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
00022 T g;
00023
00024 Eagle::Quadratic<T::Dims, double> g_inv;
00025
00026
00027 T g_diff[T::Dims];
00028
00029
00030 bool ok;
00031
00032
00033
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
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
00102
00103
00104
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
00143
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
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
00215
00216
00217 RefPtr<Field> Field;
00218
00219 Field = FieldSelection.getField();
00220
00221
00222
00223 if(!Field)
00224 {
00225
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
00242
00243 RefPtr<MemArray<3, T> > ToIntArr0 = mBase;
00244 ToIntArr0 = Field->getCreator( FragID )->create();
00245
00246 assert( ToIntArr0 );
00247
00248
00249
00250
00251
00252
00253
00254
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
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
00290
00291 RefPtr<LocalFromWorldPoint> LocalPointFinder;
00292 FieldSelector FieldSelection;
00293
00294
00295
00296
00297
00298
00299 double step_size;
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
00339
00340
00341 bool test = FieldLines::getChristoffelXYZ<T>( Q, LocalPointFinder, FieldSelection, step_size,
00342 Gamma,
00343 CurrentMetric,
00344 localPoint );
00345
00346 if(!test)
00347 {
00348
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
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 }
00377 #endif // __GEODESCICS_HPP_