MFEM  v4.5.2
Finite element discretization library
submesh_utils.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2023, 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 "submesh_utils.hpp"
13 
14 namespace mfem
15 {
16 namespace SubMeshUtils
17 {
18 int UniqueIndexGenerator::Get(int i, bool &new_index)
19 {
20  auto f = idx.find(i);
21  if (f == idx.end())
22  {
23  idx[i] = counter;
24  new_index = true;
25  return counter++;
26  }
27  else
28  {
29  new_index = false;
30  return (*f).second;
31  }
32 }
33 
34 bool ElementHasAttribute(const Element &el, const Array<int> &attributes)
35 {
36  for (int a = 0; a < attributes.Size(); a++)
37  {
38  if (el.GetAttribute() == attributes[a])
39  {
40  return true;
41  }
42  }
43  return false;
44 }
45 
46 std::tuple< Array<int>, Array<int> >
47 AddElementsToMesh(const Mesh& parent,
48  Mesh& mesh,
49  const Array<int> &attributes,
50  bool from_boundary)
51 {
52  Array<int> parent_vertex_ids, parent_element_ids;
53  UniqueIndexGenerator vertex_ids;
54  const int ne = from_boundary ? parent.GetNBE() : parent.GetNE();
55  for (int i = 0; i < ne; i++)
56  {
57  const Element *pel = from_boundary ?
58  parent.GetBdrElement(i) : parent.GetElement(i);
59  if (!ElementHasAttribute(*pel, attributes)) { continue; }
60 
61  Array<int> v;
62  pel->GetVertices(v);
63  Array<int> submesh_v(v.Size());
64 
65  for (int iv = 0; iv < v.Size(); iv++)
66  {
67  bool new_vertex;
68  int mesh_vertex_id = v[iv];
69  int submesh_vertex_id = vertex_ids.Get(mesh_vertex_id, new_vertex);
70  if (new_vertex)
71  {
72  mesh.AddVertex(parent.GetVertex(mesh_vertex_id));
73  parent_vertex_ids.Append(mesh_vertex_id);
74  }
75  submesh_v[iv] = submesh_vertex_id;
76  }
77 
78  Element *el = mesh.NewElement(from_boundary ?
79  parent.GetBdrElementType(i) : parent.GetElementType(i));
80  el->SetVertices(submesh_v);
81  el->SetAttribute(pel->GetAttribute());
82  mesh.AddElement(el);
83  parent_element_ids.Append(i);
84  }
85  return std::tuple<Array<int>, Array<int>>(parent_vertex_ids,
86  parent_element_ids);
87 }
88 
90  const FiniteElementSpace& parentfes,
91  const SubMesh::From& from,
92  const Array<int>& parent_element_ids,
93  Array<int>& vdof_to_vdof_map)
94 {
95  auto *m = subfes.GetMesh();
96  vdof_to_vdof_map.SetSize(subfes.GetVSize());
97 
98  const int vdim = parentfes.GetVDim();
99 
101  DenseMatrix T;
102  Array<int> z1;
103  for (int i = 0; i < m->GetNE(); i++)
104  {
105  Array<int> parent_vdofs;
106  if (from == SubMesh::From::Domain)
107  {
108  parentfes.GetElementVDofs(parent_element_ids[i], parent_vdofs);
109  }
110  else if (from == SubMesh::From::Boundary)
111  {
112  if (parentfes.IsDGSpace())
113  {
114  MFEM_ASSERT(static_cast<const L2_FECollection*>
115  (parentfes.FEColl())->GetBasisType() == BasisType::GaussLobatto,
116  "Only BasisType::GaussLobatto is supported for L2 spaces");
117 
118  auto pm = parentfes.GetMesh();
119 
120  int face_info, parent_volel_id;
121  pm->GetBdrElementAdjacentElement2(parent_element_ids[i],
122  parent_volel_id,
123  face_info);
124  pm->GetLocalFaceTransformation(
125  pm->GetBdrElementType(parent_element_ids[i]),
126  pm->GetElementType(parent_volel_id),
127  Tr.Transf,
128  face_info);
129 
130  Geometry::Type face_geom = pm->GetBdrElementBaseGeometry(i);
131  const FiniteElement *face_el =
132  parentfes.GetTraceElement(parent_element_ids[i], face_geom);
133  MFEM_VERIFY(dynamic_cast<const NodalFiniteElement*>(face_el),
134  "Nodal Finite Element is required");
135 
136  face_el->GetTransferMatrix(*parentfes.GetFE(parent_volel_id),
137  Tr.Transf,
138  T);
139 
140  parentfes.GetElementVDofs(parent_volel_id, z1);
141 
142  parent_vdofs.SetSize(vdim * T.Height());
143  for (int j = 0; j < T.Height(); j++)
144  {
145  for (int k = 0; k < T.Width(); k++)
146  {
147  if (T(j, k) != 0.0)
148  {
149  for (int vd=0; vd<vdim; vd++)
150  {
151  int sub_vdof = j + T.Height() * vd;
152  int parent_vdof = k + T.Width() * vd;
153  parent_vdofs[sub_vdof] =
154  z1[static_cast<int>(parent_vdof)];
155  }
156  }
157  }
158  }
159  }
160  else
161  {
162  parentfes.GetBdrElementVDofs(parent_element_ids[i], parent_vdofs);
163  }
164  }
165  else
166  {
167  MFEM_ABORT("SubMesh::From type unknown");
168  }
169 
170  Array<int> sub_vdofs;
171  subfes.GetElementVDofs(i, sub_vdofs);
172  MFEM_ASSERT(parent_vdofs.Size() == sub_vdofs.Size(), "internal error");
173  for (int j = 0; j < parent_vdofs.Size(); j++)
174  {
175  vdof_to_vdof_map[sub_vdofs[j]] = parent_vdofs[j];
176  }
177  }
178 }
179 
180 Array<int> BuildFaceMap(const Mesh& pm, const Mesh& sm,
181  const Array<int> &parent_element_ids)
182 {
183  // TODO: Check if parent is really a parent of mesh
184 
185  Array<int> pfids(sm.GetNFaces());
186  pfids = -1;
187  for (int i = 0; i < sm.GetNE(); i++)
188  {
189  int peid = parent_element_ids[i];
190 
191  Array<int> sel_faces, pel_faces, o;
192  sm.GetElementFaces(i, sel_faces, o);
193  pm.GetElementFaces(peid, pel_faces, o);
194 
195  MFEM_ASSERT(sel_faces.Size() == pel_faces.Size(), "internal error");
196 
197  for (int j = 0; j < sel_faces.Size(); j++)
198  {
199  if (pfids[sel_faces[j]] != -1)
200  {
201  MFEM_ASSERT(pfids[sel_faces[j]] == pel_faces[j], "internal error");
202  }
203  pfids[sel_faces[j]] = pel_faces[j];
204  }
205  }
206  return pfids;
207 }
208 
209 } // namespace SubMeshUtils
210 } // namespace mfem
std::unordered_map< int, int > idx
Abstract class for all finite elements.
Definition: fe_base.hpp:232
Convenience object to create unique indices.
void BuildVdofToVdofMap(const FiniteElementSpace &subfes, const FiniteElementSpace &parentfes, const SubMesh::From &from, const Array< int > &parent_element_ids, Array< int > &vdof_to_vdof_map)
Build the vdof to vdof mapping between two FiniteElementSpace objects.
virtual void GetVertices(Array< int > &v) const =0
Returns element&#39;s vertices.
Element::Type GetBdrElementType(int i) const
Returns the type of boundary element i.
Definition: mesh.cpp:6296
int GetAttribute() const
Return element&#39;s attribute.
Definition: element.hpp:55
Data type dense matrix using column-major storage.
Definition: densemat.hpp:23
const FiniteElement * GetTraceElement(int i, Geometry::Type geom_type) const
Return the trace element from element &#39;i&#39; to the given &#39;geom_type&#39;.
Definition: fespace.cpp:3175
virtual void SetVertices(const int *ind)
Set the indices the element according to the input.
Definition: element.cpp:17
const Element * GetElement(int i) const
Definition: mesh.hpp:1081
int GetNBE() const
Returns number of boundary elements.
Definition: mesh.hpp:939
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i&#39;th element in t...
Definition: fespace.cpp:2783
Element * NewElement(int geom)
Definition: mesh.cpp:3854
int Get(int i, bool &new_index)
Returns the unique index from an index set.
void GetBdrElementAdjacentElement2(int bdr_el, int &el, int &info) const
For the given boundary element, bdr_el, return its adjacent element and its info, i...
Definition: mesh.cpp:6269
int AddVertex(double x, double y=0.0, double z=0.0)
Definition: mesh.cpp:1618
void GetElementFaces(int i, Array< int > &faces, Array< int > &ori) const
Return the indices and the orientations of all faces of element i.
Definition: mesh.cpp:6161
double f(const Vector &xvec)
Definition: lor_mms.hpp:32
int Append(const T &el)
Append element &#39;el&#39; to array, resize if necessary.
Definition: array.hpp:756
const FiniteElementCollection * FEColl() const
Definition: fespace.hpp:601
const double * GetVertex(int i) const
Return pointer to vertex i&#39;s coordinates.
Definition: mesh.hpp:1053
int AddElement(Element *elem)
The parameter elem should be allocated using the NewElement() method.
Definition: mesh.cpp:1821
virtual void GetTransferMatrix(const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &I) const
Return interpolation matrix, I, which maps dofs from a coarse element, fe, to the fine dofs on this f...
Definition: fe_base.cpp:118
int GetVDim() const
Returns vector dimension.
Definition: fespace.hpp:581
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom in array dofs for i&#39;th element.
Definition: fespace.cpp:281
Mesh * GetMesh() const
Returns the mesh.
Definition: fespace.hpp:441
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:96
std::tuple< Array< int >, Array< int > > AddElementsToMesh(const Mesh &parent, Mesh &mesh, const Array< int > &attributes, bool from_boundary)
Given a Mesh parent and another Mesh mesh using the list of attributes in attributes, this function adds matching elements with those attributes from parent to mesh.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition: array.hpp:684
Array< int > BuildFaceMap(const Mesh &pm, const Mesh &sm, const Array< int > &parent_element_ids)
Given two meshes that have a parent to SubMesh relationship create a face map, using a SubMesh to par...
From
Indicator from which part of the parent Mesh the SubMesh is created.
Definition: submesh.hpp:46
int GetNE() const
Returns number of elements.
Definition: mesh.hpp:936
double a
Definition: lissajous.cpp:41
Element::Type GetElementType(int i) const
Returns the type of element i.
Definition: mesh.cpp:6291
DofTransformation * GetBdrElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom for i&#39;th boundary element.
Definition: fespace.cpp:297
bool ElementHasAttribute(const Element &el, const Array< int > &attributes)
Given an element el and a list of attributes, determine if that element is in at least one attribute ...
IsoparametricTransformation Transf
Definition: eltrans.hpp:464
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition: fespace.hpp:587
void SetAttribute(const int attr)
Set element&#39;s attribute.
Definition: element.hpp:58
int Size() const
Return the logical size of the array.
Definition: array.hpp:141
int GetNFaces() const
Return the number of faces in a 3D mesh.
Definition: mesh.hpp:945
bool IsDGSpace() const
Return whether or not the space is discontinuous (L2)
Definition: fespace.hpp:925
const Element * GetBdrElement(int i) const
Definition: mesh.hpp:1085
Abstract data type element.
Definition: element.hpp:28