MFEM  v4.3.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
marking.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2021, 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 "marking.hpp"
13 
14 namespace mfem
15 {
16 
18 {
19  elem_marker.SetSize(pmesh.GetNE() + pmesh.GetNSharedFaces());
20  elem_marker = SBElementType::INSIDE;
21 
23 
24  Vector vals;
25  // Check elements on the current MPI rank
26  for (int i = 0; i < pmesh.GetNE(); i++)
27  {
29  const IntegrationRule &ir =
30  IntRulesLo.Get(pmesh.GetElementBaseGeometry(i), 4*Tr->OrderJ());
31  ls_func.GetValues(i, ir, vals);
32 
33  int count = 0;
34  for (int j = 0; j < ir.GetNPoints(); j++)
35  {
36  if (vals(j) <= 0.) { count++; }
37  }
38 
39  if (count == ir.GetNPoints()) // completely outside
40  {
41  elem_marker[i] = SBElementType::OUTSIDE;
42  }
43  else if (count > 0) // partially outside
44  {
45  elem_marker[i] = SBElementType::CUT;
46  }
47  }
48 
49  // Check neighbors on the adjacent MPI rank
50  for (int i = pmesh.GetNE(); i < pmesh.GetNE()+pmesh.GetNSharedFaces(); i++)
51  {
52  int shared_fnum = i-pmesh.GetNE();
55  int Elem2NbrNo = tr->Elem2No - pmesh.GetNE();
56 
57  ElementTransformation *eltr =
59  const IntegrationRule &ir =
60  IntRulesLo.Get(pmesh.GetElementBaseGeometry(0),
61  4*eltr->OrderJ());
62 
63  const int nip = ir.GetNPoints();
64  vals.SetSize(nip);
65  int count = 0;
66  for (int j = 0; j < nip; j++)
67  {
68  const IntegrationPoint &ip = ir.IntPoint(j);
69  vals[j] = ls_func.GetValue(tr->Elem2No, ip);
70  if (vals[j] <= 0.) { count++; }
71  }
72 
73  if (count == ir.GetNPoints()) // completely outside
74  {
75  elem_marker[i] = SBElementType::OUTSIDE;
76  }
77  else if (count > 0) // partially outside
78  {
79  elem_marker[i] = SBElementType::CUT;
80  }
81  }
82 }
83 
85  Array<int> &sface_dof_list) const
86 {
87  if (func_dof_marking)
88  {
89  ListShiftedFaceDofs2(elem_marker, sface_dof_list);
90  return;
91  }
92 
93  sface_dof_list.DeleteAll();
94  Array<int> dofs; // work array
95 
96  // First we check interior faces of the mesh (excluding interior faces that
97  // are on the processor boundaries)
98  for (int f = 0; f < pmesh.GetNumFaces(); f++)
99  {
101  if (tr != NULL)
102  {
103  int te1 = elem_marker[tr->Elem1No], te2 = elem_marker[tr->Elem2No];
104  if (!include_cut_cell &&
106  {
107  pfes_sltn.GetFaceDofs(f, dofs);
108  sface_dof_list.Append(dofs);
109  }
110  if (!include_cut_cell &&
112  {
113  pfes_sltn.GetFaceDofs(f, dofs);
114  sface_dof_list.Append(dofs);
115  }
116  if (include_cut_cell &&
117  te1 == SBElementType::CUT && te2 == SBElementType::OUTSIDE)
118  {
119  pfes_sltn.GetFaceDofs(f, dofs);
120  sface_dof_list.Append(dofs);
121  }
122  if (include_cut_cell &&
123  te1 == SBElementType::OUTSIDE && te2 == SBElementType::CUT)
124  {
125  pfes_sltn.GetFaceDofs(f, dofs);
126  sface_dof_list.Append(dofs);
127  }
128  }
129  }
130 
131  // Add boundary faces that we want to model as SBM faces.
132  if (include_cut_cell)
133  {
134  for (int i = 0; i < pmesh.GetNBE(); i++)
135  {
137  if (tr != NULL)
138  {
139  if (elem_marker[tr->Elem1No] == SBElementType::CUT)
140  {
142  sface_dof_list.Append(dofs);
143  }
144  }
145  }
146  }
147 
148  // Now we add interior faces that are on processor boundaries.
149  for (int i = 0; i < pmesh.GetNSharedFaces(); i++)
150  {
152  if (tr != NULL)
153  {
154  int ne1 = tr->Elem1No;
155  int te1 = elem_marker[ne1];
156  int te2 = elem_marker[i+pmesh.GetNE()];
157  const int faceno = pmesh.GetSharedFace(i);
158  // Add if the element on this MPI rank is completely inside the domain
159  // and the element on other MPI rank is not.
160  if (!include_cut_cell &&
162  {
163  pfes_sltn.GetFaceDofs(faceno, dofs);
164  sface_dof_list.Append(dofs);
165  }
166  if (include_cut_cell &&
167  te2 == SBElementType::OUTSIDE && te1 == SBElementType::CUT)
168  {
169  pfes_sltn.GetFaceDofs(faceno, dofs);
170  sface_dof_list.Append(dofs);
171  }
172  }
173  }
174 }
175 
176 // Determine the list of true (i.e. conforming) essential boundary dofs. To do
177 // this, we first make a list of all dofs that are on the real boundary of the
178 // mesh, then add all the dofs of the elements that are completely outside or
179 // intersect shifted boundary. Then we remove the dofs from SBM faces
181  const Array<int> &sface_dof_list,
182  Array<int> &ess_tdof_list,
183  Array<int> &ess_shift_bdr) const
184 {
185  // Change the attribute of SBM faces that are on the boundary.
186  Array<int> ess_bdr(pmesh.bdr_attributes.Max());
187  int pmesh_bdr_attr_max = 0;
188  if (ess_bdr.Size())
189  {
190  pmesh_bdr_attr_max = pmesh.bdr_attributes.Max();
191  ess_bdr = 1;
192  }
193  bool sbm_at_true_boundary = false;
194  if (include_cut_cell)
195  {
196  for (int i = 0; i < pmesh.GetNBE(); i++)
197  {
199  if (tr != NULL)
200  {
201  if (elem_marker[tr->Elem1No] == SBElementType::CUT)
202  {
203  pmesh.SetBdrAttribute(i, pmesh_bdr_attr_max+1);
204  sbm_at_true_boundary = true;
205  }
206  }
207  }
208  }
209  bool sbm_at_true_boundary_global = false;
210  MPI_Allreduce(&sbm_at_true_boundary, &sbm_at_true_boundary_global, 1,
211  MPI_C_BOOL, MPI_LOR, MPI_COMM_WORLD);
212  if (sbm_at_true_boundary_global)
213  {
214  ess_bdr.Append(0);
216  }
217 
218  // Make a list of dofs on all boundaries
219  ess_shift_bdr.SetSize(ess_bdr.Size());
220  if (pmesh.bdr_attributes.Size())
221  {
222  for (int i = 0; i < ess_bdr.Size(); i++)
223  {
224  ess_shift_bdr[i] = 1 - ess_bdr[i];
225  }
226  }
227  Array<int> ess_vdofs_bdr;
228  pfes_sltn.GetEssentialVDofs(ess_bdr, ess_vdofs_bdr);
229 
230  // Get all dofs associated with elements outside the domain or intersected by
231  // the boundary.
232  Array<int> ess_vdofs(ess_vdofs_bdr.Size()), dofs;
233  ess_vdofs = 0;
234  for (int e = 0; e < pmesh.GetNE(); e++)
235  {
236  if (!include_cut_cell &&
237  (elem_marker[e] == SBElementType::OUTSIDE ||
238  elem_marker[e] == SBElementType::CUT))
239  {
240  pfes_sltn.GetElementVDofs(e, dofs);
241  for (int i = 0; i < dofs.Size(); i++)
242  {
243  ess_vdofs[dofs[i]] = -1;
244  }
245  }
246  if (include_cut_cell &&
247  elem_marker[e] == SBElementType::OUTSIDE)
248  {
249  pfes_sltn.GetElementVDofs(e, dofs);
250  for (int i = 0; i < dofs.Size(); i++)
251  {
252  ess_vdofs[dofs[i]] = -1;
253  }
254  }
255  }
256 
257  // Combine the lists to mark essential dofs.
258  for (int i = 0; i < ess_vdofs.Size(); i++)
259  {
260  if (ess_vdofs_bdr[i] == -1) { ess_vdofs[i] = -1; }
261  }
262 
263  // Unmark dofs that are on SBM faces (but not on Dirichlet boundaries)
264  for (int i = 0; i < sface_dof_list.Size(); i++)
265  {
266  if (ess_vdofs_bdr[sface_dof_list[i]] != -1)
267  {
268  ess_vdofs[sface_dof_list[i]] = 0;
269  }
270  }
271 
272  // Synchronize
273  for (int i = 0; i < ess_vdofs.Size() ; i++) { ess_vdofs[i] += 1; }
274  pfes_sltn.Synchronize(ess_vdofs);
275  for (int i = 0; i < ess_vdofs.Size() ; i++) { ess_vdofs[i] -= 1; }
276 
277  // Convert to tdofs
278  Array<int> ess_tdofs;
279  pfes_sltn.GetRestrictionMatrix()->BooleanMult(ess_vdofs, ess_tdofs);
280  pfes_sltn.MarkerToList(ess_tdofs, ess_tdof_list);
281 }
282 
284  Array<int> &sface_dof_list) const
285 {
286  sface_dof_list.DeleteAll();
287 
288  L2_FECollection mat_coll(0, pmesh.Dimension());
289  ParFiniteElementSpace mat_fes(&pmesh, &mat_coll);
290  ParGridFunction mat(&mat_fes);
291  ParGridFunction marker_gf(&pfes_sltn);
292  for (int i = 0; i < pmesh.GetNE(); i++)
293  {
294  // 0 is inside, 1 is outside.
295  mat(i) = 0.0;
296  if (elem_marker[i] == SBElementType::OUTSIDE)
297  { mat(i) = 1.0; }
298  if (elem_marker[i] == SBElementType::CUT && include_cut_cell == false)
299  { mat(i) = 1.0; }
300  }
301 
302  GridFunctionCoefficient coeff_mat(&mat);
303  marker_gf.ProjectDiscCoefficient(coeff_mat, GridFunction::ARITHMETIC);
304 
305  for (int j = 0; j < marker_gf.Size(); j++)
306  {
307  if (marker_gf(j) > 0.1 && marker_gf(j) < 0.9)
308  {
309  sface_dof_list.Append(j);
310  }
311  }
312 
313  // Add boundary faces that we want to model as SBM faces.
314  if (include_cut_cell)
315  {
316  Array<int> dofs;
317  for (int i = 0; i < pmesh.GetNBE(); i++)
318  {
320  if (tr != NULL)
321  {
322  if (elem_marker[tr->Elem1No] == SBElementType::CUT)
323  {
325  sface_dof_list.Append(dofs);
326  }
327  }
328  }
329  }
330 }
331 
332 }
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition: intrules.hpp:247
int Size() const
Return the logical size of the array.
Definition: array.hpp:134
Class for an integration rule - an Array of IntegrationPoint.
Definition: intrules.hpp:90
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
Definition: intrules.cpp:920
IntegrationRules IntRulesLo(0, Quadrature1D::GaussLobatto)
virtual void GetEssentialVDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_dofs, int component=-1) const
Determine the boundary degrees of freedom.
Definition: pfespace.cpp:776
void SetSize(int s)
Resize the vector to size s.
Definition: vector.hpp:513
int GetNBE() const
Returns number of boundary elements.
Definition: mesh.hpp:849
void GetElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom in array dofs for i&#39;th element.
Definition: fespace.cpp:262
void BooleanMult(const Array< int > &x, Array< int > &y) const
y = A * x, treating all entries as booleans (zero=false, nonzero=true).
Definition: sparsemat.cpp:880
ParFiniteElementSpace & pfes_sltn
Definition: marking.hpp:27
int GetNSharedFaces() const
Return the number of shared faces (3D), edges (2D), vertices (1D)
Definition: pmesh.cpp:2731
A specialized ElementTransformation class representing a face and its two neighboring elements...
Definition: eltrans.hpp:467
Coefficient defined by a GridFunction. This coefficient is mesh dependent.
Container class for integration rules.
Definition: intrules.hpp:311
int Size() const
Returns the size of the vector.
Definition: vector.hpp:190
int GetNE() const
Returns number of elements.
Definition: mesh.hpp:846
virtual double GetValue(int i, const IntegrationPoint &ip, int vdim=1) const
Definition: pgridfunc.cpp:264
virtual void ProjectDiscCoefficient(VectorCoefficient &coeff)
Project a discontinuous vector coefficient as a grid function on a continuous finite element space...
Definition: pgridfunc.cpp:514
void MarkElements(Array< int > &elem_marker) const
Mark all the elements in the mesh using the SBElementType.
Definition: marking.cpp:17
Abstract parallel finite element space.
Definition: pfespace.hpp:28
void Synchronize(Array< int > &ldof_marker) const
Given an integer array on the local degrees of freedom, perform a bitwise OR between the shared dofs...
Definition: pfespace.cpp:764
virtual void SetAttributes()
Definition: pmesh.cpp:1574
FaceElementTransformations * GetInteriorFaceTransformations(int FaceNo)
Definition: mesh.hpp:1153
virtual int OrderJ() const =0
Return the order of the elements of the Jacobian of the transformation.
Geometry::Type GetElementBaseGeometry(int i) const
Definition: mesh.hpp:971
void DeleteAll()
Delete the whole array.
Definition: array.hpp:841
static void MarkerToList(const Array< int > &marker, Array< int > &list)
Convert a Boolean marker array to a list containing all marked indices.
Definition: fespace.cpp:540
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
Definition: mesh.cpp:4915
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition: intrules.hpp:250
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:746
int GetSharedFace(int sface) const
Return the local face index for the given shared face.
Definition: pmesh.cpp:2750
void ListShiftedFaceDofs(const Array< int > &elem_marker, Array< int > &sface_dof_list) const
Definition: marking.cpp:84
FaceElementTransformations * GetSharedFaceTransformations(int sf, bool fill2=true)
Definition: pmesh.cpp:2622
void ListEssentialTDofs(const Array< int > &elem_marker, const Array< int > &sface_dof_list, Array< int > &ess_tdof_list, Array< int > &ess_shift_bdr) const
Definition: marking.cpp:180
T Max() const
Find the maximal element in the array, using the comparison operator &lt; for class T.
Definition: array.cpp:68
void GetValues(int i, const IntegrationRule &ir, Vector &vals, int vdim=1) const
Definition: gridfunc.cpp:466
FaceElementTransformations * GetBdrFaceTransformations(int BdrElemNo)
Definition: mesh.cpp:1020
int Dimension() const
Definition: mesh.hpp:911
void ListShiftedFaceDofs2(const Array< int > &elem_marker, Array< int > &sface_dof_list) const
Definition: marking.cpp:283
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition: mesh.hpp:204
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition: array.hpp:674
void SetBdrAttribute(int i, int attr)
Set the attribute of boundary element i.
Definition: mesh.hpp:1206
void GetFaceNbrElementTransformation(int i, IsoparametricTransformation *ElTr)
Definition: pmesh.cpp:1879
Class for integration point with weight.
Definition: intrules.hpp:25
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
Definition: mesh.cpp:347
virtual const SparseMatrix * GetRestrictionMatrix() const
Get the R matrix which restricts a local dof vector to true dof vector.
Definition: pfespace.hpp:379
virtual int GetFaceDofs(int i, Array< int > &dofs, int variant=0) const
Definition: pfespace.cpp:495
const bool func_dof_marking
Definition: marking.hpp:31
Vector data type.
Definition: vector.hpp:60
int GetBdrFace(int BdrElemNo) const
Return the local face index for the given boundary face.
Definition: mesh.cpp:1037
ParGridFunction & ls_func
Definition: marking.hpp:26
Class for parallel grid function.
Definition: pgridfunc.hpp:32
Arbitrary order &quot;L2-conforming&quot; discontinuous finite elements.
Definition: fe_coll.hpp:285