00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00047 #ifndef __SCHWARZSCHILD_GEODESIC_HPP
00048 #define __SCHWARZSCHILD_GEODESIC_HPP "Created 12.05.2004 21:57:45 by werner benger"
00049
00050 #include <ode/Integrate853.hpp>
00051
00052
00053
00054 #include <eagle/STA.hpp>
00055
00056 namespace Traum
00057 {
00058 using namespace Eagle;
00059
00060 #ifdef DB_LOG
00061 using namespace wb;
00062 #endif
00063
00068 class EquatorialPlane
00069 {
00070 public: typedef long double real;
00071 typedef Eagle::STA::sphericalpoint PolarPt;
00072 typedef Eagle::STA::point CartesianPt;
00073 typedef Eagle::STA::vector CartesianVec;
00074
00075 CartesianPt Center;
00076 CartesianVec X, Y;
00077
00078
00079 CartesianPt operator()(const PolarPt&P) const
00080 {
00081 real r = P[P.R],
00082 phi= P[P.PHI];
00083
00084 return CartesianPt( Center + r * ( sin(phi) * Y - cos(phi) * X) );
00085 }
00086
00087 static real cosine(const CartesianVec&l, const CartesianVec&r)
00088 {
00089 return dot( l.spatial(), r.spatial() );
00090 }
00091
00092
00093 PolarPt operator()(const CartesianPt&P, real&sinphi, real&cosphi) const
00094 {
00095 CartesianVec p = P-Center;
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 PhysicalSpace::vector dist_vec = p.spatial();
00106
00107 real r = norm( dist_vec );
00108 cosphi = -cosine(X,p) / r;
00109 sinphi = cosine(Y,p) / r;
00110
00111 real phi = atan2(sinphi, cosphi);
00112
00113 if (phi<0)
00114 phi += 2*M_PI;
00115
00116 PolarPt R;
00117 R[R.T] = P[P.T];
00118 R[R.R] = r;
00119 R[R.PHI] = phi;
00120 R[R.THETA] = 0;
00121 return R;
00122 }
00123
00124 #if 0
00125
00126
00127
00128
00129
00142 vector3 CoordinateAxes::direction(double sinphi, double cosphi,
00143 double u, double du) const
00144 {
00145 return (-du * sinphi + u * cosphi) * Y +
00146 ( du * cosphi + u * sinphi) * X;
00147
00148 #if 0
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 double z = sinphi/u - cosphi/du,
00161 n = sinphi/du + cosphi/u;
00162
00163
00164
00165
00166
00167
00168
00169 return n*X - z*Y;
00170
00171 #endif
00172 }
00173
00174 #endif
00175
00176 };
00177
00178
00179 class SchwarzschildGeodesic : public IntegratePath853<long double>
00180 {
00181 public: typedef long double real;
00182 real M;
00183 EquatorialPlane EQ;
00184
00185 typedef STA::sphericalpoint PolarPt;
00186 typedef STA::sphericalvector PolarVec;
00187 typedef STA::point CartesianPt;
00188 typedef STA::vector CartesianVec;
00189
00190 typedef PhysicalSpace::point point3;
00191 typedef PhysicalSpace::vector vector3;
00192
00193 SchwarzschildGeodesic(const real&mass=0)
00194 : M(mass)
00195 {
00196 EQ.Center.set(0.0);
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 bool restart(const real&s, const CartesianPt&x0, const CartesianVec&v0)
00221 {
00222 enum { N = 1, i=0 };
00223
00224
00225 point3 q0 = x0.spatial();
00226 vector3 dq0 = v0.spatial();
00227 dq0 /= norm(dq0);
00228
00229 const point3 & Center = EQ.Center.spatial();
00230
00231 #ifdef DB_LOG
00232 db_logf(21, "SchwarzschildGeodesic: EQ Axis: Ray (%lg,%lg,%lg) + l (%lg,%lg,%lg) \n",
00233 double( q0[0]), double( q0[1]), double( q0[2]),
00234 double(dq0[0]), double(dq0[1]), double(dq0[2])
00235 );
00236 #endif
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 real l = dot(Center - q0, dq0);
00248
00249
00250 #ifdef DB_LOG
00251 db_logf(21, "SchwarzschildGeodesic: EQ Axis: Closest linear approach is at lambda=%lg\n", double(l) );
00252 #endif
00253
00254 point3 Nm = q0 + l*dq0;
00255
00256
00257 EQ.X = tvector4( 0, dq0);
00258
00259 vector3 y = Nm-Center;
00260
00261
00262 #ifdef DB_LOG
00263 #define SVECP(V) double(V[V->x]),double(V[V->y]),double(V[V->z])
00264
00265 db_logf(21,"SchwarzschildGeodesic: CLOSEPOINT: (%lg,%lg,%lg) (lambda=%lg [%lg])\n",
00266 SVECP(y), double(l), double(l/M) );
00267 #endif
00268
00269
00270
00271
00272
00273
00274 real d = norm(y);
00275
00276
00277 if (d < 1E-8)
00278 {
00279 real *u = initialize(2*N,s);
00280 real *du = u + N;
00281 u[i] = 0;
00282 du[i] = 0;
00283
00284 #ifdef DB_LOG
00285 db_logf(21,"SchwarzschildGeodesic: DIRECT VIEW with impact parameter %lg (relative %lg, mass %lg), cannot setup axis!\n",
00286 double(d), double(d/M), double(M) );
00287 #endif
00288 return false;
00289 }
00290
00291 y /= d;
00292 EQ.Y = tvector4(0, y);
00293
00294 #ifdef DB_LOG
00295 db_logf(21,"SchwarzschildGeodesic: AXIS: (%lg,%lg,%lg) x (%lg,%lg,%lg) \n",
00296 SVECP(EQ.X), SVECP(EQ.Y) );
00297 #endif
00298
00299
00300 real sinphi, cosphi;
00301 PolarPt p0 = EQ(x0, sinphi, cosphi);
00302 #ifdef DB_LOG
00303 db_logf(21,"SchwarzschildGeodesic: Initial point at polar coordinates (r=%lg,theta=%lg,phi=%lg)\n",
00304 double(p0[p0->r]),double(p0[p0->th]),double(p0[p0->ph]) );
00305 #endif
00306
00307 real phi = p0[p0.PHI];
00308 real *u = initialize(2*N, phi);
00309 real *du = u + N;
00310
00311 u[i] = sinphi/d;
00312 du[i] = cosphi/d;
00313 #ifdef DB_LOG
00314 db_logf(21,"SchwarzschildGeodesic: sinphi=%lg cosphi=%lg d=%lg\n",
00315 double(sinphi), double(cosphi), double(d) );
00316
00317
00318 #endif
00319 return true;
00320 }
00321
00326 void Accel(real, const real *x, const real *v, real *d2x_ds2)
00327 {
00328 for(unsigned int i=0; i<nPaths(); i++)
00329 {
00330 d2x_ds2[i] = 3*M*x[i]*x[i]-x[i];
00331 }
00332 }
00333
00334 CartesianPt position() const
00335 {
00336 PolarPt P;
00337 P = EQ.Center[P.T], 1/q(0), 0, s1();
00338
00339 return EQ( P );
00340 }
00341
00342
00343 CartesianVec velocity() const
00344 {
00345 real phi = s1(),
00346 u = q(0),
00347 du = q(1),
00348 sinphi = sin(phi),
00349 cosphi = cos(phi);
00350
00351 double r_sin_delta = du * sinphi - u * cosphi,
00352 r_cos_delta = u * sinphi +du * cosphi;
00353
00354 return r_cos_delta * EQ.X + r_sin_delta * EQ.Y;
00355 }
00356
00357 CartesianPt position(real phi) const
00358 {
00359 PolarPt P;
00360 P = EQ.Center[P.T],
00361 1/q(0, phi),
00362 0,
00363 phi;
00364
00365 return EQ( P );
00366 }
00367
00368
00369 CartesianVec velocity(real phi) const
00370 {
00371 real u = q(0, phi),
00372 du = q(1, phi),
00373 sinphi = sin(phi),
00374 cosphi = cos(phi);
00375
00376 double r_sin_delta = du * sinphi - u * cosphi,
00377 r_cos_delta = u * sinphi +du * cosphi;
00378
00379 return r_cos_delta * EQ.X + r_sin_delta * EQ.Y;
00380 }
00381
00382
00383 };
00384
00385 }
00386
00387 #endif // __SCHWARZSCHILD_GEODESIC_HPP