MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
ncsubmesh.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
12#include "ncsubmesh.hpp"
13
14#include <unordered_map>
15#include "submesh_utils.hpp"
16#include "submesh.hpp"
17
18namespace mfem
19{
20
21using namespace SubMeshUtils;
22
23NCSubMesh::NCSubMesh(SubMesh& submesh, const NCMesh &parent, From from,
24 const Array<int> &attributes)
25 : NCMesh(), parent_(&parent)
26{
27 Dim = submesh.Dimension();
28 spaceDim = submesh.SpaceDimension();
29 MyRank = 0;
30 Iso = true;
31 Legacy = false;
32
33 if (from == From::Domain)
34 {
35 SubMeshUtils::ConstructVolumeTree(*this, attributes);
36 }
37 else if (from == From::Boundary)
38 {
39 SubMeshUtils::ConstructFaceTree(*this, attributes);
40 }
41
42 // Loop over all nodes, and reparent based on the node relations of the
43 // parent
44 for (int i = 0; i < parent_node_ids_.Size(); i++)
45 {
46 const auto &parent_node = parent.nodes[parent_node_ids_[i]];
47 const int submesh_p1 = parent_to_submesh_node_ids_[parent_node.p1];
48 const int submesh_p2 = parent_to_submesh_node_ids_[parent_node.p2];
49 nodes.Reparent(i, submesh_p1, submesh_p2);
50 }
51
52 nodes.UpdateUnused();
53 for (int i = 0; i < elements.Size(); i++)
54 {
55 if (elements[i].IsLeaf())
56 {
57 // Register all faces
58 RegisterFaces(i);
59 }
60 }
61
62 InitRootElements();
63 InitRootState(root_state.Size());
64 InitGeomFlags();
65 Update(); // Fills in secondary information based off of elements, nodes and faces.
66
67 // If parent has coordinates defined, copy the relevant portion
68 if (parent.coordinates.Size() > 0)
69 {
70 coordinates.SetSize(3*parent_node_ids_.Size());
71 parent.tmp_vertex = new TmpVertex[parent.nodes.NumIds()];
72 for (int n = 0; n < parent_node_ids_.Size(); n++)
73 {
74 std::memcpy(&coordinates[3*n], parent.CalcVertexPos(parent_node_ids_[n]),
75 3*sizeof(real_t));
76 }
77 delete [] parent.tmp_vertex;
78 }
79
80 // The element indexing was changed as part of generation of leaf elements.
81 // We need to update the map.
82 if (from == From::Domain)
83 {
84 // The element indexing was changed as part of generation of leaf
85 // elements. We need to update the map.
86 submesh.parent_to_submesh_element_ids_ = -1;
87 for (int i = 0; i < submesh.parent_element_ids_.Size(); i++)
88 {
89 submesh.parent_element_ids_[i] =
90 parent.elements[parent_element_ids_[leaf_elements[i]]].index;
91 submesh.parent_to_submesh_element_ids_[submesh.parent_element_ids_[i]] = i;
92 }
93 }
94 else
95 {
96 submesh.parent_to_submesh_element_ids_ = -1;
97 // parent elements are BOUNDARY elements, need to map face index to be.
98 const auto &parent_face_to_be = submesh.GetParent()->GetFaceToBdrElMap();
99 MFEM_ASSERT(NElements == submesh.GetNE(), "!");
100 auto new_parent_to_submesh_element_ids = submesh.parent_to_submesh_element_ids_;
101 Array<int> new_parent_element_ids;
102 new_parent_element_ids.Reserve(submesh.parent_element_ids_.Size());
103 for (int i = 0; i < submesh.parent_element_ids_.Size(); i++)
104 {
105 new_parent_element_ids.Append(
106 parent_face_to_be[parent.faces[parent_element_ids_[leaf_elements[i]]].index]);
107 new_parent_to_submesh_element_ids[new_parent_element_ids[i]] = i;
108 }
109
110 MFEM_ASSERT(new_parent_element_ids.Size() == submesh.parent_element_ids_.Size(),
111 "!");
112#ifdef MFEM_DEBUG
113 for (auto x : new_parent_element_ids)
114 {
115 MFEM_ASSERT(std::find(submesh.parent_element_ids_.begin(),
116 submesh.parent_element_ids_.end(), x)
117 != submesh.parent_element_ids_.end(),
118 x << " not found in submesh.parent_element_ids_");
119 }
120 for (auto x : submesh.parent_element_ids_)
121 {
122 MFEM_ASSERT(std::find(new_parent_element_ids.begin(),
123 new_parent_element_ids.end(), x)
124 != new_parent_element_ids.end(), x << " not found in new_parent_element_ids_");
125 }
126#endif
127 submesh.parent_element_ids_ = std::move(new_parent_element_ids);
128 submesh.parent_to_submesh_element_ids_ =
129 std::move(new_parent_to_submesh_element_ids);
130 }
131}
132
133} // namespace mfem
friend class NCSubMesh
Definition ncmesh.hpp:1351
void Update(Vector &x, int k, DenseMatrix &h, Vector &s, Array< Vector * > &v)
Definition solvers.cpp:995
std::array< int, NCMesh::MaxFaceNodes > nodes