forked from miguelfranca/BHRaytracer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Geodesic.cpp
75 lines (61 loc) · 1.94 KB
/
Geodesic.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "Geodesic.hpp"
#include "Matrix.hpp"
Geodesic::Geodesic(const Spacetime &a_st, double vel_squared)
: st(a_st), V2(vel_squared), ode(geodesic_RHS, 6)
{
ode.setParams({V2});
ode.setPointer(this);
ode.setMethod(ODEsolver::RK45);
ode.setStopCriteria(geodesic_stopAtSingularity);
}
// angles must be sent in radians
VecD Geodesic::shoot(const VecD &pos3, const VecD &vel3, bool evolveBackwards,
bool showHistory)
{
VecD init({0.});
init.insert(pos3);
init.insert(vel3);
// double dtau = 0.1 * (evolveBackwards ? -1. : 1.);
double dtau = 0.01 * (evolveBackwards ? -1. : 1.);
double tau = 1e8 * (evolveBackwards ? -1. : 1.);
VecD v;
if (showHistory)
{
MatrixD m = ode.evolve(init, tau, dtau, 1.e-5);
m.print();
v = m.back();
}
else
v = ode.solve(init, tau, dtau, 1.e-5);
return v;
}
VecD geodesic_RHS(const VecD &vars, const VecD ¶ms, void *ptr)
{
int i = 1;
// 1st coordinate shouldn't matter, so sending a nan just to make sure
// it really doesn't matter
VecD x({NAN, vars[i++], vars[i++], vars[i++]});
VecD v3({vars[i++], vars[i++], vars[i++]});
Geodesic *geodesic = (Geodesic *)ptr;
const Spacetime &st = geodesic->st;
auto chris = st.christoffels(x);
VecD v = st.velocity(x, v3, geodesic->V2);
VecD rhs(7);
rhs[0] = 1;
FOR(i, 3) { rhs[i + 1] = v3[i]; }
FOR(i, 3) { rhs[i + 1 + 3] = -chris[i + 1].prod(v).dot(v); }
// rhs.print();
return rhs;
}
bool geodesic_stopAtSingularity(const VecD &vars, const VecD ¶ms, void *ptr)
{
Geodesic *geodesic = (Geodesic *)ptr;
double BH_r = geodesic->st.BH_radius();
static double rMAX = 10000. * (BH_r == 0. ? 1. : BH_r);
double t = vars[0];
double r = vars[1];
double vr = vars[4];
return (r < BH_r * 0.95 &&
vr * t <= 0 /*>0 if backwards, <0 if forward*/) ||
r > rMAX || std::isnan(vr);
}