Gmsh and only C3D10 elements

Hello!

I’d like to ask for some help. I want to generate a mesh using gmsh for Calculix, specifically using only C3D10 elements.

I have a cube.geo file as follows:

SetFactory("OpenCASCADE");

// 1x1x1 cube
Merge "cube.step";

// Set mesh sizes
Mesh.CharacteristicLengthMin = 0.5; // Minimum size
Mesh.CharacteristicLengthMax = 0.8; // Maximum size

// ?? Generate C3D10 (second order tetrahedron)
Mesh.ElementType = 5;   // Tetrahedron
Mesh.ElementOrder = 2;
Mesh.SecondOrderLinear = 0;

// Generate 3D mesh
Mesh 3;

Save "cube.msh";

When I open this file in gmsh and view the statistics, I get:

  • 231 nodes
  • 8 points
  • 24 lines
  • 84 triangles
  • 100 tetrahedra

I’m not sure if points, lines and triangles should be there…
How can I use the generated .msh file in Calculix?

From Gmsh documentation:

How can I only save tetrahedral elements (not triangles and lines)?

By default, if physical groups are defined, the output mesh only contains those elements that belong to physical entities. So to save only 3D elements, simply define one (or more) physical volume(s) and don’t define any physical surfaces, physical curves or physical points.

So just create a physical volume like for example:

Physical Volume(13) = {1};

Better export to .inp since that’s the format CalculiX uses.

2 Likes

Thank you! It is easier to handle this way!

Just for completeness, here is the working .geo file:

SetFactory("OpenCASCADE");

Merge "cube.step";

Physical Volume(13) = {1};

// Set mesh sizes
Mesh.CharacteristicLengthMin = 0.5; // Minimum size
Mesh.CharacteristicLengthMax = 0.8; // Maximum size

// Generate C3D10 (second order tetrahedron)
Mesh.ElementType = 5;   // Tetrahedra
Mesh.ElementOrder = 2;
Mesh.SecondOrderLinear = 0;

// Generate 3D mesh
Mesh 3;

Save "cube.inp";

I propose a slightly different solution.

Define Physical Surface for applying constraints.

Add the following line to your .geo file:

Mesh.SaveGroupsOfElements = -1000;

Then gmsh will only save volume elements. Any Physical Surface you have defined will then consist of nodes from the volume elements. This is much more useful then the default surface sets.

If you want to use *RIGID BODY constraints, then it is a good idea to reserve some node numbers for REF NODE and ROT NODE:

Mesh.FirstNodeTag = 5; // Reserve node numbers 1-4.

A Physical Volume is required for gmsh to generate *ELEMENT. This also results in an extra *ELSET, that is why I usually name the physical volume ignore. :slight_smile:

Below is my standard .geo template for meshing a STEP-file with C3D10 elements:

SetFactory("OpenCASCADE");
// Convert coordinates to meters
Geometry.OCCTargetUnit = "M";
Merge "import.stp";

// Describe all physical groups to be saved.
Physical Surface("Nload") = {7};
Physical Surface("Nfix") = {9};
Physical Volume("ignore", 1) = {1};

Mesh.Algorithm = 2; // Automatic
Mesh.ElementOrder = 2; // Create second order elements.
Mesh.SecondOrderIncomplete = 1; // Use 10-node tet elements.

Mesh.MeshSizeFromCurvature = 40;
Mesh.MeshSizeMax = 0.01;

Mesh.FirstNodeTag = 5; // Keep node 1-4 free for ref nodes.
Mesh.Format = 39; // Save mesh as INP format.
Mesh.SaveGroupsOfNodes = 1;
Mesh.SaveGroupsOfElements = -1000; // Only save volume elements.
Mesh.Optimize = 1;

Mesh 3;
OptimizeMesh "Gmsh";
Coherence Mesh;

Save "gmsh-output.inp";

If you want to include the generated input in your own input file, make sure that there is only one *heading in both of them.

3 Likes

Thank you!

It is almost perfect. The ID of the first element is now 117, not 1 and it ignores Mesh.FirstElementTag, but no *ELSET is generated (I do not need it).

If you want to include the generated input in your own input file, make sure that there is only one *heading in both of them.

Okay, I’ll keep it in mind.

I have faced a similar problem the last weeks. For me, the .inp export did not work in my pipeline without writing code that opens the exported file and delete unnecessary lines.

To have more flexibility later on, I directly picked the mesh information from the gmsh kernel in python. Physical groups can then be exported with

physical_groups = gmsh.model.getPhysicalGroups()

for dim, tag in physical_groups:
   name = gmsh.model.getPhysicalName(dim, tag)
   entities = gmsh.model.getEntitiesForPhysicalGroup(dim, tag)

   for edim, etag in entities:
       # getNodes
       # getElements

Nodes and their coordinates can be extracted by:

(node_tags, node_coords, _) = model.mesh.getNodes(dim=-1, tag=-1, returnParametricCoord=False)
# Then, write the nodes into your data structure.

Same goes for the element connectivity.
You just have to make sure that you do not mix around the order of the lists you will receive. And note that for C3D10 tets, the last two node ids in the connectivity seem to be switched in the gmsh kernel.

This might be a little more effort, but you will have more control on what to export into your calculix mesh, as well as full control over physical entities.

That is because the previous element ID’s are taken up by the surface meshes.

I have not found a way to delete only the surface meshes using the gmsh scripting language.

It is however not that difficult to use e.g. Python to post-process the .inp file generated by gmsh and renumber the elements.

1 Like

Thank you! I’ll look into that. I’m planning to use simple .geo files for now, but nice to have a plan B.

Not really a problem, just bothered me a bit. Thank you very much for your help!