860 lines
39 KiB
C++
860 lines
39 KiB
C++
// Copyright (c) 2010-2022, 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_GRIDFUNC
|
|
#define MFEM_GRIDFUNC
|
|
|
|
#include "../config/config.hpp"
|
|
#include "fespace.hpp"
|
|
#include "coefficient.hpp"
|
|
#include "bilininteg.hpp"
|
|
#ifdef MFEM_USE_ADIOS2
|
|
#include "../general/adios2stream.hpp"
|
|
#endif
|
|
#include <limits>
|
|
#include <ostream>
|
|
#include <string>
|
|
|
|
namespace mfem
|
|
{
|
|
|
|
/// Class for grid function - Vector with associated FE space.
|
|
class GridFunction : public Vector
|
|
{
|
|
protected:
|
|
/// FE space on which the grid function lives. Owned if #fec is not NULL.
|
|
FiniteElementSpace *fes;
|
|
|
|
/** @brief Used when the grid function is read from a file. It can also be
|
|
set explicitly, see MakeOwner().
|
|
|
|
If not NULL, this pointer is owned by the GridFunction. */
|
|
FiniteElementCollection *fec;
|
|
|
|
long fes_sequence; // see FiniteElementSpace::sequence, Mesh::sequence
|
|
|
|
/** Optional, internal true-dof vector: if the FiniteElementSpace #fes has a
|
|
non-trivial (i.e. not NULL) prolongation operator, this Vector may hold
|
|
associated true-dof values - either owned or external. */
|
|
Vector t_vec;
|
|
|
|
void SaveSTLTri(std::ostream &out, double p1[], double p2[], double p3[]);
|
|
|
|
void GetVectorGradientHat(ElementTransformation &T, DenseMatrix &gh) const;
|
|
|
|
// Project the delta coefficient without scaling and return the (local)
|
|
// integral of the projection.
|
|
void ProjectDeltaCoefficient(DeltaCoefficient &delta_coeff,
|
|
double &integral);
|
|
|
|
// Sum fluxes to vertices and count element contributions
|
|
void SumFluxAndCount(BilinearFormIntegrator &blfi,
|
|
GridFunction &flux,
|
|
Array<int>& counts,
|
|
bool wcoef,
|
|
int subdomain);
|
|
|
|
/** Project a discontinuous vector coefficient in a continuous space and
|
|
return in dof_attr the maximal attribute of the elements containing each
|
|
degree of freedom. */
|
|
void ProjectDiscCoefficient(VectorCoefficient &coeff, Array<int> &dof_attr);
|
|
|
|
/// Loading helper.
|
|
void LegacyNCReorder();
|
|
|
|
void Destroy();
|
|
|
|
public:
|
|
|
|
GridFunction() { fes = NULL; fec = NULL; fes_sequence = 0; UseDevice(true); }
|
|
|
|
/// Copy constructor. The internal true-dof vector #t_vec is not copied.
|
|
GridFunction(const GridFunction &orig)
|
|
: Vector(orig), fes(orig.fes), fec(NULL), fes_sequence(orig.fes_sequence)
|
|
{ UseDevice(true); }
|
|
|
|
/// Construct a GridFunction associated with the FiniteElementSpace @a *f.
|
|
GridFunction(FiniteElementSpace *f) : Vector(f->GetVSize())
|
|
{ fes = f; fec = NULL; fes_sequence = f->GetSequence(); UseDevice(true); }
|
|
|
|
/// Construct a GridFunction using previously allocated array @a data.
|
|
/** The GridFunction does not assume ownership of @a data which is assumed to
|
|
be of size at least `f->GetVSize()`. Similar to the Vector constructor
|
|
for externally allocated array, the pointer @a data can be NULL. The data
|
|
array can be replaced later using the method SetData().
|
|
*/
|
|
GridFunction(FiniteElementSpace *f, double *data)
|
|
: Vector(data, f->GetVSize())
|
|
{ fes = f; fec = NULL; fes_sequence = f->GetSequence(); UseDevice(true); }
|
|
|
|
/** @brief Construct a GridFunction using previously allocated Vector @a base
|
|
starting at the given offset, @a base_offset. */
|
|
GridFunction(FiniteElementSpace *f, Vector &base, int base_offset = 0)
|
|
: Vector(base, base_offset, f->GetVSize())
|
|
{ fes = f; fec = NULL; fes_sequence = f->GetSequence(); UseDevice(true); }
|
|
|
|
/// Construct a GridFunction on the given Mesh, using the data from @a input.
|
|
/** The content of @a input should be in the format created by the method
|
|
Save(). The reconstructed FiniteElementSpace and FiniteElementCollection
|
|
are owned by the GridFunction. */
|
|
GridFunction(Mesh *m, std::istream &input);
|
|
|
|
GridFunction(Mesh *m, GridFunction *gf_array[], int num_pieces);
|
|
|
|
/// Copy assignment. Only the data of the base class Vector is copied.
|
|
/** It is assumed that this object and @a rhs use FiniteElementSpace%s that
|
|
have the same size.
|
|
|
|
@note Defining this method overwrites the implicitly defined copy
|
|
assignment operator. */
|
|
GridFunction &operator=(const GridFunction &rhs)
|
|
{ return operator=((const Vector &)rhs); }
|
|
|
|
/// Make the GridFunction the owner of #fec and #fes.
|
|
/** If the new FiniteElementCollection, @a fec_, is NULL, ownership of #fec
|
|
and #fes is taken away. */
|
|
void MakeOwner(FiniteElementCollection *fec_) { fec = fec_; }
|
|
|
|
FiniteElementCollection *OwnFEC() { return fec; }
|
|
|
|
int VectorDim() const;
|
|
int CurlDim() const;
|
|
|
|
/// Read only access to the (optional) internal true-dof Vector.
|
|
const Vector &GetTrueVector() const
|
|
{
|
|
MFEM_VERIFY(t_vec.Size() > 0, "SetTrueVector() before GetTrueVector()");
|
|
return t_vec;
|
|
}
|
|
/// Read and write access to the (optional) internal true-dof Vector.
|
|
/** Note that @a t_vec is set if it is not allocated or set already.*/
|
|
Vector &GetTrueVector()
|
|
{ if (t_vec.Size() == 0) { SetTrueVector(); } return t_vec; }
|
|
|
|
/// Extract the true-dofs from the GridFunction.
|
|
void GetTrueDofs(Vector &tv) const;
|
|
|
|
/// Shortcut for calling GetTrueDofs() with GetTrueVector() as argument.
|
|
void SetTrueVector() { GetTrueDofs(t_vec); }
|
|
|
|
/// Set the GridFunction from the given true-dof vector.
|
|
virtual void SetFromTrueDofs(const Vector &tv);
|
|
|
|
/// Shortcut for calling SetFromTrueDofs() with GetTrueVector() as argument.
|
|
void SetFromTrueVector() { SetFromTrueDofs(GetTrueVector()); }
|
|
|
|
/// Returns the values in the vertices of i'th element for dimension vdim.
|
|
void GetNodalValues(int i, Array<double> &nval, int vdim = 1) const;
|
|
|
|
/** @name Element index Get Value Methods
|
|
|
|
These methods take an element index and return the interpolated value of
|
|
the field at a given reference point within the element.
|
|
|
|
@warning These methods retrieve and use the ElementTransformation object
|
|
from the mfem::Mesh. This can alter the state of the element
|
|
transformation object and can also lead to unexpected results when the
|
|
ElementTransformation object is already in use such as when these methods
|
|
are called from within an integration loop. Consider using
|
|
GetValue(ElementTransformation &T, ...) instead.
|
|
*/
|
|
///@{
|
|
/** Return a scalar value from within the given element. */
|
|
virtual double GetValue(int i, const IntegrationPoint &ip,
|
|
int vdim = 1) const;
|
|
|
|
/** Return a vector value from within the given element. */
|
|
virtual void GetVectorValue(int i, const IntegrationPoint &ip,
|
|
Vector &val) const;
|
|
///@}
|
|
|
|
/** @name Element Index Get Values Methods
|
|
|
|
These are convenience methods for repeatedly calling GetValue for
|
|
multiple points within a given element. The GetValues methods are
|
|
optimized and should perform better than repeatedly calling GetValue. The
|
|
GetVectorValues method simply calls GetVectorValue repeatedly.
|
|
|
|
@warning These methods retrieve and use the ElementTransformation object
|
|
from the mfem::Mesh. This can alter the state of the element
|
|
transformation object and can also lead to unexpected results when the
|
|
ElementTransformation object is already in use such as when these methods
|
|
are called from within an integration loop. Consider using
|
|
GetValues(ElementTransformation &T, ...) instead.
|
|
*/
|
|
///@{
|
|
/** Compute a collection of scalar values from within the element indicated
|
|
by the index i. */
|
|
void GetValues(int i, const IntegrationRule &ir, Vector &vals,
|
|
int vdim = 1) const;
|
|
|
|
/** Compute a collection of vector values from within the element indicated
|
|
by the index i. */
|
|
void GetValues(int i, const IntegrationRule &ir, Vector &vals,
|
|
DenseMatrix &tr, int vdim = 1) const;
|
|
|
|
void GetVectorValues(int i, const IntegrationRule &ir,
|
|
DenseMatrix &vals, DenseMatrix &tr) const;
|
|
///@}
|
|
|
|
/** @name ElementTransformation Get Value Methods
|
|
|
|
These member functions are designed for use within
|
|
GridFunctionCoefficient objects. These can be used with
|
|
ElementTransformation objects coming from either
|
|
Mesh::GetElementTransformation() or Mesh::GetBdrElementTransformation().
|
|
|
|
@note These methods do not reset the ElementTransformation object so they
|
|
should be safe to use within integration loops or other contexts where
|
|
the ElementTransformation is already in use.
|
|
*/
|
|
///@{
|
|
/** Return a scalar value from within the element indicated by the
|
|
ElementTransformation Object. */
|
|
virtual double GetValue(ElementTransformation &T, const IntegrationPoint &ip,
|
|
int comp = 0, Vector *tr = NULL) const;
|
|
|
|
/** Return a vector value from within the element indicated by the
|
|
ElementTransformation Object. */
|
|
virtual void GetVectorValue(ElementTransformation &T,
|
|
const IntegrationPoint &ip,
|
|
Vector &val, Vector *tr = NULL) const;
|
|
///@}
|
|
|
|
/** @name ElementTransformation Get Values Methods
|
|
|
|
These are convenience methods for repeatedly calling GetValue for
|
|
multiple points within a given element. They work by calling either the
|
|
ElementTransformation or FaceElementTransformations versions described
|
|
above. Consequently, these methods should not be expected to run faster
|
|
than calling the above methods in an external loop.
|
|
|
|
@note These methods do not reset the ElementTransformation object so they
|
|
should be safe to use within integration loops or other contexts where
|
|
the ElementTransformation is already in use.
|
|
|
|
@note These methods can also be used with FaceElementTransformations
|
|
objects.
|
|
*/
|
|
///@{
|
|
/** Compute a collection of scalar values from within the element indicated
|
|
by the ElementTransformation object. */
|
|
void GetValues(ElementTransformation &T, const IntegrationRule &ir,
|
|
Vector &vals, int comp = 0, DenseMatrix *tr = NULL) const;
|
|
|
|
/** Compute a collection of vector values from within the element indicated
|
|
by the ElementTransformation object. */
|
|
void GetVectorValues(ElementTransformation &T, const IntegrationRule &ir,
|
|
DenseMatrix &vals, DenseMatrix *tr = NULL) const;
|
|
///@}
|
|
|
|
/** @name Face Index Get Values Methods
|
|
|
|
These methods are designed to work with Discontinuous Galerkin basis
|
|
functions. They compute field values on the interface between elements,
|
|
or on boundary elements, by interpolating the field in a neighboring
|
|
element. The \a side argument indices which neighboring element should be
|
|
used: 0, 1, or 2 (automatically chosen).
|
|
|
|
@warning These methods retrieve and use the FaceElementTransformations
|
|
object from the mfem::Mesh. This can alter the state of the face element
|
|
transformations object and can also lead to unexpected results when the
|
|
FaceElementTransformations object is already in use such as when these
|
|
methods are called from within an integration loop. Consider using
|
|
GetValues(ElementTransformation &T, ...) instead.
|
|
*/
|
|
///@{
|
|
/** Compute a collection of scalar values from within the face
|
|
indicated by the index i. */
|
|
int GetFaceValues(int i, int side, const IntegrationRule &ir, Vector &vals,
|
|
DenseMatrix &tr, int vdim = 1) const;
|
|
|
|
/** Compute a collection of vector values from within the face
|
|
indicated by the index i. */
|
|
int GetFaceVectorValues(int i, int side, const IntegrationRule &ir,
|
|
DenseMatrix &vals, DenseMatrix &tr) const;
|
|
///@}
|
|
|
|
void GetLaplacians(int i, const IntegrationRule &ir, Vector &laps,
|
|
int vdim = 1) const;
|
|
|
|
void GetLaplacians(int i, const IntegrationRule &ir, Vector &laps,
|
|
DenseMatrix &tr, int vdim = 1) const;
|
|
|
|
void GetHessians(int i, const IntegrationRule &ir, DenseMatrix &hess,
|
|
int vdim = 1) const;
|
|
|
|
void GetHessians(int i, const IntegrationRule &ir, DenseMatrix &hess,
|
|
DenseMatrix &tr, int vdim = 1) const;
|
|
|
|
void GetValuesFrom(const GridFunction &orig_func);
|
|
|
|
void GetBdrValuesFrom(const GridFunction &orig_func);
|
|
|
|
void GetVectorFieldValues(int i, const IntegrationRule &ir,
|
|
DenseMatrix &vals,
|
|
DenseMatrix &tr, int comp = 0) const;
|
|
|
|
/// For a vector grid function, makes sure that the ordering is byNODES.
|
|
void ReorderByNodes();
|
|
|
|
/// Return the values as a vector on mesh vertices for dimension vdim.
|
|
void GetNodalValues(Vector &nval, int vdim = 1) const;
|
|
|
|
void GetVectorFieldNodalValues(Vector &val, int comp) const;
|
|
|
|
void ProjectVectorFieldOn(GridFunction &vec_field, int comp = 0);
|
|
|
|
/** @brief Compute a certain derivative of a function's component.
|
|
Derivatives of the function are computed at the DOF locations of @a der,
|
|
and averaged over overlapping DOFs. Thus this function projects the
|
|
derivative to the FiniteElementSpace of @a der.
|
|
@param[in] comp Index of the function's component to be differentiated.
|
|
The index is 1-based, i.e., use 1 for scalar functions.
|
|
@param[in] der_comp Use 0/1/2 for derivatives in x/y/z directions.
|
|
@param[out] der The resulting derivative (scalar function). The
|
|
FiniteElementSpace of this function must be set
|
|
before the call. */
|
|
void GetDerivative(int comp, int der_comp, GridFunction &der);
|
|
|
|
double GetDivergence(ElementTransformation &tr) const;
|
|
|
|
void GetCurl(ElementTransformation &tr, Vector &curl) const;
|
|
|
|
void GetGradient(ElementTransformation &tr, Vector &grad) const;
|
|
|
|
void GetGradients(ElementTransformation &tr, const IntegrationRule &ir,
|
|
DenseMatrix &grad) const;
|
|
|
|
void GetGradients(const int elem, const IntegrationRule &ir,
|
|
DenseMatrix &grad) const
|
|
{ GetGradients(*fes->GetElementTransformation(elem), ir, grad); }
|
|
|
|
void GetVectorGradient(ElementTransformation &tr, DenseMatrix &grad) const;
|
|
|
|
/** Compute \f$ (\int_{\Omega} (*this) \psi_i)/(\int_{\Omega} \psi_i) \f$,
|
|
where \f$ \psi_i \f$ are the basis functions for the FE space of avgs.
|
|
Both FE spaces should be scalar and on the same mesh. */
|
|
void GetElementAverages(GridFunction &avgs) const;
|
|
|
|
/** Sets the output vector @a dof_vals to the values of the degrees of
|
|
freedom of element @a el. */
|
|
virtual void GetElementDofValues(int el, Vector &dof_vals) const;
|
|
|
|
/** Impose the given bounds on the function's DOFs while preserving its local
|
|
* integral (described in terms of the given weights) on the i'th element
|
|
* through SLBPQ optimization.
|
|
* Intended to be used for discontinuous FE functions. */
|
|
void ImposeBounds(int i, const Vector &weights,
|
|
const Vector &lo_, const Vector &hi_);
|
|
void ImposeBounds(int i, const Vector &weights,
|
|
double min_ = 0.0, double max_ = infinity());
|
|
|
|
/** On a non-conforming mesh, make sure the function lies in the conforming
|
|
space by multiplying with R and then with P, the conforming restriction
|
|
and prolongation matrices of the space, respectively. */
|
|
void RestrictConforming();
|
|
|
|
/** @brief Project the @a src GridFunction to @a this GridFunction, both of
|
|
which must be on the same mesh. */
|
|
/** The current implementation assumes that all elements use the same
|
|
projection matrix. */
|
|
void ProjectGridFunction(const GridFunction &src);
|
|
|
|
/** @brief Project @a coeff Coefficient to @a this GridFunction. The
|
|
projection computation depends on the choice of the FiniteElementSpace
|
|
#fes. Note that this is usually interpolation at the degrees of freedom
|
|
in each element (not L2 projection). */
|
|
virtual void ProjectCoefficient(Coefficient &coeff);
|
|
|
|
/** @brief Project @a coeff Coefficient to @a this GridFunction, using one
|
|
element for each degree of freedom in @a dofs and nodal interpolation on
|
|
that element. */
|
|
void ProjectCoefficient(Coefficient &coeff, Array<int> &dofs, int vd = 0);
|
|
|
|
/** @brief Project @a vcoeff VectorCoefficient to @a this GridFunction. The
|
|
projection computation depends on the choice of the FiniteElementSpace
|
|
#fes. Note that this is usually interpolation at the degrees of freedom
|
|
in each element (not L2 projection).*/
|
|
void ProjectCoefficient(VectorCoefficient &vcoeff);
|
|
|
|
/** @brief Project @a vcoeff VectorCoefficient to @a this GridFunction, using
|
|
one element for each degree of freedom in @a dofs and nodal interpolation
|
|
on that element. */
|
|
void ProjectCoefficient(VectorCoefficient &vcoeff, Array<int> &dofs);
|
|
|
|
/** @brief Project @a vcoeff VectorCoefficient to @a this GridFunction, only
|
|
projecting onto elements with the given @a attribute */
|
|
void ProjectCoefficient(VectorCoefficient &vcoeff, int attribute);
|
|
|
|
/** @brief Analogous to the version with argument @a vcoeff VectorCoefficient
|
|
but using an array of scalar coefficients for each component. */
|
|
void ProjectCoefficient(Coefficient *coeff[]);
|
|
|
|
/** @brief Project a discontinuous vector coefficient as a grid function on
|
|
a continuous finite element space. The values in shared dofs are
|
|
determined from the element with maximal attribute. */
|
|
virtual void ProjectDiscCoefficient(VectorCoefficient &coeff);
|
|
|
|
enum AvgType {ARITHMETIC, HARMONIC};
|
|
/** @brief Projects a discontinuous coefficient so that the values in shared
|
|
vdofs are computed by taking an average of the possible values. */
|
|
virtual void ProjectDiscCoefficient(Coefficient &coeff, AvgType type);
|
|
/** @brief Projects a discontinuous _vector_ coefficient so that the values
|
|
in shared vdofs are computed by taking an average of the possible values.
|
|
*/
|
|
virtual void ProjectDiscCoefficient(VectorCoefficient &coeff, AvgType type);
|
|
|
|
protected:
|
|
/** @brief Accumulates (depending on @a type) the values of @a coeff at all
|
|
shared vdofs and counts in how many zones each vdof appears. */
|
|
void AccumulateAndCountZones(Coefficient &coeff, AvgType type,
|
|
Array<int> &zones_per_vdof);
|
|
|
|
/** @brief Accumulates (depending on @a type) the values of @a vcoeff at all
|
|
shared vdofs and counts in how many zones each vdof appears. */
|
|
void AccumulateAndCountZones(VectorCoefficient &vcoeff, AvgType type,
|
|
Array<int> &zones_per_vdof);
|
|
|
|
/** @brief Used for the serial and parallel implementations of the
|
|
GetDerivative() method; see its documentation. */
|
|
void AccumulateAndCountDerivativeValues(int comp, int der_comp,
|
|
GridFunction &der,
|
|
Array<int> &zones_per_dof);
|
|
|
|
void AccumulateAndCountBdrValues(Coefficient *coeff[],
|
|
VectorCoefficient *vcoeff, Array<int> &attr,
|
|
Array<int> &values_counter);
|
|
|
|
void AccumulateAndCountBdrTangentValues(VectorCoefficient &vcoeff,
|
|
Array<int> &bdr_attr,
|
|
Array<int> &values_counter);
|
|
|
|
// Complete the computation of averages; called e.g. after
|
|
// AccumulateAndCountZones().
|
|
void ComputeMeans(AvgType type, Array<int> &zones_per_vdof);
|
|
|
|
public:
|
|
/** @brief Project a Coefficient on the GridFunction, modifying only DOFs on
|
|
the boundary associated with the boundary attributes marked in the
|
|
@a attr array. */
|
|
void ProjectBdrCoefficient(Coefficient &coeff, Array<int> &attr)
|
|
{
|
|
Coefficient *coeff_p = &coeff;
|
|
ProjectBdrCoefficient(&coeff_p, attr);
|
|
}
|
|
|
|
/** @brief Project a VectorCoefficient on the GridFunction, modifying only
|
|
DOFs on the boundary associated with the boundary attributes marked in
|
|
the @a attr array. */
|
|
virtual void ProjectBdrCoefficient(VectorCoefficient &vcoeff,
|
|
Array<int> &attr);
|
|
|
|
/** @brief Project a set of Coefficient%s on the components of the
|
|
GridFunction, modifying only DOFs on the boundary associated with the
|
|
boundary attributed marked in the @a attr array. */
|
|
/** If a Coefficient pointer in the array @a coeff is NULL, that component
|
|
will not be touched. */
|
|
virtual void ProjectBdrCoefficient(Coefficient *coeff[], Array<int> &attr);
|
|
|
|
/** Project the normal component of the given VectorCoefficient on
|
|
the boundary. Only boundary attributes that are marked in
|
|
'bdr_attr' are projected. Assumes RT-type VectorFE GridFunction. */
|
|
void ProjectBdrCoefficientNormal(VectorCoefficient &vcoeff,
|
|
Array<int> &bdr_attr);
|
|
|
|
/** @brief Project the tangential components of the given VectorCoefficient
|
|
on the boundary. Only boundary attributes that are marked in @a bdr_attr
|
|
are projected. Assumes ND-type VectorFE GridFunction. */
|
|
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
|
|
Array<int> &bdr_attr);
|
|
|
|
|
|
virtual double ComputeL2Error(Coefficient *exsol[],
|
|
const IntegrationRule *irs[] = NULL,
|
|
const Array<int> *elems = NULL) const;
|
|
|
|
/// Returns ||grad u_ex - grad u_h||_L2 in element ielem for H1 or L2 elements
|
|
virtual double ComputeElementGradError(int ielem, VectorCoefficient *exgrad,
|
|
const IntegrationRule *irs[] = NULL) const;
|
|
|
|
/// Returns ||u_ex - u_h||_L2 for H1 or L2 elements
|
|
/* The @a elems input variable expects a list of markers:
|
|
an elem marker equal to 1 will compute the L2 error on that element
|
|
an elem marker equal to 0 will not compute the L2 error on that element */
|
|
virtual double ComputeL2Error(Coefficient &exsol,
|
|
const IntegrationRule *irs[] = NULL,
|
|
const Array<int> *elems = NULL) const
|
|
{ return GridFunction::ComputeLpError(2.0, exsol, NULL, irs, elems); }
|
|
|
|
virtual double ComputeL2Error(VectorCoefficient &exsol,
|
|
const IntegrationRule *irs[] = NULL,
|
|
const Array<int> *elems = NULL) const;
|
|
|
|
/// Returns ||grad u_ex - grad u_h||_L2 for H1 or L2 elements
|
|
virtual double ComputeGradError(VectorCoefficient *exgrad,
|
|
const IntegrationRule *irs[] = NULL) const;
|
|
|
|
/// Returns ||curl u_ex - curl u_h||_L2 for ND elements
|
|
virtual double ComputeCurlError(VectorCoefficient *excurl,
|
|
const IntegrationRule *irs[] = NULL) const;
|
|
|
|
/// Returns ||div u_ex - div u_h||_L2 for RT elements
|
|
virtual double ComputeDivError(Coefficient *exdiv,
|
|
const IntegrationRule *irs[] = NULL) const;
|
|
|
|
/// Returns the Face Jumps error for L2 elements. The error can be weighted
|
|
/// by a constant nu, by nu/h, or nu*p^2/h, depending on the value of
|
|
/// @a jump_scaling.
|
|
virtual double ComputeDGFaceJumpError(Coefficient *exsol,
|
|
Coefficient *ell_coeff,
|
|
class JumpScaling jump_scaling,
|
|
const IntegrationRule *irs[] = NULL)
|
|
const;
|
|
|
|
/// Returns the Face Jumps error for L2 elements, with 1/h scaling.
|
|
MFEM_DEPRECATED
|
|
double ComputeDGFaceJumpError(Coefficient *exsol,
|
|
Coefficient *ell_coeff,
|
|
double Nu,
|
|
const IntegrationRule *irs[] = NULL) const;
|
|
|
|
/** This method is kept for backward compatibility.
|
|
|
|
Returns either the H1-seminorm, or the DG face jumps error, or both
|
|
depending on norm_type = 1, 2, 3. Additional arguments for the DG face
|
|
jumps norm: ell_coeff: mesh-depended coefficient (weight) Nu: scalar
|
|
constant weight */
|
|
virtual double ComputeH1Error(Coefficient *exsol, VectorCoefficient *exgrad,
|
|
Coefficient *ell_coef, double Nu,
|
|
int norm_type) const;
|
|
|
|
/// Returns the error measured in H1-norm for H1 elements or in "broken"
|
|
/// H1-norm for L2 elements
|
|
virtual double ComputeH1Error(Coefficient *exsol, VectorCoefficient *exgrad,
|
|
const IntegrationRule *irs[] = NULL) const;
|
|
|
|
/// Returns the error measured in H(div)-norm for RT elements
|
|
virtual double ComputeHDivError(VectorCoefficient *exsol,
|
|
Coefficient *exdiv,
|
|
const IntegrationRule *irs[] = NULL) const;
|
|
|
|
/// Returns the error measured in H(curl)-norm for ND elements
|
|
virtual double ComputeHCurlError(VectorCoefficient *exsol,
|
|
VectorCoefficient *excurl,
|
|
const IntegrationRule *irs[] = NULL) const;
|
|
|
|
virtual double ComputeMaxError(Coefficient &exsol,
|
|
const IntegrationRule *irs[] = NULL) const
|
|
{
|
|
return ComputeLpError(infinity(), exsol, NULL, irs);
|
|
}
|
|
|
|
virtual double ComputeMaxError(Coefficient *exsol[],
|
|
const IntegrationRule *irs[] = NULL) const;
|
|
|
|
virtual double ComputeMaxError(VectorCoefficient &exsol,
|
|
const IntegrationRule *irs[] = NULL) const
|
|
{
|
|
return ComputeLpError(infinity(), exsol, NULL, NULL, irs);
|
|
}
|
|
|
|
virtual double ComputeL1Error(Coefficient &exsol,
|
|
const IntegrationRule *irs[] = NULL) const
|
|
{ return ComputeLpError(1.0, exsol, NULL, irs); }
|
|
|
|
virtual double ComputeW11Error(Coefficient *exsol, VectorCoefficient *exgrad,
|
|
int norm_type, const Array<int> *elems = NULL,
|
|
const IntegrationRule *irs[] = NULL) const;
|
|
|
|
virtual double ComputeL1Error(VectorCoefficient &exsol,
|
|
const IntegrationRule *irs[] = NULL) const
|
|
{ return ComputeLpError(1.0, exsol, NULL, NULL, irs); }
|
|
|
|
/* The @a elems input variable expects a list of markers:
|
|
an elem marker equal to 1 will compute the L2 error on that element
|
|
an elem marker equal to 0 will not compute the L2 error on that element */
|
|
virtual double ComputeLpError(const double p, Coefficient &exsol,
|
|
Coefficient *weight = NULL,
|
|
const IntegrationRule *irs[] = NULL,
|
|
const Array<int> *elems = NULL) const;
|
|
|
|
/** Compute the Lp error in each element of the mesh and store the results in
|
|
the Vector @a error. The result should be of length number of elements,
|
|
for example an L2 GridFunction of order zero using map type VALUE. */
|
|
virtual void ComputeElementLpErrors(const double p, Coefficient &exsol,
|
|
Vector &error,
|
|
Coefficient *weight = NULL,
|
|
const IntegrationRule *irs[] = NULL
|
|
) const;
|
|
|
|
virtual void ComputeElementL1Errors(Coefficient &exsol,
|
|
Vector &error,
|
|
const IntegrationRule *irs[] = NULL
|
|
) const
|
|
{ ComputeElementLpErrors(1.0, exsol, error, NULL, irs); }
|
|
|
|
virtual void ComputeElementL2Errors(Coefficient &exsol,
|
|
Vector &error,
|
|
const IntegrationRule *irs[] = NULL
|
|
) const
|
|
{ ComputeElementLpErrors(2.0, exsol, error, NULL, irs); }
|
|
|
|
virtual void ComputeElementMaxErrors(Coefficient &exsol,
|
|
Vector &error,
|
|
const IntegrationRule *irs[] = NULL
|
|
) const
|
|
{ ComputeElementLpErrors(infinity(), exsol, error, NULL, irs); }
|
|
|
|
/** When given a vector weight, compute the pointwise (scalar) error as the
|
|
dot product of the vector error with the vector weight. Otherwise, the
|
|
scalar error is the l_2 norm of the vector error. */
|
|
virtual double ComputeLpError(const double p, VectorCoefficient &exsol,
|
|
Coefficient *weight = NULL,
|
|
VectorCoefficient *v_weight = NULL,
|
|
const IntegrationRule *irs[] = NULL) const;
|
|
|
|
/** Compute the Lp error in each element of the mesh and store the results in
|
|
the Vector @ error. The result should be of length number of elements,
|
|
for example an L2 GridFunction of order zero using map type VALUE. */
|
|
virtual void ComputeElementLpErrors(const double p, VectorCoefficient &exsol,
|
|
Vector &error,
|
|
Coefficient *weight = NULL,
|
|
VectorCoefficient *v_weight = NULL,
|
|
const IntegrationRule *irs[] = NULL
|
|
) const;
|
|
|
|
virtual void ComputeElementL1Errors(VectorCoefficient &exsol,
|
|
Vector &error,
|
|
const IntegrationRule *irs[] = NULL
|
|
) const
|
|
{ ComputeElementLpErrors(1.0, exsol, error, NULL, NULL, irs); }
|
|
|
|
virtual void ComputeElementL2Errors(VectorCoefficient &exsol,
|
|
Vector &error,
|
|
const IntegrationRule *irs[] = NULL
|
|
) const
|
|
{ ComputeElementLpErrors(2.0, exsol, error, NULL, NULL, irs); }
|
|
|
|
virtual void ComputeElementMaxErrors(VectorCoefficient &exsol,
|
|
Vector &error,
|
|
const IntegrationRule *irs[] = NULL
|
|
) const
|
|
{ ComputeElementLpErrors(infinity(), exsol, error, NULL, NULL, irs); }
|
|
|
|
virtual void ComputeFlux(BilinearFormIntegrator &blfi,
|
|
GridFunction &flux,
|
|
bool wcoef = true, int subdomain = -1);
|
|
|
|
/// Redefine '=' for GridFunction = constant.
|
|
GridFunction &operator=(double value);
|
|
|
|
/// Copy the data from @a v.
|
|
/** The size of @a v must be equal to the size of the associated
|
|
FiniteElementSpace #fes. */
|
|
GridFunction &operator=(const Vector &v);
|
|
|
|
/// Transform by the Space UpdateMatrix (e.g., on Mesh change).
|
|
virtual void Update();
|
|
|
|
FiniteElementSpace *FESpace() { return fes; }
|
|
const FiniteElementSpace *FESpace() const { return fes; }
|
|
|
|
/// Associate a new FiniteElementSpace with the GridFunction.
|
|
/** The GridFunction is resized using the SetSize() method. */
|
|
virtual void SetSpace(FiniteElementSpace *f);
|
|
|
|
using Vector::MakeRef;
|
|
|
|
/** @brief Make the GridFunction reference external data on a new
|
|
FiniteElementSpace. */
|
|
/** This method changes the FiniteElementSpace associated with the
|
|
GridFunction and sets the pointer @a v as external data in the
|
|
GridFunction. */
|
|
virtual void MakeRef(FiniteElementSpace *f, double *v);
|
|
|
|
/** @brief Make the GridFunction reference external data on a new
|
|
FiniteElementSpace. */
|
|
/** This method changes the FiniteElementSpace associated with the
|
|
GridFunction and sets the data of the Vector @a v (plus the @a v_offset)
|
|
as external data in the GridFunction.
|
|
@note This version of the method will also perform bounds checks when
|
|
the build option MFEM_DEBUG is enabled. */
|
|
virtual void MakeRef(FiniteElementSpace *f, Vector &v, int v_offset);
|
|
|
|
/** @brief Associate a new FiniteElementSpace and new true-dof data with the
|
|
GridFunction. */
|
|
/** - If the prolongation matrix of @a f is trivial (i.e. its method
|
|
FiniteElementSpace::GetProlongationMatrix() returns NULL), then the
|
|
method MakeRef() is called with the same arguments.
|
|
- Otherwise, the method SetSpace() is called with argument @a f.
|
|
- The internal true-dof vector is set to reference @a tv. */
|
|
void MakeTRef(FiniteElementSpace *f, double *tv);
|
|
|
|
/** @brief Associate a new FiniteElementSpace and new true-dof data with the
|
|
GridFunction. */
|
|
/** - If the prolongation matrix of @a f is trivial (i.e. its method
|
|
FiniteElementSpace::GetProlongationMatrix() returns NULL), this method
|
|
calls MakeRef() with the same arguments.
|
|
- Otherwise, this method calls SetSpace() with argument @a f.
|
|
- The internal true-dof vector is set to reference the sub-vector of
|
|
@a tv starting at the offset @a tv_offset. */
|
|
void MakeTRef(FiniteElementSpace *f, Vector &tv, int tv_offset);
|
|
|
|
/// Save the GridFunction to an output stream.
|
|
virtual void Save(std::ostream &out) const;
|
|
|
|
/// Save the GridFunction to a file. The given @a precision will be used for
|
|
/// ASCII output.
|
|
virtual void Save(const char *fname, int precision=16) const;
|
|
|
|
#ifdef MFEM_USE_ADIOS2
|
|
/// Save the GridFunction to a binary output stream using adios2 bp format.
|
|
virtual void Save(adios2stream &out, const std::string& variable_name,
|
|
const adios2stream::data_type
|
|
type = adios2stream::data_type::point_data) const;
|
|
#endif
|
|
|
|
/** @brief Write the GridFunction in VTK format. Note that Mesh::PrintVTK
|
|
must be called first. The parameter ref > 0 must match the one used in
|
|
Mesh::PrintVTK. */
|
|
void SaveVTK(std::ostream &out, const std::string &field_name, int ref);
|
|
|
|
/** @brief Write the GridFunction in STL format. Note that the mesh dimension
|
|
must be 2 and that quad elements will be broken into two triangles.*/
|
|
void SaveSTL(std::ostream &out, int TimesToRefine = 1);
|
|
|
|
/// Destroys grid function.
|
|
virtual ~GridFunction() { Destroy(); }
|
|
};
|
|
|
|
|
|
/** Overload operator<< for std::ostream and GridFunction; valid also for the
|
|
derived class ParGridFunction */
|
|
std::ostream &operator<<(std::ostream &out, const GridFunction &sol);
|
|
|
|
/// Class used to specify how the jump terms in
|
|
/// GridFunction::ComputeDGFaceJumpError are scaled.
|
|
class JumpScaling
|
|
{
|
|
public:
|
|
enum JumpScalingType
|
|
{
|
|
CONSTANT,
|
|
ONE_OVER_H,
|
|
P_SQUARED_OVER_H
|
|
};
|
|
private:
|
|
double nu;
|
|
JumpScalingType type;
|
|
public:
|
|
JumpScaling(double nu_=1.0, JumpScalingType type_=CONSTANT)
|
|
: nu(nu_), type(type_) { }
|
|
double Eval(double h, int p) const
|
|
{
|
|
double val = nu;
|
|
if (type != CONSTANT) { val /= h; }
|
|
if (type == P_SQUARED_OVER_H) { val *= p*p; }
|
|
return val;
|
|
}
|
|
};
|
|
|
|
/// Overload operator<< for std::ostream and QuadratureFunction.
|
|
std::ostream &operator<<(std::ostream &out, const QuadratureFunction &qf);
|
|
|
|
|
|
double ZZErrorEstimator(BilinearFormIntegrator &blfi,
|
|
GridFunction &u,
|
|
GridFunction &flux,
|
|
Vector &error_estimates,
|
|
Array<int> *aniso_flags = NULL,
|
|
int with_subdomains = 1,
|
|
bool with_coeff = false);
|
|
|
|
/// Defines the global tensor product polynomial space used by NewZZErorrEstimator
|
|
/**
|
|
* See BoundingBox(...) for a description of @a angle and @a midpoint
|
|
*/
|
|
void TensorProductLegendre(int dim, // input
|
|
int order, // input
|
|
const Vector &x_in, // input
|
|
const Vector &xmax, // input
|
|
const Vector &xmin, // input
|
|
Vector &poly, // output
|
|
double angle=0.0, // input (optional)
|
|
const Vector *midpoint=NULL); // input (optional)
|
|
|
|
/// Defines the bounding box for the face patches used by NewZZErorrEstimator
|
|
/**
|
|
* By default, BoundingBox(...) computes the parameters of a minimal bounding box
|
|
* for the given @a face_patch that is aligned with the physical (i.e. global)
|
|
* Cartesian axes. This means that the size of the bounding box will depend on the
|
|
* orientation of the patch. It is better to construct an orientation-independent box.
|
|
* This is implemented for 2D patches. The parameters @a angle and @a midpoint encode
|
|
* the necessary additional geometric information.
|
|
*
|
|
* @a iface : Index of the face that the patch corresponds to.
|
|
* This is used to compute @a angle and @a midpoint.
|
|
*
|
|
* @a angle : The angle the patch face makes with the x-axis.
|
|
* @a midpoint : The midpoint of the face.
|
|
*/
|
|
void BoundingBox(const Array<int> &face_patch, // input
|
|
FiniteElementSpace *ufes, // input
|
|
int order, // input
|
|
Vector &xmin, // output
|
|
Vector &xmax, // output
|
|
double &angle, // output
|
|
Vector &midpoint, // output
|
|
int iface=-1); // input (optional)
|
|
|
|
/// A ``true'' ZZ error estimator that uses face-based patches for flux reconstruction.
|
|
/**
|
|
* Only two-element face patches are ever used:
|
|
* - For conforming faces, the face patch consists of its two neighboring elements.
|
|
* - In the non-conforming setting, only the face patches associated to fine-scale
|
|
* element faces are used. These face patches always consist of two elements
|
|
* delivered by mesh::GetFaceElements(Face, *Elem1, *Elem2).
|
|
*/
|
|
double LSZZErrorEstimator(BilinearFormIntegrator &blfi, // input
|
|
GridFunction &u, // input
|
|
Vector &error_estimates, // output
|
|
bool subdomain_reconstruction = true, // input (optional)
|
|
bool with_coeff = false, // input (optional)
|
|
double tichonov_coeff = 0.0); // input (optional)
|
|
|
|
/// Compute the Lp distance between two grid functions on the given element.
|
|
double ComputeElementLpDistance(double p, int i,
|
|
GridFunction& gf1, GridFunction& gf2);
|
|
|
|
|
|
/// Class used for extruding scalar GridFunctions
|
|
class ExtrudeCoefficient : public Coefficient
|
|
{
|
|
private:
|
|
int n;
|
|
Mesh *mesh_in;
|
|
Coefficient &sol_in;
|
|
public:
|
|
ExtrudeCoefficient(Mesh *m, Coefficient &s, int n_)
|
|
: n(n_), mesh_in(m), sol_in(s) { }
|
|
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
|
|
virtual ~ExtrudeCoefficient() { }
|
|
};
|
|
|
|
/// Extrude a scalar 1D GridFunction, after extruding the mesh with Extrude1D.
|
|
GridFunction *Extrude1DGridFunction(Mesh *mesh, Mesh *mesh2d,
|
|
GridFunction *sol, const int ny);
|
|
|
|
} // namespace mfem
|
|
|
|
#endif
|