我目前正在尝试进行静磁 FEM 模拟,我想使用 GMSH 对几何体进行网格划分。几何形状如下所示:在
中我使用 FreeCAD 创建几何图形,并将其作为 .STEP 文件导入 GMSH。在 GMSH 中,我定义了 3 个物理组,生成以下脚本:
Merge "yoke_simulation.step";
Physical Volume("iron") = {1, 7, 9, 6, 3, 2, 4};
//+
Physical Volume("current") = {5};
//+
Physical Volume("air") = {8};
问题在于 GMSH 似乎为每个实体创建了一个单独的网格,而没有将这些网格相互连接。例如,如果观察两个锥体之间的区域,很明显两个锥体的网格与空气的网格没有连接:
如何让 GMSH 为所有实体创建单个连接的网格?
现在看来,
Air
体积8
只是整体边界框,无需减去Iron
和Current
的体积。因此,它为整个边界框创建了一个四面体网格,而不考虑其他实体。
我不是 FreeCAD 专家,所以我真的不知道如何在那里正确设置它。可能的话,尝试在那里指定
Air
卷,确保它不包含您的详细信息。
另一种方法可能涉及 GMSH 级别的轻微修改。例如,在物理化之前创建适当的
Air
体积。您想要从体积 1, 7, 9, 6, 3, 2, 4, 5
中减去体积 8
。这可以通过以下方式实现
BooleanDifference(100) = { Volume{8}; Delete; }{ Volume{1,7,9,6,3,2,4,5}; };
Physical Volume("air") = {100};
注意,前面的代码只有在使用 GMSH 内的 OpenCASCADE 内核时才有效。 请参阅 GMSH 中的以下示例代码以供参考:
SetFactory("OpenCASCADE");
Box(1) = {0,0,0, 1,1,1};
Box(2) = {0.1,0.1,0.1, 0.2,0.2,0.2};
Box(3) = {0.5,0.5,0.5, 0.2,0.2,0.2};
BooleanDifference(100) = { Volume{1}; Delete; }{ Volume{2,3}; };
Physical Volume ("air") = {100};
Physical Volume ("iron") = {2,3};
删除命令一致性;合并线后将迫使 GMSH 形成一个连贯的网格,而不会重叠体积。
我创建了一组免费开源工具来为多材料 FEM 生成分区网格。 它们可以在这里找到 github.com/NH89/SOFA_mesh_partitioning_tools
它们基于 CGAL 几何库,并从任意相交的三角表面网格生成分区四面体网格。
它们旨在与 SOFA 实时软物质 FEM 框架一起使用,但也可用于任何分区 FEM 应用程序。
我认为最好的做法是使用Fragmentation的布尔运算,从官方代码中是这样说的:
计算由交集产生的布尔片段(通用熔丝) 实体
和objectDimTags
(作为 (dim, tag) 的向量给出 对)在 OpenCASCADE CAD 表示中,使所有接口共形...toolDimTags
这就是我在案例中的做法,使用 Julia 和包装器
Gmsh.jl
:
function create_mesh(step_file, output_msh)
# Initialize Gmsh
gmsh.initialize()
# Load STEP file
gmsh.merge(step_file)
gmsh.parser.setNumber("lc", [1e-4]) # overrides subsequent DefineConstant variables
# Generate mesh
gmsh.model.geo.synchronize()
ov, ovv = gmsh.model.occ.fragment([(3, 3), (3, 2)], [(3, 1)]) # [(dim, tag), (dim, tag)], [(dim, tag)], internal_tag
# ov contains all the generated entities of the same dimension as the input
# entities:
println("fragment produced volumes:")
for e in ov
println(e)
end
gmsh.model.occ.synchronize()
# Name surfaces
gmsh.model.addPhysicalGroup(2, [9], 1, "up") # 2 <-> Surface, [9] = entity_parsed_tag, 1 = internal_tag,
gmsh.model.addPhysicalGroup(2, [2], 2, "down") # 2 <-> Surface, [2] = entity_parsed_tag, 1 = internal_tag
# Name volumes
gmsh.model.addPhysicalGroup(3, [3, 1], 3, "non_opimize") # 3 <-> Volume, [3, 1] = entity_parsed_tag, 3 = internal_tag, "non_opimize" = physical_name
gmsh.model.addPhysicalGroup(3, [2], 4, "optimize") # 3 <-> Volume, [2] = entity_parsed_tag, 4 = internal_tag, "opimize" = physical_name
# Boolean operation on different bodies
gmsh.model.mesh.generate(3)
# Write mesh to file
gmsh.write(output_msh)
# Finalize Gmsh
gmsh.finalize()
end