Medusa  1.1
Coordinate Free Mehless Method implementation
DomainDiscretization.hpp
Go to the documentation of this file.
1 #ifndef MEDUSA_BITS_DOMAINS_DOMAINDISCRETIZATION_HPP_
2 #define MEDUSA_BITS_DOMAINS_DOMAINDISCRETIZATION_HPP_
3 
11 #include <cmath>
13 #include "DomainShape.hpp"
14 #include "ShapeUnion.hpp"
15 #include "ShapeDifference.hpp"
16 #include "UnknownShape.hpp"
17 
18 namespace mm {
19 
20 template <class vec_t>
22  int N = size();
23  Range<int> sizes(N);
24  for (int i = 0; i < N; ++i) {
25  sizes[i] = supportSize(i);
26  }
27  return sizes;
28 }
29 
30 template <class vec_t>
32  assert_msg(0 <= i && i <= size(), "Index %d out of range [0, %d)", i, size());
33  assert_msg(types_[i] < 0, "Node %d must be a boundary node, got type %d.", i, types_[i]);
34  assert_msg(boundary_map_[i] != -1, "Node %d does not have a normal. Maybe you manually set"
35  " supports and positions instead of using addInternalNode* methods?", i);
36  return normals_[boundary_map_[i]];
37 }
38 
39 template <class vec_t>
40 const vec_t& DomainDiscretization<vec_t>::normal(int i) const {
41  assert_msg(0 <= i && i <= size(), "Index %d out of range [0, %d)", i, size());
42  assert_msg(types_[i] < 0, "Node %d must be a boundary node, got type %d.", i, types_[i]);
43  assert_msg(boundary_map_[i] != -1, "Node %d does not have a normal. Maybe you manually set"
44  " supports and positions instead of using addInternalNode* methods?", i);
45  return normals_[boundary_map_[i]];
46 }
47 
48 template <class vec_t>
49 int DomainDiscretization<vec_t>::addInternalNode(const vec_t& point, int type) {
50  assert_msg(type > 0, "This function is for adding internal points, but got type %d, which is "
51  "not positive. Use addBoundaryNode to add boundary nodes.", type);
52  return addNode(point, type);
53 }
54 
55 template <class vec_t>
57  const vec_t& point, int type, const vec_t& normal) {
58  assert_msg(type < 0, "Type of boundary points must be negative, got %d.", type);
59  int idx = addNode(point, type);
60  boundary_map_[idx] = normals_.size();
61  normals_.push_back(normal);
62  return idx;
63 }
64 
65 template <class vec_t>
66 int DomainDiscretization<vec_t>::addNode(const vec_t& point, int type) {
67  positions_.push_back(point);
68  types_.push_back(type);
69  support_.emplace_back();
70  boundary_map_.push_back(-1);
71  return positions_.size()-1;
72 }
73 
74 template <class vec_t>
75 void DomainDiscretization<vec_t>::changeToBoundary(int i, const vec_t& point, int type,
76  const vec_t& normal) {
77  assert_msg(0 <= i && i < size(), "Index %d out of range [0, %d).", i, size());
78  assert_msg(types_[i] >= 0, "Point %d is already a boundary point with type %d.", i,
79  types_[i]);
80  assert_msg(type < 0, "New type must be negative, got %d.", type);
81  positions_[i] = point;
82  types_[i] = type;
83  boundary_map_[i] = normals_.size();
84  normals_.push_back(normal);
85 }
86 
87 template <class vec_t>
88 void DomainDiscretization<vec_t>::changeToInterior(int i, const vec_t& point, int type) {
89  assert_msg(0 <= i && i < size(), "Index %d out of range [0, %d).", i, size());
90  assert_msg(types_[i] <= 0, "Point %d is already an interior point with type %d.", i, types_[i]);
91  assert_msg(type > 0, "New type must be positive, got %d.", type);
92  positions_[i] = point;
93  types_[i] = type;
94  normals_.remove({boundary_map_[i]});
95  for (int idx = 0; idx < boundary_map_.size(); ++idx) {
96  if (boundary_map_[idx] != -1 && boundary_map_[idx] > boundary_map_[i]) {
97  boundary_map_[idx] -= 1;
98  }
99  }
100  boundary_map_[i] = -1;
101 }
102 
103 template <class vec_t>
105  indexes_t indexes(d.size());
106  for (int i = 0; i < d.size(); ++i) {
107  if (d.type(i) < 0) {
108  indexes[i] = addBoundaryNode(d.pos(i), d.type(i), d.normal(i));
109  } else {
110  indexes[i] = addInternalNode(d.pos(i), d.type(i));
111  }
112  }
113  return indexes;
114 }
115 
116 template <class vec_t>
118  int n = size();
119  Range<bool> remove_mask(n, false);
120  remove_mask[to_remove] = true;
121  Range<int> remove_normals;
122  for (int i = 0; i < n; ++i) {
123  if (boundary_map_[i] >= 0 && remove_mask[i]) { // boundary node that has to be removed
124  remove_normals.push_back(boundary_map_[i]);
125  } else if (boundary_map_[i] >= 0) {
126  boundary_map_[i] -= remove_normals.size();
127  }
128  }
129  normals_.remove(remove_normals);
130  boundary_map_.remove(to_remove);
131  types_.remove(to_remove);
132  positions_.remove(to_remove);
133  if (support_.size() == n) support_.remove(to_remove);
134 }
135 
136 template <class vec_t>
138  return addGhostNodes([=](const vec_t&) { return h; }, type);
139 }
140 
141 template <class vec_t>
143  scalar_t h, int type, const indexes_t& indexes) {
144  return addGhostNodes([=](const vec_t&) { return h; }, type, indexes);
145 }
146 
147 template <class vec_t>
148 template <typename func_t>
150  return addGhostNodes(h, type, boundary());
151 }
152 
153 template <class vec_t>
154 template <typename func_t>
156  Range<int> gh(size(), -1);
157  for (int i : idx) {
158  assert_msg(0 <= i && i < size(), "Index %d out of range [0, %d)", i, size());
159  assert_msg(types_[i] < 0, "Only boundary nodes can have associated ghost nodes, "
160  "node %d has type %d.", i, types_[i]);
161  scalar_t ch = h(pos(i));
162  if (type > 0) gh[i] = addInternalNode(pos(i) + ch*normal(i), type);
163  else if (type < 0) gh[i] = addBoundaryNode(pos(i) + ch*normal(i), type, normal(i));
164  else if (type == 0) gh[i] = addNode(pos(i) + ch*normal(i), type);
165  }
166  return gh;
167 }
168 
169 template <class vec_t>
171  positions_.clear();
172  types_.clear();
173  support_.clear();
174  normals_.clear();
175  boundary_map_.clear();
176 }
177 
178 template <class vec_t>
180  int N = size();
181  assert_msg(N == types_.size(), "Number of node type entries (%d) not equal to domain size "
182  "(%d).", types_.size(), N);
183  assert_msg(N == boundary_map_.size(), "Number of boundary map entries (%d) not equal to domain"
184  " size (%d).", types_.size(), N);
185  assert_msg(N == support_.size(), "Number of node supports (%d) not equal to domain size "
186  "(%d).", types_.size(), N);
187  assert_msg(N == positions_.size(), "Number of node positions (%d) not equal to domain size "
188  "(%d).", types_.size(), N);
189  int num_bnd = 0;
190  for (int i = 0; i < N; ++i) {
191  if (types_[i] < 0) {
192  assert_msg(0 <= boundary_map_[i] && boundary_map_[i] < normals_.size(),
193  "Boundary map index %d of node %d must lie in interval [0, %d).",
194  boundary_map_[i], i, normals_.size());
195  ++num_bnd;
196  } else if (types_[i] > 0) {
197  assert_msg(boundary_map_[i] == -1, "Expected boundary map of internal node %d "
198  "to be -1, got %d.", i, boundary_map_[i]);
199  }
200  assert_msg(shape_->contains(pos(i)), "Position %s at index %d is not contained "
201  "in the domain.", pos(i), i);
202  }
203  assert_msg(num_bnd == normals_.size(), "Number of boundary nodes not the same as number "
204  "of normals, got %d nodes with negative type, but %d normals.",
205  num_bnd, normals_.size());
206 }
207 
208 template <class vec_t>
209 std::ostream& DomainDiscretization<vec_t>::output_report(std::ostream& os) const {
210  int internal_count = (types_ > 0).size();
211  int boundary_count = (types_ < 0).size();
212  std::size_t mem = sizeof(*this);
213  std::size_t mem_pos = mem_used(positions_);
214  std::size_t mem_types = mem_used(types_);
215  std::size_t mem_supp = mem_used(support_);
216  int max_support_size = -1;
217  for (int i = 0; i < support_.size(); ++i) {
218  max_support_size = std::max(max_support_size, support_[i].size());
219  mem_supp += mem_used(support_[i]);
220  }
221  std::size_t mem_bnd_map = mem_used(boundary_map_);
222  std::size_t mem_normals = mem_used(normals_);
223  std::size_t mem_total = mem + mem_pos + mem_types + mem_supp + mem_bnd_map + mem_normals;
224  os << " dimension: " << dim << '\n'
225  << " shape: " << *shape_ << '\n'
226  << " number of points: " << size() << " of which " << internal_count
227  << " internal and " << boundary_count << " boundary\n"
228  << " max support size: ";
229  if (max_support_size == -1) os << "support not found yet";
230  else os << max_support_size;
231  os << "\n mem used total: " << mem2str(mem_total) << '\n'
232  << " pos & types: " << mem2str(mem_pos + mem_types) << '\n'
233  << " supp: " << mem2str(mem_supp) << '\n'
234  << " bnd & normals: " << mem2str(mem_bnd_map + mem_normals) << '\n';
235  return os;
236 }
237 
238 template <class vec_t>
240  shape_(shape) {}
241 
242 template <class vec_t>
244  const Range<int>& relevant) {
245  /* Chops off `d` from the current domain. Nodes in *this that are contained
246  * in `d` or are less than `0.75*dx` away from `d` are removed. No nodes are added. */
247 
248  const bool tree_ok = relevant.size() >= 2;
249  KDTree<vec_t> tree(d.positions_[relevant]);
250 
251  Range<int> to_remove;
252  for (int i = 0; i < size(); ++i) {
253  if (d.shape().contains(pos(i))) {
254  to_remove.push_back(i);
255  continue;
256  }
257  bool not_ok = false;
258  if (tree_ok) {
259  auto r = tree.query(pos(i));
260  int idx = r.first[0];
261  scalar_t dist = r.second[0];
262  scalar_t dx = tree.query(d.pos(relevant[idx]), 2).second[1];
263  not_ok = dist < 0.75*dx;
264  }
265  if (not_ok) {
266  to_remove.push_back(i);
267  }
268  }
269  removeNodes(std::move(to_remove));
270 }
271 
272 template <class vec_t>
275  /*
276  * Domain 1 is chopped off, and the relevant part of `d` is added. The added part is almost
277  * the whole domain, without any boundary nodes that are contained in domain 1.
278  */
279  Range<int> to_add;
280  for (int i = 0; i < d.size(); ++i) {
281  if (d.type(i) > 0 || !shape().contains(d.pos(i))) {
282  to_add.push_back(i);
283  }
284  }
285  chopOff(d, to_add);
286  for (int i : to_add) {
287  if (d.type(i) < 0) {
288  addBoundaryNode(d.pos(i), d.type(i), d.normal(i));
289  } else {
290  addInternalNode(d.pos(i), d.type(i));
291  }
292  }
293  shape_ = shape() + d.shape();
294  return *this;
295 }
296 
297 template <class vec_t>
299  // Domain 1 is chopped off, and the relevant part of the boundary of `d` is added.
300  Range<int> to_add;
301  for (int i = 0; i < d.size(); ++i) {
302  if (d.type(i) < 0 && shape().contains(d.pos(i))) {
303  to_add.push_back(i);
304  }
305  }
306  chopOff(d, to_add);
307  for (int i : to_add) {
308  addBoundaryNode(d.pos(i), d.type(i), -d.normal(i));
309  }
310  shape_ = shape() - d.shape();
311  return *this;
312 }
313 
314 template <class vec_t>
315 bool DomainDiscretization<vec_t>::contains(const vec_t& point) const {
316  assert_msg((shape_->hasContains()), "Domain shape does not have a `contains` method, "
317  "try using `discreteContains`.");
318  return shape_->contains(point);
319 }
320 
321 template <class vec_t>
322 template <typename search_structure_t>
324  const vec_t& point, const search_structure_t& search) const {
325  assert_msg((search.size() != 0), "Search structure should not be empty.");
326  int closest_index = search.query(point, 1).first[0];
327  auto closest_point = search.get(closest_index);
328  auto n = normals_[closest_index];
329 
330  return n.dot(point - closest_point) < 0;
331 }
332 
333 template <class vec_t>
334 template <typename search_structure_t>
335 bool DomainDiscretization<vec_t>::contains(const vec_t& p, const search_structure_t& search) const {
336  if (shape_->hasContains()) return shape_->contains(p);
337  else return discreteContains(p, search);
338 }
339 
340 template <class vec_t>
341 template <typename search_structure_t>
342 void DomainDiscretization<vec_t>::makeDiscreteContainsStructure(search_structure_t& search) const {
343  int size = boundary().size();
344  Range<vec_t> boundary_points(size);
345  for (int i = 0; i < boundary_map_.size(); i++) {
346  if (boundary_map_[i] == -1) continue;
347  boundary_points[boundary_map_[i]] = positions_[i];
348  }
349  search.reset(boundary_points);
350 }
351 
352 template <class vec_t>
353 template <typename hdf5_file>
355  const std::string& name) {
356  file.openGroup(name);
357  auto pos = file.readDouble2DArray("pos");
358  int n = pos.size();
359  UnknownShape<vec_t> shape;
360  DomainDiscretization<vec_t> domain(shape);
361  domain.positions_.resize(n);
362  vec_t low = 1e100;
363  vec_t high = -1e100;
364  for (int i = 0; i < n; ++i) {
365  assert_msg(pos[i].size() == dim, "Node %d has invalid number of coordinates: %s, "
366  "expected %d.", i, pos[i].size(), dim);
367  for (int j = 0; j < dim; ++j) {
368  domain.positions_[i][j] = pos[i][j];
369  if (pos[i][j] <= low[j]) low[j] = pos[i][j];
370  if (pos[i][j] >= high[j]) high[j] = pos[i][j];
371  }
372  }
373  domain.types_ = file.readIntArray("types");
374  int bnd_count = (domain.types_ < 0).size();
375  domain.boundary_map_ = file.readIntArray("bmap");
376  assert_msg(static_cast<int>((domain.boundary_map_ == -1).size()) == n - bnd_count,
377  "Number of nodes with boundary index (%d) in bmap is not the same as number "
378  "of nodes with negative type (%d).",
379  (domain.boundary_map_ == -1).size(), n - bnd_count);
380  auto normals = file.readDouble2DArray("normals");
381  assert_msg(static_cast<int>(normals.size()) == bnd_count,
382  "Number of normals (%d) must be equal to number of boundary nodes (%d).",
383  normals.size(), bnd_count);
384  domain.normals_.resize(normals.size());
385  for (int i = 0; i < bnd_count; ++i) {
386  assert_msg(normals[i].size() == dim, "Normal %d has invalid number of coordinates: %s, "
387  "expected %d.", i, normals[i].size(), dim);
388  for (int j = 0; j < dim; ++j) {
389  domain.normals_[i][j] = normals[i][j];
390  }
391  }
392  // boundary map consistency check
393  for (int i = 0; i < n; ++i) {
394  if (domain.types_[i] < 0) {
395  assert_msg(0 <= domain.boundary_map_[i] && domain.boundary_map_[i] < bnd_count,
396  "Normals list and boundary map inconsistent. Node %d with type %d "
397  "has boundary index %d, but the list of normals is only %d long.",
398  i, domain.types_[i], domain.boundary_map_[i], bnd_count);
399  } else {
400  assert_msg(domain.boundary_map_[i] == -1,
401  "Boundary map assigned a normal to an internal node %d with type %d, "
402  "bmap[%d] = %d, but should be -1.",
403  i, domain.types_[i], i, domain.boundary_map_[i]);
404  }
405  }
406  domain.support_.resize(n);
407  return domain;
408 }
409 
410 template <class vec_t>
412  shape_.reset(new TranslatedShape<vec_t>(*shape_, a));
413  for (int i = 0; i < size(); ++i) {
414  positions_[i] += a;
415  }
416  return *this;
417 }
418 
419 template <class vec_t>
421  const Eigen::Matrix<scalar_t, dim, dim>& Q) {
422  shape_.reset(new RotatedShape<vec_t>(*shape_, Q));
423  for (int i = 0; i < size(); ++i) {
424  positions_[i] = Q*positions_[i];
425  if (boundary_map_[i] != -1) normals_[boundary_map_[i]] = Q*normals_[boundary_map_[i]];
426  }
427  return *this;
428 }
429 
430 template <class vec_t>
432  assert_msg(dim == 2, "Angle rotation only available in 2D.");
433  scalar_t s = std::sin(angle);
434  scalar_t c = std::cos(angle);
435  Eigen::Matrix<double, dim, dim> Q; Q << c, -s, s, c;
436  return rotate(Q);
437 }
438 
439 template <class vec_t>
440 template <typename compare_t>
442  int N = size();
443  std::vector<std::pair<vec_t, int>> nodes(N);
444  for (int i = 0; i < N; ++i) nodes[i] = {pos(i), i};
445  std::sort(nodes.begin(), nodes.end(), cmp);
446  indexes_t permutation(N);
447  for (int i = 0; i < N; ++i) permutation[i] = nodes[i].second;
448  shuffleNodes(permutation);
449  return permutation;
450 }
451 
452 template <class vec_t>
454  int N = size();
455  assert_msg(static_cast<int>(permutation.size()) == N,
456  "Permutation size %d must be equal to domain size %d.", permutation.size(), N);
457  indexes_t pinv(N, -1);
458  for (int i = 0; i < N; ++i) {
459  assert_msg(0 <= permutation[i] && permutation[i] < N, "Invalid index %d in permutation.",
460  permutation[i]);
461  assert_msg(pinv[permutation[i]] == -1, "Duplicate index %d in permutation.",
462  permutation[i]);
463  pinv[permutation[i]] = i;
464  }
465  for (int i = 0; i < N; ++i) {
466  for (int j = 0; j < supportSize(i); ++j) {
467  support_[i][j] = pinv[support_[i][j]];
468  }
469  }
470  positions_ = positions_[permutation].asRange();
471  types_ = types_[permutation].asRange();
472  boundary_map_ = boundary_map_[permutation].asRange();
473  support_ = support_[permutation].asRange();
474 }
475 
476 } // namespace mm
477 
478 #endif // MEDUSA_BITS_DOMAINS_DOMAINDISCRETIZATION_HPP_
mm::DomainDiscretization::boundary_map_
Range< int > boundary_map_
Mapping index of a boundary node among all nodes, to its index among boundary nodes.
Definition: DomainDiscretization_fwd.hpp:85
mm
Root namespace for the whole library.
Definition: Gaussian.hpp:14
mm::DomainDiscretization::addNodes
indexes_t addNodes(const DomainDiscretization< vec_t > &d)
Add nodes from another discretization to this discretization.
Definition: DomainDiscretization.hpp:104
mm::DomainDiscretization
Class representing domain discretization along with an associated shape.
Definition: DomainDiscretization_fwd.hpp:46
mm::KDTree
Class representing a static k-d tree data structure.
Definition: KDTree_fwd.hpp:36
mm::DomainDiscretization::add
DomainDiscretization & add(const DomainDiscretization &d)
Merges given discretization to the current discretization.
Definition: DomainDiscretization.hpp:274
mm::DomainDiscretization::reorderNodes
Range< int > reorderNodes(const compare_t &cmp=compare_t())
Reorders nodes according to the compare function.
Definition: DomainDiscretization.hpp:441
mm::DomainDiscretization::chopOff
void chopOff(const DomainDiscretization< vec_t > &d, const Range< int > &relevant)
Remove a portion of this domain which is contained in d or is only dx away.
Definition: DomainDiscretization.hpp:243
mm::DomainDiscretization::clear
void clear()
Clears all data about this discretization.
Definition: DomainDiscretization.hpp:170
mm::DomainDiscretization::types_
Range< int > types_
Storing types of nodes aligned with positions.
Definition: DomainDiscretization_fwd.hpp:72
mm::DomainDiscretization::translate
DomainDiscretization & translate(const vec_t &a)
Translate the domain by a given vector a.
Definition: DomainDiscretization.hpp:411
mm::TranslatedShape
Class for working with translated domain shapes.
Definition: TranslatedShape_fwd.hpp:27
mm::DomainDiscretization::output_report
std::ostream & output_report(std::ostream &os=std::cout) const
Outputs a simple report about out domain, like number of nodes, support size.
Definition: DomainDiscretization.hpp:209
dim
@ dim
Number of elements of this matrix.
Definition: MatrixBaseAddons.hpp:14
mm::RotatedShape
Class for working with rotated (or mirrored) domain shapes.
Definition: RotatedShape_fwd.hpp:27
mm::DomainDiscretization::assert_is_valid
void assert_is_valid() const
Checks if domain is in valid state.
Definition: DomainDiscretization.hpp:179
assert_msg
#define assert_msg(cond,...)
Assert with better error reporting.
Definition: assert.hpp:75
mm::DomainDiscretization::support_
Range< Range< int > > support_
Attribute used to store support points of each node.
Definition: DomainDiscretization_fwd.hpp:60
mm::KDTree::query
std::pair< Range< int >, Range< scalar_t > > query(const vec_t &point, int k=1) const
Find k nearest neighbors to given point.
Definition: KDTree.hpp:16
mm::DomainDiscretization::addGhostNodes
Range< int > addGhostNodes(scalar_t h, int type=0)
Overload of addGhostNodes with constant h and adds ghost nodes to all boundary nodes.
Definition: DomainDiscretization.hpp:137
mm::DomainShape
Base class for geometric shapes of domains.
Definition: DomainShape_fwd.hpp:52
DomainShape.hpp
mm::DomainDiscretization::normal
const vec_t & normal(int i) const
Returns outside unit normal of i-th node.
Definition: DomainDiscretization.hpp:40
mm::DomainDiscretization::changeToBoundary
void changeToBoundary(int i, const vec_t &point, int type, const vec_t &normal)
Changes node i to boundary point with given type and normal.
Definition: DomainDiscretization.hpp:75
mm::DomainDiscretization::size
int size() const
Returns N, the number of nodes in this discretization.
Definition: DomainDiscretization_fwd.hpp:189
mm::DomainDiscretization::shape
const DomainShape< vec_t > & shape() const
Returns geometric shape of the underlying domain.
Definition: DomainDiscretization_fwd.hpp:162
mm::DomainDiscretization::type
int type(int i) const
Returns type of i-th node.
Definition: DomainDiscretization_fwd.hpp:158
mm::indexes_t
std::vector< int > indexes_t
Class representing a collection of indices.
Definition: Config.hpp:36
ShapeUnion.hpp
mm::DomainDiscretization::contains
bool contains(const vec_t &point) const
Returns true if point is inside the domain.
Definition: DomainDiscretization.hpp:315
mm::DomainDiscretization::makeDiscreteContainsStructure
void makeDiscreteContainsStructure(search_structure_t &search) const
Fills the search structure search with boundary points for use with contains() or discreteContains().
Definition: DomainDiscretization.hpp:342
mm::DomainDiscretization::discreteContains
bool discreteContains(const vec_t &point, const search_structure_t &search) const
A discrete version of contains using given boundary discretization.
Definition: DomainDiscretization.hpp:323
KDTree.hpp
assert.hpp
mm::DomainDiscretization::rotate
DomainDiscretization & rotate(const Eigen::Matrix< scalar_t, dim, dim > &Q)
Transform the domain by given orthogonal matrix Q.
Definition: DomainDiscretization.hpp:420
mm::DomainDiscretization::removeNodes
void removeNodes(const Range< int > &to_remove)
Remove nodes with given indices. This removes their types and potential normals as well.
Definition: DomainDiscretization.hpp:117
mm::DomainDiscretization::addInternalNode
int addInternalNode(const vec_t &point, int type)
Adds a single interior node with specified type to this discretization.
Definition: DomainDiscretization.hpp:49
mm::DomainDiscretization::pos
const vec_t & pos(int i) const
Returns the position of i-th node.
Definition: DomainDiscretization_fwd.hpp:129
mm::DomainDiscretization::subtract
DomainDiscretization & subtract(const DomainDiscretization &d)
Subtracts given discretized domain from *this.
Definition: DomainDiscretization.hpp:298
DomainDiscretization_fwd.hpp
mm::Range::size
int size() const
Returns number of elements.
Definition: Range_fwd.hpp:185
mm::DomainDiscretization::shuffleNodes
void shuffleNodes(const indexes_t &permutation)
Shuffles node order according to given permutation.
Definition: DomainDiscretization.hpp:453
mm::DomainDiscretization::load
static DomainDiscretization< vec_t > load(hdf5_file &file, const std::string &name)
Load discretization from a HD5 file.
Definition: DomainDiscretization.hpp:354
mm::DomainDiscretization::scalar_t
vec_t::Scalar scalar_t
Scalar data type used in computation.
Definition: DomainDiscretization_fwd.hpp:49
mm::DomainDiscretization::supportSizes
Range< int > supportSizes() const
Returns a vector of support sizes for each node.
Definition: DomainDiscretization.hpp:21
UnknownShape.hpp
mm::DomainDiscretization::DomainDiscretization
DomainDiscretization(const DomainShape< vec_t > &shape)
Construct an empty discretization for a given shape.
Definition: DomainDiscretization.hpp:239
mm::DomainDiscretization::normals_
Range< vec_t > normals_
List of normals of boundary nodes.
Definition: DomainDiscretization_fwd.hpp:97
mm::DomainDiscretization::positions_
Range< vec_t > positions_
Positions of internal discretization points.
Definition: DomainDiscretization_fwd.hpp:54
mm::UnknownShape
This class represents an unknown domain shape.
Definition: UnknownShape_fwd.hpp:27
mm::sort
container_t & sort(container_t &v)
Sorts a container inplace.
Definition: stdtypesutils.hpp:43
mm::Range< int >
mm::mem_used
std::size_t mem_used(const container_t &v)
Returns number of bytes the container uses in memory.
Definition: memutils.hpp:83
mm::DomainDiscretization::changeToInterior
void changeToInterior(int i, const vec_t &point, int type)
Changes node i to interior point with given type.
Definition: DomainDiscretization.hpp:88
mm::DomainDiscretization::addNode
int addNode(const vec_t &point, int type)
Helper for adding points to the domain, which keeps the object consistent.
Definition: DomainDiscretization.hpp:66
mm::DomainDiscretization::addBoundaryNode
int addBoundaryNode(const vec_t &point, int type, const vec_t &normal)
Adds a boundary node with given type and normal to the domain.
Definition: DomainDiscretization.hpp:56
ShapeDifference.hpp
mm::mem2str
std::string mem2str(std::size_t bytes)
Simple function to help format memory amounts for printing.
Definition: memutils.cpp:10