Files
mfem/fem/coefficient.hpp
T

2637 lines
93 KiB
C++

// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#ifndef MFEM_COEFFICIENT
#define MFEM_COEFFICIENT
#include <functional>
#include "../config/config.hpp"
#include "../linalg/linalg.hpp"
#include "intrules.hpp"
#include "eltrans.hpp"
namespace mfem
{
class Mesh;
class QuadratureSpaceBase;
class QuadratureFunction;
#ifdef MFEM_USE_MPI
class ParMesh;
#endif
/** @brief Base class Coefficients that optionally depend on space and time.
These are used by the BilinearFormIntegrator, LinearFormIntegrator, and
NonlinearFormIntegrator classes to represent the physical coefficients in
the PDEs that are being discretized. This class can also be used in a more
general way to represent functions that don't necessarily belong to a FE
space, e.g., to project onto GridFunctions to use as initial conditions,
exact solutions, etc. See, e.g., ex4 or ex22 for these uses. */
class Coefficient
{
protected:
real_t time;
public:
Coefficient() { time = 0.; }
/// Set the time for time dependent coefficients
virtual void SetTime(real_t t) { time = t; }
/// Get the time for time dependent coefficients
real_t GetTime() { return time; }
/** @brief Evaluate the coefficient in the element described by @a T at the
point @a ip. */
/** @note When this method is called, the caller must make sure that the
IntegrationPoint associated with @a T is the same as @a ip. This can be
achieved by calling T.SetIntPoint(&ip). */
virtual real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) = 0;
/** @brief Evaluate the coefficient in the element described by @a T at the
point @a ip at time @a t. */
/** @note When this method is called, the caller must make sure that the
IntegrationPoint associated with @a T is the same as @a ip. This can be
achieved by calling T.SetIntPoint(&ip). */
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip, real_t t)
{
SetTime(t);
return Eval(T, ip);
}
/// @brief Fill the QuadratureFunction @a qf by evaluating the coefficient at
/// the quadrature points.
virtual void Project(QuadratureFunction &qf);
virtual ~Coefficient() { }
};
/// A coefficient that is constant across space and time
class ConstantCoefficient : public Coefficient
{
public:
real_t constant;
/// c is value of constant function
explicit ConstantCoefficient(real_t c = 1.0) { constant=c; }
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override
{ return (constant); }
/// Fill the QuadratureFunction @a qf with the constant value.
void Project(QuadratureFunction &qf) override;
};
/** @brief A piecewise constant coefficient with the constants keyed
off the element attribute numbers. */
class PWConstCoefficient : public Coefficient
{
private:
Vector constants;
public:
/// Constructs a piecewise constant coefficient in NumOfSubD subdomains
explicit PWConstCoefficient(int NumOfSubD = 0) : constants(NumOfSubD)
{ constants = 0.0; }
/// Construct the constant coefficient using a vector of constants.
/** @a c should be a vector defined by attributes, so for region with
attribute @a i @a c[i-1] is the coefficient in that region */
PWConstCoefficient(const Vector &c) { UpdateConstants(c); }
/// Update the constants with vector @a c.
void UpdateConstants(const Vector &c) { constants = c; }
/// Return a reference to the i-th constant
real_t &operator()(int i) { return constants(i-1); }
/// Set the constants for all attributes to constant @a c.
void operator=(real_t c) { constants = c; }
/// Returns the number of constants representing different attributes.
int GetNConst() { return constants.Size(); }
/// Evaluate the coefficient.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
/// Fill the QuadratureFunction @a qf with the piecewise constant values.
void Project(QuadratureFunction &qf) override;
};
/** @brief A piecewise coefficient with the pieces keyed off the element
attribute numbers.
A value of zero will be returned for any missing attribute numbers.
This object will not assume ownership of any Coefficient objects
passed to it. Consequently, the caller must ensure that the
individual Coefficient objects are not deleted while this
PWCoefficient is still in use.
\note The keys may either be domain attribute numbers or boundary
attribute numbers. If the PWCoefficient is used with a domain
integrator the keys are assumed to be domain attribute
numbers. Similarly, if the PWCoefficient is used with a boundary
integrator the keys are assumed to be boundary attribute numbers.
*/
class PWCoefficient : public Coefficient
{
private:
/** Internal data structure to store pointers to the appropriate
coefficients for different regions of the mesh. The keys used
in the map are the mesh attribute numbers (either element
attribute or boundary element attribute depending upon
context). The values returned for any missing attributes will
be zero. The coefficient pointers may be NULL in which case a
value of zero is returned.
The Coefficient objects contained in this map are NOT owned by
this PWCoefficient object. This means that they will not be
deleted when this object is deleted also the caller must ensure
that the various Coefficient objects are not deleted while this
PWCoefficient is still needed.
*/
std::map<int, Coefficient*> pieces;
/** Convenience function to check for compatible array lengths,
loop over the arrays, and add their attribute/Coefficient pairs
to the internal data structure.
*/
void InitMap(const Array<int> & attr,
const Array<Coefficient*> & coefs);
public:
/// Constructs a piecewise coefficient
explicit PWCoefficient() {}
/// Construct the coefficient using arrays describing the pieces
/** \param attr - an array of attribute numbers for each piece
\param coefs - the corresponding array of Coefficient pointers
Any missing attributes or NULL coefficient pointers will result in a
value of zero being returned for that attribute.
\note Ownership of the Coefficient objects will NOT be
transferred to this object.
*/
PWCoefficient(const Array<int> & attr,
const Array<Coefficient*> & coefs)
{ InitMap(attr, coefs); }
/// Set the time for time dependent coefficients
void SetTime(real_t t) override;
/// Replace a set of coefficients
void UpdateCoefficients(const Array<int> & attr,
const Array<Coefficient*> & coefs)
{ InitMap(attr, coefs); }
/// Replace a single Coefficient for a particular attribute
void UpdateCoefficient(int attr, Coefficient & coef)
{ pieces[attr] = &coef; }
/// Remove a single Coefficient for a particular attribute
void ZeroCoefficient(int attr)
{ pieces.erase(attr); }
/// Evaluate the coefficient.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// A general function coefficient
class FunctionCoefficient : public Coefficient
{
protected:
std::function<real_t(const Vector &)> Function;
std::function<real_t(const Vector &, real_t)> TDFunction;
public:
/// Define a time-independent coefficient from a std function
/** \param F time-independent std::function */
FunctionCoefficient(std::function<real_t(const Vector &)> F)
: Function(std::move(F))
{ }
/// Define a time-dependent coefficient from a std function
/** \param TDF time-dependent function */
FunctionCoefficient(std::function<real_t(const Vector &, real_t)> TDF)
: TDFunction(std::move(TDF))
{ }
/// (DEPRECATED) Define a time-independent coefficient from a C-function
/** @deprecated Use the method where the C-function, @a f, uses a const
Vector argument instead of Vector. */
MFEM_DEPRECATED FunctionCoefficient(real_t (*f)(Vector &))
{
// Cast first to (void*) to suppress a warning from newer version of
// Clang when using -Wextra.
Function = reinterpret_cast<real_t(*)(const Vector&)>((void*)f);
TDFunction = NULL;
}
/// (DEPRECATED) Define a time-dependent coefficient from a C-function
/** @deprecated Use the method where the C-function, @a tdf, uses a const
Vector argument instead of Vector. */
MFEM_DEPRECATED FunctionCoefficient(real_t (*tdf)(Vector &, real_t))
{
Function = NULL;
// Cast first to (void*) to suppress a warning from newer version of
// Clang when using -Wextra.
TDFunction =
reinterpret_cast<real_t(*)(const Vector&,real_t)>((void*)tdf);
}
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// A common base class for returning individual components of the domain's
/// Cartesian coordinates.
class CartesianCoefficient : public Coefficient
{
protected:
int comp;
mutable Vector transip;
/// @a comp_ index of the desired component (0 -> x, 1 -> y, 2 -> z)
CartesianCoefficient(int comp_) : comp(comp_), transip(3) {}
public:
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Scalar coefficient which returns the x-component of the evaluation point
class CartesianXCoefficient : public CartesianCoefficient
{
public:
CartesianXCoefficient() : CartesianCoefficient(0) {}
};
/// Scalar coefficient which returns the y-component of the evaluation point
class CartesianYCoefficient : public CartesianCoefficient
{
public:
CartesianYCoefficient() : CartesianCoefficient(1) {}
};
/// Scalar coefficient which returns the z-component of the evaluation point
class CartesianZCoefficient : public CartesianCoefficient
{
public:
CartesianZCoefficient() : CartesianCoefficient(2) {}
};
/// Scalar coefficient which returns the radial distance from the axis of
/// the evaluation point in the cylindrical coordinate system
class CylindricalRadialCoefficient : public Coefficient
{
private:
mutable Vector transip;
public:
CylindricalRadialCoefficient() : transip(3) {}
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Scalar coefficient which returns the angular position or azimuth (often
/// denoted by theta) of the evaluation point in the cylindrical coordinate
/// system
class CylindricalAzimuthalCoefficient : public Coefficient
{
private:
mutable Vector transip;
public:
CylindricalAzimuthalCoefficient() : transip(3) {}
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Scalar coefficient which returns the height or altitude of
/// the evaluation point in the cylindrical coordinate system
typedef CartesianZCoefficient CylindricalZCoefficient;
/// Scalar coefficient which returns the radial distance from the origin of
/// the evaluation point in the spherical coordinate system
class SphericalRadialCoefficient : public Coefficient
{
private:
mutable Vector transip;
public:
SphericalRadialCoefficient() : transip(3) {}
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Scalar coefficient which returns the azimuthal angle (often denoted by phi)
/// of the evaluation point in the spherical coordinate system
class SphericalAzimuthalCoefficient : public Coefficient
{
private:
mutable Vector transip;
public:
SphericalAzimuthalCoefficient() : transip(3) {}
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Scalar coefficient which returns the polar angle (often denoted by theta)
/// of the evaluation point in the spherical coordinate system
class SphericalPolarCoefficient : public Coefficient
{
private:
mutable Vector transip;
public:
SphericalPolarCoefficient() : transip(3) {}
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
};
class GridFunction;
/// Coefficient defined by a GridFunction. This coefficient is mesh dependent.
class GridFunctionCoefficient : public Coefficient
{
private:
const GridFunction *GridF;
int Component;
public:
GridFunctionCoefficient() : GridF(NULL), Component(1) { }
/** Construct GridFunctionCoefficient from a given GridFunction, and
optionally specify a component to use if it is a vector GridFunction. */
GridFunctionCoefficient (const GridFunction *gf, int comp = 1)
{ GridF = gf; Component = comp; }
/// Set the internal GridFunction
void SetGridFunction(const GridFunction *gf) { GridF = gf; }
/// Get the internal GridFunction
const GridFunction * GetGridFunction() const { return GridF; }
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
/// @brief Fill the QuadratureFunction @a qf by evaluating the coefficient at
/// the quadrature points.
///
/// This function uses the efficient QuadratureFunction::ProjectGridFunction
/// to fill the QuadratureFunction.
void Project(QuadratureFunction &qf) override;
};
/** @brief A coefficient that depends on 1 or 2 parent coefficients and a
transformation rule represented by a C-function.
$ C(x,t) = T(Q1(x,t)) $ or $ C(x,t) = T(Q1(x,t), Q2(x,t)) $
where T is the transformation rule, and Q1/Q2 are the parent coefficients.*/
class TransformedCoefficient : public Coefficient
{
private:
Coefficient * Q1;
Coefficient * Q2;
std::function<real_t(real_t)> Transform1;
std::function<real_t(real_t, real_t)> Transform2;
public:
TransformedCoefficient (Coefficient * q, std::function<real_t(real_t)> F)
: Q1(q), Transform1(std::move(F)) { Q2 = 0; Transform2 = 0; }
TransformedCoefficient (Coefficient * q1,Coefficient * q2,
std::function<real_t(real_t, real_t)> F)
: Q1(q1), Q2(q2), Transform2(std::move(F)) { Transform1 = 0; }
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T, const IntegrationPoint &ip) override;
};
/** @brief Delta function coefficient optionally multiplied by a weight
coefficient and a scaled time dependent C-function.
$ F(x,t) = w(x,t) s T(t) d(x - xc) $
where w is the optional weight coefficient, @a s is a scale factor
T is an optional time-dependent function and d is a delta function.
WARNING this cannot be used as a normal coefficient. The usual Eval
method is disabled. */
class DeltaCoefficient : public Coefficient
{
protected:
real_t center[3], scale, tol;
Coefficient *weight;
int sdim;
real_t (*tdf)(real_t);
public:
/// Construct a unit delta function centered at (0.0,0.0,0.0)
DeltaCoefficient()
{
center[0] = center[1] = center[2] = 0.; scale = 1.; tol = 1e-12;
weight = NULL; sdim = 0; tdf = NULL;
}
/// Construct a delta function scaled by @a s and centered at (x,0.0,0.0)
DeltaCoefficient(real_t x, real_t s)
{
center[0] = x; center[1] = 0.; center[2] = 0.; scale = s; tol = 1e-12;
weight = NULL; sdim = 1; tdf = NULL;
}
/// Construct a delta function scaled by @a s and centered at (x,y,0.0)
DeltaCoefficient(real_t x, real_t y, real_t s)
{
center[0] = x; center[1] = y; center[2] = 0.; scale = s; tol = 1e-12;
weight = NULL; sdim = 2; tdf = NULL;
}
/// Construct a delta function scaled by @a s and centered at (x,y,z)
DeltaCoefficient(real_t x, real_t y, real_t z, real_t s)
{
center[0] = x; center[1] = y; center[2] = z; scale = s; tol = 1e-12;
weight = NULL; sdim = 3; tdf = NULL;
}
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Set the center location of the delta function.
void SetDeltaCenter(const Vector& center);
/// Set the scale value multiplying the delta function.
void SetScale(real_t s_) { scale = s_; }
/// Set a time-dependent function that multiplies the Scale().
void SetFunction(real_t (*f)(real_t)) { tdf = f; }
/** @brief Set the tolerance used during projection onto GridFunction to
identify the Mesh vertex where the Center() of the delta function
lies. (default 1e-12)*/
void SetTol(real_t tol_) { tol = tol_; }
/// Set a weight Coefficient that multiplies the DeltaCoefficient.
/** The weight Coefficient multiplies the value returned by EvalDelta() but
not the value returned by Scale().
The weight Coefficient is also used as the L2-weight function when
projecting the DeltaCoefficient onto a GridFunction, so that the weighted
integral of the projection is exactly equal to the Scale(). */
void SetWeight(Coefficient *w) { weight = w; }
/// Return a pointer to a c-array representing the center of the delta
/// function.
const real_t *Center() { return center; }
/** @brief Return the scale factor times the optional time dependent
function. Returns $ s T(t) $ with $ T(t) = 1 $ when
not set by the user. */
real_t Scale() { return tdf ? (*tdf)(GetTime())*scale : scale; }
/// Return the tolerance used to identify the mesh vertices
real_t Tol() { return tol; }
/// See SetWeight() for description of the weight Coefficient.
Coefficient *Weight() { return weight; }
/// Write the center of the delta function into @a center.
void GetDeltaCenter(Vector& center);
/// The value of the function assuming we are evaluating at the delta center.
virtual real_t EvalDelta(ElementTransformation &T, const IntegrationPoint &ip);
/** @brief A DeltaFunction cannot be evaluated. Calling this method will
cause an MFEM error, terminating the application. */
real_t Eval(ElementTransformation &T, const IntegrationPoint &ip) override
{ mfem_error("DeltaCoefficient::Eval"); return 0.; }
virtual ~DeltaCoefficient() { delete weight; }
};
/** @brief Derived coefficient that takes the value of the parent coefficient
for the active attributes and is zero otherwise. */
class RestrictedCoefficient : public Coefficient
{
private:
Coefficient *c;
Array<int> active_attr;
public:
/** @brief Construct with a parent coefficient and an array with
ones marking the attributes on which this coefficient should be
active. */
RestrictedCoefficient(Coefficient &c_, Array<int> &attr)
{ c = &c_; attr.Copy(active_attr); }
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T, const IntegrationPoint &ip) override
{ return active_attr[T.Attribute-1] ? c->Eval(T, ip, GetTime()) : 0.0; }
};
/// Base class for vector Coefficients that optionally depend on time and space.
class VectorCoefficient
{
protected:
int vdim;
real_t time;
public:
/// Initialize the VectorCoefficient with vector dimension @a vd.
VectorCoefficient(int vd) { vdim = vd; time = 0.; }
/// Set the time for time dependent coefficients
virtual void SetTime(real_t t) { time = t; }
/// Get the time for time dependent coefficients
real_t GetTime() { return time; }
/// Returns dimension of the vector.
int GetVDim() { return vdim; }
/** @brief Evaluate the vector coefficient in the element described by @a T
at the point @a ip, storing the result in @a V. */
/** @note When this method is called, the caller must make sure that the
IntegrationPoint associated with @a T is the same as @a ip. This can be
achieved by calling T.SetIntPoint(&ip). */
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) = 0;
/** @brief Evaluate the vector coefficient in the element described by @a T
at all points of @a ir, storing the result in @a M. */
/** The dimensions of @a M are GetVDim() by ir.GetNPoints() and they must be
set by the implementation of this method.
The general implementation provided by the base class (using the Eval
method for one IntegrationPoint at a time) can be overloaded for more
efficient implementation.
@note The IntegrationPoint associated with @a T is not used, and this
method will generally modify this IntegrationPoint associated with @a T.
*/
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationRule &ir);
/// @brief Fill the QuadratureFunction @a qf by evaluating the coefficient at
/// the quadrature points.
///
/// The @a vdim of the VectorCoefficient should be equal to the @a vdim of
/// the QuadratureFunction.
virtual void Project(QuadratureFunction &qf);
virtual ~VectorCoefficient() { }
};
/// Vector coefficient that is constant in space and time.
class VectorConstantCoefficient : public VectorCoefficient
{
private:
Vector vec;
public:
/// Construct the coefficient with constant vector @a v.
VectorConstantCoefficient(const Vector &v)
: VectorCoefficient(v.Size()), vec(v) { }
using VectorCoefficient::Eval;
/// Evaluate the vector coefficient at @a ip.
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override { V = vec; }
/// Return a reference to the constant vector in this class.
const Vector& GetVec() const { return vec; }
};
/** @brief A piecewise vector-valued coefficient with the pieces keyed off the
element attribute numbers.
A value of zero will be returned for any missing attribute numbers.
This object will not assume ownership of any VectorCoefficient
objects passed to it. Consequently, the caller must ensure that
the individual VectorCoefficient objects are not deleted while
this PWVectorCoefficient is still in use.
\note The keys may either be domain attribute numbers or boundary
attribute numbers. If the PWVectorCoefficient is used with a
domain integrator the keys are assumed to be domain attribute
numbers. Similarly, if the PWVectorCoefficient is used with a
boundary integrator the keys are assumed to be boundary attribute
numbers.
*/
class PWVectorCoefficient : public VectorCoefficient
{
private:
/** Internal data structure to store pointers to the appropriate
coefficients for different regions of the mesh. The keys used
in the map are the mesh attribute numbers (either element
attribute or boundary element attribute depending upon
context). The values returned for any missing attributes will
be zero. The coefficient pointers may be NULL in which case a
value of zero is returned.
The VectorCoefficient objects contained in this map are NOT
owned by this PWVectorCoefficient object. This means that they
will not be deleted when this object is deleted also the caller
must ensure that the various VectorCoefficient objects are not
deleted while this PWVectorCoefficient is still needed.
*/
std::map<int, VectorCoefficient*> pieces;
/** Convenience function to check for compatible array lengths,
loop over the arrays, and add their attribute/VectorCoefficient
pairs to the internal data structure.
*/
void InitMap(const Array<int> & attr,
const Array<VectorCoefficient*> & coefs);
public:
/// Constructs a piecewise vector coefficient of dimension vd
explicit PWVectorCoefficient(int vd): VectorCoefficient(vd) {}
/// Construct the coefficient using arrays describing the pieces
/** \param vd - dimension of the vector-valued result
\param attr - an array of attribute numbers for each piece
\param coefs - the corresponding array of VectorCoefficient pointers
Any missing attributes or NULL coefficient pointers will result in a
zero vector being returned for that attribute.
\note Ownership of the VectorCoefficient objects will NOT be
transferred to this object.
*/
PWVectorCoefficient(int vd, const Array<int> & attr,
const Array<VectorCoefficient*> & coefs)
: VectorCoefficient(vd) { InitMap(attr, coefs); }
/// Set the time for time dependent coefficients
void SetTime(real_t t) override;
/// Replace a set of coefficients
void UpdateCoefficients(const Array<int> & attr,
const Array<VectorCoefficient*> & coefs)
{ InitMap(attr, coefs); }
/// Replace a single Coefficient for a particular attribute
void UpdateCoefficient(int attr, VectorCoefficient & coef);
/// Remove a single VectorCoefficient for a particular attribute
void ZeroCoefficient(int attr)
{ pieces.erase(attr); }
/// Evaluate the coefficient.
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
using VectorCoefficient::Eval;
};
/// A vector coefficient which returns the physical location of the
/// evaluation point in the Cartesian coordinate system.
class PositionVectorCoefficient : public VectorCoefficient
{
public:
PositionVectorCoefficient(int dim) : VectorCoefficient(dim) {}
using VectorCoefficient::Eval;
/// Evaluate the vector coefficient at @a ip.
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
virtual ~PositionVectorCoefficient() { }
};
/// A general vector function coefficient
class VectorFunctionCoefficient : public VectorCoefficient
{
private:
std::function<void(const Vector &, Vector &)> Function;
std::function<void(const Vector &, real_t, Vector &)> TDFunction;
Coefficient *Q;
public:
/// Define a time-independent vector coefficient from a std function
/** \param dim - the size of the vector
\param F - time-independent function
\param q - optional scalar Coefficient to scale the vector coefficient */
VectorFunctionCoefficient(int dim,
std::function<void(const Vector &, Vector &)> F,
Coefficient *q = nullptr)
: VectorCoefficient(dim), Function(std::move(F)), Q(q)
{ }
/// Define a time-dependent vector coefficient from a std function
/** \param dim - the size of the vector
\param TDF - time-dependent function
\param q - optional scalar Coefficient to scale the vector coefficient */
VectorFunctionCoefficient(int dim,
std::function<void(const Vector &, real_t, Vector &)> TDF,
Coefficient *q = nullptr)
: VectorCoefficient(dim), TDFunction(std::move(TDF)), Q(q)
{ }
using VectorCoefficient::Eval;
/// Evaluate the vector coefficient at @a ip.
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
virtual ~VectorFunctionCoefficient() { }
};
/** @brief Vector coefficient defined by an array of scalar coefficients.
Coefficients that are not set will evaluate to zero in the vector. This
object takes ownership of the array of coefficients inside it and deletes
them at object destruction. */
class VectorArrayCoefficient : public VectorCoefficient
{
private:
Array<Coefficient*> Coeff;
Array<bool> ownCoeff;
public:
/** @brief Construct vector of dim coefficients. The actual coefficients
still need to be added with Set(). */
explicit VectorArrayCoefficient(int dim);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Returns i'th coefficient.
Coefficient* GetCoeff(int i) { return Coeff[i]; }
/// Returns the entire array of coefficients.
Coefficient **GetCoeffs() { return Coeff; }
/// Sets coefficient in the vector.
void Set(int i, Coefficient *c, bool own=true);
/// Set ownership of the i'th coefficient
void SetOwnership(int i, bool own) { ownCoeff[i] = own; }
/// Get ownership of the i'th coefficient
bool GetOwnership(int i) const { return ownCoeff[i]; }
/// Evaluates i'th component of the vector of coefficients and returns the
/// value.
real_t Eval(int i, ElementTransformation &T, const IntegrationPoint &ip)
{ return Coeff[i] ? Coeff[i]->Eval(T, ip, GetTime()) : 0.0; }
using VectorCoefficient::Eval;
/** @brief Evaluate the coefficient. Each element of vector V comes from the
associated array of scalar coefficients. */
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
/// Destroys vector coefficient.
virtual ~VectorArrayCoefficient();
};
/// Vector coefficient defined by a vector GridFunction
class VectorGridFunctionCoefficient : public VectorCoefficient
{
protected:
const GridFunction *GridFunc;
public:
/** @brief Construct an empty coefficient. Calling Eval() before the grid
function is set will cause a segfault. */
VectorGridFunctionCoefficient() : VectorCoefficient(0), GridFunc(NULL) { }
/** @brief Construct the coefficient with grid function @a gf. The
grid function is not owned by the coefficient. */
VectorGridFunctionCoefficient(const GridFunction *gf);
/** @brief Set the grid function for this coefficient. Also sets the Vector
dimension to match that of the @a gf. */
void SetGridFunction(const GridFunction *gf);
/// Returns a pointer to the grid function in this Coefficient
const GridFunction * GetGridFunction() const { return GridFunc; }
/// Evaluate the vector coefficient at @a ip.
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
/** @brief Evaluate the vector coefficients at all of the locations in the
integration rule and write the vectors into the columns of matrix @a
M. */
void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationRule &ir) override;
/// @brief Fill the QuadratureFunction @a qf by evaluating the coefficient at
/// the quadrature points.
///
/// This function uses the efficient QuadratureFunction::ProjectGridFunction
/// to fill the QuadratureFunction.
void Project(QuadratureFunction &qf) override;
virtual ~VectorGridFunctionCoefficient() { }
};
/// Vector coefficient defined as the Gradient of a scalar GridFunction
class GradientGridFunctionCoefficient : public VectorCoefficient
{
protected:
const GridFunction *GridFunc;
public:
/** @brief Construct the coefficient with a scalar grid function @a gf. The
grid function is not owned by the coefficient. */
GradientGridFunctionCoefficient(const GridFunction *gf);
///Set the scalar grid function.
void SetGridFunction(const GridFunction *gf);
///Get the scalar grid function.
const GridFunction * GetGridFunction() const { return GridFunc; }
/// Evaluate the gradient vector coefficient at @a ip.
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
/** @brief Evaluate the gradient vector coefficient at all of the locations
in the integration rule and write the vectors into columns of matrix @a
M. */
void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationRule &ir) override;
/// @copydoc VectorCoefficient::Project(QuadratureFunction &)
void Project(QuadratureFunction &qf) override;
virtual ~GradientGridFunctionCoefficient() { }
};
/// Vector coefficient defined as the Curl of a vector GridFunction
class CurlGridFunctionCoefficient : public VectorCoefficient
{
protected:
const GridFunction *GridFunc;
public:
/** @brief Construct the coefficient with a vector grid function @a gf. The
grid function is not owned by the coefficient. */
CurlGridFunctionCoefficient(const GridFunction *gf);
/// Set the vector grid function.
void SetGridFunction(const GridFunction *gf);
/// Get the vector grid function.
const GridFunction * GetGridFunction() const { return GridFunc; }
using VectorCoefficient::Eval;
/// Evaluate the vector curl coefficient at @a ip.
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
virtual ~CurlGridFunctionCoefficient() { }
};
/// Scalar coefficient defined as the Divergence of a vector GridFunction
class DivergenceGridFunctionCoefficient : public Coefficient
{
protected:
const GridFunction *GridFunc;
public:
/** @brief Construct the coefficient with a vector grid function @a gf. The
grid function is not owned by the coefficient. */
DivergenceGridFunctionCoefficient(const GridFunction *gf);
/// Set the vector grid function.
void SetGridFunction(const GridFunction *gf) { GridFunc = gf; }
/// Get the vector grid function.
const GridFunction * GetGridFunction() const { return GridFunc; }
/// Evaluate the scalar divergence coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
virtual ~DivergenceGridFunctionCoefficient() { }
};
/** @brief Vector coefficient defined by a scalar DeltaCoefficient and a
constant vector direction.
WARNING this cannot be used as a normal coefficient. The usual Eval method
is disabled. */
class VectorDeltaCoefficient : public VectorCoefficient
{
protected:
Vector dir;
DeltaCoefficient d;
public:
/// Construct with a vector of dimension @a vdim_.
VectorDeltaCoefficient(int vdim_)
: VectorCoefficient(vdim_), dir(vdim_), d() { }
/** @brief Construct with a Vector object representing the direction and a
unit delta function centered at (0.0,0.0,0.0) */
VectorDeltaCoefficient(const Vector& dir_)
: VectorCoefficient(dir_.Size()), dir(dir_), d() { }
/** @brief Construct with a Vector object representing the direction and a
delta function scaled by @a s and centered at (x,0.0,0.0) */
VectorDeltaCoefficient(const Vector& dir_, real_t x, real_t s)
: VectorCoefficient(dir_.Size()), dir(dir_), d(x,s) { }
/** @brief Construct with a Vector object representing the direction and a
delta function scaled by @a s and centered at (x,y,0.0) */
VectorDeltaCoefficient(const Vector& dir_, real_t x, real_t y, real_t s)
: VectorCoefficient(dir_.Size()), dir(dir_), d(x,y,s) { }
/** @brief Construct with a Vector object representing the direction and a
delta function scaled by @a s and centered at (x,y,z) */
VectorDeltaCoefficient(const Vector& dir_, real_t x, real_t y, real_t z,
real_t s)
: VectorCoefficient(dir_.Size()), dir(dir_), d(x,y,z,s) { }
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Replace the associated DeltaCoefficient with a new DeltaCoefficient.
/** The new DeltaCoefficient cannot have a specified weight Coefficient, i.e.
DeltaCoefficient::Weight() should return NULL. */
void SetDeltaCoefficient(const DeltaCoefficient& d_) { d = d_; }
/// Return the associated scalar DeltaCoefficient.
DeltaCoefficient& GetDeltaCoefficient() { return d; }
void SetScale(real_t s) { d.SetScale(s); }
void SetDirection(const Vector& d_);
void SetDeltaCenter(const Vector& center) { d.SetDeltaCenter(center); }
void GetDeltaCenter(Vector& center) { d.GetDeltaCenter(center); }
/** @brief Return the specified direction vector multiplied by the value
returned by DeltaCoefficient::EvalDelta() of the associated scalar
DeltaCoefficient. */
virtual void EvalDelta(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
using VectorCoefficient::Eval;
/** @brief A VectorDeltaFunction cannot be evaluated. Calling this method
will cause an MFEM error, terminating the application. */
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override
{ mfem_error("VectorDeltaCoefficient::Eval"); }
virtual ~VectorDeltaCoefficient() { }
};
/** @brief Derived vector coefficient that has the value of the parent vector
where it is active and is zero otherwise. */
class VectorRestrictedCoefficient : public VectorCoefficient
{
private:
VectorCoefficient *c;
Array<int> active_attr;
public:
/** @brief Construct with a parent vector coefficient and an array of zeros
and ones representing the attributes for which this coefficient should be
active. */
VectorRestrictedCoefficient(VectorCoefficient &vc, Array<int> &attr)
: VectorCoefficient(vc.GetVDim())
{ c = &vc; attr.Copy(active_attr); }
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Evaluate the vector coefficient at @a ip.
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
/** @brief Evaluate the vector coefficient at all of the locations in the
integration rule and write the vectors into the columns of matrix @a
M. */
void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationRule &ir) override;
};
typedef VectorCoefficient DiagonalMatrixCoefficient;
/// Base class for Matrix Coefficients that optionally depend on time and space.
class MatrixCoefficient
{
protected:
int height, width;
real_t time;
bool symmetric; // deprecated
public:
/// Construct a dim x dim matrix coefficient.
explicit MatrixCoefficient(int dim, bool symm=false)
{ height = width = dim; time = 0.; symmetric = symm; }
/// Construct a h x w matrix coefficient.
MatrixCoefficient(int h, int w, bool symm=false) :
height(h), width(w), time(0.), symmetric(symm) { }
/// Set the time for time dependent coefficients
virtual void SetTime(real_t t) { time = t; }
/// Get the time for time dependent coefficients
real_t GetTime() { return time; }
/// Get the height of the matrix.
int GetHeight() const { return height; }
/// Get the width of the matrix.
int GetWidth() const { return width; }
/// For backward compatibility get the width of the matrix.
int GetVDim() const { return width; }
/** @deprecated Use SymmetricMatrixCoefficient instead */
bool IsSymmetric() const { return symmetric; }
/** @brief Evaluate the matrix coefficient in the element described by @a T
at the point @a ip, storing the result in @a K. */
/** @note When this method is called, the caller must make sure that the
IntegrationPoint associated with @a T is the same as @a ip. This can be
achieved by calling T.SetIntPoint(&ip). */
virtual void Eval(DenseMatrix &K, ElementTransformation &T,
const IntegrationPoint &ip) = 0;
/// @brief Fill the QuadratureFunction @a qf by evaluating the coefficient at
/// the quadrature points. The matrix will be transposed or not according to
/// the boolean argument @a transpose.
///
/// The @a vdim of the QuadratureFunction should be equal to the height times
/// the width of the matrix.
virtual void Project(QuadratureFunction &qf, bool transpose=false);
/// (DEPRECATED) Evaluate a symmetric matrix coefficient.
/** @brief Evaluate the upper triangular entries of the matrix coefficient
in the symmetric case, similarly to Eval. Matrix entry (i,j) is stored
in K[j - i + os_i] for 0 <= i <= j < width, os_0 = 0,
os_{i+1} = os_i + width - i. That is, K = {M(0,0), ..., M(0,w-1),
M(1,1), ..., M(1,w-1), ..., M(w-1,w-1) with w = width.
@deprecated Use Eval() instead. */
virtual void EvalSymmetric(Vector &K, ElementTransformation &T,
const IntegrationPoint &ip)
{ mfem_error("MatrixCoefficient::EvalSymmetric"); }
virtual ~MatrixCoefficient() { }
};
/// A matrix coefficient that is constant in space and time.
class MatrixConstantCoefficient : public MatrixCoefficient
{
private:
DenseMatrix mat;
public:
///Construct using matrix @a m for the constant.
MatrixConstantCoefficient(const DenseMatrix &m)
: MatrixCoefficient(m.Height(), m.Width()), mat(m) { }
using MatrixCoefficient::Eval;
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip) override { M = mat; }
/// Return a reference to the constant matrix.
const DenseMatrix& GetMatrix() { return mat; }
};
/** @brief A piecewise matrix-valued coefficient with the pieces keyed off the
element attribute numbers.
A value of zero will be returned for any missing attribute numbers.
This object will not assume ownership of any MatrixCoefficient
objects passed to it. Consequently, the caller must ensure that
the individual MatrixCoefficient objects are not deleted while
this PWMatrixCoefficient is still in use.
\note The keys may either be domain attribute numbers or boundary
attribute numbers. If the PWMatrixCoefficient is used with a
domain integrator the keys are assumed to be domain attribute
numbers. Similarly, if the PWMatrixCoefficient is used with a
boundary integrator the keys are assumed to be boundary attribute
numbers.
*/
class PWMatrixCoefficient : public MatrixCoefficient
{
private:
/** Internal data structure to store pointers to the appropriate
coefficients for different regions of the mesh. The keys used
in the map are the mesh attribute numbers (either element
attribute or boundary element attribute depending upon
context). The values returned for any missing attributes will
be zero. The coefficient pointers may be NULL in which case a
value of zero is returned.
The MatrixCoefficient objects contained in this map are NOT
owned by this PWMatrixCoefficient object. This means that they
will not be deleted when this object is deleted also the caller
must ensure that the various MatrixCoefficient objects are not
deleted while this PWMatrixCoefficient is still needed.
*/
std::map<int, MatrixCoefficient*> pieces;
/** Convenience function to check for compatible array lengths,
loop over the arrays, and add their attribute/MatrixCoefficient
pairs to the internal data structure.
*/
void InitMap(const Array<int> & attr,
const Array<MatrixCoefficient*> & coefs);
public:
/// Constructs a piecewise matrix coefficient of dimension dim by dim
explicit PWMatrixCoefficient(int dim, bool symm = false)
: MatrixCoefficient(dim, symm) {}
/// Constructs a piecewise matrix coefficient of dimension h by w
explicit PWMatrixCoefficient(int h, int w, bool symm = false)
: MatrixCoefficient(h, w, symm) {}
/// Construct the coefficient using arrays describing the pieces
/** \param dim - size of the square matrix-valued result
\param attr - an array of attribute numbers for each piece
\param coefs - the corresponding array of MatrixCoefficient pointers
\param symm - true if the result will be symmetric, false otherwise
Any missing attributes or NULL coefficient pointers will result in a
zero matrix being returned.
\note Ownership of the MatrixCoefficient objects will NOT be
transferred to this object.
*/
PWMatrixCoefficient(int dim, const Array<int> & attr,
const Array<MatrixCoefficient*> & coefs,
bool symm=false)
: MatrixCoefficient(dim, symm) { InitMap(attr, coefs); }
/// Construct the coefficient using arrays describing the pieces
/** \param h - height of the matrix-valued result
\param w - width of the matrix-valued result
\param attr - an array of attribute numbers for each piece
\param coefs - the corresponding array of MatrixCoefficient pointers
\param symm - true if the result will be symmetric, false otherwise
Any missing attributes or NULL coefficient pointers will result in a
zero matrix being returned for that attribute.
\note Ownership of the MatrixCoefficient objects will NOT be
transferred to this object.
*/
PWMatrixCoefficient(int h, int w, const Array<int> & attr,
const Array<MatrixCoefficient*> & coefs,
bool symm=false)
: MatrixCoefficient(h, w, symm) { InitMap(attr, coefs); }
/// Set the time for time dependent coefficients
void SetTime(real_t t) override;
/// Replace a set of coefficients
void UpdateCoefficients(const Array<int> & attr,
const Array<MatrixCoefficient*> & coefs)
{ InitMap(attr, coefs); }
/// Replace a single coefficient for a particular attribute
void UpdateCoefficient(int attr, MatrixCoefficient & coef);
/// Remove a single MatrixCoefficient for a particular attribute
void ZeroCoefficient(int attr)
{ pieces.erase(attr); }
/// Evaluate the coefficient.
void Eval(DenseMatrix &K, ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/** @brief A matrix coefficient with an optional scalar coefficient multiplier
\a q. The matrix function can either be represented by a std function or
a constant matrix provided when constructing this object. */
class MatrixFunctionCoefficient : public MatrixCoefficient
{
private:
std::function<void(const Vector &, DenseMatrix &)> Function;
std::function<void(const Vector &, Vector &)> SymmFunction; // deprecated
std::function<void(const Vector &, real_t, DenseMatrix &)> TDFunction;
Coefficient *Q;
DenseMatrix mat;
public:
/// Define a time-independent square matrix coefficient from a std function
/** \param dim - the size of the matrix
\param F - time-independent function
\param q - optional scalar Coefficient to scale the matrix coefficient */
MatrixFunctionCoefficient(int dim,
std::function<void(const Vector &, DenseMatrix &)> F,
Coefficient *q = nullptr)
: MatrixCoefficient(dim), Function(std::move(F)), Q(q), mat(0)
{ }
/// Define a constant matrix coefficient times a scalar Coefficient
/** \param m - constant matrix
\param q - optional scalar Coefficient to scale the matrix coefficient */
MatrixFunctionCoefficient(const DenseMatrix &m, Coefficient &q)
: MatrixCoefficient(m.Height(), m.Width()), Q(&q), mat(m)
{ }
/** @brief Define a time-independent symmetric square matrix coefficient from
a std function */
/** \param dim - the size of the matrix
\param SymmF - function used in EvalSymmetric
\param q - optional scalar Coefficient to scale the matrix coefficient
@deprecated Use another constructor without setting SymmFunction. */
MatrixFunctionCoefficient(int dim,
std::function<void(const Vector &, Vector &)> SymmF,
Coefficient *q = NULL)
: MatrixCoefficient(dim, true), SymmFunction(std::move(SymmF)), Q(q), mat(0)
{ }
/// Define a time-dependent square matrix coefficient from a std function
/** \param dim - the size of the matrix
\param TDF - time-dependent function
\param q - optional scalar Coefficient to scale the matrix coefficient */
MatrixFunctionCoefficient(int dim,
std::function<void(const Vector &, real_t, DenseMatrix &)> TDF,
Coefficient *q = nullptr)
: MatrixCoefficient(dim), TDFunction(std::move(TDF)), Q(q)
{ }
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseMatrix &K, ElementTransformation &T,
const IntegrationPoint &ip) override;
/// (DEPRECATED) Evaluate the symmetric matrix coefficient at @a ip.
/** @deprecated Use Eval() instead. */
void EvalSymmetric(Vector &K, ElementTransformation &T,
const IntegrationPoint &ip) override;
virtual ~MatrixFunctionCoefficient() { }
};
/** @brief Matrix coefficient defined by a matrix of scalar coefficients.
Coefficients that are not set will evaluate to zero in the vector. The
coefficient is stored as a flat Array with indexing (i,j) -> i*width+j. */
class MatrixArrayCoefficient : public MatrixCoefficient
{
private:
Array<Coefficient *> Coeff;
Array<bool> ownCoeff;
public:
/** @brief Construct a coefficient matrix of dimensions @a dim * @a dim. The
actual coefficients still need to be added with Set(). */
explicit MatrixArrayCoefficient (int dim);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Get the coefficient located at (i,j) in the matrix.
Coefficient* GetCoeff (int i, int j) { return Coeff[i*width+j]; }
/** @brief Set the coefficient located at (i,j) in the matrix. By default
this will take ownership of the Coefficient passed in, but this
can be overridden with the @a own parameter. */
void Set(int i, int j, Coefficient * c, bool own=true);
/// Set ownership of the coefficient at (i,j) in the matrix
void SetOwnership(int i, int j, bool own) { ownCoeff[i*width+j] = own; }
/// Get ownership of the coefficient at (i,j) in the matrix
bool GetOwnership(int i, int j) const { return ownCoeff[i*width+j]; }
using MatrixCoefficient::Eval;
/// Evaluate coefficient located at (i,j) in the matrix using integration
/// point @a ip.
real_t Eval(int i, int j, ElementTransformation &T, const IntegrationPoint &ip)
{ return Coeff[i*width+j] ? Coeff[i*width+j] -> Eval(T, ip, GetTime()) : 0.0; }
/// Evaluate the matrix coefficient @a ip.
void Eval(DenseMatrix &K, ElementTransformation &T,
const IntegrationPoint &ip) override;
virtual ~MatrixArrayCoefficient();
};
/** @brief Matrix coefficient defined row-wise by an array of vector
coefficients. Rows that are not set will evaluate to zero. The
matrix coefficient is stored as an array indexing the rows of
the matrix. */
class MatrixArrayVectorCoefficient : public MatrixCoefficient
{
private:
Array<VectorCoefficient *> Coeff;
Array<bool> ownCoeff;
public:
/** @brief Construct a coefficient matrix of dimensions @a dim * @a dim. The
actual coefficients still need to be added with Set(). */
explicit MatrixArrayVectorCoefficient (int dim);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Get the vector coefficient located at the i-th row of the matrix
VectorCoefficient* GetCoeff (int i) { return Coeff[i]; }
/** @brief Set the coefficient located at the i-th row of the matrix.
By this will take ownership of the Coefficient passed in, but this
can be overridden with the @a own parameter. */
void Set(int i, VectorCoefficient * c, bool own=true);
/// Set ownership of the i'th coefficient
void SetOwnership(int i, bool own) { ownCoeff[i] = own; }
/// Get ownership of the i'th coefficient
bool GetOwnership(int i) const { return ownCoeff[i]; }
using MatrixCoefficient::Eval;
/// Evaluate coefficient located at the i-th row of the matrix using integration
/// point @a ip.
void Eval(int i, Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
/// Evaluate the matrix coefficient @a ip.
void Eval(DenseMatrix &K, ElementTransformation &T,
const IntegrationPoint &ip) override;
virtual ~MatrixArrayVectorCoefficient();
};
/** @brief Derived matrix coefficient that has the value of the parent matrix
coefficient where it is active and is zero otherwise. */
class MatrixRestrictedCoefficient : public MatrixCoefficient
{
private:
MatrixCoefficient *c;
Array<int> active_attr;
public:
/** @brief Construct with a parent matrix coefficient and an array of zeros
and ones representing the attributes for which this coefficient should be
active. */
MatrixRestrictedCoefficient(MatrixCoefficient &mc, Array<int> &attr)
: MatrixCoefficient(mc.GetHeight(), mc.GetWidth())
{ c = &mc; attr.Copy(active_attr); }
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseMatrix &K, ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Coefficients based on sums, products, or other functions of coefficients.
///@{
/** @brief Scalar coefficient defined as the linear combination of two scalar
coefficients or a scalar and a scalar coefficient */
class SumCoefficient : public Coefficient
{
private:
real_t aConst;
Coefficient * a;
Coefficient * b;
real_t alpha;
real_t beta;
public:
/// Constructor with one coefficient. Result is alpha_ * A + beta_ * B
SumCoefficient(real_t A, Coefficient &B,
real_t alpha_ = 1.0, real_t beta_ = 1.0)
: aConst(A), a(NULL), b(&B), alpha(alpha_), beta(beta_) { }
/// Constructor with two coefficients. Result is alpha_ * A + beta_ * B.
SumCoefficient(Coefficient &A, Coefficient &B,
real_t alpha_ = 1.0, real_t beta_ = 1.0)
: aConst(0.0), a(&A), b(&B), alpha(alpha_), beta(beta_) { }
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// @copydoc Coefficient::Project(QuadratureFunction &)
void Project(QuadratureFunction &qf) override;
/// Reset the first term in the linear combination as a constant
void SetAConst(real_t A) { a = NULL; aConst = A; }
/// Return the first term in the linear combination
real_t GetAConst() const { return aConst; }
/// Reset the first term in the linear combination
void SetACoef(Coefficient &A) { a = &A; }
/// Return the first term in the linear combination
Coefficient * GetACoef() const { return a; }
/// Reset the second term in the linear combination
void SetBCoef(Coefficient &B) { b = &B; }
/// Return the second term in the linear combination
Coefficient * GetBCoef() const { return b; }
/// Reset the factor in front of the first term in the linear combination
void SetAlpha(real_t alpha_) { alpha = alpha_; }
/// Return the factor in front of the first term in the linear combination
real_t GetAlpha() const { return alpha; }
/// Reset the factor in front of the second term in the linear combination
void SetBeta(real_t beta_) { beta = beta_; }
/// Return the factor in front of the second term in the linear combination
real_t GetBeta() const { return beta; }
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override
{
return alpha * ((a == NULL ) ? aConst : a->Eval(T, ip) )
+ beta * b->Eval(T, ip);
}
};
/// Base class for symmetric matrix coefficients that optionally depend on time and space.
class SymmetricMatrixCoefficient : public MatrixCoefficient
{
protected:
/// Internal matrix used when evaluating this coefficient as a DenseMatrix.
mutable DenseSymmetricMatrix mat_aux;
public:
/// Construct a dim x dim matrix coefficient.
explicit SymmetricMatrixCoefficient(int dimension)
: MatrixCoefficient(dimension, true), mat_aux(height) { }
/// Get the size of the matrix.
int GetSize() const { return height; }
/// @brief Fill the QuadratureFunction @a qf by evaluating the coefficient at
/// the quadrature points.
///
/// @note As opposed to MatrixCoefficient::Project, this function stores only
/// the @a symmetric part of the matrix at each quadrature point.
///
/// The @a vdim of the coefficient should be equal to height*(height+1)/2.
virtual void ProjectSymmetric(QuadratureFunction &qf);
/** @brief Evaluate the matrix coefficient in the element described by @a T
at the point @a ip, storing the result as a symmetric matrix @a K. */
/** @note When this method is called, the caller must make sure that the
IntegrationPoint associated with @a T is the same as @a ip. This can be
achieved by calling T.SetIntPoint(&ip). */
virtual void Eval(DenseSymmetricMatrix &K, ElementTransformation &T,
const IntegrationPoint &ip) = 0;
/** @brief Evaluate the matrix coefficient in the element described by @a T
at the point @a ip, storing the result as a dense matrix @a K. */
/** This function allows the use of SymmetricMatrixCoefficient in situations
where the symmetry is not taken advantage of.
@note When this method is called, the caller must make sure that the
IntegrationPoint associated with @a T is the same as @a ip. This can be
achieved by calling T.SetIntPoint(&ip). */
void Eval(DenseMatrix &K, ElementTransformation &T,
const IntegrationPoint &ip) override;
/// @deprecated Return a reference to the internal matrix used when evaluating this coefficient as a DenseMatrix.
MFEM_DEPRECATED const DenseSymmetricMatrix& GetMatrix() { return mat_aux; }
virtual ~SymmetricMatrixCoefficient() { }
};
/// A matrix coefficient that is constant in space and time.
class SymmetricMatrixConstantCoefficient : public SymmetricMatrixCoefficient
{
private:
DenseSymmetricMatrix mat;
public:
///Construct using matrix @a m for the constant.
SymmetricMatrixConstantCoefficient(const DenseSymmetricMatrix &m)
: SymmetricMatrixCoefficient(m.Height()), mat(m) { }
using SymmetricMatrixCoefficient::Eval;
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseSymmetricMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip) override { M = mat; }
/// Return a reference to the constant matrix.
const DenseSymmetricMatrix& GetMatrix() { return mat; }
};
/** @brief A matrix coefficient with an optional scalar coefficient multiplier
\a q. The matrix function can either be represented by a std function or
a constant matrix provided when constructing this object. */
class SymmetricMatrixFunctionCoefficient : public SymmetricMatrixCoefficient
{
private:
std::function<void(const Vector &, DenseSymmetricMatrix &)> Function;
std::function<void(const Vector &, real_t, DenseSymmetricMatrix &)> TDFunction;
Coefficient *Q;
DenseSymmetricMatrix mat;
public:
/// Define a time-independent symmetric matrix coefficient from a std function
/** \param dim - the size of the matrix
\param F - time-independent function
\param q - optional scalar Coefficient to scale the matrix coefficient */
SymmetricMatrixFunctionCoefficient(int dim,
std::function<void(const Vector &, DenseSymmetricMatrix &)> F,
Coefficient *q = nullptr)
: SymmetricMatrixCoefficient(dim), Function(std::move(F)), Q(q), mat(0)
{ }
/// Define a constant matrix coefficient times a scalar Coefficient
/** \param m - constant matrix
\param q - optional scalar Coefficient to scale the matrix coefficient */
SymmetricMatrixFunctionCoefficient(const DenseSymmetricMatrix &m,
Coefficient &q)
: SymmetricMatrixCoefficient(m.Height()), Q(&q), mat(m)
{ }
/// Define a time-dependent square matrix coefficient from a std function
/** \param dim - the size of the matrix
\param TDF - time-dependent function
\param q - optional scalar Coefficient to scale the matrix coefficient */
SymmetricMatrixFunctionCoefficient(int dim,
std::function<void(const Vector &, real_t, DenseSymmetricMatrix &)> TDF,
Coefficient *q = nullptr)
: SymmetricMatrixCoefficient(dim), TDFunction(std::move(TDF)), Q(q)
{ }
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
using SymmetricMatrixCoefficient::Eval;
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseSymmetricMatrix &K, ElementTransformation &T,
const IntegrationPoint &ip) override;
virtual ~SymmetricMatrixFunctionCoefficient() { }
};
/** @brief Scalar coefficient defined as the product of two scalar coefficients
or a scalar and a scalar coefficient. */
class ProductCoefficient : public Coefficient
{
private:
real_t aConst;
Coefficient * a;
Coefficient * b;
public:
/// Constructor with one coefficient. Result is A * B.
ProductCoefficient(real_t A, Coefficient &B)
: aConst(A), a(NULL), b(&B) { }
/// Constructor with two coefficients. Result is A * B.
ProductCoefficient(Coefficient &A, Coefficient &B)
: aConst(0.0), a(&A), b(&B) { }
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// @copydoc Coefficient::Project(QuadratureFunction &)
void Project(QuadratureFunction &qf) override;
/// Reset the first term in the product as a constant
void SetAConst(real_t A) { a = NULL; aConst = A; }
/// Return the first term in the product
real_t GetAConst() const { return aConst; }
/// Reset the first term in the product
void SetACoef(Coefficient &A) { a = &A; }
/// Return the first term in the product
Coefficient * GetACoef() const { return a; }
/// Reset the second term in the product
void SetBCoef(Coefficient &B) { b = &B; }
/// Return the second term in the product
Coefficient * GetBCoef() const { return b; }
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override
{ return ((a == NULL ) ? aConst : a->Eval(T, ip) ) * b->Eval(T, ip); }
};
/** @brief Scalar coefficient defined as the ratio of two scalars where one or
both scalars are scalar coefficients. */
class RatioCoefficient : public Coefficient
{
private:
real_t aConst;
real_t bConst;
Coefficient * a;
Coefficient * b;
public:
/** Initialize a coefficient which returns A / B where @a A is a
constant and @a B is a scalar coefficient */
RatioCoefficient(real_t A, Coefficient &B)
: aConst(A), bConst(1.0), a(NULL), b(&B) { }
/** Initialize a coefficient which returns A / B where @a A and @a B are both
scalar coefficients */
RatioCoefficient(Coefficient &A, Coefficient &B)
: aConst(0.0), bConst(1.0), a(&A), b(&B) { }
/** Initialize a coefficient which returns A / B where @a A is a
scalar coefficient and @a B is a constant */
RatioCoefficient(Coefficient &A, real_t B)
: aConst(0.0), bConst(B), a(&A), b(NULL) { }
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// @copydoc Coefficient::Project(QuadratureFunction &)
void Project(QuadratureFunction &qf) override;
/// Reset the numerator in the ratio as a constant
void SetAConst(real_t A) { a = NULL; aConst = A; }
/// Return the numerator of the ratio
real_t GetAConst() const { return aConst; }
/// Reset the denominator in the ratio as a constant
void SetBConst(real_t B) { b = NULL; bConst = B; }
/// Return the denominator of the ratio
real_t GetBConst() const { return bConst; }
/// Reset the numerator in the ratio
void SetACoef(Coefficient &A) { a = &A; }
/// Return the numerator of the ratio
Coefficient * GetACoef() const { return a; }
/// Reset the denominator in the ratio
void SetBCoef(Coefficient &B) { b = &B; }
/// Return the denominator of the ratio
Coefficient * GetBCoef() const { return b; }
/// Evaluate the coefficient
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override
{
real_t den = (b == NULL ) ? bConst : b->Eval(T, ip);
MFEM_ASSERT(den != 0.0, "Division by zero in RatioCoefficient");
return ((a == NULL ) ? aConst : a->Eval(T, ip) ) / den;
}
};
/// Scalar coefficient defined as a scalar raised to a power
class PowerCoefficient : public Coefficient
{
private:
Coefficient * a;
real_t p;
public:
/// Construct with a coefficient and a constant power @a p_. Result is A^p.
PowerCoefficient(Coefficient &A, real_t p_)
: a(&A), p(p_) { }
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the base coefficient
void SetACoef(Coefficient &A) { a = &A; }
/// Return the base coefficient
Coefficient * GetACoef() const { return a; }
/// Reset the exponent
void SetExponent(real_t p_) { p = p_; }
/// Return the exponent
real_t GetExponent() const { return p; }
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override
{ return pow(a->Eval(T, ip), p); }
};
/// Scalar coefficient defined as the inner product of two vector coefficients
class InnerProductCoefficient : public Coefficient
{
private:
VectorCoefficient * a;
VectorCoefficient * b;
mutable Vector va;
mutable Vector vb;
public:
/// Construct with the two vector coefficients. Result is $ A \cdot B $.
InnerProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the first vector in the inner product
void SetACoef(VectorCoefficient &A) { a = &A; }
/// Return the first vector coefficient in the inner product
VectorCoefficient * GetACoef() const { return a; }
/// Reset the second vector in the inner product
void SetBCoef(VectorCoefficient &B) { b = &B; }
/// Return the second vector coefficient in the inner product
VectorCoefficient * GetBCoef() const { return b; }
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
/// @copydoc Coefficient::Project(QuadratureFunction &)
void Project(QuadratureFunction &qf) override;
};
/// Scalar coefficient defined as a cross product of two vectors in the xy-plane.
class VectorRotProductCoefficient : public Coefficient
{
private:
VectorCoefficient * a;
VectorCoefficient * b;
mutable Vector va;
mutable Vector vb;
public:
/// Constructor with two vector coefficients. Result is $ A_x B_y - A_y * B_x; $.
VectorRotProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the first vector in the product
void SetACoef(VectorCoefficient &A) { a = &A; }
/// Return the first vector of the product
VectorCoefficient * GetACoef() const { return a; }
/// Reset the second vector in the product
void SetBCoef(VectorCoefficient &B) { b = &B; }
/// Return the second vector of the product
VectorCoefficient * GetBCoef() const { return b; }
/// Evaluate the coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Scalar coefficient defined as the determinant of a matrix coefficient
class DeterminantCoefficient : public Coefficient
{
private:
MatrixCoefficient * a;
mutable DenseMatrix ma;
public:
/// Construct with the matrix.
DeterminantCoefficient(MatrixCoefficient &A);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Evaluate the determinant coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Scalar coefficient defined as the trace of a matrix coefficient
class TraceCoefficient : public Coefficient
{
private:
MatrixCoefficient * a;
mutable DenseMatrix ma;
public:
/// Construct with the matrix.
TraceCoefficient(MatrixCoefficient &A);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Evaluate the trace coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Scalar coefficient defined as component of a vector coefficient
class VectorComponentCoefficient : public Coefficient
{
private:
VectorCoefficient *a = nullptr;
mutable Vector va;
int component;
public:
/// Construct with a vector coefficient.
VectorComponentCoefficient(VectorCoefficient &A)
: a(&A), va(A.GetVDim()), component(0) {};
VectorComponentCoefficient(VectorCoefficient &A, int c);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the vector coefficient
void SetACoef(VectorCoefficient &A) { a = &A; }
/// Return the vector coefficient
VectorCoefficient * GetACoef() const { return a; }
/// Set the component
void SetComponent(int c);
/// Return the component
int GetComponent() const { return component; }
/// Evaluate the trace coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Scalar coefficient defined as component of a matrix coefficient
class MatrixComponentCoefficient : public Coefficient
{
private:
MatrixCoefficient *a = nullptr;
mutable DenseMatrix ma;
int row_idx,col_idx;
public:
MatrixComponentCoefficient(MatrixCoefficient &A)
: a(&A), ma(A.GetHeight(), A.GetWidth()), row_idx(0), col_idx(0) {};
/// Construct with the matrix coefficient.
MatrixComponentCoefficient(MatrixCoefficient &A, int ri, int ci);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Reset the index
void SetRowIndex(int ri);
/// Return the index
int GetRowIndex() const { return row_idx; }
/// Reset the index
void SetColumnIndex(int ci);
/// Return the index
int GetColumnIndex() const { return col_idx; }
/// Evaluate the trace coefficient at @a ip.
real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Vector coefficient defined as the linear combination of two vectors
class VectorSumCoefficient : public VectorCoefficient
{
private:
VectorCoefficient * ACoef;
VectorCoefficient * BCoef;
Vector A;
Vector B;
Coefficient * alphaCoef;
Coefficient * betaCoef;
real_t alpha;
real_t beta;
mutable Vector va;
public:
/** Constructor with no coefficients.
To be used with the various "Set" methods */
VectorSumCoefficient(int dim);
/** Constructor with two vector coefficients.
Result is alpha_ * A + beta_ * B */
VectorSumCoefficient(VectorCoefficient &A, VectorCoefficient &B,
real_t alpha_ = 1.0, real_t beta_ = 1.0);
/** Constructor with scalar coefficients.
Result is alpha_ * A_ + beta_ * B_ */
VectorSumCoefficient(VectorCoefficient &A_, VectorCoefficient &B_,
Coefficient &alpha_, Coefficient &beta_);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the first vector coefficient
void SetACoef(VectorCoefficient &A_) { ACoef = &A_; }
/// Return the first vector coefficient
VectorCoefficient * GetACoef() const { return ACoef; }
/// Reset the second vector coefficient
void SetBCoef(VectorCoefficient &B_) { BCoef = &B_; }
/// Return the second vector coefficient
VectorCoefficient * GetBCoef() const { return BCoef; }
/// Reset the factor in front of the first vector coefficient
void SetAlphaCoef(Coefficient &A_) { alphaCoef = &A_; }
/// Return the factor in front of the first vector coefficient
Coefficient * GetAlphaCoef() const { return alphaCoef; }
/// Reset the factor in front of the second vector coefficient
void SetBetaCoef(Coefficient &B_) { betaCoef = &B_; }
/// Return the factor in front of the second vector coefficient
Coefficient * GetBetaCoef() const { return betaCoef; }
/// Reset the first vector as a constant
void SetA(const Vector &A_) { A = A_; ACoef = NULL; }
/// Return the first vector constant
const Vector & GetA() const { return A; }
/// Reset the second vector as a constant
void SetB(const Vector &B_) { B = B_; BCoef = NULL; }
/// Return the second vector constant
const Vector & GetB() const { return B; }
/// Reset the factor in front of the first vector coefficient as a constant
void SetAlpha(real_t alpha_) { alpha = alpha_; alphaCoef = NULL; }
/// Return the factor in front of the first vector coefficient
real_t GetAlpha() const { return alpha; }
/// Reset the factor in front of the second vector coefficient as a constant
void SetBeta(real_t beta_) { beta = beta_; betaCoef = NULL; }
/// Return the factor in front of the second vector coefficient
real_t GetBeta() const { return beta; }
/// Evaluate the coefficient at @a ip.
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
using VectorCoefficient::Eval;
};
/// Vector coefficient defined as a product of scalar and vector coefficients.
class ScalarVectorProductCoefficient : public VectorCoefficient
{
private:
real_t aConst;
Coefficient * a;
VectorCoefficient * b;
public:
/// Constructor with constant and vector coefficient. Result is A * B.
ScalarVectorProductCoefficient(real_t A, VectorCoefficient &B);
/// Constructor with two coefficients. Result is A * B.
ScalarVectorProductCoefficient(Coefficient &A, VectorCoefficient &B);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the scalar factor as a constant
void SetAConst(real_t A) { a = NULL; aConst = A; }
/// Return the scalar factor
real_t GetAConst() const { return aConst; }
/// Reset the scalar factor
void SetACoef(Coefficient &A) { a = &A; }
/// Return the scalar factor
Coefficient * GetACoef() const { return a; }
/// Reset the vector factor
void SetBCoef(VectorCoefficient &B) { b = &B; }
/// Return the vector factor
VectorCoefficient * GetBCoef() const { return b; }
/// Evaluate the coefficient at @a ip.
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
using VectorCoefficient::Eval;
};
/// Vector coefficient defined as a normalized vector field (returns v/|v|)
class NormalizedVectorCoefficient : public VectorCoefficient
{
private:
VectorCoefficient * a;
real_t tol;
public:
/** @brief Return a vector normalized to a length of one
This class evaluates the vector coefficient @a A and, if |A| > @a tol,
returns the normalized vector A / |A|. If |A| <= @a tol, the zero
vector is returned.
*/
NormalizedVectorCoefficient(VectorCoefficient &A, real_t tol = 1e-6);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the vector coefficient
void SetACoef(VectorCoefficient &A) { a = &A; }
/// Return the vector coefficient
VectorCoefficient * GetACoef() const { return a; }
/// Evaluate the coefficient at @a ip.
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
using VectorCoefficient::Eval;
};
/// Vector coefficient defined as a cross product of two vectors
class VectorCrossProductCoefficient : public VectorCoefficient
{
private:
VectorCoefficient * a;
VectorCoefficient * b;
mutable Vector va;
mutable Vector vb;
public:
/// Construct with the two coefficients. Result is A x B.
VectorCrossProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the first term in the product
void SetACoef(VectorCoefficient &A) { a = &A; }
/// Return the first term in the product
VectorCoefficient * GetACoef() const { return a; }
/// Reset the second term in the product
void SetBCoef(VectorCoefficient &B) { b = &B; }
/// Return the second term in the product
VectorCoefficient * GetBCoef() const { return b; }
/// Evaluate the coefficient at @a ip.
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
using VectorCoefficient::Eval;
};
/** @brief Vector coefficient defined as a product of a matrix coefficient and
a vector coefficient. */
class MatrixVectorProductCoefficient : public VectorCoefficient
{
private:
MatrixCoefficient * a;
VectorCoefficient * b;
mutable DenseMatrix ma;
mutable Vector vb;
public:
/// Constructor with two coefficients. Result is A*B.
MatrixVectorProductCoefficient(MatrixCoefficient &A, VectorCoefficient &B);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Reset the vector coefficient
void SetBCoef(VectorCoefficient &B) { b = &B; }
/// Return the vector coefficient
VectorCoefficient * GetBCoef() const { return b; }
/// Evaluate the vector coefficient at @a ip.
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
using VectorCoefficient::Eval;
};
/// Convenient alias for the MatrixVectorProductCoefficient
typedef MatrixVectorProductCoefficient MatVecCoefficient;
/// Constant matrix coefficient defined as the identity of dimension d
class IdentityMatrixCoefficient : public MatrixCoefficient
{
private:
int dim;
public:
/// Construct with the dimension of the square identity matrix.
IdentityMatrixCoefficient(int d)
: MatrixCoefficient(d, d), dim(d) { }
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Matrix coefficient defined as the linear combination of two matrices
class MatrixSumCoefficient : public MatrixCoefficient
{
private:
MatrixCoefficient * a;
MatrixCoefficient * b;
real_t alpha;
real_t beta;
mutable DenseMatrix ma;
public:
/// Construct with the two coefficients. Result is alpha_ * A + beta_ * B.
MatrixSumCoefficient(MatrixCoefficient &A, MatrixCoefficient &B,
real_t alpha_ = 1.0, real_t beta_ = 1.0);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the first matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the first matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Reset the second matrix coefficient
void SetBCoef(MatrixCoefficient &B) { b = &B; }
/// Return the second matrix coefficient
MatrixCoefficient * GetBCoef() const { return b; }
/// Reset the factor in front of the first matrix coefficient
void SetAlpha(real_t alpha_) { alpha = alpha_; }
/// Return the factor in front of the first matrix coefficient
real_t GetAlpha() const { return alpha; }
/// Reset the factor in front of the second matrix coefficient
void SetBeta(real_t beta_) { beta = beta_; }
/// Return the factor in front of the second matrix coefficient
real_t GetBeta() const { return beta; }
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Matrix coefficient defined as the product of two matrices
class MatrixProductCoefficient : public MatrixCoefficient
{
private:
MatrixCoefficient * a;
MatrixCoefficient * b;
mutable DenseMatrix ma;
mutable DenseMatrix mb;
public:
/// Construct with the two coefficients. Result is A * B.
MatrixProductCoefficient(MatrixCoefficient &A, MatrixCoefficient &B);
/// Reset the first matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the first matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Reset the second matrix coefficient
void SetBCoef(MatrixCoefficient &B) { b = &B; }
/// Return the second matrix coefficient
MatrixCoefficient * GetBCoef() const { return b; }
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/** @brief Matrix coefficient defined as a product of a scalar coefficient and a
matrix coefficient.*/
class ScalarMatrixProductCoefficient : public MatrixCoefficient
{
private:
real_t aConst;
Coefficient * a;
MatrixCoefficient * b;
public:
/// Constructor with one coefficient. Result is A*B.
ScalarMatrixProductCoefficient(real_t A, MatrixCoefficient &B);
/// Constructor with two coefficients. Result is A*B.
ScalarMatrixProductCoefficient(Coefficient &A, MatrixCoefficient &B);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the scalar factor as a constant
void SetAConst(real_t A) { a = NULL; aConst = A; }
/// Return the scalar factor
real_t GetAConst() const { return aConst; }
/// Reset the scalar factor
void SetACoef(Coefficient &A) { a = &A; }
/// Return the scalar factor
Coefficient * GetACoef() const { return a; }
/// Reset the matrix factor
void SetBCoef(MatrixCoefficient &B) { b = &B; }
/// Return the matrix factor
MatrixCoefficient * GetBCoef() const { return b; }
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Matrix coefficient defined as the transpose of a matrix coefficient
class TransposeMatrixCoefficient : public MatrixCoefficient
{
private:
MatrixCoefficient * a;
public:
/// Construct with the matrix coefficient. Result is $ A^T $.
TransposeMatrixCoefficient(MatrixCoefficient &A);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Matrix coefficient defined as the inverse of a matrix coefficient.
class InverseMatrixCoefficient : public MatrixCoefficient
{
private:
MatrixCoefficient * a;
public:
/// Construct with the matrix coefficient. Result is $ A^{-1} $.
InverseMatrixCoefficient(MatrixCoefficient &A);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Matrix coefficient defined as the exponential of a matrix coefficient.
class ExponentialMatrixCoefficient : public MatrixCoefficient
{
private:
MatrixCoefficient * a;
public:
/// Construct the matrix coefficient. Result is $ \exp(A) $.
ExponentialMatrixCoefficient(MatrixCoefficient &A);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/// Matrix coefficient defined as the outer product of two vector coefficients.
class OuterProductCoefficient : public MatrixCoefficient
{
private:
VectorCoefficient * a;
VectorCoefficient * b;
mutable Vector va;
mutable Vector vb;
public:
/// Construct with two vector coefficients. Result is $ A B^T $.
OuterProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the first vector in the outer product
void SetACoef(VectorCoefficient &A) { a = &A; }
/// Return the first vector coefficient in the outer product
VectorCoefficient * GetACoef() const { return a; }
/// Reset the second vector in the outer product
void SetBCoef(VectorCoefficient &B) { b = &B; }
/// Return the second vector coefficient in the outer product
VectorCoefficient * GetBCoef() const { return b; }
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip) override;
};
/** @brief Matrix coefficient defined as -a k x k x, for a vector k and scalar a
This coefficient returns $a * (|k|^2 I - k \otimes k)$, where I is
the identity matrix and $\otimes$ indicates the outer product. This
can be evaluated for vectors of any dimension but in three
dimensions it corresponds to computing the cross product with k twice.
*/
class CrossCrossCoefficient : public MatrixCoefficient
{
private:
real_t aConst;
Coefficient * a;
VectorCoefficient * k;
mutable Vector vk;
public:
CrossCrossCoefficient(real_t A, VectorCoefficient &K);
CrossCrossCoefficient(Coefficient &A, VectorCoefficient &K);
/// Set the time for internally stored coefficients
void SetTime(real_t t) override;
/// Reset the scalar factor as a constant
void SetAConst(real_t A) { a = NULL; aConst = A; }
/// Return the scalar factor
real_t GetAConst() const { return aConst; }
/// Reset the scalar factor
void SetACoef(Coefficient &A) { a = &A; }
/// Return the scalar factor
Coefficient * GetACoef() const { return a; }
/// Reset the vector factor
void SetKCoef(VectorCoefficient &K) { k = &K; }
/// Return the vector factor
VectorCoefficient * GetKCoef() const { return k; }
/// Evaluate the matrix coefficient at @a ip.
void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip) override;
};
///@}
/** @brief Vector quadrature function coefficient which requires that the
quadrature rules used for this vector coefficient be the same as those that
live within the supplied QuadratureFunction. */
class VectorQuadratureFunctionCoefficient : public VectorCoefficient
{
private:
const QuadratureFunction &QuadF; //do not own
int index;
public:
/// Constructor with a quadrature function as input
VectorQuadratureFunctionCoefficient(const QuadratureFunction &qf);
/** Set the starting index within the QuadFunc that'll be used to project
outwards as well as the corresponding length. The projected length should
have the bounds of 1 <= length <= (length QuadFunc - index). */
void SetComponent(int index_, int length_);
const QuadratureFunction& GetQuadFunction() const { return QuadF; }
using VectorCoefficient::Eval;
void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) override;
void Project(QuadratureFunction &qf) override;
virtual ~VectorQuadratureFunctionCoefficient() { }
};
/** @brief Quadrature function coefficient which requires that the quadrature
rules used for this coefficient be the same as those that live within the
supplied QuadratureFunction. */
class QuadratureFunctionCoefficient : public Coefficient
{
private:
const QuadratureFunction &QuadF;
public:
/// Constructor with a quadrature function as input
QuadratureFunctionCoefficient(const QuadratureFunction &qf);
const QuadratureFunction& GetQuadFunction() const { return QuadF; }
real_t Eval(ElementTransformation &T, const IntegrationPoint &ip) override;
void Project(QuadratureFunction &qf) override;
virtual ~QuadratureFunctionCoefficient() { }
};
/// Flags that determine what storage optimizations to use in CoefficientVector
enum class CoefficientStorage : int
{
FULL = 0, ///< Store the coefficient as a full QuadratureFunction.
CONSTANTS = 1 << 0, ///< Store constants using only @a vdim entries.
SYMMETRIC = 1 << 1, ///< Store the triangular part of symmetric matrices.
COMPRESSED = CONSTANTS | SYMMETRIC ///< Enable all above compressions.
};
inline CoefficientStorage operator|(CoefficientStorage a, CoefficientStorage b)
{
return CoefficientStorage(int(a) | int(b));
}
inline int operator&(CoefficientStorage a, CoefficientStorage b)
{
return int(a) & int(b);
}
/// @brief Class to represent a coefficient evaluated at quadrature points.
///
/// In the general case, a CoefficientVector is the same as a QuadratureFunction
/// with a coefficient projected onto it.
///
/// This class allows for some "compression" of the coefficient data, according
/// to the storage flags given by CoefficientStorage. For example, constant
/// coefficients can be stored using only @a vdim values, and symmetric matrices
/// can be stored using e.g. the upper triangular part of the matrix.
class CoefficientVector : public Vector
{
protected:
CoefficientStorage storage; ///< Storage optimizations (see CoefficientStorage).
int vdim; ///< Number of values per quadrature point.
QuadratureSpaceBase &qs; ///< Associated QuadratureSpaceBase.
QuadratureFunction *qf; ///< Internal QuadratureFunction (owned, may be NULL).
public:
/// Create an empty CoefficientVector.
CoefficientVector(QuadratureSpaceBase &qs_,
CoefficientStorage storage_ = CoefficientStorage::FULL);
/// @brief Create a CoefficientVector from the given Coefficient and
/// QuadratureSpaceBase.
///
/// If @a coeff is NULL, it will be interpreted as a constant with value one.
/// @sa CoefficientStorage for a description of @a storage_.
CoefficientVector(Coefficient *coeff, QuadratureSpaceBase &qs,
CoefficientStorage storage_ = CoefficientStorage::FULL);
/// @brief Create a CoefficientVector from the given Coefficient and
/// QuadratureSpaceBase.
///
/// @sa CoefficientStorage for a description of @a storage_.
CoefficientVector(Coefficient &coeff, QuadratureSpaceBase &qs,
CoefficientStorage storage_ = CoefficientStorage::FULL);
/// @brief Create a CoefficientVector from the given VectorCoefficient and
/// QuadratureSpaceBase.
///
/// @sa CoefficientStorage for a description of @a storage_.
CoefficientVector(VectorCoefficient &coeff, QuadratureSpaceBase &qs,
CoefficientStorage storage_ = CoefficientStorage::FULL);
/// @brief Create a CoefficientVector from the given MatrixCoefficient and
/// QuadratureSpaceBase.
///
/// @sa CoefficientStorage for a description of @a storage_.
CoefficientVector(MatrixCoefficient &coeff, QuadratureSpaceBase &qs,
CoefficientStorage storage_ = CoefficientStorage::FULL);
/// @brief Evaluate the given Coefficient at the quadrature points defined by
/// @ref qs.
void Project(Coefficient &coeff);
/// @brief Evaluate the given VectorCoefficient at the quadrature points
/// defined by @ref qs.
///
/// @sa CoefficientVector for a description of the @a compress argument.
void Project(VectorCoefficient &coeff);
/// @brief Evaluate the given MatrixCoefficient at the quadrature points
/// defined by @ref qs.
///
/// @sa CoefficientVector for a description of the @a compress argument.
void Project(MatrixCoefficient &coeff, bool transpose=false);
/// @brief Project the transpose of @a coeff.
///
/// @sa Project(MatrixCoefficient&, QuadratureSpace&, bool, bool)
void ProjectTranspose(MatrixCoefficient &coeff);
/// Make this vector a reference to the given QuadratureFunction.
void MakeRef(const QuadratureFunction &qf_);
/// Set this vector to the given constant.
void SetConstant(real_t constant);
/// Set this vector to the given constant vector.
void SetConstant(const Vector &constant);
/// Set this vector to the given constant matrix.
void SetConstant(const DenseMatrix &constant, bool transpose=false);
/// Set this vector to the given constant symmetric matrix.
void SetConstant(const DenseSymmetricMatrix &constant);
/// Return the number of values per quadrature point.
int GetVDim() const;
~CoefficientVector();
};
/** @brief Compute the Lp norm of a function f.
$ \| f \|_{Lp} = ( \int_\Omega | f |^p d\Omega)^{1/p} $ */
real_t ComputeLpNorm(real_t p, Coefficient &coeff, Mesh &mesh,
const IntegrationRule *irs[]);
/** @brief Compute the Lp norm of a vector function f = {f_i}_i=1...N.
$ \| f \|_{Lp} = ( \sum_i \| f_i \|_{Lp}^p )^{1/p} $ */
real_t ComputeLpNorm(real_t p, VectorCoefficient &coeff, Mesh &mesh,
const IntegrationRule *irs[]);
#ifdef MFEM_USE_MPI
/** @brief Compute the global Lp norm of a function f.
$ \| f \|_{Lp} = ( \int_\Omega | f |^p d\Omega)^{1/p} $ */
real_t ComputeGlobalLpNorm(real_t p, Coefficient &coeff, ParMesh &pmesh,
const IntegrationRule *irs[]);
/** @brief Compute the global Lp norm of a vector function f = {f_i}_i=1...N.
$ \| f \|_{Lp} = ( \sum_i \| f_i \|_{Lp}^p )^{1/p} $ */
real_t ComputeGlobalLpNorm(real_t p, VectorCoefficient &coeff, ParMesh &pmesh,
const IntegrationRule *irs[]);
#endif
}
#endif