MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
nonlinearform.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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 void Mult(const Vector &x, Vector &y) const override;
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 Operator &GetGradient(const Vector &x) const override { return GetGradient(x, true); }
221
222 /** @brief Compute the gradient Operator of the NonlinearForm corresponding
223 to the state @a x with optional finalization and elimintaion. */
224 /** @see GetGradient(const Vector &) */
225 Operator &GetGradient(const Vector &x, bool finalize) const;
226
227 /// Update the NonlinearForm to propagate updates of the associated FE space.
228 /** After calling this method, the essential boundary conditions need to be
229 set again. */
230 virtual void Update();
231
232 /** @brief Setup the NonlinearForm: based on the current AssemblyLevel and
233 the current mesh, optionally, precompute and store data that will be
234 reused in subsequent call to Mult(). */
235 /** Typically, this method has to be called before Mult() when using
236 AssemblyLevel::PARTIAL, after calling Update(), or after modifying the
237 mesh coordinates. */
238 virtual void Setup();
239
240 /// Get the finite element space prolongation matrix
241 const Operator *GetProlongation() const override { return P; }
242 /// Get the finite element space restriction matrix
243 const Operator *GetRestriction() const override
244 { return fes->GetRestrictionMatrix(); }
245
246 /// Indicate that integrators are not owned by the NonlinearForm
248
249 /** @brief Destroy the NonlinearForm including the owned
250 NonlinearFormIntegrator%s and gradient Operator. */
251 virtual ~NonlinearForm();
252};
253
254
255/** @brief A class representing a general block nonlinear operator defined on
256 the Cartesian product of multiple FiniteElementSpace%s. */
258{
259protected:
260 /// FE spaces on which the form lives.
262
263 /// Set of Domain Integrators to be assembled (added).
266
267 /// Set of Boundary Integrators to be assembled (added).
270
271 /// Set of interior face Integrators to be assembled (added).
273
274 /// Set of Boundary Face Integrators to be assembled (added).
277
278 /** Auxiliary block-vectors for wrapping input and output vectors or holding
279 GridFunction-like block-vector data (e.g. in parallel). */
280 mutable BlockVector xs, ys;
281
284
285 // A list of the offsets
288
289 // Array of Arrays of tdofs for each space in 'fes'
291
292 /// Array of pointers to the prolongation matrix of fes, may be NULL
294
295 /// Array of results of dynamic-casting P to SparseMatrix pointer
297
298 /// Indicator if the Operator is part of a parallel run
299 bool is_serial = true;
300
301 /// Indicator if the Operator needs prolongation on assembly
302 bool needs_prolongation = false;
303
305
306 const BlockVector &Prolongate(const BlockVector &bx) const;
307
308 /// Specialized version of GetEnergy() for BlockVectors
309 real_t GetEnergyBlocked(const BlockVector &bx) const;
310
311 /// Specialized version of Mult() for BlockVector%s
312 /// Block L-Vector to Block L-Vector
313 void MultBlocked(const BlockVector &bx, BlockVector &by) const;
314
315 /// Specialized version of GetGradient() for BlockVector
316 void ComputeGradientBlocked(const BlockVector &bx, bool finalize = true) const;
317
318public:
319 /// Construct an empty BlockNonlinearForm. Initialize with SetSpaces().
321
322 /// Construct a BlockNonlinearForm on the given set of FiniteElementSpace%s.
324
325 /// Return the @a k-th FE space of the BlockNonlinearForm.
326 FiniteElementSpace *FESpace(int k) { return fes[k]; }
327 /// Return the @a k-th FE space of the BlockNonlinearForm (const version).
328 const FiniteElementSpace *FESpace(int k) const { return fes[k]; }
329
330 /// (Re)initialize the BlockNonlinearForm.
331 /** After a call to SetSpaces(), the essential b.c. must be set again. */
333
334 /// Return the regular dof offsets.
335 const Array<int> &GetBlockOffsets() const { return block_offsets; }
336 /// Return the true-dof offsets.
338
339 /// Adds new Domain Integrator.
341 { dnfi.Append(nlfi); dnfi_marker.Append(NULL); }
342
343 /// Adds new Domain Integrator, restricted to specific attributes.
345 Array<int> &elem_marker)
346 { dnfi.Append(nlfi); dnfi_marker.Append(&elem_marker); }
347
348 /// Adds new Boundary Integrator.
350 { bnfi.Append(nlfi); bnfi_marker.Append(NULL); }
351
352 /// Adds new Boundary Integrator, restricted to specific attributes.
354 Array<int> &elem_marker)
355 { bnfi.Append(nlfi); bnfi_marker.Append(&elem_marker); }
356
357 /// Adds new Interior Face Integrator.
360
361 /// Adds new Boundary Face Integrator.
363 { bfnfi.Append(nlfi); bfnfi_marker.Append(NULL); }
364
365 /** @brief Adds new Boundary Face Integrator, restricted to specific boundary
366 attributes. */
368 Array<int> &bdr_marker)
369 { bfnfi.Append(nlfi); bfnfi_marker.Append(&bdr_marker); }
370
371 /** @brief Set essential boundary conditions to each finite element space
372 using boundary attribute markers.
373
374 This method calls `FiniteElementSpace::GetEssentialTrueDofs()` for each
375 space and stores ess_tdof_lists internally.
376
377 If `rhs` vectors are non-null, the entries corresponding to these
378 essential DoFs are set to zero. This ensures compatibility with the
379 output of the `Mult()` method, which also zeroes out these entries.
380
381 @param[in] bdr_attr_is_ess A list of boundary attribute markers for each
382 space.
383 @param[in,out] rhs An array of optional right-hand side vectors.
384 If a vector at `rhs[i]` is non-null, its essential DoFs will be set
385 to zero. */
386 virtual void SetEssentialBC(const Array<Array<int>*> &bdr_attr_is_ess,
387 Array<Vector*> &rhs);
388
389 /** @brief Set essential boundary conditions to each finite element space
390 using essential true dof lists.
391
392 This method stores a copy of the provided essential true dof lists.
393
394 If `rhs` vectors are non-null, the entries corresponding to these
395 essential DoFs are set to zero. This ensures compatibility with the
396 output of the `Mult()` method, which also zeroes out these entries.
397
398 @param[in] ess_tdof_list A list of essential true dofs for each space.
399 @param[in,out] rhs An array of optional right-hand side vectors.
400 If a vector at `rhs[i]` is non-null, its essential DoFs will be set
401 to zero. */
402 virtual void SetEssentialTrueDofs(const Array<Array<int>*> &ess_tdof_list,
403 Array<Vector*> &rhs);
404
405 virtual real_t GetEnergy(const Vector &x) const;
406
407 /// Method is only called in serial, the parallel version calls MultBlocked
408 /// directly.
409 void Mult(const Vector &x, Vector &y) const override;
410
411 /// Method is only called in serial, the parallel version calls
412 /// GetGradientBlocked directly.
413 Operator &GetGradient(const Vector &x) const override;
414
415 /// Destructor.
416 virtual ~BlockNonlinearForm();
417};
418
419
420}
421
422#endif
Dynamic 2D array using row-major layout.
Definition array.hpp:430
void Copy(Array &copy) const
Create a copy of the internal array to the provided copy.
Definition array.hpp:1042
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.
void Mult(const Vector &x, Vector &y) const override
FiniteElementSpace * FESpace(int k)
Return the k-th FE space of the BlockNonlinearForm.
Operator & GetGradient(const Vector &x) const override
void AddDomainIntegrator(BlockNonlinearFormIntegrator *nlfi)
Adds new Domain Integrator.
Array< FiniteElementSpace * > fes
FE spaces on which the form lives.
real_t GetEnergyBlocked(const BlockVector &bx) const
Specialized version of GetEnergy() for BlockVectors.
void ComputeGradientBlocked(const BlockVector &bx, bool finalize=true) const
Specialized version of GetGradient() for BlockVector.
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)
Set essential boundary conditions to each finite element space using boundary attribute markers.
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 void SetEssentialTrueDofs(const Array< Array< int > * > &ess_tdof_list, Array< Vector * > &rhs)
Set essential boundary conditions to each finite element space using essential true dof lists.
virtual real_t GetEnergy(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().
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:208
virtual const SparseMatrix * GetRestrictionMatrix() const
The returned SparseMatrix is owned by the FiniteElementSpace.
Definition fespace.hpp:719
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.
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.
const Operator * GetRestriction() const override
Get the finite element space restriction matrix.
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.
Operator & GetGradient(const Vector &x) const override
Compute the gradient Operator of the NonlinearForm corresponding to the state x.
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.
const Operator * GetProlongation() const override
Get the finite element space prolongation matrix.
Array< Array< int > * > bfnfi_marker
virtual ~NonlinearForm()
Destroy the NonlinearForm including the owned NonlinearFormIntegrators and gradient Operator.
SparseMatrix * cGrad
Array< Array< int > * > bnfi_marker
void Mult(const Vector &x, Vector &y) const override
Evaluate the action of the NonlinearForm.
void AddDomainIntegrator(NonlinearFormIntegrator *nlfi)
Adds new Domain Integrator.
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.
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:82
AssemblyLevel
Enumeration defining the assembly level for bilinear and nonlinear form classes derived from Operator...
float real_t
Definition config.hpp:46
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30