
简介面向ABAQUS二次开发的随机圆形骨料模拟Python脚本适合土木、材料领域从事混凝土细观建模或骨料分布研究的工程师与研究生可省去手工布料的重复劳动并提升有限元模型的随机性与真实度。压缩包内仅含1个.py文件大小约2KB代码轻量却完整覆盖骨料粒径定义、随机坐标生成、重叠判定、随机旋转、接触对构建与部件装配等关键环节可直接放到ABAQUS/CAE的Python环境中运行或改造。已有1224人学习下载说明该脚本在细观建模和ABAQUS二次开发场景中有一定参考价值。读者不仅能看到一套可运行的随机骨料生成逻辑还能学习到利用random模块控制骨料分布、通过循环试错避免重叠、再自动生成接触关系的方法基于此逻辑可进一步扩展到不同粒径范围、不同体积分数的骨料模型为混凝土细观力学、复合材料损伤等研究提供快捷底座。1. 随机圆形骨料模拟为什么 Python 才是 ABAQUS 建模的正确入口做混凝土或复合材料的细观有限元分析时第一道坎不是求解器而是几何建模。手动画十几个圆还能接受一旦骨料数量到几十上百圆心坐标、半径级配、间距控制都变得不可控网格划分时极易出现畸形单元。用 Python 在 ABAQUS 里生成随机圆形骨料分布本质上是在求解三件事怎样让骨料位置真正随机且不重叠、怎样让多个圆形区域干净地切分基体几何、怎样把同一套代码复用到不同级配和不同骨料含量。这个方法既能服务做细观损伤、氯离子扩散、爆破破碎的工程师也能让研究混凝土随机骨料分布的科研人员摆脱重复建模。下面直接给出一套从随机算法到 ABAQUS 脚本落地的完整路径。2. 在 ABAQUS 里用 Python 生成随机骨料之前随机投放算法与脚本环境2.1 随机圆形骨料分布的三个约束随机、级配、间距随机圆形骨料不是简单地在矩形区域内撒点。真实骨料分布受三个条件约束缺少任何一个后续网格和计算都会出问题。第一均匀随机。骨料圆心应当在基体区域内近似均匀分布常见做法是使用蒙特卡洛随机投放即每次在矩形范围内生成一个候选圆心再检查是否满足约束。这里可以用 Python 的标准库random也可以用numpy.random二者的差别在于 ABAQUS 内置 Python 是否带 numpy。如果不确定环境里有没有 numpy建议直接使用random它不依赖第三方库在 ABAQUS 内置解释器里一定能跑。第二级配约束。真实骨料的粒径不是单一值而是服从连续级配比如常见的富勒级配公式P(D)sqrt(D/Dmax)。在脚本里先给定最小半径r_min、最大半径r_max和希望投放的粒径列表再对每一个半径执行随机投放。级配不同后续应力分布和裂纹路径会差很多所以脚本里半径列表一定要作为参数暴露出来。第三最小间距。圆与圆之间至少要留出一个缝隙gap这个缝隙用来保证骨料之间能生成界面层单元也避免网格划分时出现小于一个单元的薄片。重叠判断的核心公式是dist((x1,y1),(x2,y2)) r1 r2 gap若条件不满足则重新生成。注意这个gap并不是几何上骨料之间的实际间距而是你希望有限元网格在两个骨料之间至少保留的单元尺寸。一般建议gap不小于该区域全局网格尺寸的两倍否则网格质量很难控制。2.2 用内部 Python 还是外部 Python先想清楚边界ABAQUS 自带 Python 解释器版本随 ABAQUS 版本变有些用 Python 2较新的用 Python 3。脚本能直接调用mdb、part、assembly这些 ABAQUS 对象外部 Python 做不到。因此把随机数生成和 ABAQUS 建模块写在一个脚本里统一交给abaqus cae noGUIscript.py执行是最省事的方案。如果你的随机算法比较复杂比如要做大量的统计抽样可以在外部 Python 环境里把圆心和半径列表生成好保存成 CSV 或 JSON再由 ABAQUS 脚本读取并建模。我个人更推荐后者理由有两个外部 Python 的 numpy 和 matplotlib 调试起来更方便能快速画散点图检查骨料分布ABAQUS 内置 Python 由于环境限制打印大量中间结果并不舒服。但要注意外部 Python 生成坐标时坐标系和单位必须与 ABAQUS 内部一致否则建模时会出现骨料跑出基体边界的低级错误。2.3 脚本目录与 ABAQUS 运行方式写脚本之前先建一个独立工作目录比如agg_sim把脚本放进去。打开终端进入该目录然后执行abaqus cae noGUIrandom_aggregate.py这个命令不会启动图形界面适合批量生成模型。如果你想在 ABAQUS/CAE 里交互查看分区效果可以在菜单 File - Run Script 中选择同一个脚本。注意noGUI模式下脚本结束后mdb默认保存在内存里如果最后没有mdb.saveAs()模型不会落盘交互模式下脚本执行结束 CAE 界面仍然保留模型对象。写脚本时最好加上保存路径。3. 用 Python 在 ABAQUS 中生成随机圆形骨料直接可抄的脚本3.1 先写一个可独立运行的随机圆生成器这一段代码可以在外部 Python 环境直接跑也可以在 ABAQUS 脚本开头使用。它负责输出不重叠的圆形集合。import random, math def generate_circles(width, height, radii, gap1.0, seed42, max_attempts500): 在 width x height 矩形区域内投放随机圆形骨料 radii: 每个骨料的半径列表 gap: 骨料之间的最小间距 random.seed(seed) circles [] # 按半径从大到小排序大颗粒先放更容易提高填充率 radii_sorted sorted(radii, reverseTrue) for r in radii_sorted: placed False for _ in range(max_attempts): x random.uniform(r gap, width - r - gap) y random.uniform(r gap, height - r - gap) ok True for cx, cy, cr in circles: dist math.hypot(x - cx, y - cy) if dist (r cr gap): ok False break if ok: circles.append((x, y, r)) placed True break if not placed: raise RuntimeError( f半径 {r:.2f} 的骨料投放失败 f尝试 {max_attempts} 次仍未找到位置 ) return circles # 示例10 个半径 3 的圆 15 个半径 2 的圆 if __name__ __main__: circles generate_circles(80, 60, [3.0]*10 [2.0]*15, gap1.2, seed7) print(f成功投放 {len(circles)} 个骨料)这个生成器把随机种子、间隙和最大尝试次数都暴露为参数方便对同一种级配生成多组不同样本。排序后从大到小投放是提高投放成功率的关键技巧大颗粒先占据空间小颗粒利用剩余缝隙不容易出现后期大颗粒插不进去的情况。3.2 把圆投进 ABAQUS用 PartitionFaceBySketch 切分基体拿到圆心列表后在 ABAQUS 里最稳妥的做法是先创建一个二维矩形平面部件然后用一张包含所有圆的草图去划分面。这样圆内部形成一个独立区域圆外部保留为基体区域两个区域天然共享边界网格划分时不需要额外做装配约束。from abaqus import * from abaqusConstants import * import math, random # 参数区 WIDTH, HEIGHT 80.0, 60.0 GAP 1.2 SEED 7 RADII [3.0]*10 [2.0]*15 # 生成随机圆复用上一节函数这里简写为 generate_circles circles generate_circles(WIDTH, HEIGHT, RADII, gapGAP, seedSEED) # 新建模型与部件 mdb.Model(nameAggregateModel) model mdb.models[AggregateModel] part model.Part(namePlate, dimensionalityTWO_D_PLANAR, typeDEFORMABLE_BODY) # 第一步画矩形基体 sketch1 part.ConstrainedSketch(namebase, sheetSize200.0) sketch1.rectangle(point1(0.0, 0.0), point2(WIDTH, HEIGHT)) part.BaseShell(sketchsketch1) # 第二步在同一个 Part 上创建带圆的分区草图 sketch2 part.ConstrainedSketch(nameagg_circles, sheetSize200.0) for cx, cy, r in circles: sketch2.CircleByCenterPerimeter( center(cx, cy), point1(cx r, cy) ) # 找到矩形面的方式取中心点坐标WIDTH/2, HEIGHT/2 face part.faces.findAt(((WIDTH / 2, HEIGHT / 2, 0.0),)) # 用包含所有圆的草图对矩形面做分区 part.PartitionFaceBySketch(facesface, sketchsketch2) # 保存模型 mdb.saveAs(pathNameaggregate_model.cae)这段脚本的核心在于PartitionFaceBySketch。它在已有矩形面基础上用草图中的闭合圆曲线把原面切分成多个更小的面每个圆内部成为独立面圆外部仍是连通区域。这样后续在装配、网格、材料定义时可以根据几何位置区分骨料和基体而不需要做布尔运算或装配对齐。参数说明CircleByCenterPerimeter的center是圆心point1是圆周上的一个点二者的距离就是半径。不要把半径直接作为参数传进去而是要计算point1 (cx r, cy)这是新手最容易写错的地方。findAt需要传入一个位于目标面上的坐标点这里用矩形中心点只要圆没有覆盖中心点这个坐标一定落在基体面上。3.3 脚本中各参数如何设置参数含义推荐值说明WIDTH, HEIGHT基体矩形尺寸任意正数必须大于最大粒径的两倍RADII每个骨料的半径列表按级配生成长度决定骨料数量GAP骨料间最小间距2~3 倍目标网格尺寸太小会有薄片单元SEED随机数种子任意整数固定后结果可复现max_attempts单颗粒最大试投次数500频繁失败说明级配或区域不合理3.4 运行脚本和常见运行错误在终端执行下面的命令脚本完成后会生成aggregate_model.cae。abaqus cae noGUIrandom_aggregate.py如果直接拿到 ABAQUS 图形界面运行选择 File - Run Script。运行时报错最多的位置是findAtABAQUS 要求传入的三维坐标中z分量必须为 0同时坐标必须落在已有几何上。还有一种是abaqus libpng error通常出现在打开 GUI 渲染环境时改用noGUI或重新设置显示环境可以规避与脚本本身关系不大。如果脚本进入死循环多半是max_attempts内放不下所有圆任务栏里强制结束进程后修改级配或增大区域即可。4. 随机骨料分布的参数调优与排错从级配到网格质量4.1 半径列表怎么生成富勒级配的简化实现手动写半径列表只适合测试。做真实仿真时骨料级配一般来自筛分数据或富勒公式。富勒级配的累计通过率P(D) sqrt(D / D_max)反解可以得到给定粒径区间的骨料占比。要把连续级配转成离散的投放半径常见做法是按直径分档每一档计算应投放的骨料数量再把每档半径填充到列表中。import random, math def fuller_radii(d_min, d_max, num_agg, seed1): 用富勒级配生成 num_agg 个骨料半径 d_min, d_max 是最小和最大骨料直径 random.seed(seed) radii [] # 按累计通过率反算随机直径 for _ in range(num_agg): p random.uniform(0, 1) d (p ** 2) * d_max # 因为 D/Dmax P^2 - D P^2 * Dmax if d d_min: d d_min radii.append(d / 2.0) # 半径 直径/2 return radii这个函数简化了筛分区间只保证粒径分布大致符合富勒曲线。更严格的做法是按区间累计概率先抽样区间再在区间内均匀抽样直径。要注意富勒级配生成的重心偏向细颗粒所以直接用这个半径列表时骨料数量会很多体积分数也可能偏低。建议在循环里统计骨料总面积占比达不到预设体积分数时增大num_agg或减小gap。4.2 投放失败时的退让策略如果你的脚本在某个大半径骨料上反复失败大多是这三种原因gap太大、max_attempts太小、骨料面积分数超出区域极限。投放本质是一个随机覆盖问题理论上极限填充率并不高圆形骨料通常做到 40%~50% 面积分数以后就会明显变慢。我的经验是先按面积分数估算一个最大骨料数量再给投放函数加一个软失败策略某个骨料试投 500 次失败后不直接报错而是把该骨料半径缩小 10% 重试缩小两次仍失败再放弃。这样能牺牲少量级配来获得更高的体积分数。对细观模型来说宁可少几个大骨料也不要出现几何穿透或过小的网格缝隙。下面是带软失败的重试逻辑片段def generate_with_shrink(width, height, radii, gap, seed): random.seed(seed) circles [] for r0 in radii: r r0 for shrink in range(3): placed _try_place(circles, r, width, height, gap, attempts500) if placed: break r r0 * (0.9 ** (shrink 1)) return circles注意只有当r0仍然大于等于gap * 2时缩小才有意义。如果半径已经小于最小网格尺寸直接放弃更合理。4.3 ABAQUS 脚本执行和网格阶段的高频坑经常有人问“abaqus中断不了怎么办”多数是脚本里有一个无限循环。在noGUI模式下小概率能通过 CtrlC 终止更保险的方法是在脚本开头设置最大尝试次数并在外层增加超时保护。还有一个非常隐蔽的问题PartitionFaceBySketch执行时如果草图中存在两个完全相切的圆ABAQUS 会无法生成分区。所以gap必须严格大于 0同时圆心距离不能恰好等于两圆半径之和。网格阶段如果发现圆边界附近单元扭曲先不要急着调网格算法回到gap参数上。将gap增大到全局网格尺寸的 2~3 倍通常比加密网格更有效。另一个做法是把圆边界上的种子数量设为整数避免 ABAQUS 自动加密导致圆边界单元过密。你可以在 Mesh 模块使用setElementType或直接对边布种但在脚本里更可控的方式是在分区后用part.edges建立几何集合并指定种子数量。4.4 用统计指标检查随机骨料分布是否合格模型建完不能只看图觉得“差不多”。我会用一段独立 Python 脚本读取生成的圆列表算三个指标骨料面积分数所有πr²之和除以基体面积正常在 30%~50% 之间最小间距遍历所有圆对统计最小dist - r1 - r2要求大于等于设定的gap边界余量每个圆到基体边界的距离的最小值应大于等于gap。def check_distribution(circles, width, height, gap): import math area sum(math.pi * r**2 for _, _, r in circles) area_frac area / (width * height) min_spacing 1e9 for i in range(len(circles)): for j in range(i 1, len(circles)): x1, y1, r1 circles[i] x2, y2, r2 circles[j] d math.hypot(x1 - x2, y1 - y2) min_spacing min(min_spacing, d - r1 - r2) return area_frac, min_spacing如果最小间距小于gap说明投放逻辑里某个分支绕过了重叠判断建议先在外部 Python 跑一遍生成器确认圆列表没问题后再交给 ABAQUS。5. 进阶技巧把随机圆形骨料分布做成可复用的级配模板5.1 用随机种子管理样本族做参数研究时通常需要同一级配下生成多组随机分布来评估统计离散性。把seed作为最外层参数循环传入脚本即可。但要注意一个细节generate_circles内部已经调用了random.seed(seed)如果你在外面又调了一次可能会导致 ABAQUS 其他模块的随机性被重置。建议只在生成器函数里设置种子外部不要重复调用。如果你希望同一份骨料分布既生成几何模型又用于其他计算最好把圆心数据保存到文件。在 ABAQUS 脚本中写到当前目录import csv with open(circles.csv, w, newline) as f: writer csv.writer(f) writer.writerow([x, y, r]) writer.writerows(circles)下次建模时直接读取 CSV跳过投放计算既省时间又能保证多个模型完全一致。5.2 分区后如何给骨料和基体分别赋属性PartitionFaceBySketch分区后同一个 Part 里既有骨料面又有基体面。ABAQUS 中可以在 Mesh 模块对每个区域分别指派网格属性也可以在脚本里通过坐标判断。由于分区后骨料圆心的坐标是已知的遍历每个face取面的中心点坐标看它是否落在某个圆内然后为该区域创建 Setfor face in part.faces: center face.pointOn[0] cx, cy, cz center for x, y, r in circles: if math.hypot(cx - x, cy - y) r * 0.9: part.Set(namefAgg_{x}_{y}, facesface) break这个技巧用于在脚本中自动把骨料和基体分开之后定义材料或指定 cohesive 界面时无需手动选择。注意face.pointOn返回的是包含坐标的元组第一个元素是坐标数组所以代码里用face.pointOn[0]。5.3 从二维圆模板扩展到三维球骨料的思路随机圆形骨料算法同样可以外推到三维球骨料圆心变成球心重叠判断的距离公式不变只是半径加间隙在三个坐标方向上都要满足。ABAQUS 中分区工具从PartitionFaceBySketch变成PartitionCellByDatumPlane或直接使用球形几何做布尔操作。三维模型的计算量和网格难度会指数级上升建议先在二维模板上把级配、间隙、网格策略调好再扩展。最后一个建议把你的随机生成器单独存成一个agg_geometry.pyABAQUS 建模脚本只负责读取圆列表并分区。这样外部 Python 画散点图、统计面积分数、调整级配完全不需要打开 ABAQUS建模脚本保持短小简洁日常修改参数的效率会高很多。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。