
简介本资源面向土木工程、材料科学及计算力学领域的研究生、科研人员与工程师聚焦混凝土细观力学建模中的核心难点——三维随机骨料分布的高保真生成问题。资源提供一套可直接运行的MATLAB实现方案解决传统规则骨料模型偏离实际、难以支撑应力传递、裂缝演化等细观机理分析的瓶颈。压缩包共4个文件1.9MB含核心脚本ConcreteBone.m实现骨料随机投放、无重叠判定、基体填充与属性赋值全流程及3个xlsx数据表用于定义骨料级配、尺寸分布与空间约束参数结构简洁、参数开放、便于二次开发与FEA耦合。已有865人学习下载使用者可快速生成符合真实统计特征的三维混凝土微结构模型支撑有限元前处理、损伤起始位置预测、界面应力集中分析等关键研究任务是开展混凝土多尺度模拟与配合比优化的实用型工具集。1. 从宏观到微观为什么我们需要混凝土细观模型如果你做过混凝土结构的有限元分析大概率遇到过这样的困惑明明材料参数设置得“很标准”但模拟出来的开裂模式、破坏形态甚至最终的承载力和实验结果总有些对不上。问题出在哪我们通常把混凝土当作一种“均质”材料来处理给它一个统一的弹性模量、一个统一的抗压强度。但现实中的混凝土从你把它浇筑进模板的那一刻起它就不是“均质”的。它是由粗骨料、细骨料、水泥浆体、界面过渡区ITZ以及可能存在的孔隙和微裂缝组成的复杂多相复合材料。这个“复杂多相”的特性恰恰是决定混凝土宏观力学行为比如开裂、损伤演化、断裂能的微观根源。粗骨料像坚硬的“岛屿”水泥浆体是相对柔软的“基质”而包裹在骨料周围、厚度仅几十微米的界面过渡区则是整个体系中最薄弱的环节。绝大多数裂缝都从这里萌生和扩展。如果我们想真正理解混凝土的破坏机理预测其非线性行为比如损伤、塑性、动态冲击响应或者研究新型材料如纤维混凝土、再生骨料混凝土的性能继续使用宏观均质模型就像用一把钝刀做外科手术——方向对了但精度远远不够。这就是“混凝土细观力学”研究的核心价值。它不再把混凝土看作一个黑箱而是打开它在细观尺度通常是毫米到厘米级上显式地建立骨料、砂浆和界面区的几何模型并赋予它们各自真实的材料属性。通过这种“数字化混凝土试件”我们可以在计算机里进行虚拟试验观察裂缝是如何在薄弱界面处萌生如何绕过坚硬的骨料最终连通形成宏观裂缝的全过程。ConcreteBone这个工具以及“三维骨料模型”、“随机骨料”这些关键词指向的正是构建这种数字化细观模型的核心环节如何用计算机生成一个尽可能贴近真实混凝土内部结构的、包含随机分布三维骨料的几何模型。没有这一步后续的所有力学分析都是空中楼阁。所以今天我们不谈复杂的本构方程和求解器设置就聚焦在这个起点上如何高效、可靠地生成一个可用于有限元分析的混凝土三维随机骨料模型。这听起来像是个纯几何问题但里面每一步的选择都直接关系到你后续模拟结果的可靠性与计算成本。2. 三维随机骨料模型的核心要素与生成逻辑生成一个三维随机骨料模型本质上是在一个给定的长方体代表试件空间内按照一定的规则“投放”大量形状、大小各异的颗粒代表骨料并确保它们互不重叠。这个过程需要定义几个核心要素它们共同决定了模型的“真实感”。2.1 骨料级配模型的“基因”骨料级配是第一个也是最重要的约束条件。它定义了模型中不同粒径骨料的含量比例直接反映了混凝土的配合比设计。我们通常采用“富勒Fuller曲线”或其变体如泰波公式来确定理论级配。在程序中这体现为一系列筛孔尺寸如16mm, 8mm, 4mm, 2mm...及其对应的累计筛余百分率。生成模型时我们需要根据级配曲线确定每一档粒径例如4-8mm这一档的骨料总体积占试件体积的百分比。然后根据这一档的粒径范围随机生成该档内具体某个骨料的直径或等效直径。这里的关键在于骨料不是二维的圆而是三维的体。因此骨料的“含量”必须以体积为基准进行计算和投放。许多初学者容易犯的错误是在二维平面上用面积占比来模拟或者简单地将二维方法推广到三维忽略了体积计算与投放算法的根本不同导致最终模型的骨料体积分数与设计值相差甚远。2.2 骨料形状从理想球体到多面体最简单的假设是将所有骨料视为球体。这极大简化了碰撞检测判断两个骨料是否重叠的计算只需比较两球心距离与两半径之和即可。生成速度快算法稳定。对于研究某些宏观规律或进行方法验证球形骨料模型是一个很好的起点。然而真实的碎石骨料是有棱有角的多面体。多面体骨料能更真实地反映骨料的咬合作用和应力集中效应对裂缝扩展路径的影响也更显著。因此更先进的模型会采用多面体如随机凸多面体来模拟骨料。生成随机凸多面体的一种常见方法是在一个球体内随机生成若干点然后计算这些点的凸包Convex Hull这个凸包就是一个形状不规则但保证是凸的多面体。通过控制随机点的数量和分布可以生成不同“棱角分明”程度的多面体。从球形到多面体复杂度急剧上升。碰撞检测从简单的距离计算变为需要判断两个凸多面体是否相交的复杂计算几何问题常用GJK算法或分离轴定理。计算成本会成数量级增长。因此在模型真实性和计算效率之间需要权衡。一个折中的方案是采用“球体簇”或“椭球体”它们比球体更贴近真实形状而计算复杂度又低于任意多面体。2.3 投放算法如何高效地“撒豆子”这是整个生成过程的技术核心。目标是在满足级配和体积分数的前提下将成千上万个骨料快速、无重叠地放入试件空间。最直观的方法是“随机投放-检测冲突法”随机生成一个骨料位置、大小、形状。检查它与已存在的所有骨料以及试件边界是否重叠。如果不重叠则接受该骨料如果重叠则拒绝并回到步骤1尝试新的随机位置。这种方法简单但当骨料含量较高体积分数超过40%时由于“排斥效应”新骨料找到空位的成功率会变得极低算法效率急剧下降甚至无法在有限时间内达到目标体积分数。因此更实用的算法是“取-放法”或其改进版本。其基本思想是预生成骨料列表根据级配预先计算好所有需要投放的骨料的大小和形状并放入一个待投放列表。排序将列表中的骨料按体积从大到小排序。优先投放大骨料因为大骨料更难找到空位先固定它们的位置可以避免后期无法容纳大骨料的困境。迭代投放对列表中的每一个骨料在其粒径允许的范围内随机生成一个位置进行冲突检测。如果失败不是立即放弃而是在其当前位置附近进行多次比如1000次随机微调尝试“抖动”寻找一个可容纳的位置。如果仍失败则暂时跳过该骨料继续投放下一个。二次处理所有骨料完成一轮投放后对那些被跳过的骨料通常是较小的再进行一轮投放尝试。此时空间更拥挤成功率更低但小骨料更容易见缝插针。通过这种“先大后小、允许暂时跳过、多次尝试”的策略可以显著提高高体积分数下的生成成功率和效率。这里的一个经验技巧是在冲突检测时可以引入一个微小的“安全距离”比如0.05mm强制骨料之间保持一点点间隙。这并非完全出于物理真实实际骨料是紧密接触的而是为了后续的网格划分。如果骨料几何体在边界上恰好相切或无限接近在生成有限元网格时极易产生质量极差的畸形单元导致计算不收敛。这个“安全距离”为网格生成器留出了操作空间。2.4 界面过渡区ITZ的几何生成ITZ是包裹在骨料周围的一层非常薄通常10-50微米但力学性能显著弱于砂浆基体的特殊区域。在几何模型上ITZ通常不是直接建模为一层独立的实体因为其厚度相对于骨料尺寸太小若用实体单元划分网格单元数量会爆炸且容易产生畸变。更常见的处理方法是将ITZ视为骨料表面的一层“附着属性”。具体在几何生成步骤我们可以在每个骨料的表面向外偏移Offset一个ITZ厚度生成一个包裹骨料的“壳层”几何体。这个壳层与骨料、与其他骨料的ITZ壳层、与砂浆基体之间都需要有清晰的几何边界。在后续赋材和网格划分时对这个壳层区域单独指定代表ITZ的材料属性如更低的弹性模量和强度。这种方法在几何上明确了ITZ的空间范围又避免了直接划分超薄实体网格的难题。3. 基于Python与开源库的模型生成实战理解了原理我们来看如何用代码实现。这里我分享一个基于Python生态的实战流程主要依赖numpy进行数学计算pyvista或vedo进行三维可视化和数据管理而碰撞检测等核心几何逻辑可能需要自己实现或借助scipy.spatial等库。注意以下代码为概念性示例旨在说明关键步骤和逻辑无法直接运行。完整的、鲁棒的生成器代码量较大通常需要结合专门的几何算法库。3.1 环境准备与骨料定义首先我们定义骨料的基本类。这里以球形骨料为例因为它最直观。import numpy as np import random from dataclasses import dataclass from typing import List, Tuple dataclass class Aggregate: 代表一个球形骨料 diameter: float # 直径 center: np.ndarray # 球心坐标形如 [x, y, z] # 可以后续扩展属性如材料ID、形状类型球/椭球/多面体等 property def radius(self): return self.diameter / 2.0 def distance_to(self, other: Aggregate) - float: 计算两个球心之间的距离 return np.linalg.norm(self.center - other.center) def is_overlap(self, other: Aggregate, min_gap: float 0.0) - bool: 判断两个球是否重叠考虑安全间隙min_gap return self.distance_to(other) (self.radius other.radius min_gap) def is_inside_boundary(self, box_bounds: Tuple[float, float, float, float, float, float]) - bool: 判断球体是否完全在长方体试件边界内 x_min, x_max, y_min, y_max, z_min, z_max box_bounds r self.radius return (x_min r self.center[0] x_max - r and y_min r self.center[1] y_max - r and z_min r self.center[2] z_max - r)接下来我们需要一个函数来根据级配生成骨料粒径列表。假设我们已知目标总体积分数total_volume_frac试件尺寸box_size以及级配曲线定义的各档粒径范围size_ranges和该档的体积占比vol_ratios。def generate_aggregate_sizes_from_gradation(box_volume, total_volume_frac, size_ranges, vol_ratios): 根据级配生成骨料粒径列表。 box_volume: 试件体积 total_volume_frac: 骨料总体积分数如0.4 size_ranges: 列表每个元素为 (d_min, d_max) vol_ratios: 列表每个元素为该档粒径占总骨料体积的比例sum(vol_ratios)1 target_agg_vol box_volume * total_volume_frac aggregate_sizes [] for (d_min, d_max), vol_ratio in zip(size_ranges, vol_ratios): # 该档粒径骨料的总体积 range_vol target_agg_vol * vol_ratio # 假设该档内骨料平均直径 d_avg (d_min d_max) / 2.0 avg_agg_vol (4/3) * np.pi * (d_avg/2)**3 # 估算该档需要的骨料个数取整 num_in_range int(range_vol / avg_agg_vol) for _ in range(num_in_range): # 在该档粒径范围内随机生成一个直径 dia random.uniform(d_min, d_max) aggregate_sizes.append(dia) # 由于取整总体积可能略有偏差可在此进行微调 # 按直径从大到小排序关键步骤 aggregate_sizes.sort(reverseTrue) return aggregate_sizes3.2 实现“取-放”投放算法这是最核心的函数。我们实现一个简化版的“取-放”法包含基本的冲突检测和重试机制。def place_aggregates_sequential_packing(box_bounds, aggregate_sizes, max_attempts_per_agg1000, min_gap0.05): 顺序投放骨料先大后小。 box_bounds: (x_min, x_max, y_min, y_max, z_min, z_max) aggregate_sizes: 已排序的骨料直径列表 max_attempts_per_agg: 每个骨料的最大尝试次数 min_gap: 骨料间最小安全间隙 placed_aggregates [] # 已成功放置的骨料列表 failed_aggregates [] # 暂时放置失败的骨料用于后续二次处理 x_min, x_max, y_min, y_max, z_min, z_max box_bounds box_size np.array([x_max-x_min, y_max-y_min, z_max-z_min]) for i, dia in enumerate(aggregate_sizes): print(fPlacing aggregate {i1}/{len(aggregate_sizes)} (D{dia:.2f}mm)...) placed False for attempt in range(max_attempts_per_agg): # 随机生成一个候选位置 center np.array([ random.uniform(x_min dia/2, x_max - dia/2), random.uniform(y_min dia/2, y_max - dia/2), random.uniform(z_min dia/2, z_max - dia/2) ]) candidate_agg Aggregate(diameterdia, centercenter) # 检查是否在边界内 if not candidate_agg.is_inside_boundary(box_bounds): continue # 检查与所有已放置骨料是否冲突 conflict False for existing_agg in placed_aggregates: if candidate_agg.is_overlap(existing_agg, min_gap): conflict True break if conflict: continue # 通过所有检查接受该骨料 placed_aggregates.append(candidate_agg) placed True break if not placed: print(f Failed to place aggregate D{dia:.2f} after {max_attempts_per_agg} attempts. Skipping for now.) failed_aggregates.append(dia) print(fPlacement completed. Success: {len(placed_aggregates)}, Failed: {len(failed_aggregates)}) return placed_aggregates, failed_aggregates3.3 可视化与输出生成完成后必须进行可视化检查确认骨料分布是否随机、有无异常重叠、体积分数是否达标。import pyvista as pv def visualize_aggregates(aggregates, box_bounds): 使用PyVista可视化生成的骨料模型 plotter pv.Plotter() # 绘制试件边界框 x_min, x_max, y_min, y_max, z_min, z_max box_bounds box pv.Box(bounds(x_min, x_max, y_min, y_max, z_min, z_max)) plotter.add_mesh(box, stylewireframe, colorblack, line_width2, opacity0.3) # 绘制每个骨料球体 for agg in aggregates: sphere pv.Sphere(radiusagg.radius, centeragg.center) # 可以根据骨料大小赋予不同颜色 plotter.add_mesh(sphere, colortan, opacity0.7, show_edgesFalse) plotter.show_grid() plotter.show()计算实际的骨料体积分数与目标值对比def calculate_volume_fraction(aggregates, box_volume): total_agg_volume 0.0 for agg in aggregates: total_agg_volume (4/3) * np.pi * (agg.radius**3) actual_frac total_agg_volume / box_volume return actual_frac最后需要将几何模型输出为有限元软件能识别的格式如.stp(STEP),.iges或者直接生成网格文件如.inp(Abaqus),.msh(Gmsh)。这通常需要借助更专业的库如pythonOCC(CAD内核) 或meshio(网格IO)。一个更直接的思路是将每个球体骨料的中心坐标和半径输出到一个文本文件然后在有限元软件如Abaqus内用Python脚本读取并生成相应的几何部件。def export_to_text(aggregates, filenameaggregates_data.txt): 将骨料信息输出为简单文本格式便于其他程序读取 with open(filename, w) as f: f.write(# Aggregate List: Center(X,Y,Z) and Radius\n) for agg in aggregates: f.write(f{agg.center[0]}, {agg.center[1]}, {agg.center[2]}, {agg.radius}\n) print(fAggregate data exported to {filename})4. 从几何模型到有限元分析关键步骤与常见陷阱生成了漂亮的随机骨料几何模型只是万里长征第一步。接下来要把它变成能计算的分析模型这里面的坑一个接一个。4.1 几何清理与布尔运算我们的目标是得到一个由“骨料相”、“砂浆相”和“ITZ相”组成的多相几何体。通常的建模逻辑是创建代表试件的长方体基体。将所有骨料球体或骨料ITZ壳层从长方体中进行布尔减运算在基体上“挖出”骨料形状的空洞。将独立的骨料几何体代表骨料相与挖洞后的基体代表砂浆相进行布尔加运算组合成一个完整的部件。这里最大的陷阱是布尔运算的失败。当骨料数量成百上千且彼此靠近时CAD内核进行布尔运算极易因为几何容差问题而失败报错诸如“非流形”、“自相交”等。我的经验是保持安全距离如前所述投放时设置一个微小安全距离避免骨料几何体在数学上相切。简化几何对于多面体骨料适当减少面片数量过于复杂的表面会加剧布尔运算的不稳定性。分步进行不要试图一次性对上千个骨料做布尔减。可以尝试分批进行比如每成功减掉100个骨料就保存一个中间模型再继续操作。虽然繁琐但能提高成功率。考虑替代方案如果布尔运算实在无法进行可以考虑“像素体素网格法”。将整个试件空间划分为均匀的立方体网格体素根据每个体素中心点位于哪个材料相骨料、ITZ、砂浆直接给该体素赋予相应的材料属性。这种方法完全避免了布尔运算但模型精度受网格尺寸限制且边界呈锯齿状。4.2 网格划分精度与成本的博弈对于布尔运算成功得到的多相几何体网格划分是下一个挑战。不同材料相之间存在复杂的交界面。为了捕捉ITZ的力学行为通常需要在其厚度方向布置至少2-3层单元。假设ITZ厚度为50微米这意味着单元尺寸需要控制在20微米左右。对于一个标准立方体试件例如150mm边长的立方体这会导致单元数量达到一个天文数字数十亿甚至更多完全无法计算。因此实际研究中必须做出妥协代表性体积单元RVE不模拟整个试件而是选取一个尺寸足够大、能反映材料统计特性的最小体积单元进行建模。这个RVE的尺寸需要通过收敛性分析来确定即不断增大模型尺寸直到其等效宏观力学响应不再显著变化。均匀化与周期性边界条件对RVE施加周期性边界条件使其可以代表材料中的任意一点然后通过均匀化理论计算其等效宏观性能。这通常用于研究材料的有效弹性模量等线性行为。局部精细化网格如果重点研究裂缝扩展可以采用全局-局部多尺度方法或者在裂缝可能扩展的路径区域进行局部网格加密其他区域使用较粗网格。放弃实体ITZ建模如前所述采用“界面单元”或“粘结单元”来模拟ITZ的行为。在骨料和砂浆的接触面上插入一层具有特定力学属性如内聚力模型的零厚度或有限厚度界面单元。这避免了划分超薄实体网格的难题。4.3 材料属性赋值与界面设置即使几何和网格都完美材料属性赋值错误也会导致结果毫无意义。骨料通常视为线弹性材料弹性模量高如70GPa花岗岩泊松比低。砂浆可采用更复杂的本构模型如弹塑性模型、损伤塑性模型以模拟其受压软化、受拉开裂等行为。ITZ或界面单元这是关键。通常赋予其低于砂浆的强度和刚度。常用内聚力模型Cohesive Zone Model来定义其拉伸和剪切强度、断裂能等参数。这些参数往往需要通过微观或纳观实验或者分子动力学模拟来标定是细观模拟中的主要不确定性来源之一。一个容易忽略的细节是网格依赖性。特别是当使用损伤或软化类材料模型时裂缝带的能量耗散会依赖于网格尺寸。网格越细裂缝带越集中耗散的能量越少导致结果不客观。解决方法包括使用非局部模型、梯度增强模型或者根据断裂能对材料软化段的应力-位移曲线进行标定使其满足网格无关的能量耗散。5. 模型验证与结果解读如何判断你的模拟是可信的辛辛苦苦建好模型、算完分析得到了一堆云图和曲线。如何判断这些结果不是数字垃圾而是有物理意义的洞察模型验证至关重要。5.1 几何与统计验证首先验证生成的几何模型本身体积分数验证计算模型中所有骨料的总体积除以试件体积看是否与设计目标值一致通常在1%误差内可接受。级配验证将模型中的骨料按粒径分档统计绘制累计筛余曲线与目标级配曲线对比。空间分布检验可以使用“Ripley‘s K函数”或“最近邻距离分布”等空间统计方法检验骨料在空间中是随机分布还是存在聚类或排斥。理想的随机骨料模型应满足均匀随机分布。5.2 力学响应验证这是核心。将你的细观模型进行简单的单轴压缩或拉伸模拟将其应力-应变曲线、峰值强度、弹性模量与以下几类结果对比宏观均质模型结果使用相同的砂浆和骨料属性但将混凝土视为均质材料用宏观本构模型如混凝土损伤塑性模型进行模拟。细观模型的结果如弹性模量应与通过混合率法则如Voigt-Reuss-Hill平均估算的值在量级上相符。解析解或半解析解对于某些简单情况如稀疏骨料分布可能存在理论解。实验结果这是最可靠的验证。与相同配合比混凝土试件的实验室试验结果对比。注意实验室试件本身也存在变异性模拟结果落在试验结果的离散范围内是合理的。不要期望完全吻合。细观模拟的目的往往不是精确预测某个特定试件的绝对强度而是揭示破坏机理、研究参数影响规律、解释宏观现象背后的微观原因。例如你可以通过模拟观察到裂缝确实优先在ITZ萌生。骨料形状越不规则裂缝路径越曲折耗能越多。增加骨料体积分数弹性模量提高但可能因ITZ面积增加而导致抗拉强度下降。这些定性或半定量的规律与物理直觉和实验观察是否一致是判断模拟是否成功的关键。5.3 敏感性分析由于许多细观参数尤其是ITZ属性难以精确测定进行参数敏感性分析是必要的。例如系统性地改变ITZ的厚度、弹性模量、强度观察其对混凝土宏观弹性模量、抗压强度、断裂能的影响程度。这能告诉你哪些参数对结果影响最大从而指导实验测量应重点关注哪些参数也让你对模拟结果的可靠性有一个量化的认识。最后我想说的是混凝土细观力学建模是一个从几何、到网格、到材料、再到求解的完整链条任何一个环节的粗糙处理都可能使最终结果失真。生成三维随机骨料模型是一个很好的起点它强迫你去思考混凝土材料的本质。但记住模型永远是现实的简化。清晰的物理图像、合理的简化假设、严谨的验证过程比追求极致的几何细节或网格数量更重要。当你看着屏幕上那个由无数彩色球体或石块组成的数字混凝土在载荷下逐渐开裂、破碎时你看到的不仅是应力云图更是对材料行为更深层次的理解。这个过程充满挑战但也正是其魅力所在。本文还有配套的精品资源点击获取