Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
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 >
23  {
24  public:
25  typedef _Matrix Matrix;
26 
27  private:
29 
30  public:
31  // Constructor
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];
248  real* _xyz[3];
249  }; // Class Spectral_hex_map
250 
251 } // namespace element_utility
252 
253 } // namespace moab
254 #endif // MOAB_SPECTRAL_HEX_nPP