summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorDominic Steinitz <dominic@steinitz.org>2018-04-17 12:09:35 +0100
committerDominic Steinitz <dominic@steinitz.org>2018-04-17 12:09:35 +0100
commit09f2d4cea649be1185183164fc65789c5944a2c8 (patch)
tree47a28228a897bc547d0fddccfafc8e1d835384c9 /packages
parent9336945b570c81533bbd77bbcc084f5954791f95 (diff)
Support user-defined initial step size
Diffstat (limited to 'packages')
-rw-r--r--packages/sundials/src/Main.hs2
-rw-r--r--packages/sundials/src/Numeric/Sundials/ARKode/ODE.hs44
2 files changed, 38 insertions, 8 deletions
diff --git a/packages/sundials/src/Main.hs b/packages/sundials/src/Main.hs
index 14b1f8a..e96522f 100644
--- a/packages/sundials/src/Main.hs
+++ b/packages/sundials/src/Main.hs
@@ -144,7 +144,7 @@ main = do
144 (D.dims2D 500.0 500.0) 144 (D.dims2D 500.0 500.0)
145 (renderAxis $ kSaxis $ zip [0.0, 0.1 .. 10.0] (concat $ toLists res2)) 145 (renderAxis $ kSaxis $ zip [0.0, 0.1 .. 10.0] (concat $ toLists res2))
146 146
147 let res2a = odeSolveV (SDIRK_5_3_4 stiffJac) 0.1 1e-3 1e-6 stiffishV (fromList [0.0]) (fromList [0.0, 0.1 .. 10.0]) 147 let res2a = odeSolveV (SDIRK_5_3_4 stiffJac) Nothing 1e-3 1e-6 stiffishV (fromList [0.0]) (fromList [0.0, 0.1 .. 10.0])
148 putStrLn "Lower tolerances" 148 putStrLn "Lower tolerances"
149 putStrLn $ show res2a 149 putStrLn $ show res2a
150 150
diff --git a/packages/sundials/src/Numeric/Sundials/ARKode/ODE.hs b/packages/sundials/src/Numeric/Sundials/ARKode/ODE.hs
index ee8def5..444138d 100644
--- a/packages/sundials/src/Numeric/Sundials/ARKode/ODE.hs
+++ b/packages/sundials/src/Numeric/Sundials/ARKode/ODE.hs
@@ -241,15 +241,20 @@ getJacobian (SDIRK_5_3_4' ) = Nothing
241-- | A version of 'odeSolveVWith' with reasonable default step control. 241-- | A version of 'odeSolveVWith' with reasonable default step control.
242odeSolveV 242odeSolveV
243 :: ODEMethod 243 :: ODEMethod
244 -> Double -- ^ initial step size 244 -> Maybe Double -- ^ initial step size - by default, ARKode
245 -- estimates the initial step size to be the
246 -- solution \(h\) of the equation
247 -- \(\|\frac{h^2\ddot{y}}{2}\| = 1\), where
248 -- \(\ddot{y}\) is an estimated value of the
249 -- second derivative of the solution at \(t_0\)
245 -> Double -- ^ absolute tolerance for the state vector 250 -> Double -- ^ absolute tolerance for the state vector
246 -> Double -- ^ relative tolerance for the state vector 251 -> Double -- ^ relative tolerance for the state vector
247 -> (Double -> Vector Double -> Vector Double) -- ^ The RHS of the system \(\dot{y} = f(t,y)\) 252 -> (Double -> Vector Double -> Vector Double) -- ^ The RHS of the system \(\dot{y} = f(t,y)\)
248 -> Vector Double -- ^ initial conditions 253 -> Vector Double -- ^ initial conditions
249 -> Vector Double -- ^ desired solution times 254 -> Vector Double -- ^ desired solution times
250 -> Matrix Double -- ^ solution 255 -> Matrix Double -- ^ solution
251odeSolveV meth _hi epsAbs epsRel f y0 ts = 256odeSolveV meth hi epsAbs epsRel f y0 ts =
252 case odeSolveVWith meth (X epsAbs epsRel) g y0 ts of 257 case odeSolveVWith meth (X epsAbs epsRel) hi g y0 ts of
253 Left c -> error $ show c -- FIXME 258 Left c -> error $ show c -- FIXME
254 -- FIXME: Can we do better than using lists? 259 -- FIXME: Can we do better than using lists?
255 Right (v, d) -> trace (show d) $ (nR >< nC) (V.toList v) 260 Right (v, d) -> trace (show d) $ (nR >< nC) (V.toList v)
@@ -269,7 +274,7 @@ odeSolve :: (Double -> [Double] -> [Double]) -- ^ The RHS of the system \(\dot{y
269 -> Matrix Double -- ^ solution 274 -> Matrix Double -- ^ solution
270odeSolve f y0 ts = 275odeSolve f y0 ts =
271 -- FIXME: These tolerances are different from the ones in GSL 276 -- FIXME: These tolerances are different from the ones in GSL
272 case odeSolveVWith SDIRK_5_3_4' (XX' 1.0e-6 1.0e-10 1 1) g (V.fromList y0) (V.fromList $ toList ts) of 277 case odeSolveVWith SDIRK_5_3_4' (XX' 1.0e-6 1.0e-10 1 1) Nothing g (V.fromList y0) (V.fromList $ toList ts) of
273 Left c -> error $ show c -- FIXME 278 Left c -> error $ show c -- FIXME
274 Right (v, d) -> trace (show d) $ (nR >< nC) (V.toList v) 279 Right (v, d) -> trace (show d) $ (nR >< nC) (V.toList v)
275 where 280 where
@@ -281,12 +286,18 @@ odeSolve f y0 ts =
281odeSolveVWith :: 286odeSolveVWith ::
282 ODEMethod 287 ODEMethod
283 -> StepControl 288 -> StepControl
289 -> Maybe Double -- ^ initial step size - by default, ARKode
290 -- estimates the initial step size to be the
291 -- solution \(h\) of the equation
292 -- \(\|\frac{h^2\ddot{y}}{2}\| = 1\), where
293 -- \(\ddot{y}\) is an estimated value of the second
294 -- derivative of the solution at \(t_0\)
284 -> (Double -> V.Vector Double -> V.Vector Double) -- ^ The RHS of the system \(\dot{y} = f(t,y)\) 295 -> (Double -> V.Vector Double -> V.Vector Double) -- ^ The RHS of the system \(\dot{y} = f(t,y)\)
285 -> V.Vector Double -- ^ Initial conditions 296 -> V.Vector Double -- ^ Initial conditions
286 -> V.Vector Double -- ^ Desired solution times 297 -> V.Vector Double -- ^ Desired solution times
287 -> Either Int ((V.Vector Double), SundialsDiagnostics) -- ^ Error code or solution 298 -> Either Int ((V.Vector Double), SundialsDiagnostics) -- ^ Error code or solution
288odeSolveVWith method control f y0 tt = 299odeSolveVWith method control initStepSize f y0 tt =
289 case solveOdeC (fromIntegral $ getMethod method) jacH (scise control) 300 case solveOdeC (fromIntegral $ getMethod method) (coerce initStepSize) jacH (scise control)
290 (coerce f) (coerce y0) (coerce tt) of 301 (coerce f) (coerce y0) (coerce tt) of
291 Left c -> Left $ fromIntegral c 302 Left c -> Left $ fromIntegral c
292 Right (v, d) -> Right (coerce v, d) 303 Right (v, d) -> Right (coerce v, d)
@@ -308,13 +319,24 @@ odeSolveVWith method control f y0 tt =
308 319
309solveOdeC :: 320solveOdeC ::
310 CInt -> 321 CInt ->
322 Maybe CDouble ->
311 (Maybe (CDouble -> V.Vector CDouble -> T.SunMatrix)) -> 323 (Maybe (CDouble -> V.Vector CDouble -> T.SunMatrix)) ->
312 (V.Vector CDouble, CDouble) -> 324 (V.Vector CDouble, CDouble) ->
313 (CDouble -> V.Vector CDouble -> V.Vector CDouble) -- ^ The RHS of the system \(\dot{y} = f(t,y)\) 325 (CDouble -> V.Vector CDouble -> V.Vector CDouble) -- ^ The RHS of the system \(\dot{y} = f(t,y)\)
314 -> V.Vector CDouble -- ^ Initial conditions 326 -> V.Vector CDouble -- ^ Initial conditions
315 -> V.Vector CDouble -- ^ Desired solution times 327 -> V.Vector CDouble -- ^ Desired solution times
316 -> Either CInt ((V.Vector CDouble), SundialsDiagnostics) -- ^ Error code or solution 328 -> Either CInt ((V.Vector CDouble), SundialsDiagnostics) -- ^ Error code or solution
317solveOdeC method jacH (absTols, relTol) fun f0 ts = unsafePerformIO $ do 329solveOdeC method initStepSize jacH (absTols, relTol) fun f0 ts = unsafePerformIO $ do
330
331 let isInitStepSize :: CInt
332 isInitStepSize = fromIntegral $ fromEnum $ isJust initStepSize
333 ss :: CDouble
334 ss = case initStepSize of
335 -- It would be better to put an error message here but
336 -- inline-c seems to evaluate this even if it is never
337 -- used :(
338 Nothing -> 0.0
339 Just x -> x
318 let dim = V.length f0 340 let dim = V.length f0
319 nEq :: CLong 341 nEq :: CLong
320 nEq = fromIntegral dim 342 nEq = fromIntegral dim
@@ -416,6 +438,14 @@ solveOdeC method jacH (absTols, relTol) fun f0 ts = unsafePerformIO $ do
416 flag = ARKDlsSetLinearSolver(arkode_mem, LS, A); 438 flag = ARKDlsSetLinearSolver(arkode_mem, LS, A);
417 if (check_flag(&flag, "ARKDlsSetLinearSolver", 1)) return 1; 439 if (check_flag(&flag, "ARKDlsSetLinearSolver", 1)) return 1;
418 440
441 /* Set the initial step size if there is one */
442 if ($(int isInitStepSize)) {
443 /* FIXME: We could check if the initial step size is 0 */
444 /* or even NaN and then throw an error */
445 flag = ARKodeSetInitStep(arkode_mem, $(double ss));
446 if (check_flag(&flag, "ARKodeSetInitStep", 1)) return 1;
447 }
448
419 /* Set the Jacobian if there is one */ 449 /* Set the Jacobian if there is one */
420 if ($(int isJac)) { 450 if ($(int isJac)) {
421 flag = ARKDlsSetJacFn(arkode_mem, $fun:(int (* jacIO) (double t, SunVector y[], SunVector fy[], SunMatrix Jac[], void * params, SunVector tmp1[], SunVector tmp2[], SunVector tmp3[]))); 451 flag = ARKDlsSetJacFn(arkode_mem, $fun:(int (* jacIO) (double t, SunVector y[], SunVector fy[], SunMatrix Jac[], void * params, SunVector tmp1[], SunVector tmp2[], SunVector tmp3[])));