diff options
Diffstat (limited to 'packages/sundials/src/Numeric/Sundials/ARKode')
-rw-r--r-- | packages/sundials/src/Numeric/Sundials/ARKode/ODE.hs | 44 |
1 files changed, 37 insertions, 7 deletions
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. |
242 | odeSolveV | 242 | odeSolveV |
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 |
251 | odeSolveV meth _hi epsAbs epsRel f y0 ts = | 256 | odeSolveV 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 |
270 | odeSolve f y0 ts = | 275 | odeSolve 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 = | |||
281 | odeSolveVWith :: | 286 | odeSolveVWith :: |
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 |
288 | odeSolveVWith method control f y0 tt = | 299 | odeSolveVWith 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 | ||
309 | solveOdeC :: | 320 | solveOdeC :: |
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 |
317 | solveOdeC method jacH (absTols, relTol) fun f0 ts = unsafePerformIO $ do | 329 | solveOdeC 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[]))); |