|
6 | 6 |
|
7 | 7 | using namespace std;
|
8 | 8 |
|
| 9 | +// This is the computation of the full EIH equations in 1PN limit. The equations are based |
| 10 | +// on (Will 2014) section 3. See Arxiv:1312.1289v3 |
| 11 | +// The higher order terms that are added are found in REF |
| 12 | + |
9 | 13 | void EIHPerturbation::CalculateAccelerations(Model *model, int thread_id, int num_threads)
|
10 | 14 | {
|
11 | 15 | ParticleSetView &all = model->GetAllParticles();
|
12 | 16 | Real c2_recipr = 1 / (m_SpeedOfLight * m_SpeedOfLight);
|
13 |
| - |
| 17 | + Real c4_recipr = c2_recipr * c2_recipr; |
| 18 | + Real c5_recipr = c4_recipr / m_SpeedOfLight; |
| 19 | + // The primary double loop includes all direct interactions between the masses |
14 | 20 | for (Particle &a : Strided(all, thread_id, num_threads))
|
15 | 21 | {
|
16 | 22 | for (Particle &b : all)
|
17 | 23 | {
|
| 24 | + // No summation over the particle interacting with itself |
18 | 25 | if (a == b)
|
19 | 26 | continue;
|
20 |
| - |
| 27 | + |
| 28 | + // |
| 29 | + // Compute the differences in position and velocity |
21 | 30 | Vec x_ab = a.pos - b.pos;
|
22 | 31 | Vec v_ab = a.vel - b.vel;
|
23 |
| - |
24 |
| - Real r_ab2 = x_ab.SquaredNorm(); |
25 |
| - Real r_ab = sqrt(r_ab2); |
26 |
| - Real r_ab3 = r_ab * r_ab2; |
27 |
| - |
28 |
| - Vec n_ab = x_ab / r_ab; |
29 |
| - Real m_a_over_r_ab = a.mass / r_ab; |
30 |
| - Real m_b_over_r_ab = b.mass / r_ab; |
31 |
| - Real m_b_over_r_ab3 = b.mass / r_ab3; |
32 |
| - |
33 |
| - Real v_b_dot_n_ab = b.vel.Dot(n_ab); |
34 |
| - |
35 |
| - a.acc_pert += c2_recipr * v_ab * (m_b_over_r_ab3 * x_ab.Dot(4*a.vel - 3*b.vel)); |
36 |
| - |
37 |
| - Real temp = 4 * m_b_over_r_ab; |
38 |
| - temp += 5 * m_a_over_r_ab; |
39 |
| - temp -= a.vel.SquaredNorm(); |
40 |
| - temp += 4 * a.vel.Dot(b.vel); |
41 |
| - temp -= 2 * b.vel.SquaredNorm(); |
42 |
| - temp += 1.5 * v_b_dot_n_ab * v_b_dot_n_ab; |
43 |
| - |
| 32 | + // compute the distances and its powers |
| 33 | + Real r_ab2 = x_ab.SquaredNorm(); // PN0.0 |
| 34 | + Real r_ab = sqrt(r_ab2); // PN1.0 |
| 35 | + Real r_ab3 = r_ab * r_ab2; // PN1.0 |
| 36 | + // Compute the normal vector, and mass to distance ratios |
| 37 | + Vec n_ab = x_ab / r_ab; // PN0.0 |
| 38 | + Real m_a_over_r_ab = a.mass / r_ab; // PN1.0 |
| 39 | + Real m_b_over_r_ab = b.mass / r_ab; // PN1.0 |
| 40 | + Real m_b_over_r_ab3 = b.mass / r_ab3; // PN1.0 |
| 41 | + Real m_b_over_r_ab2 = b.mass / r_ab2; // PN1.0 |
| 42 | + |
| 43 | + // Compute the inner products used in the equations |
| 44 | + Real v_b_dot_n_ab = b.vel.Dot(n_ab); // PN1.0 |
| 45 | + Real v_a_dot_v_b = a.vel.Dot(b.vel); // PN1.0 |
| 46 | + Real v_a_dot_v_a = a.vel.SquaredNorm(); // PN1.0 |
| 47 | + Real v_b_dot_v_b = b.vel.SquaredNorm(); // PN1.0 |
| 48 | + Real square_v_a_dot_v_a = v_a_dot_v_a * v_a_dot_v_a; // PN1.0 |
| 49 | + Real square_v_b_dot_v_b = b.vel.SquaredNorm() * b.vel.SquaredNorm(); // PN1.0 |
| 50 | + Real v_a_dot_n_ab = a.vel.Dot(n_ab); // PN2.0 |
| 51 | + Real square_v_a_dot_v_b = a.vel.Dot(b.vel) * a.vel.Dot(b.vel); // PN2.0 |
| 52 | + Real square_v_b_dot_n_ab = v_b_dot_n_ab * v_b_dot_n_ab; // PN2.0 |
| 53 | + Real square_v_a_dot_n_ab = v_a_dot_n_ab * v_a_dot_n_ab; // PN2.0 |
| 54 | + Real cubed_v_b_dot_n_ab = square_v_b_dot_n_ab * v_b_dot_n_ab; // PN2.0 |
| 55 | + Real quarted_v_b_dot_n_ab = square_v_b_dot_n_ab * square_v_b_dot_n_ab; // PN2.0 |
| 56 | + |
| 57 | + // Where does the PN 0.0 term apply? |
| 58 | + // PN 1.0 |
| 59 | + Real temp = 5.0 * m_a_over_r_ab; |
| 60 | + temp += 4.0 * m_b_over_r_ab; |
| 61 | + temp += 1.5 * v_a_dot_n_ab; |
| 62 | + temp -= v_a_dot_v_a; |
| 63 | + temp += 4.0 * v_a_dot_v_b; |
| 64 | + temp -= 2.0 * v_b_dot_v_b; |
| 65 | + |
| 66 | + // Include the cross terms between all particle a and particles b and c. |
44 | 67 | for (Particle &c : all)
|
45 | 68 | {
|
| 69 | + // No summation over the particles interacting with themselves |
46 | 70 | if (a == c || b == c)
|
47 | 71 | continue;
|
48 |
| - |
| 72 | + |
49 | 73 | Vec x_bc = b.pos - c.pos;
|
50 | 74 | Vec x_ac = a.pos - c.pos;
|
51 |
| - |
| 75 | + |
52 | 76 | Real r_bc2 = x_bc.SquaredNorm();
|
53 | 77 | Real r_bc = sqrt(r_bc2);
|
54 | 78 | Real r_bc3 = r_bc2 * r_bc;
|
55 | 79 | Real r_ac = x_ac.Norm();
|
56 |
| - |
| 80 | + Real n_bc = x_bc / r_bc; |
| 81 | + |
57 | 82 | Real m_c_over_r_bc3 = c.mass / r_bc3;
|
58 |
| - |
| 83 | + // Add the 3 cross terms |
59 | 84 | temp += c.mass / r_bc;
|
60 |
| - temp += 4 * c.mass / r_ac; |
| 85 | + temp += 4.0 * c.mass / r_ac; |
61 | 86 | temp -= 0.5 * m_c_over_r_bc3 * x_ab.Dot(x_bc);
|
62 |
| - |
| 87 | + // Seperately add the 7/2 cross term (since it does not scale with m_b_over_r_ab3) |
63 | 88 | a.acc_pert -= c2_recipr * x_bc * (3.5 * m_b_over_r_ab * m_c_over_r_bc3);
|
64 | 89 | }
|
65 |
| - |
66 |
| - a.acc_pert += c2_recipr * x_ab * (m_b_over_r_ab3 * temp); |
| 90 | + // Add the 1st PN in the v_ab direction |
| 91 | + a.acc_pert += c2_recipr * v_ab * (m_b_over_r_ab2 * (4.0 * v_a_dot_n_ab - 3.0 * v_b_dot_n_ab)); |
| 92 | + // Add the sum of the pair and cross terms in the n_ab direction |
| 93 | + a.acc_pert += c2_recipr * n_ab * (m_b_over_r_ab2 * temp); |
| 94 | + |
| 95 | + // PN 2.0 |
| 96 | + Real inv_r_ab2 = 1.0 / r_ab2; // computing inverse and reusing it |
| 97 | + Real temp = -14.25 * a.mass * a.mass * inv_r_ab2; // 57/4 |
| 98 | + temp -= 34.5 * a.mass * b.mass * inv_r_ab2; // 69/2 |
| 99 | + temp -= 9.0 * b.mass * b.mass * inv_r_ab2; // 9 |
| 100 | + temp -= 1.875 * quarted_v_b_dot_n_ab; // 16/8 |
| 101 | + temp += 1.5 * square_v_b_dot_n_ab * v_a_dot_v_a; // 3/2 |
| 102 | + temp -= 6.0 * square_v_b_dot_v_b * v_a_dot_v_b; // 6 |
| 103 | + temp -= 2.0 * square_v_a_dot_v_b; // 2 |
| 104 | + temp += 4.5 * square_v_b_dot_n_ab * v_b_dot_n_ab; // 9/2 |
| 105 | + temp += 4.0 * v_a_dot_v_b * v_b_dot_v_b; // 4 |
| 106 | + temp -= 2.0 * v_b_dot_v_b; // 2 |
| 107 | + // Compute longer terms with new dummy variable |
| 108 | + Real temp2 = 19.5 * square_v_a_dot_n_ab; // 39/2 |
| 109 | + temp2 -= 39.0 * v_a_dot_n_ab * v_b_dot_n_ab; // 39 |
| 110 | + temp2 += 8.5 * square_v_b_dot_n_ab; // 17/2 |
| 111 | + temp2 -= 3.75 * v_a_dot_v_a; // 15/4 |
| 112 | + temp2 += 2.5 * v_a_dot_v_b; // 5/2 |
| 113 | + temp2 += 1.25 * v_b_dot_v_b; // 5/4 |
| 114 | + temp += a.mass / r_ab * temp2; |
| 115 | + // Next long term |
| 116 | + Real temp2 = 2.0 * square_v_a_dot_n_ab; // 2 |
| 117 | + temp2 -= 4.0 * v_a_dot_n_ab * v_b_dot_n_ab; // 4 |
| 118 | + temp2 -= 6.0 * square_v_b_dot_n_ab; // 6 |
| 119 | + temp2 -= 8.0 * v_a_dot_v_b; // 8 |
| 120 | + temp2 += 4.0 * v_b_dot_v_b; // 4 |
| 121 | + temp += b.mass / r_ab * temp2; |
| 122 | + // Add the 2.0 PN contributions in n_ab |
| 123 | + a.acc_pert += c4_recipr * n_ab * (m_b_over_r_ab2 * temp); |
| 124 | + // Compute the v_ab contributions |
| 125 | + Real temp = m_b_over_r_ab * (-2.0 * v_a_dot_n_ab - 2.0 * v_b_dot_n_ab); // 2, 2 |
| 126 | + temp += m_a_over_r_ab * (-15.75 * v_a_dot_n_ab + 13.75 * v_b_dot_n_ab); // -63/4, 55/4 |
| 127 | + temp += 6.0 * v_a_dot_n_ab * square_v_b_dot_n_ab; // 6 |
| 128 | + temp += 4.5 * cubed_v_b_dot_n_ab; // 9/2 |
| 129 | + temp += v_b_dot_n_ab * v_a_dot_v_a; // 1 |
| 130 | + temp -= 4.0 * v_a_dot_n_ab * v_a_dot_v_b; // -4 |
| 131 | + temp += 4.0 * v_b_dot_n_ab * v_a_dot_v_b; // +4 |
| 132 | + temp += 4.0 * v_a_dot_n_ab * v_b_dot_v_b; // +4 |
| 133 | + temp -= 5.0 * v_b_dot_n_ab * v_b_dot_v_b; // -5 |
| 134 | + a.acc_pert += c4_recipr * v_ab * (m_b_over_r_ab2 * temp); |
| 135 | + |
| 136 | + // PN 2.5 |
| 137 | + Real m_a_m_b_over_r_ab3 = a.mass * b.mass / r_ab3; |
| 138 | + Real v_ab_dot_n_ab = v_ab.Dot(n_ab); |
| 139 | + Real v_ab_dot_v_ab = v_ab.SquaredNorm(); |
| 140 | + // Compute the n_ab terms for PN 2.5 |
| 141 | + Real temp = 52.0 / 3.0 * b.mass / r_ab * v_ab_dot_n_ab; // 52/3 |
| 142 | + temp -= 6.0 * a.mass / r_ab * v_ab_dot_n_ab; // 6 |
| 143 | + temp += 3.0 * (v_ab_dot_n_ab)*v_ab_dot_v_ab; // 3 |
| 144 | + a.acc_pert += c5_recipr * n_ab * (0.8 * m_a_m_b_over_r_ab3 * temp); |
| 145 | + Real temp = 2.0 * a.mass / r_ab; // 2 |
| 146 | + temp -= 8.0 * b.mass / r_ab; // 8 |
| 147 | + temp -= v_ab_dot_v_ab; // 1 |
| 148 | + a.acc_pert += c5_recipr * v_ab * (0.8 * m_a_m_b_over_r_ab3 * temp); |
67 | 149 | }
|
68 | 150 | }
|
69 |
| -} |
70 | 151 |
|
71 |
| -Real EIHPerturbation::GetEnergy(Model *model) |
72 |
| -{ |
73 |
| - ParticleSetView &all = model->GetAllParticles(); |
74 |
| - Real energy = 0; |
75 |
| - |
76 |
| - for (Particle &a : all) |
| 152 | + Real EIHPerturbation::GetEnergy(Model * model) |
77 | 153 | {
|
78 |
| - Vec v_a = a.vel; |
79 |
| - Real v_a2 = v_a.SquaredNorm(); |
80 |
| - |
81 |
| - Real energypart = 0.375 * v_a2*v_a2; |
82 |
| - for (Particle &b : all) |
| 154 | + ParticleSetView &all = model->GetAllParticles(); |
| 155 | + Real energy = 0; |
| 156 | + Real c2_recipr = 1 / (m_SpeedOfLight * m_SpeedOfLight); |
| 157 | + Real c4_recipr = c2_recipr * c2_recipr; |
| 158 | + |
| 159 | + for (Particle &a : all) |
83 | 160 | {
|
84 |
| - if (a == b) |
85 |
| - continue; |
86 |
| - |
87 |
| - Real r_ab = sqrt((a.pos - b.pos).SquaredNorm()); |
88 |
| - Real m_b_over_r_ab = b.mass / r_ab; |
89 |
| - Vec n_ab = (a.pos - b.pos) / r_ab; |
90 |
| - |
91 |
| - energypart += 1.5 * v_a2 * m_b_over_r_ab; |
92 |
| - |
93 |
| - Real temp = 7*a.vel.Dot(b.vel); |
94 |
| - temp += a.vel.Dot(n_ab) * b.vel.Dot(n_ab); |
95 |
| - energypart -= 0.25 * m_b_over_r_ab * temp; |
96 |
| - |
97 |
| - for (Particle &c : all) |
| 161 | + Vec v_a = a.vel; |
| 162 | + Real v_a_dot_v_a = v_a.SquaredNorm(); |
| 163 | + Real square_v_a_dot_v_a = v_a_dot_v_a * v_a_dot_v_a; // PN1.0 |
| 164 | + // 1PN kinetic term |
| 165 | + energy += c2_recipr * a.mass * 0 .375 * v_a_dot_v_a * v_a_dot_v_a; |
| 166 | + // 2PN kinetic term |
| 167 | + energy += c4_recipr * a.mass * 0.3125 * v_a_dot_v_a * v_a_dot_v_a * v_a_dot_v_a; |
| 168 | + for (Particle &b : all) |
98 | 169 | {
|
99 |
| - // Note: it could be b == c, which is not clear in Will (2014a) |
100 |
| - if (a == c) |
| 170 | + if (a == b) |
101 | 171 | continue;
|
102 |
| - |
103 |
| - Real r_ac = (a.pos - c.pos).Norm(); |
104 |
| - energypart += 0.5 * m_b_over_r_ab * c.mass / r_ac; |
| 172 | + |
| 173 | + // Compute the differences in position and velocity |
| 174 | + Vec x_ab = a.pos - b.pos; |
| 175 | + Vec v_ab = a.vel - b.vel; |
| 176 | + // compute the distances and its powers |
| 177 | + Real r_ab2 = x_ab.SquaredNorm(); // PN0.0 |
| 178 | + Real r_ab = sqrt(r_ab2); // PN1.0 |
| 179 | + Real r_ab3 = r_ab * r_ab2; // PN1.0 |
| 180 | + // Compute the normal vector, and mass to distance ratios |
| 181 | + Vec n_ab = x_ab / r_ab; // PN0.0 |
| 182 | + Real m_a_over_r_ab = a.mass / r_ab; // PN1.0 |
| 183 | + Real ma_am_b_over_r_ab = a.mass * b.mass / r_ab; // PN1.0 |
| 184 | + Real ma_m_b_over_r_ab3 = a.mass * b.mass / r_ab3; // PN1.0 |
| 185 | + Real ma_m_b_over_r_ab2 = a.mass * b.mass / r_ab2; // PN1.0 |
| 186 | + Real m_b_over_r_ab = b.mass / r_ab; // PN1.0 |
| 187 | + |
| 188 | + // Compute the inner products used in the equations |
| 189 | + Real v_b_dot_n_ab = b.vel.Dot(n_ab); // PN1.0 |
| 190 | + Real v_a_dot_v_b = a.vel.Dot(b.vel); // PN1.0 |
| 191 | + Real v_b_dot_v_b = b.vel.SquaredNorm(); // PN1.0 |
| 192 | + Real square_v_b_dot_v_b = b.vel.SquaredNorm() * b.vel.SquaredNorm(); // PN1.0 |
| 193 | + Real v_a_dot_n_ab = a.vel.Dot(n_ab); // PN2.0 |
| 194 | + Real square_v_b_dot_n_ab = v_b_dot_n_ab * v_b_dot_n_ab; // PN2.0 |
| 195 | + Real square_v_a_dot_n_ab = v_a_dot_n_ab * v_a_dot_n_ab; // PN2.0 |
| 196 | + Real cubed_v_a_dot_n_ab = square_v_a_dot_n_ab * v_a_dot_n_ab; // PN2.0 |
| 197 | + Real quarted_v_b_dot_n_ab = square_v_b_dot_n_ab * square_v_b_dot_n_ab; // PN2.0 |
| 198 | + |
| 199 | + // 1PN terms |
| 200 | + Real energypart = 1.5 * va_dot_va * m_b_over_r_ab; |
| 201 | + Real energytemp = 7.0 * a.vel.Dot(b.vel); |
| 202 | + energytemp += a.vel.Dot(n_ab) * b.vel.Dot(n_ab); |
| 203 | + energypart -= 0.25 * m_b_over_r_ab * energytemp; |
| 204 | + // 1PN cross terms |
| 205 | + for (Particle &c : all) |
| 206 | + { |
| 207 | + // Note: it could be b == c, which is not clear in Will (2014a) |
| 208 | + if (a == c) |
| 209 | + continue; |
| 210 | + |
| 211 | + Real r_ac = (a.pos - c.pos).Norm(); |
| 212 | + energypart += 0.5 * m_b_over_r_ab * c.mass / r_ac; |
| 213 | + } |
| 214 | + // ADD 1PN terms |
| 215 | + energy += c2_recipr * energypart * a.mass; |
| 216 | + // 2PN terms |
| 217 | + Real energypart = -0.5 * m_a_over_r_ab * m_a_over_r_ab; |
| 218 | + energypart -= 2.375 * m_a_over_r_ab * m_b_over_r_ab; |
| 219 | + energypart += 0.375 * cubed_v_a_dot_n_ab * v_b_dot_n_ab; |
| 220 | + energypart += 0.1875 * square_v_a_dot_n_ab * square_v_b_dot_n_ab; |
| 221 | + energypart -= 1.125 * v_a_dot_n_ab * v_b_dot_n_ab * v_a_dot_v_a; |
| 222 | + energypart -= 1.625 * square_v_b_dot_n_ab * v_a_dot_v_a; |
| 223 | + energypart += 2.625 * square_v_a_dot_v_a; |
| 224 | + energypart += 1.625 * square_v_a_dot_n_ab * v_a_dot_v_b; |
| 225 | + energypart += 0.75 * v_a_dot_n_ab * v_b_dot_n_ab * v_a_dot_v_b; |
| 226 | + energypart -= 6.875 * v_a_dot_v_a * v_a_dot_v_b; |
| 227 | + energypart += 2.125 * v_a_dot_v_b * v_a_dot_v_b; |
| 228 | + energypart += 1.9375 * v_a_dot_v_a * v_b_dot_v_b; |
| 229 | + Real energytemp = 7.25 * square_v_a_dot_n_ab; |
| 230 | + energytemp -= 3.25 * v_a_dot_n_ab * v_b_dot_n_ab; |
| 231 | + energytemp += 0.5 * square_v_b_dot_n_ab; |
| 232 | + energytemp += 1.5 * v_a_dot_v_a; |
| 233 | + energytemp += 1.75 * v_b_dot_v_b; |
| 234 | + energypart += energytemp * m_a_over_r_ab; |
| 235 | + energy += a.mass * c4_recipr * energypart * m_b_over_r_ab; |
105 | 236 | }
|
106 | 237 | }
|
107 |
| - |
108 |
| - energy += energypart * a.mass; |
| 238 | + return energy; |
109 | 239 | }
|
110 |
| - |
111 |
| - energy /= m_SpeedOfLight * m_SpeedOfLight; |
112 | 240 |
|
113 |
| - return energy; |
114 |
| -} |
115 |
| - |
116 |
| -Vec EIHPerturbation::GetLinearMomentum(Model *model) |
117 |
| -{ |
118 |
| - // TODO |
119 |
| - ParticleSetView &all = model->GetAllParticles(); |
120 |
| - Vec momentum = Vec::Zero(); |
121 |
| - |
122 |
| - for (Particle &p : all) |
| 241 | + Vec EIHPerturbation::GetLinearMomentum(Model * model) |
123 | 242 | {
|
124 |
| - momentum += p.mass * p.vel; |
| 243 | + // This term is computed up to 1PN with cross terms |
| 244 | + ParticleSetView &all = model->GetAllParticles(); |
| 245 | + Vec momentum = Vec::Zero(); |
| 246 | + Real c2_recipr = 1 / (m_SpeedOfLight * m_SpeedOfLight); |
| 247 | + |
| 248 | + for (Particle &a : all) |
| 249 | + { |
| 250 | + // 0PN |
| 251 | + momentum += a.mass * a.vel; |
| 252 | + // 1PN |
| 253 | + Real v_a_dot_v_a = v_a.SquaredNorm(); |
| 254 | + Vec momentumpart = v_a_dot_v_a * a.vel; |
| 255 | + for (Particle &b : all) |
| 256 | + { |
| 257 | + if (b == a) |
| 258 | + continue; |
| 259 | + Vec x_ab = a.pos - b.pos; |
| 260 | + Real r_ab = x_ab.Norm(); |
| 261 | + Vec n_ab = x_ab / r_ab; |
| 262 | + momentumpart -= b.mass / r_ab * a.vel; |
| 263 | + momentumpart -= b.mass / r_ab * (a.vel.Dot(n_ab)) * n_ab |
| 264 | + } |
| 265 | + momentum += 0.5 * c2_recipr * a.mass * momentumpart |
| 266 | + } |
| 267 | + return momentum; |
125 | 268 | }
|
126 |
| - |
127 |
| - return momentum; |
128 |
| -} |
|
0 commit comments