1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
// *****************************************************************************
/*!
  \file      src/IO/ExodusIIMeshReader.hpp
  \copyright 2012-2015 J. Bakosi,
             2016-2018 Los Alamos National Security, LLC.,
             2019-2021 Triad National Security, LLC.,
             2022-2025 J. Bakosi
             All rights reserved. See the LICENSE file for details.
  \brief     ExodusII mesh reader
  \details   ExodusII mesh reader class declaration.
*/
// *****************************************************************************
#ifndef ExodusIIMeshReader_h
#define ExodusIIMeshReader_h

#include <cstddef><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <iosfwd><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <vector><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <array><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <map><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <unordered_map><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include "NoWarning/exodusII.hpp"<--- Include file: "NoWarning/exodusII.hpp" not found.

#include "Types.hpp"
#include "Exception.hpp"
#include "UnsMesh.hpp"<--- Include file: "UnsMesh.hpp" not found.

namespace tk {

//! Supported ExodusII mesh cell types
//! \see ExodusIIMeshReader::readElemBlockIDs()
enum class ExoElemType : int { TET = 0, TRI = 1 };

//! ExodusII mesh cell number of nodes
//! \details List of number of nodes per element for different element types
//!   supported in the order of tk::ExoElemType
const std::array< std::size_t, 2 > ExoNnpe {{ 4, 3 }};

//! ExodusII face-node numbering for tetrahedron side sets
//! \see ExodusII manual figure on "Sideset side Numbering"
const std::array< std::array< std::size_t, 3 >, 4 >
  expofa{{ {{0,1,3}}, {{1,2,3}}, {{0,3,2}}, {{0,2,1}} }};

//! ExodusII mesh-based data reader
//! \details Mesh reader class facilitating reading from mesh-based field data
//!   a file in ExodusII format.
//! \see https://github.com/trilinos/Trilinos/tree/master/packages/seacas
class ExodusIIMeshReader {

  public:
    //! Constructor
    explicit ExodusIIMeshReader( const std::string& filename,
                                 int cpuwordsize = sizeof(double),
                                 int iowordsize = sizeof(double) );

    //! Destructor
    ~ExodusIIMeshReader() noexcept;

    //! Read ExodusII mesh from file
    void readMesh( UnsMesh& mesh );

    //! Return total number of mesh points in mesh file
    std::size_t npoin() { return readHeader(); }

    //! Read part of the mesh (graph and coords) from file
    //! \details Total number of PEs defaults to 1 for a single-CPU read, this
    //!    PE defaults to 0 for a single-CPU read.
    void readMeshPart( std::vector< std::size_t >& ginpoel,
                       std::vector< std::size_t >& inpoel,
                       std::vector< std::size_t >& triinp,
                       std::unordered_map< std::size_t, std::size_t >& lid,
                       tk::UnsMesh::Coords& coord,
                       int numpes=1, int mype=0 );

    //! Read coordinates of a number of mesh nodes from ExodusII file
    std::array< std::vector< tk::real >, 3 >
    readCoords( const std::vector< std::size_t >& gid ) const;

    //! Read face list of all side sets from ExodusII file
    void
    readSidesetFaces( std::map< int, std::vector< std::size_t > >& bface,
                      std::map< int, std::vector< std::size_t > >& faces );

    //! Read face connectivity of a number boundary faces from file
    void readFaces( std::vector< std::size_t >& conn ) const;

    //! Read node list of all side sets from ExodusII file
    std::map< int, std::vector< std::size_t > > readSidesetNodes();

    //! Read coordinates of a single mesh node from ExodusII file
    void readNode( std::size_t fid,
                   std::size_t mid,
                   std::vector< tk::real >& x,
                   std::vector< tk::real >& y,
                   std::vector< tk::real >& z ) const;

    //! Read coordinates of a single mesh node from ExodusII file
    void readNode( std::size_t id, std::array< tk::real, 3 >& coord ) const;

    //! Read coordinates of a number of mesh nodes from ExodusII file
    std::array< std::vector< tk::real >, 3 >
    readNodes( const std::vector< std::size_t >& gid ) const;

    //! Read element block IDs from file
    std::size_t readElemBlockIDs();

    //! Read element connectivity of a number of mesh cells from file
    void readElements( const std::array< std::size_t, 2 >& ext,
                       tk::ExoElemType elemtype,
                       std::vector< std::size_t >& conn ) const;

    //! Read local to global node-ID map
    std::vector< std::size_t > readNodemap();

    //! Generate triangle face connectivity for side sets
    std::vector< std::size_t > triinpoel(
      std::map< int, std::vector< std::size_t > >& belem,
      const std::map< int, std::vector< std::size_t > >& faces,
      const std::vector< std::size_t >& ginpoel,
      const std::vector< std::size_t >& triinp ) const;

    //! Read the names of nodal output variables from ExodusII file
    void readNodeVarNames( std::vector< std::string >& nv ) const;

    //! Read time values from ExodusII file
    void readTimeValues( std::vector< tk::real >& tv ) const;

    //! Read node scalar fields from ExodusII file
    void readNodeScalars(
      std::size_t ntime,
      std::size_t nvar,
      std::vector< std::vector< std::vector< tk::real > > >& var ) const;

    //!  Return number of elements in a mesh block in the ExodusII file
    std::size_t nelem( tk::ExoElemType elemtype ) const;

