GMSH Transfinite Volume & Fenics I/0

I would like to create an ordered mesh with GMSH along with physical tags to apply boundary conditions to. I noticed that after adding transfinite lines/surfaces/volumes to create the ordered mesh, dolfin-convert fails to convert the mesh file to .xml format. In addition, I used the meshio package similar to previous posts, and it eventually fails when trying to read the mesh functions from the .h5 file. I use gmsh version 3.0.6, and the dolfin 2019.1.0 Docker image. The following is a .geo file of a sample geometry I would to import into fenics:

// Gmsh project created on Tue Jul 16 15:55:38 2019
SetFactory(“OpenCASCADE”);
x = 0.1;
//+
Point(1) = {0, 0, 0, x};
//+
Point(2) = {1, 0, 0, x};
//+
Point(3) = {1, 1, 0, x};
//+
Point(4) = {0, 1, 0, x};
//+
Point(5) = {0, 0, 1, x};
//+
Point(6) = {1, 0, 1, x};
//+
Point(7) = {1, 1, 1, x};
//+
Point(8) = {0, 1, 1, x};
//+
Line(1) = {1, 2};
//+
Line(2) = {2, 3};
//+
Line(3) = {3, 4};
//+
Line(4) = {4, 1};
//+
Line(5) = {5, 6};
//+
Line(6) = {6, 7};
//+
Line(7) = {7, 8};
//+
Line(8) = {8, 5};
//+
Line(9) = {5, 1};
//+
Line(10) = {2, 6};
//+
Line(11) = {7, 3};
//+
Line(12) = {4, 8};
//+
Line Loop(1) = {5, -10, -1, -9};
//+
Plane Surface(1) = {1};
//+
Line Loop(2) = {12, -7, 11, 3};
//+
Plane Surface(2) = {2};
//+
Line Loop(3) = {6, 7, 8, 5};
//+
Plane Surface(3) = {3};
//+
Line Loop(4) = {8, 9, -4, 12};
//+
Plane Surface(4) = {4};
//+
Line Loop(5) = {4, 1, 2, 3};
//+
Plane Surface(5) = {5};
//+
Line Loop(6) = {10, 6, 11, -2};
//+
Plane Surface(6) = {6};
//+
Surface Loop(1) = {1, 3, 6, 2, 4, 5};
//+
Volume(1) = {1};
//+
Transfinite Volume{1} = {1, 2, 6, 5, 4, 3, 7, 8};
//+
Transfinite Line {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} = 10 Using Progression 1;
//+
Transfinite Surface {4} Left;
//+
Transfinite Surface {6} Right;
//+
Transfinite Surface {1} Left;
//+
Transfinite Surface {2} Right;
//+
Transfinite Surface {3} Left;
//+
Transfinite Surface {5} Right;
//+
Physical Surface(“inlet”) = {1};
//+
Physical Surface(“outlet”) = {2};
//+
Physical Surface(“walls”) = {3, 4, 5, 6};
//+
Physical Volume(“fluid”) = {1};

Once again, using a mesh with either transfinite or physical definitions works, however using both definitions fails when using dolfin-convert or meshio. This is the error when using dolfin-convert:

Converting from Gmsh format (.msh, .gmsh) to DOLFIN XML format
Expecting 1000 vertices
Found all vertices
Expecting 4374 cells
Found all cells
Traceback (most recent call last):
File “/usr/local/bin/dolfin-convert”, line 132, in
main(sys.argv[1:])
File “/usr/local/bin/dolfin-convert”, line 79, in main
meshconvert.convert2xml(ifilename, ofilename, iformat=iformat)
File “/usr/local/lib/python3.6/dist-packages/dolfin_utils/meshconvert/meshconvert.py”, line 1301, in convert2xml
convert(ifilename, XmlHandler(ofilename), iformat=iformat)
File “/usr/local/lib/python3.6/dist-packages/dolfin_utils/meshconvert/meshconvert.py”, line 1322, in convert
gmsh2xml(ifilename, handler)
File “/usr/local/lib/python3.6/dist-packages/dolfin_utils/meshconvert/meshconvert.py”, line 494, in gmsh2xml
index = nodes_as_facets[tuple(nodes)]
KeyError: (4, 40, 72)

This is the error when converting with meshio and reading from .h5:

Traceback (most recent call last):
File “example3.py”, line 9, in
infile.read(mvc, “name_to_read”)
RuntimeError:

*** -------------------------------------------------------------------------
*** DOLFIN encountered an error. If you are not able to resolve this issue
*** using the information listed below, you can ask for help at


*** fenics-support@googlegroups.com


*** Remember to include the error message listed below and, if possible,
*** include a minimal running example to reproduce the error.


