MFEM  v3.3.2
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
nonlinearform.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
11 
12 #include "fem.hpp"
13 
14 namespace mfem
15 {
16 
17 void NonlinearForm::SetEssentialBC(const Array<int> &bdr_attr_is_ess,
18  Vector *rhs)
19 {
20  int i, j, vsize, nv;
21  vsize = fes->GetVSize();
22  Array<int> vdof_marker(vsize);
23 
24  // virtual call, works in parallel too
25  fes->GetEssentialVDofs(bdr_attr_is_ess, vdof_marker);
26  nv = 0;
27  for (i = 0; i < vsize; i++)
28  if (vdof_marker[i])
29  {
30  nv++;
31  }
32 
33  ess_vdofs.SetSize(nv);
34 
35  for (i = j = 0; i < vsize; i++)
36  if (vdof_marker[i])
37  {
38  ess_vdofs[j++] = i;
39  }
40 
41  if (rhs)
42  for (i = 0; i < nv; i++)
43  {
44  (*rhs)(ess_vdofs[i]) = 0.0;
45  }
46 }
47 
48 double NonlinearForm::GetEnergy(const Vector &x) const
49 {
50  Array<int> vdofs;
51  Vector el_x;
52  const FiniteElement *fe;
54  double energy = 0.0;
55 
56  if (dnfi.Size())
57  for (int i = 0; i < fes->GetNE(); i++)
58  {
59  fe = fes->GetFE(i);
60  fes->GetElementVDofs(i, vdofs);
62  x.GetSubVector(vdofs, el_x);
63  for (int k = 0; k < dnfi.Size(); k++)
64  {
65  energy += dnfi[k]->GetElementEnergy(*fe, *T, el_x);
66  }
67  }
68 
69  if (fnfi.Size())
70  {
71  MFEM_ABORT("TODO: add energy contribution from interior face terms");
72  }
73 
74  if (bfnfi.Size())
75  {
76  MFEM_ABORT("TODO: add energy contribution from boundary face terms");
77  }
78 
79  return energy;
80 }
81 
82 void NonlinearForm::Mult(const Vector &x, Vector &y) const
83 {
84  Array<int> vdofs;
85  Vector el_x, el_y;
86  const FiniteElement *fe;
88  Mesh *mesh = fes->GetMesh();
89 
90  y = 0.0;
91 
92  if (dnfi.Size())
93  {
94  for (int i = 0; i < fes->GetNE(); i++)
95  {
96  fe = fes->GetFE(i);
97  fes->GetElementVDofs(i, vdofs);
99  x.GetSubVector(vdofs, el_x);
100  for (int k = 0; k < dnfi.Size(); k++)
101  {
102  dnfi[k]->AssembleElementVector(*fe, *T, el_x, el_y);
103  y.AddElementVector(vdofs, el_y);
104  }
105  }
106  }
107 
108  if (fnfi.Size())
109  {
111  const FiniteElement *fe1, *fe2;
112  Array<int> vdofs2;
113 
114  for (int i = 0; i < mesh->GetNumFaces(); i++)
115  {
116  tr = mesh->GetInteriorFaceTransformations(i);
117  if (tr != NULL)
118  {
119  fes->GetElementVDofs(tr->Elem1No, vdofs);
120  fes->GetElementVDofs(tr->Elem2No, vdofs2);
121  vdofs.Append (vdofs2);
122 
123  x.GetSubVector(vdofs, el_x);
124 
125  fe1 = fes->GetFE(tr->Elem1No);
126  fe2 = fes->GetFE(tr->Elem2No);
127 
128  for (int k = 0; k < fnfi.Size(); k++)
129  {
130  fnfi[k]->AssembleFaceVector(*fe1, *fe2, *tr, el_x, el_y);
131  y.AddElementVector(vdofs, el_y);
132  }
133  }
134  }
135  }
136 
137  if (bfnfi.Size())
138  {
140  const FiniteElement *fe1, *fe2;
141 
142  // Which boundary attributes need to be processed?
143  Array<int> bdr_attr_marker(mesh->bdr_attributes.Size() ?
144  mesh->bdr_attributes.Max() : 0);
145  bdr_attr_marker = 0;
146  for (int k = 0; k < bfnfi.Size(); k++)
147  {
148  if (bfnfi_marker[k] == NULL)
149  {
150  bdr_attr_marker = 1;
151  break;
152  }
153  Array<int> &bdr_marker = *bfnfi_marker[k];
154  MFEM_ASSERT(bdr_marker.Size() == bdr_attr_marker.Size(),
155  "invalid boundary marker for boundary face integrator #"
156  << k << ", counting from zero");
157  for (int i = 0; i < bdr_attr_marker.Size(); i++)
158  {
159  bdr_attr_marker[i] |= bdr_marker[i];
160  }
161  }
162 
163  for (int i = 0; i < fes -> GetNBE(); i++)
164  {
165  const int bdr_attr = mesh->GetBdrAttribute(i);
166  if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
167 
168  tr = mesh->GetBdrFaceTransformations (i);
169  if (tr != NULL)
170  {
171  fes->GetElementVDofs(tr->Elem1No, vdofs);
172  x.GetSubVector(vdofs, el_x);
173 
174  fe1 = fes->GetFE(tr->Elem1No);
175  // The fe2 object is really a dummy and not used on the boundaries,
176  // but we can't dereference a NULL pointer, and we don't want to
177  // actually make a fake element.
178  fe2 = fe1;
179  for (int k = 0; k < bfnfi.Size(); k++)
180  {
181  if (bfnfi_marker[k] &&
182  (*bfnfi_marker[k])[bdr_attr-1] == 0) { continue; }
183 
184  bfnfi[k]->AssembleFaceVector(*fe1, *fe2, *tr, el_x, el_y);
185  y.AddElementVector(vdofs, el_y);
186  }
187  }
188  }
189  }
190 
191  for (int i = 0; i < ess_vdofs.Size(); i++)
192  {
193  y(ess_vdofs[i]) = 0.0;
194  }
195  // y(ess_vdofs[i]) = x(ess_vdofs[i]);
196 }
197 
199 {
200  const int skip_zeros = 0;
201  Array<int> vdofs;
202  Vector el_x;
203  DenseMatrix elmat;
204  const FiniteElement *fe;
206  Mesh *mesh = fes->GetMesh();
207 
208  if (Grad == NULL)
209  {
210  Grad = new SparseMatrix(fes->GetVSize());
211  }
212  else
213  {
214  *Grad = 0.0;
215  }
216 
217  if (dnfi.Size())
218  {
219  for (int i = 0; i < fes->GetNE(); i++)
220  {
221  fe = fes->GetFE(i);
222  fes->GetElementVDofs(i, vdofs);
224  x.GetSubVector(vdofs, el_x);
225  for (int k = 0; k < dnfi.Size(); k++)
226  {
227  dnfi[k]->AssembleElementGrad(*fe, *T, el_x, elmat);
228  Grad->AddSubMatrix(vdofs, vdofs, elmat, skip_zeros);
229  // Grad->AddSubMatrix(vdofs, vdofs, elmat, 1);
230  }
231  }
232  }
233 
234  if (fnfi.Size())
235  {
237  const FiniteElement *fe1, *fe2;
238  Array<int> vdofs2;
239 
240  for (int i = 0; i < mesh->GetNumFaces(); i++)
241  {
242  tr = mesh->GetInteriorFaceTransformations(i);
243  if (tr != NULL)
244  {
245  fes->GetElementVDofs(tr->Elem1No, vdofs);
246  fes->GetElementVDofs(tr->Elem2No, vdofs2);
247  vdofs.Append (vdofs2);
248 
249  x.GetSubVector(vdofs, el_x);
250 
251  fe1 = fes->GetFE(tr->Elem1No);
252  fe2 = fes->GetFE(tr->Elem2No);
253 
254  for (int k = 0; k < fnfi.Size(); k++)
255  {
256  fnfi[k]->AssembleFaceGrad(*fe1, *fe2, *tr, el_x, elmat);
257  Grad->AddSubMatrix(vdofs, vdofs, elmat, skip_zeros);
258  }
259  }
260  }
261  }
262 
263  if (bfnfi.Size())
264  {
266  const FiniteElement *fe1, *fe2;
267 
268  // Which boundary attributes need to be processed?
269  Array<int> bdr_attr_marker(mesh->bdr_attributes.Size() ?
270  mesh->bdr_attributes.Max() : 0);
271  bdr_attr_marker = 0;
272  for (int k = 0; k < bfnfi.Size(); k++)
273  {
274  if (bfnfi_marker[k] == NULL)
275  {
276  bdr_attr_marker = 1;
277  break;
278  }
279  Array<int> &bdr_marker = *bfnfi_marker[k];
280  MFEM_ASSERT(bdr_marker.Size() == bdr_attr_marker.Size(),
281  "invalid boundary marker for boundary face integrator #"
282  << k << ", counting from zero");
283  for (int i = 0; i < bdr_attr_marker.Size(); i++)
284  {
285  bdr_attr_marker[i] |= bdr_marker[i];
286  }
287  }
288 
289  for (int i = 0; i < fes -> GetNBE(); i++)
290  {
291  const int bdr_attr = mesh->GetBdrAttribute(i);
292  if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
293 
294  tr = mesh->GetBdrFaceTransformations (i);
295  if (tr != NULL)
296  {
297  fes->GetElementVDofs(tr->Elem1No, vdofs);
298  x.GetSubVector(vdofs, el_x);
299 
300  fe1 = fes->GetFE(tr->Elem1No);
301  // The fe2 object is really a dummy and not used on the boundaries,
302  // but we can't dereference a NULL pointer, and we don't want to
303  // actually make a fake element.
304  fe2 = fe1;
305  for (int k = 0; k < bfnfi.Size(); k++)
306  {
307  if (bfnfi_marker[k] &&
308  (*bfnfi_marker[k])[bdr_attr-1] == 0) { continue; }
309 
310  bfnfi[k]->AssembleFaceGrad(*fe1, *fe2, *tr, el_x, elmat);
311  Grad->AddSubMatrix(vdofs, vdofs, elmat, skip_zeros);
312  }
313  }
314  }
315  }
316 
317  for (int i = 0; i < ess_vdofs.Size(); i++)
318  {
320  }
321 
322  if (!Grad->Finalized())
323  {
324  Grad->Finalize(skip_zeros);
325  }
326 
327  return *Grad;
328 }
329 
331 {
332  delete Grad;
333  for (int i = 0; i < dnfi.Size(); i++) { delete dnfi[i]; }
334  for (int i = 0; i < fnfi.Size(); i++) { delete fnfi[i]; }
335  for (int i = 0; i < bfnfi.Size(); i++) { delete bfnfi[i]; }
336 }
337 
338 }
Abstract class for Finite Elements.
Definition: fe.hpp:47
int Size() const
Logical size of the array.
Definition: array.hpp:110
int GetVSize() const
Definition: fespace.hpp:163
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
Definition: mesh.hpp:855
Array< NonlinearFormIntegrator * > dnfi
Set of Domain Integrators to be assembled (added).
virtual void Finalize(int skip_zeros=1)
Finalize the matrix initialization, switching the storage format from LIL to CSR. ...
Definition: sparsemat.hpp:278
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:133
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Definition: vector.cpp:462
virtual void GetEssentialVDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_vdofs, int component=-1) const
Definition: fespace.cpp:258
void EliminateRowCol(int rc, const double sol, Vector &rhs, int d=0)
Definition: sparsemat.cpp:1162
Data type dense matrix using column-major storage.
Definition: densemat.hpp:23
Array< NonlinearFormIntegrator * > bfnfi
Set of boundary face Integrators to be assembled (added).
FiniteElementSpace * fes
FE space on which the form lives.
FaceElementTransformations * GetInteriorFaceTransformations(int FaceNo)
Definition: mesh.hpp:822
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
Definition: mesh.cpp:3334
int GetNE() const
Returns number of elements in the mesh.
Definition: fespace.hpp:184
Data type sparse matrix.
Definition: sparsemat.hpp:38
int Append(const T &el)
Append element to array, resize if necessary.
Definition: array.hpp:548
Mesh * GetMesh() const
Returns the mesh.
Definition: fespace.hpp:136
Array< NonlinearFormIntegrator * > fnfi
Set of interior face Integrators to be assembled (added).
T Max() const
Find the maximal element in the array, using the comparison operator &lt; for class T.
Definition: array.cpp:108
Array< int > ess_vdofs
Array< Array< int > * > bfnfi_marker
FaceElementTransformations * GetBdrFaceTransformations(int BdrElemNo)
Definition: mesh.cpp:717
void AddElementVector(const Array< int > &dofs, const Vector &elemvect)
Add (element) subvector to the vector.
Definition: vector.cpp:550
void AddSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
Definition: sparsemat.cpp:1850
bool Finalized() const
Definition: sparsemat.hpp:283
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
ElementTransformation * GetElementTransformation(int i) const
Returns ElementTransformation for the i&#39;th element.
Definition: fespace.hpp:205
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition: mesh.hpp:172
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
Definition: array.hpp:503
virtual Operator & GetGradient(const Vector &x) const
Evaluate the gradient operator at the point x. The default behavior in class Operator is to generate ...
const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement associated with i&#39;th element.
Definition: fespace.cpp:1171
virtual void SetEssentialBC(const Array< int > &bdr_attr_is_ess, Vector *rhs=NULL)
Vector data type.
Definition: vector.hpp:41
SparseMatrix * Grad
virtual double GetEnergy(const Vector &x) const
Abstract operator.
Definition: operator.hpp:21