先说结论:我写了一个技能 pfc-hob-shape,输入刀径、刀刃角、刃口平宽、刀圈厚这些真实参数,就能生成一把 17″/18″/19″ TBM 盘形滚刀的完整三维形状,输出纯 ASCII 的 .dat,在 PFC3D 里跑一次就得到一条 wall,直接能跟颗粒接触、受力、加载。默认做成一个封闭实体(不是几个零件拼的)。
做这件事的过程里,最有意思的不是代码,是我在核对尺寸时发现:文献里给的滚刀刀刃角,在几何上根本不成立。
用 DEM 模拟滚刀破岩,第一件事就是把刀建出来。
手工在 PFC 里画一把刀是能做到的——wall create 一个一个顶点敲,或者导个 STL。但一旦要研究"刀刃角对破岩效率的影响"“刀径从 17″ 换到 19″ 会怎样”,就得重画。而这些恰恰是 TBM 刀具设计最常扫的参数。
所以目标很明确:把滚刀的形状参数化,改参数就换刀,并且保证生成的形状能直接进 PFC 变成 wall。
一把真实的盘形滚刀,外形上就是几个同心回转体套在一起:
图1 生成的总成剖面。从外到内:刀圈刃口 r=216 → 刀圈内孔/刀体外径 r=150 → 端盖 r=115 → 刀轴 r=50.8。
因为是回转体,整把刀只用一条二维母线(在 r-z 平面上的折线)绕轴转一圈就能生成,不需要手工铺三角面。
图2 同一个模型的三维形态,3072 个三角面。这里把刀轴摆成水平——就是它在刀盘上工作的姿态,刀刃在最外圈。
参数不能瞎给。我查了一轮文献和厂商资料,17″ 单刃常截面(CCS)滚刀能坐实的硬数据是这些:
轴承型号这条挺关键——它反过来定了刀轴直径(101.6 mm,就是轴承内径)和刀体内孔(212.7 mm,轴承外径)。端盖要盖住轴承,所以外径取 230 mm。刀体高 130 + 两个端盖各 27.5 = 185 mm,跟文献给的整刀总高正好对上。
这种"互相咬合"的自洽,是判断尺寸表靠不靠谱的最好办法。
刀刃角是滚刀最核心的形状参数。文献里对 17″ 常截面滚刀的说法有好几种:
我按 20° 建了一版,出来的刀圈不对劲。算了一下才发现问题。
刀圈的截面是一个闭合环。刃面从刃口出发,走到刀圈端面时,能消耗的径向高度是有限的:
刃面与径向的夹角 h 满足 tan(h) = 28.5 / (216 − r_终点)。要让刃面恰好落在内孔上(r_终点 = 150),需要
这是几何下限。 比它更尖的刃角,刃面会在到达刀圈端面之前就穿过内孔——刀圈会变成一个没有端面的尖边环,没法跟刀体做热套配合。
图3 左:几何自洽的 46.7° 刃面,正好落在内孔上。右:按文献的 20° 画,刃面要 162 mm 的径向空间才能爬到端面,而实际只有 66 mm 可用。
所以文献那个"20°"多半指的是刃面与径向平面的夹角(也就是半角)的某种口径,而不是两侧刃面的夹角。不管它原本指什么,直接拿来当全角建模一定是错的。
我的处理是:默认取 90°(45° 倒角,径向消耗 28.5 mm,留下 37.5 mm 的环形端面给热套配合),同时把几何下限写进代码——刀刃角一旦小于自动算出的下限,直接报错并告诉你可用值是多少,不会闷头生成一个穿模的刀圈。
这类"文献值 + 几何约束"打架的情况,我的经验是信几何。角度、比例这类参数经常在不同文献里指的不是同一个东西,但截面能不能闭合是不会骗人的。
PFC 6.0 有一条命令是专门干这个的:
它把已有 geometry set 里的三角面缝合成 wall facets。用起来有三个硬约束:
第三条决定了总成怎么组织。
我一开始是把刀圈、刀体、端盖、刀轴各建一个 geometry set,各 import 一次,得到 5 条 wall。能跑,但有问题:这 5 个零件互相贴合的地方全是隐藏的内表面,白白增加面片数;而且它们本来是装配成一体的刚体,拆成 5 条 wall 只是徒增管理成本。
改成单一封闭实体更合理:既然球只可能碰到外表面,那就只取装配后的外轮廓——
内部那个装轴承的腔体完全封在这个包络里面,球永远够不着它,所以它一个面片都不用出。结果是一个球面拓扑的单一闭合曲面:3072 个面片,比五件套的 3840 还少。
生成器自己会先验一遍网格:算欧拉特征 V−E+F(实心件应该是 2,带孔环是 0)、边界边数、非流形边数、有向边是否一致、有符号体积是否为正。任何一项不过就直接拒绝出文件,比跑到 PFC 里再看报错快得多。
导入日志干净:
但"导入成功"和"能当墙用"是两回事,所以我做了两个实测。
图4 模型全貌:单一实体滚刀(刀轴沿 y、刀刃朝下)压在 φ500×300×120 的胶结岩样上。
图5 沿刀轴剖切,岩石与滚刀各切掉近侧一半,露出刀刃在岩石里的就位状态。
第一个:撒 8788 个球把整把刀埋起来,看它接不接得住。
结果:单一 wall 吃住 940 个激活接触 / 8618 个总接触。球被稳稳挡住。
第二个:让滚刀以刀轴水平、刀刃朝下的姿态压入一块胶结岩样(φ500×300×120),看力-贯入响应。
图6 上:刀具法向力随贯入线性增长到 10.2 MN。下:接触数在 2.2 / 2.8 / 4.3 / 5.2 mm 处 1→2→3→4→5 逐级跳变。
这张图我觉得挺能说明问题:每次有新球进入接触,力曲线的斜率就跟着变一次——接触数台阶和力曲线拐点是严格对应的。这是真实压痕过程该有的样子。
说明一下:这个 demo 是演示不是标定模型。岩石强度、球径、加载速率都没标定过,力的绝对值偏大(真实 17″ 滚刀额定载荷约 250–320 kN)。要做定量研究,得先按标定流程把岩石参数标好。
这是做参数化的意义所在。改一个参数,形状立刻跟着变。
图7 17″/18″/19″ 三种规格。外径、内孔、刃面位置全都跟着走。
图8 同一个 17″ 刀圈,刃角取 47°(几何下限,刃面直达内孔)、90°(默认)、120°。三种刃角下刀圈端面的宽度差得很明显——刃角越大,刃面越浅、端面越宽,这直接决定了刀刃的锋利程度和耐磨性。
用法就一行:
输出是纯 ASCII 的 .dat,不依赖任何外部文件、不含 FISH,可以直接看、可以直接改。
写的过程里有两个坑值得单独记一下,都属于"不报错但结果是错的"那类。
坑一:keepid 会让第二个部件直接失败。 每个 geometry set 的多边形 ID 都从 1 重新编号,keepid 把 wall facet 的 ID 设成 geometry 的 polygon ID,于是第二个部件撞上第一条 wall 的 ID,报 Polygon with ID 1: The specified facet exists。默认别加它。
坑二:wall.find() 吃的是 ID,不是名字。 传字符串 wall.find('hob_ring') 不报错,而是返回一个无效指针,于是读出来的力是垃圾值(实测虚高到 1e13 N)。要按 ID 抓,就在 import 时用 id 参数固定编号。
第二个坑我排查了一轮——力大了十几个数量级,第一反应是单位制搞错了,改完单位制力还是不对,才回头查函数签名。
这个技能现在包含:参数化生成器、剖面与三维预览(含交互式 HTML)、参数扫描对比图、压入破岩 demo、以及一份记着尺寸出处和推导过程的参考文档。
回头看,最值得记的不是代码量,而是那个刀刃角:如果一个参数在不同文献里有好几个互相矛盾的取值,先别急着挑一个用——拿几何约束验一遍。 截面闭不闭合,是骗不了人的。