GetFEM  5.5
getfem_interpolation.cc
1 /*===========================================================================
2 
3  Copyright (C) 2001-2026 Yves Renard
4 
5  This file is a part of GetFEM
6 
7  GetFEM is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Lesser General Public License as published
9  by the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version along with the GCC Runtime Library
11  Exception either version 3.1 or (at your option) any later version.
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15  License and GCC Runtime Library Exception for more details.
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program. If not, see https://www.gnu.org/licenses/.
18 
19 ===========================================================================*/
20 
21 
23 
24 namespace getfem {
25 
26  size_type mesh_trans_inv::id_of_point(size_type ipt) const {
27 
28  if (!ids.empty()) {
29  const auto it = ids.find(ipt);
30  if (it != ids.end())
31  return it->second;
32  }
33  // otherwise assume that the point id is the point index
34  return ipt;
35  }
36 
37  void mesh_trans_inv::points_on_convex(size_type cv,
38  std::vector<size_type> &itab) const {
39  itab.resize(pts_in_cvx[cv].size()); size_type j = 0;
40  for (auto it = pts_in_cvx[cv].cbegin(); it != pts_in_cvx[cv].cend(); ++it)
41  itab[j++] = *it;
42  }
43 
44  size_type mesh_trans_inv::point_on_convex(size_type cv, size_type i) const {
45  auto it = pts_in_cvx[cv].cbegin();
46  for (size_type j = 0; it != pts_in_cvx[cv].cend() && j < i; ++it, ++j) {}
47  GMM_ASSERT1(it != pts_in_cvx[cv].cend(), "internal error");
48  return *it;
49  }
50 
51  void mesh_trans_inv::distribute(int extrapolation, mesh_region rg_source) {
52  // this function fills in these two data structures:
53  // pts_in_cvx[cv_i] --> set with indices of all points belonging to convex cv_i
54  // ref_coords[pt_i] --> local coordinates of point pt_i in the convex it belongs to
55  rg_source.from_mesh(msh);
56  rg_source.error_if_not_convexes();
57  bool all_convexes = (rg_source.id() == mesh_region::all_convexes().id());
58  bool projection_into_element(extrapolation == 0);
59 
60  size_type nbpts = nb_points();
61  size_type nbcvx = msh.nb_allocated_convex();
62  pts_in_cvx.clear();
63  pts_in_cvx.resize(nbcvx);
64  ref_coords.resize(nbpts);
65 
66  // ephemeral data containters
67  std::vector<size_type> cvx_of_pt(nbpts);
68  std::vector<double> dist(nbpts);
69  dal::bit_vector remaining_pts, cv_on_bound;
70  remaining_pts.add(0, nbpts);
71 
72  bool identity_map = all_convexes && (nbpts == msh.nb_points());
73 
74  // check for any overlapping mesh points
75  dal::bv_visitor ip(msh.points_index()); // used only for identity map
76  for (const bgeot::index_node_pair &ind_node : tree.points()) {
77  size_type mesh_pt(-1);
78  if (identity_map) {
79  GMM_ASSERT1(!ip.finished(), "internal error, not enouph points in mesh?");
80  base_node diff(msh.points()[ip]);
81  gmm::add(gmm::scaled(ind_node.n, -1.0), diff);
82  if (gmm::vect_norm2(diff) < EPS) {
83  mesh_pt = ip;
84  ++ip;
85  } else // give up identity map
86  identity_map = false;
87  }
88  if (!identity_map)
89  mesh_pt = msh.search_point(ind_node.n, 1e-6); // check within a tiny radius
90  if (mesh_pt != size_type(-1)) {
91  size_type cv = msh.first_convex_of_point(mesh_pt);
92  if (cv != size_type(-1)) {
93  bgeot::pgeometric_trans pgt = msh.trans_of_convex(cv);
94  gic.init(msh.points_of_convex(cv), pgt);
95  base_node pt_ref;
96  bool converged; // following invert should be trivial, converge in 1 iter
97  if (gic.invert(ind_node.n, pt_ref, converged, EPS,
98  projection_into_element)) { // this should always be true
99  double isin = pgt->convex_ref()->is_in(pt_ref);
100  size_type ind = ind_node.i;
101  pts_in_cvx[cv].insert(ind); // output
102  ref_coords[ind] = pt_ref; // output
103  cvx_of_pt[ind] = cv; // ephemeral
104  dist[ind] = isin; // ephemeral, should be zero or negative
105  remaining_pts.sup(ind); // ephemeral
106  }
107  }
108  }
109  }
110 
111  scalar_type mult = scalar_type(1);
112  do {
113  for (dal::bv_visitor j(rg_source.index()); !j.finished(); ++j) {
114  if (mult > scalar_type(1) && !(cv_on_bound.is_in(j)))
115  continue;
116  base_node min, max; /* bound of the box enclosing the convex */
117  bgeot::pgeometric_trans pgt = msh.trans_of_convex(j);
118  bounding_box(min, max, msh.points_of_convex(j), pgt);
119  for (size_type k=0; k < min.size(); ++k) {
120  min[k] -= EPS;
121  max[k] += EPS;
122  }
123  if (extrapolation == 2) { // find also points far outside the convex
124  if (mult == scalar_type(1)) // in the 1st pass mark all convexes on boundary
125  for (short_type f = 0; f < msh.nb_faces_of_convex(j); ++f) {
126  size_type neighbor_cv = msh.neighbor_of_convex(j, f);
127  if (!all_convexes && neighbor_cv != size_type(-1)) {
128  // check if the neighbor is also contained in rg_source ...
129  if (!rg_source.is_in(neighbor_cv))
130  cv_on_bound.add(j); // ... if not, treat the element as a boundary one
131  } else // boundary element of the overall mesh
132  cv_on_bound.add(j);
133  }
134  if (cv_on_bound.is_in(j)) {
135  scalar_type h = scalar_type(0);
136  for (size_type k=0; k < min.size(); ++k)
137  h = std::max(h, max[k] - min[k]);
138  for (size_type k=0; k < min.size(); ++k) {
139  min[k] -= mult*h;
140  max[k] += mult*h;
141  }
142  }
143  }
144  bgeot::kdtree_tab_type boxpts;
145  points_in_box(boxpts, min, max);
146  if (boxpts.size() > 0)
147  gic.init(msh.points_of_convex(j), pgt);
148  // check and treat all points found in the bounding box around convex j
149  for (const bgeot::index_node_pair &ind_node : boxpts) {
150  size_type ind = ind_node.i;
151  if (remaining_pts[ind] || dist[ind] > 0) {
152  base_node pt_ref;
153  bool converged;
154  bool gicisin = gic.invert(ind_node.n, pt_ref, converged, EPS,
155  projection_into_element);
156  bool toadd = extrapolation || gicisin;
157  double isin = pgt->convex_ref()->is_in(pt_ref);
158 
159  if (toadd && !(remaining_pts[ind])) {
160  if (isin < dist[ind])
161  pts_in_cvx[cvx_of_pt[ind]].erase(ind);
162  else
163  toadd = false;
164  }
165  if (toadd) {
166 // if (mult > 1.5) {
167 // cout << "adding " << ind << "ref_coord = " << pt_ref
168 // << " cv = " << j << " mult = " << mult << endl;
169 // }
170  pts_in_cvx[j].insert(ind); // output
171  ref_coords[ind] = pt_ref; // output
172  cvx_of_pt[ind] = j; // ephemeral
173  dist[ind] = isin; // ephemeral
174  remaining_pts.sup(ind); // ephemeral
175  }
176  }
177  }
178  }
179  mult *= scalar_type(2);
180  } while (remaining_pts.card() > 0 && extrapolation == 2);
181  }
182 } /* end of namespace getfem. */
183 
static mesh_region all_convexes()
provide a default value for the mesh_region parameters of assembly procedures etc.
Interpolation of fields from a mesh_fem onto another.
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*‍/
Definition: gmm_blas.h:1663
void add(const L1 &l1, L2 &l2)
*‍/
Definition: gmm_blas.h:1275
std::vector< index_node_pair > kdtree_tab_type
store a set of points with associated indexes.
Definition: bgeot_kdtree.h:67
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:72
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
GEneric Tool for Finite Element Methods.
store a point and the associated index for the kdtree.
Definition: bgeot_kdtree.h:58