9#include <kernel/geometry/conformal_mesh.hpp> 
   10#include <kernel/shape.hpp> 
   11#include <kernel/meshopt/base.hpp> 
   12#include <kernel/meshopt/rumpf_functional.hpp> 
   14#include <kernel/eval_tags.hpp> 
   15#include <kernel/cubature/dynamic_factory.hpp> 
   16#include <kernel/cubature/rule.hpp> 
   27    template<
typename DataType_, 
int shape_dim_>
 
   28    class RumpfFunctional<DataType_,
 
   29    Trafo::Standard::Mapping<Geometry::ConformalMesh<Shape::Simplex<shape_dim_>, shape_dim_, DataType_>>> :
 
   30      public RumpfFunctionalBase<DataType_>
 
   34          typedef RumpfFunctionalBase<DataType_> 
BaseClass;
 
   39          static constexpr int shape_dim = shape_dim_;
 
   43          typedef Shape::Simplex<shape_dim_> 
ShapeType;
 
   45          typedef Trafo::Standard::Mapping<Geometry::ConformalMesh<ShapeType, world_dim, DataType_>> 
TrafoType;
 
   47          typedef typename Intern::TrafoFE<TrafoType>::Space 
TrafoSpace;
 
   50          typedef Tiny::Matrix<DataType_, Shape::FaceTraits<ShapeType,0>::count, 
world_dim> 
Tx;
 
   52          typedef Tiny::Vector<DataType_, Shape::FaceTraits<ShapeType,0>::count*
world_dim> 
Tgradh;
 
   55          typedef Tiny::Matrix<DataType_, shape_dim, world_dim> 
TgradR;
 
   58          typedef typename TrafoType::template Evaluator<ShapeType, DataType>::Type 
TrafoEvaluator;
 
   60          typedef typename TrafoSpace::template Evaluator<TrafoEvaluator>::Type 
SpaceEvaluator;
 
   68          typedef typename TrafoEvaluator::template ConfigTraits<trafo_config>::EvalDataType 
TrafoEvalData;
 
   70          typedef typename SpaceEvaluator::template ConfigTraits<space_config>::EvalDataType 
SpaceEvalData;
 
   82          Cubature::DynamicFactory _cubature_factory;
 
   84          Cubature::Rule<ShapeType, DataType, DataType, Tiny::Vector<DataType, world_dim>> _cubature_rule;
 
   96          const int _exponent_det;
 
   99          const bool _compute_frobenius;
 
  101          const bool _compute_cof;
 
  103          const bool _compute_det;
 
  105          const bool _compute_inverse;
 
  116            const int exponent_det_) :
 
  125            _cubature_factory(
"auto-degree:0"),
 
  126            _cubature_rule(Cubature::ctor_factory,_cubature_factory),
 
  127            _frobenius_grad_R(0),
 
  128            _frobenius_cof_grad_R(0),
 
  130            _normalized_ref_cell_vol(1),
 
  131            _exponent_det(exponent_det_),
 
  132            _compute_frobenius( (fac_frobenius_ > 
DataType(0)) ),
 
  133            _compute_cof( (fac_cof_ > 0) ),
 
  134            _compute_det( (fac_det_ > 0) ),
 
  135            _compute_inverse( _compute_det || _compute_cof)
 
  137              XASSERTM(exponent_det_ == 1 || exponent_det_ == 2,
"exponent_det must be 1 or 2!");
 
  139              "In 2d, the cofactor and frobenius norm term are redundant, so set fac_cof = 0.");
 
  144                _normalized_ref_cell_vol /= 
DataType(d+1);
 
  164            const Index pad_width(30);
 
  166              + String(
"\nexponent_det").
pad_back(pad_width, 
'.') + String(
": ") + 
stringify(_exponent_det)
 
  167              + String(
"\ncubature_rule").
pad_back(pad_width, 
'.') + String(
": ") + _cubature_rule.get_name();
 
  174            inv_grad_R = trafo_data.jac_mat*mat_tensor;
 
  177            grad_R.set_transpose(inv_grad_R);
 
  181            if(_compute_det || _compute_inverse)
 
  183              _det_grad_R = grad_R.det();
 
  190                inv_grad_R.set_inverse(grad_R);
 
  195                inv_grad_R.format(Math::nan<DataType>());
 
  199            if(_compute_frobenius)
 
  201              _frobenius_grad_R = grad_R.norm_frobenius();
 
  206              cof_grad_R.set_cofactor(grad_R);
 
  207              _frobenius_cof_grad_R = cof_grad_R.norm_frobenius();
 
  232            if(_exponent_det == 1)
 
  234              return _det_grad_R/_normalized_ref_cell_vol;
 
  238              return Math::sqr(_det_grad_R)/_normalized_ref_cell_vol;
 
  257            if(_exponent_det == 1)
 
  259              return fac/_normalized_ref_cell_vol;
 
  263              return Math::sqr(fac)/_normalized_ref_cell_vol;
 
  285            for(
int k(0); k < _cubature_rule.get_num_points(); ++k)
 
  288              trafo_eval(trafo_data, _cubature_rule.get_point(k));
 
  289              space_eval(space_data, trafo_data);
 
  291              set_point(trafo_data, mat_tensor);
 
  293              DataType weight(_cubature_rule.get_weight(k));
 
  295              if(_compute_frobenius)
 
  297                fval_frobenius += this->_fac_frobenius*weight*compute_frobenius_part();
 
  299                add_grad_frobenius(
grad, space_data, mat_tensor, this->_fac_frobenius*weight);
 
  304                fval_cof += this->_fac_cof*weight*compute_cof_part();
 
  306                add_grad_cof(
grad, space_data, mat_tensor, this->_fac_cof*weight);
 
  311                fval_det += this->_fac_det*weight*compute_det_part();
 
  312                add_grad_det(
grad, space_data, mat_tensor, this->_fac_det*weight);
 
  314                fval_rec_det += this->_fac_rec_det*weight*compute_rec_det_part();
 
  315                add_grad_rec_det(
grad, space_data, mat_tensor, this->_fac_rec_det*weight);
 
  320            fval = fval_frobenius + fval_cof + fval_det + fval_rec_det;
 
  343            for(
int k(0); k < _cubature_rule.get_num_points(); ++k)
 
  346              trafo_eval(trafo_data, _cubature_rule.get_point(k));
 
  347              space_eval(space_data, trafo_data);
 
  350              set_point(trafo_data, mat_tensor);
 
  351              DataType weight(_cubature_rule.get_weight(k));
 
  353              if(_compute_frobenius)
 
  355                fval_frobenius += weight*this->_fac_frobenius*compute_frobenius_part();
 
  360                fval_cof += weight*this->_fac_cof*compute_cof_part();
 
  365                fval_det += weight*this->_fac_det*compute_det_part();
 
  366                fval_det += weight*this->_fac_rec_det*compute_rec_det_part();
 
  371            fval = fval_frobenius + fval_cof + fval_det;
 
  380            my_fac /= _normalized_ref_cell_vol;
 
  382            for(
int i(0); i < SpaceEvalData::max_local_dofs; ++i)
 
  386                grad[i] += my_fac*(mat_tensor[d]*space_data.phi[i].ref_grad[d])*grad_R;
 
  397            my_fac /= _normalized_ref_cell_vol;
 
  399            TgradR cof_grad_R_transpose(0);
 
  400            cof_grad_R_transpose.set_transpose(cof_grad_R);
 
  402            for(
int i(0); i < SpaceEvalData::max_local_dofs; ++i)
 
  404              auto transformed_phi_ref_grad = space_data.phi[i].ref_grad*mat_tensor;
 
  408                grad[i][d] += my_fac*(
 
  410                  - 
Tiny::dot(cof_grad_R[d], cof_grad_R_transpose*(inv_grad_R*transformed_phi_ref_grad)));
 
  421            if(_exponent_det == 1)
 
  423              my_fac *= _det_grad_R/_normalized_ref_cell_vol;
 
  430            for(
int i(0); i < SpaceEvalData::max_local_dofs; ++i)
 
  434                grad[i] += my_fac*inv_grad_R*(mat_tensor[d]*space_data.phi[i].ref_grad[d]);
 
  444            DataType my_fac(-fac/_normalized_ref_cell_vol);
 
  445            if(_exponent_det == 1)
 
  454                my_fac /= this->_fac_reg;
 
  470            for(
int i(0); i < SpaceEvalData::max_local_dofs; ++i)
 
  474                grad[i] += my_fac*inv_grad_R*(mat_tensor[d]*space_data.phi[i].ref_grad[d]);
 
  494            for(
int k(0); k < _cubature_rule.get_num_points(); ++k)
 
  497              trafo_eval(trafo_data, _cubature_rule.get_point(k));
 
  498              space_eval(space_data, trafo_data);
 
  501              set_point(trafo_data, mat_tensor);
 
  503              DataType weight(_cubature_rule.get_weight(k));
 
  507                Math::sqr(_frobenius_grad_R)/_normalized_ref_cell_vol;
 
  509              det_der_h += weight*_det_grad_R/_normalized_ref_cell_vol;
 
  518                fac = this->_fac_reg;
 
  520              rec_det_der_h += weight*_det_grad_R/(fac*(_det_grad_R + fac))/_normalized_ref_cell_vol;
 
  525            frobenius_der_h *= this->_fac_frobenius*
DataType(-1)/h;
 
  526            det_der_h *= this->_fac_det*
