MFEM  v4.5.1
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
submesh_utils.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2022, 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 
99  DenseMatrix T;
100  Array<int> z1;
101  for (int i = 0; i < m->GetNE(); i++)
102  {
103  Array<int> parent_vdofs;
104  if (from == SubMesh::From::Domain)
105  {
106  parentfes.GetElementVDofs(parent_element_ids[i], parent_vdofs);
107  }
108  else if (from == SubMesh::From::Boundary)
109  {
110  if (parentfes.IsDGSpace())
111  {
112  MFEM_ASSERT(static_cast<const L2_FECollection*>
113  (parentfes.FEColl())->GetBasisType() == BasisType::GaussLobatto,
114  "Only BasisType::GaussLobatto is supported for L2 spaces");
115 
116  auto pm = parentfes.GetMesh();
117 
118  int face_info, parent_volel_id;
119  pm->GetBdrElementAdjacentElement2(parent_element_ids[i],
120  parent_volel_id,
121  face_info);
122  pm->GetLocalFaceTransformation(
123  pm->GetBdrElementType(parent_element_ids[i]),
124  pm->GetElementType(parent_volel_id),
125  Tr.Transf,
126  face_info);
127 
128  Geometry::Type face_geom = pm->GetBdrElementBaseGeometry(i);
129  const FiniteElement *face_el =
130  parentfes.GetTraceElement(parent_element_ids[i], face_geom);
131  MFEM_VERIFY(dynamic_cast<const NodalFiniteElement*>(face_el),
132  "Nodal Finite Element is required");
133 
134  face_el->GetTransferMatrix(*parentfes.GetFE(parent_volel_id),
135  Tr.Transf,
136  T);
137 
138  parentfes.GetElementVDofs(parent_volel_id, z1);
139 
140  parent_vdofs.SetSize(parentfes.GetVDim() * T.Height());
141  for (int j = 0; j < T.Height(); j++)
142  {
143  for (int k = 0; k < parentfes.GetVDim() * T.Width(); k++)
144  {
145  if (T(j, k) != 0.0)
146  {
147  parent_vdofs[j] = z1[static_cast<int>(k)];
148  }
149  }
150  }
151  }
152  else
153  {
154  parentfes.GetBdrElementVDofs(parent_element_ids[i], parent_vdofs);
155  }
156  }
157  else
158  {
159  MFEM_ABORT("SubMesh::From type unknown");
160  }
161 
162  Array<int> sub_vdofs;
163  subfes.GetElementVDofs(i, sub_vdofs);
164  MFEM_ASSERT(parent_vdofs.Size() == sub_vdofs.Size(), "internal error");
165  for (int j = 0; j < parent_vdofs.Size(); j++)
166  {
167  vdof_to_vdof_map[sub_vdofs[j]] = parent_vdofs[j];
168  }
169  }
170 }
171 
172 Array<int> BuildFaceMap(const Mesh& pm, const Mesh& sm,
173  const Array<int> &parent_element_ids)
174 {
175  // TODO: Check if parent is really a parent of mesh
176 
177  Array<int> pfids(sm.GetNFaces());
178  pfids = -1;
179  for (int i = 0; i < sm.GetNE(); i++)
180  {
181  int peid = parent_element_ids[i];
182 
183  Array<int> sel_faces, pel_faces, o;
184  sm.GetElementFaces(i, sel_faces, o);
185  pm.GetElementFaces(peid, pel_faces, o);
186 
187  MFEM_ASSERT(sel_faces.Size() == pel_faces.Size(), "internal error");
188 
189  for (int j = 0; j < sel_faces.Size(); j++)
190  {
191  if (pfids[sel_faces[j]] != -1)
192  {
193  MFEM_ASSERT(pfids[sel_faces[j]] == pel_faces[j], "internal error");
194  }
195  pfids[sel_faces[j]] = pel_faces[j];
196  }
197  }
198  return pfids;
199 }
200 
201 } // namespace SubMeshUtils
202 } // namespace mfem
std::unordered_map< int, int > idx
Abstract class for all finite elements.
Definition: fe_base.hpp:235
int Size() const
Return the logical size of the array.
Definition: array.hpp:138
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition: fespace.hpp:587
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.
const double * GetVertex(int i) const
Return pointer to vertex i&#39;s coordinates.
Definition: mesh.hpp:1012
virtual void GetVertices(Array< int > &v) const =0
Returns element&#39;s vertices.
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:3173
int GetNBE() const
Returns number of boundary elements.
Definition: mesh.hpp:926
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition: operator.hpp:73
Element::Type GetElementType(int i) const
Returns the type of element i.
Definition: mesh.cpp:6250
Element::Type GetBdrElementType(int i) const
Returns the type of boundary element i.
Definition: mesh.cpp:6255
Data type dense matrix using column-major storage.
Definition: densemat.hpp:23
int GetNE() const
Returns number of elements.
Definition: mesh.hpp:923
virtual void SetVertices(const int *ind)
Set the indices the element according to the input.
Definition: element.cpp:17
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:6228
Element * NewElement(int geom)
Definition: mesh.cpp:3841
DofTransformation * GetBdrElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom for i&#39;th boundary element.
Definition: fespace.cpp:297
int Get(int i, bool &new_index)
Returns the unique index from an index set.
int AddVertex(double x, double y=0.0, double z=0.0)
Definition: mesh.cpp:1613
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
double f(const Vector &xvec)
Definition: lor_mms.hpp:32
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition: operator.hpp:67
int Append(const T &el)
Append element &#39;el&#39; to array, resize if necessary.
Definition: array.hpp:751
Mesh * GetMesh() const
Returns the mesh.
Definition: fespace.hpp:441
int AddElement(Element *elem)
The parameter elem should be allocated using the NewElement() method.
Definition: mesh.cpp:1809
int GetAttribute() const
Return element&#39;s attribute.
Definition: element.hpp:55
bool IsDGSpace() const
Return whether or not the space is discontinuous (L2)
Definition: fespace.hpp:925
const Element * GetElement(int i) const
Definition: mesh.hpp:1040
int GetVDim() const
Returns vector dimension.
Definition: fespace.hpp:581
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:679
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
double a
Definition: lissajous.cpp:41
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
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:2781
void SetAttribute(const int attr)
Set element&#39;s attribute.
Definition: element.hpp:58
int GetNFaces() const
Return the number of faces in a 3D mesh.
Definition: mesh.hpp:932
const FiniteElementCollection * FEColl() const
Definition: fespace.hpp:601
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
Abstract data type element.
Definition: element.hpp:28
const Element * GetBdrElement(int i) const
Definition: mesh.hpp:1044
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:6148