GetFEM++  5.3
bgeot_geotrans_inv.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2000-2017 Yves Renard
5 
6  This file is a part of GetFEM++
7 
8  GetFEM++ is free software; you can redistribute it and/or modify it
9  under the terms of the GNU Lesser General Public License as published
10  by the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You should have received a copy of the GNU Lesser General Public License
18  along with this program; if not, write to the Free Software Foundation,
19  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, you may use this file as it is a part of a free
22  software library without restriction. Specifically, if other files
23  instantiate templates or use macros or inline functions from this file,
24  or you compile this file and link it with other files to produce an
25  executable, this file does not by itself cause the resulting executable
26  to be covered by the GNU Lesser General Public License. This exception
27  does not however invalidate any other reasons why the executable file
28  might be covered by the GNU Lesser General Public License.
29 
30 ===========================================================================*/
31 
32 /**@file bgeot_geotrans_inv.h
33  @author Yves Renard <Yves.Renard@insa-lyon.fr>
34  @date December 20, 2000.
35  @brief Inversion of geometric transformations.
36 
37  Inversion means: given a set of convexes and a point, find:
38 
39  - a subset of candidate convexes, which are likely to contain the
40  point (using bgeot::kdtree).
41 
42  - on these candidate convexes, invert the geometric
43  transformation, i.e. find the corresponding coordinates on the
44  reference element.
45 
46  Inversion of a geometric transformation is not a trivial task,
47  especially with non-linear geometric transformations. This is the
48  central part of interpolation routines from a getfem::mesh_fem onto
49  another.
50 */
51 
52 #ifndef BGEOT_GEOTRANS_INV_H__
53 #define BGEOT_GEOTRANS_INV_H__
54 
55 #include "bgeot_geometric_trans.h"
56 #include "bgeot_small_vector.h"
57 #include "bgeot_kdtree.h"
58 
59 namespace bgeot {
60  class geotrans_inv_convex;
61 
62  struct nonlinear_storage_struct {
63  base_node diff;
64  base_node x_real;
65  base_node x_ref;
66  bool project_into_element;
67 
68  struct linearised_structure {
69  linearised_structure(
70  const convex_ind_ct &direct_points_indices,
71  const stored_point_tab &reference_nodes,
72  const std::vector<base_node> &real_nodes);
73  void invert(const base_node &x_real, base_node &x_ref,
74  scalar_type IN_EPS) const;
75 
76  base_matrix K_ref_linear;
77  base_matrix B_linear;
78  base_node P_linear;
79  base_node P_ref_linear;
80  mutable base_node diff;
81  mutable base_node diff_ref;
82  };
83 
84  std::shared_ptr<linearised_structure> plinearised_structure = nullptr;
85  };
86  /**
87  does the inversion of the geometric transformation for a given convex
88  */
90  size_type N, P;
91  base_matrix G, pc, K, B, CS;
92  pgeometric_trans pgt = nullptr;
93  scalar_type EPS;
94  nonlinear_storage_struct nonlinear_storage;
95 
96  public:
97  const base_matrix &get_G() const { return G; }
98  geotrans_inv_convex(scalar_type e=10e-12, bool project_into_element=false) :
99  N(0), P(0), pgt(0), EPS(e)
100  { this->nonlinear_storage.project_into_element = project_into_element; }
101 
102  template<class TAB> geotrans_inv_convex(const convex<base_node, TAB> &cv,
103  pgeometric_trans pgt_,
104  scalar_type e=10e-12,
105  bool project_into_element = false)
106  : N(0), P(0), pgt(0), EPS(e) {
107  this->nonlinear_storage.project_into_element = project_into_element;
108  init(cv.points(),pgt_);
109  }
110 
111  geotrans_inv_convex(const std::vector<base_node> &nodes,
112  pgeometric_trans pgt_,
113  scalar_type e=10e-12,
114  bool project_into_element = false)
115  : N(0), P(0), pgt(0), EPS(e) {
116  this->nonlinear_storage.project_into_element = project_into_element;
117  init(nodes,pgt_);
118  }
119 
120  void set_projection_into_element(bool activate);
121 
122  template<class TAB> void init(const TAB &nodes, pgeometric_trans pgt_);
123 
124  /**
125  given the node on the real element, returns the node on the
126  reference element (even if it is outside of the ref. convex).
127 
128  If the geometric transformation is not invertible at point n,
129  an exception is thrown.
130 
131  @return true if the n is inside the convex
132 
133  @param n node on the real element
134 
135  @param n_ref computed node on the reference convex
136 
137  @param IN_EPS a threshold.
138  */
139  bool invert(const base_node& n, base_node& n_ref,
140  scalar_type IN_EPS=1e-12);
141 
142  /**
143  given the node on the real element, returns the node
144  on the reference element (even if it is outside of the ref. convex).
145 
146  This version will not throw an exception if the geometric
147  transformation is not invertible at point n.
148 
149  @return true if the n is inside the convex
150 
151  @param n node on the real element
152 
153  @param n_ref computed node on the reference convex
154 
155  @param converged on output, will be set to true if the
156  geometric transformation could be inverted.
157 
158  @param IN_EPS a threshold.
159  */
160  bool invert(const base_node& n, base_node& n_ref, bool &converged,
161  scalar_type IN_EPS=1e-12);
162  private:
163  bool invert_lin(const base_node& n, base_node& n_ref, scalar_type IN_EPS);
164  bool invert_nonlin(const base_node& n, base_node& n_ref,
165  scalar_type IN_EPS, bool &converged, bool throw_except);
166  void update_B();
167 
168  friend class geotrans_inv_convex_bfgs;
169  };
170 
171  template<class TAB>
172  void geotrans_inv_convex::init(const TAB &nodes, pgeometric_trans pgt_) {
173  bool geotrans_changed = (pgt != pgt_); if (geotrans_changed) pgt = pgt_;
174  GMM_ASSERT3(!nodes.empty(), "empty points!");
175  if (N != nodes[0].size())
176  { N = nodes[0].size(); geotrans_changed = true; }
177  if (geotrans_changed) {
178  P = pgt->structure()->dim();
179  pc.resize(pgt->nb_points() , P);
180  K.resize(N,P); B.resize(N,P); CS.resize(P,P);
181  G.resize(N, pgt->nb_points());
182  }
183  vectors_to_base_matrix(G, nodes);
184  if (pgt->is_linear()) {
185  if (geotrans_changed) {
186  base_node Dummy(P);
187  pgt->poly_vector_grad(Dummy, pc);
188  }
189  // computation of the pseudo inverse
190  update_B();
191  } else {
192  this->nonlinear_storage.diff.resize(N);
193  this->nonlinear_storage.x_real.resize(N);
194  this->nonlinear_storage.x_ref.resize(P);
195 
196  if (pgt->complexity() > 1) {
197  std::vector<base_node> real_nodes(nodes.begin(), nodes.end());
198  this->nonlinear_storage.plinearised_structure
199  = std::make_shared<nonlinear_storage_struct::linearised_structure>
200  (pgt->structure()->ind_dir_points(), pgt->geometric_nodes(),
201  real_nodes);
202  }
203  }
204  }
205 
206 
207  /**
208  handles the geometric inversion for a given (supposedly quite large)
209  set of points
210  */
212  {
213  protected :
214  mutable kdtree tree;
215  scalar_type EPS;
217  public :
218  void clear(void) { tree.clear(); }
219  /// Add the points contained in c to the list of points.
220  template<class CONT> void add_points(const CONT &c) {
221  tree.reserve(std::distance(c.begin(),c.end()));
222  typename CONT::const_iterator it = c.begin(), ite = c.end();
223  for (; it != ite; ++it) tree.add_point(*it);
224  }
225 
226  /// Number of points.
227  size_type nb_points(void) const { return tree.nb_points(); }
228  /// Add point p to the list of points.
229  size_type add_point(base_node p) { return tree.add_point(p); }
230  void add_point_with_id(base_node p,size_type id)
231  { tree.add_point_with_id(p,id); }
232 
233  /// Find all the points present in the box between min and max.
235  const base_node &min,
236  const base_node &max) const {
237  tree.points_in_box(ipts, min, max);
238  return ipts.size();
239  }
240 
241  /** Search all the points in the convex cv, which is the transformation
242  * of the convex cref via the geometric transformation pgt.
243  *
244  * IMPORTANT : It is assumed that the whole convex is include in the
245  * minmax box of its nodes times a factor 1.2. If the transformation is
246  * linear, the factor is 1.0.
247  *
248  * @param cv the convex points (as given by getfem_mesh::convex(ic)).
249  *
250  * @param pgt the geometric trans (as given by
251  * getfem_mesh::trans_of_convex(ic)).
252  *
253  * @param pftab container for the coordinates of points in the reference
254  * convex (should be of size nb_points())
255  *
256  * @param itab the indices of points found in the convex.
257  *
258  * @param bruteforce use a brute force search(only for debugging purposes).
259  *
260  * @return the number of points in the convex (i.e. the size of itab,
261  * and pftab)
262  */
263  template<class TAB, class CONT1, class CONT2>
264  size_type points_in_convex(const convex<base_node, TAB> &cv,
265  pgeometric_trans pgt,
266  CONT1 &pftab, CONT2 &itab,
267  bool bruteforce=false);
268 
269  geotrans_inv(scalar_type EPS_ = 10E-12) : EPS(EPS_) {}
270  };
271 
272 
273 
274  template<class TAB, class CONT1, class CONT2>
276  pgeometric_trans pgt,
277  CONT1 &pftab, CONT2 &itab,
278  bool bruteforce) {
279  base_node min, max; /* bound of the box enclosing the convex */
280  size_type nbpt = 0; /* nb of points in the convex */
281  kdtree_tab_type boxpts;
282  bounding_box(min, max, cv.points(), pgt);
283  for (size_type k=0; k < min.size(); ++k) { min[k] -= EPS; max[k] += EPS; }
284  gic.init(cv.points(),pgt);
285  /* get the points in a box enclosing the convex */
286  if (!bruteforce) points_in_box(boxpts, min, max);
287  else boxpts = tree.points();
288  /* and invert the geotrans, and check if the obtained point is
289  inside the reference convex */
290  for (size_type l = 0; l < boxpts.size(); ++l) {
291  // base_node pt_ref;
292  if (gic.invert(boxpts[l].n, pftab[nbpt], EPS)) {
293  itab[nbpt++] = boxpts[l].i;
294  }
295  }
296  return nbpt;
297  }
298 
299 
300 
301 
302 
303 } /* end of namespace bgeot. */
304 
305 
306 #endif /* BGEOT_GEOMETRIC_TRANSFORMATION_H__ */
void add_points(const CONT &c)
Add the points contained in c to the list of points.
Geometric transformations on convexes.
Small (dim < 8) vectors.
size_type points_in_box(kdtree_tab_type &ipts, const base_node &min, const base_node &max) const
Find all the points present in the box between min and max.
size_type add_point(base_node p)
Add point p to the list of points.
does the inversion of the geometric transformation for a given convex
handles the geometric inversion for a given (supposedly quite large) set of points ...
generic definition of a convex ( bgeot::convex_structure + vertices coordinates ) ...
Definition: bgeot_convex.h:50
Balanced tree over a set of points.
Definition: bgeot_kdtree.h:103
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
size_type points_in_convex(const convex< base_node, TAB > &cv, pgeometric_trans pgt, CONT1 &pftab, CONT2 &itab, bool bruteforce=false)
Search all the points in the convex cv, which is the transformation of the convex cref via the geomet...
size_type nb_points(void) const
Number of points.
void add_point_with_id(const base_node &n, size_type i)
insert a new point, with an associated number.
Definition: bgeot_kdtree.h:117
void clear()
reset the tree, remove all points
Definition: bgeot_kdtree.h:110
Basic Geometric Tools.
size_type add_point(const base_node &n)
insert a new point
Definition: bgeot_kdtree.h:113
Simple implementation of a KD-tree.
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
std::vector< index_node_pair > kdtree_tab_type
store a set of points with associated indexes.
Definition: bgeot_kdtree.h:69