混凝土材料本身是个多相体系,细观尺度下骨料形状对力学响应的影响远比很多人想象的大。早些年大家做二维细观模拟,图省事直接用圆形骨料,后来拿真实混凝土切片的扫描图一对比,问题就出来了——真实骨料几乎没有圆的,绝大多数是棱角分明的多边形,有的还带着内凹。裂缝在圆形骨料界面附近走的路径,和在实际多边形骨料界面附近的路径,差异相当明显。这就是为什么现在做混凝土细观建模的人,开始认认真真搞多边形骨料。这篇文章我就把"混凝土多边形骨料二维建模"从构思到落地实现的整条链路讲清楚,适合正在做细观力学模拟、离散元分析、或者需要生成数字试件做有限元计算的工程师和学生参考。
1. 为什么混凝土细观建模绕不开多边形骨料
1.1 圆形骨料模型的天然局限
二维细观模型里,骨料的最简单近似就是圆。圆的优势太明显了:几何描述只需要圆心和半径,生成随机分布时碰撞检测只用算圆心距离,网格划分也省心。当年很多数值试件就是这么建的,用来研究氯离子扩散、干燥收缩这类问题,结果也能看。但一旦涉及力学问题,尤其是裂缝萌生和扩展,圆的缺陷就藏不住了。
真实骨料的轮廓上有棱角,有尖点,这些几何特征在受力时会产生局部的应力集中。圆形骨料表面曲率处处相同,应力分布均匀,裂缝倾向于沿界面滑移;多边形骨料的棱角则会钉扎裂缝路径,让裂缝必须绕行甚至穿过骨料,消耗更多的断裂能。做过对比模拟的人应该都有体会:同样面积占比下,圆形骨料模型的宏观强度普遍偏低,破坏模式也更偏向界面脱粘,而多边形骨料模型的裂缝路径明显更曲折,和真实混凝土试件的破坏形态更接近。
1.2 从真实骨料到几何抽象
混凝土里的粗骨料来源包括碎石和卵石。碎石是机械破碎得到的,形状多棱角,凸多边形是很好的近似;卵石经过水流搬运磨圆,接近椭圆或圆形。实际工程中碎石用得最多,所以多边形建模的优先级自然最高。
在做二维建模时要明白一个概念:三维骨料在二维截面上的表现,其实和骨料本身的形状有关。一个三维的凸多面体骨料,被任意平面切开后,截面也是一个凸多边形。这为二维凸多边形建模提供了几何依据。而实际切片照片里也会看到凹多边形,主要是因为切片位置经过骨料的凹陷区域,或者多个骨料在图像上粘连,所以在做统计建模时,凹多边形也应该纳入考虑范围。
1.3 多边形建模要解决的核心问题
多边形骨料建模相比圆形,难点集中在三块:形状生成、随机投放、网格处理。形状生成要保证骨料轮廓合理,不能出现过于畸形的细长条或离谱的内角;随机投放要满足级配和面积占比要求,同时保证骨料之间互不重叠;网格处理则需要确保后续有限元计算的稳定性和收敛性。这三块解决好了,一个能用的数字试件就算立起来了。
2. 二维多边形骨料生成的核心思路与原理
2.1 凸多边形:从随机圆到随机顶点
先讲最常用的凸多边形生成方法。核心思路不复杂:在一个基准半径附近,对极坐标下的角度和半径同时施加随机扰动,再把极坐标转换成直角坐标,连接起来就是一个不规则的凸多边形。
具体做法是:设定目标等效直径 D,则目标半径 R = D/2。确定顶点数 n,一般在 4 到 12 之间,太少了不像骨料,太多了几何退化接近圆,反而失去模拟意义。对第 i 个顶点(i = 0, 1, ..., n-1),其极角为:
θ_i = 2π·i / n + δθ_i
其中 δθ_i 是角度扰动,让顶点位置在圆周方向上错开,避免形成正多边形。半径方向也引入扰动:
r_i = R · (1 + δr_i)
δr_i 一般控制在 ±0.3 左右,太大容易产生非常尖锐的凸角或内凹趋势,太小则形状太规则。
得到每个顶点的极坐标后,转换公式:
x_i = r_i · cos(θ_i),y_i = r_i · sin(θ_i)
把这些点按顺序连起来就得到一个凸多边形。最后用鞋带公式计算实际面积和等效直径,再整体缩放,使多边形的等效直径精确等于目标值D。
实际编码时有一个容易忽略的问题:顶点排序。如果每个 θ_i 本来就按 2π·i/n 的基底递增,那连点时按 i 顺序连即可,不会出现边交叉。但如果你用其他方法生成顶点,就要先把顶点按角度排序,否则连出来的多边形边会互相穿插,完全不能用。
2.2 凹多边形:贴近真实轮廓的另一条路
真实骨料切片里有相当一部分是凹多边形。凹多边形建模有两种常用思路。
第一种是在凸多边形基础上做局部内凹处理:选择一条边或多条边,把边的中点向多边形内部平移一段距离,形成凹入的折线。这样可以在保持整体"骨料感"的同时引入内凹特征。注意凹陷不能太大,否则多边形可能出现退化甚至自相交,要加一个几何校验。
第二种思路是从图像数据出发:用真实骨料的照片或CT切片做边缘检测,提取轮廓点列,再用折线简化算法(比如经典的 Douglas-Peucker 抽稀算法)把轮廓压缩成几十个顶点,得到非常真实的凹多边形。这种方法生成的骨料形状真实度最高,缺点是形状特征完全来自特定图像,做随机批量生成时需要对形状参数做统计分析。
2.3 形状控制参数与几何校验
生成骨料时,一组稳定的控制参数是必须的。建议至少包含:
- 顶点数范围 n_min ~ n_max
- 半径扰动幅度 ε_r
- 角度扰动幅度 ε_θ
- 最小内角阈值(比如不小于 30 度)
- 最小边长阈值(避免出现过短的边,否则网格划分会很痛苦)
每生成一个多边形,必须立即做一轮几何校验:检查最小内角、检查边长均匀性、检查是否自相交。不合格就重新生成。校验里最容易被忽略的是"内角过大"的情况,一个接近 180 度的内角会让骨料边上出现"近似共线"的顶点,网格划分时会产生极薄的单元层,严重影响有限元计算。
3. 投放策略与碰撞检测:成败都在效率上
3.1 投放目标:面积占比和级配曲线
随机投放不是一个无目标的撒点过程。混凝土配合比会给出粗骨料的体积占比,通常在三到四成左右。二维模型里直接对应面积占比,常规做法是让骨料面积占总试件面积的 30% 到 45%。超过 45% 之后,随机投放难度急剧上升,因为空隙越来越小,能塞进去的骨料越来越少。
级配方面,富勒级配曲线是混凝土骨料最常见的理论级配,累计通过率满足:
P(D) = (D / D_max)^0.5
意思是粒径小于 D 的骨料占全部骨料的质量(或体积)百分比。二维模型里,可以按简化方式处理:直接按这个公式生成一系列目标等效直径,让生成的多边形骨料沿着这条曲线分布。实际操作时,先生成一堆随机粒径,再按面积累积修正,使整个模型的粒径分布与理论曲线吻合。
3.2 从大到小投放:一个简单但极其有效的策略
投放顺序上,强烈建议按直径从大到小投放。原因是小骨料能填进大骨料之间的缝隙,而反过来先放大量小骨料会把空间填得七零八落,大骨料根本塞不进去。这种做法在几何填充问题里几乎是常识,但很多人刚开始做的时候没意识到,结果设计面积占比 40%,实际跑到 32% 就填不进去了。
每次投放的具体流程是:
- 取当前目标粒径,生成多边形骨料
- 在试件区域内随机生成一个中心点
- 检查该位置是否与所有已投放骨料重叠
- 无重叠则投放成功;有重叠则重新随机生成中心点,继续尝试
单个骨料的最大尝试次数需要控制,通常设 500 次。超过次数说明这个粒径在当前剩余空间里很难再投放,就直接换下一个稍小的粒径继续。这个逻辑虽然简单,但能避免程序死循环,也能让最终面积占比尽可能逼近设定值。
3.3 碰撞检测的两层优化
骨料数量少的时候,碰撞检测直接暴力两两比较就行。比如一个 100mm × 100mm 的二维试件,骨料等效直径在 5mm 到 20mm 之间,面积占比 40%,骨料数量大约在 200 到 500 颗。两两比较也就是十几万次,现代计算机跑起来毫无压力。
但如果试件尺寸放大到 500mm、骨料数量到几千颗,或者你打算把算法推广到三维,那就必须做优化。我习惯的做法是分层检测。
粗检测用 AABB(轴向包围盒)。每个多边形算一个外接矩形,两个外接矩形不相交,那这两个多边形必然不相交。矩形相交判断理论上只要比较四个坐标值,非常快。这一步能剔除 90% 以上的无效检测对。
只有包围盒相交的骨料对,才进入细检测。细检测用分离轴定理(SAT):两个凸多边形不相交,则必然存在一条分离轴,使得两个多边形在该轴上的投影区间互不重叠。候选轴就取两个多边形的所有边的法向。对每一条候选轴,把所有顶点投影上去,比较两个投影区间是否有重叠。一旦发现某条轴上投影区间分离,立即判定不相交,跳出循环。
对凹多边形,SAT 不能直接使用。常规做法是把凹多边形先做凸分解(比如耳切法),把单个凹多边形拆成若干凸多边形,然后对每个凸多边形和对方做 SAT。代价是计算量成倍增加,但逻辑清晰,不容易出错。
3.4 进一步提速:空间哈希网格
骨料数量再往上走时,可以引入空间哈希网格。把整个试件区域按网格划分,网格边长取最大骨料直径的 1 到 2 倍,每个网格维护一个骨料索引列表。新骨料投放时,先算它的包围盒覆盖了哪些网格,只需要和这些网格里的骨料做粗检测。平均每颗骨料只需检查附近网格里的十来个候选对象,检测开销从 O(N²) 降到接近 O(N)。
实际测试中,用空间哈希后投放效率至少提升一个数量级。写代码时注意,网格尺寸选得太小会导致骨料跨大量网格、反复查表,选得太大则退化成暴力搜索。经验值是网格边长 = 1.5 倍最大骨料直径。
4. 网格划分与界面过渡区:从几何模型到计算模型
4.1 网格划分的常见坑
几何模型建好了,离能算还差一步:网格划分。多边形骨料的网格划分,最大的敌人是"尖角"和"短边"。
尖角处的网格单元为了保证几何边界贴合,往往会被压得极扁,导致单元畸变,计算时刚度矩阵病态,轻则收敛慢,重则直接不收敛。所以建模阶段就要提前预防:生成多边形时限制最小内角不小于 30 度,限制最小边长不小于骨料直径的 1/20。这两个参数我一般写死在生成代码里,而不是等网格出问题再回来修改。
骨料和砂浆之间的界面过渡区(ITZ)是细观模型的重点关注区域。ITZ 是水泥砂浆与骨料表面之间的一层薄弱区域,孔隙率高、强度低,裂缝通常从这里开始萌生。数值模型里有两种处理方式:一种是在骨料边界和砂浆之间嵌入一层零厚度内聚力单元,模拟界面开裂;另一种是在骨料周围显式划分出一层薄单元,赋予和砂浆不同的材料属性。
显式 ITZ 建模时,骨料边界到砂浆区域之间至少保留 1 到 2 层单元。这要求骨料之间的间距不能太小,否则两颗粒靠在一起的骨料,各自的 ITZ 层会打架。所以投放阶段就得在碰撞检测里增加一个额外的"最小间距"判据——两个骨料之间的最近距离不小于 ITZ 厚度的两倍加上一个网格单元尺寸。这个细节看起来不起眼,但直接影响网格质量和计算稳定性。
4.2 网格种子布置与单元尺寸选择
单元尺寸的选择遵循一个经验法则:最小骨料直径方向上至少要有 3 到 5 个单元。也就是说,如果最小骨料等效直径是 2mm,那单元尺寸最好控制在 0.4mm 到 0.7mm。否则骨料内部的应力分布根本算不精确,体积占比看起来对,但计算结果不可信。
网格种子的布置建议采用分区域策略:骨料内部和砂浆区域用中等密度的自由网格,骨料边界附近加密,布置局部种子。很多商业软件支持按边划分种子数,可以在每个骨料的每条边上按边长等分数设置种子,保证边界处的网格尺寸均匀。
4.3 周期性边界处理
有些细观模拟需要施加周期性边界条件,比如单轴拉伸、压缩的代表体元分析。周期性边界条件要求试件对边网格节点一一对应,这要求骨料在边界处也是周期的:如果一颗骨料从左边界伸出,它的对应部分必须出现在右边界。
实现方法也不复杂:先正常投放骨料,完成之后遍历所有骨料,检查是否跨越边界。对跨越边界的骨料,裁剪掉边界外的部分,同时在对面边界对应位置生成一个镜像的骨料剩余部分。这部分逻辑如果手写,注意镜像后要重新做一次碰撞检测,防止镜像体和原有骨料重叠。
5. 建模质量的三个硬指标:面积占比、级配曲线与均匀性
5.1 面积占比与多边形面积计算
建模质量不能靠肉眼判断。第一个硬指标就是面积占比是否达到设计值。多边形面积的计算用鞋带公式实现:
A = 0.5 × |Σ(x_i × y_{i+1} - x_{i+1} × y_i)|
注意顶点顺序必须一致,要么全顺时针,要么全逆时针,公式里的求和往外取绝对值。如果顶点数多,这个公式计算效率也完全够用。
所有投放结束后,把全部骨料的面积求和,除以试件总面积,就得到实际面积占比。如果实测值离设计值差太多,比如差了 5% 以上,先检查是不是投放尝试次数设置太保守,或者级配曲线偏向了小粒径方向。实测下来,当最大骨料直径和试件特征尺寸的比值小于 1/5 时,面积占比比较容易逼近设计值;比值越大,边壁效应越明显,面积占比越难做上去。
5.2 级配曲线对比
第二个指标是级配曲线。把生成的所有骨料按等效直径从小到大排序,画出累计面积百分比曲线,再叠加上理论富勒曲线,直接肉眼对比。两边的曲线贴合程度越高,说明生成骨料的粒径分布越接近设定。
如果曲线在某一粒径段明显偏低,说明这个粒径段的骨料投放失败率偏高。最常见的原因是该粒径段的骨料数量太多,在有限空间里来不及找到合适位置。处理方法要么放宽最大尝试次数,要么把目标面积占比适当下调,要么细化投放顺序,优先处理大粒径骨料。
5.3 均匀性检验
第三个指标是均匀性。细观模拟要求骨料分布尽量均匀,不能出现大片没有骨料的砂浆富集区,也不能出现骨料扎堆区域。一个简单可操作的检验方法是把试件区域划分成 10×10 的网格,统计每个子区域内的骨料面积占比,计算标准差和变异系数。
变异系数低于 10% 说明分布很均匀;在 10% 到 20% 之间属于可接受范围;超过 20% 就要怀疑投放策略是否在某处出现了聚集或空洞。出现聚集通常是因为随机数种子质量不好,或者碰撞检测的最小间距没控制好;出现空洞则要检查投放过程中的随机扰动幅度是否过大,导致大粒径骨料分布不均匀。
5.4 骨料级配的统计校准技巧
有时候理论目标曲线和实际生成曲线总会有一点偏差,尤其是粒径范围宽的模型。一个我常用的校准技巧是:先跑一次完整投放流程,统计实际级配曲线和理论曲线的偏差,然后按照偏差反向修改下一轮的生成权重——某一粒径段生成数量偏少了就加大该段的生成概率,偏多了就减小。迭代两到三轮之后,实际级配曲线就能和理论曲线贴合得相当好。这个过程本质上是个开环校准,不需要复杂的优化算法,但非常实用。
6. 从二维走向应用:导出格式、脚本化与三维扩展
6.1 几何导出与各类模拟软件的衔接
完成建模后,几何数据要导出成通用格式才能进其他软件。我最常用的格式是DXF,它保存二维多边形折线非常方便,大部分有限元前处理软件都支持导入。另一种做法是直接生成脚本:给某个商业有限元软件写参数化建模脚本,在软件内部生成骨料几何并划分网格,省去中间格式转换的麻烦。
导出的对象除了骨料本身,还要把砂浆区域单独导出。做法是先导出整个试件外边界,再在有限元软件里用骨料轮廓切割砂浆区域,得到"砂浆-骨料"两相几何。如果 ITZ 需要显式建模,则要在骨料边界偏移出一个闭合轮廓,形成独立的封闭区域。
6.2 批量化参数扫描
多边形骨料建模的一个核心优势是可以做随机性参数的批量扫描。改变随机种子,同一条级配曲线可以生成几十个不同的数字试件。做力学模拟时,这些试件能用来讨论随机骨料分布对宏观响应的影响,而不再是单个试件的单次结果。
脚本化时建议把参数全部收拢到一个配置文件里,包括试件尺寸、面积占比、级配参数、骨料顶点数范围、随机种子等。每次跑批量生成只改配置文件,代码不动。这样既方便复现,也方便后续交接给其他人使用。
6.3 向三维建模的思路上看一步
二维建模成熟之后,很多人自然想往三维走。三维多面体骨料的建模复杂度比二维高一个量级,主要难点还是碰撞检测:凸多面体需要检测面与面的相交,凹多面体要做更复杂的分解。如果一开始就冲三维,研发周期会拉得很长,而且调试困难。
一个很实际的路径是:先用二维模型完成方法的验证和参数标定,搞清楚骨料形状对宏观响应的基本影响规律,再迁移到三维时,只需要把凸多边形生成算法改成凸多面体生成算法,把 SAT 的二维投影扩展成三维分离轴判断,投放和级配逻辑完全复用。这样风险小,且每一步的成果都能落地产出。
6.4 结合图像数据的真实骨料库
最后聊一个很实用的进阶方向:用真实骨料图像建立形状特征库。对一批碎石骨料拍照,做边缘检测提取轮廓,简化成多边形后统计每一项形状指标,比如凹凸度、棱角度、长宽比。这些统计特征反过来用于随机生成参数,生成的数字骨料在统计意义上和真实骨料高度一致。
我实际做过的流程是用一块深色背景板拍摄骨料顶面,转灰度后做二值化分割,提取轮廓后先用抽稀算法压成 20 到 40 个顶点,再按顶点数、凸凹比例、内角分布统计成字典键值对。之后生成新骨料时,按这个字典的分布抽样参数,效果非常自然。这个方案的好处是,不同批次的砂石料可以建立各自的特征库。做这类实验时,把拍摄距离和光照条件固定下来,不然轮廓提取的精度会受很大影响,颗粒小的骨料尤其明显。
混凝土多边形骨料二维建模这条路,严格说起来并不难,核心就是搞清楚形状生成、随机填充、碰撞检测、网格处理这几件事之间的关系。每一步都有现成的算法,但组合起来的工程细节才是真正花时间的地方。我最初做的时候,卡在碰撞检测优化上很长一段时间,后面想通"先粗检测后细检测"这套组合拳,整个流程才顺利起来。希望这篇文章能帮正在做类似工作的同行省掉一部分弯路,把这些工程细节一次到位。