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