9#include <kernel/assembly/slip_filter_assembler.hpp>
10#include <kernel/assembly/unit_filter_assembler.hpp>
11#include <kernel/geometry/export_vtk.hpp>
12#include <kernel/geometry/mesh_node.hpp>
13#include <kernel/lafem/filter_chain.hpp>
14#include <kernel/lafem/filter_sequence.hpp>
15#include <kernel/lafem/slip_filter.hpp>
16#include <kernel/lafem/unit_filter_blocked.hpp>
17#include <kernel/meshopt/mesh_concentration_function.hpp>
18#include <kernel/meshopt/mesh_quality_functional.hpp>
19#include <kernel/meshopt/rumpf_trafo.hpp>
20#include <kernel/util/dist.hpp>
26#include <kernel/meshopt/rumpf_functional.hpp>
27#include <kernel/meshopt/rumpf_functionals/p1.hpp>
28#include <kernel/meshopt/rumpf_functionals/q1.hpp>
55 current_concentration,
63 inline std::ostream& operator<<(std::ostream& os,
ScaleComputation scale_computation)
65 switch(scale_computation)
67 case ScaleComputation::undefined:
68 return os <<
"undefined";
69 case ScaleComputation::once_uniform:
70 return os <<
"once_uniform";
71 case ScaleComputation::once_cellsize:
72 return os <<
"once_cellsize";
73 case ScaleComputation::once_concentration:
74 return os <<
"once_concentration";
75 case ScaleComputation::current_uniform:
76 return os <<
"current_uniform";
77 case ScaleComputation::current_cellsize:
78 return os <<
"current_cellsize";
79 case ScaleComputation::current_concentration:
80 return os <<
"current_concentration";
81 case ScaleComputation::iter_concentration:
82 return os <<
"iter_concentration";
84 return os <<
"-unknown-";
88 inline void operator<<(
ScaleComputation& scale_computation,
const String& sc_name)
90 if(sc_name ==
"undefined")
91 scale_computation = ScaleComputation::undefined;
92 else if(sc_name ==
"once_uniform")
93 scale_computation = ScaleComputation::once_uniform;
94 else if(sc_name ==
"once_cellsize")
95 scale_computation = ScaleComputation::once_cellsize;
96 else if(sc_name ==
"once_concentration")
97 scale_computation = ScaleComputation::once_concentration;
98 else if(sc_name ==
"current_uniform")
99 scale_computation = ScaleComputation::current_uniform;
100 else if(sc_name ==
"current_cellsize")
101 scale_computation = ScaleComputation::current_cellsize;
102 else if(sc_name ==
"current_concentration")
103 scale_computation = ScaleComputation::current_concentration;
104 else if(sc_name ==
"iter_concentration")
105 scale_computation = ScaleComputation::iter_concentration;
107 XABORTM(
"Unknown ScaleComputation identifier string " +sc_name);
170 typename CellFunctionalType_,
171 typename RefCellTrafo_ = RumpfTrafo<Trafo_, typename Trafo_::MeshType::CoordType>
221 typedef typename Intern::TrafoFE<TrafoType>::Space
SpaceType;
233 static_assert(std::is_same<ShapeType, typename CellFunctionalType::ShapeType>::value,
234 "ShapeTypes of the transformation / cell functional have to agree" );
249 std::map<String, std::shared_ptr<Assembly::UnitFilterAssembler<MeshType>>>
_dirichlet_asm;
251 std::map<String, std::shared_ptr<Assembly::SlipFilterAssembler<TrafoType>>>
_slip_asm;
253 std::shared_ptr<MeshConcentrationFunctionBase<Trafo_, RefCellTrafo_>>
_mesh_conc;
310 const std::deque<String>& dirichlet_list,
311 const std::deque<String>& slip_list,
312 std::shared_ptr<CellFunctionalType_> cell_functional_)
335 XASSERTM(cell_functional_ !=
nullptr,
"cell functional must not be nullptr");
339 for(
auto& it : dirichlet_list)
342 auto new_asm = std::make_shared<Assembly::UnitFilterAssembler<MeshType>>();
349 new_asm->add_mesh_part(*mpp);
359 for(
auto& it : slip_list)
362 auto new_asm = std::make_shared<Assembly::SlipFilterAssembler<TrafoType>>(this->
_trafo);
369 new_asm->add_mesh_part(*mpp);
420 const std::deque<String>& dirichlet_list,
421 const std::deque<String>& slip_list,
422 std::shared_ptr<CellFunctionalType_> cell_functional_,
448 XASSERTM(cell_functional_ !=
nullptr,
"cell functional must not be nullptr!\n");
453 for(
auto& it : dirichlet_list)
456 auto new_asm = std::make_shared<Assembly::UnitFilterAssembler<MeshType>>();
463 new_asm->add_mesh_part(*mpp);
473 for(
auto& it : slip_list)
476 auto new_asm = std::make_shared<Assembly::SlipFilterAssembler<TrafoType>>(this->
_trafo);
483 new_asm->add_mesh_part(*mpp);
497 if(mesh_conc_ !=
nullptr)
499 _mesh_conc = mesh_conc_->create_empty_clone();
571 return "HyperelasticityFunctional<"+MeshType::name()+
">";
579 const Index pad_width(30);
623 if(this->_penalty_param >
DataType(0))
627 this->_mesh_conc->compute_constraint(constraint_at_cell);
630 delete[] constraint_at_cell;
636 delete [] fval_rec_det;
661 "Excessively large penalty parameter.");
715 if((this->_scale_computation == ScaleComputation::current_concentration) ||
716 (this->_scale_computation == ScaleComputation::iter_concentration) ||
798 auto& dirichlet_filters = filter.template at<1>();
800 for(
auto& it : dirichlet_filters)
805 XABORTM(
"Could not find unit filter assembler for filter with key "+it.first);
807 assembler->second->assemble(it.second,
trafo_space, vec_state);
811 auto& slip_filters = filter.template at<0>();
812 for(
const auto& it:slip_filters)
818 for(
auto& it : slip_filters)
820 const auto& assembler =
_slip_asm.find(it.first);
824 XABORTM(
"Could not find slip filter assembler for filter with key "+it.first);
827 assembler->second->assemble(it.second,
trafo_space);
830 if( (this->_scale_computation == ScaleComputation::iter_concentration) ||
874 if(this->_scale_computation == ScaleComputation::iter_concentration)
950 vol_min = Math::huge<CoordType>();
953 for(
Index cell(0); cell < this->
get_mesh()->get_num_entities(ShapeType::dimension); ++cell)
955 CoordType my_vol = this->_trafo.template compute_vol<ShapeType, CoordType>(cell);
993 lambda_min = Math::huge<CoordType>();
996 for(
Index cell(0); cell < this->
get_mesh()->get_num_entities(ShapeType::dimension); ++cell)
998 size_defect +=
Math::abs(this->_trafo.template
999 compute_vol<ShapeType, CoordType>(cell)/vol - this->_lambda(cell));
1030 typedef typename TrafoType::template Evaluator<ShapeType, DataType>::Type TrafoEvaluator;
1031 typedef typename SpaceType::template Evaluator<TrafoEvaluator>::Type SpaceEvaluator;
1038 Index ncells(this->
get_mesh()->get_num_entities(ShapeType::dimension));
1041 auto& idx = this->
get_mesh()->template get_index_set<ShapeType::dimension,0>();
1044 FEAT::Tiny::Matrix <CoordType, Shape::FaceTraits<ShapeType,0>::count, MeshType::world_dim> x;
1052 TrafoEvaluator trafo_eval(this->_trafo);
1053 SpaceEvaluator space_eval(this->trafo_space);
1056 for(
Index cell(0); cell < ncells; ++cell)
1059 trafo_eval.prepare(cell);
1060 space_eval.prepare(trafo_eval);
1063 for(
int j(0); j < Shape::FaceTraits<ShapeType,0>::count; ++j)
1068 auto mat_tensor = RefCellTrafo_::compute_mat_tensor(x, this->
_h(cell));
1070 this->_cell_functional->eval_fval_grad(
1071 fval_loc, grad_loc, mat_tensor, trafo_eval, space_eval, x, this->
_h(cell));
1074 if(this->_mesh_conc !=
nullptr && this->_mesh_conc->use_derivative())
1076 const auto& grad_h = this->_mesh_conc->get_grad_h();
1077 this->_cell_functional->add_grad_h_part(
1078 grad_loc, mat_tensor, trafo_eval, space_eval, x, this->
_h(cell), grad_h(cell));
1081 fval += this->
_mu(cell)*fval_loc;
1083 for(
int j(0); j < Shape::FaceTraits<ShapeType,0>::count; ++j)
1085 Index i(idx(cell,j));
1087 tmp += this->
_mu(cell)*grad_loc[j];
1093 if(this->_penalty_param >
DataType(0))
1095 XASSERTM(this->_mesh_conc !=
nullptr,
1096 "You need a mesh concentration function for imposing a mesh alignment constraint!");
1098 if(add_penalty_fval)
1101 fval += this->_penalty_param*
DataType(0.5)*
Math::sqr(this->_alignment_constraint);
1105 this->_mesh_conc->add_constraint_grad(
grad, this->_alignment_constraint, this->_penalty_param);
1129 typedef typename TrafoType::template Evaluator<ShapeType, DataType>::Type TrafoEvaluator;
1130 typedef typename SpaceType::template Evaluator<TrafoEvaluator>::Type SpaceEvaluator;
1133 Index ncells(this->
get_mesh()->get_num_entities(ShapeType::dimension));
1136 auto& idx = this->
get_mesh()->template get_index_set<ShapeType::dimension,0>();
1139 FEAT::Tiny::Matrix <CoordType, Shape::FaceTraits<ShapeType,0>::count, MeshType::world_dim> x;
1147 TrafoEvaluator trafo_eval(this->_trafo);
1148 SpaceEvaluator space_eval(this->trafo_space);
1151 for(
Index cell(0); cell < ncells; ++cell)
1154 trafo_eval.prepare(cell);
1155 space_eval.prepare(trafo_eval);
1159 for(
int j(0); j < Shape::FaceTraits<ShapeType,0>::count; ++j)
1164 auto mat_tensor = RefCellTrafo_::compute_mat_tensor(x, this->
_h(cell));
1166 this->_cell_functional->eval_fval_cellwise(fval_loc, mat_tensor, trafo_eval, space_eval, x, h,
1167 fval_norm[cell], fval_cof[cell], fval_det[cell]);
1169 fval += this->
_mu(cell)*fval_loc;
1178 Index ncells(this->
get_mesh()->get_num_entities(ShapeType::dimension));
1181 for(
Index cell(0); cell < ncells; ++cell)
1183 _lambda(cell, this->_trafo.template compute_vol<ShapeType, CoordType>(cell));
1187 this->sync_scalars.emplace(
"_sum_lambda",&
_sum_lambda);
1197 this->sync_scalars.emplace(
"_sum_lambda",&
_sum_lambda);
1204 this->sync_scalars.emplace(
"_sum_conc",&(
_mesh_conc->get_sum_conc()));
1213 for(
Index cell(0); cell < this->
get_mesh()->get_num_entities(ShapeType::dimension); ++cell)
1217 this->sync_scalars.emplace(
"_sum_lambda",&
_sum_lambda);
1229 case ScaleComputation::once_uniform:
1230 case ScaleComputation::once_cellsize:
1231 case ScaleComputation::once_concentration:
1233 case ScaleComputation::current_uniform:
1236 case ScaleComputation::current_cellsize:
1239 case ScaleComputation::current_concentration:
1240 case ScaleComputation::iter_concentration:
1248 this->sync_scalars.emplace(
"_sum_det",&
_sum_det);
1261 case ScaleComputation::iter_concentration:
1269 this->sync_scalars.emplace(
"_sum_det",&
_sum_det);
1281 case ScaleComputation::once_uniform:
1284 case ScaleComputation::once_cellsize:
1287 case ScaleComputation::once_concentration:
1295 this->sync_scalars.emplace(
"_sum_det",&
_sum_det);
1303 extern template class HyperelasticityFunctional
1314 extern template class HyperelasticityFunctional
1325 extern template class HyperelasticityFunctional
1336 extern template class HyperelasticityFunctional
#define XABORTM(msg)
Abortion macro definition with custom message.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
VTK exporter class template.
void add_vertex_vector(const String &name, const T_ *x, const T_ *y=nullptr, const T_ *z=nullptr, double scaling_factor=1.0)
Adds a vector-field vertex variable to the exporter.
void add_cell_vector(const String &name, const T_ *x, const T_ *y=nullptr, const T_ *z=nullptr, double scaling_factor=1.0)
Adds a vector-field cell variable to the exporter.
void add_cell_scalar(const String &name, const T_ *data, double scaling_factor=1.0)
Adds a scalar cell variable to the exporter.
void add_vertex_scalar(const String &name, const T_ *data, double scaling_factor=1.0)
Adds a scalar vertex variable to the exporter.
bool adapt_by_name(const String &part_name, bool recursive=false)
Adapts this mesh node.
MeshPartType * find_mesh_part(const String &part_name)
Searches this container for a MeshPart.
Root mesh node class template.
Index size() const
Returns the containers size.
void format(DT_ value=DT_(0))
Reset all elements of the container to a given value or zero if missing.
Blocked Dense data vector class template.
void copy(const DenseVectorBlocked &x, bool full=false)
Performs .
Dense data vector class template.
void scale(const DenseVector &x, const DT_ alpha)
Calculate .
DT_ * elements()
Get a pointer to the data array.
void copy(const VT_ &a)
Performs .
Filter Chainclass template.
Sequence of filters of the same type.
Slip Filter class template.
Unit Filter Blocked class template.
Baseclass for a family of variational mesh optimization algorithms.
LAFEM::DenseVectorBlocked< CoordType, IndexType, MeshType::world_dim > VectorType
Vector type for coordinate vectors etc.
DataType _sum_mu
The sum of all mu (= cell weights) over all cells before normalization.
std::shared_ptr< MeshConcentrationFunctionBase< Trafo_, RefCellTrafo_ > > _mesh_conc
The mesh concentration function (if any)
virtual void init() override
Performs intializations that cannot be done in the constructor.
ScalarVectorType _h
Size parameters for the local reference element.
static constexpr int BlockWidth
Block Weight of the operator's gradient.
DataType _sum_lambda
The sum of all lambda (= optimal cell size) over all cells before normalization.
DataType get_constraint()
Gets the last computed (alignment) constraint.
DataType _alignment_constraint
Last computed contraint (violation)
virtual void _compute_lambda_uniform()
Computes the uniformly distributed weights _lambda.
virtual void _compute_lambda_cellsize()
Computes the weights _lambda according to the current mesh.
virtual void add_to_vtk_exporter(Geometry::ExportVTK< typename Trafo_::MeshType > &exporter) const override
Adds relevant quantities of this object to a VTK exporter.
virtual void init_pre_sync()
Performs initializations that cannot be done in the constructor, pre synchronization phase.
bool empty() const
Checks if the functional is empty (= the null functional)
static constexpr int BlockHeight
Block height of the operator's gradient.
std::map< String, std::shared_ptr< Assembly::UnitFilterAssembler< MeshType > > > _dirichlet_asm
Assembler for Dirichlet boundary conditions.
std::map< String, std::shared_ptr< Assembly::SlipFilterAssembler< TrafoType > > > _slip_asm
Assembler for slip boundary conditions.
std::map< String, DataType * > sync_scalars
These are the scalars that need to be synchronized in init() or prepare()
CoordType DataType
We always use the precision of the mesh.
DataType get_penalty_param() const
Gets the penalty parameter.
VectorTypeL create_vector_l() const
Creates an L-vector for the functional's gradient.
LAFEM::DenseVectorBlocked< DT_, IT_, MeshType::world_dim > VectorTypeR
Input vector type of the operator.
MeshQualityFunctional< MeshType > BaseClass
Our base class.
VectorTypeR create_vector_r() const
Creates an R-vector for the functional and its gradient.
TrafoType::MeshType MeshType
The mesh the transformation is defined on.
virtual void eval_fval_cellwise(CoordType &fval, CoordType *fval_norm, CoordType *fval_cof, CoordType *fval_det) const
Computes the functional value parts on every cell.
LAFEM::SlipFilter< DT_, IT_, MeshType::world_dim > SlipFilterType
Filter for slip boundary conditions.
const Index _rows
This is the number of DoFs in the test space (= number of mesh vertices)
virtual void _compute_scales_init()
Recomputes the optimal scales, every call to the solver.
TrafoType & _trafo
The transformation defining the physical mesh.
HyperelasticityFunctional()=delete
Explicitly delete default constructor.
virtual String info() const
Prints some characteristics of the HyperelasticityFunctional object.
MeshType::CoordType CoordType
The precision of the mesh coordinates.
ScalarVectorType _lambda
Weights for local mesh size.
LAFEM::UnitFilterBlocked< DT_, IT_, MeshType::world_dim > DirichletFilterType
Filter for Dirichlet boundary conditions.
virtual void _compute_scales_iter()
Recomputes the optimal scales, every iteration.
LAFEM::FilterSequence< DirichletFilterType > DirichletFilterSequence
Sequence of Dirichlet filters for several different boundary parts.
HyperelasticityFunctional(Geometry::RootMeshNode< MeshType > *rmn_, TrafoType &trafo, const std::deque< String > &dirichlet_list, const std::deque< String > &slip_list, std::shared_ptr< CellFunctionalType_ > cell_functional_)
Constructor.
void compute_cell_size_defect_pre_sync(CoordType &vol_min, CoordType &vol_max, CoordType &vol) const
Computes a quality indicator concerning the cell sizes, pre synchronization phase.
DataType _penalty_param
Factor for the alignment penalty term.
CellFunctionalType_ CellFunctionalType
Type for the cell functional.
virtual void _compute_scales_once()
Computes the scales, just once.
virtual void eval_fval_grad(CoordType &fval, VectorTypeL &grad, const bool &add_penalty_fval=true)
Evaluates the functional's value and gradient at the current state.
static String name()
The class name.
SpaceType trafo_space
The FE space for the transformation, needed for filtering.
virtual void prepare(const VectorTypeR &vec_state, FilterType &filter)
Prepares the functional for evaluation.
LAFEM::FilterChain< SlipFilterSequence, DirichletFilterSequence > FilterType
Combined filter.
VectorTypeR GradientType
Type of the gradient vector.
virtual CoordType compute_cell_size_defect_post_sync(CoordType &lambda_min, CoordType &lambda_max, CoordType &vol_min, CoordType &vol_max, const CoordType &vol) const
Computes a quality indicator concerning the cell sizes, pre synchronization phase.
LAFEM::DenseVector< CoordType, IndexType > ScalarVectorType
Vector type for element sizes etc.
Trafo_ TrafoType
Type for the transformation.
Index rows() const
Returns the number of rows.
const Index _columns
This is the number of DoFs in the trial space (= number of mesh vertices)
virtual void _compute_lambda_conc()
Computes _lambda according to the concentration function given by _mesh_conc.
MeshType::ShapeType ShapeType
ShapeType of said mesh.
HyperelasticityFunctional(Geometry::RootMeshNode< MeshType > *rmn_, TrafoType &trafo, const std::deque< String > &dirichlet_list, const std::deque< String > &slip_list, std::shared_ptr< CellFunctionalType_ > cell_functional_, ScaleComputation scale_computation_, std::shared_ptr< MeshConcentrationFunctionBase< Trafo_, RefCellTrafo_ > > mesh_conc_=nullptr, DataType penalty_param_=DataType(0))
Constructor.
virtual CoordType compute_cell_size_defect(CoordType &lambda_min, CoordType &lambda_max, CoordType &vol_min, CoordType &vol_max, CoordType &vol) const override
Computes a quality indicator concerning the cell sizes.
virtual void prepare_post_sync(const VectorTypeR &vec_state, FilterType &filter)
Prepares the functional for evaluation, post synchronization phase.
ScalarVectorType _mu
Weights for the local contributions to the global functional value.
ScaleComputation _scale_computation
How to compute the optimal scales.
Index columns() const
Returns the number of columns.
RefCellTrafo_ RefCellTrafo
Type of the reference cell trafo for the mesh quality.
std::shared_ptr< CellFunctionalType > _cell_functional
Since the cell functional contains a ShapeType, these have to be the same.
void set_penalty_param(const DataType penalty_param_)
Sets the penalty parameter.
Intern::TrafoFE< TrafoType >::Space SpaceType
Finite Element space for the transformation.
BaseClass::CoordsBufferType CoordsBufferType
Type for exchanging information between state variable and mesh.
virtual void init_post_sync()
Performs initializations that cannot be done in the constructor, post synchronization phase.
LAFEM::DenseVectorBlocked< DT_, IT_, MeshType::world_dim > VectorTypeL
Output vector type of the operator.
HyperelasticityFunctional(const HyperelasticityFunctional &)=delete
Explicitly delete copy constructor.
virtual ~HyperelasticityFunctional()
Destructor.
LAFEM::FilterSequence< SlipFilterType > SlipFilterSequence
Sequence of Slip filters for several different boundary parts.
virtual void prepare_pre_sync(const VectorTypeR &vec_state, FilterType &filter)
Prepares the functional for evaluation, pre synchronization phase.
Index IndexType
We always use Index for now.
std::set< VectorTypeR * > sync_vecs
These are the vectors that need to be synchronized (type-0 to type-1)
Base class for mesh concentration functions.
Baseclass for mesh optimization algorithms.
virtual void mesh_to_buffer()
Gets the coordinates from the underlying mesh and saves them in _coords_buffer.
Geometry::RootMeshNode< MeshType > * _mesh_node
The mesh for the underlying transformation.
Index _num_func_evals
Counter for number of function evaluations.
Index _num_grad_evals
Counter for number of gradient evaluations.
virtual void buffer_to_mesh()
Sets the coordinates in the underlying mesh to _coords_buffer.
CoordsBufferType _coords_buffer
Coordinates, used for setting new boundary values etc.
Functionals for measuring and optimising mesh quality.
String class implementation.
String pad_back(size_type len, char c=' ') const
Pads the back of the string up to a desired length.
Tiny Matrix class template.
Tiny Vector class template.
Standard transformation mapping class template.
T_ abs(T_ x)
Returns the absolute value.
T_ pow(T_ x, T_ y)
Returns x raised to the power of y.
T_ sqr(T_ x)
Returns the square of a value.
T_ min(T_ a, T_ b)
Returns the minimum of two values.
T_ max(T_ a, T_ b)
Returns the maximum of two values.
ScaleComputation
Enum class for different types of scale computations.
String stringify(const T_ &item)
Converts an item into a String.
String stringify_fp_sci(DataType_ value, int precision=0, int width=0, bool sign=false)
Prints a floating point value to a string in scientific notation.
@ grad
specifies whether the space should supply basis function gradients
std::uint64_t Index
Index data type.