/*! \file writegmsh2.cpp * \brief Export Netgen Mesh in the GMSH v2.xx File format * \author Philippose Rajan * \date 02 November 2008 * * This function extends the export capabilities of * Netgen to include the GMSH v2.xx File Format. * * Current features of this function include: * * 1. Exports Triangles, Quadrangles and Tetrahedra \n * 2. Supports upto second order elements of each type * */ #include #include #include #include #include namespace netgen { #include "writeuser.hpp" extern MeshingParameters mparam; // Mapping of entities from Netgen definitions to GMSH definitions enum GMSH_ELEMENTS {GMSH_TRIG = 2, GMSH_TRIG6 = 9, GMSH_QUAD = 3, GMSH_QUAD8 = 16, GMSH_TET = 4, GMSH_TET10 = 11}; const int triGmsh[7] = {0,1,2,3,6,4,5}; const int quadGmsh[9] = {0,1,2,3,4,5,8,6,7}; const int tetGmsh[11] = {0,1,2,3,4,5,8,6,7,10,9}; /*! GMSH v2.xx mesh format export function * * This function extends the export capabilities of * Netgen to include the GMSH v2.xx File Format. * * Current features of this function include: * * 1. Exports Triangles, Quadrangles and Tetrahedra \n * 2. Supports upto second order elements of each type * */ void WriteGmsh2Format (const Mesh & mesh, const NetgenGeometry & geom, const filesystem::path & filename) { ofstream outfile (filename); outfile.precision(6); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); int np = mesh.GetNP(); /// number of points in mesh int ne = mesh.GetNE(); /// number of 3D elements in mesh int nse = mesh.GetNSE(); /// number of surface elements (BC) int i, j, k, l; /* * 3D section : Volume elements (currently only tetrahedra) */ if ((ne > 0) && (mesh.VolumeElement(1).GetNP() <= 10) && (mesh.SurfaceElement(1).GetNP() <= 6)) { cout << "Write GMSH v2.xx Format \n"; cout << "The GMSH v2.xx export is currently available for elements upto 2nd Order\n" << endl; int inverttets = mparam.inverttets; int invertsurf = mparam.inverttrigs; /// Prepare GMSH 2.0 file (See GMSH 2.0 Documentation) outfile << "$MeshFormat\n"; outfile << (float)2.0 << " " << (int)0 << " " << (int)sizeof(double) << "\n"; outfile << "$EndMeshFormat\n"; /// Write nodes outfile << "$Nodes\n"; outfile << np << "\n"; for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile << i << " "; /// node number outfile << p.X() << " "; outfile << p.Y() << " "; outfile << p.Z() << "\n"; } outfile << "$EndNodes\n"; /// write elements (both, surface elements and volume elements) outfile << "$Elements\n"; outfile << ne + nse << "\n"; //// number of elements + number of surfaces BC for (i = 1; i <= nse; i++) { int elType = 0; Element2d el = mesh.SurfaceElement(i); if(invertsurf) el.Invert(); if(el.GetNP() == 3) elType = GMSH_TRIG; //// GMSH Type for a 3 node triangle if(el.GetNP() == 6) elType = GMSH_TRIG6; //// GMSH Type for a 6 node triangle if(elType == 0) { cout << " Invalid surface element type for Gmsh 2.0 3D-Mesh Export Format !\n"; return; } outfile << i; outfile << " "; outfile << elType; outfile << " "; outfile << "2"; //// Number of tags (2 => Physical and elementary entities) outfile << " "; outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; /// that means that physical entity = elementary entity (arbitrary approach) outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; for (j = 1; j <= el.GetNP(); j++) { outfile << " "; outfile << el.PNum(triGmsh[j]); } outfile << "\n"; } for (i = 1; i <= ne; i++) { int elType = 0; Element el = mesh.VolumeElement(i); if (inverttets) el.Invert(); if(el.GetNP() == 4) elType = GMSH_TET; //// GMSH Element type for 4 node tetrahedron if(el.GetNP() == 10) elType = GMSH_TET10; //// GMSH Element type for 10 node tetrahedron if(elType == 0) { cout << " Invalid volume element type for Gmsh 2.0 3D-Mesh Export Format !\n"; return; } outfile << nse + i; //// element number (Remember to add on surface elements) outfile << " "; outfile << elType; outfile << " "; outfile << "2"; //// Number of tags (2 => Physical and elementary entities) outfile << " "; outfile << 100000 + el.GetIndex(); /// that means that physical entity = elementary entity (arbitrary approach) outfile << " "; outfile << 100000 + el.GetIndex(); /// volume number outfile << " "; for (j = 1; j <= el.GetNP(); j++) { outfile << " "; outfile << el.PNum(tetGmsh[j]); } outfile << "\n"; } outfile << "$EndElements\n"; } /* * End of 3D section */ /* * 2D section : available for triangles and quadrangles * upto 2nd Order */ else if(ne == 0) /// means that there's no 3D element { cout << "\n Write Gmsh v2.xx Surface Mesh (triangle and/or quadrangles upto 2nd Order)" << endl; /// Prepare GMSH 2.0 file (See GMSH 2.0 Documentation) outfile << "$MeshFormat\n"; outfile << (float)2.0 << " " << (int)0 << " " << (int)sizeof(double) << "\n"; outfile << "$EndMeshFormat\n"; /// Write nodes outfile << "$Nodes\n"; outfile << np << "\n"; for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile << i << " "; /// node number outfile << p.X() << " "; outfile << p.Y() << " "; outfile << p.Z() << "\n"; } outfile << "$EndNodes\n"; /// write triangles & quadrangles outfile << "$Elements\n"; outfile << nse << "\n"; for (k = 1; k <= nse; k++) { int elType = 0; const Element2d & el = mesh.SurfaceElement(k); if(el.GetNP() == 3) elType = GMSH_TRIG; //// GMSH Type for a 3 node triangle if(el.GetNP() == 6) elType = GMSH_TRIG6; //// GMSH Type for a 6 node triangle if(el.GetNP() == 4) elType = GMSH_QUAD; //// GMSH Type for a 4 node quadrangle if(el.GetNP() == 8) elType = GMSH_QUAD8; //// GMSH Type for an 8 node quadrangle if(elType == 0) { cout << " Invalid surface element type for Gmsh 2.0 2D-Mesh Export Format !\n"; return; } outfile << k; outfile << " "; outfile << elType; outfile << " "; outfile << "2"; outfile << " "; outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; /// that means that physical entity = elementary entity (arbitrary approach) outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; for (l = 1; l <= el.GetNP(); l++) { outfile << " "; if((elType == GMSH_TRIG) || (elType == GMSH_TRIG6)) { outfile << el.PNum(triGmsh[l]); } else if((elType == GMSH_QUAD) || (elType == GMSH_QUAD8)) { outfile << el.PNum(quadGmsh[l]); } } outfile << "\n"; } outfile << "$EndElements\n"; } /* * End of 2D section */ else { cout << " Invalid element type for Gmsh v2.xx Export Format !\n"; } } // End: WriteGmsh2Format } // End: namespace netgen