netgen/libsrc/interface/writeelmer.cpp
2023-10-12 19:04:40 +02:00

203 lines
5.0 KiB
C++

//
// Write Elmer file
//
//
#include <mystdlib.h>
#include <myadt.hpp>
#include <linalg.hpp>
#include <csg.hpp>
#include <meshing.hpp>
#include <sys/stat.h>
#include "writeuser.hpp"
namespace netgen
{
extern MeshingParameters mparam;
void WriteElmerFormat (const Mesh &mesh,
const filesystem::path &dirname)
{
cout << "write elmer mesh files" << endl;
std::map<ELEMENT_TYPE, int> tmap;
tmap[TRIG] = 303;
tmap[TRIG6] = 306;
tmap[QUAD] = 404;
tmap[QUAD8] = 408;
tmap[TET] = 504;
tmap[TET10] = 510;
tmap[PYRAMID] = 605;
tmap[PYRAMID13] = 613;
tmap[PRISM] = 706;
tmap[PRISM15] = 715;
tmap[HEX] = 808;
tmap[HEX20] = 820;
std::map<int, Array<int,int>> pmap;
pmap[TRIG] = {1,2,3};
pmap[TRIG6] = {1,2,3, 6,4,5};
pmap[QUAD] = {1,2,3,4};
pmap[QUAD8] = {1,2,3,4, 5,8,6,7};
pmap[TET] = {1,2,3,4};
pmap[TET10] = {1,2,3,4, 5,8,6,7,9,10};
pmap[PYRAMID]={1,2,3,4,5};
pmap[PYRAMID13]= {1,2,3,4,5,6,7,8,9,10,11,12,13};
pmap[PRISM] = {1,2,3,4,5,6};
pmap[PRISM15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
pmap[HEX] = {1,2,3,4,5,6,7,8};
pmap[HEX20] = {1,2,3,4,5,8,6,7,8, 9,12,10,11, 17,20,19,18, 13,16,14,15};
int np = mesh.GetNP();
int ne = mesh.GetNE();
int nse = mesh.GetNSE();
int i, j;
// char str[200];
int inverttets = mparam.inverttets;
int invertsurf = mparam.inverttrigs;
filesystem::create_directories(dirname);
auto get_name = [&dirname]( string s ) {
return filesystem::path(dirname).append(s);
};
ofstream outfile_h(get_name("mesh.header"));
ofstream outfile_n(get_name("mesh.nodes"));
ofstream outfile_e(get_name("mesh.elements"));
ofstream outfile_b(get_name("mesh.boundary"));
ofstream outfile_names(get_name("mesh.names"));
for( auto codim : IntRange(0, mesh.GetDimension()-1) )
{
auto & names = const_cast<Mesh&>(mesh).GetRegionNamesCD(codim);
for (auto i0 : Range(names) )
{
if(names[i0] == nullptr)
continue;
string name = *names[i0];
if(name == "" || name == "default")
continue;
outfile_names << "$" << name << "=" << i0+1 << "\n";
}
}
auto get3FacePoints = [](const Element2d & el)
{
INDEX_3 i3;
INDEX_4 i4;
auto eltype = el.GetType();
switch (eltype)
{
case TRIG:
case TRIG6:
i3 = {el[0], el[1], el[2]};
i3.Sort();
break;
case QUAD:
case QUAD8:
i4 = {el[0], el[1], el[2], el[3]};
i4.Sort();
i3 = {i4[0], i4[1], i4[2]};
break;
default:
throw Exception("Got invalid type (no face)");
}
return i3;
};
// fill hashtable
// use lowest three point numbers of lowest-order face to index faces
INDEX_3_HASHTABLE<int> face2volelement(ne);
for (int i = 1; i <= ne; i++)
{
const Element & el = mesh.VolumeElement(i);
// getface not working for second order elements -> reconstruct linear element here
Element linear_el = el;
linear_el.SetNP(el.GetNV()); // GetNV returns 8 for HEX20 for instance
for (auto j : Range(1,el.GetNFaces()+1))
{
Element2d face;
linear_el.GetFace(j, face);
face2volelement.Set (get3FacePoints(face), i);
cout << "set " << get3FacePoints(face) << "\tto " << i << endl;
}
}
// outfile.precision(6);
// outfile.setf (ios::fixed, ios::floatfield);
// outfile.setf (ios::showpoint);
std::map<ELEMENT_TYPE, size_t> elcount;
for (i = 1; i <= np; i++)
{
const Point3d & p = mesh.Point(i);
outfile_n << i << " -1 ";
outfile_n << p.X() << " ";
outfile_n << p.Y() << " ";
outfile_n << p.Z() << "\n";
}
for (i = 1; i <= ne; i++)
{
Element el = mesh.VolumeElement(i);
if (inverttets) el.Invert();
auto eltype = el.GetType();
elcount[eltype]++;
outfile_e << i << " " << el.GetIndex() << " " << tmap[eltype] << " ";
auto & map = pmap[eltype];
for (j = 1; j <= el.GetNP(); j++)
{
outfile_e << " ";
outfile_e << el.PNum(map[j-1]);
}
outfile_e << "\n";
}
for (i = 1; i <= nse; i++)
{
Element2d el = mesh.SurfaceElement(i);
if (invertsurf) el.Invert();
auto eltype = el.GetType();
elcount[eltype]++;
int elind = face2volelement.Get(get3FacePoints(el));
cout << "get " << get3FacePoints(el) << "\t " << elind << endl;
outfile_b << i << " " << mesh.GetFaceDescriptor(el.GetIndex()).BCProperty() <<
" " << elind << " 0 " << tmap[eltype] << " ";
auto & map = pmap[el.GetType()];
for (j = 1; j <= el.GetNP(); j++)
{
outfile_b << " ";
outfile_b << el.PNum(map[j-1]);
}
outfile_b << "\n";
}
outfile_h << np << " " << ne << " " << nse << "\n";
outfile_h << "2" << "\n";
for( auto & [eltype,count] : elcount )
outfile_h << tmap[eltype] << " " << count << "\n";
}
static RegisterUserFormat reg_elmer ("Elmer Format", {"*"}, nullopt, WriteElmerFormat);
}