全国服务热线

178-9711-7595
案例展示
当前位置:首页>>案例展示
如何在 COMSOL 中创建随机几何结构
作者:管理员   时间:2023-12-23 13:16:01  来源:本站   浏览804次

你有没有想过在你的模型中加入一个随机创建的几何对象?比如你想要模拟一种天然材料,或者一种在尺寸变化上具有某些已知的统计分布的零件排列。当遇到这类情况时,你可能希望在 COMSOL Multiphysics® 软件中创建一个随机几何对象。对此,我们可以借助模型方法来实现这个需求。本文我们将以一块美味的奶酪为例,介绍具体的操作方法。

建立瑞士奶酪模型

挑选出世界上最好的奶酪,是一项艰巨且难以抉择的任务,但是我可以发表自己的意见:优质的埃曼塔(Emmentaler)奶酪绝不会输给其他任何种类。一位奶酪制作大师或许会开玩笑地说,其实是奶酪上的蜂窝状圆孔增加了风味。所以如果要在 COMSOL Multiphysics 中建立一个逼真的圆盘状奶酪模型,我们必须加上这些小孔。

图片1.png

埃曼塔奶酪的模型,小孔的位置与大小均为随机设定。

事实证明,瑞士奶酪中的小孔形成的原因相当复杂,所以我们不会去模拟小孔的形成,而是简单地建立一个如上图所示的奶酪模型。我们计划在奶酪中添加一组随机分布的小孔,其半径在一个上限和一个下限之间随机浮动。在 COMSOL Multiphysics中,我们可以使用模型方法功能创建这个随机几何对象。那么,该如何实现呢?

在 COMSOL Multiphysics® 中引入模型方法

在 Windows® 平台上运行 COMSOL Multiphysics® 并使用模型开发器时,你会在功能区看到一个开发工具选项,如下面的截图所示。其中一个选项是录制方法。单击此选项后,系统会提示您输入新方法的名称和方法类型。您可以输入任意符合要求的字符串来定义方法名称,方法类型则可选 App 方法或模型方法。

您可以在 COMSOL App 中使用 App方法,这个教程视频中介绍了该方法的使用过程。模型方法可以在 COMSOL Multiphysics 的底层模型中使用,并可以基于已有的模型数据运行(并添加信息)。

图片2.png

开发工具选项卡,显示了录制方法和运行模型方法按钮。

单击录制方法对话框中的确定按钮后,您将看到一圈高亮的红线环绕整个图形用户界面。随后所有的执行操作都会录制到此方法中,直到单击停止录制按钮。然后,您可以切换到App 开发器来查看录制好的方法。下方截图显示了录制完单个几何对象的创建过程后的App 开发器和方法。这是一个标签为 cyl1、半径为 40 cm、高度为 20 cm 的圆柱体,对于圆盘奶酪而言,这是一个良好的初始近似值。

图片3.png

App 开发器,显示了用于创建几何对象的模型方法代码。

在模型开发器中,借助开发工具选项卡下的运行模型方法按钮,就能够在其他任何模型文件(只要模型文件的几何序列中不存在带有 cyl1 标签的现有对象)中调用这个模型方法。当然,这个简单的模型方法仅仅创建了一个圆柱体。如果要模拟小孔,我们需要在方法中引入一些随机性。接下来,我们将研究这一点。

创建一个随机的几何特征集

在模型方法中,您可以调用标准 Java® 类,例如返回大于或等于 0.0 且小于 1.0 的双精度数的Math.random 类。我们将使用这个类,和新编写的少量代码,在圆盘奶酪模型中建立指定数量、位置和大小随机设定的小孔。

假设整块奶酪中随机分布 1000 个小孔,每个小孔的半径随机分布在 0.1 cm 到 1 cm 之间。此外不要忘记,埃曼塔奶酪有一层天然的坚硬外皮,其上不会形成小孔。所以,我们需要添加一些逻辑,确保 1000 个小孔实际存在于奶酪内部。下方的完整模型方法(添加了行号,并将文本字符串标记为红色)展示了具体的设置步骤。

