diff --git a/doc/element_types.tex b/doc/element_types.tex new file mode 100644 index 00000000..7f05fec2 --- /dev/null +++ b/doc/element_types.tex @@ -0,0 +1,282 @@ +\documentclass[convert=pdf2svg]{standalone} +% \documentclass{article} + +\usepackage[T1]{fontenc} +\usepackage{lmodern} +\renewcommand{\familydefault}{\sfdefault} +\usepackage{tikz} +\usepackage{tikz-3dplot} +\usetikzlibrary{external} +\tikzset{external/force remake} +\tikzset{external/disable dependency files} +\tikzset{external/aux in dpth={false}} +% uncomment this to generate a figure for each cell type (and change documentclass to article) +% \tikzexternalize + +\tikzstyle{vertex} = [circle,draw=black,fill=black,scale = 0.5] +\tdplotsetmaincoords{70}{110} + +% cnode(tag,x,y,z,label,label_pos) +\def\cnode(#1,#2,#3,#4,#5,#6){ +\node (#1) at (#2,#3,#4) [vertex,label=#6:$\mathsf{#5}$] {}; +} + +\pagestyle{empty} + +\begin{document} + +\begin{tabular}{cc} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SEGMENT & +SEGMENT3 +\\ +\tikzsetnextfilename{line} +\begin{tikzpicture}[scale = 2] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,2,below right); +\draw (n0) -- (n1); +\end{tikzpicture} +& +\tikzsetnextfilename{line3} +\begin{tikzpicture}[scale = 2] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,2,below right); +\cnode(n2,1,0,0,3,below right); +\draw (n0) -- (n2) -- (n1); +\end{tikzpicture} +\\[1 em] + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +TRIG & +TRIG6 +\\ +\tikzsetnextfilename{triangle} +\begin{tikzpicture}[scale = 2] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,2,below right); +\cnode(n2,0,2,0,3,right); +\draw (n0) -- (n1) -- (n2) -- (n0); +\end{tikzpicture} +& +\tikzsetnextfilename{triangle6} +\begin{tikzpicture}[scale = 2] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,2,below right); +\cnode(n2,0,2,0,3,right); +\cnode(n3,1,0,0,6,below right); +\cnode(n4,1,1,0,4,right); +\cnode(n5,0,1,0,5,below right); +\draw (n0) -- (n3) -- (n1) -- (n4) -- (n2) -- (n5) -- (n0); +\end{tikzpicture} +\\[1 em] + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +QUAD & +QUAD8 +\\ +\tikzsetnextfilename{quad} +\begin{tikzpicture}[scale = 2] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,2,below right); +\cnode(n2,2,2,0,3,below right); +\cnode(n3,0,2,0,4,below right); +\draw (n0) -- (n1) -- (n2) -- (n3) -- (n0); +\end{tikzpicture} +& +\tikzsetnextfilename{quad8} +\begin{tikzpicture}[scale = 2] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,2,below right); +\cnode(n2,2,2,0,3,below right); +\cnode(n3,0,2,0,4,below right); +\cnode(n4,1,0,0,5,below right); +\cnode(n5,2,1,0,8,below right); +\cnode(n6,1,2,0,6,below right); +\cnode(n7,0,1,0,7,below right); +\draw (n0) -- (n4) -- (n1) -- (n5) -- (n2) -- (n6) -- (n3) -- (n7) -- (n0); +\end{tikzpicture} +\\[1 em] + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +TET & +TET10 +\\ +\tikzsetnextfilename{tetra} +\begin{tikzpicture}[scale = 2, tdplot_main_coords] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,3,below right); +\cnode(n2,0,2,0,2,below right); +\cnode(n3,0,0,2,4,right); +\draw (n0) -- (n1) -- (n2) -- (n0); +\draw (n0) -- (n3); +\draw (n1) -- (n3); +\draw (n2) -- (n3); +\end{tikzpicture} +& +\tikzsetnextfilename{tetra10} % VTK +\begin{tikzpicture}[scale = 2, tdplot_main_coords] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,3,below right); +\cnode(n2,0,2,0,2,below right); +\cnode(n3,0,0,2,4,right); +\cnode(n4,1,0,0,6,below right); +\cnode(n5,1,1,0,8,below right); +\cnode(n6,0,1,0,5,below right); +\cnode(n7,0,0,1,7,below right); +\cnode(n8,1,0,1,10,below right); +\cnode(n9,0,1,1,9,right); +\draw (n0) -- (n4) -- (n1) -- (n5) -- (n2) -- (n6) -- (n0); +\draw (n0) -- (n7) -- (n3); +\draw (n1) -- (n8) -- (n3); +\draw (n2) -- (n9) -- (n3); +\end{tikzpicture} +\\[1 em] + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +PYRAMID & +PYRAMID13 +\\ +\tikzsetnextfilename{pyramid} +\begin{tikzpicture}[scale = 2, tdplot_main_coords] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,4,below right); +\cnode(n2,2,2,0,3,below right); +\cnode(n3,0,2,0,2,below right); +\cnode(n4,1,1,2,5,right); +\draw (n0) -- (n1) -- (n2) -- (n3) -- (n0); +\draw (n0) -- (n4); +\draw (n1) -- (n4); +\draw (n2) -- (n4); +\draw (n3) -- (n4); +\end{tikzpicture} +& +\tikzsetnextfilename{pyramid13} % VTK != gmsh +\begin{tikzpicture}[scale = 2, tdplot_main_coords] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,4,below right); +\cnode(n2,2,2,0,3,below right); +\cnode(n3,0,2,0,2,below right); +\cnode(n4,1,1,2,5,right); +\cnode(n5,1,0,0,8,below right); +\cnode(n6,2,1,0,7,below right); +\cnode(n7,1,2,0,9,below right); +\cnode(n8,0,1,0,6,below right); +\cnode(n9,0.5,0.5,1,10,below right); +\cnode(n10,1.5,0.5,1,13,below right); +\cnode(n11,1.5,1.5,1,12,below right); +\cnode(n12,0.5,1.5,1,11,right); +\draw (n0) -- (n5) -- (n1) -- (n6) -- (n2) -- (n7) -- (n3) -- (n8) -- (n0); +\draw (n0) -- (n9) -- (n4); +\draw (n1) -- (n10) -- (n4); +\draw (n2) -- (n11) -- (n4); +\draw (n3) -- (n12) -- (n4); +\end{tikzpicture} +\\[1 em] + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +PRISM & +PRISM15 +\\ +\tikzsetnextfilename{wedge} % gmsh != VTK +\begin{tikzpicture}[scale = 2, tdplot_main_coords] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,3,below right); +\cnode(n2,0,2,0,2,below right); +\cnode(n3,0,0,2,4,below right); +\cnode(n4,2,0,2,6,below right); +\cnode(n5,0,2,2,5,below right); +\draw (n0) -- (n1) -- (n2) -- (n0); +\draw (n3) -- (n4) -- (n5) -- (n3); +\draw (n0) -- (n3); +\draw (n1) -- (n4); +\draw (n2) -- (n5); +\end{tikzpicture} +& +\tikzsetnextfilename{wedge15} % VTK != gmsh +\begin{tikzpicture}[scale = 2, tdplot_main_coords] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,3,below right); +\cnode(n2,0,2,0,2,below right); +\cnode(n3,0,0,2,4,below right); +\cnode(n4,2,0,2,6,below right); +\cnode(n5,0,2,2,5,below right); +\cnode(n6,1,0,0,8,below right); +\cnode(n7,1,1,0,9,below right); +\cnode(n8,0,1,0,7,below right); +\cnode(n9,1,0,2,14,below right); +\cnode(n10,1,1,2,15,below right); +\cnode(n11,0,1,2,13,below right); +\cnode(n12,0,0,1,10,below right); +\cnode(n13,2,0,1,12,below right); +\cnode(n14,0,2,1,11,below right); +\draw (n0) -- (n6) -- (n1) -- (n7) -- (n2) -- (n8) -- (n0); +\draw (n3) -- (n9) -- (n4) -- (n10) -- (n5) -- (n11) -- (n3); +\draw (n0) -- (n12) -- (n3); +\draw (n1) -- (n13) -- (n4); +\draw (n2) -- (n14) -- (n5); +\end{tikzpicture} +\\[1 em] + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +HEX & +HEX20 +\\ +\tikzsetnextfilename{hexahedron} +\begin{tikzpicture}[scale = 2, tdplot_main_coords] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,4,below right); +\cnode(n2,2,2,0,3,below right); +\cnode(n3,0,2,0,2,below right); +\cnode(n4,0,0,2,5,below right); +\cnode(n5,2,0,2,8,below right); +\cnode(n6,2,2,2,7,below right); +\cnode(n7,0,2,2,6,below right); +\draw (n0) -- (n1) -- (n2) -- (n3) -- (n0); +\draw (n4) -- (n5) -- (n6) -- (n7) -- (n4); +\draw (n0) -- (n4); +\draw (n1) -- (n5); +\draw (n2) -- (n6); +\draw (n3) -- (n7); +\end{tikzpicture} +& +\tikzsetnextfilename{hexahedron20} % VTK != gmsh +\begin{tikzpicture}[scale = 2, tdplot_main_coords] +\cnode(n0,0,0,0,1,below right); +\cnode(n1,2,0,0,4,below right); +\cnode(n2,2,2,0,3,below right); +\cnode(n3,0,2,0,2,below right); +\cnode(n4,0,0,2,5,below right); +\cnode(n5,2,0,2,8,below right); +\cnode(n6,2,2,2,7,below right); +\cnode(n7,0,2,2,6,below right); +\cnode(n8,1,0,0,11,below right); +\cnode(n9,2,1,0,10,below right); +\cnode(n10,1,2,0,12,below right); +\cnode(n11,0,1,0,9,below right); +\cnode(n12,1,0,2,15,below right); +\cnode(n13,2,1,2,14,below right); +\cnode(n14,1,2,2,16,below right); +\cnode(n15,0,1,2,13,below right); +\cnode(n16,0,0,1,17,below right); +\cnode(n17,2,0,1,20,below right); +\cnode(n18,2,2,1,19,below right); +\cnode(n19,0,2,1,18,below right); +\draw (n0) -- (n8) -- (n1) -- (n9) -- (n2) -- (n10) -- (n3) -- (n11) -- (n0); +\draw (n4) -- (n12) -- (n5) -- (n13) -- (n6) -- (n14) -- (n7) -- (n15) -- (n4); +\draw (n0) -- (n16) -- (n4); +\draw (n1) -- (n17) -- (n5); +\draw (n2) -- (n18) -- (n6); +\draw (n3) -- (n19) -- (n7); +\end{tikzpicture} + + + +\end{tabular} + +\end{document} diff --git a/libsrc/interface/writeelmer.cpp b/libsrc/interface/writeelmer.cpp index 805d3dca..d0dc2a7d 100644 --- a/libsrc/interface/writeelmer.cpp +++ b/libsrc/interface/writeelmer.cpp @@ -24,6 +24,35 @@ void WriteElmerFormat (const Mesh &mesh, const string &filename) { cout << "write elmer mesh files" << endl; + + std::map 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> 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(); @@ -50,27 +79,67 @@ void WriteElmerFormat (const Mesh &mesh, ofstream outfile_e(str); sprintf( str, "%s/mesh.boundary", filename.c_str() ); ofstream outfile_b(str); + sprintf( str, "%s/mesh.names", filename.c_str() ); + ofstream outfile_names(str); + + for( auto codim : IntRange(0, mesh.GetDimension()-1) ) + { + auto & names = const_cast(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 face2volelement(ne); - for (i = 1; i <= ne; i++) + for (int i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); - INDEX_3 i3; - int k, l; - for (j = 1; j <= 4; j++) // loop over faces of tet + + // 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)) { - l = 0; - for (k = 1; k <= 4; k++) - if (k != j) - { - l++; - i3.I(l) = el.PNum(k); - } - i3.Sort(); - face2volelement.Set (i3, i); + Element2d face; + linear_el.GetFace(j, face); + face2volelement.Set (get3FacePoints(face), i); + cout << "set " << get3FacePoints(face) << "\tto " << i << endl; } } @@ -78,10 +147,7 @@ void WriteElmerFormat (const Mesh &mesh, // outfile.setf (ios::fixed, ios::floatfield); // outfile.setf (ios::showpoint); - outfile_h << np << " " << ne << " " << nse << "\n"; - outfile_h << "2" << "\n"; - outfile_h << "303 " << nse << "\n"; - outfile_h << "504 " << ne << "\n"; + std::map elcount; for (i = 1; i <= np; i++) { @@ -97,12 +163,15 @@ void WriteElmerFormat (const Mesh &mesh, { Element el = mesh.VolumeElement(i); if (inverttets) el.Invert(); - sprintf( str, "5%02d", (int)el.GetNP() ); - outfile_e << i << " " << el.GetIndex() << " " << str << " "; + 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(j); + outfile_e << el.PNum(map[j-1]); } outfile_e << "\n"; } @@ -111,23 +180,29 @@ void WriteElmerFormat (const Mesh &mesh, { Element2d el = mesh.SurfaceElement(i); if (invertsurf) el.Invert(); - sprintf( str, "3%02d", (int)el.GetNP() ); - { - INDEX_3 i3; - for (j = 1; j <= 3; j++) i3.I(j) = el.PNum(j); - i3.Sort(); - - int elind = face2volelement.Get(i3); - outfile_b << i << " " << mesh.GetFaceDescriptor(el.GetIndex()).BCProperty() << - " " << elind << " 0 " << str << " "; - } + 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(j); + 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"; } }