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::Hypercube<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::Hypercube<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_) :
 
  127            _cubature_factory(
"newton-cotes-closed:"+
stringify(4)),
 
  129            _cubature_rule(Cubature::ctor_factory,_cubature_factory),
 
  130            _frobenius_grad_R(0),
 
  131            _frobenius_cof_grad_R(0),
 
  134            _exponent_det(exponent_det_),
 
  135            _compute_frobenius( (fac_frobenius_ > 
DataType(0)) ),
 
  136            _compute_cof( (fac_cof_ > 0) ),
 
  137            _compute_det( (fac_det_ > 0) ),
 
  138            _compute_inverse( _compute_det || _compute_cof)
 
  140              XASSERTM(exponent_det_ == 1 || exponent_det_ == 2,
"exponent_det must be 1 or 2!");
 
  142              "In 2d, the cofactor and frobenius norm term are redundant, so set fac_cof = 0.");
 
  160            const Index pad_width(30);
 
  162              + String(
"\nexponent_det").
pad_back(pad_width, 
'.') + String(
": ") + 
stringify(_exponent_det)
 
  163              + String(
"\ncubature_rule").
pad_back(pad_width, 
'.') + String(
": ") + _cubature_rule.get_name();
 
  170            inv_grad_R = trafo_data.jac_mat*mat_tensor;
 
  173            grad_R.set_transpose(inv_grad_R);
 
  177            if(_compute_det || _compute_inverse)
 
  179              _det_grad_R = grad_R.det();
 
  186                inv_grad_R.set_inverse(grad_R);
 
  191                inv_grad_R.format(Math::nan<DataType>());
 
  195            if(_compute_frobenius)
 
  197              _frobenius_grad_R = grad_R.norm_frobenius();
 
  202              cof_grad_R.set_cofactor(grad_R);
 
  203              _frobenius_cof_grad_R = cof_grad_R.norm_frobenius();
 
  228            if(_exponent_det == 1)
 
  230              return _det_grad_R/_normalized_ref_cell_vol;
 
  234              return Math::sqr(_det_grad_R)/_normalized_ref_cell_vol;
 
  253            if(_exponent_det == 1)
 
  255              return fac/_normalized_ref_cell_vol;
 
  259              return Math::sqr(fac)/_normalized_ref_cell_vol;
 
  281            for(
int k(0); k < _cubature_rule.get_num_points(); ++k)
 
  284              trafo_eval(trafo_data, _cubature_rule.get_point(k));
 
  285              space_eval(space_data, trafo_data);
 
  287              set_point(trafo_data, mat_tensor);
 
  289              DataType weight(_cubature_rule.get_weight(k));
 
  291              if(_compute_frobenius)
 
  293                fval_frobenius += this->_fac_frobenius*weight*compute_frobenius_part();
 
  295                add_grad_frobenius(
grad, space_data, mat_tensor, this->_fac_frobenius*weight);
 
  300                fval_cof += this->_fac_cof*weight*compute_cof_part();
 
  302                add_grad_cof(
grad, space_data, mat_tensor, this->_fac_cof*weight);
 
  307                fval_det += this->_fac_det*weight*compute_det_part();
 
  308                add_grad_det(
grad, space_data, mat_tensor, this->_fac_det*weight);
 
  310                fval_rec_det += this->_fac_rec_det*weight*compute_rec_det_part();
 
  311                add_grad_rec_det(
grad, space_data, mat_tensor, this->_fac_rec_det*weight);
 
  316            fval = fval_frobenius + fval_cof + fval_det + fval_rec_det;
 
  339            for(
int k(0); k < _cubature_rule.get_num_points(); ++k)
 
  342              trafo_eval(trafo_data, _cubature_rule.get_point(k));
 
  343              space_eval(space_data, trafo_data);
 
  346              set_point(trafo_data, mat_tensor);
 
  348              DataType weight(_cubature_rule.get_weight(k));
 
  350              if(_compute_frobenius)
 
  352                fval_frobenius += weight*this->_fac_frobenius*compute_frobenius_part();
 
  357                fval_cof += weight*this->_fac_cof*compute_cof_part();
 
  362                fval_det += weight*this->_fac_det*compute_det_part();
 
  363                fval_det += weight*this->_fac_rec_det*compute_rec_det_part();
 
  368            fval = fval_frobenius + fval_cof + fval_det;
 
  379            my_fac /= _normalized_ref_cell_vol;
 
  381            for(
int i(0); i < SpaceEvalData::max_local_dofs; ++i)
 
  385                grad[i] += my_fac*(mat_tensor[d]*space_data.phi[i].ref_grad[d])*grad_R;
 
  396            my_fac /= _normalized_ref_cell_vol;
 
  398            TgradR cof_grad_R_transpose(0);
 
  399            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]);
 
  442          void add_grad_rec_det(
 
  445            DataType my_fac(-fac/_normalized_ref_cell_vol);
 
  446            if(_exponent_det == 1)
 
  455                my_fac /= this->_fac_reg;
 
  471            for(
int i(0); i < SpaceEvalData::max_local_dofs; ++i)
 
  475                grad[i] += my_fac*inv_grad_R*(mat_tensor[d]*space_data.phi[i].ref_grad[d]);
 
  495            for(
int k(0); k < _cubature_rule.get_num_points(); ++k)
 
  498              trafo_eval(trafo_data, _cubature_rule.get_point(k));
 
  499              space_eval(space_data, trafo_data);
 
  502              set_point(trafo_data, mat_tensor);
 
  504              DataType weight(_cubature_rule.get_weight(k));
 
  508                Math::sqr(_frobenius_grad_R)/_normalized_ref_cell_vol;
 
  510              det_der_h += weight*_det_grad_R/_normalized_ref_cell_vol;
 
  519                fac = this->_fac_reg;
 
  522              rec_det_der_h += weight*_det_grad_R/(fac*(_det_grad_R + fac))/_normalized_ref_cell_vol;
 
  528            frobenius_der_h *= this->_fac_frobenius*
DataType(-1)/h;
 
  529            det_der_h *= this->_fac_det*
DataType(-2)/h;
 
  530            rec_det_der_h *= this->_fac_rec_det*
DataType(2)/h;
 
  532            DataType der_h(frobenius_der_h + det_der_h + rec_det_der_h);
 
  535            for(
int i(0); i < 
Tx::m; ++i)
 
  537              for(
int d(0); d < 
Tx::n; ++d)
 
  546    extern template class RumpfFunctional<double,
 
  547    Trafo::Standard::Mapping<Geometry::ConformalMesh<Shape::Hypercube<2>, 2, 
double>>>;
 
  549    extern template class RumpfFunctional<double,
 
  550    Trafo::Standard::Mapping<Geometry::ConformalMesh<Shape::Hypercube<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.