NiHu  2.0
element.hpp
Go to the documentation of this file.
1 // This file is a part of NiHu, a C++ BEM template library.
2 //
3 // Copyright (C) 2012-2014 Peter Fiala <fiala@hit.bme.hu>
4 // Copyright (C) 2012-2014 Peter Rucz <rucz@hit.bme.hu>
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 
24 #ifndef ELEMENT_HPP_INCLUDED
25 #define ELEMENT_HPP_INCLUDED
26 
27 #include <boost/math/constants/constants.hpp>
28 
29 #include "../util/crtp_base.hpp"
30 #include "../tmp/bool.hpp"
31 #include "shapeset.hpp"
32 
33 #include <iostream>
34 
35 namespace NiHu
36 {
37 
40 {
41 public:
43  unsigned get_num(void) const
44  {
45  return m_num;
46  }
47 
49  unsigned get_ind1(void) const
50  {
51  return m_ind1;
52  }
53 
55  unsigned get_ind2(void) const
56  {
57  return m_ind2;
58  }
59 
62  unsigned num = 0, unsigned ind1 = 0, unsigned ind2 = 0) :
63  m_num(num), m_ind1(ind1), m_ind2(ind2)
64  {
65  }
66 
67  std::ostream &print_debug(std::ostream &os) const
68  {
69  return os << "Element overlapping info: " << std::endl
70  << "Number of coincident nodes: " << m_num << std::endl
71  << "Start index on element 1 : " << m_ind1 << " and on element 2 " << m_ind2;
72  }
73 
74 private:
76  unsigned m_num;
78  unsigned m_ind1, m_ind2;
79 };
80 
81 
83 template <class Derived, unsigned Order>
85 
87 namespace element_traits
88 {
90  template <class Derived>
91  struct name
92  {
93  static const std::string value;
94  };
95 
97  template <class Derived>
98  struct space_type;
99 
101  template <class Derived>
102  struct lset;
103 
105  template <class Derived>
107 
109  template <class Derived>
110  struct id
111  {
112  enum {
115  };
116  };
117 
119  template <class Derived, unsigned Order>
121  typename lset<Derived>::type,
122  Order
123  > {};
124 
126  template <class Derived>
127  struct coords_type
128  {
129  typedef Eigen::Matrix<
133  > type;
134  };
135 
137  template <class Derived, unsigned Order>
139  {
140  typedef Eigen::Matrix<
143  num_derivatives(Order, shape_set_traits::domain<typename lset<Derived>::type>::type::dimension)
144  > type;
145  };
146 
148  template <class Derived, unsigned Order>
150  typename location_complexity<Derived, Order>::type,
151  location_impl<Derived, Order>,
152  typename coords_type<Derived>::type,
153  typename shape_set_traits::domain<
154  typename lset<Derived>::type
155  >::type::xi_t
156  > {};
157 
159  template <class Derived, unsigned Order>
161  {
162  typedef typename location_factory_functor<
163  Derived,
164  Order
165  >::type::return_type type;
166  };
167 }
168 
170 typedef Eigen::Matrix<unsigned, 1, 1> elem_id_t;
171 
172 
173 template <class Derived, unsigned Order>
174 class location_impl
175 {
176 public:
177  typedef typename element_traits::lset<Derived>::type lset_t;
178  typedef typename element_traits::coords_type<Derived>::type coords_t;
179  typedef typename element_traits::location_value_type<Derived, Order>::type ret_t;
180  typedef typename shape_set_traits::domain<lset_t>::type::xi_t xi_t;
181 
182  static ret_t eval(coords_t const &coords, xi_t const &xi)
183  {
184  return coords * lset_t::template eval_shape<Order>(xi);
185  }
186 };
187 
188 
193 template <class Derived>
195 {
196 public:
198  typedef Derived type;
199 
205  typedef typename space_t::scalar_t scalar_t;
206 
208  typedef typename lset_t::domain_t domain_t;
210  typedef typename domain_t::xi_t xi_t;
211 
212  enum {
216  num_nodes = lset_t::num_nodes,
217  };
218 
220  typedef typename element_traits::location_value_type<Derived, 0>::type x_t;
222  typedef typename element_traits::location_return_type<Derived, 0>::type x_return_type;
224  typedef typename element_traits::location_value_type<Derived, 1>::type dx_t;
226  typedef typename element_traits::location_return_type<Derived, 1>::type dx_return_type;
228  typedef typename element_traits::location_value_type<Derived, 2>::type ddx_t;
230  typedef typename element_traits::location_return_type<Derived, 2>::type ddx_return_type;
231 
233  typedef Eigen::Matrix<unsigned, num_nodes, 1> nodes_t;
235  typedef typename element_traits::coords_type<Derived>::type coords_t;
237  typedef elem_id_t id_t;
238 
239 protected:
250 
257 
258 public:
260 
263 
270  element_base(coords_t const &coords, unsigned id = 0, nodes_t const &nodes = nodes_t())
271  :m_id((id_t()<<id).finished())
272  , m_nodes(nodes)
273  , m_coords(coords)
275  , x_computer(m_coords, xi_t())
278  {
279  // compute linear size estimate (average edge length)
280  scalar_t d = 0.0;
281  for (unsigned e = 0; e < domain_t::num_edges; ++e)
282  {
283  auto const &edge = domain_t::get_edge(e);
284  x_t x0 = get_x(domain_t::get_corner(edge[0]));
285  x_t x1 = get_x(domain_t::get_corner(edge[1]));
286  d += (x1-x0).norm();
287  }
288  d /= scalar_t(domain_t::num_edges);
290  }
291 
296  id_t const &get_id(void) const
297  {
298  return m_id;
299  }
300 
305  nodes_t const &get_nodes(void) const
306  {
307  return m_nodes;
308  }
309 
314  coords_t const &get_coords(void) const
315  {
316  return m_coords;
317  }
318 
324  x_return_type get_x(xi_t const &xi) const
325  {
326  return x_computer(m_coords, xi);
327  }
328 
334  dx_return_type get_dx(xi_t const &xi) const
335  {
336  return dx_computer(m_coords, xi);
337  }
338 
344  ddx_return_type get_ddx(xi_t const &xi) const
345  {
346  return ddx_computer(m_coords, xi);
347  }
348 
353  x_t const &get_center(void) const
354  {
355  return m_center;
356  }
357 
363  {
364  return m_linear_size_estimate;
365  }
366 
373  template <class OtherElem>
374  element_overlapping get_overlapping(OtherElem const &other) const
375  {
376  unsigned num_coinc = 0; // number of coincident nodes
377  unsigned start_ind1 = 0, start_ind2 = 0;
378 
379  auto const &otherNodes = other.get_nodes();
380  for (unsigned i = 0; i < num_nodes; ++i)
381  {
382  for (unsigned j = 0; j < OtherElem::num_nodes; ++j)
383  {
384  if (m_nodes[i] == otherNodes[j])
385  {
386  if (num_coinc == 0)
387  {
388  start_ind1 = i;
389  start_ind2 = j;
390  }
391  else
392  {
393  if (i < start_ind1
394  || (i==num_nodes-1
395  && start_ind1 == 0
396  && num_coinc == 1))
397  start_ind1 = i;
398  if (j < start_ind2 ||
399  (j==OtherElem::num_nodes-1 &&
400  start_ind2 == 0 &&
401  num_coinc == 1))
402  start_ind2 = j;
403  }
404  num_coinc++;
405  }
406  }
407  }
408  if (num_coinc == 0)
409  return element_overlapping();
410  return element_overlapping(num_coinc, start_ind1, start_ind2);
411  }
412 
416  Derived get_linearized_elem(xi_t const &xi0) const
417  {
418  // coordinates of the linearized elem
419  coords_t coords;
420 
421  // phyisical location and its derivative at the reference point
422  x_t x0 = get_x(xi0);
423  auto dx0 = get_dx(xi0);
424 
425  // compute corners of linearized elem
426  for (size_t i = 0; i < num_nodes; ++i)
427  {
428  xi_t const &xi = lset_t::corner_at(i);
429  xi_t dxi = xi - xi0;
430  coords.col(i) = x0 + dx0 * dxi;
431  }
432 
433  // construct linearized elem
434  return Derived(coords);
435  }
436 };
437 
443 inline bool operator<(elem_id_t const &lhs, elem_id_t const &rhs)
444 {
445  return lhs(0,0) < rhs(0,0);
446 }
447 
448 
449 // forward declaration
450 template <class LSet, class scalar_t>
452 
453 // forward declaration
454 template <class LSet, class scalar_t>
456 
457 
459 namespace element_traits
460 {
461  /* the space dimension is computed from the Lset domain's dimension */
462  template <class LSet, class Scalar>
463  struct space_type<volume_element<LSet, Scalar> >
464  : space<Scalar, LSet::domain_t::dimension> {};
465 
466  template <class LSet, class Scalar>
467  struct lset<volume_element<LSet, Scalar> >
468  {
469  typedef LSet type;
470  };
471 
472  template <class LSet, class Scalar>
473  struct is_surface_element<volume_element<LSet, Scalar> > : std::false_type {};
474 }
475 
476 
477 
479 template<class Derived, class enable = void>
481 
483 namespace element_traits
484 {
485  /* the space dimension is computed from the Lset domain's dimension (dL+1) */
486  template <class LSet, class Scalar>
487  struct space_type<surface_element<LSet, Scalar> >
488  : space<Scalar, LSet::domain_t::dimension + 1> {};
489 
490  template <class LSet, class Scalar>
491  struct lset<surface_element<LSet, Scalar> >
492  {
493  typedef LSet type;
494  };
495 
496  template <class LSet, class Scalar>
497  struct is_surface_element<surface_element<LSet, Scalar> > : std::true_type {};
498 }
499 
501 template <class Derived>
502 class normal_impl<Derived, typename std::enable_if<
503  element_traits::space_type<Derived>::type::dimension == 3
504 >::type>
505 {
506  typedef typename element_traits::location_value_type<Derived, 0>::type x_t;
507  typedef typename element_traits::location_value_type<Derived, 1>::type dx_t;
508 public:
509  static x_t eval(dx_t const &m)
510  {
511  return m.col(shape_derivative_index::dXI).cross(m.col(shape_derivative_index::dETA));
512  }
513 };
514 
516 template <class Derived>
517 class normal_impl<Derived, typename std::enable_if<
518  element_traits::space_type<Derived>::type::dimension == 2
519 >::type>
520 {
521  typedef typename element_traits::location_value_type<Derived, 0>::type x_t;
522  typedef typename element_traits::location_value_type<Derived, 1>::type dx_t;
523 public:
524  static x_t eval(dx_t const &m)
525  {
526  using namespace boost::math::double_constants;
527  return Eigen::Rotation2D<typename Derived::scalar_t>(-pi/2.0) * m;
528  }
529 };
530 
531 namespace element_traits
532 {
534  template <class Derived>
536  typename location_complexity<Derived, 1>::type,
537  normal_impl<Derived>,
538  typename location_value_type<Derived, 1>::type
539  > {};
540 
542  template <class Derived>
544  {
545  typedef typename normal_factory_functor<
546  Derived
547  >::type::return_type type;
548  };
549 }
550 
554 template <class LSet, class scalar_t>
555 class surface_element :
556  public element_base<surface_element<LSet, scalar_t> >
557 {
558 public:
561 
562  using typename base_t::coords_t;
563  using typename base_t::nodes_t;
564  using typename base_t::xi_t;
565  using typename base_t::x_t;
566  using typename base_t::dx_t;
567 
569  using domain_t = typename base_t::domain_t;
570 
571  using base_t::get_dx;
572 
574  typedef typename element_traits::normal_return_type<surface_element>::type normal_return_type;
575 
576 protected:
579 
580 public:
588  coords_t const &coords,
589  unsigned id = 0,
590  nodes_t const &nodes = nodes_t())
591  : base_t(coords, id, nodes),
592  normal_computer(get_dx(xi_t()))
593  {
594  }
595 
596  void flip_inplace(void)
597  {
598  *this = flip();
599  }
600 
601  surface_element flip(void) const
602  {
603  return surface_element(this->get_coords().colwise().reverse(), this->get_id()(0), this->get_nodes().reverse());
604  }
605 
611  normal_return_type get_normal(xi_t const &xi = domain_t::get_center()) const
612  {
613  return normal_computer(get_dx(xi));
614  }
615 };
616 
617 
618 
622 template <class LSet, class scalar_t>
623 class volume_element :
624  public element_base<volume_element<LSet, scalar_t> >
625 {
626 public:
629 
630  using typename base_t::coords_t;
631  using typename base_t::nodes_t;
632  using typename base_t::xi_t;
633  using typename base_t::x_t;
634  using typename base_t::dx_t;
635 
637  using domain_t = typename base_t::domain_t;
638 
639  using base_t::get_dx;
640 
648  coords_t const &coords,
649  unsigned id = 0,
650  nodes_t const &nodes = nodes_t())
651  : base_t(coords, id, nodes)
652  {
653  }
654 };
655 
656 } // namespace NiHu
657 
658 
659 #endif
660 
NiHu::element_base::x_t
element_traits::location_value_type< Derived, 0 >::type x_t
type of the element's physical location variable
Definition: element.hpp:220
NiHu::volume_element::base_t
element_base< volume_element< LSet, scalar_t > > base_t
the base class type
Definition: element.hpp:628
NiHu::element_base::get_linearized_elem
Derived get_linearized_elem(xi_t const &xi0) const
construct linearized elem around an intrinsic coordinate
Definition: element.hpp:416
NiHu::volume_element
class describing a volume element that has no normal vector
Definition: element.hpp:455
NiHu::element_base::nodes_t
Eigen::Matrix< unsigned, num_nodes, 1 > nodes_t
vector type that stores the element's corner node indices
Definition: element.hpp:233
NiHu::element_traits::space_type
The physical coordinate space of the element.
Definition: element.hpp:98
NiHu::element_base::m_linear_size_estimate
scalar_t m_linear_size_estimate
estimated linear size of an element
Definition: element.hpp:249
NiHu::shape_set_traits::domain
Defines the domain where the shape function set is defined.
Definition: shapeset.hpp:106
NiHu::element_traits::location_return_type
The return type of the physical location's derivatives.
Definition: element.hpp:160
NiHu::element_base::element_base
element_base(coords_t const &coords, unsigned id=0, nodes_t const &nodes=nodes_t())
constructor
Definition: element.hpp:270
NiHu::element_base::get_center
const x_t & get_center(void) const
return element center
Definition: element.hpp:353
NiHu::element_base::lset_t
element_traits::lset< Derived >::type lset_t
the element's L-set
Definition: element.hpp:203
NiHu::surface_element::normal_return_type
element_traits::normal_return_type< surface_element >::type normal_return_type
the return type of function get_normal
Definition: element.hpp:574
NiHu::element_base::num_nodes
@ num_nodes
the number of nodes
Definition: element.hpp:216
NiHu::surface_element::get_normal
normal_return_type get_normal(xi_t const &xi=domain_t::get_center()) const
return element normal
Definition: element.hpp:611
NiHu::element_base::m_nodes
nodes_t m_nodes
the element's nodal indices in the mesh
Definition: element.hpp:243
NiHu::element_base::get_overlapping
element_overlapping get_overlapping(OtherElem const &other) const
check overlapping state with other element
Definition: element.hpp:374
NiHu::element_base::id
@ id
the element id
Definition: element.hpp:214
NiHu::surface_element::normal_computer
element_traits::normal_factory_functor< surface_element >::type normal_computer
functor computing the normal vector
Definition: element.hpp:578
NiHu::surface_element::base_t
element_base< surface_element< LSet, scalar_t > > base_t
the base class type
Definition: element.hpp:560
NiHu::volume_element::coords_t
element_traits::coords_type< Derived >::type coords_t
matrix type that stores the element's corner nodes
Definition: element.hpp:235
NiHu::num_derivatives
constexpr unsigned num_derivatives(unsigned order, unsigned dim)
return the number of partial derivatives in dim dimensions In 1D there is one partial derivative and ...
Definition: shapeset.hpp:89
NiHu::element_base::get_nodes
const nodes_t & get_nodes(void) const
return nodes
Definition: element.hpp:305
NiHu::element_traits::location_factory_functor
Class that computes or stores the locations.
Definition: element.hpp:149
NiHu::element_base::scalar_t
space_t::scalar_t scalar_t
the element's scalar variable
Definition: element.hpp:205
NiHu::element_base::m_coords
coords_t m_coords
the element's corner coordinates
Definition: element.hpp:245
NiHu::element_traits::location_complexity
Defines the complexity to determine if the location derivative can be precomputed or not.
Definition: element.hpp:120
NiHu::element_base::xi_t
domain_t::xi_t xi_t
type of the shape functions' independent variable
Definition: element.hpp:210
NiHu::space
class representing a coordinate space with a scalar and a dimension
Definition: space.hpp:36
NiHu::element_base::get_dx
dx_return_type get_dx(xi_t const &xi) const
return element location gradient
Definition: element.hpp:334
NiHu::surface_element< LSet, Scalar >::coords_t
element_traits::coords_type< Derived >::type coords_t
matrix type that stores the element's corner nodes
Definition: element.hpp:235
NiHu::element_traits::is_surface_element
Indicates if the element is a surface element or not.
Definition: element.hpp:106
NIHU_CRTP_HELPERS
#define NIHU_CRTP_HELPERS
define CRTP helper function
Definition: crtp_base.hpp:29
NiHu::element_traits::name
The element type's textual id.
Definition: element.hpp:91
NiHu::element_base::dx_return_type
element_traits::location_return_type< Derived, 1 >::type dx_return_type
return type of the element physical location derivative
Definition: element.hpp:226
NiHu::element_traits::location_value_type
Matrix that stores the physical location's derivatives.
Definition: element.hpp:138
NiHu::surface_element< LSet, Scalar >::domain_t
typename base_t::domain_t domain_t
the domain type
Definition: element.hpp:569
NiHu::element_traits::id
Assigns an id to the element type.
Definition: element.hpp:110
NiHu::element_base::x_computer
element_traits::location_factory_functor< Derived, 0 >::type x_computer
functor computing the locations
Definition: element.hpp:252
NiHu::element_base::id_t
elem_id_t id_t
type that stores the element's id
Definition: element.hpp:237
NiHu::element_traits::normal_return_type
The return type of the normal vector.
Definition: element.hpp:543
NiHu::surface_element< LSet, Scalar >::xi_t
domain_t::xi_t xi_t
type of the shape functions' independent variable
Definition: element.hpp:210
NiHu::element_overlapping
class describing the overlapping state of two elements
Definition: element.hpp:39
NiHu::element_base::get_x
x_return_type get_x(xi_t const &xi) const
return element location
Definition: element.hpp:324
NiHu::element_traits::lset
The geometrical shape set of the element.
Definition: element.hpp:102
NiHu::location_impl
compute location derivatives from nodal coordinates
Definition: element.hpp:84
NiHu::volume_element::volume_element
volume_element(coords_t const &coords, unsigned id=0, nodes_t const &nodes=nodes_t())
constructor
Definition: element.hpp:647
NiHu::conditional_precompute_instance
Definition: conditional_precompute.hpp:112
NiHu::element_base::type
Derived type
self-returning metafunction
Definition: element.hpp:198
NiHu::element_base::m_id
id_t m_id
the element's identifier
Definition: element.hpp:241
NiHu::element_base::get_linear_size_estimate
const scalar_t & get_linear_size_estimate(void) const
return linear size estimate
Definition: element.hpp:362
NiHu::normal_impl
compute surface normal from location derivatives
Definition: element.hpp:480
NiHu::element_traits::normal_factory_functor
Class that computes or stores the normals.
Definition: element.hpp:535
NiHu::element_base::dx_computer
element_traits::location_factory_functor< Derived, 1 >::type dx_computer
functor computing the location derivative vector
Definition: element.hpp:254
NiHu::surface_element::surface_element
surface_element(coords_t const &coords, unsigned id=0, nodes_t const &nodes=nodes_t())
constructor
Definition: element.hpp:587
NiHu::volume_element::nodes_t
Eigen::Matrix< unsigned, num_nodes, 1 > nodes_t
vector type that stores the element's corner node indices
Definition: element.hpp:233
NiHu::element_overlapping::get_ind2
unsigned get_ind2(void) const
return index of first coincident node in element 2
Definition: element.hpp:55
NiHu::surface_element
class describing a surface element that provides a normal vector
Definition: element.hpp:451
NiHu::element_overlapping::element_overlapping
element_overlapping(unsigned num=0, unsigned ind1=0, unsigned ind2=0)
constructor
Definition: element.hpp:61
NiHu::operator<
bool operator<(elem_id_t const &lhs, elem_id_t const &rhs)
compare two element id's by value
Definition: element.hpp:443
NiHu::element_base::domain_t
lset_t::domain_t domain_t
the element's reference domain
Definition: element.hpp:208
NiHu::element_base::get_ddx
ddx_return_type get_ddx(xi_t const &xi) const
return element location second derivative matrix
Definition: element.hpp:344
NiHu::element_overlapping::get_num
unsigned get_num(void) const
return number of coincident nodes
Definition: element.hpp:43
NiHu::element_base::x_return_type
element_traits::location_return_type< Derived, 0 >::type x_return_type
return type of the element physical location variable when obtained by get_x
Definition: element.hpp:222
NiHu::element_overlapping::get_ind1
unsigned get_ind1(void) const
return index of first coincident node in element 1
Definition: element.hpp:49
NiHu::surface_element< LSet, Scalar >::nodes_t
Eigen::Matrix< unsigned, num_nodes, 1 > nodes_t
vector type that stores the element's corner node indices
Definition: element.hpp:233
NiHu::element_base::dx_t
element_traits::location_value_type< Derived, 1 >::type dx_t
type of the gradient of the element's physical location variable
Definition: element.hpp:224
NiHu::element_base::space_t
element_traits::space_type< Derived >::type space_t
the element space type
Definition: element.hpp:201
NiHu::element_base::get_coords
const coords_t & get_coords(void) const
return coordinates
Definition: element.hpp:314
NiHu::shape_derivative_index::dXI
@ dXI
index of xi in 1st derivative matrix
Definition: shapeset.hpp:49
NiHu::element_base::element_base
NIHU_CRTP_HELPERS element_base()
default constructor for std::vector container
Definition: element.hpp:262
NiHu::volume_element::domain_t
typename base_t::domain_t domain_t
the domain type
Definition: element.hpp:637
NiHu::shape_derivative_index::dETA
@ dETA
index of eta in 1st derivative matrix
Definition: shapeset.hpp:50
NiHu::element_base::m_center
x_t m_center
the element's center
Definition: element.hpp:247
NiHu::element_base::ddx_t
element_traits::location_value_type< Derived, 2 >::type ddx_t
type of the second derivative of the element's physical location variable
Definition: element.hpp:228
shapeset.hpp
Definition of shape function sets.
NiHu::element_base::get_id
const id_t & get_id(void) const
return elem id
Definition: element.hpp:296
NiHu::element_base::coords_t
element_traits::coords_type< Derived >::type coords_t
matrix type that stores the element's corner nodes
Definition: element.hpp:235
NiHu::element_base::ddx_return_type
element_traits::location_return_type< Derived, 2 >::type ddx_return_type
return type of the element physical location second derivative
Definition: element.hpp:230
NiHu::elem_id_t
Eigen::Matrix< unsigned, 1, 1 > elem_id_t
type that stores the element's id
Definition: element.hpp:170
NiHu::element_base
The geometrical element representation.
Definition: element.hpp:194
NiHu::element_base::ddx_computer
element_traits::location_factory_functor< Derived, 2 >::type ddx_computer
functor computing the location second derivative matrix
Definition: element.hpp:256
NiHu::element_traits::coords_type
Matrix that stores the element's corner coordinates.
Definition: element.hpp:127
NiHu::shape_set_traits::shape_complexity
Defines the complexity to determine if the shape functions can be precomputed or not.
Definition: shapeset.hpp:134
NiHu::shape_set_traits::id
Assigns an id to the shape set.
Definition: shapeset.hpp:114