Reputation: 289
I am currently trying to do a magnetostatic FEM simulation and I want to mesh my geometry using GMSH. The geometry is shown below: in
I create the geometry using FreeCAD and import into GMSH as a .STEP File. In GMSH I define 3 physical groups, resulting in the following script:
Merge "yoke_simulation.step";
Physical Volume("iron") = {1, 7, 9, 6, 3, 2, 4};
//+
Physical Volume("current") = {5};
//+
Physical Volume("air") = {8};
When I create the Mesh, I get the following result:
The problem is that GMSH seems to be creating a seperate mesh for each body without connecting these meshes with one another. If one looks at the region between the two cones for example, it is evident that the mesh of the two cones is not connected to the mesh of the air:
How can I get GMSH to create a single, connected mesh for all bodies?
Upvotes: 3
Views: 5064
Reputation: 531
I think the best way to proceed is to use the boolean operation of Fragmentation, from the official code is said:
Compute the boolean fragments (general fuse) resulting from the intersection of the entities
objectDimTags
andtoolDimTags
(given as vectors of (dim, tag) pairs) in the OpenCASCADE CAD representation, making all interfaces conformal...
That's how I do it on my cases, using Julia with the wrapper 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
This create a uniform mesh like the following one from 3 distinct volumes (please infer the volumes definition)
Upvotes: 0
Reputation: 29
I have created a set of free-and-open-source tools to generate partitioned meshes for multi-material FEM. They are available here github.com/NH89/SOFA_mesh_partitioning_tools
The are based on the CGAL geometry library, and generate a partitioned tetrahedral mesh from arbitrary intersecting triangulated surface meshes.
They are conceived for use with the SOFA real-time soft matter FEM framework, but could be used for any partitioned FEM application.
Upvotes: 0
Reputation: 9
Dropping the command Coherence; after the merge line will force GMSH to form a coherent mesh without overlapping volumes.
Upvotes: 0
Reputation: 2326
It seems that right now the Air
volume 8
is just the overall bounding box, without necessary subtraction of volumes for Iron
and Current
. Thus, it creates a tetrahedral mesh for the entire bounding box without taking other bodies into the account.
I am not a FreeCAD expert, so I don't really know how to setup it properly there. Possibly, try specifying the Air
volume there making sure it does not contain your detail.
Another approach could involve slight modifications at the GMSH level. For example, creating the proper Air
volume before making it physical. You have volumes 1, 7, 9, 6, 3, 2, 4, 5
which you want to subtract from volume 8
. That can be achieved by
BooleanDifference(100) = { Volume{8}; Delete; }{ Volume{1,7,9,6,3,2,4,5}; };
Physical Volume("air") = {100};
Notice, that the previous code will work only if OpenCASCADE kernel inside GMSH is used. Please, see the following sample code in GMSH for reference:
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};
Upvotes: 2