FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
inverse_mapping.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
8#include <kernel/trafo/mapping_base.hpp>
10
11#include <vector>
12
13namespace FEAT
14{
15 namespace Trafo
16 {
18 namespace Intern
19 {
20 template<typename Shape_>
21 struct InverseMappingHelper;
22 } // namespace Intern
24
34 public FEAT::Exception
35 {
36 public:
46 template<typename DT_, int n_, int s_>
48 Exception(String("Failed to unmap point ") + stringify(point) + " on cell " + stringify(cell))
49 {
50 }
51 }; // class InverseMappingError
52
70 template<typename DataType_, int shape_dim_, int world_dim_ = shape_dim_>
72 {
73 public:
78
81
83 std::vector<Index> cells;
84
86 std::vector<DomainPointType> dom_points;
87
90 {
91 }
92
94 InverseMappingData(const InverseMappingData& other) = default;
95
98 img_point(other.img_point),
99 cells(std::forward<std::vector<Index>>(other.cells)),
100 dom_points(std::forward<std::vector<DomainPointType>>(other.dom_points))
101 {
102 }
103
106 {
107 if(this != &other)
108 {
109 img_point = other.img_point;
110 cells = std::forward<std::vector<Index>>(other.cells);
111 dom_points = std::forward<std::vector<DomainPointType>>(other.dom_points);
112 }
113 return *this;
114 }
115
119 bool empty() const
120 {
121 return cells.empty();
122 }
123
125 std::size_t size() const
126 {
127 return cells.size();
128 }
129 }; // class InverseMappingData
130
155 template<typename Trafo_, typename DataType_>
157 {
158 public:
160 typedef Trafo_ TrafoType;
162 typedef DataType_ DataType;
164 typedef typename TrafoType::ShapeType ShapeType;
166 static constexpr int shape_dim = ShapeType::dimension;
168 static constexpr int world_dim = TrafoType::world_dim;
169
172
177
178 protected:
184 std::vector<BBox> _bboxes;
191
192 public:
210 explicit InverseMapping(const TrafoType& trafo,
211 DataType bbox_tol = DataType(1E-2),
212 DataType domain_tol = DataType(1E-4),
213 bool init_boxes = true
214 ) :
215 _trafo(trafo),
216 _domain_tol(domain_tol),
217 _newton_tol(Math::pow(Math::eps<DataType>(), DataType(0.9))),
219 {
220 if(init_boxes)
221 init_bounding_boxes(bbox_tol);
222 }
223
226 {
227 }
228
240 {
241 // get the mesh
242 const auto& mesh = _trafo.get_mesh();
243 // get the vertex set
244 const auto& vtx_set = mesh.get_vertex_set();
245 // get the vertices-at-cell index set
246 const auto& vert_idx = mesh.template get_index_set<shape_dim, 0>();
247
248 // resize bounding boxes array
249 _bboxes.resize(std::size_t(mesh.get_num_elements()));
250
251 // loop over all cells
252 for(Index cell(0); cell < vert_idx.get_num_entities(); ++cell)
253 {
254 // get this cell's vertex indices
255 const auto& vidx = vert_idx[cell];
256
257 // get this cell's bounding box
258 BBox& bbox = _bboxes.at(std::size_t(cell));
259
260 // build cell bounding box
261 bbox[0] = bbox[1] = vtx_set[vidx[0]];
262 for(int i(1); i < vert_idx.get_num_indices(); ++i)
263 {
264 // get vertex and update bounding box
265 const auto& vtx = vtx_set[vidx[i]];
266 for(int j(0); j < world_dim; ++j)
267 {
268 Math::minimax(DataType(vtx[j]), bbox[0][j], bbox[1][j]);
269 }
270 }
271
272 // finally, incorporate tolerances
273 for(int j(0); j < world_dim; ++j)
274 {
275 // compute bbox dimension
276 DataType bb_extra = bbox_tol * (bbox[1][j] - bbox[0][j]);
277 bbox[0][j] -= bb_extra;
278 bbox[1][j] += bb_extra;
279 }
280 }
281 }
282
319 InvMapDataType unmap_point(const ImagePointType& img_point, bool ignore_failures = false) const
320 {
321 // store image point
322 InvMapDataType inv_data;
323 inv_data.img_point = img_point;
324
325 // find candidate cells
326 std::vector<Index> cells;
327 if(!this->find_candidate_cells(cells, img_point))
328 return inv_data;
329
330 // loop over all candidate cells
331 for(Index cell : cells)
332 {
333 // try to unmap the point by newton
335 if(!this->unmap_point_by_newton(dom_point, img_point, cell))
336 {
337 // point unmapping failed!
338 if(ignore_failures)
339 continue;
340
341 // throw an inverse mapping error
342 throw InverseMappingError(dom_point, cell);
343 }
344
345 // check if the domain point is on the reference element
346 if(!this->test_domain_point(dom_point))
347 {
348 // nope ==> skip point
349 continue;
350 }
351
352 // okay
353 inv_data.cells.push_back(cell);
354 inv_data.dom_points.push_back(dom_point);
355 }
356
357 // found at least one cell?
358 return inv_data;
359 }
360
402 InvMapDataType unmap_point(const ImagePointType& img_point, const std::vector<Index>& cells, bool ignore_failures = false) const
403 {
404 // store image point
405 InvMapDataType inv_data;
406 inv_data.img_point = img_point;
407
408 if(cells.empty())
409 return inv_data;
410
411 // loop over all candidate cells
412 for(Index cell : cells)
413 {
414 // try to unmap the point by newton
416 if(!this->unmap_point_by_newton(dom_point, img_point, cell))
417 {
418 // point unmapping failed!
419 if(ignore_failures)
420 continue;
421
422 // throw an inverse mapping error
423 throw InverseMappingError(dom_point, cell);
424 }
425
426 // check if the domain point is on the reference element
427 if(!this->test_domain_point(dom_point))
428 {
429 // nope ==> skip point
430 continue;
431 }
432
433 // okay
434 inv_data.cells.push_back(cell);
435 inv_data.dom_points.push_back(dom_point);
436 }
437
438 // found at least one cell?
439 return inv_data;
440 }
441
465 bool find_candidate_cells(std::vector<Index>& cells, const ImagePointType& img_point) const
466 {
467 XASSERTM(_bboxes.size() == _trafo.get_mesh().get_num_elements(), "Boundingbox are not initilialized correctly");
468 // loop over all cells/bounding boxes
469 for(std::size_t cell(0); cell < _bboxes.size(); ++cell)
470 {
471 const BBox& bbox = _bboxes.at(cell);
472
473 // check whether the point is in the bounding box
474 bool is_in = true;
475 for(int j(0); j < shape_dim; ++j)
476 {
477 if((img_point[j] < bbox[0][j]) || (img_point[j] > bbox[1][j]))
478 {
479 is_in = false;
480 break;
481 }
482 }
483
484 // point inside bounding box?
485 if(is_in)
486 cells.push_back(Index(cell));
487 }
488
489 return !cells.empty();
490 }
491
509 {
510 // define an evaluator
511 typedef typename TrafoType::template Evaluator<ShapeType, DataType>::Type TrafoEvaluator;
512 TrafoEvaluator trafo_eval(_trafo);
513
514 // for Newton iteration we need image points and inverse jacobians
515 static constexpr TrafoTags trafo_tags = TrafoTags::img_point|TrafoTags::jac_inv;
516
517 // define the trafo eval data
518 typename TrafoEvaluator::template ConfigTraits<trafo_tags>::EvalDataType trafo_data;
519
520 // initialize output domain point to cell centre
521 for(int i(0); i < shape_dim; ++i)
523
524 // compute squared tolerance
525 const DataType tol_sqr = Math::sqr(_newton_tol);
526
527 // no convergence yet
528 bool converged = false;
529
530 // prepare trafo evaluator
531 trafo_eval.prepare(cell);
532
533 // newton iteration
534 for(Index iter(0); iter < _newton_max_iter; ++iter)
535 {
536 // evaluate trafo in current point
537 trafo_eval(trafo_data, dom_point);
538
539 // compute image point distance vector
540 ImagePointType def = trafo_data.img_point - img_point;
541
542 // check defect for tolerance
543 if(def.norm_euclid_sqr() < tol_sqr)
544 {
545 converged = true;
546 break;
547 }
548
549 // update reference point by newton
550 dom_point -= trafo_data.jac_inv * def;
551 }
552
553 // finish trafo evaluator
554 trafo_eval.finish();
555
556 // Newton converged?
557 return converged;
558 }
559
570 {
571 return Intern::InverseMappingHelper<ShapeType>::is_on_ref(dom_point, _domain_tol);
572 }
573 }; // class InverseMapping
574
576 namespace Intern
577 {
578 template<int dim_>
579 struct InverseMappingHelper<Shape::Simplex<dim_>>
580 {
581 // checks whether p is on the reference cell
582 template<typename PT_, typename DT_>
583 static bool is_on_ref(const PT_& p, const DT_ tol)
584 {
585 // reference simplex: all coords are in range [0,1]
586 // and the sum of all coords is <= 1
587 DT_ s = DT_(0);
588 for(int i(0); i < dim_; ++i)
589 {
590 // coord outside range [-tol, 1+tol] ?
591 if((p[i] < -tol) || (p[i] > DT_(1)+tol))
592 return false;
593 s += p[i];
594 }
595 // coord sum <= 1+tol ?
596 return (s <= DT_(1) + tol);
597 }
598 };
599
600 template<int dim_>
601 struct InverseMappingHelper<Shape::Hypercube<dim_>>
602 {
603 // checks whether p is on the reference cell
604 template<typename PT_, typename DT_>
605 static bool is_on_ref(const PT_& p, const DT_ tol)
606 {
607 // reference hypercube: all coordinates are in range [-1,+1]
608 for(int i(0); i < dim_; ++i)
609 {
610 // coord outside range [-1-tol, +1+tol] ?
611 if((p[i] < -DT_(1)-tol) || (p[i] > DT_(1)+tol))
612 return false;
613 }
614 return true;
615 }
616 };
617 } // namespace Intern
619 } // namespace Trafo
620} // namespace FEAT
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Base exception class.
Definition: exception.hpp:27
String class implementation.
Definition: string.hpp:47
Tiny Matrix class template.
Tiny Vector class template.
CUDA_HOST_DEVICE DataType norm_euclid_sqr() const
Computes the squared euclid norm of this vector.
Data structure for InverseMapping evaluations.
Tiny::Vector< DataType_, shape_dim_ > DomainPointType
the domain point type
InverseMappingData & operator=(InverseMappingData &&other)
move-assign operator
ImagePointType img_point
the image point that was unmapped
std::vector< Index > cells
the indices of the cells that intersect with the image point
InverseMappingData()
default constructor
InverseMappingData(const InverseMappingData &other)=default
use default copy constructor
std::vector< DomainPointType > dom_points
the domain points on each cell that map onto the image point
Tiny::Vector< DataType_, world_dim_ > ImagePointType
the image point type
InverseMappingData(InverseMappingData &&other)
move constructor
bool empty() const
Checks whether no cells were found.
Inverse Trafo Mapping Error class.
InverseMappingError(const Tiny::Vector< DT_, n_, s_ > &point, Index cell)
Constructor.
Inverse Trafo mapping class template.
std::vector< BBox > _bboxes
the array of cell bounding boxes
bool find_candidate_cells(std::vector< Index > &cells, const ImagePointType &img_point) const
Determines a set of candidate cells by a bounding-box test.
Index _newton_max_iter
maximum number of newton iterations for unmapping
void init_bounding_boxes(DataType bbox_tol)
Initializes the cell bounding boxes array.
Tiny::Matrix< DataType_, 2, world_dim > BBox
our bounding box type
static constexpr int shape_dim
the shape dimension
Trafo_ TrafoType
the underlying trafo type
bool unmap_point_by_newton(DomainPointType &dom_point, const ImagePointType &img_point, const Index cell) const
Unmaps a given point on a particular cell by Newton iteration.
DataType_ DataType
the datatype to be used
bool test_domain_point(const DomainPointType &dom_point) const
Tests whether a given domain point is on the reference element.
InverseMappingData< DataType, shape_dim, world_dim > InvMapDataType
the inverse mapping data type
InvMapDataType::DomainPointType DomainPointType
the domain point type
InvMapDataType unmap_point(const ImagePointType &img_point, const std::vector< Index > &cells, bool ignore_failures=false) const
Unmaps a given image point.
InvMapDataType::ImagePointType ImagePointType
the image point type
InvMapDataType unmap_point(const ImagePointType &img_point, bool ignore_failures=false) const
Unmaps a given image point.
InverseMapping(const TrafoType &trafo, DataType bbox_tol=DataType(1E-2), DataType domain_tol=DataType(1E-4), bool init_boxes=true)
Constructor.
static constexpr int world_dim
the world dimension
virtual ~InverseMapping()
virtual destructor
DataType _domain_tol
tolerance for unmapped domain coordinates
DataType _newton_tol
absolute tolerance for newton iteration
const TrafoType & _trafo
the trafo mapping
TrafoType::ShapeType ShapeType
the shape type
void minimax(T_ x, T_ &a, T_ &b)
Updates the minimum and maximum.
Definition: math.hpp:195
T_ sqr(T_ x)
Returns the square of a value.
Definition: math.hpp:95
FEAT namespace.
Definition: adjactor.hpp:12
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:993
std::uint64_t Index
Index data type.
TrafoTags
Trafo configuration tags enum.
Definition: eval_tags.hpp:22
@ img_point
specifies whether the trafo should supply image point coordinates
@ dom_point
specifies whether the trafo should supply domain point coordinates
@ jac_inv
specifies whether the trafo should supply inverse jacobian matrices
Reference cell traits structure.
Definition: shape.hpp:230