mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-26 22:00:33 +05:00
262 lines
7.5 KiB
C++
262 lines
7.5 KiB
C++
/*! \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 <mystdlib.h>
|
|
|
|
#include <myadt.hpp>
|
|
#include <linalg.hpp>
|
|
#include <csg.hpp>
|
|
#include <meshing.hpp>
|
|
|
|
namespace netgen
|
|
{
|
|
#include "writeuser.hpp"
|
|
|
|
// 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 CSGeometry & geom,
|
|
const string & filename)
|
|
{
|
|
ofstream outfile (filename.c_str());
|
|
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
|
|
|
|
|