*** -------------------------------------------------------------------------
*** Error: Unable to find entity in map.
*** Reason: Error reading MeshValueCollection.
*** Where: This error was encountered inside HDF5File.cpp.
*** Process: 0


*** DOLFIN version: 2019.1.0
*** Git changeset: 74d7efe1e84d65e9433fd96c50f1d278fa3e3f3f
*** -------------------------------------------------------------------------

Any help would be appreciated.
Also, is it possible to use meshio to read a quadrilateral/hexahedral mesh into fenics?
Thank you.

Does this really happen only if you add the transfinite property?
Which format did you save the mesh in? Which gmsh version are you using?
Gmsh 4 introduced a new format that dolfin-convert does not understand (yet).

You can invoke the mesh generation like this to force msh2 or msh22 format:

gmsh -format msh2 ...
gmsh -format msh22 ...

Hi there,

I am also experiencing the same error with pliebersbach.
To be more specific, I try to make structured 3D mesh using GMSH and convert this mesh to FEniCS as well as import the boundary data and subdomain data using Meshio. I could do so when I delete the transfinite volume out of my .geo file, but in this case, the mesh will not be structured. However, if I want to leave the transfinite volume in the .geo file to keep my mesh structured, I need to only convert the .msh file to .xmdf file using meshio and explicitly define my subdomains and boundaries in FEniCS’s script, which is not practical for complex geometry. I would like to ask if anyone here know some work around on this problem?

My .geo file is the following

//+
Point(1) = {0, 0, 0, 1.0};
//+
Point(2) = {0, 0.75, 0, 1.0};
//+
Point(3) = {0, -0.75, 0, 1.0};
//+
Point(4) = {0, 0, 0.75, 1.0};
//+
Point(5) = {0, 0, -0.75, 1.0};
//+
Point(6) = {0, 1, 1, 1.0};
//+
Point(7) = {0, -1, -1, 1.0};
//+
Point(8) = {0, 1, -1, 1.0};
//+
Point(9) = {0, -1, 1, 1.0};
//+
Rotate {{1, 0, 0}, {0, 0, 0}, Pi/4} {
  Point{5}; Point{2}; Point{4}; Point{3}; 
}
//+
Circle(1) = {2, 1, 4};
//+
Circle(2) = {4, 1, 3};
//+
Circle(3) = {3, 1, 5};
//+
Circle(4) = {5, 1, 2};
//+
Line(5) = {7, 8};
//+
Line(6) = {8, 6};
//+
Line(7) = {7, 9};
//+
Line(8) = {9, 6};
//+
Line(9) = {3, 7};
//+
Line(10) = {5, 8};
//+
Line(11) = {2, 6};
//+
Line(12) = {4, 9};
//+
Line Loop(1) = {4, 11, -6, -10};
//+
Plane Surface(1) = {1};
//+
Line Loop(2) = {8, -11, 1, 12};
//+
Plane Surface(2) = {2};
//+
Line Loop(3) = {2, 9, 7, -12};
//+
Plane Surface(3) = {3};
//+
Line Loop(4) = {3, 10, -5, -9};
//+
Plane Surface(4) = {4};
//+
Line Loop(5) = {4, 1, 2, 3};
//+
Plane Surface(5) = {5};
//+
Extrude {2, 0, 0} {
  Surface{1}; Surface{2}; Surface{3}; Surface{4}; Surface{5}; 
}
//+
Transfinite Line {6, 8, 7, 5, 4, 1, 2, 3, 68, 64, 41, 50, 24, 20, 28, 19, 82, 60, 36, 16, 14, 80, 58, 38} = 10 Using Progression 1;
//+
Transfinite Line {10, 9, 12, 11, 17, 59, 39, 15} = 5 Using Progression 1;
//+
Transfinite Surface {122} = {31, 12, 10, 34};
//+
Transfinite Surface {56} = {16, 12, 31, 21};
//+
Transfinite Surface {34} = {16, 20, 10, 12};
//+
Transfinite Surface {100} = {10, 20, 38, 34};
//+
Transfinite Surface {78} = {34, 38, 21, 31};
//+
Transfinite Surface {2} = {2, 6, 9, 4};
//+
Transfinite Surface {3} = {4, 9, 7, 3};
//+
Transfinite Surface {4} = {3, 7, 8, 5};
//+
Transfinite Surface {1} = {5, 8, 6, 2};
//+
Transfinite Surface {5} = {2, 4, 3, 5};
//+
Transfinite Surface {69} = {7, 3, 34, 38};
//+
Transfinite Surface {55} = {9, 4, 31, 21};
//+
Transfinite Surface {25} = {6, 2, 12, 16};
//+
Transfinite Surface {33} = {8, 5, 10, 20};
//+
Transfinite Surface {87} = {5, 3, 34, 10};
//+
Transfinite Surface {65} = {3, 4, 31, 34};
//+
Transfinite Surface {51} = {2, 12, 31, 4};
//+
Transfinite Surface {21} = {5, 10, 12, 2};
//+
Transfinite Surface {29} = {6, 8, 20, 16};
//+
Transfinite Surface {95} = {8, 7, 38, 20};
//+
Transfinite Surface {73} = {7, 9, 21, 38};
//+
Transfinite Surface {43} = {9, 6, 16, 21};
//+
Transfinite Volume{5} = {2, 4, 3, 5, 12, 31, 34, 10};
//+
Transfinite Volume{4} = {3, 7, 8, 5, 34, 38, 20, 10};
//+
Transfinite Volume{3} = {4, 9, 7, 3, 31, 21, 38, 34};
//+
Transfinite Volume{2} = {2, 6, 9, 4, 12, 16, 21, 31};
//+
Transfinite Volume{1} = {5, 8, 6, 2, 10, 20, 16, 12};
//+
Physical Surface("fluid-in") = {5};
//+
Physical Surface("fluid-out") = {122};
//+
Physical Surface("fluid-boundary") = {65, 87, 21, 51};
//+
Physical Surface("solid-sides") = {1, 2, 3, 4, 56, 34, 100, 78, 43, 29, 95};
//+
Physical Surface("solid-bottom") = {73};
//+
Physical Volume("fluid") = {5};
//+
Physical Volume("solid") = {4, 1, 2, 3};

