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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249 | {-
- Voimafunktio täällä
-}
module Astro.PostNewtonian
where
import Astro.Misc
import Numeric.LinearAlgebra
import Data.List (foldl')
-- Calculate Post-Newtonian acceleration functions for non-spin
-- dependent terms
mkNonSpinPNs :: Double->Double->Double->Double->
[(Vector Double->Vector Double->Vector Double)]
mkNonSpinPNs gc c m1 m2 = [ a1
, a2
, a2_5
]
where
-- Keplerian contribution
--a0 :: Vector Double -> Vector Double -> Vector Double
--a0 rv vv = scale (-gm / r^3) rv where r = norm rv
a1 :: Vector Double -> Vector Double -> Vector Double
a1 rv vv = {-# SCC "a1" #-}
scale (-gmperc2 / r^2) $
scale nbrac nv + scale vbrac vv
where
nbrac = -2*(2+eta)*gm/r + (1+3*eta)*v^2 - 3/2*eta*rd^2
vbrac = -2*(2-eta)*rd
r = norm rv
v = norm vv
nv = unitV rv
rd = (rv <.> vv)/r
a2 :: Vector Double -> Vector Double -> Vector Double
a2 rv vv = {-# SCC "a2" #-}
scale (- gmperc2 / (c^2 * r^2)) $
scale (nbrac/r) rv + scale ((-rd/2) * vbrac) vv
where
nbrac = 3/4*(12+29*eta)*(gm/r)^2 + eta*(3-4*eta)*v^4
+ 15/8*eta*(1-3*eta)*rd^4
- 3/2*eta*(3-4*eta)*v^2*rd^2
- 1/2*eta*(13-4*eta)*(gm/r)*v^2
- (2+25*eta+2*eta^2)*(gm/r)*rd^2
vbrac = eta*(15+4*eta)*v^2 - (eta+41*eta+8*eta^2)*(gm/r)
- 3*eta*(3+2*eta)*rd^2
r = norm rv
v = norm vv
rd = (rv <.> vv)/r
a2_5 :: Vector Double -> Vector Double -> Vector Double
a2_5 rv vv = {-# SCC "a2_5" #-}
scale (8/15*(gmperc2)^2*eta/(c*r^2)) $
scale (nbrac*rd/r) rv + scale (-vbrac) vv
where
nbrac = 9*v^2 + 17*gm/r
vbrac = 3*v^2 + 9*gm/r
r = norm rv
v = norm vv
rd = (rv <.> vv)/r
gm = gc * m
gmperc2 = gm / c ^2
m = m1+m2
eta = m1*m2/m^2
-- Calculate Post-Newtonian acceleration functions for spin
-- dependent terms
mkSpinPNs :: Double->Double->Double->Double->Double->Double->
[(Vector Double->Vector Double->Vector Double->Vector Double)]
mkSpinPNs gc c m1 m2 chi q = [ spinOrbit
, quadMonoInteraction
] where
spinOrbit :: Vector Double -> Vector Double -> Vector Double
-> Vector Double
spinOrbit rv vv s = {-# SCC "SO" #-}
scale (gm^2/(r^3*c^3)*(1+sqrt (1-4*eta))/4*chi) $
scale nbrac nv + scale (nsbrac) (cross nv s)
+ scale (-vsbrac) (cross vv s)
where
nbrac = 12 * s <.> (cross nv vv)
nsbrac = (9 + 3 * sqrt (1-4*eta))*rd
vsbrac = 7 + sqrt(1-4*eta)
r = norm rv
v = norm vv
nv = unitV rv
rd = (rv <.> vv)/r
quadMonoInteraction :: Vector Double -> Vector Double -> Vector Double
-> Vector Double
quadMonoInteraction rv vv s = {-# SCC "Q" #-}
-- FIXME: Minus or no minus? Depends on whether
-- coordinates fixed on m1 or m2, see OJ287 paper, minus
-- in paper.
scale (-q*chi^2*3*gc^3*m1^2*m/(2*c^4*r^4)) $
scale nbrac nv + scale (-2 * nv <.> s) s
where
nbrac = 5 * (nv <.> s)^2 - 1
r = norm rv
v = norm vv
nv = unitV rv
gm = gc * m
m = m1+m2
eta = m1*m2/m^2
-- Time derivative of spin unit vector
spinDt :: Double->Double->Double->Double->Double->Double->
Vector Double->Vector Double->Vector Double->Vector Double
spinDt gc c m1 m2 chi q rv vv s = cross omega s
where
omega = scale (gm*eta/(2*c^2*r^2)*(7+sqrt (1-4*eta))
/(1+sqrt (1-4*eta))) (cross nv vv)
r = norm rv
nv = scale (1/r) rv
gm = gc * m
m = m1+m2
eta = m1*m2/m^2
-- Post-Newtonian acceleration functions for highest supported degree
nonSpinPNAcc gc c m1 m2 rv vv =
sum [f rv vv | f <- mkNonSpinPNs gc c m1 m2]
spinPNAcc gc c m1 m2 chi q rv vv s =
sum [f rv vv s | f <- mkSpinPNs gc c m1 m2 chi q]
totalPNAcc gc c m1 m2 chi q rv vv s = ((f1 rv vv) + (f2 rv vv s))
where (f1, f2) = (nonSpinPNAcc gc c m1 m2,
spinPNAcc gc c m1 m2 chi q)
-- Explicitly calculated total acceleration
totalPNAccExp gc c m1 m2 chi q rv vv s =
a1 + spinOrbit + quadMono + a2 + a2_5
where
a1 = {-# SCC "a1" #-}
scale (-gmperc2 / r^2) $
scale nbrac nv + scale vbrac vv
where
nbrac = -2*(2+eta)*gm/r + (1+3*eta)*v^2 - 3/2*eta*rd^2
vbrac = -2*(2-eta)*rd
a2 = {-# SCC "a2" #-}
scale (- gmperc2 / (c^2 * r^2)) $
scale nbrac nv + scale ((-rd/2) * vbrac) vv
where
nbrac = 3/4*(12+29*eta)*(gm/r)^2 + eta*(3-4*eta)*v^4
+ 15/8*eta*(1-3*eta)*rd^4
- 3/2*eta*(3-4*eta)*v^2*rd^2
- 1/2*eta*(13-4*eta)*(gm/r)*v^2
- (2+25*eta+2*eta^2)*(gm/r)*rd^2
vbrac = eta*(15+4*eta)*v^2 - (eta+41*eta+8*eta^2)*(gm/r)
- 3*eta*(3+2*eta)*rd^2
a2_5 = {-# SCC "a2_5" #-}
scale (8/15*(gmperc2)^2*eta/(c*r^2)) $
scale (nbrac*rd) nv + scale (-vbrac) vv
where
nbrac = 9*v^2 + 17*gm/r
vbrac = 3*v^2 + 9*gm/r
spinOrbit = {-# SCC "SO" #-}
scale (gm^2/(r^3*c^3)*(1+sqrt (1-4*eta))/4*chi) $
scale nbrac nv + scale (nsbrac) (cross nv s)
+ scale (-vsbrac) (cross vv s)
where
nbrac = 12 * s <.> (cross nv vv)
nsbrac = (9 + 3 * sqrt (1-4*eta))*rd
vsbrac = 7 + sqrt(1-4*eta)
quadMono = {-# SCC "Q" #-}
scale (-q*chi^2*3*gc^3*m1^2*m/(2*c^4*r^4)) $
scale nbrac nv + scale (-2 * nv <.> s) s
where
nbrac = 5 * (nv <.> s)^2 - 1
r = norm rv
v = norm vv
nv = scale (1/r) rv
rd = (rv <.> vv)/r
gm = gc * m
gmperc2 = gm / c ^2
m = m1+m2
eta = m1*m2/m^2
{-
- käytetään täällä
-}
module Dynamics where
import State
import Astro.Kepler
import Astro.PostNewtonian
import Astro.Misc
import Numeric.LinearAlgebra
-- Calculate next state from previous one, depending on the timestep
nextState :: Parameters -> Double -> State -> State
nextState ps h s = State newRV newS newRVs where
(newRV, newS) = propagateBinary ps h s
newRVs = propagateDisk ps h s
-- 2nd order leapfrog for keplerian movement
kepLF2 f (r0,v0) h = (r2,v2) where
r1 = r0 + scale (h/2) v0
v2 = v0 + scale h (f r1)
r2 = r1 + scale (h/2) v2
-- Solve non-Keplerian perturbation iteratively
solvePerturbation f (r0,v0,s0) h (tol,maxIt) = iter 0 (3|>[0,0,0])
where iter n y
| norm (yNew - y) <= tol = yNew + v0
| n > maxIt = yNew + v0 `debug`
("solvePerturbation: iter. incomp., err: "
++(show $ norm(yNew-y))
++" tol: "++(show tol)
)
| otherwise = iter (n+1) yNew
-- `debug`
-- ("n: "++(show n)++" v0: "++(dispVector v0)++
-- " yNew: "++(dispVector yNew)++
-- "\n|yNew-y|: "++(show (norm (yNew-y))))
where yNew = scale h (f r0 (v0+scale 0.5 y) s0)
-- Propagate binary state
propagateBinary :: Parameters -> Double -> State
-> ((Vector Double, Vector Double), Vector Double)
propagateBinary p h s = ((newR, newV), newS) where
(r0,v0) = binaryRV s
s0 = binaryS s
--(r1,v1) = kepLF2 forceKep (r0, v0) (h/2) -- kepler leap
(r1,v1) = keplerPropagate r0 v0 (h/2) (kIterParams p)
v2 = solvePerturbation forcePN (r1,v1,s0) (h/2) (pIterParams p)
-- PN velocity jump
newS = s0 + scale h (ds r1 v2 s0) -- change in spin
v3 = solvePerturbation forcePN (r1,v2,newS) (h/2) (pIterParams p)
-- PN velocity jump
--(newR,newV) = kepLF2 forceKep (r1,v3) (h/2) -- kepler leap
(newR,newV) = keplerPropagate r1 v3 (h/2) (kIterParams p)
-- primary - secondary force
forceKep r = scale (-1.0/norm r ^ 3) r :: Vector Double
forcePN = totalPNAccExp 1.0 (phys_c p) (binaryM1 p) (binaryM2 p)
(binaryChi p) (binaryQ p)
-- spin time derivative
ds = spinDt 1.0 (phys_c p) (binaryM1 p) (binaryM2 p)
(binaryChi p) (binaryQ p)
|