FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
hyperelasticity_functional.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
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>
21
22#include <map>
23
24// This is for the explicit template instantiation below
25#ifdef FEAT_EICKT
26#include <kernel/meshopt/rumpf_functional.hpp>
27#include <kernel/meshopt/rumpf_functionals/p1.hpp>
28#include <kernel/meshopt/rumpf_functionals/q1.hpp>
29#endif
30
31
32namespace FEAT
33{
34 namespace Meshopt
35 {
36
48 {
49 undefined = 0,
50 once_uniform,
51 once_cellsize,
52 once_concentration,
53 current_uniform,
54 current_cellsize,
55 current_concentration,
56 iter_concentration
57 };
58
60
63 inline std::ostream& operator<<(std::ostream& os, ScaleComputation scale_computation)
64 {
65 switch(scale_computation)
66 {
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";
83 default:
84 return os << "-unknown-";
85 }
86 }
87
88 inline void operator<<(ScaleComputation& scale_computation, const String& sc_name)
89 {
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;
106 else
107 XABORTM("Unknown ScaleComputation identifier string " +sc_name);
108 }
110
165 template
166 <
167 typename DT_,
168 typename IT_,
169 typename Trafo_,
170 typename CellFunctionalType_,
171 typename RefCellTrafo_ = RumpfTrafo<Trafo_, typename Trafo_::MeshType::CoordType>
172 >
174 public MeshQualityFunctional<typename Trafo_::MeshType>
175 {
176 public :
178 typedef Trafo_ TrafoType;
180 typedef typename TrafoType::MeshType MeshType;
182 typedef typename MeshType::CoordType CoordType;
184 typedef CellFunctionalType_ CellFunctionalType;
185
187 typedef RefCellTrafo_ RefCellTrafo;
188
193
196
198 static constexpr int BlockHeight = MeshType::world_dim;
200 static constexpr int BlockWidth = MeshType::world_dim;
201
203 typedef typename MeshType::ShapeType ShapeType;
204
219
221 typedef typename Intern::TrafoFE<TrafoType>::Space SpaceType;
222
231
233 static_assert(std::is_same<ShapeType, typename CellFunctionalType::ShapeType>::value,
234 "ShapeTypes of the transformation / cell functional have to agree" );
235
236 protected:
238 std::shared_ptr<CellFunctionalType> _cell_functional;
244 // In the optimal case, every cell in the mesh has the size lambda(cell)
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;
254
255 public:
259 std::map<String, DataType*> sync_scalars;
261 std::set<VectorTypeR*> sync_vecs;
262
263 private:
270
275
283
284 public:
309 TrafoType& trafo,
310 const std::deque<String>& dirichlet_list,
311 const std::deque<String>& slip_list,
312 std::shared_ptr<CellFunctionalType_> cell_functional_)
313 : BaseClass(rmn_),
314 _cell_functional(cell_functional_),
315 _trafo(trafo),
316 _mu(rmn_->get_mesh()->get_num_entities(ShapeType::dimension), DataType(1)),
317 _lambda(rmn_->get_mesh()->get_num_entities(ShapeType::dimension)),
318 _h(rmn_->get_mesh()->get_num_entities(ShapeType::dimension)),
320 _slip_asm(),
321 _mesh_conc(nullptr),
322 trafo_space(trafo),
323 sync_scalars(),
324 sync_vecs(),
325 _columns(trafo_space.get_num_dofs()),
326 _rows(trafo_space.get_num_dofs()),
330 _sum_det(0),
331 _sum_lambda(0),
332 _sum_mu(0)
333 {
334
335 XASSERTM(cell_functional_ != nullptr, "cell functional must not be nullptr");
336
337 // For every MeshPart specified in the list of Dirichlet boundaries, create a UnitFilterAssembler and
338 // insert it into the std::map
339 for(auto& it : dirichlet_list)
340 {
341 // Create empty assembler
342 auto new_asm = std::make_shared<Assembly::UnitFilterAssembler<MeshType>>();
343
344 // Add the MeshPart to the assembler if it is there. There are legitimate reasons for it NOT to be
345 // there, i.e. we are in parallel and our patch is not adjacent to that MeshPart
346 auto* mpp = rmn_->find_mesh_part(it);
347 if(mpp != nullptr)
348 {
349 new_asm->add_mesh_part(*mpp);
350 }
351
352 // Insert into the map
353 String identifier(it);
354 _dirichlet_asm.emplace(identifier, new_asm);
355 }
356
357 // For every MeshPart specified in the list of slip boundaries, create a SlipFilterAssembler and
358 // insert it into the std::map
359 for(auto& it : slip_list)
360 {
361 // Create empty assembler
362 auto new_asm = std::make_shared<Assembly::SlipFilterAssembler<TrafoType>>(this->_trafo);
363
364 // Add the MeshPart to the assembler if it is there. There are legitimate reasons for it NOT to be
365 // there, i.e. we are in parallel and our patch is not adjacent to that MeshPart
366 auto* mpp = rmn_->find_mesh_part(it);
367 if(mpp != nullptr)
368 {
369 new_asm->add_mesh_part(*mpp);
370 }
371
372 // Insert into the map
373 String identifier(it);
374 _slip_asm.emplace(identifier, new_asm);
375 }
376
377 for(Index i(0); i < _mu.size(); ++i)
378 {
379 _sum_mu += _mu(i);
380 }
381
382 sync_scalars.emplace("_sum_mu",&_sum_mu);
383
384 // Compute desired element size distribution
386 }
387
419 TrafoType& trafo,
420 const std::deque<String>& dirichlet_list,
421 const std::deque<String>& slip_list,
422 std::shared_ptr<CellFunctionalType_> cell_functional_,
423 ScaleComputation scale_computation_,
424 std::shared_ptr<MeshConcentrationFunctionBase<Trafo_, RefCellTrafo_>> mesh_conc_ = nullptr,
425 DataType penalty_param_ = DataType(0))
426 : BaseClass(rmn_),
427 _cell_functional(cell_functional_),
428 _trafo(trafo),
429 _mu(rmn_->get_mesh()->get_num_entities(ShapeType::dimension), DataType(1)),
430 _lambda(rmn_->get_mesh()->get_num_entities(ShapeType::dimension)),
431 _h(rmn_->get_mesh()->get_num_entities(ShapeType::dimension)),
433 _slip_asm(),
434 _mesh_conc(mesh_conc_),
435 trafo_space(trafo),
436 sync_scalars(),
437 sync_vecs(),
438 _columns(trafo_space.get_num_dofs()),
439 _rows(trafo_space.get_num_dofs()),
440 _scale_computation(scale_computation_),
441 _penalty_param(penalty_param_),
443 _sum_det(0),
444 _sum_lambda(0),
445 _sum_mu(0)
446 {
447
448 XASSERTM(cell_functional_ != nullptr, "cell functional must not be nullptr!\n");
449 XASSERTM(_penalty_param >= DataType(0), "penalty_param must be >= 0!\n");
450
451 // For every MeshPart specified in the list of Dirichlet boundaries, create a UnitFilterAssembler and
452 // insert it into the std::map
453 for(auto& it : dirichlet_list)
454 {
455 // Create empty assembler
456 auto new_asm = std::make_shared<Assembly::UnitFilterAssembler<MeshType>>();
457
458 // Add the MeshPart to the assembler if it is there. There are legitimate reasons for it NOT to be
459 // there, i.e. we are in parallel and our patch is not adjacent to that MeshPart
460 auto* mpp = rmn_->find_mesh_part(it);
461 if(mpp != nullptr)
462 {
463 new_asm->add_mesh_part(*mpp);
464 }
465
466 // Insert into the map
467 String identifier(it);
468 _dirichlet_asm.emplace(identifier, new_asm);
469 }
470
471 // For every MeshPart specified in the list of slip boundaries, create a SlipFilterAssembler and
472 // insert it into the std::map
473 for(auto& it : slip_list)
474 {
475 // Create empty assembler
476 auto new_asm = std::make_shared<Assembly::SlipFilterAssembler<TrafoType>>(this->_trafo);
477
478 // Add the MeshPart to the assembler if it is there. There are legitimate reasons for it NOT to be
479 // there, i.e. we are in parallel and our patch is not adjacent to that MeshPart
480 auto* mpp = rmn_->find_mesh_part(it);
481 if(mpp != nullptr)
482 {
483 new_asm->add_mesh_part(*mpp);
484 }
485
486 // Insert into the map
487 String identifier(it);
488 _slip_asm.emplace(identifier, new_asm);
489 }
490
491 for(Index i(0); i < _mu.size(); ++i)
492 {
493 _sum_mu += _mu(i);
494 }
495 sync_scalars.emplace("_sum_mu",&_sum_mu);
496
497 if(mesh_conc_ != nullptr)
498 {
499 _mesh_conc = mesh_conc_->create_empty_clone();
500 _mesh_conc->set_mesh_node(rmn_);
501 _mesh_conc->add_sync_vecs(sync_vecs);
502 }
503
504 // Perform one time scal computation
506 }
507
512
515 {
516 }
517
523 bool empty() const
524 {
525 return (trafo_space.get_num_dofs() == Index(0));
526 }
527
532 {
533 return VectorTypeL(trafo_space.get_num_dofs());
534 }
535
540 {
541 return VectorTypeR(trafo_space.get_num_dofs());
542 }
543
550 {
551 return _columns;
552 }
553
559 Index rows() const
560 {
561 return _rows;
562 }
563
569 static String name()
570 {
571 return "HyperelasticityFunctional<"+MeshType::name()+">";
572 }
573
577 virtual String info() const
578 {
579 const Index pad_width(30);
580
581 String msg = name() + String("\nScale computation").pad_back(pad_width, '.')
582 + String(": ") + stringify(_scale_computation) + "\n";
583
584 msg += _cell_functional->info() + "\n";
585 if(_mesh_conc != nullptr)
586 {
587 msg += _mesh_conc->info() + "\n";
588 }
589
590 return msg;
591 }
592
605 {
606 exporter.add_cell_scalar("h", this->_h.elements());
607 exporter.add_cell_scalar("lambda", this->_lambda.elements());
608 exporter.add_cell_scalar("mu", this->_mu.elements());
609
610 DataType* fval_norm(new DataType[this->get_mesh()->get_num_entities(MeshType::shape_dim)]);
611 DataType* fval_det(new DataType[this->get_mesh()->get_num_entities(MeshType::shape_dim)]);
612 DataType* fval_rec_det(new DataType[this->get_mesh()->get_num_entities(MeshType::shape_dim)]);
613
614 DataType fval(0);
615 eval_fval_cellwise(fval, fval_norm, fval_det, fval_rec_det);
616 exporter.add_cell_vector("fval", fval_norm, fval_det, fval_rec_det);
617
618 if(_mesh_conc != nullptr)
619 {
620 exporter.add_vertex_scalar("dist", _mesh_conc->get_dist().elements());
621 exporter.add_vertex_vector("grad_dist", _mesh_conc->get_grad_dist());
622
623 if(this->_penalty_param > DataType(0))
624 {
625 DataType* constraint_at_cell = new DataType[this->get_mesh()->get_num_entities(MeshType::shape_dim)];
626
627 this->_mesh_conc->compute_constraint(constraint_at_cell);
628 exporter.add_cell_scalar("alignment_constraint", constraint_at_cell);
629
630 delete[] constraint_at_cell;
631 }
632 }
633
634 delete [] fval_norm;
635 delete [] fval_det;
636 delete [] fval_rec_det;
637
638 }
639
646 {
647 return _penalty_param;
648 }
649
657 void set_penalty_param(const DataType penalty_param_)
658 {
659 XASSERTM(penalty_param_ >= DataType(0),"Penalty parameter must be >= 0!");
660 XASSERTM(penalty_param_ <= Math::pow(Math::huge<DataType>(), DataType(0.25)),
661 "Excessively large penalty parameter.");
662
663 _penalty_param = penalty_param_;
664 }
665
674 {
676 }
677
678 //void set_mu(std::vector<CoordType>& cells, const CoordType& weight)
679 //{
680 // for(Index i(0); i < cells.size(); ++i)
681 // {
682 // _mu(cells(i), weight);
683 // }
684
685 // _sum_mu = CoordType(0);
686 // for(Index i(0); i < _mu.size(); ++i)
687 // {
688 // _sum_mu += _mu(i);
689 // }
690 //}
691
698 virtual void init() override
699 {
702 }
703
709 virtual void init_pre_sync()
710 {
711 // Write any potential changes to the mesh
712 this->buffer_to_mesh();
713
714 // Compute distances if necessary
715 if((this->_scale_computation == ScaleComputation::current_concentration) ||
716 (this->_scale_computation == ScaleComputation::iter_concentration) ||
717 (_penalty_param > DataType(0)) )
718 {
719 if(_mesh_conc == nullptr)
720 XABORTM("Scale computation set to "+stringify(_scale_computation)+"and alignment penalty factor to "+
721 stringify_fp_sci(_penalty_param)+", but no concentration function was given");
722
723 _mesh_conc->compute_dist();
724 }
725
726 // Compute desired element size distribution
727 this->_compute_scales_init();
728 }
729
735 virtual void init_post_sync()
736 {
737 // Scale mu so that || mu ||_1 = 1
738 // For this, _sum_mu needs to have been summed up over all patches in the synchronization phase.
739 if(_sum_mu != DataType(1))
740 {
742 _sum_mu = DataType(1);
743 }
744
745 // Scale lambda so that || lambda ||_1 = 1
746 // For this, _sum_lambda needs to have been summed up over all patches in the synchronization phase.
747 if(_sum_lambda != DataType(1))
748 {
751 }
752
753 // Compute the new optimal scales. For this, lambda needs to be scaled correctly and _sum_det needs to be
754 // summed up over all patches in the synchronization phase.
755 RefCellTrafo_::compute_h(_h, _lambda, _sum_det);
756 }
757
770 virtual void prepare(const VectorTypeR& vec_state, FilterType& filter)
771 {
772 prepare_pre_sync(vec_state, filter);
773 prepare_post_sync(vec_state, filter);
774 }
775
788 virtual void prepare_pre_sync(const VectorTypeR& vec_state, FilterType& filter)
789 {
790 // Download state if necessary
791 //CoordsBufferType vec_buf;
792 //vec_buf.convert(vec_state);
793
794 // Copy to buffer and mesh
795 this->_coords_buffer.copy(vec_state);
796 this->buffer_to_mesh();
797
798 auto& dirichlet_filters = filter.template at<1>();
799
800 for(auto& it : dirichlet_filters)
801 {
802 const auto& assembler = _dirichlet_asm.find(it.first);
803
804 if(assembler == _dirichlet_asm.end())
805 XABORTM("Could not find unit filter assembler for filter with key "+it.first);
806
807 assembler->second->assemble(it.second, trafo_space, vec_state);
808 }
809
810 // The slip filter contains the outer unit normal, so reassemble it
811 auto& slip_filters = filter.template at<0>();
812 for(const auto& it:slip_filters)
813 this->_mesh_node->adapt_by_name(it.first);
814
815 // Copy back to the buffer as adaption might have changed the mesh
816 this->mesh_to_buffer();
817
818 for(auto& it : slip_filters)
819 {
820 const auto& assembler = _slip_asm.find(it.first);
821
822 if(assembler == _slip_asm.end())
823 {
824 XABORTM("Could not find slip filter assembler for filter with key "+it.first);
825 }
826
827 assembler->second->assemble(it.second, trafo_space);
828 }
829
830 if( (this->_scale_computation == ScaleComputation::iter_concentration) ||
832 {
833 if(_mesh_conc == nullptr)
834 {
835 XABORTM("Scale computation set to "+stringify(_scale_computation)+"and alignment penalty factor to "+
836 stringify_fp_sci(_penalty_param)+", but no concentration function was given");
837 }
838
839 _mesh_conc->compute_dist();
840 }
841
843
844 if(_penalty_param > DataType(0))
845 {
846 _alignment_constraint = this->_mesh_conc->compute_constraint();
847 this->sync_scalars.emplace("_alignment_constraint",&_alignment_constraint);
848 }
849
850 }
851
864 virtual void prepare_post_sync(const VectorTypeR& DOXY(vec_state), FilterType& DOXY(filter))
865 {
866 if(_sum_lambda != DataType(1))
867 {
870 }
871
872 RefCellTrafo_::compute_h(_h, _lambda, _sum_det);
873
874 if(this->_scale_computation == ScaleComputation::iter_concentration)
875 {
876 _mesh_conc->compute_grad_h(this->_sum_det);
877 }
878 }
879
916 virtual CoordType compute_cell_size_defect(CoordType& lambda_min, CoordType& lambda_max, CoordType& vol_min,
917 CoordType& vol_max, CoordType& vol) const override
918 {
919
920 compute_cell_size_defect_pre_sync(vol_min, vol_max, vol);
921 return compute_cell_size_defect_post_sync(lambda_min, lambda_max, vol_min, vol_max, vol);
922
923 }
924
947 {
948 vol = CoordType(0);
949
950 vol_min = Math::huge<CoordType>();
951 vol_max = CoordType(0);
952
953 for(Index cell(0); cell < this->get_mesh()->get_num_entities(ShapeType::dimension); ++cell)
954 {
955 CoordType my_vol = this->_trafo.template compute_vol<ShapeType, CoordType>(cell);
956 vol_min = Math::min(vol_min, my_vol);
957 vol_max = Math::max(vol_min, my_vol);
958 vol += my_vol;
959 }
960 }
961
990 CoordType& vol_min, CoordType& vol_max, const CoordType& vol) const
991 {
992 CoordType size_defect(0);
993 lambda_min = Math::huge<CoordType>();
994 lambda_max = CoordType(0);
995
996 for(Index cell(0); cell < this->get_mesh()->get_num_entities(ShapeType::dimension); ++cell)
997 {
998 size_defect += Math::abs(this->_trafo.template
999 compute_vol<ShapeType, CoordType>(cell)/vol - this->_lambda(cell));
1000
1001 lambda_min = Math::min(lambda_min, this->_lambda(cell));
1002 lambda_max = Math::max(lambda_max, this->_lambda(cell));
1003 }
1004
1005 vol_min /= vol;
1006 vol_max/= vol;
1007
1008 return size_defect;
1009 }
1010
1028 virtual void eval_fval_grad(CoordType& fval, VectorTypeL& grad, const bool& add_penalty_fval = true)
1029 {
1030 typedef typename TrafoType::template Evaluator<ShapeType, DataType>::Type TrafoEvaluator;
1031 typedef typename SpaceType::template Evaluator<TrafoEvaluator>::Type SpaceEvaluator;
1032
1033 // Increase number of functional evaluations
1034 this->_num_func_evals++;
1035 this->_num_grad_evals++;
1036
1037 // Total number of cells in the mesh
1038 Index ncells(this->get_mesh()->get_num_entities(ShapeType::dimension));
1039
1040 // Index set for local/global numbering
1041 auto& idx = this->get_mesh()->template get_index_set<ShapeType::dimension,0>();
1042
1043 // This will hold the coordinates for one element for passing to other routines
1044 FEAT::Tiny::Matrix <CoordType, Shape::FaceTraits<ShapeType,0>::count, MeshType::world_dim> x;
1045 // This will hold the local gradient for one element for passing to other routines
1047
1048 // Clear gradient vector
1049 grad.format();
1050 fval = DataType(0);
1051
1052 TrafoEvaluator trafo_eval(this->_trafo);
1053 SpaceEvaluator space_eval(this->trafo_space);
1054
1055 // Compute the functional value for each cell
1056 for(Index cell(0); cell < ncells; ++cell)
1057 {
1058 DataType fval_loc(0);
1059 trafo_eval.prepare(cell);
1060 space_eval.prepare(trafo_eval);
1061
1062 // Get local coordinates
1063 for(int j(0); j < Shape::FaceTraits<ShapeType,0>::count; ++j)
1064 {
1065 x[j] = this->_coords_buffer(idx(cell,j));
1066 }
1067
1068 auto mat_tensor = RefCellTrafo_::compute_mat_tensor(x, this->_h(cell));
1069
1070 this->_cell_functional->eval_fval_grad(
1071 fval_loc, grad_loc, mat_tensor, trafo_eval, space_eval, x, this->_h(cell));
1072
1073 // Add the contribution from the dependence of h on the vertex coordinates
1074 if(this->_mesh_conc != nullptr && this->_mesh_conc->use_derivative())
1075 {
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));
1079 }
1080
1081 fval += this->_mu(cell)*fval_loc;
1082 // Add local contributions to global gradient vector
1083 for(int j(0); j < Shape::FaceTraits<ShapeType,0>::count; ++j)
1084 {
1085 Index i(idx(cell,j));
1087 tmp += this->_mu(cell)*grad_loc[j];
1088
1089 grad(i,tmp);
1090 }
1091 }
1092
1093 if(this->_penalty_param > DataType(0))
1094 {
1095 XASSERTM(this->_mesh_conc != nullptr,
1096 "You need a mesh concentration function for imposing a mesh alignment constraint!");
1097
1098 if(add_penalty_fval)
1099 {
1100 // Add the quadratic penalty term to the functional value
1101 fval += this->_penalty_param*DataType(0.5)*Math::sqr(this->_alignment_constraint);
1102 }
1103
1104 // Add the gradient of the penalty term
1105 this->_mesh_conc->add_constraint_grad(grad, this->_alignment_constraint, this->_penalty_param);
1106
1107 }
1108 }
1109
1126 virtual void eval_fval_cellwise(CoordType& fval, CoordType* fval_norm, CoordType* fval_cof,
1127 CoordType* fval_det) const
1128 {
1129 typedef typename TrafoType::template Evaluator<ShapeType, DataType>::Type TrafoEvaluator;
1130 typedef typename SpaceType::template Evaluator<TrafoEvaluator>::Type SpaceEvaluator;
1131
1132 // Total number of cells in the mesh
1133 Index ncells(this->get_mesh()->get_num_entities(ShapeType::dimension));
1134
1135 // Index set for local/global numbering
1136 auto& idx = this->get_mesh()->template get_index_set<ShapeType::dimension,0>();
1137
1138 // This will hold the coordinates for one element for passing to other routines
1139 FEAT::Tiny::Matrix <CoordType, Shape::FaceTraits<ShapeType,0>::count, MeshType::world_dim> x;
1140 // Local cell dimensions for passing to other routines
1141 CoordType h(0);
1142 // This will hold the local gradient for one element for passing to other routines
1144
1145 fval = DataType(0);
1146
1147 TrafoEvaluator trafo_eval(this->_trafo);
1148 SpaceEvaluator space_eval(this->trafo_space);
1149
1150 // Compute the functional value for each cell
1151 for(Index cell(0); cell < ncells; ++cell)
1152 {
1153 DataType fval_loc(0);
1154 trafo_eval.prepare(cell);
1155 space_eval.prepare(trafo_eval);
1156
1157 h = this->_h(cell);
1158 // Get local coordinates
1159 for(int j(0); j < Shape::FaceTraits<ShapeType,0>::count; ++j)
1160 {
1161 x[j] = this->_coords_buffer(idx(cell,j));
1162 }
1163
1164 auto mat_tensor = RefCellTrafo_::compute_mat_tensor(x, this->_h(cell));
1165
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]);
1168
1169 fval += this->_mu(cell)*fval_loc;
1170 }
1171
1172 } // eval_fval_cellwise
1173
1174 protected:
1177 {
1178 Index ncells(this->get_mesh()->get_num_entities(ShapeType::dimension));
1179
1180 _sum_lambda = DataType(0);
1181 for(Index cell(0); cell < ncells; ++cell)
1182 {
1183 _lambda(cell, this->_trafo.template compute_vol<ShapeType, CoordType>(cell));
1184 _sum_lambda += _lambda(cell);
1185 }
1186
1187 this->sync_scalars.emplace("_sum_lambda",&_sum_lambda);
1188
1189 }
1190
1193 {
1195
1197 this->sync_scalars.emplace("_sum_lambda",&_sum_lambda);
1198 }
1199
1202 {
1203 _mesh_conc->compute_conc();
1204 this->sync_scalars.emplace("_sum_conc",&(_mesh_conc->get_sum_conc()));
1205
1206 _mesh_conc->compute_grad_conc();
1207
1208 _mesh_conc->compute_grad_sum_det(this->_coords_buffer);
1209
1210 _lambda.copy(_mesh_conc->get_conc());
1211
1212 _sum_lambda = DataType(0);
1213 for(Index cell(0); cell < this->get_mesh()->get_num_entities(ShapeType::dimension); ++cell)
1214 {
1215 _sum_lambda += _lambda(cell);
1216 }
1217 this->sync_scalars.emplace("_sum_lambda",&_sum_lambda);
1218
1219 }
1220
1225 {
1226
1227 switch(_scale_computation)
1228 {
1229 case ScaleComputation::once_uniform:
1230 case ScaleComputation::once_cellsize:
1231 case ScaleComputation::once_concentration:
1232 return;
1233 case ScaleComputation::current_uniform:
1235 break;
1236 case ScaleComputation::current_cellsize:
1238 break;
1239 case ScaleComputation::current_concentration:
1240 case ScaleComputation::iter_concentration:
1242 break;
1243 default:
1244 return;
1245 }
1246
1247 _sum_det = RefCellTrafo_::compute_sum_det(this->_coords_buffer, *(this->get_mesh()));
1248 this->sync_scalars.emplace("_sum_det",&_sum_det);
1249
1250 }
1251
1258 {
1259 switch(_scale_computation)
1260 {
1261 case ScaleComputation::iter_concentration:
1263 break;
1264 default:
1265 return;
1266 }
1267
1268 _sum_det = RefCellTrafo_::compute_sum_det(this->_coords_buffer, *(this->get_mesh()));
1269 this->sync_scalars.emplace("_sum_det",&_sum_det);
1270 }
1271
1278 {
1279 switch(_scale_computation)
1280 {
1281 case ScaleComputation::once_uniform:
1283 break;
1284 case ScaleComputation::once_cellsize:
1286 break;
1287 case ScaleComputation::once_concentration:
1289 break;
1290 default:
1291 return;
1292 }
1293
1294 _sum_det = RefCellTrafo_::compute_sum_det(this->_coords_buffer, *(this->get_mesh()));
1295 this->sync_scalars.emplace("_sum_det",&_sum_det);
1296
1297 }
1298
1299 }; // class HyperelasticityFunctional
1300
1301#ifdef FEAT_EICKT
1303 extern template class HyperelasticityFunctional
1304 <
1305 double, Index,
1308 <
1309 double,
1311 >
1312 >;
1313
1314 extern template class HyperelasticityFunctional
1315 <
1316 double, Index,
1319 <
1320 double,
1322 >
1323 >;
1324
1325 extern template class HyperelasticityFunctional
1326 <
1327 double, Index,
1330 <
1331 double,
1333 >
1334 >;
1335
1336 extern template class HyperelasticityFunctional
1337 <
1338 double, Index,
1341 <
1342 double,
1344 >
1345 >;
1347#endif // FEAT_EICKT
1348
1349 } // namespace Meshopt
1350} // namespace FEAT
#define XABORTM(msg)
Abortion macro definition with custom message.
Definition: assertion.hpp:192
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
FEAT Kernel base header.
VTK exporter class template.
Definition: export_vtk.hpp:119
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.
Definition: export_vtk.hpp:313
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.
Definition: export_vtk.hpp:442
void add_cell_scalar(const String &name, const T_ *data, double scaling_factor=1.0)
Adds a scalar cell variable to the exporter.
Definition: export_vtk.hpp:411
void add_vertex_scalar(const String &name, const T_ *data, double scaling_factor=1.0)
Adds a scalar vertex variable to the exporter.
Definition: export_vtk.hpp:282
bool adapt_by_name(const String &part_name, bool recursive=false)
Adapts this mesh node.
Definition: mesh_node.hpp:523
MeshPartType * find_mesh_part(const String &part_name)
Searches this container for a MeshPart.
Definition: mesh_node.hpp:398
Root mesh node class template.
Definition: mesh_node.hpp:748
Index size() const
Returns the containers size.
Definition: container.hpp:1136
void format(DT_ value=DT_(0))
Reset all elements of the container to a given value or zero if missing.
Definition: container.hpp:851
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.
Definition: slip_filter.hpp:67
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.
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.
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.
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.
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.
Definition: string.hpp:46
String pad_back(size_type len, char c=' ') const
Pads the back of the string up to a desired length.
Definition: string.hpp:415
Tiny Matrix class template.
Tiny Vector class template.
Standard transformation mapping class template.
Definition: mapping.hpp:39
T_ abs(T_ x)
Returns the absolute value.
Definition: math.hpp:275
T_ pow(T_ x, T_ y)
Returns x raised to the power of y.
Definition: math.hpp:643
T_ sqr(T_ x)
Returns the square of a value.
Definition: math.hpp:95
T_ min(T_ a, T_ b)
Returns the minimum of two values.
Definition: math.hpp:123
T_ max(T_ a, T_ b)
Returns the maximum of two values.
Definition: math.hpp:137
ScaleComputation
Enum class for different types of scale computations.
FEAT namespace.
Definition: adjactor.hpp:12
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:944
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.
Definition: string.hpp:1088
@ grad
specifies whether the space should supply basis function gradients
std::uint64_t Index
Index data type.