Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/Inciter/Refiner.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 Mesh refiner for interfacing the mesh refinement library
9 : : \details Mesh refiner is a Charm++ chare array and is used to interface the
10 : : mesh refinement object which does not know about parallelization and thus the
11 : : distributed nature of the mesh it operates on, i.e., it operates on mesh
12 : : chunks. Thus it does not do parallel communication and also does not know
13 : : about global vs local IDs. Instead this Charm++ chare array is the one that
14 : : does all parallel computing aspects, i.e., communcation, and using the mesh
15 : : refiner object as a library.
16 : : */
17 : : // *****************************************************************************
18 : : #ifndef Refiner_h
19 : : #define Refiner_h
20 : :
21 : : #include <vector>
22 : : #include <unordered_map>
23 : :
24 : : #include "PUPAMR.hpp"
25 : : #include "AMR/mesh_adapter.hpp"
26 : : #include "Inciter/Options/AMRInitial.hpp"
27 : : #include "TaggedTuple.hpp"
28 : : #include "Tags.hpp"
29 : : #include "Callback.hpp"
30 : : #include "UnsMesh.hpp"
31 : : #include "Base/Fields.hpp"
32 : : #include "Scheme.hpp"
33 : : #include "ALECG.hpp"
34 : : #include "OversetFE.hpp"
35 : : #include "DG.hpp"
36 : : #include "FV.hpp"
37 : : #include "CommMap.hpp"
38 : :
39 : : #include "NoWarning/transporter.decl.h"
40 : : #include "NoWarning/refiner.decl.h"
41 : :
42 : : namespace inciter {
43 : :
44 : : //! Mesh refiner for interfacing the mesh refinement library
45 : : class Refiner : public CBase_Refiner {
46 : :
47 : : private:
48 : : using Edge = tk::UnsMesh::Edge;
49 : : using Face = tk::UnsMesh::Face;
50 : : using Tet = tk::UnsMesh::Tet;
51 : : using EdgeSet = tk::UnsMesh::EdgeSet;
52 : : using FaceSet = tk::UnsMesh::FaceSet;
53 : : using TetSet = tk::UnsMesh::TetSet;
54 : : template< std::size_t N > using Hash = tk::UnsMesh::Hash< N >;
55 : : template< std::size_t N > using Eq = tk::UnsMesh::Eq< N >;
56 : :
57 : : //! Boundary face data, see boundary()
58 : : using BndFaceData = std::unordered_map< Face, std::size_t, Hash<3>, Eq<3> >;
59 : :
60 : : //! Used to associate error to edges
61 : : using EdgeError = std::unordered_map< Edge, tk::real, Hash<2>, Eq<2> >;
62 : :
63 : : public:
64 : : //! Mode of operation: the way Refiner is used
65 : : enum class RefMode : std::size_t {
66 : : T0REF = 1, //!< Initial (t<0) refinement
67 : : DTREF, //!< During time stepping (t>0)
68 : : OUTREF, //!< Refinement for field output
69 : : OUTDEREF }; //!< De-refinement after field output
70 : :
71 : : //! Constructor
72 : : explicit Refiner( std::size_t meshid,
73 : : const CProxy_Transporter& transporter,
74 : : const CProxy_Sorter& sorter,
75 : : const tk::CProxy_MeshWriter& meshwriter,
76 : : const std::vector< Scheme >& scheme,
77 : : const tk::RefinerCallback& cbr,
78 : : const tk::SorterCallback& cbs,
79 : : const std::vector< std::size_t >& ginpoel,
80 : : const tk::UnsMesh::CoordMap& coordmap,
81 : : const std::map< int, std::vector< std::size_t > >& bface,
82 : : const std::vector< std::size_t >& triinpoel,
83 : : const std::map< int, std::vector< std::size_t > >& bnode,
84 : : const std::vector< std::size_t >& elemblid,
85 : : int nchare );
86 : :
87 : : #if defined(__clang__)
88 : : #pragma clang diagnostic push
89 : : #pragma clang diagnostic ignored "-Wundefined-func-template"
90 : : #endif
91 : : //! Migrate constructor
92 : : // cppcheck-suppress uninitMemberVar
93 : 23355 : explicit Refiner( CkMigrateMessage* ) {}
94 : : #if defined(__clang__)
95 : : #pragma clang diagnostic pop
96 : : #endif
97 : :
98 : : //! \brief Incoming query for a list boundary edges for which this chare
99 : : //! compiles shared edges
100 : : void query( int fromch, const EdgeSet& edges );
101 : : //! Receive receipt of boundary edge lists to quer
102 : : void recvquery();
103 : : //! Respond to boundary edge list queries
104 : : void response();
105 : : //! Receive shared boundary edges for our mesh chunk
106 : : void bnd( int fromch, const std::vector< int >& chares );
107 : : //! Receive receipt of shared boundary edges
108 : : void recvbnd();
109 : :
110 : : //! Query Sorter and update local mesh with the reordered one
111 : : void reorder();
112 : :
113 : : //! Start new step of initial mesh refinement/derefinement
114 : : void start();
115 : :
116 : : //! Continue after finishing a refinemen/derefinementt step
117 : : void next();
118 : :
119 : : //! Start mesh refinement (during time stepping, t>0)
120 : : void dtref( const std::map< int, std::vector< std::size_t > >& bface,
121 : : const std::map< int, std::vector< std::size_t > >& bnode,
122 : : const std::vector< std::size_t >& triinpoel );
123 : :
124 : : //! Start mesh refinement (for field output)
125 : : void outref( const std::map< int, std::vector< std::size_t > >& bface,
126 : : const std::map< int, std::vector< std::size_t > >& bnode,
127 : : const std::vector< std::size_t >& triinpoel,
128 : : CkCallback c,
129 : : RefMode mode = RefMode::OUTREF );
130 : :
131 : : //! Do a single step of mesh refinemen/derefinementt (only tag edges)
132 : : void refine();
133 : :
134 : : //! Receive newly added mesh edges and locks on our chare boundary
135 : : void addRefBndEdges( int fromch,
136 : : const AMR::EdgeData& ed,
137 : : const std::unordered_set<size_t>& intermediates );
138 : :
139 : : //! Correct refinement to arrive at conforming mesh across chare boundaries
140 : : void correctref();
141 : :
142 : : //! Communicate refined edges after a refinement/derefinement step
143 : : void comExtra();
144 : :
145 : : //! Perform mesh refinement and decide how to continue
146 : : void perform();
147 : :
148 : : //! Send Refiner proxy to Discretization objects
149 : : void sendProxy();
150 : :
151 : : //! Get refinement field data in mesh cells
152 : : std::tuple< std::vector< std::string >,
153 : : std::vector< std::vector< tk::real > >,
154 : : std::vector< std::string >,
155 : : std::vector< std::vector< tk::real > > >
156 : : refinementFields() const;
157 : :
158 : : /** @name Charm++ pack/unpack serializer member functions */
159 : : ///@{
160 : : //! \brief Pack/Unpack serialize member function
161 : : //! \param[in,out] p Charm++'s PUP::er serializer object reference
162 : 24125 : void pup( PUP::er &p ) override {
163 : 24125 : p | m_meshid;
164 : 24125 : p | m_ncit;
165 : 24125 : p | m_host;
166 : 24125 : p | m_sorter;
167 : 24125 : p | m_meshwriter;
168 : 24125 : p | m_scheme;
169 : : p | m_cbr;
170 : : p | m_cbs;
171 : 24125 : p | m_ginpoel;
172 : 24125 : p | m_el;
173 [ + + ]: 24125 : if (p.isUnpacking()) {
174 : 7785 : m_inpoel = std::get< 0 >( m_el );
175 : 7785 : m_gid = std::get< 1 >( m_el );
176 [ - + ]: 7785 : m_lid = std::get< 2 >( m_el );
177 : : }
178 : 24125 : p | m_coordmap;
179 : : p | m_coord;
180 : : p | m_bface;
181 : 24125 : p | m_bnode;
182 : 24125 : p | m_triinpoel;
183 : 24125 : p | m_elemblockid;
184 : 24125 : p | m_nchare;
185 : 24125 : p | m_mode;
186 : 24125 : p | m_initref;
187 : 24125 : p | m_refiner;
188 : 24125 : p | m_nref;
189 : 24125 : p | m_nbnd;
190 : 24125 : p | m_extra;
191 : 24125 : p | m_ch;
192 : 24125 : p | m_edgech;
193 : 24125 : p | m_chedge;
194 : 24125 : p | m_localEdgeData;
195 : 24125 : p | m_remoteEdgeData;
196 : 24125 : p | m_remoteEdges;
197 : 24125 : p | m_intermediates;
198 : 24125 : p | m_nodeCommMap;
199 : 24125 : p | m_oldTets;
200 : 24125 : p | m_addedNodes;
201 : 24125 : p | m_addedTets;
202 : 24125 : p | m_removedNodes;
203 : 24125 : p | m_amrNodeMap;
204 : 24125 : p | m_oldntets;
205 : 24125 : p | m_coarseBndFaces;
206 : 24125 : p | m_coarseBndNodes;
207 : 24125 : p | m_coarseBlkElems;
208 : 24125 : p | m_rid;
209 : : //p | m_oldrid;
210 : 24125 : p | m_lref;
211 : : //p | m_oldlref;
212 : : //p | m_oldparent;
213 : 24125 : p | m_writeCallback;
214 : 24125 : p | m_outref_ginpoel;
215 : 24125 : p | m_outref_el;
216 : : p | m_outref_coord;
217 : : p | m_outref_addedNodes;
218 : 24125 : p | m_outref_addedTets;
219 : 24125 : p | m_outref_nodeCommMap;
220 : 24125 : p | m_outref_bface;
221 : 24125 : p | m_outref_bnode;
222 : 24125 : p | m_outref_triinpoel;
223 : 24125 : }
224 : : //! \brief Pack/Unpack serialize operator|
225 : : //! \param[in,out] p Charm++'s PUP::er serializer object reference
226 : : //! \param[in,out] r Refiner object reference
227 : : friend void operator|( PUP::er& p, Refiner& r ) { r.pup(p); }
228 : : //@}
229 : :
230 : : private:
231 : : //! Mesh ID
232 : : std::size_t m_meshid;
233 : : //! Number of parallel-compatibility (mesh ref correction) iterations
234 : : std::size_t m_ncit;
235 : : //! Host proxy
236 : : CProxy_Transporter m_host;
237 : : //! Mesh sorter proxy
238 : : CProxy_Sorter m_sorter;
239 : : //! Mesh writer proxy
240 : : tk::CProxy_MeshWriter m_meshwriter;
241 : : //! Discretization schemes (one per mesh)
242 : : std::vector< Scheme > m_scheme;
243 : : //! Charm++ callbacks associated to compile-time tags for refiner
244 : : tk::RefinerCallback m_cbr;
245 : : //! Charm++ callbacks associated to compile-time tags for sorter
246 : : tk::SorterCallback m_cbs;
247 : : //! Tetrtahedron element connectivity of our chunk of the mesh (global ids)
248 : : std::vector< std::size_t > m_ginpoel;
249 : : //! Elements of the mesh chunk we operate on
250 : : //! \details The first vector is the element connectivity (local IDs), the
251 : : //! second vector is the global node IDs of owned elements, while the
252 : : //! third one is a map of global->local node IDs.
253 : : tk::UnsMesh::Chunk m_el;
254 : : //! Alias to element connectivity with local node IDs in m_el
255 : : std::vector< std::size_t >& m_inpoel = std::get<0>( m_el );
256 : : //! Alias to global node IDs of owned elements in m_el
257 : : std::vector< std::size_t >& m_gid = std::get<1>( m_el );
258 : : //! \brief Alias to local node IDs associated to the global ones of owned
259 : : //! elements in m_el
260 : : std::unordered_map< std::size_t, std::size_t >& m_lid = std::get<2>( m_el );
261 : : //! Coordinates associated to global node IDs of our mesh chunk
262 : : tk::UnsMesh::CoordMap m_coordmap;
263 : : //! Coordinates of mesh nodes of our chunk of the mesh
264 : : tk::UnsMesh::Coords m_coord;
265 : : //! List of boundary faces associated to side-set IDs
266 : : std::map< int, std::vector< std::size_t > > m_bface;
267 : : //! List of boundary nodes associated to side-set IDs
268 : : std::map< int, std::vector< std::size_t > > m_bnode;
269 : : //! Boundary face-node connectivity
270 : : std::vector< std::size_t > m_triinpoel;
271 : : //! Mesh block ids associated with local tet ids
272 : : std::unordered_map< std::size_t, std::set< std::size_t > > m_elemblockid;
273 : : //! Total number of refiner chares
274 : : int m_nchare;
275 : : //! True if initial AMR, false if during time stepping
276 : : RefMode m_mode;
277 : : //! Initial mesh refinement type list (in reverse order)
278 : : std::vector< ctr::AMRInitialType > m_initref;
279 : : //! Number of initial mesh refinement/derefinement steps
280 : : std::size_t m_ninitref;
281 : : //! Mesh refiner (library) object
282 : : AMR::mesh_adapter_t m_refiner;
283 : : //! Counter during distribution of newly added nodes to chare-boundary edges
284 : : std::size_t m_nref;
285 : : //! Counter for number of chares contributing to chare boundary edges
286 : : std::size_t m_nbnd;
287 : : //! Number of chare-boundary newly added nodes that need correction
288 : : std::size_t m_extra;
289 : : //! Chares we share at least a single edge with
290 : : std::unordered_set< int > m_ch;
291 : : //! Edge->chare map used to build shared boundary edges
292 : : std::unordered_map< Edge, std::vector< int >, Hash<2>, Eq<2> > m_edgech;
293 : : //! Chare->edge map used to build shared boundary edges
294 : : std::unordered_map< int, EdgeSet > m_chedge;
295 : : //! Refinement data associated to edges (edges stored with node-gids)
296 : : AMR::EdgeData m_localEdgeData;
297 : : //! \brief Refinement data associated to edges shared with other chares
298 : : //! (edges stored with node-gids)
299 : : std::unordered_map< int, std::vector< std::tuple<
300 : : Edge, int, int, AMR::Edge_Lock_Case > > > m_remoteEdgeData;
301 : : //! Edges received from other chares
302 : : std::unordered_map< int, std::vector< Edge > > m_remoteEdges;
303 : : //! Intermediate nodes
304 : : std::unordered_set< size_t> m_intermediates;
305 : : //! \brief Global mesh node IDs bordering the mesh chunk held by fellow
306 : : //! worker chares associated to their chare IDs for the coarse mesh
307 : : tk::NodeCommMap m_nodeCommMap;
308 : : //! Tetrahedra before refinement/derefinement step
309 : : TetSet m_oldTets;
310 : : //! Newly added mesh nodes (local id) and their parents (local ids)
311 : : std::unordered_map< std::size_t, Edge > m_addedNodes;
312 : : //! Newly added mesh cells (local id) and their parent (local id)
313 : : std::unordered_map< std::size_t, std::size_t > m_addedTets;
314 : : //! Newly removed mesh node local ids
315 : : std::set< std::size_t > m_removedNodes;
316 : : //! Node id maps from old mesh to new refined mesh
317 : : std::unordered_map< std::size_t, std::size_t > m_amrNodeMap;
318 : : //! Number of tetrahedra in the mesh before refinement/derefinement step
319 : : std::size_t m_oldntets;
320 : : //! A unique set of faces associated to side sets of the coarsest mesh
321 : : std::unordered_map< int, FaceSet > m_coarseBndFaces;
322 : : //! A unique set of nodes associated to side sets of the coarsest mesh
323 : : std::unordered_map< int, std::unordered_set<std::size_t> > m_coarseBndNodes;
324 : : //! Set of elements associated to mesh block ids of the coarsest mesh
325 : : std::unordered_map< std::size_t, TetSet > m_coarseBlkElems;
326 : : //! Local -> refiner lib node id map
327 : : std::vector< std::size_t > m_rid;
328 : : //! Local -> refiner lib node id map for previous mesh
329 : : //std::vector< std::size_t > m_oldrid;
330 : : //! Refiner lib -> local node id map
331 : : std::unordered_map< std::size_t, std::size_t > m_lref;
332 : : //! Refiner lib -> local node id map for previous mesh
333 : : //std::unordered_map< std::size_t, std::size_t > m_oldlref;
334 : : //! Child -> parent tet map for previous mesh
335 : : //std::unordered_map< Tet, Tet, Hash<4>, Eq<4> > m_oldparent;
336 : : //! Function to continue with after writing field output
337 : : CkCallback m_writeCallback;
338 : : //! \brief Tetrahedron element connectivity of our chunk of the mesh
339 : : //! (global ids) for the field-output-refined mesh
340 : : std::vector< std::size_t > m_outref_ginpoel;
341 : : //! \brief Elements of the mesh chunk we operate on for the
342 : : //! field-output-refined mesh
343 : : //! \details The first vector is the element connectivity (local IDs), the
344 : : //! second vector is the global node IDs of owned elements, while the
345 : : //! third one is a map of global->local node IDs.
346 : : tk::UnsMesh::Chunk m_outref_el;
347 : : //! \brief Coordinates of mesh nodes of our chunk of the mesh for
348 : : //! field-output-refined mesh
349 : : tk::UnsMesh::Coords m_outref_coord;
350 : : //! \brief Newly added mesh nodes (local id) and their parents (local ids)
351 : : //! for the field-output-refined mesh
352 : : std::unordered_map< std::size_t, Edge > m_outref_addedNodes;
353 : : //! \brief Newly added mesh cells (local id) and their parent (local id)
354 : : //! for the field-output-refined mesh
355 : : std::unordered_map< std::size_t, std::size_t > m_outref_addedTets;
356 : : //! \brief Global mesh node IDs bordering the mesh chunk held by fellow
357 : : //! worker chares associated to their chare IDs for the coarse mesh for
358 : : //! the field-output-refined mesh
359 : : tk::NodeCommMap m_outref_nodeCommMap;
360 : : //! \brief List of boundary faces associated to side-set IDs for the
361 : : //! field-output-refined mesh
362 : : std::map< int, std::vector< std::size_t > > m_outref_bface;
363 : : //! \brief List of boundary nodes associated to side-set IDs for the
364 : : //! field-output-refined mesh
365 : : std::map< int, std::vector< std::size_t > > m_outref_bnode;
366 : : //! Boundary face-node connectivity for the field-output-refinedmesh
367 : : std::vector< std::size_t > m_outref_triinpoel;
368 : :
369 : : //! (Re-)generate local -> refiner lib node id map and its inverse
370 : : void libmap();
371 : :
372 : : //! (Re-)generate side set and block data structures for coarse mesh
373 : : void coarseMesh();
374 : :
375 : : //! Generate flat coordinate data from coordinate map
376 : : tk::UnsMesh::Coords flatcoord( const tk::UnsMesh::CoordMap& coordmap );
377 : :
378 : : //! Output mesh to file before a new step of mesh refinement/derefinement
379 : : void t0ref();
380 : :
381 : : //! Generate boundary edges and send them to all chares
382 : : void bndEdges();
383 : :
384 : : //! Finish initiel mesh refinement
385 : : void endt0ref();
386 : :
387 : : //! Do uniform mesh refinement
388 : : void uniformRefine();
389 : :
390 : : //! Do uniform mesh derefinement
391 : : void uniformDeRefine();
392 : :
393 : : //! Do error-based mesh refinement
394 : : void errorRefine();
395 : :
396 : : //! Compute errors in edges
397 : : EdgeError
398 : : errorsInEdges( std::size_t npoin,
399 : : const std::pair< std::vector< std::size_t >,
400 : : std::vector< std::size_t > >& esup,
401 : : const tk::Fields& u ) const;
402 : :
403 : : //! Update (or evaluate) solution on current mesh
404 : : tk::Fields
405 : : solution( std::size_t npoin,
406 : : const std::pair< std::vector< std::size_t >,
407 : : std::vector< std::size_t > >& esup ) const;
408 : :
409 : : //! Do mesh refinement based on user explicitly tagging edges
410 : : void edgelistRefine();
411 : :
412 : : //! Do mesh refinement based on tagging edges based on end-point coordinates
413 : : void coordRefine();
414 : :
415 : : //! Query AMR lib and update our local store of edge data
416 : : void updateEdgeData();
417 : :
418 : : //! Query AMR lib and update our local store of boundary edge data
419 : : void updateBndEdgeData();
420 : :
421 : : //! Aggregate number of extra edges across all chares
422 : : void matched();
423 : :
424 : : //! Update old mesh after refinement
425 : : void updateMesh();
426 : :
427 : : //! Update volume mesh after mesh refinement
428 : : void newVolMesh( const std::unordered_set< std::size_t >& old,
429 : : const std::unordered_set< std::size_t >& ref );
430 : :
431 : : //! Update boundary data structures after mesh refinement
432 : : void newBndMesh( const std::unordered_set< std::size_t >& ref );
433 : :
434 : : //! \brief Generate boundary data structures used to update
435 : : //! refined/derefined boundary faces and nodes of side sets
436 : : BndFaceData boundary();
437 : :
438 : : //! Regenerate boundary faces and nodes after AMR step
439 : : void updateBndData( const std::unordered_set< std::size_t >& ref,
440 : : const BndFaceData& bnd );
441 : :
442 : : //! Evaluate initial conditions (IC) at mesh nodes
443 : : tk::Fields
444 : : nodeinit( std::size_t npoin,
445 : : const std::pair< std::vector< std::size_t >,
446 : : std::vector< std::size_t > >& esup ) const;
447 : :
448 : : //! Output mesh to file(s)
449 : : void writeMesh( const std::string& basefilename,
450 : : uint64_t it,
451 : : tk::real t,
452 : : CkCallback c ) const;
453 : :
454 : : //! Compute partial boundary surface integral and sum across all chares
455 : : bool bndIntegral();
456 : :
457 : : //! Find the oldest parents of a mesh node in the AMR hierarchy
458 : : std::unordered_set< std::size_t >
459 : : ancestors( std::size_t n );
460 : :
461 : : //! Return a set of keys among whose values a primitive is found
462 : : //! \tparam Sets Type of map of sets we search for the primitive
463 : : //! \tparam Primitive The primitive we search for in the sets
464 : : //! \note Sets::mapped_type == Primitive
465 : : //! \param[in] sets Map of sets we search in
466 : : //! \param[in] p Primitive we search for
467 : : //! \return A unique set of set ids in which the primitive is found or
468 : : //! an empty set if the primitive was not found.
469 : : //! \details This function searches a map of sets for an item (a primitive,
470 : : //! e.g., a single id or a face given by 3 node ids) and returns a
471 : : //! unique set of keys behind whose associated sets the item was found.
472 : : template< class Sets, class Primitive >
473 : : std::unordered_set< int >
474 : 1927206 : keys( const Sets& sets, const Primitive& p ) {
475 : : static_assert( std::is_same< typename Sets::mapped_type::value_type,
476 : : Primitive >::value, "Type of primitive (face/node) in map of sets must "
477 : : "be the same as the type of primitive (face/node) that is searched" );
478 : : std::unordered_set< int > ss;
479 [ + + ]: 2130822 : for (const auto& s : sets)
480 [ + + ]: 203616 : if (s.second.find(p) != end(s.second))
481 [ + - ]: 52752 : ss.insert( s.first );
482 : 1927206 : return ss;
483 : : }
484 : : };
485 : :
486 : : } // inciter::
487 : :
488 : : #endif // Refiner_h
|