    //! Copy assignment
    // cppcheck-suppress operatorEqVarError
    // cppcheck-suppress operatorEqMissingReturnStatement
    ExodusIIMeshReader& operator=( const ExodusIIMeshReader& x ) {
      m_filename = x.m_filename;
      m_cpuwordsize = x.m_cpuwordsize;
      m_iowordsize = x.m_iowordsize;
      float version;
      m_inFile = ex_open( m_filename.c_str(), EX_READ, &m_cpuwordsize,
                          &m_iowordsize, &version );
      ErrChk( m_inFile > 0, "Failed to open ExodusII file: " + m_filename );
      m_nnode = x.m_nnode;
      m_neblk = x.m_neblk;
      m_neset = x.m_neset;
      m_from = x.m_from;
      m_till = x.m_till;
      m_blockid = x.m_blockid;
      m_blockid_by_type = x.m_blockid_by_type;
      m_nel = x.m_nel;
      m_elemblocks = x.m_elemblocks;
      m_tri = x.m_tri;
      return *this;
    }

    //! Copy constructor: in terms of copy assignment
    // cppcheck-suppress uninitMemberVar
    ExodusIIMeshReader( const ExodusIIMeshReader& x ) { operator=(x); }

    //! Move assignment
    // cppcheck-suppress operatorEqMissingReturnStatement
    // cppcheck-suppress operatorEqVarError
    ExodusIIMeshReader& operator=( ExodusIIMeshReader&& x ) {
      m_filename = x.m_filename;
      m_cpuwordsize = x.m_cpuwordsize;
      m_iowordsize = x.m_iowordsize;
      float version;
      m_inFile = ex_open( m_filename.c_str(), EX_READ, &m_cpuwordsize,
                          &m_iowordsize, &version );
      ErrChk( m_inFile > 0, "Failed to open ExodusII file: " + m_filename );
      m_nnode = x.m_nnode;
      m_neblk = x.m_neblk;
      m_neset = x.m_neset;
      m_from = x.m_from;
      m_till = x.m_till;
      m_blockid = x.m_blockid;
      m_blockid_by_type = x.m_blockid_by_type;
      m_nel = x.m_nel;
      m_elemblocks = x.m_elemblocks;
      m_tri = x.m_tri;
      x.m_cpuwordsize = sizeof(double);
      x.m_iowordsize = sizeof(double);
      x.m_inFile = ex_open( m_filename.c_str(), EX_READ, &x.m_cpuwordsize,
                            &x.m_iowordsize, &version );
      ErrChk( x.m_inFile > 0, "Failed to open ExodusII file: " + m_filename );
      x.m_nnode = 0;
      x.m_neblk = 0;
      x.m_neset = 0;
      x.m_from = 0;
      x.m_till = 0;
      x.m_blockid.clear();
      x.m_blockid_by_type.resize( ExoNnpe.size() );
      x.m_nel.resize( ExoNnpe.size() );
      x.m_elemblocks.clear();
      x.m_tri.clear();
      return *this;
    }

    //! Move constructor: in terms of move assignment
    ExodusIIMeshReader( ExodusIIMeshReader&& x ) :
      m_filename(),
      m_cpuwordsize( 0 ),
      m_iowordsize( 0 ),
      m_inFile( 0 ),
      m_nnode( 0 ),
      m_neblk( 0 ),
      m_neset( 0 ),
      m_from( 0 ),
      m_till( 0 ),
      m_blockid(),
      m_blockid_by_type(),
      m_nel(),
      m_elemblocks(),
      m_tri()
    { *this = std::move(x); }

  private:
    std::string m_filename;             //!< Input file name
    int m_cpuwordsize;                  //!< CPU word size for ExodusII
    int m_iowordsize;                   //!< I/O word size for ExodusII
    int m_inFile;                       //!< ExodusII file handle
    std::size_t m_nnode;                //!< Number of nodes in file
    std::size_t m_neblk;                //!< Number of element blocks in file
    std::size_t m_neset;                //!< Number of element sets in file
    std::size_t m_from;                 //!< Lower bound of tet ids on this PE
    std::size_t m_till;                 //!< Upper bound of tet ids on this PE
    //! Element block IDs in the order as in the file
    std::vector< int > m_blockid;
    //! Element block IDs for each elem type
    std::vector< std::vector< int > > m_blockid_by_type;
    //! Number of elements in blocks for each elem type
    std::vector< std::vector< std::size_t > > m_nel;
    //! Cell type and number of elements in blocks in the order as in the file
    std::vector< std::pair< ExoElemType, std::size_t > > m_elemblocks;
    //! Global->local triangle element ids on this PE
    std::unordered_map< std::size_t, std::size_t > m_tri;

    //! Read ExodusII header without setting mesh size
    std::size_t readHeader();

    //! Read ExodusII header with setting mesh size
    void readHeader( UnsMesh& mesh );

    //! Read coordinates of a single mesh node from file
    void readNode( std::size_t id, tk::real& x, tk::real& y, tk::real& z )
    const;

    //! Read all node coordinates from ExodusII file
    void readAllNodes( UnsMesh& mesh ) const;

    //! Read all element blocks and mesh connectivity from ExodusII file
    void readAllElements( UnsMesh& mesh );

    //! Compute element-block-relative element id and element type
    std::pair< tk::ExoElemType, std::size_t >
    blkRelElemId( std::size_t id ) const;
};

} // tk::

#endif // ExodusIIMeshReader_h