Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/IO/MeshFactory.cpp
4 : : \copyright 2012-2015 J. Bakosi,
5 : : 2016-2018 Los Alamos National Security, LLC.,
6 : : 2019-2021 Triad National Security, LLC.,
7 : : 2022-2025 J. Bakosi
8 : : All rights reserved. See the LICENSE file for details.
9 : : \brief Unstructured mesh reader and writer factory
10 : : \details Unstructured mesh reader and writer factory.
11 : : */
12 : : // *****************************************************************************
13 : :
14 : : #include <string>
15 : :
16 : : #include "MeshFactory.hpp"
17 : : #include "MeshDetect.hpp"
18 : : #include "Timer.hpp"
19 : : #include "Reader.hpp"
20 : : #include "GmshMeshReader.hpp"
21 : : #include "NetgenMeshReader.hpp"
22 : : #include "ExodusIIMeshReader.hpp"
23 : : #include "UGRIDMeshReader.hpp"
24 : : #include "RDGFLOMeshReader.hpp"
25 : : #include "MeditMeshReader.hpp"
26 : : #include "ASCMeshReader.hpp"
27 : : #include "NetgenMeshWriter.hpp"
28 : : #include "GmshMeshWriter.hpp"
29 : : #include "ExodusIIMeshWriter.hpp"
30 : : #include "DerivedData.hpp"
31 : : #include "Reorder.hpp"
32 : : #include "XystBuildConfig.hpp"
33 : :
34 : : namespace tk {
35 : :
36 : : UnsMesh
37 : 48 : readUnsMesh( const tk::Print& print,
38 : : const std::string& filename,
39 : : std::pair< std::string, tk::real >& timestamp )
40 : : // *****************************************************************************
41 : : // Read unstructured mesh from file
42 : : //! \param[in] print Pretty printer
43 : : //! \param[in] filename Filename to read mesh from
44 : : //! \param[out] timestamp A time stamp consisting of a timer label (a string),
45 : : //! and a time state (a tk::real in seconds) measuring the mesh read time
46 : : //! \return Unstructured mesh object
47 : : // *****************************************************************************
48 : : {
49 [ + - ][ + - ]: 48 : print.diagstart( "Reading mesh from file '" + filename + "' ..." );
[ + - ]
50 : :
51 : : // Read in mesh
52 : 48 : tk::Timer t;
53 : :
54 : : //! Create unstructured mesh to store mesh
55 : 48 : UnsMesh mesh;
56 : :
57 [ + - ]: 48 : const auto meshtype = detectInput( filename );
58 : :
59 [ + + ]: 48 : if (meshtype == MeshReaderType::GMSH)
60 [ + - ][ + - ]: 5 : GmshMeshReader( filename ).readMesh( mesh );
61 [ + + ]: 43 : else if (meshtype == MeshReaderType::NETGEN)
62 [ + - ][ + - ]: 2 : NetgenMeshReader( filename ).readMesh( mesh );
63 [ + + ]: 41 : else if (meshtype == MeshReaderType::EXODUSII)
64 [ + - ][ + - ]: 33 : ExodusIIMeshReader( filename ).readMesh( mesh );
65 [ + + ]: 8 : else if (meshtype == MeshReaderType::ASC)
66 [ + - ][ + - ]: 4 : ASCMeshReader( filename ).readMesh( mesh );
67 [ + + ]: 4 : else if (meshtype == MeshReaderType::UGRID)
68 [ + - ][ + - ]: 1 : UGRIDMeshReader( filename ).readMesh( mesh );
69 [ + + ]: 3 : else if (meshtype == MeshReaderType::RDGFLO)
70 [ + - ][ + - ]: 1 : RDGFLOMeshReader( filename ).readMesh( mesh );
71 [ + - ]: 2 : else if (meshtype == MeshReaderType::MEDIT)
72 [ + - ][ + - ]: 2 : MeditMeshReader( filename ).readMesh( mesh );
73 : :
74 : : timestamp =
75 [ + - ][ + - ]: 48 : std::make_pair( "Read mesh from file '" + filename + '\'', t.dsec() );
[ + - ][ + - ]
76 : :
77 [ + - ][ + - ]: 48 : print.diagend( "done" );
78 : :
79 : : // Return (move out) mesh object
80 : 48 : return mesh;
81 : 0 : }
82 : :
83 : : std::vector< std::pair< std::string, tk::real > >
84 : 19 : writeUnsMesh( const tk::Print& print,
85 : : const std::string& filename,
86 : : UnsMesh& mesh,
87 : : bool reorder )
88 : : // *****************************************************************************
89 : : // Write unstructured mesh to file
90 : : //! \param[in] print Pretty printer
91 : : //! \param[in] filename Filename to write mesh to
92 : : //! \param[in] mesh Unstructured mesh object to write from
93 : : //! \param[in] reorder Whether to also reorder mesh nodes
94 : : //! \return Vector of time stamps consisting of a timer label (a string), and a
95 : : //! time state (a tk::real in seconds) measuring the renumber and the mesh
96 : : //! write time
97 : : // *****************************************************************************
98 : : {
99 : 19 : std::vector< std::pair< std::string, tk::real > > times;
100 : :
101 : 19 : tk::Timer t;
102 : :
103 : : // If mesh has tetrahedra but no triangles, generate triangle connectivity
104 [ + + ][ + + ]: 19 : if (!mesh.tetinpoel().empty() && mesh.triinpoel().empty()) {
[ + + ]
105 [ + - ][ + - ]: 5 : print.diagstart( "Generating missing surface mesh ..." );
106 : :
107 : 5 : const auto& inpoel = mesh.tetinpoel(); // get tet connectivity
108 [ + - ]: 5 : auto esup = tk::genEsup( inpoel, 4 ); // elements surrounding points
109 [ + - ]: 5 : auto esuel = tk::genEsuelTet( inpoel, esup ); // elems surrounding elements
110 : 5 : auto& triinpoel = mesh.triinpoel();
111 : : // collect boundary faces
112 [ + + ]: 424075 : for (std::size_t e=0; e<esuel.size()/4; ++e) {
113 : 424070 : auto mark = e*4;
114 [ + + ]: 2120350 : for (std::size_t f=0; f<4; ++f) {
115 [ + + ]: 1696280 : if (esuel[mark+f] == -1) {
116 : : // extract triangle element connectivity from tetrahedron
117 [ + - ]: 46000 : triinpoel.push_back( inpoel[ mark+tk::lpofa[f][0] ] );
118 [ + - ]: 46000 : triinpoel.push_back( inpoel[ mark+tk::lpofa[f][1] ] );
119 [ + - ]: 46000 : triinpoel.push_back( inpoel[ mark+tk::lpofa[f][2] ] );
120 : : }
121 : : }
122 : : }
123 : :
124 [ + - ][ + - ]: 5 : print.diagend( "done" );
125 [ + - ][ + - ]: 5 : times.emplace_back( "Generate surface mesh", t.dsec() );
126 : 5 : t.zero();
127 : 5 : }
128 : :
129 [ + + ]: 19 : if (reorder) {
130 [ + - ][ + - ]: 1 : print.diagstart( "Reordering mesh nodes ..." );
131 : :
132 : : // If mesh has tetrahedra elements, reorder based on those
133 [ + - ]: 1 : if (!mesh.tetinpoel().empty()) {
134 : :
135 : 1 : auto& inpoel = mesh.tetinpoel();
136 [ + - ][ + - ]: 1 : const auto psup = tk::genPsup( inpoel, 4, tk::genEsup( inpoel, 4 ) );
137 [ + - ]: 1 : auto map = tk::renumber( psup );
138 [ + - ]: 1 : tk::remap( inpoel, map );
139 [ + - ]: 1 : tk::remap( mesh.triinpoel(), map );
140 [ + - ]: 1 : tk::remap( mesh.x(), map );
141 [ + - ]: 1 : tk::remap( mesh.y(), map );
142 [ + - ]: 1 : tk::remap( mesh.z(), map );
143 : :
144 : : // If mesh has no tetrahedra elements, reorder based on triangle mesh if any
145 [ - - ][ - - ]: 1 : } else Throw( "No tetrahedra in input mesh" );
[ - - ]
146 : :
147 [ + - ][ + - ]: 1 : print.diagend( "done" );
148 [ + - ][ + - ]: 1 : times.emplace_back( "Reorder mesh", t.dsec() );
149 : 1 : t.zero();
150 : : }
151 : :
152 [ + - ][ + - ]: 19 : print.diagstart( "Writing mesh to file '" + filename + "' ..." );
[ + - ]
153 : :
154 [ + - ]: 19 : const auto meshtype = pickOutput( filename );
155 : :
156 [ + + ]: 19 : if (meshtype == MeshWriterType::GMSH)
157 [ + - ][ + - ]: 4 : GmshMeshWriter( filename ).writeMesh( mesh );
158 [ + + ]: 15 : else if (meshtype == MeshWriterType::NETGEN)
159 [ + - ][ + - ]: 4 : NetgenMeshWriter( filename ).writeMesh( mesh );
160 [ + - ]: 11 : else if (meshtype== MeshWriterType::EXODUSII)
161 [ + - ][ + - ]: 11 : ExodusIIMeshWriter( filename, ExoWriter::CREATE ).writeMesh( mesh );
162 : :
163 [ + - ][ + - ]: 19 : print.diagend( "done" );
164 [ + - ][ + - ]: 19 : times.emplace_back( "Write mesh to file", t.dsec() );
165 : :
166 : 19 : return times;
167 : 0 : }
168 : :
169 : : } // tk::
|