Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/IO/MeshReader.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 Polymorphic mesh reader class for connecting to various readers
9 : : \brief Polymorphic mesh reader class for connecting to various lower
10 : : level, specific mesh readers.
11 : : */
12 : : // *****************************************************************************
13 : : #ifndef MeshReader_h
14 : : #define MeshReader_h
15 : :
16 : : #include <vector>
17 : : #include <array>
18 : : #include <string>
19 : : #include <memory>
20 : :
21 : : #include "Types.hpp"
22 : : #include "MeshDetect.hpp"
23 : : #include "ExodusIIMeshReader.hpp"
24 : :
25 : : #ifdef HAS_OMEGA_H
26 : : #include "Omega_h_MeshReader.hpp"
27 : : #endif
28 : :
29 : : namespace tk {
30 : :
31 : : //! Polymorphic mesh reader class for connecting to various mesh readers
32 : : //! \details This class uses runtime polymorphism without client-side
33 : : //! inheritance: inheritance is confined to the internals of the this class,
34 : : //! invisible to client-code. The class exclusively deals with ownership
35 : : //! enabling client-side value semantics. Credit goes to Sean Parent at Adobe.
36 : : //! \see http://sean-parent.stlab.cc/papers-and-presentations/#value-semantics-and-concept-based-polymorphism.
37 : : //! \see For example client code that models a MeshReader, see
38 : : //! tk::ExodusIIMeshReader or tk::Omega_h_MeshReader.
39 : 2 : class MeshReader {
40 : :
41 : : public:
42 : : //! Constructor
43 : : //! \param[in] filename Input mesh filename
44 : : //! \details Dispatch constructor call to various low level mesh readers by
45 : : //! creating child class and assigning to base to be used in polymorphic
46 : : //! fashion.
47 : 775 : explicit MeshReader( const std::string& filename ) {
48 [ + + ]: 774 : auto meshtype = detectInput( filename );
49 [ + - ]: 773 : if (meshtype == MeshReaderType::EXODUSII) {
50 : : using R = ExodusIIMeshReader;
51 [ + - ][ + - ]: 773 : self = std::make_unique< Model<R> >( R(filename) );
52 : : #ifdef HAS_OMEGA_H
53 : : } else if (meshtype == MeshReaderType::OMEGA_H) {
54 : : using R = Omega_h_MeshReader;
55 : : self = std::make_unique< Model<R> >( R(filename) );
56 : : #endif
57 [ - - ][ - - ]: 0 : } else Throw( "Mesh type not implemented or not supported" );
[ - - ]
58 : 773 : }
59 : :
60 : : //! Public interface to return the total number of nodes in mesh file
61 : 189 : std::size_t npoin() { return self->npoin(); }
62 : :
63 : : //! Public interface to read part of the mesh (graph and coords) from file
64 : : //! \details Total number of PEs defaults to 1 for a single-CPU read, this
65 : : //! PE defaults to 0 for a single-CPU read.
66 : 581 : void readMeshPart( std::vector< std::size_t >& ginpoel,
67 : : std::vector< std::size_t >& inpoel,
68 : : std::vector< std::size_t >& triinp,
69 : : std::unordered_map< std::size_t, std::size_t >& lid,
70 : : tk::UnsMesh::Coords& coord,
71 : : std::unordered_map< std::size_t, std::set< std::size_t > >&
72 : : elemBlockId,
73 : : int numpes=1, int mype=0 )
74 : 581 : { self->readMeshPart( ginpoel, inpoel, triinp, lid, coord, elemBlockId,
75 : 581 : numpes, mype ); }
76 : : //! ...
77 : 574 : std::vector< std::size_t > triinpoel(
78 : : std::map< int, std::vector< std::size_t > >& bface,
79 : : const std::map< int, std::vector< std::size_t > >& faceid,
80 : : const std::vector< std::size_t >& ginpoel,
81 : : const std::vector< std::size_t >& triinp )
82 : 574 : { return self->triinpoel( bface, faceid, ginpoel, triinp ); }
83 : :
84 : : //! Public interface to side sets from mesh file
85 : : void
86 : 196 : readSidesetFaces( std::map< int, std::vector< std::size_t > >& bface,
87 : : std::map< int, std::vector< std::size_t > >& faces )
88 : 196 : { self->readSidesetFaces( bface, faces ); }
89 : :
90 : : //! Public interface to read face connectivity of boundary faces from file
91 : 7 : void readFaces( std::vector< std::size_t >& conn )
92 : 7 : { self->readFaces( conn ); }
93 : :
94 : : //! Public interfaces to read node list of all side sets from mesh file
95 : 93 : std::map< int, std::vector< std::size_t > > readSidesetNodes()
96 : 93 : { return self->readSidesetNodes(); }
97 : :
98 : : //! Copy assignment
99 : 2 : MeshReader& operator=( const MeshReader& x )
100 [ + - ]: 4 : { MeshReader tmp(x); *this = std::move(tmp); return *this; }
101 : : //! Copy constructor
102 : 10 : MeshReader( const MeshReader& x ) : self( x.self->copy() ) {}
103 : : //! Move assignment
104 : : MeshReader& operator=( MeshReader&& ) noexcept = default;
105 : : //! Move constructor
106 : 6 : MeshReader( MeshReader&& ) noexcept = default;
107 : :
108 : : private:
109 : : //! \brief Concept is a pure virtual base class specifying the requirements
110 : : //! of polymorphic objects deriving from it
111 : : struct Concept {
112 : 773 : Concept() = default;
113 : 10 : Concept( const Concept& ) = default;
114 : 783 : virtual ~Concept() = default;
115 : : virtual Concept* copy() const = 0;
116 : : virtual std::size_t npoin() = 0;
117 : : virtual void readMeshPart(
118 : : std::vector< std::size_t >&,
119 : : std::vector< std::size_t >&,
120 : : std::vector< std::size_t >&,
121 : : std::unordered_map< std::size_t, std::size_t >&,
122 : : tk::UnsMesh::Coords&,
123 : : std::unordered_map< std::size_t, std::set< std::size_t > >&,
124 : : int, int ) = 0;
125 : : virtual void
126 : : readSidesetFaces( std::map< int, std::vector< std::size_t > >&,
127 : : std::map< int, std::vector< std::size_t > >& ) = 0;
128 : : virtual std::vector< std::size_t >
129 : : triinpoel( std::map< int, std::vector< std::size_t > >&,
130 : : const std::map< int, std::vector< std::size_t > >&,
131 : : const std::vector< std::size_t >&,
132 : : const std::vector< std::size_t >& ) = 0;
133 : : virtual void readFaces( std::vector< std::size_t >& ) = 0;
134 : : virtual std::map< int, std::vector< std::size_t > >
135 : : readSidesetNodes() = 0;
136 : : };
137 : :
138 : : //! \brief Model models the Concept above by deriving from it and overriding
139 : : //! the the virtual functions required by Concept
140 : : template< typename T >
141 : : struct Model : Concept {
142 [ + - ]: 773 : Model( T x ) : data( std::move(x) ) {}
143 [ + - ]: 10 : Concept* copy() const override { return new Model( *this ); }
144 : 189 : std::size_t npoin() override { return data.npoin(); }
145 : 581 : void readMeshPart( std::vector< std::size_t >& ginpoel,
146 : : std::vector< std::size_t >& inpoel,
147 : : std::vector< std::size_t >& triinp,
148 : : std::unordered_map< std::size_t, std::size_t >& lid,
149 : : tk::UnsMesh::Coords& coord,
150 : : std::unordered_map< std::size_t, std::set< std::size_t > >&
151 : : elemBlockId,
152 : : int numpes, int mype ) override
153 : 581 : { data.readMeshPart( ginpoel, inpoel, triinp, lid, coord, elemBlockId,
154 : 581 : numpes, mype ); }
155 : 574 : std::vector< std::size_t > triinpoel(
156 : : std::map< int, std::vector< std::size_t > >& bface,
157 : : const std::map< int, std::vector< std::size_t > >& faceid,
158 : : const std::vector< std::size_t >& ginpoel,
159 : : const std::vector< std::size_t >& triinp ) override
160 : 574 : { return data.triinpoel( bface, faceid, ginpoel, triinp ); }
161 : : void
162 : 196 : readSidesetFaces( std::map< int, std::vector< std::size_t > >& bface,
163 : : std::map< int, std::vector< std::size_t > >& faces )
164 : 196 : override { data.readSidesetFaces( bface, faces ); }
165 : 7 : void readFaces( std::vector< std::size_t >& conn )
166 : 7 : override { data.readFaces( conn ); }
167 : 93 : std::map< int, std::vector< std::size_t > > readSidesetNodes() override
168 : 93 : { return data.readSidesetNodes(); }
169 : : T data;
170 : : };
171 : :
172 : : std::unique_ptr< Concept > self; //!< Base pointer used polymorphically
173 : : };
174 : :
175 : : } // tk::
176 : :
177 : : #endif // MeshReader_h
|