1  int NUMBER_OF_HOLES = 1000;
2  int ind = 0;
3  double hx, hy, hz, hr = 0.0;
4  double CHEESE_HEIGHT = 20.0;
5  double CHEESE_RADIUS = 40.0;
6  double RIND_THICKNESS = 0.2;
7  double HOLE_MIN_RADIUS = 0.1;
8  double HOLE_MAX_RADIUS = 1.0;
9  model.component("comp1").geom("geom1").lengthUnit("cm");
10 model.component("comp1").geom("geom1").selection().create("csel1", "CumulativeSelection");
11 while (ind < NUMBER_OF_HOLES) {
12   hx = (2.0*Math.random()-1.0)*CHEESE_RADIUS;
13   hy = (2.0*Math.random()-1.0)*CHEESE_RADIUS;
14   hz = Math.random()*CHEESE_HEIGHT;
15   hr = Math.random()*(HOLE_MAX_RADIUS-HOLE_MIN_RADIUS)+HOLE_MIN_RADIUS;
16   if ((Math.sqrt(hx*hx+hy*hy)+hr) > CHEESE_RADIUS-RIND_THICKNESS) {continue; }
17   if (((hz-hr) < RIND_THICKNESS) || ((hz+hr) > CHEESE_HEIGHT-RIND_THICKNESS)) {continue; }
18   model.component("comp1").geom("geom1").create("sph"+ind, "Sphere");
19   model.component("comp1").geom("geom1").feature("sph"+ind).set("r", hr);
20   model.component("comp1").geom("geom1").feature("sph"+ind).set("pos", new double[]{hx, hy, hz});
21   model.component("comp1").geom("geom1").feature("sph"+ind).set("contributeto", "csel1");
22   ind++;
23 }
24 model.component("comp1").geom("geom1").create("cyl1", "Cylinder");
25 model.component("comp1").geom("geom1").feature("cyl1").set("r", CHEESE_RADIUS);
26 model.component("comp1").geom("geom1").feature("cyl1").set("h", CHEESE_HEIGHT);
27 model.component("comp1").geom("geom1").create("dif1", "Difference");
28 model.component("comp1").geom("geom1").feature("dif1").selection("input").set("cyl1");
29 model.component("comp1").geom("geom1").feature("dif1").selection("input2").named("csel1");
30 model.component("comp1").geom("geom1").run();

让我们一起逐行分析上述模型方法:

1. 初始化并定义奶酪内的小孔总数。

2. 初始化并定义用于后续步骤的索引计数器。
3. 初始化一组用于保留每个小孔的 xyz 位置和半径的双精度数。
4–8. 初始化并定义一组数字,以 cm 为单位定义奶酪的高度、半径、环线粗细以及小孔的最大和最小半径。
9. 将几何的长度单位设置为 cm。
10. 创建一个新选择集,并添加标签 csel 和名称 CumulativeSelection。请注意:如果类似的选择集已存在,此时该方法将失败。如果您要在同一个文件中反复运行该方法,可以通过修改方法来解决这个问题。
11. 初始化 while 循环,创建指定数量的孔。
12–14. 通过调用随机方法和缩放输出来定义小孔的 xyz 坐标,使小孔的 xyz 坐标位于奶酪模型的笛卡尔坐标的外部界限之内。
15. 在规定的限值范围内定义小孔半径。
16–17. 检查小孔的位置和尺寸是否会使其脱离奶酪。如果是,继续执行 while 循环的下一次迭代,停止执行循环中的剩余代码。此检查可在一行中进行,也可以分为三行,这取决于您的编程风格。
18. 创建一个球体,使其名称基于当前的索引值。
19–20. 指定新创建球体的半径和位置。虽然半径可以通过一个双精度数直接传递,但位置必须使用双精度数组。
21. 指定此球体特征属于名为 csel1 的选择集的一部分(做出了贡献)。
22–23. 对索引运行迭代,表明已创建球体,并结束 while 循环。
24–26. 创建一个代表圆盘奶酪的圆柱体。
27–29. 建立一个布尔差集运算。要添加的对象是圆柱体,要减去的对象是所有球体的选择。
30. 运行整个几何序列,将所有球体从圆柱体中切除,最终形成圆盘奶酪。

我们可以在新的(和空的)模型文件中运行这个方法,来创建一个圆盘奶酪模型。每一次重新运行此方法,会得到一个不同的模型。模型文件中的几何序列包含全部球体、圆柱体以及布尔运算。

如果有必要,我们还可以在模型方法中添加一些额外的代码,直接输出最终模型(奶酪)的几何文件。您可以使用 COMSOL Multiphysics 格式或者 STL 文件格式编写模型文件,也可以使用任何包含 Parasolid® 软件内核的可选模块,并以 Parasolid®软件或 ACIS® 软件文件格式导出。相比于直接处理完整的几何序列,在处理最终几何对象之前,先进行导出和重新导入的效率更高。

下图是我们的努力成果。嗯,看上去很美味!

图片4.png

将被吃掉的埃曼塔圆盘奶酪的模型。

结束语

文中,我们通过一个简单示例介绍了如何使用模型方法来创建位置和大小随机分布的几何对象。我们留了一些尚未解决的问题,例如,如何确保孔洞不重叠,或者如何模拟密集叠加的布局等。不过,这些问题本质上是各自领域中的一些数学难题。