Geodesics .hpp

00001 #ifndef __GEODESCICS_HPP_
00002 #define __GEODESCICS_HPP_
00003 
00004 #include <fish/fiber/vector/CubicIpol.hpp>
00005 #include <eagle/QuadraticMatrix.hpp> 
00006 #include <eagle/Coordinates.hpp>
00007 #include <fish/fiber/baseop/LocalFromWorldPoint.hpp>
00008 #include <ode/dop853.hpp>
00009 
00010 namespace FieldLines
00011 {
00012 
00013 struct Geodesic{};
00014 
00015 
00016 template<class T>
00017 class ChristoffelXYZ : public MemCore::ReferenceBase< ChristoffelXYZ<T> >
00018 {
00019         typedef typename T::Chart_t Chart_t;
00020         typedef typename Eagle::Coordinates<Chart_t>::point point;
00021         // store metric tensor
00022         T g;
00023         
00024         Eagle::Quadratic<T::Dims, double> g_inv;
00025  
00026         // store precomputed finite differences of g // array size 3
00027         T g_diff[T::Dims];
00028 
00029 
00030         bool ok;
00031         // consts for access
00032 //      enum { MU = 0, NU, LAMBDA  };
00033 //      enum { X = 0, Y, Z};
00034 
00035 public:
00036         ChristoffelXYZ( const T&gP, const T&g_xP, const T&g_yP, const T&g_zP,
00037                         const double dxP, const double dyP, const double dzP  )
00038         : MemCore::ReferenceBase< ChristoffelXYZ >(this)
00039         , g(gP)
00040         , ok(true)
00041         {
00042                 if(T::Dims == 3)
00043                 {
00044                         enum { X = 0, Y, Z};
00045 
00046                 if(dxP != 0.0)
00047                         for(unsigned i = 0; i < T::SIZE; i++)
00048                                 g_diff[X][i] = ( g_xP[i] - g[i] ) / dxP; 
00049 
00050                 if(dyP != 0.0)
00051                         for(unsigned i = 0; i < T::SIZE; i++)
00052                                 g_diff[Y][i] = ( g_yP[i] - g[i] ) / dyP; 
00053 
00054                 if(dzP != 0.0)
00055                         for(unsigned i = 0; i < T::SIZE; i++)
00056                                 g_diff[Z][i] = ( g_zP[i] - g[i] ) / dzP;
00057 
00058                 } 
00059 
00060                 if(T::Dims == 4)
00061                 {
00062                         enum {  t = Eagle::STA::CartesianChart4D<>::T, 
00063                                 X = Eagle::STA::CartesianChart4D<>::X,
00064                                 Y = Eagle::STA::CartesianChart4D<>::Y,
00065                                 Z = Eagle::STA::CartesianChart4D<>::Z }; 
00066 
00067                         if(dxP != 0.0)
00068                                 for(unsigned i = 0; i < T::SIZE; i++)
00069                                         g_diff[X][i] = ( g_xP[i] - g[i] ) / dxP; 
00070 
00071                         if(dyP != 0.0)
00072                                 for(unsigned i = 0; i < T::SIZE; i++)
00073                                         g_diff[Y][i] = ( g_yP[i] - g[i] ) / dyP; 
00074 
00075                         if(dzP != 0.0)
00076                                 for(unsigned i = 0; i < T::SIZE; i++)
00077                                         g_diff[Z][i] = ( g_zP[i] - g[i] ) / dzP;
00078                         
00079                 }
00080         }
00081 
00082         ChristoffelXYZ( const T&gP, const T&g_dxP, const T&g_dyP, const T&g_dzP )
00083         : MemCore::ReferenceBase< ChristoffelXYZ<T> >(this)
00084         , g(gP)
00085         , ok(true)      
00086         {
00087 //              std::cout << "hello?";
00088                 if(T::Dims == 3)
00089                 {
00090                         enum { X = 0, Y, Z};
00091                         g_diff[X] = g_dxP; 
00092                         g_diff[Y] = g_dyP; 
00093                         g_diff[Z] = g_dzP; 
00094 
00095                         try
00096                         {
00097                                 Eagle::Quadratic<T::Dims, double> q (g); 
00098 
00099                                 Eagle::ComputeInverse(g_inv, q); 
00100 
00101                                 // Eagle::Matrix<T::Dims,T::Dims, double> &mg = q ; 
00102                                 // Eagle::Matrix<T::Dims,T::Dims, double> &mg_i = g_inv; 
00103                                 // Eagle::Matrix<T::Dims,T::Dims, double> I = mg * mg_i; 
00104                                 // std::cout << "controll inversion: " << I << std::endl; 
00105                         } 
00106                         catch(const Eagle::DegeneratedMatrix&)
00107                         {
00108                                 puts("ChristoffelXYZ<>::ChristoffelXYZ ERROR Degenerated Matrix in inversion."); fflush(stdout); 
00109                                 ok = false;
00110                         } 
00111                         
00112                 } 
00113                 if(T::Dims == 4)
00114                 {
00115                         enum {  t = Eagle::STA::CartesianChart4D<>::T, 
00116                                 X = Eagle::STA::CartesianChart4D<>::X,
00117                                 Y = Eagle::STA::CartesianChart4D<>::Y,
00118                                 Z = Eagle::STA::CartesianChart4D<>::Z }; 
00119 
00120                         g_diff[t].set(0.0);
00121                         g_diff[X] = g_dxP; 
00122                         g_diff[Y] = g_dyP; 
00123                         g_diff[Z] = g_dzP; 
00124 
00125                         g_inv(g);
00126                 } 
00127 
00128 
00129 
00130         }
00131 
00132         bool isOk(){ return ok;}
00133 
00134         void  getMetricfromQuadratic(const Eagle::Quadratic<T::Dims,double>&q, T&g)
00135                 {
00136                         for(unsigned i = 0; T::SIZE; i++)
00137                                 g[i] = q[i];
00138                 }
00139 
00140 
00141 
00142         // christoffel symbols function for on demand symbol computing, later there may be the need to 
00143         // store them and reuse them when possible.
00144         const double operator()(const unsigned mu, const unsigned nu, const unsigned lambda) const 
00145         {
00146         double gamma = 0.0; 
00147 
00148                 if(mu > T::Dims-1 || nu > T::Dims-1 || lambda > T::Dims-1)
00149                         return 0.0; 
00150 
00151                 for(unsigned i = 0; i < T::Dims; i++)
00152                         gamma += g_inv(lambda, i) * ( g_diff[nu](mu,i) + g_diff[mu](nu,mu) - g_diff[i](mu, nu) ); 
00153 
00154                 gamma /= 0.5;
00155 
00156                 return gamma;
00157         }
00158 
00159         const T& getG() { return g; }
00160         
00161         void speak() const
00162        {
00163                if(T::Dims == 3)
00164                        std::cout << "Christoffel content:\n" << "g: " << g << "\ng': " << g_diff[0] << g_diff[1] << g_diff[2]; 
00165                if(T::Dims == 4)
00166                        std::cout << "Christoffel content:\n" << "g: " << g << "\ng': " << g_diff[0] << g_diff[1] << g_diff[2]<< g_diff[3];
00167 
00168        }
00169 
00170 };
00171 
00172 template<class T>
00173 typename Eagle::Coordinates<typename T::Chart_t >::vector getQddot( RefPtr< ChristoffelXYZ<T> >& Gamma, 
00174                                                                     typename Eagle::Coordinates<typename T::Chart_t >::vector&q_dot )
00175 {
00176 typename Eagle::Coordinates<typename T::Chart_t >::vector q_ddot; 
00177 
00178         q_ddot.set(0.0);
00179 
00180         // q-ddot^lamba = - Gamma^lambda_mu_nu * q-dot^mu * q-dot^nu 
00181 
00182         for(index_t lambda = 0; lambda < T::Dims; lambda++)
00183                 for( index_t mu = 0; mu < T::Dims; mu++)
00184                         for(index_t nu = 0; nu < T::Dims; nu++)
00185                                 q_ddot[lambda] -= (*Gamma)( mu, nu, lambda ) * q_dot[mu] * q_dot[nu]; 
00186         return q_ddot;
00187 }
00188 
00189 template<class T>
00190 bool getChristoffelXYZ( const typename Eagle::Coordinates<typename T::Chart_t >::point& CurrentPoint, 
00191                         const MemCore::RefPtr<LocalFromWorldPoint>&LocalPointFinder, 
00192                         const FieldSelector&FieldSelection, const double step_size, 
00193                         RefPtr< ChristoffelXYZ<T> >& Christoffels,
00194                         T& CurrentMetric,
00195                         pair<Eagle::PhysicalSpace::point, string>& localPoint ) 
00196         {
00197         typedef typename T::Chart_t Chart_t;
00198         typedef typename Coordinates<Chart_t>::point point; 
00199 
00200                 Eagle::PhysicalSpace::point current (CurrentPoint[0+T::Dims-3], CurrentPoint[1+T::Dims-3], CurrentPoint[2+T::Dims-3]); 
00201 
00202         bool test = LocalPointFinder->get( current, localPoint ); 
00203 
00204                 if(!test)
00205                 {
00206                         puts("getChristoffelXYZ()1 error finding local point at:"); 
00207                         cout << current << endl;
00208                         return false;
00209                 } 
00210                 
00211         const string&FragName = localPoint.second; 
00212         const Eagle::PhysicalSpace::point &float_index = localPoint.first; 
00213 
00214 //              cout << "FieldLines::getChristoffelXYZ local point: " << float_index; 
00215 //              cout << "in Fragment:" << FragName << endl;
00216                
00217         RefPtr<Field> Field; 
00218 
00219                 Field = FieldSelection.getField(); 
00220 
00221 //              cout << "getting Field: " << FieldSelection.getFieldName() << endl;
00222                 
00223                 if(!Field) 
00224                 { 
00225                         //puts("AtomicIntegrator<metric33, Geodesic>doit2(); ERROR: No Field0 found in Time iteration"); 
00226                         return false; 
00227                 } 
00228 
00229 
00230          RefPtr<FragmentID> FragID;
00231 
00232                 if(FragName.compare("") != 0 )
00233                         FragID   = new FragmentID( FragName ); 
00234 
00235                 RefPtr<CreativeArrayBase> cBase = Field->getCreator( FragID ); 
00236                 assert(cBase); 
00237 
00238                 RefPtr<MemBase> mBase = cBase->create(); 
00239                 assert(mBase); 
00240 
00241 //              mBase.speak("bla");
00242 
00243                 RefPtr<MemArray<3, T> > ToIntArr0 = mBase; 
00244                 ToIntArr0   = Field->getCreator( FragID )->create(); 
00245 
00246                 assert( ToIntArr0 );
00247 
00248 
00249 
00250                         // NOTE: Here optionally use another interpolator, eventually cubic, or 
00251                         //       self-aligning for eigenvector fields.
00252                         // 
00253 
00254 //              cout << "before interpol" << endl;
00255 
00256         T InterpolData0_x, InterpolData0_y, InterpolData0_z; 
00257 
00258         Interpolate<3, T, CubicIpol<T> > myField0  ( *ToIntArr0,   float_index); 
00259         Interpolate<3, T, CubicIpol<T>, double, NoDelimiter<T>, 0  > myField0_x( *ToIntArr0, float_index); 
00260         Interpolate<3, T, CubicIpol<T>, double, NoDelimiter<T>, 1  > myField0_y( *ToIntArr0, float_index); 
00261         Interpolate<3, T, CubicIpol<T>, double, NoDelimiter<T>, 2  > myField0_z( *ToIntArr0, float_index); 
00262                   CurrentMetric   = myField0.eval(); 
00263                   InterpolData0_x = myField0_x.eval(); 
00264                   InterpolData0_y = myField0_y.eval(); 
00265                   InterpolData0_z = myField0_z.eval(); 
00266 
00267 //                cout << "-----------------------" << endl << CurrentMetric << InterpolData0_x << InterpolData0_y << InterpolData0_z; 
00268 
00269                   Christoffels = new ChristoffelXYZ<T>( CurrentMetric, InterpolData0_x, InterpolData0_y, InterpolData0_z ); 
00270 
00271                   if( Christoffels->isOk() == false)
00272                   {
00273                           puts("getChristoffelXYZ()<T>:warning, christoffels probably degenerated matrix."); 
00274                           return false;
00275                   }
00276 
00277                   return true;
00278         }
00279 
00280 
00281 template<class T>
00282 struct  GeodesicDifferentialEquation : public Traum::VirtualSecondOrderDiffEquation <double>
00283 {
00284 typedef typename T::Chart_t Chart_t;
00285 typedef typename Eagle::Coordinates<Chart_t>::point point;
00286 typedef typename Eagle::Coordinates<Chart_t>::vector tvector;
00287 
00288         
00289 //typedef ::Eagle::metric33 metric33;
00290 
00291 RefPtr<LocalFromWorldPoint> LocalPointFinder;   
00292 FieldSelector FieldSelection;
00293 
00294 //MultiIndex<3>       FieldSize;
00295         
00296 //FixedArray<double, 3> DomainStart,
00297 //                    DomainEnd;
00298 
00299 double step_size; // define stepsize for finite differential derivation of the metric tensors used for ChristoffelsXYZ33
00300 double scale;
00301 
00302 bool valid_point;
00303 
00304         pair<Eagle::PhysicalSpace::point, std::string>localPoint;
00305 
00306 T CurrentMetric;
00307         Eagle::tvector3 DataDir;
00308 RefPtr<ChristoffelXYZ<T> > Gamma;
00309 
00310         enum { N = 6 };
00311         typedef double real;
00312         
00313         GeodesicDifferentialEquation()
00314         {}
00315         
00316         virtual ~GeodesicDifferentialEquation() {}
00317         
00318         struct RealArray_t : FixedArray<real, N>               
00319         {
00320                 void init(int) {}
00321         };
00322         
00323         struct DOPVarsArray_t : FixedArray<Traum::dop_vars<real>, N >
00324         {
00325                 void init(int) {}
00326         };
00327         
00328         void Accel(real s, const real *x, const real *v, real *d2x_ds2)
00329         {
00330                 point Q; 
00331                 tvector q_dot; 
00332 
00333                         for(int k=0; k < point::Dims; k++)
00334                         {
00335                                 Q[k] = x[k]; 
00336                                 q_dot[k] = v[k];
00337                         } 
00338 //              printf("Q: %f, %f, %f\n", Q[0], Q[1], Q[2] ); 
00339 //              printf("V: %f, %f, %f\n", v[0], v[1], v[2] ); 
00340 
00341         bool test = FieldLines::getChristoffelXYZ<T>( Q, LocalPointFinder, FieldSelection, step_size, 
00342                                                      Gamma,
00343                                                      CurrentMetric,
00344                                                      localPoint ); 
00345 
00346                 if(!test)
00347                 {
00348                         //puts("GeodesicDifferentialEquation::DifferentialEquation::Accel() No valid point found!");fflush(stdout); 
00349                         return;
00350                 } 
00351 
00352                 tvector qdd = getQddot( Gamma, q_dot); 
00353 
00354                 for(int k=0; k < point::Dims; k++)
00355                         d2x_ds2[k] = qdd[k];
00356 
00357         }
00358 
00359 };
00360 
00361 // double linearInterpolate(const double t0, const double d0, const double t1, const double d1, const double t)
00362 // {
00363 //      return d0 + (d1 - d0) / (t1 - t0) * (t - t0);
00364 // }
00365 
00366 // metric33 linearInterpolate(const double t0, const metric33&m0, const double t1, const metric33&m1, const double t )
00367 // {
00368 // metric33 tmp; 
00369 //      for(unsigned i = 0; i < metric33::SIZE; i++)
00370 //              tmp[i] = linearInterpolate(t0, m0[i], t1, m1[i], t); 
00371 
00372 //      return tmp;
00373 // }
00374 
00375 
00376 }
00377 #endif // __GEODESCICS_HPP_