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::