From eabc46fa9563ce12665e62e32c09f5e0b0e20901 Mon Sep 17 00:00:00 2001 From: James Tocknell Date: Wed, 21 Nov 2018 12:24:46 +1100 Subject: [PATCH] ENH: Add some useful SUNDIALS user functions --- docs/solvers.rst | 14 +++++ scikits/odes/sundials/__init__.py | 88 +++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/docs/solvers.rst b/docs/solvers.rst index 55d9bbe..3ad752c 100644 --- a/docs/solvers.rst +++ b/docs/solvers.rst @@ -37,3 +37,17 @@ A comparison of different methods is given in following image. In this BDF, RK23 .. image:: ../ipython_examples/PerformanceTests.png You can generate above graph via the `Performance notebook `_. + +Solver Specific Options +####################### + +The high level interfaces allow the option of passing solver specific options to +the solvers. These options are covered in more detail in the `API docs `_, but some features specific to ``odes`` are mentioned below. + +SUNDIALS +======== + +There are a number of SUNDIALS specific utilities in :py:mod:`scikits.odes.sundials`. +Firstly there are :py:func:`scikits.odes.sundials.ontstop_stop`, :py:func:`scikits.odes.sundials.ontstop_continue`, :py:func:`scikits.odes.sundials.onroot_stop` and :py:func:`scikits.odes.sundials.onroot_continue`, which can be used with the `ontstop` or `onroot` options to either stop or continue evaluation when tstop or a root is encountered. +Secondly, there are functions which can be passed to the `err_handler` option to either stop all messages from SUNDIALS being printed (:py:func:`scikits.odes.sundials.drop_all_error_handler`), or to pass them to Python's logging machinery (:py:func:`scikits.odes.sundials.log_error_handler`). +Finally, the module contains the exceptions which can be caught in user code raised when using the `validate_flags` option. diff --git a/scikits/odes/sundials/__init__.py b/scikits/odes/sundials/__init__.py index fb1f36d..fbd8744 100644 --- a/scikits/odes/sundials/__init__.py +++ b/scikits/odes/sundials/__init__.py @@ -3,6 +3,11 @@ # import inspect +from logging import getLogger + +logger = getLogger(__name__) +DEFAULT_LOG_FORMAT = "SUNDIALS message in %s:%s: %s" + class CVODESolveException(Exception): """Base class for exceptions raised by ``CVODE.validate_flags``.""" @@ -64,3 +69,86 @@ def _get_num_args(func): return numargs else: return len(inspect.getargspec(func).args) + + +def drop_all_error_handler(error_code, module, func, msg, user_data): + """ + Drop all CVODE/IDA messages, rather than printing them. + + Examples + -------- + >>> scikits.odes.ode('cvode', rhsfuc, err_handler=drop_all_error_handler) + """ + # pylint: disable=unused-argument + pass + + +def log_error_handler(error_code, module, func, msg, user_data): + """ + Log all CVODE/IDA messages using the builtin python logging. + + Examples + -------- + >>> scikits.odes.ode('cvode', rhsfuc, err_handler=log_error_handler) + """ + # pylint: disable=unused-argument + if error_code > 0: + logger.warning(DEFAULT_LOG_FORMAT, module, func, msg) + else: + logger.error(DEFAULT_LOG_FORMAT, module, func, msg) + + +def onroot_continue(*args): + """ + Always continue after finding root. + + Examples + -------- + >>> scikits.odes.ode( + ... 'cvode', rhsfuc, rootfn=rootfn, nr_rootfns=nroots, + ... onroot=onroot_continue + ... ) + """ + # pylint: disable=unused-argument + return 0 + + +def onroot_stop(*args): + """ + Always stop after finding root. + + Examples + -------- + >>> scikits.odes.ode( + ... 'cvode', rhsfuc, rootfn=rootfn, nr_rootfns=nroots, + ... onroot=onroot_stop + ... ) + """ + # pylint: disable=unused-argument + return 1 + + +def ontstop_continue(*args): + """ + Always continue after finding tstop. + + Examples + -------- + >>> scikits.odes.ode( + ... 'cvode', rhsfuc, tstop=tstop, ontstop=ontstop_continue + ... ) + """ + # pylint: disable=unused-argument + return 0 + + +def ontstop_stop(*args): + """ + Always stop after finding tstop. + + Examples + -------- + >>> scikits.odes.ode('cvode', rhsfuc, tstop=tstop, ontstop=ontstop_stop) + """ + # pylint: disable=unused-argument + return 1