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.