Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/IO/ExodusIIMeshReader.hpp
4 : : \copyright 2012-2015 J. Bakosi,
5 : : 2016-2018 Los Alamos National Security, LLC.,
6 : : 2019-2021 Triad National Security, LLC.
7 : : All rights reserved. See the LICENSE file for details.
8 : : \brief ExodusII mesh reader
9 : : \details ExodusII mesh reader class declaration.
10 : : */
11 : : // *****************************************************************************
12 : : #ifndef ExodusIIMeshReader_h
13 : : #define ExodusIIMeshReader_h
14 : :
15 : : #include <cstddef>
16 : : #include <iosfwd>
17 : : #include <vector>
18 : : #include <array>
19 : : #include <map>
20 : : #include <unordered_map>
21 : :
22 : : #include "NoWarning/exodusII.hpp"
23 : :
24 : : #include "Types.hpp"
25 : : #include "Exception.hpp"
26 : : #include "UnsMesh.hpp"
27 : :
28 : : namespace tk {
29 : :
30 : : //! Supported ExodusII mesh cell types
31 : : //! \see ExodusIIMeshReader::readElemBlockIDs()
32 : : enum class ExoElemType : int { TET = 0, TRI = 1 };
33 : :
34 : : //! ExodusII mesh cell number of nodes
35 : : //! \details List of number of nodes per element for different element types
36 : : //! supported in the order of tk::ExoElemType
37 : : const std::array< std::size_t, 2 > ExoNnpe {{ 4, 3 }};
38 : :
39 : : //! ExodusII face-node numbering for tetrahedron side sets
40 : : //! \see ExodusII manual figure on "Sideset side Numbering"
41 : : const std::array< std::array< std::size_t, 3 >, 4 >
42 : : expofa{{ {{0,1,3}}, {{1,2,3}}, {{0,3,2}}, {{0,2,1}} }};
43 : :
44 : : //! ExodusII mesh-based data reader
45 : : //! \details Mesh reader class facilitating reading from mesh-based field data
46 : : //! a file in ExodusII format.
47 : : //! \see https://github.com/trilinos/Trilinos/tree/master/packages/seacas
48 : : class ExodusIIMeshReader {
49 : :
50 : : public:
51 : : //! Constructor
52 : : explicit ExodusIIMeshReader( const std::string& filename,
53 : : int cpuwordsize = sizeof(double),
54 : : int iowordsize = sizeof(double) );
55 : :
56 : : //! Destructor
57 : : ~ExodusIIMeshReader() noexcept;
58 : :
59 : : //! Read ExodusII mesh from file
60 : : void readMesh( UnsMesh& mesh );
61 : :
62 : : //! Read only connectivity graph from file
63 : : void readGraph( UnsMesh& mesh );
64 : :
65 : : //! Return total number of mesh points in mesh file
66 : 189 : std::size_t npoin() { return readHeader(); }
67 : :
68 : : //! Read part of the mesh (graph and coords) from file
69 : : //! \details Total number of PEs defaults to 1 for a single-CPU read, this
70 : : //! PE defaults to 0 for a single-CPU read.
71 : : void readMeshPart( std::vector< std::size_t >& ginpoel,
72 : : std::vector< std::size_t >& inpoel,
73 : : std::vector< std::size_t >& triinp,
74 : : std::unordered_map< std::size_t, std::size_t >& lid,
75 : : tk::UnsMesh::Coords& coord,
76 : : std::unordered_map< std::size_t, std::set< std::size_t > >&
77 : : elemBlockId,
78 : : int numpes=1, int mype=0 );
79 : :
80 : : //! Read coordinates of a number of mesh nodes from ExodusII file
81 : : std::array< std::vector< tk::real >, 3 >
82 : : readCoords( const std::vector< std::size_t >& gid ) const;
83 : :
84 : : //! Read face list of all side sets from ExodusII file
85 : : void
86 : : readSidesetFaces( std::map< int, std::vector< std::size_t > >& bface,
87 : : std::map< int, std::vector< std::size_t > >& faces );
88 : :
89 : : //! Read face connectivity of a number boundary faces from file
90 : : void readFaces( std::vector< std::size_t >& conn );
91 : :
92 : : //! Read node list of all side sets from ExodusII file
93 : : std::map< int, std::vector< std::size_t > > readSidesetNodes();
94 : :
95 : : //! Read coordinates of a single mesh node from ExodusII file
96 : : void readNode( std::size_t fid,
97 : : std::size_t mid,
98 : : std::vector< tk::real >& x,
99 : : std::vector< tk::real >& y,
100 : : std::vector< tk::real >& z ) const;
101 : :
102 : : //! Read coordinates of a single mesh node from ExodusII file
103 : : void readNode( std::size_t id, std::array< tk::real, 3 >& coord ) const;
104 : :
105 : : //! Read coordinates of a number of mesh nodes from ExodusII file
106 : : std::array< std::vector< tk::real >, 3 >
107 : : readNodes( const std::vector< std::size_t >& gid ) const;
108 : :
109 : : //! Read element block IDs from file
110 : : std::size_t readElemBlockIDs();
111 : :
112 : : //! Read element connectivity of a number of mesh cells from file
113 : : void readElements( const std::array< std::size_t, 2 >& ext,
114 : : tk::ExoElemType elemtype,
115 : : std::vector< std::size_t >& conn );
116 : :
117 : : //! Read local to global node-ID map
118 : : std::vector< std::size_t > readNodemap();
119 : :
120 : : //! Generate triangle face connectivity for side sets
121 : : std::vector< std::size_t > triinpoel(
122 : : std::map< int, std::vector< std::size_t > >& belem,
123 : : const std::map< int, std::vector< std::size_t > >& faces,
124 : : const std::vector< std::size_t >& ginpoel,
125 : : const std::vector< std::size_t >& triinp ) const;
126 : :
127 : : //! Read the names of nodal output variables from ExodusII file
128 : : void readNodeVarNames( std::vector< std::string >& nv ) const;
129 : :
130 : : //! Read the names of elemental output variables from ExodusII file
131 : : void readElemVarNames( std::vector< std::string >& ev ) const;
132 : :
133 : : //! Read time values from ExodusII file
134 : : void readTimeValues( std::vector< tk::real >& tv ) const;
135 : :
136 : : //! Read node scalar fields from ExodusII file
137 : : void readNodeScalars(
138 : : std::size_t ntime,
139 : : std::size_t nvar,
140 : : std::vector< std::vector< std::vector< tk::real > > >& var ) const;
141 : :
142 : : //! Read element scalar fields from ExodusII file
143 : : void readElemScalars(
144 : : std::size_t ntime,
145 : : std::size_t nvar,
146 : : std::vector< std::vector< std::vector< tk::real > > >& var ) const;
147 : :
148 : : //! Return number of elements in a mesh block in the ExodusII file
149 : : std::size_t nelem( tk::ExoElemType elemtype ) const;
150 : :
151 : : //! Copy assignment
152 : : // cppcheck-suppress operatorEqVarError
153 : : // cppcheck-suppress operatorEqMissingReturnStatement
154 : 10 : ExodusIIMeshReader& operator=( const ExodusIIMeshReader& x ) {
155 [ + - ]: 10 : m_filename = x.m_filename;
156 : 10 : m_cpuwordsize = x.m_cpuwordsize;
157 : 10 : m_iowordsize = x.m_iowordsize;
158 : : float version;
159 [ + - ]: 10 : m_inFile = ex_open( m_filename.c_str(), EX_READ, &m_cpuwordsize,
160 : : &m_iowordsize, &version );
161 [ - + ][ - - ]: 10 : ErrChk( m_inFile > 0, "Failed to open ExodusII file: " + m_filename );
[ - - ][ - - ]
162 : 10 : m_nnode = x.m_nnode;
163 : 10 : m_nelem = x.m_nelem;
164 : 10 : m_neblk = x.m_neblk;
165 : 10 : m_neset = x.m_neset;
166 : 10 : m_from = x.m_from;
167 : 10 : m_till = x.m_till;
168 [ + - ]: 10 : m_blockid = x.m_blockid;
169 [ + - ]: 10 : m_blockid_by_type = x.m_blockid_by_type;
170 [ + - ]: 10 : m_nel = x.m_nel;
171 [ + - ]: 10 : m_elemblocks = x.m_elemblocks;
172 [ + - ]: 10 : m_tri = x.m_tri;
173 [ + - ]: 10 : m_elemInBlockId = x.m_elemInBlockId;
174 : 10 : return *this;
175 : : }
176 : :
177 : : //! Copy constructor: in terms of copy assignment
178 : : // cppcheck-suppress uninitMemberVar
179 [ + - ]: 10 : ExodusIIMeshReader( const ExodusIIMeshReader& x ) { operator=(x); }
180 : :
181 : : //! Move assignment
182 : : // cppcheck-suppress operatorEqMissingReturnStatement
183 : : // cppcheck-suppress operatorEqVarError
184 : 1546 : ExodusIIMeshReader& operator=( ExodusIIMeshReader&& x ) {
185 [ + - ]: 1546 : m_filename = x.m_filename;
186 : 1546 : m_cpuwordsize = x.m_cpuwordsize;
187 : 1546 : m_iowordsize = x.m_iowordsize;
188 : : float version;
189 [ + - ]: 1546 : m_inFile = ex_open( m_filename.c_str(), EX_READ, &m_cpuwordsize,
190 : : &m_iowordsize, &version );
191 [ - + ][ - - ]: 1546 : ErrChk( m_inFile > 0, "Failed to open ExodusII file: " + m_filename );
[ - - ][ - - ]
192 : 1546 : m_nnode = x.m_nnode;
193 : 1546 : m_nelem = x.m_nelem;
194 : 1546 : m_neblk = x.m_neblk;
195 : 1546 : m_neset = x.m_neset;
196 : 1546 : m_from = x.m_from;
197 : 1546 : m_till = x.m_till;
198 [ + - ]: 1546 : m_blockid = x.m_blockid;
199 [ + - ]: 1546 : m_blockid_by_type = x.m_blockid_by_type;
200 [ + - ]: 1546 : m_nel = x.m_nel;
201 [ + - ]: 1546 : m_elemblocks = x.m_elemblocks;
202 [ + - ]: 1546 : m_tri = x.m_tri;
203 [ + - ]: 1546 : m_elemInBlockId = x.m_elemInBlockId;
204 : 1546 : x.m_cpuwordsize = sizeof(double);
205 : 1546 : x.m_iowordsize = sizeof(double);
206 [ + - ]: 1546 : x.m_inFile = ex_open( m_filename.c_str(), EX_READ, &x.m_cpuwordsize,
207 : : &x.m_iowordsize, &version );
208 [ - + ][ - - ]: 1546 : ErrChk( x.m_inFile > 0, "Failed to open ExodusII file: " + m_filename );
[ - - ][ - - ]
209 : 1546 : x.m_nnode = 0;
210 : 1546 : x.m_nelem = 0;
211 : 1546 : x.m_neblk = 0;
212 : 1546 : x.m_neset = 0;
213 : 1546 : x.m_from = 0;
214 : 1546 : x.m_till = 0;
215 : 1546 : x.m_blockid.clear();
216 [ + - ]: 1546 : x.m_blockid_by_type.resize( ExoNnpe.size() );
217 [ + - ]: 1546 : x.m_nel.resize( ExoNnpe.size() );
218 : 1546 : x.m_elemblocks.clear();
219 : 1546 : x.m_tri.clear();
220 : 1546 : x.m_elemInBlockId.clear();
221 : 1546 : return *this;
222 : : }
223 : :
224 : : //! Move constructor: in terms of move assignment
225 : 1546 : ExodusIIMeshReader( ExodusIIMeshReader&& x ) :
226 : : m_filename(),
227 : : m_cpuwordsize( 0 ),
228 : : m_iowordsize( 0 ),
229 : : m_inFile( 0 ),
230 : : m_nnode( 0 ),
231 : : m_nelem( 0 ),
232 : : m_neblk( 0 ),
233 : : m_neset( 0 ),
234 : : m_from( 0 ),
235 : : m_till( 0 ),
236 : : m_blockid(),
237 : : m_blockid_by_type(),
238 : : m_nel(),
239 : : m_elemblocks(),
240 : : m_tri(),
241 : 1546 : m_elemInBlockId()
242 [ + - ]: 1546 : { *this = std::move(x); }
243 : :
244 : : private:
245 : : std::string m_filename; //!< Input file name
246 : : int m_cpuwordsize; //!< CPU word size for ExodusII
247 : : int m_iowordsize; //!< I/O word size for ExodusII
248 : : int m_inFile; //!< ExodusII file handle
249 : : std::size_t m_nnode; //!< Number of nodes in file
250 : : std::size_t m_nelem; //!< Number of elements in file
251 : : std::size_t m_neblk; //!< Number of element blocks in file
252 : : std::size_t m_neset; //!< Number of element sets in file
253 : : std::size_t m_from; //!< Lower bound of tet ids on this PE
254 : : std::size_t m_till; //!< Upper bound of tet ids on this PE
255 : : //! Element block IDs in the order as in the file
256 : : std::vector< int > m_blockid;
257 : : //! Element block IDs for each elem type
258 : : std::vector< std::vector< int > > m_blockid_by_type;
259 : : //! Number of elements in blocks for each elem type
260 : : std::vector< std::vector< std::size_t > > m_nel;
261 : : //! Cell type and number of elements in blocks in the order as in the file
262 : : std::vector< std::pair< ExoElemType, std::size_t > > m_elemblocks;
263 : : //! Global->local triangle element ids on this PE
264 : : std::unordered_map< std::size_t, std::size_t > m_tri;
265 : : //! \brief List of elements for each block-id.
266 : : // key: block id; value: set of elements in corresponding block
267 : : std::unordered_map< std::size_t, std::set< std::size_t > > m_elemInBlockId;
268 : :
269 : : //! Read ExodusII header without setting mesh size
270 : : std::size_t readHeader();
271 : :
272 : : //! Read ExodusII header with setting mesh size
273 : : void readHeader( UnsMesh& mesh );
274 : :
275 : : //! Read coordinates of a single mesh node from file
276 : : void readNode( std::size_t id, tk::real& x, tk::real& y, tk::real& z )
277 : : const;
278 : :
279 : : //! Read all node coordinates from ExodusII file
280 : : void readAllNodes( UnsMesh& mesh ) const;
281 : :
282 : : //! Read all element blocks and mesh connectivity from ExodusII file
283 : : void readAllElements( UnsMesh& mesh );
284 : :
285 : : //! Compute element-block-relative element id and element type
286 : : std::pair< tk::ExoElemType, std::size_t >
287 : : blkRelElemId( std::size_t id ) const;
288 : : };
289 : :
290 : : } // tk::
291 : :
292 : : #endif // ExodusIIMeshReader_h
|