GetFEM++  5.3
bgeot_node_tab.cc
1 /*===========================================================================
2 
3  Copyright (C) 2007-2017 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, write to the Free Software Foundation,
18  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20 ===========================================================================*/
21 
22 
23 #include "getfem/bgeot_node_tab.h"
24 
25 namespace bgeot {
26 
27  bool node_tab::component_comp::operator()(size_type i1,size_type i2) const {
28  if (i1 == i2) return false;
29  const base_node &pt1((i1 == size_type(-1)) ? *c : (*vbn)[i1]);
30  const base_node &pt2((i2 == size_type(-1)) ? *c : (*vbn)[i2]);
31  unsigned d = pt1.size();
32  base_small_vector::const_iterator it = v.begin();
33  base_node::const_iterator it1 = pt1.begin(), it2 = pt2.begin();
34  scalar_type a(0);
35  for (size_type i = 0; i < d; ++i) a += (*it++) * (*it1++ - *it2++);
36  if (a != scalar_type(0)) return a < 0;
37  if (i1 == size_type(-1) || i2 == size_type(-1)) return false;
38  return i1 < i2;
39  }
40 
41  node_tab::component_comp::component_comp
42  (const dal::dynamic_tas<base_node> &vbn_, const base_node &c_, unsigned dim)
43  : vbn(&vbn_), c(&c_), v(dim) {
44  do gmm::fill_random(v); while (gmm::vect_norm2(v) == 0);
45  gmm::scale(v, scalar_type(1) / gmm::vect_norm2(v) );
46  }
47 
48  void node_tab::add_sorter(void) const {
49  if (sorters.size() > 1)
50  GMM_WARNING3("Multiple sort needed for node tab : " << sorters.size()+1);
51  sorters.push_back(sorter(component_comp(*this, c, dim_)));
52  for (dal::bv_visitor i(index()); !i.finished(); ++i)
53  sorters.back().insert(size_type(i));
54  }
55 
56  size_type node_tab::search_node(const base_node &pt,
57  const scalar_type radius) const {
58  if (card() == 0) 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(void) {
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  size_type id;
103  if (this->card() == 0) {
104  dim_ = pt.size();
105  id = dal::dynamic_tas<base_node>::add(pt);
106  for (size_type i = 0; i < sorters.size(); ++i) sorters[i].insert(id);
107  }
108  else {
109  GMM_ASSERT1(dim_ == pt.size(), "Nodes should have the same dimension");
110  id = remove_duplicated_nodes ? search_node(pt, radius) : size_type(-1);
111  if (id == size_type(-1)) {
112  id = dal::dynamic_tas<base_node>::add(pt);
113  for (size_type i = 0; i < sorters.size(); ++i) {
114  sorters[i].insert(id);
115  GMM_ASSERT3(sorters[i].size() == card(), "internal error");
116  }
117  }
118  }
119  return id;
120  }
121 
122  void node_tab::swap_points(size_type i, size_type j) {
123  if (i != j) {
124  bool existi = index().is_in(i), existj = index().is_in(j);
125  for (size_type is = 0; is < sorters.size(); ++is) {
126  if (existi) sorters[is].erase(i);
127  if (existj) sorters[is].erase(j);
128  }
129  dal::dynamic_tas<base_node>::swap(i, j);
130  for (size_type is = 0; is < sorters.size(); ++is) {
131  if (existi) sorters[is].insert(j);
132  if (existj) sorters[is].insert(i);
133  GMM_ASSERT3(sorters[is].size() == card(), "internal error");
134  }
135  }
136  }
137 
138  void node_tab::sup_node(size_type i) {
139  if (index().is_in(i)) {
140  for (size_type is = 0; is < sorters.size(); ++is) {
141  sorters[is].erase(i);
142  GMM_ASSERT3(sorters[is].size()+1 == card(), "Internal error");
143  // if (sorters[is].size()+1 != card()) { resort(); }
144  }
145  dal::dynamic_tas<base_node>::sup(i);
146 
147  }
148  }
149 
150  void node_tab::translation(const base_small_vector &V) {
151  for (dal::bv_visitor i(index()); !i.finished(); ++i) (*this)[i] += V;
152  resort();
153  }
154 
155  void node_tab::transformation(const base_matrix &M) {
156  base_small_vector w(M.nrows());
157  GMM_ASSERT1(gmm::mat_nrows(M) != 0 && gmm::mat_ncols(M) == dim(),
158  "invalid dimensions for the transformation matrix");
159  dim_ = unsigned(gmm::mat_nrows(M));
160  for (dal::bv_visitor i(index()); !i.finished(); ++i) {
161  w = (*this)[i];
162  gmm::resize((*this)[i], dim_);
163  gmm::mult(M,w,(*this)[i]);
164  }
165  resort();
166  }
167 
168  node_tab::node_tab(scalar_type prec_loose) {
169  max_radius = scalar_type(1e-60);
170  sorters.reserve(5);
171  prec_factor = gmm::default_tol(scalar_type()) * prec_loose;
172  eps = max_radius * prec_factor;
173  }
174 
175  node_tab::node_tab(const node_tab &t)
176  : dal::dynamic_tas<base_node>(t), sorters(), eps(t.eps),
177  prec_factor(t.prec_factor), max_radius(t.max_radius), dim_(t.dim_) {}
178 
179  node_tab &node_tab::operator =(const node_tab &t) {
180  dal::dynamic_tas<base_node>::operator =(t);
181  sorters = std::vector<sorter>();
182  eps = t.eps; prec_factor = t.prec_factor;
183  max_radius = t.max_radius; dim_ = t.dim_;
184  return *this;
185  }
186 
187 }
void clear(void)
reset the array, remove all points
void fill_random(L &l, double cfill)
*/
Definition: gmm_blas.h:154
Structure which dynamically collects points identifying points that are nearer than a certain very sm...
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
size_type search_node(const base_node &pt, const scalar_type radius=0) const
Search a node in the array.
size_type size(void) const
Number of allocated elements.
Definition: dal_basic.h:219
Store a set of points, identifying points that are nearer than a certain very small distance...
iterator end(void)
Iterator on the last + 1 element.
Definition: dal_basic.h:229
Basic Geometric Tools.
size_type add_node(const base_node &pt, const scalar_type radius=0, bool remove_duplicated_nodes=true)
Add a point to the array or identify it with a very close existing point.