monad-bayes-1.0.0: test/TestStormerVerlet.hs
module TestStormerVerlet
( passed1,
)
where
import Control.Lens
import Control.Monad.ST
import Data.Maybe (fromJust)
import qualified Data.Vector as V
import qualified Linear as L
import Linear.V
import Math.Integrators.StormerVerlet
gConst :: Double
gConst = 6.67384e-11
nStepsTwoPlanets :: Int
nStepsTwoPlanets = 44
stepTwoPlanets :: Double
stepTwoPlanets = 24 * 60 * 60 * 100
sunMass, jupiterMass :: Double
sunMass = 1.9889e30
jupiterMass = 1.8986e27
jupiterPerihelion :: Double
jupiterPerihelion = 7.405736e11
jupiterV :: [Double]
jupiterV = [-1.0965244901087316e02, -1.3710001990210707e04, 0.0]
jupiterQ :: [Double]
jupiterQ = [negate jupiterPerihelion, 0.0, 0.0]
sunV :: [Double]
sunV = [0.0, 0.0, 0.0]
sunQ :: [Double]
sunQ = [0.0, 0.0, 0.0]
tm :: V.Vector Double
tm = V.enumFromStepN 0 stepTwoPlanets nStepsTwoPlanets
keplerP :: L.V2 (L.V3 Double) -> L.V2 (L.V3 Double)
keplerP (L.V2 p1 p2) = L.V2 dHdP1 dHdP2
where
dHdP1 = p1 / pure jupiterMass
dHdP2 = p2 / pure sunMass
keplerQ :: L.V2 (L.V3 Double) -> L.V2 (L.V3 Double)
keplerQ (L.V2 q1 q2) = L.V2 dHdQ1 dHdQ2
where
r = q2 L.^-^ q1
ri = r `L.dot` r
rr = ri * (sqrt ri)
q1' = pure gConst * r / pure rr
q2' = negate q1'
dHdQ1 = q1' * pure sunMass * pure jupiterMass
dHdQ2 = q2' * pure sunMass * pure jupiterMass
listToV3 :: [a] -> L.V3 a
listToV3 [x, y, z] = fromV . fromJust . fromVector . V.fromList $ [x, y, z]
listToV3 xs = error $ "Only supply 3 elements not: " ++ show (length xs)
initPQ2s :: L.V2 (L.V2 (L.V3 Double))
initPQ2s =
L.V2
(L.V2 (listToV3 jupiterQ) (listToV3 sunQ))
(L.V2 (pure jupiterMass * listToV3 jupiterV) (pure sunMass * listToV3 sunV))
result2 :: V.Vector (L.V2 (L.V2 (L.V3 Double)))
result2 = runST $ integrateV (\h -> stormerVerlet2H (pure h) keplerQ keplerP) initPQ2s tm
energy :: (L.V2 (L.V2 (L.V3 Double))) -> Double
energy x = keJ + keS + peJ + peS
where
qs = x ^. _1
ps = x ^. _2
qJ = qs ^. _1
qS = qs ^. _2
pJ = ps ^. _1
pS = ps ^. _2
keJ = (* 0.5) $ (/ jupiterMass) $ sum $ fmap (^ 2) pJ
keS = (* 0.5) $ (/ sunMass) $ sum $ fmap (^ 2) pS
r = qJ L.^-^ qS
ri = r `L.dot` r
peJ = 0.5 * gConst * sunMass * jupiterMass / (sqrt ri)
peS = 0.5 * gConst * sunMass * jupiterMass / (sqrt ri)
energies :: V.Vector Double
energies = fmap energy result2
diffs :: V.Vector Double
diffs = V.zipWith (\x y -> abs (x - y) / x) energies (V.tail energies)
passed1 :: IO Bool
passed1 = return $ V.all (< 1.0e-3) diffs