# ODE_SOLVER

An optional section that defines how an PoPy will solve the ordinary differential equations in the DERIVATIVES section.

Note the ODE_SOLVER section is optional, if you have no DERIVATIVES section then you do not need to have an ODE_SOLVER section.

The ODE_SOLVER section is available in the following scripts:-

- Tut Script
- Gen Script
- Fit Script
- Sim Script
- MTut Script
- MGen Script
- MFit Script
- MSim Script

i.e. Any script that processes PK/PD models and may have a DERIVATIVES section, may also have an ODE_SOLVER section.

## ODE_SOLVER Options

There are three principle ODE_SOLVER options available:-

- NO_SOLVER - use if there is no DERIVATIVES section
- ANALYTIC - use if DERIVATIVES contains only analytic compartment functions
- CPPLSODA - numerical solver - use if DERIVATIVES contains `d[X]` equations
- SCIPY_ODEINT - numerical solver - deprecated, slower, SciPy version of CPPLSODA.

The options above are tied to the nature of the DERIVATIVES section. Some examples of DERIVATIVES sections and appropriate ODE_SOLVER settings are shown below.

## Example ODE_SOLVER using NO_SOLVER

In the case where the PoPy script contains no DERIVATIVES section or the DERIVATIVES section is null:-

    DERIVATIVES: |

Then the PoPy script should contain no ODE_SOLVER section or the ODE_SOLVER should also be null:-

    ODE_SOLVER:
        NO_SOLVER: {}

If the DERIVATIVES section is null and ODE_SOLVER is set to ‘ANALYTIC’ or ‘SCIPY_ODEINT’, then PoPy should issue a warning, but the ODE_SOLVER section will otherwise have no effect.

Note, the simplest solution if you have no compartment model is to just remove the DERIVATIVES and ODE_SOLVER sections from the script completely.

## Example ODE_SOLVER using ANALYTIC

In the case where the PoPy script contains a DERIVATIVES section consisting of only an analytic compartment function:-

    DERIVATIVES: |
        s[DEPOT,CENTRAL,PERI] = @dep_two_cmp_cl{dose:@bolus{amt:c[AMT]}

Then the ODE_SOLVER section should be:-

    ODE_SOLVER:
        ANALYTIC: {}

If the DERIVATIVES section contains only an analytic compartment function and ODE_SOLVER is set to ‘NO_SOLVER’ or ‘SCIPY_ODEINT’, then PoPy should issue a warning, but the ODE_SOLVER section will otherwise automatically switch to ‘ANALYTIC’.

## Example ODE_SOLVER using CPPLSODA

In the case where the PoPy script contains a DERIVATIVES section consisting of ordinary differential equations with `d[X]` variables on the left hand side and `s[X]` on the right hand side, for example:-

    DERIVATIVES: |
        # s[DEPOT,CENTRAL,PERI] = @dep_two_cmp_cl{dose:@bolus{amt:c[AMT]}}
        d[DEPOT] = @bolus{amt:c[AMT]} - m[KA]*s[DEPOT]
        d[CENTRAL] = m[KA]*s[DEPOT] - s[CENTRAL]*m[CL]/m[V1] - s[CENTRAL]*m[Q]/m[V1]  + s[PERI]*m[Q]/m[V2]
        d[PERI] = s[CENTRAL]*m[Q]/m[V1] - s[PERI]*m[Q]/m[V2]

Then the ODE_SOLVER section should use ‘CPPLSODA’, for example:-

    ODE_SOLVER:
        CPPLSODA:
            atol: 1e-06
            rtol: 1e-06
            max_nsteps: 10000000

If the DERIVATIVES section contains `d[X]` equations and ODE_SOLVER is set to ‘NO_SOLVER’ or ‘ANALYTIC’, then PoPy should issue an error when checking the script, because a numerical solver is required.

CPPLSODA is a C++ version of the Fortran LSODA solver [Radhakrishnan1994]. The same ordinary differential equation solver method used by the Nonmem ADVAN13 routine.

Note that CPPLSODA exposes the following parameters of LSODA:-

- atol - Additive tolerance of the LSODA error control
- rtol - Relative tolerance of the LSODA error control
- max_nsteps - Maximum number of steps for LSODA integrator

All of the parameters above are optional with the following default values:-

- atol: 1e-12
- rtol: 1e-12
- max_nsteps: 10000000

Hence the following ODE_SOLVER section:-

    ODE_SOLVER: {CPPLSODA: {}}

Is equivalent to:-

    ODE_SOLVER:
        CPPLSODA:
            atol: 1e-12
            rtol: 1e-12
            max_nsteps: 10000000

## Example ODE_SOLVER using SCIPY_ODEINT

Note ‘SCIPY_ODEINT’ is deprecated in favour of CPPLSODA above.

SCIPY_ODEINT is a wrapper around the following Python numerical ordinary differential equation solver from the SciPy package:-

    scipy.integrate.odeint

Which in turn is a wrapper around the Fortran LSODA solver [Radhakrishnan1994]. The same ordinary differential equation solver that is used by the Nonmem ADVAN13 routine. You can read more about this integrator here in the SciPy documentation:-

http://lagrange.univ-lyon1.fr/docs/scipy/0.17.1/generated/scipy.integrate.odeint.html

Note that PoPy exposes the following parameters of LSODA:-

- atol - Additive tolerance of the LSODA error control
- rtol - Relative tolerance of the LSODA error control
- max_nsteps - Maximum number of steps for LSODA integrator (called ‘mxstep’ in link above)

All of the parameters above are optional with the following default values:-

- atol: 1e-12
- rtol: 1e-12
- max_nsteps: 10000000

Hence the following ODE_SOLVER section:-

    ODE_SOLVER: {SCIPY_ODEINT: {}}

Is equivalent to:-

    ODE_SOLVER:
        SCIPY_ODEINT:
            atol: 1e-12
            rtol: 1e-12
            max_nsteps: 10000000

Note it is recommended to use CPPLSODA instead, which is faster and will give very similar results.