347 lines
14 KiB
C++
347 lines
14 KiB
C++
// Copyright (c) 2010-2020, 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_NONLININTEG
|
|
#define MFEM_NONLININTEG
|
|
|
|
#include "../config/config.hpp"
|
|
#include "fe.hpp"
|
|
#include "coefficient.hpp"
|
|
#include "fespace.hpp"
|
|
|
|
namespace mfem
|
|
{
|
|
|
|
/** @brief This class is used to express the local action of a general nonlinear
|
|
finite element operator. In addition it may provide the capability to
|
|
assemble the local gradient operator and to compute the local energy. */
|
|
class NonlinearFormIntegrator
|
|
{
|
|
protected:
|
|
const IntegrationRule *IntRule;
|
|
|
|
NonlinearFormIntegrator(const IntegrationRule *ir = NULL)
|
|
: IntRule(ir) { }
|
|
|
|
public:
|
|
/** @brief Prescribe a fixed IntegrationRule to use (when @a ir != NULL) or
|
|
let the integrator choose (when @a ir == NULL). */
|
|
void SetIntRule(const IntegrationRule *ir) { IntRule = ir; }
|
|
|
|
/// Prescribe a fixed IntegrationRule to use.
|
|
void SetIntegrationRule(const IntegrationRule &irule) { IntRule = &irule; }
|
|
|
|
/// Perform the local action of the NonlinearFormIntegrator
|
|
virtual void AssembleElementVector(const FiniteElement &el,
|
|
ElementTransformation &Tr,
|
|
const Vector &elfun, Vector &elvect);
|
|
|
|
/// @brief Perform the local action of the NonlinearFormIntegrator resulting
|
|
/// from a face integral term.
|
|
virtual void AssembleFaceVector(const FiniteElement &el1,
|
|
const FiniteElement &el2,
|
|
FaceElementTransformations &Tr,
|
|
const Vector &elfun, Vector &elvect);
|
|
|
|
/// Assemble the local gradient matrix
|
|
virtual void AssembleElementGrad(const FiniteElement &el,
|
|
ElementTransformation &Tr,
|
|
const Vector &elfun, DenseMatrix &elmat);
|
|
|
|
/// @brief Assemble the local action of the gradient of the
|
|
/// NonlinearFormIntegrator resulting from a face integral term.
|
|
virtual void AssembleFaceGrad(const FiniteElement &el1,
|
|
const FiniteElement &el2,
|
|
FaceElementTransformations &Tr,
|
|
const Vector &elfun, DenseMatrix &elmat);
|
|
|
|
/// Compute the local energy
|
|
virtual double GetElementEnergy(const FiniteElement &el,
|
|
ElementTransformation &Tr,
|
|
const Vector &elfun);
|
|
|
|
/// Method defining partial assembly.
|
|
/** The result of the partial assembly is stored internally so that it can be
|
|
used later in the methods AddMultPA(). */
|
|
virtual void AssemblePA(const FiniteElementSpace &fes);
|
|
|
|
/** The result of the partial assembly is stored internally so that it can be
|
|
used later in the methods AddMultPA().
|
|
Used with BilinearFormIntegrators that have different spaces. */
|
|
virtual void AssemblePA(const FiniteElementSpace &trial_fes,
|
|
const FiniteElementSpace &test_fes);
|
|
|
|
/// Method for partially assembled action.
|
|
/** Perform the action of integrator on the input @a x and add the result to
|
|
the output @a y. Both @a x and @a y are E-vectors, i.e. they represent
|
|
the element-wise discontinuous version of the FE space.
|
|
|
|
This method can be called only after the method AssemblePA() has been
|
|
called. */
|
|
virtual void AddMultPA(const Vector &x, Vector &y) const;
|
|
|
|
virtual ~NonlinearFormIntegrator() { }
|
|
};
|
|
|
|
/** The abstract base class BlockNonlinearFormIntegrator is
|
|
a generalization of the NonlinearFormIntegrator class suitable
|
|
for block state vectors. */
|
|
class BlockNonlinearFormIntegrator
|
|
{
|
|
public:
|
|
/// Compute the local energy
|
|
virtual double GetElementEnergy(const Array<const FiniteElement *>&el,
|
|
ElementTransformation &Tr,
|
|
const Array<const Vector *>&elfun);
|
|
|
|
/// Perform the local action of the BlockNonlinearFormIntegrator
|
|
virtual void AssembleElementVector(const Array<const FiniteElement *> &el,
|
|
ElementTransformation &Tr,
|
|
const Array<const Vector *> &elfun,
|
|
const Array<Vector *> &elvec);
|
|
|
|
virtual void AssembleFaceVector(const Array<const FiniteElement *> &el1,
|
|
const Array<const FiniteElement *> &el2,
|
|
FaceElementTransformations &Tr,
|
|
const Array<const Vector *> &elfun,
|
|
const Array<Vector *> &elvect);
|
|
|
|
/// Assemble the local gradient matrix
|
|
virtual void AssembleElementGrad(const Array<const FiniteElement*> &el,
|
|
ElementTransformation &Tr,
|
|
const Array<const Vector *> &elfun,
|
|
const Array2D<DenseMatrix *> &elmats);
|
|
|
|
virtual void AssembleFaceGrad(const Array<const FiniteElement *>&el1,
|
|
const Array<const FiniteElement *>&el2,
|
|
FaceElementTransformations &Tr,
|
|
const Array<const Vector *> &elfun,
|
|
const Array2D<DenseMatrix *> &elmats);
|
|
|
|
virtual ~BlockNonlinearFormIntegrator() { }
|
|
};
|
|
|
|
|
|
/// Abstract class for hyperelastic models
|
|
class HyperelasticModel
|
|
{
|
|
protected:
|
|
ElementTransformation *Ttr; /**< Reference-element to target-element
|
|
transformation. */
|
|
|
|
public:
|
|
HyperelasticModel() : Ttr(NULL) { }
|
|
virtual ~HyperelasticModel() { }
|
|
|
|
/// A reference-element to target-element transformation that can be used to
|
|
/// evaluate Coefficient%s.
|
|
/** @note It is assumed that _Ttr.SetIntPoint() is already called for the
|
|
point of interest. */
|
|
void SetTransformation(ElementTransformation &_Ttr) { Ttr = &_Ttr; }
|
|
|
|
/** @brief Evaluate the strain energy density function, W = W(Jpt).
|
|
@param[in] Jpt Represents the target->physical transformation
|
|
Jacobian matrix. */
|
|
virtual double EvalW(const DenseMatrix &Jpt) const = 0;
|
|
|
|
/** @brief Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
|
|
@param[in] Jpt Represents the target->physical transformation
|
|
Jacobian matrix.
|
|
@param[out] P The evaluated 1st Piola-Kirchhoff stress tensor. */
|
|
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const = 0;
|
|
|
|
/** @brief Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor
|
|
and assemble its contribution to the local gradient matrix 'A'.
|
|
@param[in] Jpt Represents the target->physical transformation
|
|
Jacobian matrix.
|
|
@param[in] DS Gradient of the basis matrix (dof x dim).
|
|
@param[in] weight Quadrature weight coefficient for the point.
|
|
@param[in,out] A Local gradient matrix where the contribution from this
|
|
point will be added.
|
|
|
|
Computes weight * d(dW_dxi)_d(xj) at the current point, for all i and j,
|
|
where x1 ... xn are the FE dofs. This function is usually defined using
|
|
the matrix invariants and their derivatives.
|
|
*/
|
|
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS,
|
|
const double weight, DenseMatrix &A) const = 0;
|
|
};
|
|
|
|
|
|
/** Inverse-harmonic hyperelastic model with a strain energy density function
|
|
given by the formula: W(J) = (1/2) det(J) Tr((J J^t)^{-1}) where J is the
|
|
deformation gradient. */
|
|
class InverseHarmonicModel : public HyperelasticModel
|
|
{
|
|
protected:
|
|
mutable DenseMatrix Z, S; // dim x dim
|
|
mutable DenseMatrix G, C; // dof x dim
|
|
|
|
public:
|
|
virtual double EvalW(const DenseMatrix &J) const;
|
|
|
|
virtual void EvalP(const DenseMatrix &J, DenseMatrix &P) const;
|
|
|
|
virtual void AssembleH(const DenseMatrix &J, const DenseMatrix &DS,
|
|
const double weight, DenseMatrix &A) const;
|
|
};
|
|
|
|
|
|
/** Neo-Hookean hyperelastic model with a strain energy density function given
|
|
by the formula: \f$(\mu/2)(\bar{I}_1 - dim) + (K/2)(det(J)/g - 1)^2\f$ where
|
|
J is the deformation gradient and \f$\bar{I}_1 = (det(J))^{-2/dim} Tr(J
|
|
J^t)\f$. The parameters \f$\mu\f$ and K are the shear and bulk moduli,
|
|
respectively, and g is a reference volumetric scaling. */
|
|
class NeoHookeanModel : public HyperelasticModel
|
|
{
|
|
protected:
|
|
mutable double mu, K, g;
|
|
Coefficient *c_mu, *c_K, *c_g;
|
|
bool have_coeffs;
|
|
|
|
mutable DenseMatrix Z; // dim x dim
|
|
mutable DenseMatrix G, C; // dof x dim
|
|
|
|
inline void EvalCoeffs() const;
|
|
|
|
public:
|
|
NeoHookeanModel(double _mu, double _K, double _g = 1.0)
|
|
: mu(_mu), K(_K), g(_g), have_coeffs(false) { c_mu = c_K = c_g = NULL; }
|
|
|
|
NeoHookeanModel(Coefficient &_mu, Coefficient &_K, Coefficient *_g = NULL)
|
|
: mu(0.0), K(0.0), g(1.0), c_mu(&_mu), c_K(&_K), c_g(_g),
|
|
have_coeffs(true) { }
|
|
|
|
virtual double EvalW(const DenseMatrix &J) const;
|
|
|
|
virtual void EvalP(const DenseMatrix &J, DenseMatrix &P) const;
|
|
|
|
virtual void AssembleH(const DenseMatrix &J, const DenseMatrix &DS,
|
|
const double weight, DenseMatrix &A) const;
|
|
};
|
|
|
|
|
|
/** Hyperelastic integrator for any given HyperelasticModel.
|
|
|
|
Represents @f$ \int W(Jpt) dx @f$ over a target zone, where W is the
|
|
@a model's strain energy density function, and Jpt is the Jacobian of the
|
|
target->physical coordinates transformation. The target configuration is
|
|
given by the current mesh at the time of the evaluation of the integrator.
|
|
*/
|
|
class HyperelasticNLFIntegrator : public NonlinearFormIntegrator
|
|
{
|
|
private:
|
|
HyperelasticModel *model;
|
|
|
|
// Jrt: the Jacobian of the target-to-reference-element transformation.
|
|
// Jpr: the Jacobian of the reference-to-physical-element transformation.
|
|
// Jpt: the Jacobian of the target-to-physical-element transformation.
|
|
// P: represents dW_d(Jtp) (dim x dim).
|
|
// DSh: gradients of reference shape functions (dof x dim).
|
|
// DS: gradients of the shape functions in the target (stress-free)
|
|
// configuration (dof x dim).
|
|
// PMatI: coordinates of the deformed configuration (dof x dim).
|
|
// PMatO: reshaped view into the local element contribution to the operator
|
|
// output - the result of AssembleElementVector() (dof x dim).
|
|
DenseMatrix DSh, DS, Jrt, Jpr, Jpt, P, PMatI, PMatO;
|
|
|
|
public:
|
|
/** @param[in] m HyperelasticModel that will be integrated. */
|
|
HyperelasticNLFIntegrator(HyperelasticModel *m) : model(m) { }
|
|
|
|
/** @brief Computes the integral of W(Jacobian(Trt)) over a target zone
|
|
@param[in] el Type of FiniteElement.
|
|
@param[in] Ttr Represents ref->target coordinates transformation.
|
|
@param[in] elfun Physical coordinates of the zone. */
|
|
virtual double GetElementEnergy(const FiniteElement &el,
|
|
ElementTransformation &Ttr,
|
|
const Vector &elfun);
|
|
|
|
virtual void AssembleElementVector(const FiniteElement &el,
|
|
ElementTransformation &Ttr,
|
|
const Vector &elfun, Vector &elvect);
|
|
|
|
virtual void AssembleElementGrad(const FiniteElement &el,
|
|
ElementTransformation &Ttr,
|
|
const Vector &elfun, DenseMatrix &elmat);
|
|
};
|
|
|
|
/** Hyperelastic incompressible Neo-Hookean integrator with the PK1 stress
|
|
\f$P = \mu F - p F^{-T}\f$ where \f$\mu\f$ is the shear modulus,
|
|
\f$p\f$ is the pressure, and \f$F\f$ is the deformation gradient */
|
|
class IncompressibleNeoHookeanIntegrator : public BlockNonlinearFormIntegrator
|
|
{
|
|
private:
|
|
Coefficient *c_mu;
|
|
DenseMatrix DSh_u, DS_u, J0i, J, J1, Finv, P, F, FinvT;
|
|
DenseMatrix PMatI_u, PMatO_u, PMatI_p, PMatO_p, Z, G, C;
|
|
Vector Sh_p;
|
|
|
|
public:
|
|
IncompressibleNeoHookeanIntegrator(Coefficient &_mu) : c_mu(&_mu) { }
|
|
|
|
virtual double GetElementEnergy(const Array<const FiniteElement *>&el,
|
|
ElementTransformation &Tr,
|
|
const Array<const Vector *> &elfun);
|
|
|
|
/// Perform the local action of the NonlinearFormIntegrator
|
|
virtual void AssembleElementVector(const Array<const FiniteElement *> &el,
|
|
ElementTransformation &Tr,
|
|
const Array<const Vector *> &elfun,
|
|
const Array<Vector *> &elvec);
|
|
|
|
/// Assemble the local gradient matrix
|
|
virtual void AssembleElementGrad(const Array<const FiniteElement*> &el,
|
|
ElementTransformation &Tr,
|
|
const Array<const Vector *> &elfun,
|
|
const Array2D<DenseMatrix *> &elmats);
|
|
};
|
|
|
|
class VectorConvectionNLFIntegrator : public NonlinearFormIntegrator
|
|
{
|
|
private:
|
|
Coefficient *Q{};
|
|
DenseMatrix dshape, dshapex, EF, gradEF, ELV, elmat_comp;
|
|
Vector shape;
|
|
// PA extension
|
|
Vector pa_data;
|
|
const DofToQuad *maps; ///< Not owned
|
|
const GeometricFactors *geom; ///< Not owned
|
|
int dim, ne, nq;
|
|
public:
|
|
VectorConvectionNLFIntegrator(Coefficient &q): Q(&q) { }
|
|
|
|
VectorConvectionNLFIntegrator() = default;
|
|
|
|
static const IntegrationRule &GetRule(const FiniteElement &fe,
|
|
ElementTransformation &T);
|
|
|
|
virtual void AssembleElementVector(const FiniteElement &el,
|
|
ElementTransformation &trans,
|
|
const Vector &elfun,
|
|
Vector &elvect);
|
|
|
|
virtual void AssembleElementGrad(const FiniteElement &el,
|
|
ElementTransformation &trans,
|
|
const Vector &elfun,
|
|
DenseMatrix &elmat);
|
|
|
|
using NonlinearFormIntegrator::AssemblePA;
|
|
|
|
virtual void AssemblePA(const FiniteElementSpace &fes);
|
|
|
|
virtual void AddMultPA(const Vector &x, Vector &y) const;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|