MFEM  v4.6.0
Finite element discretization library
linearform_ext.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 "linearform.hpp"
13 #include "../general/forall.hpp"
14 
15 namespace mfem
16 {
17 
19 
21 {
22  const FiniteElementSpace &fes = *lf->FESpace();
23  MFEM_VERIFY(lf->SupportsDevice(), "Not supported.");
24  MFEM_VERIFY(lf->Size() == fes.GetVSize(), "LinearForm size does not "
25  "match the number of vector dofs!");
26 
27  const Array<Array<int>*> &domain_integs_marker = *lf->GetDLFI_Marker();
28  const int mesh_attributes_max = fes.GetMesh()->attributes.Size() ?
29  fes.GetMesh()->attributes.Max() : 0;
30  const Array<LinearFormIntegrator*> &domain_integs = *lf->GetDLFI();
31 
32  for (int k = 0; k < domain_integs.Size(); ++k)
33  {
34  // Get the markers for this integrator
35  const Array<int> *domain_integs_marker_k = domain_integs_marker[k];
36 
37  // check if there are markers for this integrator
38  const bool has_markers_k = domain_integs_marker_k != nullptr;
39 
40  if (has_markers_k)
41  {
42  // Element attribute marker should be of length mesh->attributes
43  MFEM_VERIFY(mesh_attributes_max == domain_integs_marker_k->Size(),
44  "invalid element marker for domain linear form "
45  "integrator #" << k << ", counting from zero");
46  }
47 
48  // if there are no markers, just use the whole linear form (1)
49  if (!has_markers_k) { markers.HostReadWrite(); markers = 1; }
50  else
51  {
52  // scan the attributes to set the markers to 0 or 1
53  const int NE = fes.GetNE();
54  const auto attr = attributes.Read();
55  const auto dimk = domain_integs_marker_k->Read();
56  auto markers_w = markers.Write();
57  mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
58  {
59  markers_w[e] = dimk[attr[e]-1] == 1;
60  });
61  }
62 
63  // Assemble the linear form
64  b = 0.0;
65  domain_integs[k]->AssembleDevice(fes, markers, b);
66  if (k == 0) { elem_restrict_lex->MultTranspose(b, *lf); }
67  else { elem_restrict_lex->AddMultTranspose(b, *lf); }
68  }
69 
70  const Array<Array<int>*> &boundary_integs_marker = lf->boundary_integs_marker;
71  const int bdr_attributes_max = fes.GetMesh()->bdr_attributes.Size() ?
72  fes.GetMesh()->bdr_attributes.Max() : 0;
73  const Array<LinearFormIntegrator*> &boundary_integs = lf->boundary_integs;
74 
75  for (int k = 0; k < boundary_integs.Size(); ++k)
76  {
77  // Get the markers for this integrator
78  const Array<int> *boundary_integs_marker_k = boundary_integs_marker[k];
79 
80  // check if there are markers for this integrator
81  const bool has_markers_k = boundary_integs_marker_k != nullptr;
82 
83  if (has_markers_k)
84  {
85  // Element attribute marker should be of length mesh->attributes
86  MFEM_VERIFY(bdr_attributes_max == boundary_integs_marker_k->Size(),
87  "invalid boundary marker for boundary linear form "
88  "integrator #" << k << ", counting from zero");
89  }
90 
91  // if there are no markers, just use the whole linear form (1)
92  if (!has_markers_k) { bdr_markers.HostReadWrite(); bdr_markers = 1; }
93  else
94  {
95  // scan the attributes to set the markers to 0 or 1
96  const int NBE = bdr_attributes.Size();
97  const auto attr = bdr_attributes.Read();
98  const auto attr_markers = boundary_integs_marker_k->Read();
99  auto markers_w = bdr_markers.Write();
100  mfem::forall(NBE, [=] MFEM_HOST_DEVICE (int e)
101  {
102  markers_w[e] = attr_markers[attr[e]-1] == 1;
103  });
104  }
105 
106  // Assemble the linear form
107  bdr_b = 0.0;
108  boundary_integs[k]->AssembleDevice(fes, bdr_markers, bdr_b);
109  bdr_restrict_lex->AddMultTranspose(bdr_b, *lf);
110  }
111 }
112 
114 {
115  const FiniteElementSpace &fes = *lf->FESpace();
116  const Mesh &mesh = *fes.GetMesh();
118 
119  MFEM_VERIFY(lf->Size() == fes.GetVSize(), "");
120 
121  if (lf->domain_integs.Size() > 0)
122  {
123  const int NE = fes.GetNE();
124  markers.SetSize(NE);
125  //markers.UseDevice(true);
126 
127  // Gather the attributes on the host from all the elements
128  attributes.SetSize(NE);
129  for (int i = 0; i < NE; ++i) { attributes[i] = mesh.GetAttribute(i); }
130 
131  elem_restrict_lex = fes.GetElementRestriction(ordering);
132  MFEM_VERIFY(elem_restrict_lex, "Element restriction not available");
133  b.SetSize(elem_restrict_lex->Height(), Device::GetMemoryType());
134  b.UseDevice(true);
135  }
136 
137  if (lf->boundary_integs.Size() > 0)
138  {
139  const int nf_bdr = fes.GetNFbyType(FaceType::Boundary);
140  bdr_markers.SetSize(nf_bdr);
141  // bdr_markers.UseDevice(true);
142 
143  // The face restriction will give us "face E-vectors" on the boundary that
144  // are numbered in the order of the faces of mesh. This numbering will be
145  // different than the numbering of the boundary elements. We compute
146  // mappings so that the array `bdr_attributes[i]` gives the boundary
147  // attribute of the `i`th boundary face in the mesh face order.
148  std::unordered_map<int,int> f_to_be;
149  for (int i = 0; i < mesh.GetNBE(); ++i)
150  {
151  const int f = mesh.GetBdrElementEdgeIndex(i);
152  f_to_be[f] = i;
153  }
154  MFEM_VERIFY(size_t(nf_bdr) == f_to_be.size(), "Incompatible sizes");
155  bdr_attributes.SetSize(nf_bdr);
156  int f_ind = 0;
157  for (int f = 0; f < mesh.GetNumFaces(); ++f)
158  {
159  if (f_to_be.find(f) != f_to_be.end())
160  {
161  const int be = f_to_be[f];
162  bdr_attributes[f_ind] = mesh.GetBdrAttribute(be);
163  ++f_ind;
164  }
165  }
166 
167  bdr_restrict_lex =
168  dynamic_cast<const FaceRestriction*>(
171  MFEM_VERIFY(bdr_restrict_lex, "Face restriction not available");
172  bdr_b.SetSize(bdr_restrict_lex->Height(), Device::GetMemoryType());
173  bdr_b.UseDevice(true);
174  }
175 }
176 
177 } // namespace mfem
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Definition: array.hpp:307
LinearFormExtension(LinearForm *lf)
Create a LinearForm extension of lf.
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
Definition: operator.hpp:93
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
Definition: array.hpp:327
int GetBdrElementEdgeIndex(int i) const
Definition: mesh.cpp:6588
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
Definition: mesh.cpp:5668
void SetSize(int s)
Resize the vector to size s.
Definition: vector.hpp:517
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition: vector.hpp:115
virtual const FaceRestriction * GetFaceRestriction(ElementDofOrdering f_ordering, FaceType, L2FaceValues mul=L2FaceValues::DoubleValued) const
Return an Operator that converts L-vectors to E-vectors on each face.
Definition: fespace.cpp:1335
int Size() const
Returns the size of the vector.
Definition: vector.hpp:197
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition: array.cpp:68
virtual bool SupportsDevice() const
Return true if assembly on device is supported, false otherwise.
Definition: linearform.cpp:104
void AddMultTranspose(const Vector &x, Vector &y, const double a=1.0) const override=0
Add the E-vector degrees of freedom x to the L-vector degrees of freedom y.
int GetNBE() const
Returns number of boundary elements.
Definition: mesh.hpp:1089
FiniteElementSpace * FESpace()
Read+write access to the associated FiniteElementSpace.
Definition: linearform.hpp:129
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
Definition: fespace.cpp:1302
int GetNFbyType(FaceType type) const
Returns the number of faces according to the requested type.
Definition: fespace.hpp:753
std::function< double(const Vector &)> f(double mass_coeff)
Definition: lor_mms.hpp:30
int GetAttribute(int i) const
Return the attribute of element i.
Definition: mesh.hpp:1190
virtual void AddMultTranspose(const Vector &x, Vector &y, const double a=1.0) const override=0
Add the face degrees of freedom x to the element degrees of freedom y.
static MemoryType GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
Definition: device.hpp:277
Array< LinearFormIntegrator * > domain_integs
Set of Domain Integrators to be applied.
Definition: linearform.hpp:45
void Update()
Update the linear form extension.
int GetNE() const
Returns number of elements in the mesh.
Definition: fespace.hpp:736
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
Definition: mesh.hpp:1196
Mesh * GetMesh() const
Returns the mesh.
Definition: fespace.hpp:555
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition: mesh.hpp:275
void forall(int N, lambda &&body)
Definition: forall.hpp:742
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:219
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition: array.hpp:687
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition: operator.hpp:66
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
Definition: fespace.hpp:74
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition: fespace.hpp:709
Lexicographic ordering for tensor-product FiniteElements.
int Size() const
Return the logical size of the array.
Definition: array.hpp:141
T * Write(bool on_dev=true)
Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
Definition: array.hpp:315
Array< LinearFormIntegrator * > boundary_integs
Set of Boundary Integrators to be applied.
Definition: linearform.hpp:57
Vector with associated FE space and LinearFormIntegrators.
Definition: linearform.hpp:24
Array< Array< int > * > boundary_integs_marker
Entries are not owned.
Definition: linearform.hpp:59
Array< Array< int > * > * GetDLFI_Marker()
Access all domain markers added with AddDomainIntegrator(). If no marker was specified when the integ...
Definition: linearform.hpp:173
Base class for operators that extracts Face degrees of freedom.
Array< LinearFormIntegrator * > * GetDLFI()
Access all integrators added with AddDomainIntegrator() which are not DeltaLFIntegrators or they are ...
Definition: linearform.hpp:168
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Definition: mesh.hpp:273