MFEM  v4.3.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-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 // 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  Vector elemvect;
107 
108  int i;
109 
110  Vector::operator=(0.0);
111 
112  // The above operation is executed on device because of UseDevice().
113  // The first use of AddElementVector() below will move it back to host
114  // because both 'vdofs' and 'elemvect' are on host.
115 
116  if (domain_integs.Size())
117  {
118  for (int k = 0; k < domain_integs.Size(); k++)
119  {
120  if (domain_integs_marker[k] != NULL)
121  {
122  MFEM_VERIFY(fes->GetMesh()->attributes.Size() ==
123  domain_integs_marker[k]->Size(),
124  "invalid element marker for domain linear form "
125  "integrator #" << k << ", counting from zero");
126  }
127  }
128 
129  for (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  fes -> GetElementVDofs (i, vdofs);
138  eltrans = fes -> GetElementTransformation (i);
139  domain_integs[k]->AssembleRHSElementVect(*fes->GetFE(i),
140  *eltrans, elemvect);
141  AddElementVector (vdofs, elemvect);
142  }
143  }
144  }
145  }
146  AssembleDelta();
147 
148  if (boundary_integs.Size())
149  {
150  Mesh *mesh = fes->GetMesh();
151 
152  // Which boundary attributes need to be processed?
153  Array<int> bdr_attr_marker(mesh->bdr_attributes.Size() ?
154  mesh->bdr_attributes.Max() : 0);
155  bdr_attr_marker = 0;
156  for (int k = 0; k < boundary_integs.Size(); k++)
157  {
158  if (boundary_integs_marker[k] == NULL)
159  {
160  bdr_attr_marker = 1;
161  break;
162  }
163  Array<int> &bdr_marker = *boundary_integs_marker[k];
164  MFEM_ASSERT(bdr_marker.Size() == bdr_attr_marker.Size(),
165  "invalid boundary marker for boundary integrator #"
166  << k << ", counting from zero");
167  for (int i = 0; i < bdr_attr_marker.Size(); i++)
168  {
169  bdr_attr_marker[i] |= bdr_marker[i];
170  }
171  }
172 
173  for (i = 0; i < fes -> GetNBE(); i++)
174  {
175  const int bdr_attr = mesh->GetBdrAttribute(i);
176  if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
177  fes -> GetBdrElementVDofs (i, vdofs);
178  eltrans = fes -> GetBdrElementTransformation (i);
179  for (int k=0; k < boundary_integs.Size(); k++)
180  {
181  if (boundary_integs_marker[k] &&
182  (*boundary_integs_marker[k])[bdr_attr-1] == 0) { continue; }
183 
184  boundary_integs[k]->AssembleRHSElementVect(*fes->GetBE(i),
185  *eltrans, elemvect);
186 
187  AddElementVector (vdofs, elemvect);
188  }
189  }
190  }
191  if (boundary_face_integs.Size())
192  {
194  Mesh *mesh = fes->GetMesh();
195 
196  // Which boundary attributes need to be processed?
197  Array<int> bdr_attr_marker(mesh->bdr_attributes.Size() ?
198  mesh->bdr_attributes.Max() : 0);
199  bdr_attr_marker = 0;
200  for (int k = 0; k < boundary_face_integs.Size(); k++)
201  {
202  if (boundary_face_integs_marker[k] == NULL)
203  {
204  bdr_attr_marker = 1;
205  break;
206  }
207  Array<int> &bdr_marker = *boundary_face_integs_marker[k];
208  MFEM_ASSERT(bdr_marker.Size() == bdr_attr_marker.Size(),
209  "invalid boundary marker for boundary face integrator #"
210  << k << ", counting from zero");
211  for (int i = 0; i < bdr_attr_marker.Size(); i++)
212  {
213  bdr_attr_marker[i] |= bdr_marker[i];
214  }
215  }
216 
217  for (i = 0; i < mesh->GetNBE(); i++)
218  {
219  const int bdr_attr = mesh->GetBdrAttribute(i);
220  if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
221 
222  tr = mesh->GetBdrFaceTransformations(i);
223  if (tr != NULL)
224  {
225  fes -> GetElementVDofs (tr -> Elem1No, vdofs);
226  for (int k = 0; k < boundary_face_integs.Size(); k++)
227  {
229  (*boundary_face_integs_marker[k])[bdr_attr-1] == 0)
230  { continue; }
231 
233  AssembleRHSElementVect(*fes->GetFE(tr->Elem1No),
234  *tr, elemvect);
235  AddElementVector (vdofs, elemvect);
236  }
237  }
238  }
239  }
240 
241  if (interior_face_integs.Size())
242  {
243  Mesh *mesh = fes->GetMesh();
244 
245  for (int k = 0; k < interior_face_integs.Size(); k++)
246  {
247  for (i = 0; i < mesh->GetNumFaces(); i++)
248  {
249  FaceElementTransformations *tr = NULL;
250  tr = mesh->GetInteriorFaceTransformations (i);
251  if (tr != NULL)
252  {
253  fes -> GetElementVDofs (tr -> Elem1No, vdofs);
254  Array<int> vdofs2;
255  fes -> GetElementVDofs (tr -> Elem2No, vdofs2);
256  vdofs.Append(vdofs2);
258  AssembleRHSElementVect(*fes->GetFE(tr->Elem1No),
259  *fes->GetFE(tr->Elem2No),
260  *tr, elemvect);
261  AddElementVector (vdofs, elemvect);
262  }
263  }
264  }
265  }
266 }
267 
269 {
270  MFEM_ASSERT(v.Size() >= v_offset + f->GetVSize(), "");
271  fes = f;
272  v.UseDevice(true);
273  this->Vector::MakeRef(v, v_offset, fes->GetVSize());
275 }
276 
278 {
279  Update(f, v, v_offset);
280 }
281 
283 {
284  if (domain_delta_integs.Size() == 0) { return; }
285 
286  if (!HaveDeltaLocations())
287  {
288  int sdim = fes->GetMesh()->SpaceDimension();
289  Vector center;
290  DenseMatrix centers(sdim, domain_delta_integs.Size());
291  for (int i = 0; i < centers.Width(); i++)
292  {
293  centers.GetColumnReference(i, center);
294  domain_delta_integs[i]->GetDeltaCenter(center);
295  MFEM_VERIFY(center.Size() == sdim,
296  "Point dim " << center.Size() <<
297  " does not match space dim " << sdim);
298  }
301  }
302 
303  Array<int> vdofs;
304  Vector elemvect;
305  for (int i = 0; i < domain_delta_integs.Size(); i++)
306  {
307  int elem_id = domain_delta_integs_elem_id[i];
308  // The delta center may be outside of this sub-domain, or
309  // (Par)Mesh::FindPoints() failed to find this point:
310  if (elem_id < 0) { continue; }
311 
314  Trans.SetIntPoint(&ip);
315 
316  fes->GetElementVDofs(elem_id, vdofs);
317  domain_delta_integs[i]->AssembleDeltaElementVect(*fes->GetFE(elem_id),
318  Trans, elemvect);
319  AddElementVector(vdofs, elemvect);
320  }
321 }
322 
324 {
325  Vector::operator=(value);
326  return *this;
327 }
328 
330 {
331  MFEM_ASSERT(fes && v.Size() == fes->GetVSize(), "");
333  return *this;
334 }
335 
337 {
338  if (!extern_lfs)
339  {
340  int k;
341  for (k=0; k < domain_delta_integs.Size(); k++)
342  { delete domain_delta_integs[k]; }
343  for (k=0; k < domain_integs.Size(); k++) { delete domain_integs[k]; }
344  for (k=0; k < boundary_integs.Size(); k++) { delete boundary_integs[k]; }
345  for (k=0; k < boundary_face_integs.Size(); k++)
346  { delete boundary_face_integs[k]; }
347  for (k=0; k < interior_face_integs.Size(); k++)
348  { delete interior_face_integs[k]; }
349  }
350 }
351 
352 }
int Size() const
Return the logical size of the array.
Definition: array.hpp:134
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition: fespace.hpp:540
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
Definition: mesh.hpp:1203
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
virtual void MakeRef(FiniteElementSpace *f, Vector &v, int v_offset)
Make the LinearForm reference external data on a new FiniteElementSpace.
Definition: linearform.cpp:277
Array< Array< int > * > boundary_face_integs_marker
Entries not owned.
Definition: linearform.hpp:52
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:109
void SetIntPoint(const IntegrationPoint *ip)
Set the integration point ip that weights and Jacobians will be evaluated at.
Definition: eltrans.hpp:85
A specialized ElementTransformation class representing a face and its two neighboring elements...
Definition: eltrans.hpp:467
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:61
int Size() const
Returns the size of the vector.
Definition: vector.hpp:190
void ResetDeltaLocations()
Force (re)computation of delta locations.
Definition: linearform.hpp:68
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:58
Array< LinearFormIntegrator * > boundary_face_integs
Set of Boundary Face Integrators to be applied.
Definition: linearform.hpp:51
FaceElementTransformations * GetInteriorFaceTransformations(int FaceNo)
Definition: mesh.hpp:1153
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition: vector.hpp:108
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:4915
Array< LinearFormIntegrator * > interior_face_integs
Set of Internal Face Integrators to be applied.
Definition: linearform.hpp:55
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
Mesh * GetMesh() const
Returns the mesh.
Definition: fespace.hpp:410
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:1020
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:617
int SpaceDimension() const
Definition: mesh.hpp:912
LinearForm()
Create an empty LinearForm without an associated FiniteElementSpace.
Definition: linearform.hpp:93
ElementTransformation * GetElementTransformation(int i) const
Returns ElementTransformation for the i-th element.
Definition: fespace.hpp:600
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:204
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:87
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:282
Array< DeltaLFIntegrator * > domain_delta_integs
Separate array for integrators with delta function coefficients.
Definition: linearform.hpp:43
void Update()
Update the object according to the associated FE space fes.
Definition: linearform.hpp:187
Class for integration point with weight.
Definition: intrules.hpp:25
~LinearForm()
Destroys linear form.
Definition: linearform.cpp:336
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:2388
bool HaveDeltaLocations()
If true, the delta locations are not (re)computed during assembly.
Definition: linearform.hpp:64
Array< LinearFormIntegrator * > boundary_integs
Set of Boundary Integrators to be applied.
Definition: linearform.hpp:46
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:11277
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:577
virtual bool UseDevice() const
Return the device flag of the Memory object used by the Vector.
Definition: vector.hpp:111
Vector with associated FE space and LinearFormIntegrators.
Definition: linearform.hpp:23
Array< Array< int > * > boundary_integs_marker
Entries are not owned.
Definition: linearform.hpp:48
Array< Array< int > * > domain_integs_marker
Definition: linearform.hpp:40
const FiniteElement * GetBE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i&#39;th boundary fac...
Definition: fespace.cpp:2686
int GetAttribute(int i) const
Return the attribute of element i.
Definition: mesh.hpp:1197
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Definition: mesh.hpp:202