MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
nonlinearform.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, 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#ifndef MFEM_NONLINEARFORM
13#define MFEM_NONLINEARFORM
14
15#include "../config/config.hpp"
16#include "nonlininteg.hpp"
17#include "nonlinearform_ext.hpp"
18#include "bilinearform.hpp"
19#include "gridfunc.hpp"
20
21namespace mfem
22{
23
24class NonlinearForm : public Operator
25{
26protected:
27 /// The assembly level.
29
30 /// Extension for supporting different AssemblyLevel%s
31 /** For nonlinear operators, the "matrix" assembly levels usually do not make
32 sense, so only PARTIAL and NONE (matrix-free) are supported. */
34
35 /// FE space on which the form lives.
36 FiniteElementSpace *fes; // not owned
37
38 /** @brief Indicates the NonlinearFormIntegrator%s stored in #dnfi, #bnfi,
39 #fnfi, and #bfnfi are not owned by this NonlinearForm. */
41
42 /// Set of Domain Integrators to be assembled (added).
45
46 /// Set of Boundary Integrators to be assembled (added).
49
50 /// Set of interior face Integrators to be assembled (added).
52
53 /// Set of boundary face Integrators to be assembled (added).
56
57 mutable SparseMatrix *Grad, *cGrad; // owned
58 /// Gradient Operator when not assembled as a matrix.
59 mutable OperatorHandle hGrad; // has internal ownership flag
60
61 /// A list of all essential true dofs
63
64 /// Counter for updates propagated from the FiniteElementSpace.
66
67 /// Auxiliary Vector%s
68 mutable Vector aux1, aux2;
69
70 /// Pointer to the prolongation matrix of fes, may be NULL.
71 const Operator *P; // not owned
72 /// The result of dynamic-casting P to SparseMatrix pointer.
73 const SparseMatrix *cP; // not owned
74
75 bool Serial() const { return (!P || cP); }
76 const Vector &Prolongate(const Vector &x) const;
77
78public:
79 /// Construct a NonlinearForm on the given FiniteElementSpace, @a f.
80 /** As an Operator, the NonlinearForm has input and output size equal to the
81 number of true degrees of freedom, i.e. f->GetTrueVSize(). */
83 : Operator(f->GetTrueVSize()), assembly(AssemblyLevel::LEGACY),
84 ext(NULL), fes(f), extern_bfs(0), Grad(NULL), cGrad(NULL),
85 sequence(f->GetSequence()), P(f->GetProlongationMatrix()),
86 cP(dynamic_cast<const SparseMatrix*>(P))
87 { }
88
89 /// Set the desired assembly level. The default is AssemblyLevel::LEGACY.
90 /** For nonlinear operators, the "matrix" assembly levels usually do not make
91 sense, so only LEGACY, NONE (matrix-free) and PARTIAL are supported.
92
93 Currently, AssemblyLevel::LEGACY uses the standard nonlinear action
94 methods like AssembleElementVector of the NonlinearFormIntegrator class
95 which work only on CPU and do not utilize features such as fast
96 tensor-product basis evaluations. In this mode, the gradient operator is
97 constructed as a SparseMatrix (or, in parallel, format such as
98 HypreParMatrix).
99
100 When using AssemblyLevel::PARTIAL, the action is performed using methods
101 like AddMultPA of the NonlinearFormIntegrator class which typically
102 support both CPU and GPU backends and utilize features such as fast
103 tensor-product basis evaluations. In this mode, the gradient operator
104 also uses partial assembly with support for CPU and GPU backends.
105
106 When using AssemblyLevel::NONE, the action is performed using methods
107 like AddMultMF of the NonlinearFormIntegrator class which typically
108 support both CPU and GPU backends and utilize features such as fast
109 tensor-product basis evaluations. In this mode, the gradient operator
110 is currently not supported.
111
112 This method must be called before "assembly" with Setup(). */
113 void SetAssemblyLevel(AssemblyLevel assembly_level);
114
116 const FiniteElementSpace *FESpace() const { return fes; }
117
118 /// Adds new Domain Integrator.
120 { dnfi.Append(nlfi); dnfi_marker.Append(NULL); }
121
122 /// Adds new Domain Integrator, restricted to specific attributes.
124 Array<int> &elem_marker)
125 { dnfi.Append(nlfi); dnfi_marker.Append(&elem_marker); }
126
127 /// Access all integrators added with AddDomainIntegrator().
129 const Array<NonlinearFormIntegrator*> *GetDNFI() const { return &dnfi; }
130
131 /// Adds new Boundary Integrator.
133 { bnfi.Append(nlfi); bnfi_marker.Append(NULL); }
134
135 /// Adds new Boundary Integrator, restricted to specific attributes.
137 Array<int> &elem_marker)
138 { bnfi.Append(nlfi); bnfi_marker.Append(&elem_marker); }
139
140 /// Access all integrators added with AddBoundaryIntegrator().
142 const Array<NonlinearFormIntegrator*> *GetBNFI() const { return &bnfi; }
143
144 /// Adds new Interior Face Integrator.
146 { fnfi.Append(nlfi); }
147
148 /** @brief Access all interior face integrators added with
149 AddInteriorFaceIntegrator(). */
152
153 /// Adds new Boundary Face Integrator.
155 { bfnfi.Append(nlfi); bfnfi_marker.Append(NULL); }
156
157 /** @brief Adds new Boundary Face Integrator, restricted to specific boundary
158 attributes. */
160 Array<int> &bdr_marker)
161 { bfnfi.Append(nfi); bfnfi_marker.Append(&bdr_marker); }
162
163 /** @brief Access all boundary face integrators added with
164 AddBdrFaceIntegrator(). */
167
168 /// Specify essential boundary conditions.
169 /** This method calls FiniteElementSpace::GetEssentialTrueDofs() and stores
170 the result internally for use by other methods. If the @a rhs pointer is
171 not NULL, its essential true dofs will be set to zero. This makes it
172 "compatible" with the output vectors from the Mult() method which also
173 have zero entries at the essential true dofs. */
174 void SetEssentialBC(const Array<int> &bdr_attr_is_ess, Vector *rhs = NULL);
175
176 /// Specify essential boundary conditions.
177 /** Use either SetEssentialBC() or SetEssentialTrueDofs() if possible. */
178 void SetEssentialVDofs(const Array<int> &ess_vdofs_list);
179
180 /// Specify essential boundary conditions.
181 void SetEssentialTrueDofs(const Array<int> &ess_tdof_list_)
182 { ess_tdof_list_.Copy(this->ess_tdof_list); }
183
184 /// Return a (read-only) list of all essential true dofs.
186
187 /// Compute the energy corresponding to the state @a x.
188 /** In general, @a x may have non-homogeneous essential boundary values.
189
190 The state @a x must be a "GridFunction size" vector, i.e. its size must
191 be fes->GetVSize(). */
192 real_t GetGridFunctionEnergy(const Vector &x) const;
193
194 /// Compute the energy corresponding to the state @a x.
195 /** In general, @a x may have non-homogeneous essential boundary values.
196
197 The state @a x must be a true-dof vector. */
198 virtual real_t GetEnergy(const Vector &x) const
199 { return GetGridFunctionEnergy(Prolongate(x)); }
200
201 /// Evaluate the action of the NonlinearForm.
202 /** The input essential dofs in @a x will, generally, be non-zero. However,
203 the output essential dofs in @a y will always be set to zero.
204
205 Both the input and the output vectors, @a x and @a y, must be true-dof
206 vectors, i.e. their size must be fes->GetTrueVSize(). */
207 virtual void Mult(const Vector &x, Vector &y) const;
208
209 /** @brief Compute the gradient Operator of the NonlinearForm corresponding
210 to the state @a x. */
211 /** Any previously specified essential boundary conditions will be
212 automatically imposed on the gradient operator.
213
214 The returned object is valid until the next call to this method or the
215 destruction of this object.
216
217 In general, @a x may have non-homogeneous essential boundary values.
218
219 The state @a x must be a true-dof vector. */
220 virtual Operator &GetGradient(const Vector &x) const;
221
222 /// Update the NonlinearForm to propagate updates of the associated FE space.
223 /** After calling this method, the essential boundary conditions need to be
224 set again. */
225 virtual void Update();
226
227 /** @brief Setup the NonlinearForm: based on the current AssemblyLevel and
228 the current mesh, optionally, precompute and store data that will be
229 reused in subsequent call to Mult(). */
230 /** Typically, this method has to be called before Mult() when using
231 AssemblyLevel::PARTIAL, after calling Update(), or after modifying the
232 mesh coordinates. */
233 virtual void Setup();
234
235 /// Get the finite element space prolongation matrix
236 virtual const Operator *GetProlongation() const { return P; }
237 /// Get the finite element space restriction matrix
238 virtual const Operator *GetRestriction() const
239 { return fes->GetRestrictionMatrix(); }
240
241 /// Indicate that integrators are not owned by the NonlinearForm
243
244 /** @brief Destroy the NonlinearForm including the owned
245 NonlinearFormIntegrator%s and gradient Operator. */
246 virtual ~NonlinearForm();
247};
248
249
250/** @brief A class representing a general block nonlinear operator defined on
251 the Cartesian product of multiple FiniteElementSpace%s. */
253{
254protected:
255 /// FE spaces on which the form lives.
257
258 /// Set of Domain Integrators to be assembled (added).
261
262 /// Set of Boundary Integrators to be assembled (added).
265
266 /// Set of interior face Integrators to be assembled (added).
268
269 /// Set of Boundary Face Integrators to be assembled (added).
272
273 /** Auxiliary block-vectors for wrapping input and output vectors or holding
274 GridFunction-like block-vector data (e.g. in parallel). */
275 mutable BlockVector xs, ys;
276
279
280 // A list of the offsets
283
284 // Array of Arrays of tdofs for each space in 'fes'
286
287 /// Array of pointers to the prolongation matrix of fes, may be NULL
289
290 /// Array of results of dynamic-casting P to SparseMatrix pointer
292
293 /// Indicator if the Operator is part of a parallel run
294 bool is_serial = true;
295
296 /// Indicator if the Operator needs prolongation on assembly
297 bool needs_prolongation = false;
298
300
301 const BlockVector &Prolongate(const BlockVector &bx) const;
302
303 /// Specialized version of GetEnergy() for BlockVectors
304 real_t GetEnergyBlocked(const BlockVector &bx) const;
305
306 /// Specialized version of Mult() for BlockVector%s
307 /// Block L-Vector to Block L-Vector
308 void MultBlocked(const BlockVector &bx, BlockVector &by) const;
309
310 /// Specialized version of GetGradient() for BlockVector
311 void ComputeGradientBlocked(const BlockVector &bx) const;
312
313public:
314 /// Construct an empty BlockNonlinearForm. Initialize with SetSpaces().
316
317 /// Construct a BlockNonlinearForm on the given set of FiniteElementSpace%s.
319
320 /// Return the @a k-th FE space of the BlockNonlinearForm.
321 FiniteElementSpace *FESpace(int k) { return fes[k]; }
322 /// Return the @a k-th FE space of the BlockNonlinearForm (const version).
323 const FiniteElementSpace *FESpace(int k) const { return fes[k]; }
324
325 /// (Re)initialize the BlockNonlinearForm.
326 /** After a call to SetSpaces(), the essential b.c. must be set again. */
328
329 /// Return the regular dof offsets.
330 const Array<int> &GetBlockOffsets() const { return block_offsets; }
331 /// Return the true-dof offsets.
333
334 /// Adds new Domain Integrator.
336 { dnfi.Append(nlfi); dnfi_marker.Append(NULL); }
337
338 /// Adds new Domain Integrator, restricted to specific attributes.
340 Array<int> &elem_marker)
341 { dnfi.Append(nlfi); dnfi_marker.Append(&elem_marker); }
342
343 /// Adds new Boundary Integrator.
345 { bnfi.Append(nlfi); bnfi_marker.Append(NULL); }
346
347 /// Adds new Boundary Integrator, restricted to specific attributes.
349 Array<int> &elem_marker)
350 { bnfi.Append(nlfi); bnfi_marker.Append(&elem_marker); }
351
352 /// Adds new Interior Face Integrator.
355
356 /// Adds new Boundary Face Integrator.
358 { bfnfi.Append(nlfi); bfnfi_marker.Append(NULL); }
359
360 /** @brief Adds new Boundary Face Integrator, restricted to specific boundary
361 attributes. */
363 Array<int> &bdr_marker)
364 { bfnfi.Append(nlfi); bfnfi_marker.Append(&bdr_marker); }
365
366 virtual void SetEssentialBC(const Array<Array<int> *>&bdr_attr_is_ess,
367 Array<Vector *> &rhs);
368
369 virtual real_t GetEnergy(const Vector &x) const;
370
371 /// Method is only called in serial, the parallel version calls MultBlocked
372 /// directly.
373 virtual void Mult(const Vector &x, Vector &y) const;
374
375 /// Method is only called in serial, the parallel version calls
376 /// GetGradientBlocked directly.
377 virtual Operator &GetGradient(const Vector &x) const;
378
379 /// Destructor.
380 virtual ~BlockNonlinearForm();
381};
382
383
384}
385
386#endif
Dynamic 2D array using row-major layout.
Definition array.hpp:372
void Copy(Array &copy) const
Create a copy of the internal array to the provided copy.
Definition array.hpp:874
A class representing a general block nonlinear operator defined on the Cartesian product of multiple ...
Array< Array< int > * > dnfi_marker
Array< Array< int > * > bnfi_marker
Array< BlockNonlinearFormIntegrator * > dnfi
Set of Domain Integrators to be assembled (added).
void AddInteriorFaceIntegrator(BlockNonlinearFormIntegrator *nlfi)
Adds new Interior Face Integrator.
FiniteElementSpace * FESpace(int k)
Return the k-th FE space of the BlockNonlinearForm.
void AddDomainIntegrator(BlockNonlinearFormIntegrator *nlfi)
Adds new Domain Integrator.
Array< FiniteElementSpace * > fes
FE spaces on which the form lives.
void ComputeGradientBlocked(const BlockVector &bx) const
Specialized version of GetGradient() for BlockVector.
real_t GetEnergyBlocked(const BlockVector &bx) const
Specialized version of GetEnergy() for BlockVectors.
void SetSpaces(Array< FiniteElementSpace * > &f)
(Re)initialize the BlockNonlinearForm.
void AddBdrFaceIntegrator(BlockNonlinearFormIntegrator *nlfi, Array< int > &bdr_marker)
Adds new Boundary Face Integrator, restricted to specific boundary attributes.
Array2D< SparseMatrix * > Grads
bool is_serial
Indicator if the Operator is part of a parallel run.
void MultBlocked(const BlockVector &bx, BlockVector &by) const
const Array< int > & GetBlockOffsets() const
Return the regular dof offsets.
void AddBoundaryIntegrator(BlockNonlinearFormIntegrator *nlfi, Array< int > &elem_marker)
Adds new Boundary Integrator, restricted to specific attributes.
void AddDomainIntegrator(BlockNonlinearFormIntegrator *nlfi, Array< int > &elem_marker)
Adds new Domain Integrator, restricted to specific attributes.
virtual ~BlockNonlinearForm()
Destructor.
const FiniteElementSpace * FESpace(int k) const
Return the k-th FE space of the BlockNonlinearForm (const version).
Array< BlockNonlinearFormIntegrator * > fnfi
Set of interior face Integrators to be assembled (added).
const BlockVector & Prolongate(const BlockVector &bx) const
Array< Array< int > * > bfnfi_marker
virtual void SetEssentialBC(const Array< Array< int > * > &bdr_attr_is_ess, Array< Vector * > &rhs)
bool needs_prolongation
Indicator if the Operator needs prolongation on assembly.
const Array< int > & GetBlockTrueOffsets() const
Return the true-dof offsets.
void AddBdrFaceIntegrator(BlockNonlinearFormIntegrator *nlfi)
Adds new Boundary Face Integrator.
Array2D< SparseMatrix * > cGrads
Array< BlockNonlinearFormIntegrator * > bnfi
Set of Boundary Integrators to be assembled (added).
void AddBoundaryIntegrator(BlockNonlinearFormIntegrator *nlfi)
Adds new Boundary Integrator.
Array< const SparseMatrix * > cP
Array of results of dynamic-casting P to SparseMatrix pointer.
Array< BlockNonlinearFormIntegrator * > bfnfi
Set of Boundary Face Integrators to be assembled (added).
virtual real_t GetEnergy(const Vector &x) const
virtual Operator & GetGradient(const Vector &x) const
Array< const Operator * > P
Array of pointers to the prolongation matrix of fes, may be NULL.
Array< Array< int > * > ess_tdofs
BlockNonlinearForm()
Construct an empty BlockNonlinearForm. Initialize with SetSpaces().
virtual void Mult(const Vector &x, Vector &y) const
A class to handle Block systems in a matrix-free implementation.
A class to handle Vectors in a block fashion.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:220
virtual const SparseMatrix * GetRestrictionMatrix() const
The returned SparseMatrix is owned by the FiniteElementSpace.
Definition fespace.hpp:620
Class extending the NonlinearForm class to support the different AssemblyLevels.
This class is used to express the local action of a general nonlinear finite element operator....
Array< Array< int > * > dnfi_marker
Array< NonlinearFormIntegrator * > * GetBNFI()
Access all integrators added with AddBoundaryIntegrator().
const Array< NonlinearFormIntegrator * > * GetDNFI() const
void AddBdrFaceIntegrator(NonlinearFormIntegrator *nlfi)
Adds new Boundary Face Integrator.
FiniteElementSpace * fes
FE space on which the form lives.
virtual void Mult(const Vector &x, Vector &y) const
Evaluate the action of the NonlinearForm.
long sequence
Counter for updates propagated from the FiniteElementSpace.
bool extern_bfs
Indicates the NonlinearFormIntegrators stored in dnfi, bnfi, fnfi, and bfnfi are not owned by this No...
void AddBdrFaceIntegrator(NonlinearFormIntegrator *nfi, Array< int > &bdr_marker)
Adds new Boundary Face Integrator, restricted to specific boundary attributes.
const Array< NonlinearFormIntegrator * > * GetBNFI() const
AssemblyLevel assembly
The assembly level.
SparseMatrix * Grad
const Vector & Prolongate(const Vector &x) const
Vector aux1
Auxiliary Vectors.
const SparseMatrix * cP
The result of dynamic-casting P to SparseMatrix pointer.
NonlinearFormExtension * ext
Extension for supporting different AssemblyLevels.
void AddInteriorFaceIntegrator(NonlinearFormIntegrator *nlfi)
Adds new Interior Face Integrator.
void AddBoundaryIntegrator(NonlinearFormIntegrator *nlfi)
Adds new Boundary Integrator.
const Array< int > & GetEssentialTrueDofs() const
Return a (read-only) list of all essential true dofs.
Array< NonlinearFormIntegrator * > dnfi
Set of Domain Integrators to be assembled (added).
void AddDomainIntegrator(NonlinearFormIntegrator *nlfi, Array< int > &elem_marker)
Adds new Domain Integrator, restricted to specific attributes.
OperatorHandle hGrad
Gradient Operator when not assembled as a matrix.
FiniteElementSpace * FESpace()
const Operator * P
Pointer to the prolongation matrix of fes, may be NULL.
virtual real_t GetEnergy(const Vector &x) const
Compute the energy corresponding to the state x.
NonlinearForm(FiniteElementSpace *f)
Construct a NonlinearForm on the given FiniteElementSpace, f.
Array< NonlinearFormIntegrator * > bnfi
Set of Boundary Integrators to be assembled (added).
virtual void Update()
Update the NonlinearForm to propagate updates of the associated FE space.
const Array< NonlinearFormIntegrator * > & GetBdrFaceIntegrators() const
Access all boundary face integrators added with AddBdrFaceIntegrator().
void UseExternalIntegrators()
Indicate that integrators are not owned by the NonlinearForm.
void AddBoundaryIntegrator(NonlinearFormIntegrator *nlfi, Array< int > &elem_marker)
Adds new Boundary Integrator, restricted to specific attributes.
Array< int > ess_tdof_list
A list of all essential true dofs.
Array< Array< int > * > bfnfi_marker
virtual Operator & GetGradient(const Vector &x) const
Compute the gradient Operator of the NonlinearForm corresponding to the state x.
virtual ~NonlinearForm()
Destroy the NonlinearForm including the owned NonlinearFormIntegrators and gradient Operator.
SparseMatrix * cGrad
Array< Array< int > * > bnfi_marker
void AddDomainIntegrator(NonlinearFormIntegrator *nlfi)
Adds new Domain Integrator.
virtual const Operator * GetRestriction() const
Get the finite element space restriction matrix.
void SetAssemblyLevel(AssemblyLevel assembly_level)
Set the desired assembly level. The default is AssemblyLevel::LEGACY.
Array< NonlinearFormIntegrator * > * GetDNFI()
Access all integrators added with AddDomainIntegrator().
void SetEssentialBC(const Array< int > &bdr_attr_is_ess, Vector *rhs=NULL)
Specify essential boundary conditions.
const FiniteElementSpace * FESpace() const
Array< NonlinearFormIntegrator * > fnfi
Set of interior face Integrators to be assembled (added).
Array< NonlinearFormIntegrator * > bfnfi
Set of boundary face Integrators to be assembled (added).
void SetEssentialTrueDofs(const Array< int > &ess_tdof_list_)
Specify essential boundary conditions.
real_t GetGridFunctionEnergy(const Vector &x) const
Compute the energy corresponding to the state x.
const Array< NonlinearFormIntegrator * > & GetInteriorFaceIntegrators() const
Access all interior face integrators added with AddInteriorFaceIntegrator().
virtual void Setup()
Setup the NonlinearForm: based on the current AssemblyLevel and the current mesh, optionally,...
void SetEssentialVDofs(const Array< int > &ess_vdofs_list)
Specify essential boundary conditions.
virtual const Operator * GetProlongation() const
Get the finite element space prolongation matrix.
Pointer to an Operator of a specified type.
Definition handle.hpp:34
Abstract operator.
Definition operator.hpp:25
Data type sparse matrix.
Definition sparsemat.hpp:51
Vector data type.
Definition vector.hpp:80
AssemblyLevel
Enumeration defining the assembly level for bilinear and nonlinear form classes derived from Operator...
float real_t
Definition config.hpp:43
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30