the script I used to import the mesh, subdomains, boundary data is the following,

from fenics import *
from fenics_adjoint import *

mesh = Mesh()
with XDMFFile("workspace/dolfin-adjoint/3-D_application/mesh/mesh.xdmf") as infile:
    infile.read(mesh)

mvc = MeshValueCollection("size_t", mesh, 3)
with XDMFFile("workspace/dolfin-adjoint/3-D_application/mesh/mf.xdmf") as infile:
    infile.read(mvc, "name_to_read")
mf = cpp.mesh.MeshFunctionSizet(mesh, mvc)

mvc = MeshValueCollection("size_t", mesh, 2)
with XDMFFile("workspace/dolfin-adjoint/3-D_application/mesh/cf.xdmf") as infile:
    infile.read(mvc, "name_to_read")
cf = cpp.mesh.MeshFunctionSizet(mesh, mvc)

and the error I got,

*** -------------------------------------------------------------------------
*** DOLFIN encountered an error. If you are not able to resolve this issue
*** using the information listed below, you can ask for help at
***
***     fenics-support@googlegroups.com
***
*** Remember to include the error message listed below and, if possible,
*** include a *minimal* running example to reproduce the error.
***
*** -------------------------------------------------------------------------
*** Error:   Unable to find entity in map.
*** Reason:  Error reading MeshValueCollection.
*** Where:   This error was encountered inside HDF5File.cpp.
*** Process: 0
*** 
*** DOLFIN version: 2019.2.0.dev0
*** Git changeset:  f0a90b8fffc958ed612484cd3465e59994b695f9
*** -------------------------------------------------------------------------

Thank you very much

Hi @phurisja, I was wondering if you solved this problem. I am facing the same issue. Thanks a lot!

I had a look at the original mesh in this post, and made it slightly coarser for easier debugging:

// Gmsh project created on Tue Jul 16 15:55:38 2019
SetFactory(“OpenCASCADE”);
Mesh.SaveAll = 0;
Mesh.SaveParametric = 0;

x = 0.5;
//+
Point(1) = {0, 0, 0, x};
//+
Point(2) = {1, 0, 0, x};
//+
Point(3) = {1, 1, 0, x};
//+
Point(4) = {0, 1, 0, x};
//+
Point(5) = {0, 0, 1, x};
//+
Point(6) = {1, 0, 1, x};
//+
Point(7) = {1, 1, 1, x};
//+
Point(8) = {0, 1, 1, x};
//+
Line(1) = {1, 2};
//+
Line(2) = {2, 3};
//+
Line(3) = {3, 4};
//+
Line(4) = {4, 1};
//+
Line(5) = {5, 6};
//+
Line(6) = {6, 7};
//+
Line(7) = {7, 8};
//+
Line(8) = {8, 5};
//+
Line(9) = {5, 1};
//+
Line(10) = {2, 6};
//+
Line(11) = {7, 3};
//+
Line(12) = {4, 8};
//+
Line Loop(1) = {5, -10, -1, -9};
//+
Plane Surface(1) = {1};
//+
Line Loop(2) = {12, -7, 11, 3};
//+
Plane Surface(2) = {2};
//+
Line Loop(3) = {6, 7, 8, 5};
//+
Plane Surface(3) = {3};
//+
Line Loop(4) = {8, 9, -4, 12};
//+
Plane Surface(4) = {4};
//+
Line Loop(5) = {4, 1, 2, 3};
//+
Plane Surface(5) = {5};
//+
Line Loop(6) = {10, 6, 11, -2};
//+
Plane Surface(6) = {6};
//+
Surface Loop(1) = {1, 3, 6, 2, 4, 5};
//+
Volume(1) = {1};
//+
Transfinite Volume{1} = {1, 2, 6, 5, 4, 3, 7, 8};
//+
Transfinite Line {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} = 2 Using Progression 1;
//+
//+
Physical Surface("inlet") = {1};
//+
Physical Surface("outlet") = {2};
//+
Physical Surface("walls") = {3, 4, 5, 6};
//+
Physical Volume("fluid") = {1};

