KASKADE 7 development version
tools.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2002-2012 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef INTERPOLATION_TOOLS_HH
14#define INTERPOLATION_TOOLS_HH
15
16#include <algorithm>
17#include <cassert>
18#include <cmath>
19#include <iostream>
20#include <memory>
21#include <string>
22#include <type_traits>
23#include <utility>
24#include <vector>
25#include "fem/barycentric.hh"
26#include "fem/lagrangespace.hh"
28#include "fem/fetransfer.hh"
33
35namespace Dune
36{
37
38 namespace Capabilities
39 {
40
41 template< class Grid >
43 {
44 static const bool v = false;
45 };
46
47 template< class Grid >
48 struct hasHierarchicIndexSet< const Grid >
49 {
51 };
52
53 }
54
55}
56
57namespace Kaskade
58{
59
60 namespace InterpolationTools
61 {
63 /*
64 * Throws an exception if an empty vector is passed.
65 * Vector entries must be less-than comparable, provide a copy-constructor and the assignment-operator.
66 *
67 * \param vec input vector
68 * \result maximal entry in vec
69 */
70 template<class Type>//, class ReturnType=Type>
71 Type getMaximumValue(std::vector<Type> const& vec)
72 {
73 if(vec.size() == 0) throw DetailedException("Cannot detect maximum value in empty vector." , __FILE__, __LINE__);
74 Type result = vec[0];
75 std::for_each(++(vec.begin()), vec.end(), [&](Type const& entry) { if(result < entry) result = entry; });
76
77 return result;
78 }
79
81 template<class Type>
82 bool contains(Type const entry, std::vector< Type > const& vec)
83 {
84 for(size_t i=0; i<vec.size(); ++i)
85 if(vec[i] == entry) return true;
86 return false;
87 }
89 /*
90 * This container may be used to store normals together with additional information that are associated
91 * to i.e. a vertex or an edge.
92 */
93 template<class Scalar_, int dim_>
95 static int const dim = dim_;
96 typedef Scalar_ Scalar;
98
99 NormalCollection() : onBoundary(false), normals(0), weights(0), phaseIds(0), ids(0), isRelevant(true) {}
100
102 {
103 *this = std::move(other);
104 }
105
106 std::ostream& print(std::ostream& os = std::cout) const
107 {
108 os << std::boolalpha << "Relevant: " << isRelevant << std::endl;
109 for(int i=0; i<normals.size(); ++i) os << "normal: " << normals[i] << ", material id: " << phaseIds[i] << std::endl;
110 return os;
111 }
112
113 void clear() {
114 normals.clear();
115 weights.clear();
116 phaseIds.clear();
117 ids.clear();
118 isRelevant = false;
119 }
120
122 {
123 clear();
124 normals.push_back(Vector(0));
125 weights.push_back(0);
126 phaseIds.push_back(-1);
127 ids.push_back(-1);
128 }
129
131 std::vector<Vector> normals;
132 std::vector<Scalar> weights;
133 std::vector<int> phaseIds, ids;
135
136 // move assignment operator
138 {
139 // steal resources
140 onBoundary = other.onBoundary;
141 normals = std::move(other.normals);
142 weights = std::move(other.normals);
143 phaseIds = std::move(other.phaseIds);
144 ids = std::move(other.ids);
145 isRelevant = other.isRelevant;
146
147 // invalidate other
148 other.onBoundary = false;
149 other.isRelevant = true;
150 }
151
153 void print(std::ostream& os){
154 os << std::boolalpha << "is relevant: " << isRelevant << std::endl;
155 os << "normals:" << std::endl;
156 for(size_t j=0; j<normals.size(); ++j) os << normals[j] << ", phase id: " << phaseIds[j] << std::endl;
157 }
158
159 // friends
160 friend std::ostream& operator <<(std::ostream &os, NormalCollection<Scalar,dim> const& collection)
161 {
162 return collection.print(os);
163 }
164 };
165
166 // compute mean normals
171 template <bool inVertex, class NormalCollection>
173
174 // if vertex does not lie on the boundary: normals.size() == 0
175 // if edge has more than 4 normals (more than 2 materials meet at this edge) -> do nothing
176 if(collection.normals.size() == 0 || (collection.normals.size() > 4 && !inVertex) ){
177 collection.irrelevant();
178 return;
179 }
180 if(!collection.isRelevant)
181 {
182 collection.irrelevant();
183 return;
184 }
185
186 // if vertex/edge belongs to two faces of the same entity -> no smoothing
187 // TODO delegate to policy
188 if(!collection.onBoundary)
189 {
190 std::vector<int> idCount;
191 for(size_t i=0; i<collection.ids.size(); ++i){
192 if( InterpolationTools::contains(collection.ids[i], idCount) ){
193 collection.irrelevant();
194 return;
195 }
196 else idCount.push_back( collection.ids[i] );
197 }
198 }
199 // else
200 // collect material types
201 std::vector<bool> materials;
202 if(collection.onBoundary){
203 materials = std::vector<bool>(1, true);
204 }
205 else{
206 materials = std::vector<bool>( (InterpolationTools::getMaximumValue(collection.phaseIds) + 1), false );
207 for(size_t i=0; i<collection.normals.size(); ++i)
208 materials[collection.phaseIds[i]] = true;
209 }
210
211 // compute mean normals
212 std::vector<int> reducedMaterialList;
213 std::vector<typename NormalCollection::Vector> reducedNormalList;
214 for(size_t i=0; i<materials.size(); ++i){
215 // if material does not exist in adjacent cells do nothing
216 if(!materials[i]) continue;
217
218 // if material exists store its id
219 reducedMaterialList.push_back(i);
220 std::vector<typename NormalCollection::Vector> tmp;
221 // and collect all corresponding normals
222 for(size_t j=0; j<collection.normals.size(); ++j)
223 if(collection.phaseIds[j] == i || collection.onBoundary)
224 tmp.push_back(collection.weights[j]*collection.normals[j]);
225
226 // compute mean normal
227 typename NormalCollection::Vector meanNormal(0);
228 for(size_t j=0; j<tmp.size(); ++j)
229 meanNormal += tmp[j];
230
231 GeomTools::normalize(meanNormal);
232
233 reducedNormalList.push_back(meanNormal);
234 }
235
236 collection.normals = reducedNormalList;
237 collection.phaseIds = reducedMaterialList;
238
239 // if intersection with other inner boundary layers
240 if(collection.phaseIds.size() > 2) collection.irrelevant();
241
242 }
243
244 // -------------------------------------------------------------------------------------------------
245 // Choose function space / shape function set
246 // -------------------------------------------------------------------------------------------------
250
251 template<class Scalar, class Grid, int dim>
252 struct ChoiceOfShapeFunctionSet
253 {
254 typedef typename std::conditional<
255 dim==3,
258 >::type type;
259
260 ChoiceOfShapeFunctionSet() : shapeFunctionSet(3){}
261
262 type const shapeFunctionSet;
263 };
264
265 // -------------------------------------------------------------------------------------------------
266 // Data Container.
267 // -------------------------------------------------------------------------------------------------
268
269 struct Empty
270 {
271 Empty() = default;
272
273 Empty(const Empty&) = delete;
274 Empty& operator=(const Empty&) = delete;
275 };
282 template<class Scalar, int dim>
284
286 template<class Scalar>
287 struct NormalContainer<Scalar, 2> : public Empty {
289 typedef std::vector<EntryType> CollectionType;
290
291 explicit NormalContainer(size_t numberOfVertices=0) : vertexNormals(numberOfVertices) {}
292
293 template <class GridView>
294 explicit NormalContainer(GridView const& gridView) : vertexNormals(gridView.size(GridView::dimension))
295 {}
296
297 NormalContainer(NormalContainer&& other) : vertexNormals(std::move(other.vertexNormals)) {}
298
300 {
301 vertexNormals = std::move(other.vertexNormals);
302 }
303
304 std::ostream& print(std::ostream& os) const
305 {
306 int id = 0;
307 for(EntryType const& entry : vertexNormals)
308 {
309 std::cout << "entry nr. " << id++ << std::endl;
310 entry.print(os);
311 }
312 return os;
313 }
314
315 friend std::ostream& operator<<(std::ostream& os, NormalContainer const& container) { return container.print(os); }
316
318 };
319
321 template<class Scalar>
322 struct NormalContainer<Scalar, 3> : public Empty{
324 typedef std::vector< EntryType > CollectionType;
325
326 explicit NormalContainer(size_t numberOfVertices=0, size_t numberOfEdges=0) : vertexNormals(numberOfVertices), edgeNormals(numberOfEdges) {}
327
328 template <class GridView>
329 explicit NormalContainer(GridView const& gridView) : vertexNormals(gridView.size(GridView::dimension)), edgeNormals(gridView.size(GridView::dimension-1))
330 {}
331
332 NormalContainer(NormalContainer&& other) : vertexNormals(std::move(other.vertexNormals)), edgeNormals(std::move(other.edgeNormals)) {}
333
335 {
336 vertexNormals = std::move(other.vertexNormals);
337 edgeNormals = std::move(other.edgeNormals);
338 }
339
340 std::ostream& print(std::ostream& os) const
341 {
342 int id = 0;
343 for(EntryType const& entry : vertexNormals)
344 {
345 std::cout << "entry nr. " << id++ << std::endl;
346 entry.print(os);
347 }
348 id = 0;
349 for(EntryType const& entry : edgeNormals)
350 {
351 std::cout << "entry nr. " << id++ << std::endl;
352 entry.print(os);
353 }
354 return os;
355 }
356
357 friend std::ostream& operator<<(std::ostream& os, NormalContainer const& container) { return container.print(os); }
358
360 };
361 } /* end of namespace InterpolationTools 1 */
362
363 namespace Policy{
364
365 /**************************************************************************************************/
366 /******************************* Boundary Policies - Inner Boundary *******************************/
367 /**************************************************************************************************/
368
371 bool ignoreInnerBoundary(int tissue, int tissueNeighbour) const { return true; }
372 };
373
376 bool ignoreInnerBoundary(int tissue, int tissueNeighbour) const { return false; }
377 };
378
380 /*
381 * \param IdVector vector containing the boundary ids (i.e. std::vector<int>)
382 * \param skipSpecifiedIds bool value indicating default treatment (i.e. true: consider only specified parts of the boundary, false: ignore specified parts)
383 */
384 template<class IdVector, bool skipSpecifiedIds = false>
386 {
387 /*
388 * \param boundaryIds vector of boundary ids
389 * \param specifiedIds vector of ids that will be ignored or considered only
390 */
391 SpecifyInnerBoundary(std::vector<std::pair<int,int> > specifiedInterfaces)
392 {
393 for(size_t i=0; i<specifiedInterfaces.size(); ++i) addInterface( specifiedInterfaces[i] );
394 }
395
397 void addInterface(std::pair<int,int> ids){
398 if(ids.first == ids.second) std::cout << "Ignoring interface between same material ids (id: " << ids.first << ")" << std::endl;
399 else specifiedInterfaces_.push_back(std::make_pair(std::min(ids.first,ids.second), std::max(ids.first,ids.second)));
400 }
401
403 void addInterface(int first, int second){
404 addInterface(std::make_pair(first,second));
405 }
406
408 bool ignoreInnerBoundary(int tissue, int tissueNeighbour) const
409 {
410 if(tissue == tissueNeighbour) return true;
411 int const tmp1 = std::min(tissue, tissueNeighbour),
412 tmp2 = std::max(tissue, tissueNeighbour);
413 bool contains = std::find( specifiedInterfaces_.begin(), specifiedInterfaces_.end(), std::make_pair(tmp1, tmp2) ) != specifiedInterfaces_.end();
414 return (contains == skipSpecifiedIds);
415 }
416
417 private:
418 std::vector<std::pair<int,int> > specifiedInterfaces_;
419 };
420
421 /**************************************************************************************************/
422 /******************************* Boundary Policies - Outer Boundary *******************************/
423 /**************************************************************************************************/
424
427 template <class Face>
428 bool ignoreOuterBoundary(Face const&) const { return true; }
429 };
430
433 template <class Face>
434 bool ignoreOuterBoundary(Face const&) const { return false; }
435 };
436
438 /*
439 * \param IdVector vector containing the boundary ids (i.e. std::vector<int>)
440 * \param skipSpecifiedIds bool value indicating default treatment (i.e. true: consider only specified parts of the boundary, false: ignore specified parts)
441 */
442 template<class IdVector, bool skipSpecifiedIds = false>
444 {
445 /*
446 * \param boundaryIds vector of boundary ids
447 * \param specifiedIds vector of ids that will be ignored or considered only
448 */
449 SpecifyOuterBoundary(IdVector const& boundaryIds, IdVector const& specifiedIds) :
450 boundaryIds_(boundaryIds), considerFace_(InterpolationTools::getMaximumValue(specifiedIds) + 1, skipSpecifiedIds)
451 {
452 for(size_t i=0; i<specifiedIds.size(); ++i)
453 considerFace_[specifiedIds[i]] = !skipSpecifiedIds;
454 }
455
457 template<class Face>
458 bool ignoreOuterBoundary(Face const& face) const
459 {
460 unsigned int index = face.boundarySegmentIndex();
461 if(index < boundaryIds_.size()) return considerFace_[boundaryIds_[index]];
462 else return !skipSpecifiedIds;
463
464 return false;
465 }
466
467 private:
468 IdVector const& boundaryIds_;
469 std::vector<bool> considerFace_;
470 };
471
472 /**************************************************************************************************/
473 /******************************* Interpolation Policies - Threshold *******************************/
474 /**************************************************************************************************/
475
476 template <class Scalar>
478 {
479 void applyGradientThreshold(Scalar &gradient) const {}
480 };
481
483
487 template <class Scalar>
489 {
490 explicit ApplyGradientThreshold(Scalar const threshold=1.0) : threshold_(threshold){}
491
492 void applyGradientThreshold(Scalar &gradient) const
493 {
494 if(threshold_ < 0) return;
495 if(fabs(gradient) > threshold_)
496 gradient = 0;
497 }
498
499 private:
500 Scalar threshold_;
501 };
502
503 /**************************************************************************************************/
504 /**************************************** Material Policy *****************************************/
505 /**************************************************************************************************/
510 template <class Scalar>
511 struct NoPhaseInfo
512 {
513 NoPhaseInfo(){}
514
515 template <class PhaseElement>
516 explicit NoPhaseInfo(PhaseElement const&){}
517
518 template <class Entity>
519 Scalar phaseId(Entity const& entity) const { return 0; }
520 };
521
523
526 template<class PhaseElement>
527 struct PhaseAsFSElement
528 {
529 explicit PhaseAsFSElement(PhaseElement const& phase_) : phase(phase_){}
530
531 PhaseAsFSElement(PhaseAsFSElement const& other) : phase(other.phase){}
532
533 template<class Entity>
534 typename PhaseElement::Scalar phaseId(Entity const& entity) const
535 {
537 }
538
539 PhaseElement const& phase;
540 };
541
542 /**************************************************************************************************/
543 /************************************* ShapeFunctionSet Policy ************************************/
544 /**************************************************************************************************/
545
547 template <class InterpolationPolynomial>
548 struct NoShapeFunctionSet{
549 typedef typename InterpolationPolynomial::GridView::Grid::template Codim<0>::Entity Entity;
550
551 template <typename... Parameters>
552 InterpolationPolynomial init(Entity const& entity, typename InterpolationPolynomial::GridView const& gridView, Parameters const&... parameters)
553 {
554 return InterpolationPolynomial(entity, gridView, parameters...);
555 }
556
557 typename InterpolationPolynomial::range_type
558 evaluate(InterpolationPolynomial& polynomial, typename InterpolationPolynomial::domain_type const& x) const
559 {
560 return polynomial.evaluate(x);
561 }
562 };
563
565 template <class InterpolationPolynomial>
566 struct UseShapeFunctionSet
567 : private InterpolationTools::ChoiceOfShapeFunctionSet<typename InterpolationPolynomial::Scalar, typename InterpolationPolynomial::GridView::Grid, InterpolationPolynomial::GridView::dimension>
568 {
569 typedef typename InterpolationPolynomial::GridView::Grid::template Codim<0>::Entity Entity;
570
571 template <typename... Parameters>
572 InterpolationPolynomial init(Entity const& entity, typename InterpolationPolynomial::GridView const& gridView, Parameters const&... parameters)
573 {
574 return InterpolationPolynomial(entity, gridView, shapeFunctionSet, parameters...);
575 }
576
577 typename InterpolationPolynomial::range_type
578 evaluate(InterpolationPolynomial const& polynomial, typename InterpolationPolynomial::domain_type const& x) const
579 {
580 return polynomial.evaluate(x, shapeFunctionSet);
581 }
582
583 private:
584 using InterpolationTools::ChoiceOfShapeFunctionSet<typename InterpolationPolynomial::Scalar,typename InterpolationPolynomial::GridView::Grid,InterpolationPolynomial::GridView::dimension>::shapeFunctionSet;
585 };
586
587 // Create struct that checks if a type (i.e. an interpolation polynomial) has a const bool variable
588 // called 'needsShapeFunctionSet'
589 namespace Detail{
590 KASKADE_CREATE_MEMBER_VARIABLE_CHECK(bool const, needsShapeFunctionSet, Has_needsShapeFunctionSet)
591
592 template <class InterpolationPolynomial, bool has_needsShapeFunctionSet>
593 struct ChooseShapeFunctionSetPolicy
594 {
595 typedef NoShapeFunctionSet<InterpolationPolynomial> type;
596 };
597
598 template <class InterpolationPolynomial>
599 struct ChooseShapeFunctionSetPolicy<InterpolationPolynomial,true>
600 {
601 // use UseShapeFunctionSet if InterpolationPolynomial::needsShapeFunctionSet=true
602 typedef typename std::conditional<InterpolationPolynomial::needsShapeFunctionSet,UseShapeFunctionSet<InterpolationPolynomial>,NoShapeFunctionSet<InterpolationPolynomial> >::type type;
603 };
604 }
605
606 template <class InterpolationPolynomial>
607 struct ShapeFunctionSetPolicy : public Detail::ChooseShapeFunctionSetPolicy<InterpolationPolynomial,Detail::Has_needsShapeFunctionSet<InterpolationPolynomial>::value>::type
608 {};
613 template <class Scalar>
615 {
616 explicit RelativeDeformation(Scalar scale_=0.25) : scale(scale_)
617 {}
618
619 template <class Entity>
620 void init(Entity const& entity)
621 {
622 initialVolume = entity.geometry().volume();
623 }
624
625 template <class Entity>
626 bool operator()(Entity const& entity, Scalar referenceVolume = -1.) const
627 {
628 return (entity.geometry().volume() < ((referenceVolume<0) ? scale*initialVolume : referenceVolume ));
629 }
630
631 private:
632 Scalar scale, initialVolume;
633 };
634
635 template <class Scalar>
637 {
638 explicit ConstantDamping(Scalar const dampingFactor_ = 0.9) : dampingFactor(dampingFactor_), exponent(0)
639 {
640 assert(dampingFactor > 0);
641 }
642
643 void increase() { (dampingFactor < 1) ? --exponent : ++exponent; }
644
645 void decrease() { (dampingFactor < 1) ? ++exponent : --exponent; }
646
647 void reset() { exponent = 0; }
648
649 Scalar operator()() const
650 {
651 return 1;//pow(dampingFactor,exponent);
652 }
653
654 private:
655 Scalar const dampingFactor;
656 int exponent;
657 };
658
659 /**************************************************************************************************/
660 /**************************************** Merging Policies ****************************************/
661 /**************************************************************************************************/
662 template <class... Policies> struct MergedPolicy : public Policies...
663 {
664 explicit MergedPolicy(const Policies&... policies) : Policies(policies)...{}
665 };
666
667 } /* end of namespace Policy */
668
669
670 // -------------------------------------------------------------------------------------------------
671 // Namespace hiding tools.
672 // -------------------------------------------------------------------------------------------------
673 namespace InterpolationTools
674 {
676 /*
677 * \param entity entity
678 * \param gridView GridView containing the entity
679 * \result global indices of the entity's vertices
680 */
681 template <class Entity, class GridView>
682 std::vector<int> getGlobalVertexIds(Entity const &entity, GridView const &gridView)
683 {
684 std::vector<int> result(GridView::dimension+1,-1);
685 for(size_t i=0; i<result.size(); ++i) result[i] = gridView.indexSet().subIndex(entity,i,GridView::dimension);
686
687 return result;
688 }
689
691 /*
692 * \param entity entity containing the edge
693 * \param edgeId local index of the edge in the entity
694 * \result local indices of the edge's vertices wrt entity
695 */
696 template <class Entity>
697 std::vector<int> getEdgeCornerIdsInEntity(Entity const& entity, int edgeId)
698 {
699 Dune::GeometryType const gt(entity.type().id(), Entity::dimension);
700 std::vector<int> result(2,0);
701 // get local indices in cell
702 result[0] = Dune::GenericReferenceElements<typename Entity::ctype,Entity::dimension>::general(gt).subEntity(edgeId,Entity::dimension-1,0,Entity::dimension);
703 result[1] = Dune::GenericReferenceElements<typename Entity::ctype,Entity::dimension>::general(gt).subEntity(edgeId,Entity::dimension-1,1,Entity::dimension);
704 return result;
705 }
706
708 /*
709 * \param entity entity containing the edge
710 * \param edgeId local id in entity
711 * \param gridView gridView containing the entity and edge
712 * \return global indices of the edges vertices
713 */
714 template <class Entity, class GridView>
715 std::vector<int> getGlobalEdgeCornerIds(Entity const& entity, int edgeId, GridView const& gridView)
716 {
717 std::vector<int> localIds = getEdgeCornerIdsInEntity(entity, edgeId);
718 std::vector<int> result(2,0);
719 result[0] = gridView.indexSet().subIndex(entity,localIds[0],GridView::dimension);
720 result[1] = gridView.indexSet().subIndex(entity,localIds[1],GridView::dimension);
721 return result;
722 }
723
725 /*
726 * \param vid global vertex indices
727 * \param vertexNormals global collection of directions associated to the vertices
728 * \param localNormals directions corresponding to the vertices indexed through vid
729 */
730 template <class NormalCollection, class Vector>
731 void getVertexNormals(std::vector<int> const &vid, NormalCollection const& vertexNormals, std::vector<Vector> &localNormals, typename Vector::field_type const tissueId)
732 {
733 for(int i=0; i<vid.size(); ++i){
734 for(int j=0; j<vertexNormals[vid[i]].normals.size(); ++j)
735 if(fabs(vertexNormals[vid[i]].phaseIds[j] - tissueId ) < 1e-9){
736 localNormals[i] = vertexNormals[vid[i]].normals[0];
737 break;
738 }
739 }
740 }
741
742 } /* end namespace InterpolationTools 2 */
743
744
745 template <class FaceIterator, class Scalar, int dim>
746 Dune::FieldVector<Scalar,dim+1> getWeights(FaceIterator& iter, FaceIterator& iend, Dune::FieldVector<Scalar,dim> const& x, std::vector<Dune::FieldVector<Scalar,dim> >& normals)
747 {
749 size_t counter = 0;
750 LinAlg::EuclideanScalarProduct scalarProduct;
751 for(; iter!=iend; ++iter, ++counter)
752 {
753 normals[counter] = -1.*iter->centerUnitOuterNormal();
754 result[counter] = -1.*scalarProduct(x - iter->geometry().corner(0), normals[counter]);
755 assert(result[counter] <= 0);
756 }
757 return result;
758 }
759
760 template <class Vector>
761 inline typename Vector::field_type dist(Vector const& point, Vector const& start, Vector const& end)
762 {
763 typedef typename Vector::field_type Scalar;
764 Vector edge = end - start;
765 Vector p = point - start;
767
768 Scalar alpha = p*edge;
769 edge *= alpha;
770 p -= edge;
771
772 return sqrt(p*p);
773 }
774
775 template <class Entity, class Scalar, int dim>
776 inline Scalar dist(Entity const& entity, Dune::FieldVector<Scalar,dim> const& x)
777 {
778 Scalar d = dist(x, entity.geometry().corner(0), entity.geometry().corner(1));
779 Scalar tmp = dist(x, entity.geometry().corner(1), entity.geometry().corner(2));
780 if(tmp < d) d = tmp;
781 tmp = dist(x, entity.geometry().corner(2), entity.geometry().corner(3));
782 if(tmp < d) d = tmp;
783 return d;
784 }
785
786 template <class Scalar>
787 inline Scalar invert(Scalar const entry){ return -1./entry; }
788
789 template <class Scalar>
790 inline Scalar invert2(Scalar const entry){ return 1./(entry*entry); }
791
792 template <class Scalar>
793 inline Scalar invert3(Scalar const entry){
794 Scalar div = sqrt(pow(-1.*entry,1.8));
795 return (div > 1e-9) ? 1./div : 1e9;
796 // 1./sqrt(-1.*pow(entry,1.3));
797 }
798
799 template <class Vector>
800 inline Vector getLinearWeights(Vector const& weights, typename Vector::field_type (*fun)(typename Vector::field_type const))
801 {
802 Vector result(0);
803 for(int i=0; i<weights.size(); ++i) result[i] = 1.0 - weights[i];
804 return GeomTools::normalize(result);
805 }
806
807 template <class Vector>
808 inline Vector getNormalizedWeights(Vector const& weights, typename Vector::field_type (*fun)(typename Vector::field_type const))
809 {
810 Vector result(0);
811 for(int i=0; i<weights.size(); ++i) result[i] = fun(weights[i]);
812 return GeomTools::normalize(result);
813 }
814
816 template <class GridView, class Entity, class Vector, class Deformation>
817 Vector interpolateDeformation(GridView const& gridView, Entity const& entity, Vector const& x_local, Deformation const& deformation)
818 {
819 typedef typename Vector::field_type Scalar;
820 typedef typename GridView::IntersectionIterator FaceIterator;
821 int constexpr dim = GridView::dimension;
822 std::vector<Vector> normals(dim+1);
823 FaceIterator iter = gridView.ibegin(entity),
824 iend = gridView.iend(entity);
825 Dune::FieldVector<Scalar, dim+1> weights= getWeights<FaceIterator>(iter, iend, entity.geometry().global(x_local), normals);
826 std::vector<Vector> localEvaluationPoints(dim+1);
827 for(int i=0; i<dim+1; ++i) localEvaluationPoints[i] = entity.geometry().local(entity.geometry().global(x_local) + (weights[i])*normals[i]);
828
829 GeomTools::normalize(weights);
830
831 Dune::FieldVector<Scalar, dim+1> normalizedWeights = getNormalizedWeights(weights, invert);//getLinearWeights(weights, invert3);//GeomTools::getNormalized(weights);
832 Vector result(0);
833 for(size_t i=0; i<localEvaluationPoints.size(); ++i) result += normalizedWeights[i] * deformation.value(entity, localEvaluationPoints[i]);
834 return result;
835 }
836
837 template <class Interpolation>
838 struct Distance
839 {
840 explicit Distance(Interpolation const& interpolation_)
841 : interpolation(interpolation_)
842 {}
843
844 template <class Cell, class Vector>
845 typename Vector::field_type operator()(Cell const& cell, Vector const& x) const
846 {
847 Vector const& c0 = cell.geometry().corner(0),
848 c1 = cell.geometry().corner(1),
849 c2 = cell.geometry().corner(2);
850
851 Vector pos = 0.5*(c0 + c1);
852 Vector def = interpolation.value(cell,cell.geometry().local(pos));
853 if(def*def > 1e-9) return dist(x,c0,c1);
854 pos = 0.5*(c1 + c2);
855 def = interpolation.value(cell,cell.geometry().local(pos));
856 if(def*def > 1e-9) return dist(x,c1,c2);
857 pos = 0.5*(c2 + c0);
858 def = interpolation.value(cell,cell.geometry().local(pos));
859 if(def*def > 1e-9) return dist(x,c2,c0);
860 }
861
862 template <class Cell, class Vector=Dune::FieldVector<double,Cell::dimension> >
863 Vector normal(Cell const& cell) const
864 {
865 Vector const& c0 = cell.geometry().corner(0),
866 c1 = cell.geometry().corner(1),
867 c2 = cell.geometry().corner(2);
868
869 Vector pos = 0.5*(c0 + c1);
870 Vector def = interpolation.value(cell,cell.geometry().local(pos));
871 if(def*def > 1e-9) return getNormal(c0,c1);
872 pos = 0.5*(c1 + c2);
873 def = interpolation.value(cell,cell.geometry().local(pos));
874 if(def*def > 1e-9) return getNormal(c1,c2);
875 pos = 0.5*(c2 + c0);
876 def = interpolation.value(cell,cell.geometry().local(pos));
877 if(def*def > 1e-9) return getNormal(c2,c0);
878 }
879
880 private:
881 template <class Vector>
882 Vector getNormal(Vector const& start, Vector const& end) const
883 {
884 Vector result(end);
885 result -= start;
886 auto tmp = result[0];
887 result[0] = -result[1];
888 result[1] = tmp;
889 return GeomTools::normalize(result);
890 }
891
892 Interpolation const& interpolation;
893 };
894
895 template <class Distance, class Cell, class Vector, class Scalar=typename Vector::field_type>
896 void relaxVertex(Distance const& distance, Cell const& cell, Vector& x, Scalar const& h, Scalar eta = 0.3, size_t rad=3)
897 {
898 Scalar r = rad*sqrt(h*h);
899
900 Scalar alpha = eta*h*(1+distance(cell,x)/r);
901
902 Vector dir = distance.normal(cell);
903 dir *= alpha;
904 x -= dir;
905 }
906
907 template <class Grid, class Deformation, class Vector, class DeformationPolicy, class DampingPolicy>
908 bool adjustDampingFactor(Grid& grid, Deformation const& deformation, Vector const& initialVolume, DeformationPolicy const& deformationPolicy, DampingPolicy& dampingPolicy)
909 {
910 typedef typename Grid::ctype ctype;
911 typedef typename Grid::template Codim<0>::Entity Cell;
912 // constexpr int dim = Grid::dimension;
913
914 // iterate over cells
915 std::for_each(grid.leafGridView().template begin<0>(), grid.leafGridView().template end<0>(), [&](typename Grid::LeafGridView::template Codim<0>::Iterator::Entity const& entity)
916 {
917 LocalGeometryInCoarseGridAncestor<Grid> lgcga(grid, Cell(entity));
918 typedef decltype(entity) EntityRef;
919 typedef typename std::remove_reference<EntityRef>::type Entity;
920 constexpr int dim = Entity::Geometry::dimension;
921
922 for(int i=0; i<entity.geometry().corners(); ++i)
923 {
924 typename Dune::template UGGridFamily<dim, dim>::Traits::template Codim<dim>::Entity e(entity.template subEntity<dim>(i));
925
926 Dune::FieldVector<ctype,dim> p(Dune::template GenericReferenceElements<ctype,dim>::general(entity.type()).position(i,dim));
927 Dune::FieldVector<ctype,dim> v(lgcga.global(p));
928 Dune::FieldVector<ctype,dim> w(lgcga.getFather()->geometry().global(v));
929
930 Dune::FieldVector<ctype,dim+1> baryInFatherCell = barycentric(v);
931 bool inCell = true;
932 for(int i=0; i<dim+1; ++i) if(std::abs(baryInFatherCell[i]) < 1e-9) inCell = false;
933
934 w = lgcga.getFather()->geometry().global(v);
935 Distance<Deformation> distance(deformation);
936 if(!inCell)
937 w += dampingPolicy() * deformation.value(*(lgcga.getFather()),v);
938 else w += dampingPolicy() * interpolateDeformation(grid.levelView(0), *(lgcga.getFather()), v, deformation);
939 //else
940 //{
941 // relaxVertex(distance,*(lgcga.getFather()),w,1);
942 //}
943 grid.setPosition(e,w);
944 }
945 });
946
947 ctype minvol = 1000;
948 ctype minrel = 1000;
949 auto cend = grid.leafGridView().template end<0>();
950 for(auto ci = grid.leafGridView().template begin<0>(); ci!=cend; ++ci)
951 {
952 if(ci->geometry().volume()/initialVolume[grid.leafGridView().indexSet().index(*ci)] < minrel) minrel = ci->geometry().volume()/initialVolume[grid.leafGridView().indexSet().index(*ci)];
953 if(ci->geometry().volume() < minvol) minvol = ci->geometry().volume();
954 if(deformationPolicy(*ci, 0.3*initialVolume[grid.leafGridView().indexSet().index(*ci)])) return false;
955 }
956
957 std::cout << "Minvol: " << minvol << std::endl;
958 std::cout << "Minrel: " << minrel << std::endl;
959
960 return true;
961 }
962
963 template<class Grid, class DefFunction, template <class> class AcceptDeformationPolicy=Policy::RelativeDeformation, template <class> class DampingPolicy = Policy::ConstantDamping >
964 void deformGrid(Grid& grid, DefFunction const& deformation, bool allCells, bool doreset,
965 AcceptDeformationPolicy<typename Grid::ctype> deformationPolicy = AcceptDeformationPolicy<typename Grid::ctype>(),
966 DampingPolicy<typename Grid::ctype> dampingPolicy = DampingPolicy<typename Grid::ctype>())
967 {
968 typedef typename Grid::LeafGridView::template Codim<0>::Iterator CellIterator;
969
970 // store initial cell volumes
971 std::vector<typename Grid::ctype> initialVolume(grid.leafGridView().indexSet().size(0),0);
972 std::for_each(grid.leafGridView().template begin<0>(), grid.leafGridView().template end<0>(), [&initialVolume,&grid](typename CellIterator::Entity const& entity)
973 {
974 for(int i=0; i<entity.geometry().corners(); ++i) initialVolume[grid.leafGridView().indexSet().index(entity)] = entity.geometry().volume();
975 });
976
977 std::cout << "Initial damping factor: " << dampingPolicy() << std::endl;
978 while(!adjustDampingFactor(grid,deformation,initialVolume,deformationPolicy,dampingPolicy))
979 {
980 break;
981 dampingPolicy.decrease();
982 std::cout << "Damping factor: " << dampingPolicy() << std::endl;
983 }
984 }
985
986} /* end of namespace Kaskade */
987
988#endif
A wrapper class for conveniently providing exceptions with context information.
A container of hierarchic shape functions (see HierarchicSimplexShapeFunction) up to a given nominal ...
A container of Lagrange shape functions of order Ord on the unit simplex of grid dimension....
Tools for transfer of data between grids.
Some simple tools for geometric calculations. Please extend.
typename GridView::template Codim< 0 >::Entity Cell
The type of cells (entities of codimension 0) in the grid view.
Definition: gridBasics.hh:35
typename GridView::Intersection Face
The type of faces in the grid view.
Definition: gridBasics.hh:42
Dune::FieldVector< T, n > max(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise maximum.
Definition: fixdune.hh:109
Dune::FieldVector< T, n > min(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise minimum.
Definition: fixdune.hh:121
Hierarchic Finite Elements.
Lagrange Finite Elements.
#define KASKADE_CREATE_MEMBER_VARIABLE_CHECK(VARIABLE_TYPE, VARIABLE_NAME, NAME)
Necessary information for Dune::GeometryGrid.
Definition: fixdune.hh:42
Vector normalize(Vector &vector)
Normalize vector.
Definition: geomtools.hh:48
Scalar distance(Point< Scalar, dim > const &first, Point< Scalar, dim > const &second)
void getVertexNormals(std::vector< int > const &vid, NormalCollection const &vertexNormals, std::vector< Vector > &localNormals, typename Vector::field_type const tissueId)
Get the normals assoicated to the global vertex indices in vid.
Definition: tools.hh:731
std::vector< int > getEdgeCornerIdsInEntity(Entity const &entity, int edgeId)
Get local coordinates of the edges vertices in the codim<0> entity.
Definition: tools.hh:697
bool contains(Type const entry, std::vector< Type > const &vec)
Check if entry is contained in vec.
Definition: tools.hh:82
Type getMaximumValue(std::vector< Type > const &vec)
Get maximum value in a vector.
Definition: tools.hh:71
std::vector< int > getGlobalVertexIds(Entity const &entity, GridView const &gridView)
Get global vertex ids of the entities corners.
Definition: tools.hh:682
std::vector< int > getGlobalEdgeCornerIds(Entity const &entity, int edgeId, GridView const &gridView)
Get global indices of the edges vertices.
Definition: tools.hh:715
void computeMeanNormal(NormalCollection &collection)
Definition: tools.hh:172
Dune::FieldVector< Scalar, dim > Vector
void deformGrid(Grid &grid, DefFunction const &deformation, bool allCells, bool doreset, AcceptDeformationPolicy< typename Grid::ctype > deformationPolicy=AcceptDeformationPolicy< typename Grid::ctype >(), DampingPolicy< typename Grid::ctype > dampingPolicy=DampingPolicy< typename Grid::ctype >())
Definition: tools.hh:964
Dune::FieldVector< Scalar, dim+1 > getWeights(FaceIterator &iter, FaceIterator &iend, Dune::FieldVector< Scalar, dim > const &x, std::vector< Dune::FieldVector< Scalar, dim > > &normals)
Definition: tools.hh:746
Scalar invert(Scalar const entry)
Definition: tools.hh:787
Vector interpolateDeformation(GridView const &gridView, Entity const &entity, Vector const &x_local, Deformation const &deformation)
Definition: tools.hh:817
Vector getNormalizedWeights(Vector const &weights, typename Vector::field_type(*fun)(typename Vector::field_type const))
Definition: tools.hh:808
Vector::field_type dist(Vector const &point, Vector const &start, Vector const &end)
Definition: tools.hh:761
Scalar invert2(Scalar const entry)
Definition: tools.hh:790
Scalar invert3(Scalar const entry)
Definition: tools.hh:793
bool adjustDampingFactor(Grid &grid, Deformation const &deformation, Vector const &initialVolume, DeformationPolicy const &deformationPolicy, DampingPolicy &dampingPolicy)
Definition: tools.hh:908
void relaxVertex(Distance const &distance, Cell const &cell, Vector &x, Scalar const &h, Scalar eta=0.3, size_t rad=3)
Definition: tools.hh:896
Vector getLinearWeights(Vector const &weights, typename Vector::field_type(*fun)(typename Vector::field_type const))
Definition: tools.hh:800
Vector normal(Cell const &cell) const
Definition: tools.hh:863
Vector::field_type operator()(Cell const &cell, Vector const &x) const
Definition: tools.hh:845
Distance(Interpolation const &interpolation_)
Definition: tools.hh:840
Container storing normals together with some additional information.
Definition: tools.hh:94
Dune::FieldVector< Scalar, dim > Vector
Definition: tools.hh:97
void print(std::ostream &os)
Print some information on a collection of normals.
Definition: tools.hh:153
std::ostream & print(std::ostream &os=std::cout) const
Definition: tools.hh:106
NormalCollection(NormalCollection &&other)
Definition: tools.hh:101
friend std::ostream & operator<<(std::ostream &os, NormalCollection< Scalar, dim > const &collection)
Definition: tools.hh:160
NormalCollection & operator=(NormalCollection &&other)
Definition: tools.hh:137
std::ostream & print(std::ostream &os) const
Definition: tools.hh:304
NormalContainer & operator=(NormalContainer &&other)
Definition: tools.hh:299
friend std::ostream & operator<<(std::ostream &os, NormalContainer const &container)
Definition: tools.hh:315
InterpolationTools::NormalCollection< Scalar, 2 > EntryType
Definition: tools.hh:288
NormalContainer & operator=(NormalContainer &&other)
Definition: tools.hh:334
std::ostream & print(std::ostream &os) const
Definition: tools.hh:340
NormalContainer(size_t numberOfVertices=0, size_t numberOfEdges=0)
Definition: tools.hh:326
friend std::ostream & operator<<(std::ostream &os, NormalContainer const &container)
Definition: tools.hh:357
InterpolationTools::NormalCollection< Scalar, 3 > EntryType
Definition: tools.hh:323
Simple data container holding only vertex/edge normals and a threshold value for corner detection.
Definition: tools.hh:283
Threshold for feature detection.
Definition: tools.hh:489
void applyGradientThreshold(Scalar &gradient) const
Definition: tools.hh:492
ApplyGradientThreshold(Scalar const threshold=1.0)
Definition: tools.hh:490
Policy for inner boundaries. Considers all of them.
Definition: tools.hh:375
bool ignoreInnerBoundary(int tissue, int tissueNeighbour) const
Definition: tools.hh:376
Policy for inner boundaries. Considers all of them.
Definition: tools.hh:432
bool ignoreOuterBoundary(Face const &) const
Definition: tools.hh:434
ConstantDamping(Scalar const dampingFactor_=0.9)
Definition: tools.hh:638
Default policy for inner boundaries. Ignores them.
Definition: tools.hh:370
bool ignoreInnerBoundary(int tissue, int tissueNeighbour) const
Definition: tools.hh:371
Default policy for outer boundary. Ignores them.
Definition: tools.hh:426
bool ignoreOuterBoundary(Face const &) const
Definition: tools.hh:428
MergedPolicy(const Policies &... policies)
Definition: tools.hh:664
void applyGradientThreshold(Scalar &gradient) const
Definition: tools.hh:479
RelativeDeformation(Scalar scale_=0.25)
Definition: tools.hh:616
bool operator()(Entity const &entity, Scalar referenceVolume=-1.) const
Definition: tools.hh:626
void init(Entity const &entity)
Definition: tools.hh:620
Allows to specify parts of the inner boundary. Inner boundaries are characterized by a change of the ...
Definition: tools.hh:386
SpecifyInnerBoundary(std::vector< std::pair< int, int > > specifiedInterfaces)
Definition: tools.hh:391
void addInterface(int first, int second)
Add interface specified by two material ids.
Definition: tools.hh:403
bool ignoreInnerBoundary(int tissue, int tissueNeighbour) const
Check if interface specified by two material ids should be ignored.
Definition: tools.hh:408
void addInterface(std::pair< int, int > ids)
Add interface specified by two material ids.
Definition: tools.hh:397
Allows to specify parts of the outer boundary.
Definition: tools.hh:444
bool ignoreOuterBoundary(Face const &face) const
Check if outer bounday face should be ignored.
Definition: tools.hh:458
SpecifyOuterBoundary(IdVector const &boundaryIds, IdVector const &specifiedIds)
Definition: tools.hh:449