MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
pncsubmesh.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
13
14#ifdef MFEM_USE_MPI
15
16#include "pncsubmesh.hpp"
17
18#include <numeric>
19#include <unordered_map>
20#include "submesh_utils.hpp"
21#include "psubmesh.hpp"
22namespace mfem
23{
24
25using namespace SubMeshUtils;
26
27
29 From from, const Array<int> &attributes)
30 : ParNCMesh(), parent_(&parent)
31{
32 MyComm = submesh.GetComm();
33 NRanks = submesh.GetNRanks();
34 MyRank = submesh.GetMyRank();
35
36 Dim = submesh.Dimension();
37 spaceDim = submesh.SpaceDimension();
38 Iso = true;
39 Legacy = false;
40
41 // Loop over parent leaf elements and add nodes for all vertices. Register as
42 // top level nodes, will reparent when looping over edges. Cannot add edge
43 // nodes at same time because top level vertex nodes must be contiguous and
44 // first in node list (see coordinates).
45 if (from == From::Domain)
46 {
47 SubMeshUtils::ConstructVolumeTree(*this, attributes);
48 }
49 else if (from == From::Boundary)
50 {
51 SubMeshUtils::ConstructFaceTree(*this, attributes);
52 }
53
54 // Loop over all nodes, and reparent based on the node relations of the
55 // parent
56 for (int i = 0; i < parent_node_ids_.Size(); i++)
57 {
58 const auto &parent_node = parent.nodes[parent_node_ids_[i]];
59 const int submesh_p1 = parent_to_submesh_node_ids_[parent_node.p1];
60 const int submesh_p2 = parent_to_submesh_node_ids_[parent_node.p2];
61 nodes.Reparent(i, submesh_p1, submesh_p2);
62 }
63
64 nodes.UpdateUnused();
65 for (int i = 0; i < elements.Size(); i++)
66 {
67 if (elements[i].IsLeaf())
68 {
69 // Register all faces
71 }
72 }
73
77 Update(); // Fills in secondary information based off of elements, nodes and faces.
78#ifdef MFEM_DEBUG
79 // Check all processors have the same number of roots
80 {
81 int p[2] = {root_state.Size(), -root_state.Size()};
82 MPI_Allreduce(MPI_IN_PLACE, p, 2, MPI_INT, MPI_MIN, submesh.GetComm());
83 MFEM_ASSERT(p[0] == -p[1], "Ranks must agree on number of root elements: min "
84 << p[0] << " max " << -p[1] << " local " << root_state.Size() << " MyRank " <<
85 submesh.GetMyRank());
86 }
87#endif
88
89 // If parent has coordinates defined, copy the relevant portion
90 if (parent.coordinates.Size() > 0)
91 {
92 // Loop over new_nodes -> coordinates is indexed by node.
94 parent.tmp_vertex = new TmpVertex[parent.nodes.NumIds()];
95 for (int n = 0; n < parent_node_ids_.Size(); n++)
96 {
97 std::memcpy(&coordinates[3*n], parent.CalcVertexPos(parent_node_ids_[n]),
98 3*sizeof(real_t));
99 }
100 delete [] parent.tmp_vertex;
101 }
102
103 // The element indexing was changed as part of generation of leaf elements.
104 // We need to update the map.
105 if (from == From::Domain)
106 {
107 // The element indexing was changed as part of generation of leaf
108 // elements. We need to update the map.
109 submesh.parent_to_submesh_element_ids_ = -1;
110 for (int i = 0; i < submesh.parent_element_ids_.Size(); i++)
111 {
112 submesh.parent_element_ids_[i] =
114 submesh.parent_to_submesh_element_ids_[submesh.parent_element_ids_[i]] = i;
115 }
116 }
117 else
118 {
119 submesh.parent_to_submesh_element_ids_ = -1;
120 // parent elements are BOUNDARY elements, need to map face index to be.
121 const auto &parent_face_to_be = submesh.GetParent()->GetFaceToBdrElMap();
122 MFEM_ASSERT(NElements == submesh.GetNE(), NElements << ' ' << submesh.GetNE());
123 auto new_parent_to_submesh_element_ids = submesh.parent_to_submesh_element_ids_;
124 Array<int> new_parent_element_ids;
125 new_parent_element_ids.Reserve(submesh.parent_element_ids_.Size());
126 for (int i = 0; i < submesh.parent_element_ids_.Size(); i++)
127 {
128 new_parent_element_ids.Append(
129 parent_face_to_be[parent.faces[parent_element_ids_[leaf_elements[i]]].index]);
130 new_parent_to_submesh_element_ids[new_parent_element_ids[i]] = i;
131 }
132
133 MFEM_ASSERT(new_parent_element_ids.Size() == submesh.parent_element_ids_.Size(),
134 new_parent_element_ids.Size() << ' ' << submesh.parent_element_ids_.Size());
135#ifdef MFEM_DEBUG
136 for (auto x : new_parent_element_ids)
137 {
138 MFEM_ASSERT(std::find(submesh.parent_element_ids_.begin(),
139 submesh.parent_element_ids_.end(), x)
140 != submesh.parent_element_ids_.end(),
141 x << " not found in submesh.parent_element_ids_");
142 }
143 for (auto x : submesh.parent_element_ids_)
144 {
145 MFEM_ASSERT(std::find(new_parent_element_ids.begin(),
146 new_parent_element_ids.end(), x)
147 != new_parent_element_ids.end(), x << " not found in new_parent_element_ids_");
148 }
149#endif
150 submesh.parent_element_ids_ = new_parent_element_ids;
151 submesh.parent_to_submesh_element_ids_ = new_parent_to_submesh_element_ids;
152 }
153}
154
155} // namespace mfem
156
157#endif // MFEM_USE_MPI
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
Definition array.hpp:165
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:758
int Size() const
Return the logical size of the array.
Definition array.hpp:147
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:830
T * end()
STL-like end. Returns pointer after the last element of the array.
Definition array.hpp:325
T * begin()
STL-like begin. Returns pointer to the first element of the array.
Definition array.hpp:322
Array< int > GetFaceToBdrElMap() const
Definition mesh.cpp:1517
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1282
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1216
int SpaceDimension() const
Dimension of the physical space containing the mesh.
Definition mesh.hpp:1219
HashTable< Node > nodes
Definition ncmesh.hpp:619
HashTable< Face > faces
Definition ncmesh.hpp:620
BlockArray< Element > elements
Definition ncmesh.hpp:624
TmpVertex * tmp_vertex
Definition ncmesh.hpp:1211
Array< int > leaf_elements
finest elements, in Mesh ordering (+ ghosts)
Definition ncmesh.hpp:723
const real_t * CalcVertexPos(int node) const
Definition ncmesh.cpp:2733
void InitRootState(int root_count)
Definition ncmesh.cpp:2652
friend class ParNCSubMesh
Definition ncmesh.hpp:1352
Array< int > root_state
Definition ncmesh.hpp:701
void InitRootElements()
Count root elements and initialize root_state.
Definition ncmesh.cpp:6335
bool Iso
true if the mesh only contains isotropic refinements
Definition ncmesh.hpp:526
bool Legacy
true if the mesh was loaded from the legacy v1.1 format
Definition ncmesh.hpp:528
Array< real_t > coordinates
Definition ncmesh.hpp:705
int MyRank
used in parallel, or when loading a parallel file in serial
Definition ncmesh.hpp:525
int spaceDim
dimensions of the elements and the vertex coordinates
Definition ncmesh.hpp:524
void RegisterFaces(int elem, int *fattr=NULL)
Definition ncmesh.cpp:441
void InitGeomFlags()
Definition ncmesh.cpp:259
MPI_Comm GetComm() const
Definition pmesh.hpp:402
int GetMyRank() const
Definition pmesh.hpp:404
int GetNRanks() const
Definition pmesh.hpp:403
A parallel extension of the NCMesh class.
Definition pncmesh.hpp:63
MPI_Comm MyComm
Definition pncmesh.hpp:295
void Update() override
Definition pncmesh.cpp:98
Array< int > parent_node_ids_
Array< int > parent_element_ids_
std::unordered_map< int, int > parent_to_submesh_node_ids_
Mapping from parent NCMesh node ids to submesh NCMesh node ids.
Subdomain representation of a topological parent in another ParMesh.
Definition psubmesh.hpp:54
const ParMesh * GetParent() const
Get the parent ParMesh object.
Definition psubmesh.hpp:89
From
Indicator from which part of the parent Mesh the SubMesh is created.
Definition submesh.hpp:49
void ConstructFaceTree(NCSubMeshT &submesh, const Array< int > &attributes)
Construct a nonconformal mesh (serial or parallel) for a surface submesh, from an existing nonconform...
void ConstructVolumeTree(NCSubMeshT &submesh, const Array< int > &attributes)
Construct a nonconformal mesh (serial or parallel) for a volume submesh, from an existing nonconforma...
float real_t
Definition config.hpp:43
real_t p(const Vector &x, real_t t)