Transfinite Surface {4} Left;
//+
Transfinite Surface {6} Right;
//+
Transfinite Surface {1} Left;
//+
Transfinite Surface {2} Right;
//+
Transfinite Surface {3} Left;
//+
Transfinite Surface {5} Right;

Then using meshio to convert the mesh to xdmf:

import meshio
in_mesh = meshio.read("trans.msh")

out_mesh = meshio.Mesh(points=in_mesh.points, cells={"triangle": in_mesh.get_cells_type(
    "triangle")}, cell_data={"name_to_read": [in_mesh.cell_data_dict["gmsh:physical"]["triangle"]]})
meshio.write("triangle_mesh.xdmf", out_mesh)
embed()

out_mesh = meshio.Mesh(points=in_mesh.points, cells={"tetra": in_mesh.get_cells_type(
    "tetra")}, cell_data={"name_to_read": [in_mesh.cell_data_dict["gmsh:physical"]["tetra"]]})
meshio.write("tetra_mesh.xdmf", out_mesh)

We visually observe that the facet mesh (of triangles, right figure) does not match the tetrahedron mesh (left figure):


As I am not sure what @pliebersbach intended for each of the surfaces, it is hard for me to tell which of these meshes where intended, if any. To be of any further assistance we would need more information.

Thanks a lot @dokken. I had a look at my mesh, and indeed it faces the same problem you are describing. It seems that transfinite volumes have this inconsistency …

@XGC and anyone who might be interested.

The solution is to edit the “.geo” file in GMSH to create a mesh with 2D and 3D surfaces with the same orientation. Briefly…

  1. Create all transfinite surfaces and then the transfinite volume within the GMSH GUI or via the command line.
  2. Enable visibility for 2D element edges, 2D element faces, 3D element edges and 3D element faces. You probably will see the same facet mesh (of triangles) not matching the tetrahedron mesh as highlighted by @dokken earlier represented as a cross. This can be viewed by enabling and disabling 3D element edges and faces in GMSH (see images below)
  3. Locate the plane which 2D surface elements orientated the wrong direction to the 3D surface elements and edit said transfinite surface in “.geo” to orientated to the right (default is left if undefined). For example Transfinite Surface {3} Right;
  4. Reload the script and generate the mesh. This should have the 2D surface elements and 3D surface elements aligned correctly. Repeat this process for all surfaces with 2D surface elements orientated the wrong direction to the 3D surface elements.

Once all surface elements have been orientated correctly, you should be able to successfully use the structured GMSH mesh within Dolfin (once the GMSH mesh is converted with MeshIO to an “.XDMF” mesh as described above).

Hope this helps!



Example script for reference:

Merge "20mmDiaCurvedChannel.step";
//+
Transfinite Curve {2, 4, 5, 10} = 10 Using Progression 1;
//+
Transfinite Curve {1, 3, 8, 9} = 20 Using Progression 1;
//+
Transfinite Curve {6, 7, 11, 12} = 200 Using Progression 1;
//+
Transfinite Surface {1};
//+
//Transfinite Surface {2}; // Wrong Orientation
Transfinite Surface {2} Right;
//+
//Transfinite Surface {3}; // Wrong Orientation
Transfinite Surface {3} Right;
//+
Transfinite Surface {4};
//+
Transfinite Surface {5};
//+
Transfinite Surface {6};
//+
Transfinite Volume{1};
//+
Physical Surface("3", 13) = {3};
//+
Physical Surface("4", 14) = {4};
//+
Physical Surface("5", 15) = {5};
//+
Physical Surface("6", 16) = {6};
//+
Physical Surface("2", 17) = {2};
//+
Physical Surface("1", 18) = {1};
//+
Physical Volume("1", 19) = {1};
1 Like