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 ) :
214 _trafo(trafo),
215 _domain_tol(domain_tol),
216 _newton_tol(Math::pow(Math::eps<DataType>(), DataType(0.9))),
218 {
219 init_bounding_boxes(bbox_tol);
220 }
221
224 {
225 }
226
238 {
239 // get the mesh
240 const auto& mesh = _trafo.get_mesh();
241 // get the vertex set
242 const auto& vtx_set = mesh.get_vertex_set();
243 // get the vertices-at-cell index set
244 const auto& vert_idx = mesh.template get_index_set<shape_dim, 0>();
245
246 // resize bounding boxes array
247 _bboxes.resize(std::size_t(mesh.get_num_elements()));
248
249 // loop over all cells
250 for(Index cell(0); cell < vert_idx.get_num_entities(); ++cell)
251 {
252 // get this cell's vertex indices
253 const auto& vidx = vert_idx[cell];
254
255 // get this cell's bounding box
256 BBox& bbox = _bboxes.at(std::size_t(cell));
257
258 // build cell bounding box
259 bbox[0] = bbox[1] = vtx_set[vidx[0]];
260 for(int i(1); i < vert_idx.get_num_indices(); ++i)
261 {
262 // get vertex and update bounding box
263 const auto& vtx = vtx_set[vidx[i]];
264 for(int j(0); j < world_dim; ++j)
265 {
266 Math::minimax(DataType(vtx[j]), bbox[0][j], bbox[1][j]);
267 }
268 }
269
270 // finally, incorporate tolerances
271 for(int j(0); j < world_dim; ++j)
272 {
273 // compute bbox dimension
274 DataType bb_extra = bbox_tol * (bbox[1][j] - bbox[0][j]);
275 bbox[0][j] -= bb_extra;
276 bbox[1][j] += bb_extra;
277 }
278 }
279 }
280
317 InvMapDataType unmap_point(const ImagePointType& img_point, bool ignore_failures = false) const
318 {
319 // store image point
320 InvMapDataType inv_data;
321 inv_data.img_point = img_point;
322
323 // find candidate cells
324 std::vector<Index> cells;
325 if(!this->find_candidate_cells(cells, img_point))
326 return inv_data;
327
328 // loop over all candidate cells
329 for(Index cell : cells)
330 {
331 // try to unmap the point by newton
333 if(!this->unmap_point_by_newton(dom_point, img_point, cell))
334 {
335 // point unmapping failed!
336 if(ignore_failures)
337 continue;
338
339 // throw an inverse mapping error
340 throw InverseMappingError(dom_point, cell);
341 }
342
343 // check if the domain point is on the reference element
344 if(!this->test_domain_point(dom_point))
345 {
346 // nope ==> skip point
347 continue;
348 }
349
350 // okay
351 inv_data.cells.push_back(cell);
352 inv_data.dom_points.push_back(dom_point);
353 }
354
355 // found at least one cell?
356 return inv_data;
357 }
358
400 InvMapDataType unmap_point(const ImagePointType& img_point, const std::vector<Index>& cells, bool ignore_failures = false) const
401 {
402 // store image point
403 InvMapDataType inv_data;
404 inv_data.img_point = img_point;
405
406 if(cells.empty())
407 return inv_data;
408
409 // loop over all candidate cells
410 for(Index cell : cells)
411 {
412 // try to unmap the point by newton
414 if(!this->unmap_point_by_newton(dom_point, img_point, cell))
415 {
416 // point unmapping failed!
417 if(ignore_failures)
418 continue;
419
420 // throw an inverse mapping error
421 throw InverseMappingError(dom_point, cell);
422 }
423
424 // check if the domain point is on the reference element
425 if(!this->test_domain_point(dom_point))
426 {
427 // nope ==> skip point
428 continue;
429 }
430
431 // okay
432 inv_data.cells.push_back(cell);
433 inv_data.dom_points.push_back(dom_point);
434 }
435
436 // found at least one cell?
437 return inv_data;
438 }
439
463 bool find_candidate_cells(std::vector<Index>& cells, const ImagePointType& img_point) const
464 {
465 // loop over all cells/bounding boxes
466 for(std::size_t cell(0); cell < _bboxes.size(); ++cell)
467 {
468 const BBox& bbox = _bboxes.at(cell);
469
470 // check whether the point is in the bounding box
471 bool is_in = true;
472 for(int j(0); j < shape_dim; ++j)
473 {
474 if((img_point[j] < bbox[0][j]) || (img_point[j] > bbox[1][j]))
475 {
476 is_in = false;
477 break;
478 }
479 }
480
481 // point inside bounding box?
482 if(is_in)
483 cells.push_back(Index(cell));
484 }
485
486 return !cells.empty();
487 }
488
506 {
507 // define an evaluator
508 typedef typename TrafoType::template Evaluator<ShapeType, DataType>::Type TrafoEvaluator;
509 TrafoEvaluator trafo_eval(_trafo);
510
511 // for Newton iteration we need image points and inverse jacobians
512 static constexpr TrafoTags trafo_tags = TrafoTags::img_point|TrafoTags::jac_inv;
513
514 // define the trafo eval data
515 typename TrafoEvaluator::template ConfigTraits<trafo_tags>::EvalDataType trafo_data;
516
517 // initialize output domain point to cell centre
518 for(int i(0); i < shape_dim; ++i)
520
521 // compute squared tolerance
522 const DataType tol_sqr = Math::sqr(_newton_tol);
523
524 // no convergence yet
525 bool converged = false;
526
527 // prepare trafo evaluator
528 trafo_eval.prepare(cell);
529
530 // newton iteration
531 for(Index iter(0); iter < _newton_max_iter; ++iter)
532 {
533 // evaluate trafo in current point
534 trafo_eval(trafo_data, dom_point);
535
536 // compute image point distance vector
537 ImagePointType def = trafo_data.img_point - img_point;
538
539 // check defect for tolerance
540 if(def.norm_euclid_sqr() < tol_sqr)
541 {
542 converged = true;
543 break;
544 }
545
546 // update reference point by newton
547 dom_point -= trafo_data.jac_inv * def;
548 }
549
550 // finish trafo evaluator
551 trafo_eval.finish();
552
553 // Newton converged?
554 return converged;
555 }
556
567 {
568 return Intern::InverseMappingHelper<ShapeType>::is_on_ref(dom_point, _domain_tol);
569 }
570 }; // class InverseMapping
571
573 namespace Intern
574 {
575 template<int dim_>
576 struct InverseMappingHelper<Shape::Simplex<dim_>>
577 {
578 // checks whether p is on the reference cell
579 template<typename PT_, typename DT_>
580 static bool is_on_ref(const PT_& p, const DT_ tol)
581 {
582 // reference simplex: all coords are in range [0,1]
583 // and the sum of all coords is <= 1
584 DT_ s = DT_(0);
585 for(int i(0); i < dim_; ++i)
586 {
587 // coord outside range [-tol, 1+tol] ?
588 if((p[i] < -tol) || (p[i] > DT_(1)+tol))
589 return false;
590 s += p[i];
591 }
592 // coord sum <= 1+tol ?
593 return (s <= DT_(1) + tol);
594 }
595 };
596
597 template<int dim_>
598 struct InverseMappingHelper<Shape::Hypercube<dim_>>
599 {
600 // checks whether p is on the reference cell
601 template<typename PT_, typename DT_>
602 static bool is_on_ref(const PT_& p, const DT_ tol)
603 {
604 // reference hypercube: all coordinates are in range [-1,+1]
605 for(int i(0); i < dim_; ++i)
606 {
607 // coord outside range [-1-tol, +1+tol] ?
608 if((p[i] < -DT_(1)-tol) || (p[i] > DT_(1)+tol))
609 return false;
610 }
611 return true;
612 }
613 };
614 } // namespace Intern
616 } // namespace Trafo
617} // namespace FEAT
Base exception class.
Definition: exception.hpp:27
String class implementation.
Definition: string.hpp:46
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
InverseMapping(const TrafoType &trafo, DataType bbox_tol=DataType(1E-2), DataType domain_tol=DataType(1E-4))
Constructor.
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.
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:944
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