MFEM  v4.4.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
linearform.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 // Implementation of class LinearForm
13 
14 #include "fem.hpp"
15 
16 namespace mfem
17 {
18 
20  : Vector(f->GetVSize())
21 {
22  // Linear forms are stored on the device
23  UseDevice(true);
24 
25  fes = f;
26  extern_lfs = 1;
27 
28  // Copy the pointers to the integrators
30 
32 
34 
37 }
38 
40 {
41  DeltaLFIntegrator *maybe_delta =
42  dynamic_cast<DeltaLFIntegrator *>(lfi);
43  if (!maybe_delta || !maybe_delta->IsDelta())
44  {
45  domain_integs.Append(lfi);
46  }
47  else
48  {
49  domain_delta_integs.Append(maybe_delta);
50  }
51  domain_integs_marker.Append(NULL);
52 }
53 
55  Array<int> &elem_marker)
56 {
57  DeltaLFIntegrator *maybe_delta =
58  dynamic_cast<DeltaLFIntegrator *>(lfi);
59  if (!maybe_delta || !maybe_delta->IsDelta())
60  {
61  domain_integs.Append(lfi);
62  }
63  else
64  {
65  domain_delta_integs.Append(maybe_delta);
66  }
67  domain_integs_marker.Append(&elem_marker);
68 }
69 
71 {
72  boundary_integs.Append (lfi);
73  boundary_integs_marker.Append(NULL); // NULL -> all attributes are active
74 }
75 
77  Array<int> &bdr_attr_marker)
78 {
79  boundary_integs.Append (lfi);
80  boundary_integs_marker.Append(&bdr_attr_marker);
81 }
82 
84 {
85  boundary_face_integs.Append(lfi);
86  // NULL -> all attributes are active
87  boundary_face_integs_marker.Append(NULL);
88 }
89 
91  Array<int> &bdr_attr_marker)
92 {
93  boundary_face_integs.Append(lfi);
94  boundary_face_integs_marker.Append(&bdr_attr_marker);
95 }
96 
98 {
99  interior_face_integs.Append(lfi);
100 }
101 
103 {
104  Array<int> vdofs;
105  ElementTransformation *eltrans;
106  DofTransformation *doftrans;
107  Vector elemvect;
108 
109  Vector::operator=(0.0);
110 
111  // The above operation is executed on device because of UseDevice().
112  // The first use of AddElementVector() below will move it back to host
113  // because both 'vdofs' and 'elemvect' are on host.
114 
115  if (domain_integs.Size())
116  {
117  for (int k = 0; k < domain_integs.Size(); k++)
118  {
119  if (domain_integs_marker[k] != NULL)
120  {
121  MFEM_VERIFY(domain_integs_marker[k]->Size() ==
122  (fes->GetMesh()->attributes.Size() ?
123  fes->GetMesh()->attributes.Max() : 0),
124  "invalid element marker for domain linear form "
125  "integrator #" << k << ", counting from zero");
126  }
127  }
128 
129  for (int i = 0; i < fes -> GetNE(); i++)
130  {
131  int elem_attr = fes->GetMesh()->GetAttribute(i);
132  for (int k = 0; k < domain_integs.Size(); k++)
133  {
134  if ( domain_integs_marker[k] == NULL ||
135  (*(domain_integs_marker[k]))[elem_attr-1] == 1 )
136  {
137  doftrans = fes -> GetElementVDofs (i, vdofs);
138  eltrans = fes -> GetElementTransformation (i);
139  domain_integs[k]->AssembleRHSElementVect(*fes->GetFE(i),
140  *eltrans, elemvect);
141  if (doftrans)
142  {
143  doftrans->TransformDual(elemvect);
144  }
145  AddElementVector (vdofs, elemvect);
146  }
147  }
148  }
149  }
150  AssembleDelta();
151 
152  if (boundary_integs.Size())
153  {
154  Mesh *mesh = fes->GetMesh();
155 
156  // Which boundary attributes need to be processed?
157  Array<int> bdr_attr_marker(mesh->bdr_attributes.Size() ?
158  mesh->bdr_attributes.Max() : 0);
159  bdr_attr_marker = 0;
160  for (int k = 0; k < boundary_integs.Size(); k++)
161  {
162  if (boundary_integs_marker[k] == NULL)
163  {
164  bdr_attr_marker = 1;
165  break;
166  }
167  Array<int> &bdr_marker = *boundary_integs_marker[k];
168  MFEM_ASSERT(bdr_marker.Size() == bdr_attr_marker.Size(),
169  "invalid boundary marker for boundary integrator #"
170  << k << ", counting from zero");
171  for (int i = 0; i < bdr_attr_marker.Size(); i++)
172  {
173  bdr_attr_marker[i] |= bdr_marker[i];
174  }
175  }
176 
177  for (int i = 0; i < fes -> GetNBE(); i++)
178  {
179  const int bdr_attr = mesh->GetBdrAttribute(i);
180  if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
181  doftrans = fes -> GetBdrElementVDofs (i, vdofs);
182  eltrans = fes -> GetBdrElementTransformation (i);
183  for (int k=0; k < boundary_integs.Size(); k++)
184  {
185  if (boundary_integs_marker[k] &&
186  (*boundary_integs_marker[k])[bdr_attr-1] == 0) { continue; }
187 
188  boundary_integs[k]->AssembleRHSElementVect(*fes->GetBE(i),
189  *eltrans, elemvect);
190 
191  if (doftrans)
192  {
193  doftrans->TransformDual(elemvect);
194  }
195  AddElementVector (vdofs, elemvect);
196  }
197  }
198  }
199  if (boundary_face_integs.Size())
200  {
202  Mesh *mesh = fes->GetMesh();
203 
204  // Which boundary attributes need to be processed?
205  Array<int> bdr_attr_marker(mesh->bdr_attributes.Size() ?
206  mesh->bdr_attributes.Max() : 0);
207  bdr_attr_marker = 0;
208  for (int k = 0; k < boundary_face_integs.Size(); k++)
209  {
210  if (boundary_face_integs_marker[k] == NULL)
211  {
212  bdr_attr_marker = 1;
213  break;
214  }
215  Array<int> &bdr_marker = *boundary_face_integs_marker[k];
216  MFEM_ASSERT(bdr_marker.Size() == bdr_attr_marker.Size(),
217  "invalid boundary marker for boundary face integrator #"
218  << k << ", counting from zero");
219  for (int i = 0; i < bdr_attr_marker.Size(); i++)
220  {
221  bdr_attr_marker[i] |= bdr_marker[i];
222  }
223  }
224 
225  for (int i = 0; i < mesh->GetNBE(); i++)
226  {
227  const int bdr_attr = mesh->GetBdrAttribute(i);
228  if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
229 
230  tr = mesh->GetBdrFaceTransformations(i);
231  if (tr != NULL)
232  {
233  fes -> GetElementVDofs (tr -> Elem1No, vdofs);
234  for (int k = 0; k < boundary_face_integs.Size(); k++)
235  {
237  (*boundary_face_integs_marker[k])[bdr_attr-1] == 0)
238  { continue; }
239 
241  AssembleRHSElementVect(*fes->GetFE(tr->Elem1No),
242  *tr, elemvect);
243  AddElementVector (vdofs, elemvect);
244  }
245  }
246  }
247  }
248 
249  if (interior_face_integs.Size())
250  {
251  Mesh *mesh = fes->GetMesh();
252 
253  for (int k = 0; k < interior_face_integs.Size(); k++)
254  {
255  for (int i = 0; i < mesh->GetNumFaces(); i++)
256  {
257  FaceElementTransformations *tr = NULL;
258  tr = mesh->GetInteriorFaceTransformations (i);
259  if (tr != NULL)
260  {
261  fes -> GetElementVDofs (tr -> Elem1No, vdofs);
262  Array<int> vdofs2;
263  fes -> GetElementVDofs (tr -> Elem2No, vdofs2);
264  vdofs.Append(vdofs2);
266  AssembleRHSElementVect(*fes->GetFE(tr->Elem1No),
267  *fes->GetFE(tr->Elem2No),
268  *tr, elemvect);
269  AddElementVector (vdofs, elemvect);
270  }
271  }
272  }
273  }
274 }
275 
277 {
278  MFEM_ASSERT(v.Size() >= v_offset + f->GetVSize(), "");
279  fes = f;
280  v.UseDevice(true);
281  this->Vector::MakeRef(v, v_offset, fes->GetVSize());
283 }
284 
286 {
287  Update(f, v, v_offset);
288 }
289 
291 {
292  if (domain_delta_integs.Size() == 0) { return; }
293 
294  if (!HaveDeltaLocations())
295  {
296  int sdim = fes->GetMesh()->SpaceDimension();
297  Vector center;
298  DenseMatrix centers(sdim, domain_delta_integs.Size());
299  for (int i = 0; i < centers.Width(); i++)
300  {
301  centers.GetColumnReference(i, center);
302  domain_delta_integs[i]->GetDeltaCenter(center);
303  MFEM_VERIFY(center.Size() == sdim,
304  "Point dim " << center.Size() <<
305  " does not match space dim " << sdim);
306  }
309  }
310 
311  Array<int> vdofs;
312  Vector elemvect;
313  for (int i = 0; i < domain_delta_integs.Size(); i++)
314  {
315  int elem_id = domain_delta_integs_elem_id[i];
316  // The delta center may be outside of this sub-domain, or
317  // (Par)Mesh::FindPoints() failed to find this point:
318  if (elem_id < 0) { continue; }
319 
322  Trans.SetIntPoint(&ip);
323 
324  fes->GetElementVDofs(elem_id, vdofs);
325  domain_delta_integs[i]->AssembleDeltaElementVect(*fes->GetFE(elem_id),
326  Trans, elemvect);
327  AddElementVector(vdofs, elemvect);
328  }
329 }
330 
332 {
333  Vector::operator=(value);
334  return *this;
335 }
336 
338 {
339  MFEM_ASSERT(fes && v.Size() == fes->GetVSize(), "");
341  return *this;
342 }
343 
345 {
346  if (!extern_lfs)
347  {
348  int k;
349  for (k=0; k < domain_delta_integs.Size(); k++)
350  { delete domain_delta_integs[k]; }
351  for (k=0; k < domain_integs.Size(); k++) { delete domain_integs[k]; }
352  for (k=0; k < boundary_integs.Size(); k++) { delete boundary_integs[k]; }
353  for (k=0; k < boundary_face_integs.Size(); k++)
354  { delete boundary_face_integs[k]; }
355  for (k=0; k < interior_face_integs.Size(); k++)
356  { delete interior_face_integs[k]; }
357  }
358 }
359 
360 }
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:563
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
Definition: mesh.hpp:1461
int GetNBE() const
Returns number of boundary elements.
Definition: mesh.hpp:931
virtual void MakeRef(FiniteElementSpace *f, Vector &v, int v_offset)
Make the LinearForm reference external data on a new FiniteElementSpace.
Definition: linearform.cpp:285
Array< Array< int > * > boundary_face_integs_marker
Entries not owned.
Definition: linearform.hpp:53
void Assemble()
Assembles the linear form i.e. sums over all domain/bdr integrators.
Definition: linearform.cpp:102
int extern_lfs
Indicates the LinearFormIntegrators stored in domain_integs, domain_delta_integs, boundary_integs...
Definition: linearform.hpp:32
LinearForm & operator=(const LinearForm &rhs)
Copy assignment. Only the data of the base class Vector is copied.
Definition: linearform.hpp:110
void SetIntPoint(const IntegrationPoint *ip)
Set the integration point ip that weights and Jacobians will be evaluated at.
Definition: eltrans.hpp:93
A specialized ElementTransformation class representing a face and its two neighboring elements...
Definition: eltrans.hpp:480
Data type dense matrix using column-major storage.
Definition: densemat.hpp:23
Array< IntegrationPoint > domain_delta_integs_ip
The reference coordinates where the centers of the delta functions lie.
Definition: linearform.hpp:62
int Size() const
Returns the size of the vector.
Definition: vector.hpp:199
void ResetDeltaLocations()
Force (re)computation of delta locations.
Definition: linearform.hpp:69
void AddInteriorFaceIntegrator(LinearFormIntegrator *lfi)
Adds new Interior Face Integrator. Assumes ownership of lfi.
Definition: linearform.cpp:97
Array< int > domain_delta_integs_elem_id
The element ids where the centers of the delta functions lie.
Definition: linearform.hpp:59
Array< LinearFormIntegrator * > boundary_face_integs
Set of Boundary Face Integrators to be applied.
Definition: linearform.hpp:52
FaceElementTransformations * GetInteriorFaceTransformations(int FaceNo)
Definition: mesh.hpp:1245
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition: vector.hpp:117
Abstract base class LinearFormIntegrator.
Definition: lininteg.hpp:22
Vector & operator=(const double *v)
Copy Size() entries from v.
Definition: vector.cpp:124
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
Definition: mesh.cpp:5345
Array< LinearFormIntegrator * > interior_face_integs
Set of Internal Face Integrators to be applied.
Definition: linearform.hpp:56
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 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:433
Array< LinearFormIntegrator * > domain_integs
Set of Domain Integrators to be applied.
Definition: linearform.hpp:35
T Max() const
Find the maximal element in the array, using the comparison operator &lt; for class T.
Definition: array.cpp:68
FiniteElementSpace * fes
FE space on which the LinearForm lives. Not owned.
Definition: linearform.hpp:27
void AddBdrFaceIntegrator(LinearFormIntegrator *lfi)
Adds new Boundary Face Integrator. Assumes ownership of lfi.
Definition: linearform.cpp:83
FaceElementTransformations * GetBdrFaceTransformations(int BdrElemNo)
Definition: mesh.cpp:1094
void AddBoundaryIntegrator(LinearFormIntegrator *lfi)
Adds new Boundary Integrator. Assumes ownership of lfi.
Definition: linearform.cpp:70
bool IsDelta() const
Returns true if the derived class instance uses a delta coefficient.
Definition: lininteg.hpp:74
void AddElementVector(const Array< int > &dofs, const Vector &elemvect)
Add elements of the elemvect Vector to the entries listed in dofs. Negative dof values cause the -dof...
Definition: vector.cpp:626
int SpaceDimension() const
Definition: mesh.hpp:1000
LinearForm()
Create an empty LinearForm without an associated FiniteElementSpace.
Definition: linearform.hpp:94
ElementTransformation * GetElementTransformation(int i) const
Returns ElementTransformation for the i-th element.
Definition: fespace.hpp:623
void AddDomainIntegrator(LinearFormIntegrator *lfi)
Adds new Domain Integrator. Assumes ownership of lfi.
Definition: linearform.cpp:39
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition: mesh.hpp:270
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:88
void GetColumnReference(int c, Vector &col)
Definition: densemat.hpp:285
Abstract class for integrators that support delta coefficients.
Definition: lininteg.hpp:51
void AssembleDelta()
Assembles delta functions of the linear form.
Definition: linearform.cpp:290
Array< DeltaLFIntegrator * > domain_delta_integs
Separate array for integrators with delta function coefficients.
Definition: linearform.hpp:44
void Update()
Update the object according to the associated FE space fes.
Definition: linearform.hpp:188
Class for integration point with weight.
Definition: intrules.hpp:25
~LinearForm()
Destroys linear form.
Definition: linearform.cpp:344
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
bool HaveDeltaLocations()
If true, the delta locations are not (re)computed during assembly.
Definition: linearform.hpp:65
Array< LinearFormIntegrator * > boundary_integs
Set of Boundary Integrators to be applied.
Definition: linearform.hpp:47
virtual int FindPoints(DenseMatrix &point_mat, Array< int > &elem_ids, Array< IntegrationPoint > &ips, bool warn=true, InverseElementTransformation *inv_trans=NULL)
Find the ids of the elements that contain the given points, and their corresponding reference coordin...
Definition: mesh.cpp:11820
Vector data type.
Definition: vector.hpp:60
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
Definition: vector.hpp:585
virtual bool UseDevice() const
Return the device flag of the Memory object used by the Vector.
Definition: vector.hpp:120
Vector with associated FE space and LinearFormIntegrators.
Definition: linearform.hpp:23
Array< Array< int > * > boundary_integs_marker
Entries are not owned.
Definition: linearform.hpp:49
Array< Array< int > * > domain_integs_marker
Definition: linearform.hpp:41
const FiniteElement * GetBE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i&#39;th boundary fac...
Definition: fespace.cpp:3102
int GetAttribute(int i) const
Return the attribute of element i.
Definition: mesh.hpp:1455
virtual void TransformDual(double *v) const =0
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Definition: mesh.hpp:268