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
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466 | // *****************************************************************************
/*!
\file src/Inciter/Refiner.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 Mesh refiner for interfacing the mesh refinement library
\details Mesh refiner is a Charm++ chare array and is used to interface the
mesh refinement object which does not know about parallelization and thus the
distributed nature of the mesh it operates on, i.e., it operates on mesh
chunks. Thus it does not do parallel communication and also does not know
about global vs local IDs. Instead this Charm++ chare array is the one that
does all parallel computing aspects, i.e., communication, and using the mesh
refiner object as a library.
*/
// *****************************************************************************
#pragma once
#include <vector><--- 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 "PUPAMR.hpp"
#include "AMR/mesh_adapter.hpp"
#include "TaggedTuple.hpp"
#include "Callback.hpp"
#include "UnsMesh.hpp"<--- Include file: "UnsMesh.hpp" not found.
#include "Base/Fields.hpp"<--- Include file: "Base/Fields.hpp" not found.
#include "RieCG.hpp"
#include "LaxCG.hpp"
#include "ZalCG.hpp"
#include "KozCG.hpp"
#include "ChoCG.hpp"
#include "LohCG.hpp"
#include "NoWarning/transporter.decl.h"<--- Include file: "NoWarning/transporter.decl.h" not found.
#include "NoWarning/refiner.decl.h"<--- Include file: "NoWarning/refiner.decl.h" not found.
namespace inciter {
//! Mesh refiner for interfacing the mesh refinement library
class Refiner : public CBase_Refiner {
private:
using Edge = tk::UnsMesh::Edge;
using Face = tk::UnsMesh::Face;
using Tet = tk::UnsMesh::Tet;
using EdgeSet = tk::UnsMesh::EdgeSet;
using FaceSet = tk::UnsMesh::FaceSet;
using TetSet = tk::UnsMesh::TetSet;
template< std::size_t N > using Hash = tk::UnsMesh::Hash< N >;
template< std::size_t N > using Eq = tk::UnsMesh::Eq< N >;
//! Boundary face data, see boundary()
using BndFaceData = std::unordered_map< Face, std::size_t, Hash<3>, Eq<3> >;
//! Used to associate error to edges
using EdgeError = std::unordered_map< Edge, tk::real, Hash<2>, Eq<2> >;
public:
//! Mode of operation: the way Refiner is used
enum class RefMode : std::size_t {
T0REF = 1 //!< Initial (t<0) refinement
, DTREF //!< During time stepping (t>0)
};
//! Constructor
explicit
Refiner( std::size_t meshid,
const CProxy_Transporter& transporter,
const CProxy_Sorter& sorter,
const tk::CProxy_MeshWriter& meshwriter,
const std::vector< CProxy_Discretization >& discretization,
const CProxy_RieCG& riecg,
const CProxy_LaxCG& laxcg,
const CProxy_ZalCG& zalcg,
const CProxy_KozCG& kozcg,
const CProxy_ChoCG& chocg,
const CProxy_LohCG& lohcg,
const tk::CProxy_ConjugateGradients& cgpre,
const tk::CProxy_ConjugateGradients& cgmom,
const tk::RefinerCallback& cbr,
const tk::SorterCallback& cbs,
const std::vector< std::size_t >& ginpoel,
const tk::UnsMesh::CoordMap& coordmap,
const std::map< int, std::vector< std::size_t > >& bface,
const std::vector< std::size_t >& triinpoel,
const std::map< int, std::vector< std::size_t > >& bnode,
int nchare );
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundefined-func-template"
#endif
//! Migrate constructor
// cppcheck-suppress uninitMemberVar
explicit Refiner( CkMigrateMessage* m ) : CBase_Refiner( m ) {}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
//! \brief Incoming query for a list boundary edges for which this chare
//! compiles shared edges
void query( int fromch, const EdgeSet& edges );
//! Receive receipt of boundary edge lists to quer
void recvquery();
//! Respond to boundary edge list queries
void response();
//! Receive shared boundary edges for our mesh chunk
void bnd( int fromch, const std::vector< int >& chares );
//! Receive receipt of shared boundary edges
void recvbnd();
//! Query Sorter and update local mesh with the reordered one
void reorder();
//! Start new step of initial mesh refinement/derefinement
void start();
//! Continue after finishing a refinemen/derefinementt step
void next();
//! Start mesh refinement (during time stepping, t>0)
void dtref( const std::map< int, std::vector< std::size_t > >& bface,
const std::map< int, std::vector< std::size_t > >& bnode,
const std::vector< std::size_t >& triinpoel );
//! Do a single step of mesh refinemen/derefinementt (only tag edges)
void refine();
//! Receive newly added mesh edges and locks on our chare boundary
void addRefBndEdges( int fromch,
const AMR::EdgeData& ed,
const std::unordered_set<size_t>& intermediates );
//! Correct refinement to arrive at conforming mesh across chare boundaries
void correctref();
//! Communicate refined edges after a refinement/derefinement step
void comExtra();
//! Perform mesh refinement and decide how to continue
void perform();
//! Send Refiner proxy to Discretization objects
void sendProxy();
//! Get refinement field data in mesh cells
std::tuple< std::vector< std::string >,
std::vector< std::vector< tk::real > >,
std::vector< std::string >,
std::vector< std::vector< tk::real > > >
refinementFields() const;
/** @name Charm++ pack/unpack serializer member functions */
///@{
//! \brief Pack/Unpack serialize member function
//! \param[in,out] p Charm++'s PUP::er serializer object reference
void pup( PUP::er &p ) override {
p | m_meshid;
p | m_ncit;
p | m_host;
p | m_sorter;
p | m_meshwriter;
p | m_disc;
p | m_riecg;
p | m_laxcg;
p | m_zalcg;
p | m_kozcg;
p | m_chocg;
p | m_lohcg;
p | m_cgpre;
p | m_cgmom;
p | m_cbr;
p | m_cbs;
p | m_ginpoel;
p | m_el;
if (p.isUnpacking()) {
m_inpoel = std::get< 0 >( m_el );
m_gid = std::get< 1 >( m_el );
m_lid = std::get< 2 >( m_el );
}
p | m_coordmap;
p | m_coord;
p | m_bface;
p | m_bnode;
p | m_triinpoel;
p | m_nchare;
p | m_mode;
p | m_multi;
p | m_initref;
p | m_refiner;
p | m_nref;
p | m_nbnd;
p | m_extra;
p | m_ch;
p | m_edgech;
p | m_chedge;
p | m_localEdgeData;
p | m_remoteEdgeData;
p | m_remoteEdges;
p | m_intermediates;
p | m_nodeCommMap;
p | m_oldTets;
p | m_addedNodes;
p | m_addedTets;
p | m_removedNodes;
p | m_amrNodeMap;
p | m_oldntets;
p | m_coarseBndFaces;
p | m_coarseBndNodes;
p | m_rid;
//p | m_oldrid;
p | m_lref;
//p | m_oldlref;
//p | m_oldparent;
p | m_writeCallback;
}
//! \brief Pack/Unpack serialize operator|
//! \param[in,out] p Charm++'s PUP::er serializer object reference
//! \param[in,out] r Refiner object reference
friend void operator|( PUP::er& p, Refiner& r ) { r.pup(p); }
//@}
private:
//! Mesh ID
std::size_t m_meshid;
//! Number of parallel-compatibility (mesh ref correction) iterations
std::size_t m_ncit;
//! Host proxy
CProxy_Transporter m_host;
//! Mesh sorter proxy
CProxy_Sorter m_sorter;
//! Mesh writer proxy
tk::CProxy_MeshWriter m_meshwriter;
//! Discretization proxy for all meshes
std::vector< CProxy_Discretization > m_disc;
//! Discretization scheme proxy
CProxy_RieCG m_riecg;
//! Discretization scheme proxy
CProxy_LaxCG m_laxcg;
//! Discretization scheme proxy
CProxy_ZalCG m_zalcg;
//! Discretization scheme proxy
CProxy_KozCG m_kozcg;
//! Discretization scheme proxy
CProxy_ChoCG m_chocg;
//! Discretization scheme proxy
CProxy_LohCG m_lohcg;
//! Conjugate Gradients Charm++ proxy for pressure solve
tk::CProxy_ConjugateGradients m_cgpre;
//! Conjugate Gradients Charm++ proxy for momentum solve
tk::CProxy_ConjugateGradients m_cgmom;
//! Charm++ callbacks associated to compile-time tags for refiner
tk::RefinerCallback m_cbr;
//! Charm++ callbacks associated to compile-time tags for sorter
tk::SorterCallback m_cbs;
//! Tetrtahedron element connectivity of our chunk of the mesh (global ids)
std::vector< std::size_t > m_ginpoel;
//! Elements of the mesh chunk we operate on
//! \details The first vector is the element connectivity (local IDs), the
//! second vector is the global node IDs of owned elements, while the
//! third one is a map of global->local node IDs.
tk::UnsMesh::Chunk m_el;
//! Alias to element connectivity with local node IDs in m_el
std::vector< std::size_t >& m_inpoel = std::get<0>( m_el );
//! Alias to global node IDs of owned elements in m_el
std::vector< std::size_t >& m_gid = std::get<1>( m_el );
//! \brief Alias to local node IDs associated to the global ones of owned
//! elements in m_el
std::unordered_map< std::size_t, std::size_t >& m_lid = std::get<2>( m_el );
//! Coordinates associated to global node IDs of our mesh chunk
tk::UnsMesh::CoordMap m_coordmap;
//! Coordinates of mesh nodes of our chunk of the mesh
tk::UnsMesh::Coords m_coord;
//! List of boundary faces associated to side-set IDs
std::map< int, std::vector< std::size_t > > m_bface;
//! List of boundary nodes associated to side-set IDs
std::map< int, std::vector< std::size_t > > m_bnode;
//! Boundary face-node connectivity
std::vector< std::size_t > m_triinpoel;
//! Total number of refiner chares
int m_nchare;
//! True if initial AMR, false if during time stepping
RefMode m_mode;
//! True if coupled (overset)
bool m_multi;
//! Initial mesh refinement type list (in reverse order)
std::vector< std::string > m_initref;
//! Number of initial mesh refinement/derefinement steps
std::size_t m_ninitref;
//! Mesh refiner (library) object
AMR::mesh_adapter_t m_refiner;
//! Counter during distribution of newly added nodes to chare-boundary edges
std::size_t m_nref;
//! Counter for number of chares contributing to chare boundary edges
std::size_t m_nbnd;
//! Number of chare-boundary newly added nodes that need correction
std::size_t m_extra;
//! Chares we share at least a single edge with
std::unordered_set< int > m_ch;
//! Edge->chare map used to build shared boundary edges
std::unordered_map< Edge, std::vector< int >, Hash<2>, Eq<2> > m_edgech;
//! Chare->edge map used to build shared boundary edges
std::unordered_map< int, EdgeSet > m_chedge;
//! Refinement data associated to edges (edges stored with node-gids)
AMR::EdgeData m_localEdgeData;
//! \brief Refinement data associated to edges shared with other chares
//! (edges stored with node-gids)
std::unordered_map< int, std::vector< std::tuple<
Edge, int, int, AMR::Edge_Lock_Case > > > m_remoteEdgeData;
//! Edges received from other chares
std::unordered_map< int, std::vector< Edge > > m_remoteEdges;
//! Intermediate nodes
std::unordered_set< size_t> m_intermediates;
//! \brief Global mesh node IDs bordering the mesh chunk held by fellow
//! worker chares associated to their chare IDs for the coarse mesh
std::unordered_map< int, std::unordered_set< std::size_t > > m_nodeCommMap;
//! Tetrahedra before refinement/derefinement step
TetSet m_oldTets;
//! Newly added mesh nodes (local id) and their parents (local ids)
std::unordered_map< std::size_t, Edge > m_addedNodes;
//! Newly added mesh cells (local id) and their parent (local id)
std::unordered_map< std::size_t, std::size_t > m_addedTets;
//! Newly removed mesh node local ids
std::set< std::size_t > m_removedNodes;
//! Node id maps from old mesh to new refined mesh
std::unordered_map< std::size_t, std::size_t > m_amrNodeMap;
//! Number of tetrahedra in the mesh before refinement/derefinement step
std::size_t m_oldntets;
//! A unique set of faces associated to side sets of the coarsest mesh
std::unordered_map< int, FaceSet > m_coarseBndFaces;
//! A unique set of nodes associated to side sets of the coarsest mesh
std::unordered_map< int, std::unordered_set<std::size_t> > m_coarseBndNodes;
//! Local -> refiner lib node id map
std::vector< std::size_t > m_rid;
//! Local -> refiner lib node id map for previous mesh
//std::vector< std::size_t > m_oldrid;
//! Refiner lib -> local node id map
std::unordered_map< std::size_t, std::size_t > m_lref;
//! Refiner lib -> local node id map for previous mesh
//std::unordered_map< std::size_t, std::size_t > m_oldlref;
//! Child -> parent tet map for previous mesh
//std::unordered_map< Tet, Tet, Hash<4>, Eq<4> > m_oldparent;
//! Function to continue with after writing field output
CkCallback m_writeCallback;
//! (Re-)generate local -> refiner lib node id map and its inverse
void libmap();
//! (Re-)generate side set and block data structures for coarse mesh
void coarseMesh();
//! Generate flat coordinate data from coordinate map
tk::UnsMesh::Coords flatcoord( const tk::UnsMesh::CoordMap& coordmap );
//! Output mesh to file before a new step of mesh refinement/derefinement
void t0ref();
//! Generate boundary edges and send them to all chares
void bndEdges();
//! Finish initiel mesh refinement
void endt0ref();
//! Do uniform mesh refinement
void uniformRefine();
//! Do uniform mesh derefinement
void uniformDeRefine();
//! Do error-based mesh refinement
void errorRefine();
//! Compute errors in edges
EdgeError
errorsInEdges( std::size_t npoin,
const std::pair< std::vector< std::size_t >,
std::vector< std::size_t > >& esup,
const tk::Fields& u ) const;
//! Update (or evaluate) solution on current mesh
tk::Fields
solution( std::size_t npoin,
const std::pair< std::vector< std::size_t >,
std::vector< std::size_t > >& esup ) const;
//! Do mesh refinement based on user explicitly tagging edges
void edgelistRefine();
//! Do mesh refinement based on tagging edges based on end-point coordinates
void coordRefine();
//! Query AMR lib and update our local store of edge data
void updateEdgeData();
//! Query AMR lib and update our local store of boundary edge data
void updateBndEdgeData();
//! Aggregate number of extra edges across all chares
void matched();
//! Update old mesh after refinement
void updateMesh();
//! Update volume mesh after mesh refinement
void newVolMesh( const std::unordered_set< std::size_t >& old,
const std::unordered_set< std::size_t >& ref );
//! Update boundary data structures after mesh refinement
void newBndMesh( const std::unordered_set< std::size_t >& ref );
//! \brief Generate boundary data structures used to update
//! refined/derefined boundary faces and nodes of side sets
BndFaceData boundary();
//! Regenerate boundary faces and nodes after AMR step
void updateBndData( const std::unordered_set< std::size_t >& ref,
const BndFaceData& pcFaceTets );
//! Evaluate initial conditions (IC) at mesh nodes
tk::Fields
nodeinit( std::size_t /*npoin*/,
const std::pair< std::vector< std::size_t >,
std::vector< std::size_t > >& /*esup*/ ) const;
//! Output mesh to file(s)
void writeMesh( const std::string& basefilename,
uint64_t it,
tk::real t,
CkCallback c ) const;
//! Compute partial boundary surface integral and sum across all chares
bool bndIntegral();
//! Find the oldest parents of a mesh node in the AMR hierarchy
std::unordered_set< std::size_t >
ancestors( std::size_t n );
//! Return a set of keys among whose values a primitive is found
//! \tparam Sets Type of map of sets we search for the primitive
//! \tparam Primitive The primitive we search for in the sets
//! \note Sets::mapped_type == Primitive
//! \param[in] sets Map of sets we search in
//! \param[in] p Primitive we search for
//! \return A unique set of set ids in which the primitive is found or
//! an empty set if the primitive was not found.
//! \details This function searches a map of sets for an item (a primitive,
//! e.g., a single id or a face given by 3 node ids) and returns a
//! unique set of keys behind whose associated sets the item was found.
template< class Sets, class Primitive >
std::unordered_set< int >
keys( const Sets& sets, const Primitive& p ) {
static_assert( std::is_same< typename Sets::mapped_type::value_type,
Primitive >::value, "Type of primitive (face/node) in map of sets must "
"be the same as the type of primitive (face/node) that is searched" );
std::unordered_set< int > ss;
for (const auto& s : sets)
if (s.second.find(p) != end(s.second))
ss.insert( s.first );
return ss;
}
};
} // inciter::
|