DataType(-2)/h;
 
  527            rec_det_der_h *= this->_fac_rec_det*
DataType(2)/h;
 
  529            DataType der_h(frobenius_der_h + det_der_h + rec_det_der_h);
 
  532            for(
int i(0); i < 
Tx::m; ++i)
 
  534              for(
int d(0); d < 
Tx::n; ++d)
 
  543    extern template class RumpfFunctional<double,
 
  544    Trafo::Standard::Mapping<Geometry::ConformalMesh<Shape::Simplex<2>, 2, 
double>>>;
 
  546    extern template class RumpfFunctional<double,
 
  547    Trafo::Standard::Mapping<Geometry::ConformalMesh<Shape::Simplex<3>, 3, 
double>>>;
 
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
String info() const
Print basic information.
SpaceEvaluator::template ConfigTraits< space_config >::EvalDataType SpaceEvalData
Data from evaluating FE spaces.
void eval_fval_cellwise(DataType &fval, const TgradR &mat_tensor, const TrafoEvaluator &trafo_eval, const SpaceEvaluator &space_eval, const Tx &x, const DataType &h, DataType &fval_frobenius, DataType &fval_cof, DataType &fval_det)
Computes the different contributions to the functional's value on one cell.
TrafoType::template Evaluator< ShapeType, DataType >::Type TrafoEvaluator
Type for evaluating the transformation.
Tiny::Matrix< DataType_, shape_dim, world_dim > TgradR
Type for the gradient of the local reference mapping.
void eval_fval_grad(DataType &fval, Tx &grad, const TgradR &mat_tensor, const TrafoEvaluator &trafo_eval, const SpaceEvaluator &space_eval, const Tx &x, const DataType &h)
Computes the functional's value and gradient on one cell.
DataType_ DataType
Our data type.
static constexpr int world_dim
Our world dimension - only world_dim == shape_dim is supported.
RumpfFunctional(const DataType_ fac_frobenius_, const DataType_ fac_det_, const DataType_ fac_cof_, const DataType_ fac_reg_, const int exponent_det_)
Constructor.
Tiny::Matrix< DataType_, Shape::FaceTraits< ShapeType, 0 >::count, world_dim > Tx
Type for a pack of local vertex coordinates.
static constexpr int shape_dim
Our shape dimension.
static constexpr SpaceTags space_config
For the FE space, we only need the gradients on the reference cell.
Trafo::Standard::Mapping< Geometry::ConformalMesh< ShapeType, world_dim, DataType_ > > TrafoType
The transformation this functional works on.
Tiny::Vector< DataType_, Shape::FaceTraits< ShapeType, 0 >::count *world_dim > Tgradh
Type for the gradient of the local cell sizes.
Shape::Hypercube< shape_dim_ > ShapeType
Shape type of the underlying transformation.
TrafoSpace::template Evaluator< TrafoEvaluator >::Type SpaceEvaluator
Type for evaluating the FE functions.
void add_grad_h_part(Tx &grad, const TgradR &mat_tensor, const TrafoEvaluator &trafo_eval, const SpaceEvaluator &space_eval, const Tx &x, const DataType &h, const Tgradh &grad_h)
Adds the gradient h part to the local gradient.
RumpfFunctionalBase< DataType_ > BaseClass
Our baseclass.
static constexpr TrafoTags trafo_config
We need the Trafo to evaluate the image point, the Jacobian and its determinant.
TrafoEvaluator::template ConfigTraits< trafo_config >::EvalDataType TrafoEvalData
Data from evaluating the transformation.
Intern::TrafoFE< TrafoType >::Space TrafoSpace
The FE space associated with the transformation.
String pad_back(size_type len, char c=' ') const
Pads the back of the string up to a desired length.
static constexpr int n
the column count of the matrix
static constexpr int m
the row count of the matrix
T_ sqrt(T_ x)
Returns the square-root of a value.
bool isnormal(T_ x)
Checks whether a value is normal.
T_ pow(T_ x, T_ y)
Returns x raised to the power of y.
T_ sqr(T_ x)
Returns the square of a value.
CUDA_HOST_DEVICE T_ dot(const T_ &a, const T_ &b)
Computes the dot-product of two scalars.
String stringify(const T_ &item)
Converts an item into a String.
SpaceTags
Space configuration tags enum.
@ ref_grad
specifies whether the space should supply reference basis function gradients
@ grad
specifies whether the space should supply basis function gradients
std::uint64_t Index
Index data type.
TrafoTags
Trafo configuration tags enum.
@ img_point
specifies whether the trafo should supply image point coordinates
@ jac_mat
specifies whether the trafo should supply jacobian matrices
@ jac_det
specifies whether the trafo should supply jacobian determinants
static String name()
Returns the name of the class as a String.