GetFEM  5.5
bgeot_node_tab.cc
1 /*===========================================================================
2 
3  Copyright (C) 2007-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 
22 #include "getfem/bgeot_node_tab.h"
23 
24 namespace bgeot {
25 
26  bool node_tab::component_comp::operator()(size_type i1,size_type i2) const {
27  if (i1 == i2) return false;
28  const base_node &pt1((i1 == size_type(-1)) ? *c : (*vbn)[i1]);
29  const base_node &pt2((i2 == size_type(-1)) ? *c : (*vbn)[i2]);
30  unsigned d = pt1.size();
31  base_small_vector::const_iterator it = v.begin();
32  base_node::const_iterator it1 = pt1.begin(), it2 = pt2.begin();
33  scalar_type a(0);
34  for (size_type i = 0; i < d; ++i) a += (*it++) * (*it1++ - *it2++);
35  if (a != scalar_type(0)) return a < 0;
36  if (i1 == size_type(-1) || i2 == size_type(-1)) return false;
37  return i1 < i2;
38  }
39 
40  node_tab::component_comp::component_comp
41  (const dal::dynamic_tas<base_node> &vbn_, const base_node &c_, unsigned dim)
42  : vbn(&vbn_), c(&c_), v(dim) {
43  do gmm::fill_random(v); while (gmm::vect_norm2(v) == 0);
44  gmm::scale(v, scalar_type(1) / gmm::vect_norm2(v) );
45  }
46 
47  void node_tab::add_sorter(void) const {
48  if (sorters.size() > 1)
49  GMM_WARNING3("Multiple sort needed for node tab : " << sorters.size()+1);
50  sorters.push_back(sorter(component_comp(*this, c, dim_)));
51  for (dal::bv_visitor i(index()); !i.finished(); ++i)
52  sorters.back().insert(size_type(i));
53  }
54 
55  size_type node_tab::search_node(const base_node &pt,
56  const scalar_type radius) const {
57  if (card() == 0 || radius < 0.)
58  return size_type(-1);
59 
60  scalar_type eps_radius = std::max(eps, radius);
61  for (size_type is = 0; is < 5; ++is) {
62  if (is >= sorters.size()) add_sorter();
63 
64  c = pt - eps_radius * sorters[is].key_comp().v;
65 
66  sorter::const_iterator it = sorters[is].lower_bound(size_type(-1));
67  scalar_type up_bound
68  = gmm::vect_sp(pt, sorters[is].key_comp().v) + 2*eps_radius;
69  size_type count = 0;
70  // if (is > 0) cout << "begin loop " << " v = " << sorters[is].key_comp().v << "sp c = " << gmm::vect_sp(c, sorters[is].key_comp().v) << " eps_radius = " << eps_radius << " max_radius " << max_radius << endl;
71  for (; it != sorters[is].end() && count < 20; ++it, ++count) {
72 
73  const base_node &pt2 = (*this)[*it];
74 
75 // if (count > 0) {
76 // cout << "count " << count << " is = " << is << " pt = " << pt << " pt2 = " << pt2 << " sp = " << gmm::vect_sp(pt2, sorters[is].key_comp().v) << " spinit = " << gmm::vect_sp(pt, sorters[is].key_comp().v) << endl;
77 // }
78 
79  if (gmm::vect_dist2(pt, pt2) < eps_radius) return *it;
80  if (gmm::vect_sp(pt2, sorters[is].key_comp().v) > up_bound)
81  return size_type(-1);
82  }
83  if (it == sorters[is].end()) return size_type(-1);
84  }
85  GMM_ASSERT1(false, "Problem in node structure !!");
86  }
87 
88  void node_tab::clear() {
89  dal::dynamic_tas<base_node>::clear();
90  sorters = std::vector<sorter>();
91  max_radius = scalar_type(1e-60);
92  eps = max_radius * prec_factor;
93  }
94 
95  size_type node_tab::add_node(const base_node &pt,
96  const scalar_type radius,
97  bool remove_duplicated_nodes) {
98  scalar_type npt = gmm::vect_norm2(pt);
99  max_radius = std::max(max_radius, npt);
100  eps = max_radius * prec_factor;
101 
102  if (this->card() == 0)
103  dim_ = pt.size();
104  else
105  GMM_ASSERT1(dim_ == pt.size(), "Nodes should have the same dimension");
106  size_type id(-1);
107  if (remove_duplicated_nodes && radius >= 0.)
108  id = search_node(pt, radius);
109  if (id == size_type(-1)) {
110  id = dal::dynamic_tas<base_node>::add(pt);
111  for (size_type i = 0; i < sorters.size(); ++i) {
112  sorters[i].insert(id);
113  GMM_ASSERT3(sorters[i].size() == card(), "internal error");
114  }
115  }
116  return id;
117  }
118 
119  void node_tab::swap_points(size_type i, size_type j) {
120  if (i != j) {
121  bool existi = index().is_in(i), existj = index().is_in(j);
122  for (size_type is = 0; is < sorters.size(); ++is) {
123  if (existi) sorters[is].erase(i);
124  if (existj) sorters[is].erase(j);
125  }
126  dal::dynamic_tas<base_node>::swap(i, j);
127  for (size_type is = 0; is < sorters.size(); ++is) {
128  if (existi) sorters[is].insert(j);
129  if (existj) sorters[is].insert(i);
130  GMM_ASSERT3(sorters[is].size() == card(), "internal error");
131  }
132  }
133  }
134 
135  void node_tab::sup_node(size_type i) {
136  if (index().is_in(i)) {
137  for (size_type is = 0; is < sorters.size(); ++is) {
138  sorters[is].erase(i);
139  GMM_ASSERT3(sorters[is].size()+1 == card(), "Internal error");
140  // if (sorters[is].size()+1 != card()) { resort(); }
141  }
142  dal::dynamic_tas<base_node>::sup(i);
143 
144  }
145  }
146 
147  void node_tab::translation(const base_small_vector &V) {
148  for (dal::bv_visitor i(index()); !i.finished(); ++i) (*this)[i] += V;
149  resort();
150  }
151 
152  void node_tab::transformation(const base_matrix &M) {
153  base_small_vector w(M.nrows());
154  GMM_ASSERT1(gmm::mat_nrows(M) != 0 && gmm::mat_ncols(M) == dim(),
155  "invalid dimensions for the transformation matrix");
156  dim_ = unsigned(gmm::mat_nrows(M));
157  for (dal::bv_visitor i(index()); !i.finished(); ++i) {
158  w = (*this)[i];
159  gmm::resize((*this)[i], dim_);
160  gmm::mult(M,w,(*this)[i]);
161  }
162  resort();
163  }
164 
165  node_tab::node_tab(scalar_type prec_loose) {
166  max_radius = scalar_type(1e-60);
167  sorters.reserve(5);
168  prec_factor = gmm::default_tol(scalar_type()) * prec_loose;
169  eps = max_radius * prec_factor;
170  }
171 
172  node_tab::node_tab(const node_tab &t)
173  : dal::dynamic_tas<base_node>(t), sorters(), eps(t.eps),
174  prec_factor(t.prec_factor), max_radius(t.max_radius), dim_(t.dim_) {}
175 
176  node_tab &node_tab::operator =(const node_tab &t) {
177  dal::dynamic_tas<base_node>::operator =(t);
178  sorters = std::vector<sorter>();
179  eps = t.eps; prec_factor = t.prec_factor;
180  max_radius = t.max_radius; dim_ = t.dim_;
181  return *this;
182  }
183 
184 }
Structure which dynamically collects points identifying points that are nearer than a certain very sm...
void fill_random(L &l)
fill a vector or matrix with random value (uniform [-1,1]).
Definition: gmm_blas.h:129
void resize(V &v, size_type n)
*‍/
Definition: gmm_blas.h:209
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*‍/
Definition: gmm_blas.h:1663
Basic Geometric Tools.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48
Dynamic Array Library.