Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/Inciter/FV.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 FV advances a system of PDEs with the finite volume scheme
9 : : \details FV advances a system of partial differential equations (PDEs) using
10 : : the finite volume (FV) spatial discretization (on tetrahedron elements).
11 : :
12 : : There are a potentially large number of FV Charm++ chares created by
13 : : Transporter. Each FV gets a chunk of the full load (part of the mesh)
14 : : and does the same: initializes and advances a number of PDE systems in time.
15 : :
16 : : The implementation uses the Charm++ runtime system and is fully
17 : : asynchronous, overlapping computation and communication. The algorithm
18 : : utilizes the structured dagger (SDAG) Charm++ functionality. The high-level
19 : : overview of the algorithm structure and how it interfaces with Charm++ is
20 : : discussed in the Charm++ interface file src/Inciter/fv.ci.
21 : : */
22 : : // *****************************************************************************
23 : : #ifndef FV_h
24 : : #define FV_h
25 : :
26 : : #include <array>
27 : : #include <set>
28 : : #include <unordered_set>
29 : : #include <unordered_map>
30 : :
31 : : #include "DerivedData.hpp"
32 : : #include "FaceData.hpp"
33 : : #include "ElemDiagnostics.hpp"
34 : : #include "Ghosts.hpp"
35 : :
36 : : #include "NoWarning/fv.decl.h"
37 : :
38 : : namespace inciter {
39 : :
40 : : //! FV Charm++ chare array used to advance PDEs in time with FV
41 : : class FV : public CBase_FV {
42 : :
43 : : public:
44 : : #if defined(__clang__)
45 : : #pragma clang diagnostic push
46 : : #pragma clang diagnostic ignored "-Wunused-parameter"
47 : : #pragma clang diagnostic ignored "-Wdeprecated-declarations"
48 : : #elif defined(STRICT_GNUC)
49 : : #pragma GCC diagnostic push
50 : : #pragma GCC diagnostic ignored "-Wunused-parameter"
51 : : #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
52 : : #elif defined(__INTEL_COMPILER)
53 : : #pragma warning( push )
54 : : #pragma warning( disable: 1478 )
55 : : #endif
56 : : // Include Charm++ SDAG code. See http://charm.cs.illinois.edu/manuals/html/
57 : : // charm++/manual.html, Sec. "Structured Control Flow: Structured Dagger".
58 : : FV_SDAG_CODE
59 : : #if defined(__clang__)
60 : : #pragma clang diagnostic pop
61 : : #elif defined(STRICT_GNUC)
62 : : #pragma GCC diagnostic pop
63 : : #elif defined(__INTEL_COMPILER)
64 : : #pragma warning( pop )
65 : : #endif
66 : :
67 : : //! Constructor
68 : : explicit FV( const CProxy_Discretization& disc,
69 : : const CProxy_Ghosts& ghostsproxy,
70 : : const std::map< int, std::vector< std::size_t > >& bface,
71 : : const std::map< int, std::vector< std::size_t > >& /* bnode */,
72 : : const std::vector< std::size_t >& triinpoel );
73 : :
74 : : #if defined(__clang__)
75 : : #pragma clang diagnostic push
76 : : #pragma clang diagnostic ignored "-Wundefined-func-template"
77 : : #endif
78 : : //! Migrate constructor
79 : : // cppcheck-suppress uninitMemberVar
80 : 108 : explicit FV( CkMigrateMessage* msg ) : CBase_FV( msg ) {}
81 : : #if defined(__clang__)
82 : : #pragma clang diagnostic pop
83 : : #endif
84 : :
85 : : //! Return from migration
86 : : void ResumeFromSync() override;
87 : :
88 : : //! Configure Charm++ reduction types for concatenating BC nodelists
89 : : static void registerReducers();
90 : :
91 : : //! Resize solution vectors after extension due to Ghosts and continue setup
92 : : void resizeSolVectors();
93 : :
94 : : //! Setup: query boundary conditions, output mesh, etc.
95 : : void setup();
96 : :
97 : : //! Receive total box IC volume and set conditions in box
98 : : void box( tk::real v, const std::vector< tk::real >& blkvols );
99 : :
100 : : // Evaluate whether to do load balancing
101 : : void evalLB( int nrestart );
102 : :
103 : : //! Start time stepping
104 : : void start();
105 : :
106 : : //! Continue to next time step
107 : : void next();
108 : :
109 : : //! Receive chare-boundary limiter function data from neighboring chares
110 : : void comlim( int fromch,
111 : : const std::vector< std::size_t >& tetid,
112 : : const std::vector< std::vector< tk::real > >& u,
113 : : const std::vector< std::vector< tk::real > >& prim );
114 : :
115 : : //! Receive chare-boundary ghost data from neighboring chares
116 : : void comsol( int fromch,
117 : : const std::vector< std::size_t >& tetid,
118 : : const std::vector< std::vector< tk::real > >& u,
119 : : const std::vector< std::vector< tk::real > >& prim );
120 : :
121 : : //! \brief Receive nodal solution (ofor field output) contributions from
122 : : //! neighboring chares
123 : : void comnodeout( const std::vector< std::size_t >& gid,
124 : : const std::vector< std::size_t >& nesup,
125 : : const std::vector< std::vector< tk::real > >& Lu,
126 : : const std::vector< std::vector< tk::real > >& Lp );
127 : :
128 : : //! Optionally refine/derefine mesh
129 : : void refine( const std::vector< tk::real >& l2res );
130 : :
131 : : //! Receive new mesh from Refiner
132 : : void resizePostAMR(
133 : : const std::vector< std::size_t >& /* ginpoel */,
134 : : const tk::UnsMesh::Chunk& chunk,
135 : : const tk::UnsMesh::Coords& coord,
136 : : const std::unordered_map< std::size_t, tk::UnsMesh::Edge >& /* addedNodes */,
137 : : const std::unordered_map< std::size_t, std::size_t >& addedTets,
138 : : const std::set< std::size_t >& removedNodes,
139 : : const std::unordered_map< std::size_t, std::size_t >& amrNodeMap,
140 : : const tk::NodeCommMap& nodeCommMap,
141 : : const std::map< int, std::vector< std::size_t > >& bface,
142 : : const std::map< int, std::vector< std::size_t > >& /* bnode */,
143 : : const std::vector< std::size_t >& triinpoel,
144 : : const std::unordered_map< std::size_t, std::set< std::size_t > >&
145 : : elemblockid );
146 : :
147 : : //! Extract field output going to file
148 : : void extractFieldOutput(
149 : : const std::vector< std::size_t >& /* ginpoel */,
150 : : const tk::UnsMesh::Chunk& chunk,
151 : : const tk::UnsMesh::Coords& coord,
152 : : const std::unordered_map< std::size_t, tk::UnsMesh::Edge >& /* addedNodes */,
153 : : const std::unordered_map< std::size_t, std::size_t >& addedTets,
154 : : const tk::NodeCommMap& nodeCommMap,
155 : : const std::map< int, std::vector< std::size_t > >& /* bface */,
156 : : const std::map< int, std::vector< std::size_t > >& /* bnode */,
157 : : const std::vector< std::size_t >& /* triinpoel */,
158 : : CkCallback c );
159 : :
160 : : //! Const-ref access to current solution
161 : : //! \return Const-ref to current solution
162 : 0 : const tk::Fields& solution() const { return m_u; }
163 : :
164 : : //! Compute left hand side
165 : : void lhs();
166 : :
167 : : //! Unused in FV
168 : 0 : void resized() {}
169 : :
170 : : //! (no-op)
171 : 0 : void transferSol() {}
172 : :
173 : : //! (no-op)
174 : 0 : void advance( tk::real, tk::real ) {}
175 : :
176 : : //! Compute right hand side and solve system
177 : : void solve( tk::real newdt );
178 : :
179 : : //! Evaluate whether to continue with next time step
180 : : void step();
181 : :
182 : : /** @name Charm++ pack/unpack serializer member functions */
183 : : ///@{
184 : : //! \brief Pack/Unpack serialize member function
185 : : //! \param[in,out] p Charm++'s PUP::er serializer object reference
186 : 330 : void pup( PUP::er &p ) override {
187 : 330 : p | m_disc;
188 : 330 : p | m_ghosts;
189 : 330 : p | m_nsol;
190 : 330 : p | m_ninitsol;
191 : 330 : p | m_nlim;
192 : 330 : p | m_nnod;
193 : 330 : p | m_u;
194 : 330 : p | m_un;
195 : 330 : p | m_p;
196 : 330 : p | m_lhs;
197 : 330 : p | m_rhs;
198 : 330 : p | m_npoin;
199 : 330 : p | m_diag;
200 : 330 : p | m_stage;
201 : 330 : p | m_uc;
202 : 330 : p | m_pc;
203 : 330 : p | m_initial;
204 : 330 : p | m_uElemfields;
205 : 330 : p | m_pElemfields;
206 : 330 : p | m_uNodefields;
207 : 330 : p | m_pNodefields;
208 : 330 : p | m_uNodefieldsc;
209 : 330 : p | m_pNodefieldsc;
210 : 330 : p | m_boxelems;
211 : 330 : p | m_srcFlag;
212 : 330 : p | m_rkcoef;
213 : 330 : p | m_nrk;
214 : 330 : p | m_dte;
215 : 330 : p | m_finished;
216 : 330 : }
217 : : //! \brief Pack/Unpack serialize operator|
218 : : //! \param[in,out] p Charm++'s PUP::er serializer object reference
219 : : //! \param[in,out] i FV object reference
220 : : friend void operator|( PUP::er& p, FV& i ) { i.pup(p); }
221 : : //@}
222 : :
223 : : private:
224 : : //! Discretization proxy
225 : : CProxy_Discretization m_disc;
226 : : //! Distributed Ghosts proxy
227 : : CProxy_Ghosts m_ghosts;
228 : : //! Counter signaling that we have received all our solution ghost data
229 : : std::size_t m_nsol;
230 : : //! \brief Counter signaling that we have received all our solution ghost
231 : : //! data during setup
232 : : std::size_t m_ninitsol;
233 : : //! \brief Counter signaling that we have received all our limiter function
234 : : //! ghost data
235 : : std::size_t m_nlim;
236 : : //! \brief Counter signaling that we have received all our node solution
237 : : //! contributions
238 : : std::size_t m_nnod;
239 : : //! Vector of unknown/solution average over each mesh element
240 : : tk::Fields m_u;
241 : : //! Vector of unknown at previous time-step
242 : : tk::Fields m_un;
243 : : //! Vector of primitive quantities over each mesh element
244 : : tk::Fields m_p;
245 : : //! Left-hand side mass-matrix which is a diagonal matrix
246 : : tk::Fields m_lhs;
247 : : //! Vector of right-hand side
248 : : tk::Fields m_rhs;
249 : : //! Counter for number of nodes on this chare excluding ghosts
250 : : std::size_t m_npoin;
251 : : //! Diagnostics object
252 : : ElemDiagnostics m_diag;
253 : : //! Runge-Kutta stage counter
254 : : std::size_t m_stage;
255 : : //! Solution receive buffers for ghosts only
256 : : std::array< std::vector< std::vector< tk::real > >, 2 > m_uc;
257 : : //! Primitive-variable receive buffers for ghosts only
258 : : std::array< std::vector< std::vector< tk::real > >, 2 > m_pc;
259 : : //! 1 if starting time stepping, 0 if during time stepping
260 : : std::size_t m_initial;
261 : : //! Solution elem output fields
262 : : tk::Fields m_uElemfields;
263 : : //! Primitive elem output fields
264 : : tk::Fields m_pElemfields;
265 : : //! Solution nodal output fields
266 : : tk::Fields m_uNodefields;
267 : : //! Primitive nodal output fields
268 : : tk::Fields m_pNodefields;
269 : : //! Receive buffer for communication of solution node fields
270 : : //! \details Key: global node id, value: output fields and number of
271 : : //! elements surrounding the node
272 : : std::unordered_map< std::size_t, std::pair< std::vector< tk::real >,
273 : : std::size_t > > m_uNodefieldsc;
274 : : //! Receive buffer for communication of primitive quantity node fields
275 : : //! \details Key: global node id, value: output fields and number of
276 : : //! elements surrounding the node
277 : : std::unordered_map< std::size_t, std::pair< std::vector< tk::real >,
278 : : std::size_t > > m_pNodefieldsc;
279 : : //! Element ids at which box ICs are defined by user (multiple boxes)
280 : : std::vector< std::unordered_set< std::size_t > > m_boxelems;
281 : : //! Vector indicating if a source was added to element
282 : : std::vector< int > m_srcFlag;
283 : : //! Runge-Kutta coefficients
284 : : std::array< std::vector< tk::real >, 2 > m_rkcoef;
285 : : //! Number of Runge-Kutta stages
286 : : std::size_t m_nrk;
287 : : //! Time step size for each element (for local time stepping)
288 : : std::vector< tk::real > m_dte;
289 : : //! Flag for completed calculation
290 : : int m_finished;
291 : :
292 : : //! Access bound Discretization class pointer
293 : 2842474 : Ghosts* myGhosts() const {
294 [ + - ][ - + ]: 2842474 : Assert( m_ghosts[ thisIndex ].ckLocal() != nullptr, "ckLocal() null" );
[ - - ][ - - ]
[ - - ]
295 [ + - ]: 2842474 : return m_ghosts[ thisIndex ].ckLocal();
296 : : }
297 : :
298 : : //! Access bound Discretization class pointer
299 : 25248 : Discretization* Disc() const {
300 [ + - ][ - + ]: 25248 : Assert( m_disc[ thisIndex ].ckLocal() != nullptr, "ckLocal() null" );
[ - - ][ - - ]
[ - - ]
301 [ + - ]: 25248 : return m_disc[ thisIndex ].ckLocal();
302 : : }
303 : :
304 : : //! Output mesh field data
305 : : void writeFields( CkCallback c );
306 : :
307 : : //! Compute solution reconstructions
308 : : void reco();
309 : :
310 : : //! Compute limiter function
311 : : void lim();
312 : :
313 : : //! Compute time step size
314 : : void dt();
315 : :
316 : : //! Evaluate whether to continue with next time step stage
317 : : void stage();
318 : :
319 : : //! Evaluate whether to save checkpoint/restart
320 : : void evalRestart();
321 : :
322 : : //! Decide wether to output field data
323 : : bool fieldOutput() const;
324 : :
325 : : //! Decide if we write field output using a refined mesh
326 : : bool refinedOutput() const;
327 : :
328 : : //! Start preparing fields for output to file
329 : : void startFieldOutput( CkCallback c );
330 : : };
331 : :
332 : : } // inciter::
333 : :
334 : : #endif // FV_h
|