moab
SpectralHex.cpp
Go to the documentation of this file.
00001 #include "moab/SpectralHex.hpp"
00002 #include "moab/Forward.hpp"
00003 
00004 namespace moab 
00005 {
00006     
00007   // SpectralHex
00008 
00009   // filescope for static member data that is cached
00010 int SpectralHex::_n;
00011 real *SpectralHex::_z[3];
00012 lagrange_data SpectralHex::_ld[3];
00013 opt_data_3 SpectralHex::_data;
00014 real * SpectralHex::_odwork;
00015 
00016 bool SpectralHex::_init = false;
00017 
00018     void SpectralHex::initFcn(const double *verts, const int nverts, double *&work)
00019 {
00020   if (_init && _n==order)
00021     return;
00022   if (_init && _n!=order)
00023   {
00024       // TODO: free data cached
00025     freedata();
00026   }
00027     // compute stuff that depends only on order
00028   _init = true;
00029   _n = order;
00030     //triplicates! n is the same in all directions !!!
00031   for(int d=0; d<3; d++){
00032     _z[d] = tmalloc(double, _n);
00033     lobatto_nodes(_z[d], _n);
00034     lagrange_setup(&_ld[d], _z[d], _n);
00035   }
00036   opt_alloc_3(&_data, _ld);
00037 
00038   unsigned int nf = _n*_n, ne = _n, nw = 2*_n*_n + 3*_n;
00039   _odwork = tmalloc(double, 6*nf + 9*ne + nw);
00040 }
00041 void SpectralHex::freedata()
00042 {
00043   for(int d=0; d<3; d++){
00044     free(_z[d]);
00045     lagrange_free(&_ld[d]);
00046   }
00047   opt_free_3(&_data);
00048   free(_odwork);
00049 }
00050 
00051 void SpectralHex::set_gl_points( double * x, double * y, double *z)
00052 {
00053   _xyz[0] = x;
00054   _xyz[1] = y;
00055   _xyz[2] = z;
00056 }
00057 CartVect SpectralHex::evaluate( const CartVect& params ) const
00058 {
00059     //piece that we shouldn't want to cache
00060   int d=0;
00061   for(d=0; d<3; d++){
00062     lagrange_0(&_ld[d], params[d]);
00063   }
00064   CartVect result;
00065   for (d=0; d<3; d++)
00066   {
00067     result[d] = tensor_i3(_ld[0].J,_ld[0].n,
00068                           _ld[1].J,_ld[1].n,
00069                           _ld[2].J,_ld[2].n,
00070                           _xyz[d],   // this is the "field"
00071                           _odwork);
00072   }
00073   return result;
00074 }
00075   // replicate the functionality of hex_findpt
00076     bool SpectralHex::evaluate_reverse(CartVect const & xyz, CartVect &params, double iter_tol, const double inside_tol,
00077                                        const CartVect &init) const
00078 {
00079   params = init;
00080       
00081     //find nearest point
00082   double x_star[3];
00083   xyz.get(x_star);
00084 
00085   double r[3] = {0, 0, 0 }; // initial guess for parametric coords
00086   unsigned c = opt_no_constraints_3;
00087   double dist = opt_findpt_3(&_data, (const double **)_xyz, x_star, r, &c);
00088     // if it did not converge, get out with throw...
00089   if (dist > 0.9e+30)
00090     return false;
00091     //c tells us if we landed inside the element or exactly on a face, edge, or node
00092     // also, dist shows the distance to the computed point.
00093     //copy parametric coords back
00094   params = r;
00095 
00096   return is_inside(params, inside_tol);
00097 }
00098 Matrix3  SpectralHex::jacobian(const CartVect& params) const
00099 {
00100   double x_i[3];
00101   params.get(x_i);
00102     // set the positions of GL nodes, before evaluations
00103   _data.elx[0]=_xyz[0];
00104   _data.elx[1]=_xyz[1];
00105   _data.elx[2]=_xyz[2];
00106   opt_vol_set_intp_3(&_data,x_i);
00107   Matrix3 J(0.);
00108     // it is organized differently
00109   J(0,0) = _data.jac[0]; // dx/dr
00110   J(0,1) = _data.jac[1]; // dx/ds
00111   J(0,2) = _data.jac[2]; // dx/dt
00112   J(1,0) = _data.jac[3]; // dy/dr
00113   J(1,1) = _data.jac[4]; // dy/ds
00114   J(1,2) = _data.jac[5]; // dy/dt
00115   J(2,0) = _data.jac[6]; // dz/dr
00116   J(2,1) = _data.jac[7]; // dz/ds
00117   J(2,2) = _data.jac[8]; // dz/dt
00118   return J;
00119 }
00120 void SpectralHex::evaluate_vector(const CartVect& params, const double *field, int num_tuples, double *eval) const
00121 {
00122     //piece that we shouldn't want to cache
00123   int d;
00124   for(d=0; d<3; d++){
00125     lagrange_0(&_ld[d], params[d]);
00126   }
00127 
00128   *eval = tensor_i3(_ld[0].J,_ld[0].n,
00129                     _ld[1].J,_ld[1].n,
00130                     _ld[2].J,_ld[2].n,
00131                     field,
00132                     _odwork);
00133 }
00134 void SpectralHex::integrate_vector(const double *field_values, int num_tuples, double *integral) const
00135 {
00136     // set the position of GL points
00137     // set the positions of GL nodes, before evaluations
00138   _data.elx[0]=_xyz[0];
00139   _data.elx[1]=_xyz[1];
00140   _data.elx[2]=_xyz[2];
00141   double params[3];
00142     //triple loop; the most inner loop is in r direction, then s, then t
00143   for (int l = 0; l < num_tuples; l++) integral[l] = 0.0;
00144     //double volume = 0;
00145   int index=0; // used fr the inner loop
00146   for (int k=0; k<_n; k++ )
00147   {
00148     params[2]=_ld[2].z[k];
00149       //double wk= _ld[2].w[k];
00150     for (int j=0; j<_n; j++)
00151     {
00152       params[1]=_ld[1].z[j];
00153         //double wj= _ld[1].w[j];
00154       for (int i=0; i<_n; i++)
00155       {
00156         params[0]=_ld[0].z[i];
00157           //double wi= _ld[0].w[i];
00158         opt_vol_set_intp_3(&_data,params);
00159         double wk= _ld[2].J[k];
00160         double wj= _ld[1].J[j];
00161         double wi= _ld[0].J[i];
00162         Matrix3 J(0.);
00163           // it is organized differently
00164         J(0,0) = _data.jac[0]; // dx/dr
00165         J(0,1) = _data.jac[1]; // dx/ds
00166         J(0,2) = _data.jac[2]; // dx/dt
00167         J(1,0) = _data.jac[3]; // dy/dr
00168         J(1,1) = _data.jac[4]; // dy/ds
00169         J(1,2) = _data.jac[5]; // dy/dt
00170         J(2,0) = _data.jac[6]; // dz/dr
00171         J(2,1) = _data.jac[7]; // dz/ds
00172         J(2,2) = _data.jac[8]; // dz/dt
00173         double bm = wk*wj*wi* J.determinant();
00174         for (int l = 0; l < num_tuples; l++)
00175           integral[l]+= bm*field_values[num_tuples*index+l];
00176           //volume +=bm;
00177       }
00178     }
00179   }
00180     //std::cout << "volume: " << volume << "\n";
00181 }
00182 
00183     int SpectralHex::insideFcn(const double *params, const int ndim, const double tol) 
00184     {
00185       return EvalSet::inside(params, ndim, tol);
00186     }
00187 
00188   // SpectralHex
00189 
00190 } // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines