Loading [MathJax]/extensions/tex2jax.js
Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
spectral_hex_map.hpp
Go to the documentation of this file.
1 #ifndef MOAB_SPECTRAL_HEX_HPP 2 #define MOAB_SPECTRAL_HEX_HPP 3  4 #include "moab/Matrix3.hpp" 5 #include "moab/CartVect.hpp" 6 #include "moab/FindPtFuncs.h" 7 #include <sstream> 8 #include <iomanip> 9 #include <iostream> 10  11 namespace moab 12 { 13  14 namespace element_utility 15 { 16  17  namespace 18  { 19  } // namespace 20  21  template < typename _Matrix > 22  class Spectral_hex_map 23  { 24  public: 25  typedef _Matrix Matrix; 26  27  private: 28  typedef Spectral_hex_map< Matrix > Self; 29  30  public: 31  // Constructor 32  Spectral_hex_map(){}; 33  Spectral_hex_map( int order ) 34  { 35  initialize_spectral_hex( order ); 36  } 37  // Copy constructor 38  Spectral_hex_map( const Self& f ) {} 39  40  private: 41  void initialize_spectral_hex( int order ) 42  { 43  if( _init && _n == order ) 44  { 45  return; 46  } 47  if( _init && _n != order ) 48  { 49  free_data(); 50  } 51  _init = true; 52  _n = order; 53  for( int d = 0; d < 3; d++ ) 54  { 55  lobatto_nodes( _z[d], _n ); 56  lagrange_setup( &_ld[d], _z[d], _n ); 57  } 58  opt_alloc_3( &_data, _ld ); 59  std::size_t nf = _n * _n, ne = _n, nw = 2 * _n * _n + 3 * _n; 60  _odwork = tmalloc( real, 6 * nf + 9 * ne + nw ); 61  } 62  63  void free_data() 64  { 65  for( int d = 0; d < 3; d++ ) 66  { 67  free( _z[d] ); 68  lagrange_free( &_ld[d] ); 69  } 70  opt_free_3( &_data ); 71  free( _odwork ); 72  } 73  74  public: 75  // Natural coordinates 76  template < typename Moab, typename Entity_handle, typename Points, typename Point > 77  std::pair< bool, Point > operator()( const Moab& /* moab */, 78  const Entity_handle& /* h */, 79  const Points& v, 80  const Point& p, 81  const double tol = 1.e-6 ) 82  { 83  Point result( 3, 0.0 ); 84  /* 85  moab.tag_get_by_ptr(_xm1Tag, &eh, 1,(const void **) &_xyz[ 0] ); 86  moab.tag_get_by_ptr(_ym1Tag, &eh, 1,(const void **) &_xyz[ 1] ); 87  moab.tag_get_by_ptr(_zm1Tag, &eh, 1,(const void **) &_xyz[ 2] ); 88  */ 89  bool point_found = solve_inverse( p, result, v, tol ) && is_contained( result, tol ); 90  return std::make_pair( point_found, result ); 91  } 92  93  private: 94  void set_gl_points( double* x, double* y, double* z ) 95  { 96  _xyz[0] = x; 97  _xyz[1] = y; 98  _xyz[2] = z; 99  } 100  template < typename Point > 101  bool is_contained( const Point& p, const double tol ) const 102  { 103  // just look at the box+tol here 104  return ( p[0] >= -1. - tol ) && ( p[0] <= 1. + tol ) && ( p[1] >= -1. - tol ) && ( p[1] <= 1. + tol ) && 105  ( p[2] >= -1. - tol ) && ( p[2] <= 1. + tol ); 106  } 107  108  template < typename Point, typename Points > 109  bool solve_inverse( const Point& x, Point& xi, const Points& points, const double tol = 1.e-6 ) 110  { 111  const double error_tol_sqr = tol * tol; 112  Point delta( 3, 0.0 ); 113  xi = delta; 114  evaluate( xi, points, delta ); 115  vec_subtract( delta, x ); 116  std::size_t num_iterations = 0; 117 #ifdef SPECTRAL_HEX_DEBUG 118  std::stringstream ss; 119  ss << "Point: "; 120  ss << x[0] << ", " << x[1] << ", " << x[2] << std::endl; 121  ss << "Hex: "; 122  for( int i = 0; i < 8; ++i ) 123  { 124  ss << points[i][0] << ", " << points[i][1] << ", " << points[i][2] << std::endl; 125  } 126  ss << std::endl; 127 #endif 128  while( normsq( delta ) > error_tol_sqr ) 129  { 130 #ifdef SPECTRAL_HEX_DEBUG 131  ss << "Iter #: " << num_iterations << " Err: " << sqrt( normsq( delta ) ) << " Iterate: "; 132  ss << xi[0] << ", " << xi[1] << ", " << xi[2] << std::endl; 133 #endif 134  if( ++num_iterations >= 5 ) 135  { 136  return false; 137  } 138  Matrix J; 139  jacobian( xi, points, J ); 140  double det = moab::Matrix::determinant3( J ); 141  if( fabs( det ) < 1.e-10 ) 142  { 143 #ifdef SPECTRAL_HEX_DEBUG 144  std::cerr << ss.str(); 145 #endif 146 #ifndef SPECTRAL_HEX_DEBUG 147  std::cerr << x[0] << ", " << x[1] << ", " << x[2] << std::endl; 148 #endif 149  std::cerr << "inverse solve failure: det: " << det << std::endl; 150  exit( -1 ); 151  } 152  vec_subtract( xi, moab::Matrix::inverse( J, 1.0 / det ) * delta ); 153  evaluate( xi, points, delta ); 154  vec_subtract( delta, x ); 155  } 156  return true; 157  } 158  159  template < typename Point, typename Points > 160  Point& evaluate( const Point& p, const Points& /* points */, Point& f ) 161  { 162  for( int d = 0; d < 3; ++d ) 163  { 164  lagrange_0( &_ld[d], p[0] ); 165  } 166  for( int d = 0; d < 3; ++d ) 167  { 168  f[d] = tensor_i3( _ld[0].J, _ld[0].n, _ld[1].J, _ld[1].n, _ld[2].J, _ld[2].n, _xyz[d], _odwork ); 169  } 170  return f; 171  } 172  173  template < typename Point, typename Field > 174  double evaluate_scalar_field( const Point& p, const Field& field ) const 175  { 176  int d; 177  for( d = 0; d < 3; d++ ) 178  { 179  lagrange_0( &_ld[d], p[d] ); 180  } 181  return tensor_i3( _ld[0].J, _ld[0].n, _ld[1].J, _ld[1].n, _ld[2].J, _ld[2].n, field, _odwork ); 182  } 183  template < typename Points, typename Field > 184  double integrate_scalar_field( const Points& p, const Field& field ) const 185  { 186  // set the position of GL points 187  // set the positions of GL nodes, before evaluations 188  _data.elx[0] = _xyz[0]; 189  _data.elx[1] = _xyz[1]; 190  _data.elx[2] = _xyz[2]; 191  double xi[3]; 192  // triple loop; the most inner loop is in r direction, then s, then t 193  double integral = 0.; 194  // double volume = 0; 195  int index = 0; // used fr the inner loop 196  for( int k = 0; k < _n; k++ ) 197  { 198  xi[2] = _ld[2].z[k]; 199  // double wk= _ld[2].w[k]; 200  for( int j = 0; j < _n; j++ ) 201  { 202  xi[1] = _ld[1].z[j]; 203  // double wj= _ld[1].w[j]; 204  for( int i = 0; i < _n; i++ ) 205  { 206  xi[0] = _ld[0].z[i]; 207  // double wi= _ld[0].w[i]; 208  opt_vol_set_intp_3( (opt_data_3*)&_data, xi ); // cast away const-ness 209  double wk = _ld[2].J[k]; 210  double wj = _ld[1].J[j]; 211  double wi = _ld[0].J[i]; 212  Matrix3 J( 0. ); 213  for( int n = 0; n < 8; n++ ) 214  J( n / 3, n % 3 ) = _data.jac[n]; 215  double bm = wk * wj * wi * J.determinant(); 216  integral += bm * field[index++]; 217  // volume +=bm; 218  } 219  } 220  } 221  // std::cout << "volume: " << volume << "\n"; 222  return integral; 223  } 224  225  template < typename Point, typename Points > 226  Matrix& jacobian( const Point& /* p */, const Points& /* points */, Matrix& J ) 227  { 228  real x[3]; 229  for( int i = 0; i < 3; ++i ) 230  { 231  _data.elx[i] = _xyz[i]; 232  } 233  opt_vol_set_intp_3( &_data, x ); 234  for( int i = 0; i < 9; ++i ) 235  { 236  J( i % 3, i / 3 ) = _data.jac[i]; 237  } 238  return J; 239  } 240  241  private: 242  bool _init; 243  int _n; 244  real* _z[3]; 245  lagrange_data _ld[3]; 246  opt_data_3 _data; 247  real* _odwork; 248  real* _xyz[3]; 249  }; // Class Spectral_hex_map 250  251 } // namespace element_utility 252  253 } // namespace moab 254 #endif // MOAB_SPECTRAL_HEX_nPP