File: stateupdate.pyx

package info (click to toggle)
brian 2.9.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,872 kB
  • sloc: python: 51,820; cpp: 2,033; makefile: 108; sh: 72
file content (132 lines) | stat: -rw-r--r-- 4,936 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
{# ITERATE_ALL { _idx } #}
{# USES_VARIABLES { N } #}
{# ALLOWS_SCALAR_WRITE #}
{% extends 'common_group.pyx' %}

{% block template_support_code %}

from brian2.codegen.runtime.GSLcython_rt import IntegrationError
from libc.stdlib cimport malloc, free

cdef enum:
    GSL_SUCCESS = 0

cdef extern from "gsl/gsl_odeiv2.h":
    # gsl_odeiv2_system
    ctypedef struct gsl_odeiv2_system:
        int (* function) (double t,  double _GSL_y[], double dydt[], void * params)
        int (* jacobian) (double t,  double _GSL_y[], double * dfdy, double dfdt[], void * params)
        size_t dimension
        void * params

    ctypedef struct gsl_odeiv2_driver:
        gsl_odeiv2_system * sys
        gsl_odeiv2_step *s
        gsl_odeiv2_control *c
        gsl_odeiv2_evolve *e
        double h
        double hmin
        double hmax
        unsigned long int n
        unsigned long int nmax

    ctypedef struct gsl_odeiv2_evolve:
        size_t dimension
        double *y0
        double *yerr
        double *dydt_in
        double *dydt_out
        double last_step
        unsigned long int count
        unsigned long int failed_steps
        const gsl_odeiv2_driver *driver

    ctypedef struct gsl_odeiv2_step
    ctypedef struct gsl_odeiv2_control

    ctypedef struct gsl_odeiv2_step_type

    gsl_odeiv2_step_type *gsl_odeiv2_step_{{GSL_settings['integrator']}}

    int gsl_odeiv2_driver_apply(
        gsl_odeiv2_driver *_GSL_driver, double *t, double t1, double _GSL_y[])
    int gsl_odeiv2_driver_apply_fixed_step(
        gsl_odeiv2_driver *_GSL_driver, double *t, const double h, const unsigned long int n, double _GSL_y[])
    int gsl_odeiv2_driver_reset_hstart(
        gsl_odeiv2_driver *_GSL_driver, const double hstart)
    int gsl_odeiv2_driver_reset(
        gsl_odeiv2_driver *GSL_driver)
    int gsl_odeiv2_driver_set_nmax(
        gsl_odeiv2_driver *GSL_driver, const unsigned long int nmax)
    int gsl_odeiv2_driver_set_hmax(
        gsl_odeiv2_driver *GSL_driver, const double hmax)

    gsl_odeiv2_driver *gsl_odeiv2_driver_alloc_scaled_new(
        gsl_odeiv2_system *_sys, gsl_odeiv2_step_type *T,
        double hstart, double epsabs, double epsrel,
        double a_y, double a_dydt, double scale[])

    int gsl_odeiv2_driver_free(gsl_odeiv2_driver *_GSL_driver)
{% endblock %}

{% block maincode %}

    # scalar code
    _vectorisation_idx = 1
    {% if define_dt %}
    dt = {{dt_array}}
    {% endif %}
    cdef double t1
    cdef _dataholder * _GSL_dataholder = <_dataholder *>malloc(sizeof(_dataholder))

    {{scalar_code['GSL']|autoindent}}

    cdef double _GSL_y[{{n_diff_vars}}]
    {{define_GSL_scale_array|autoindent}}
    
    cdef gsl_odeiv2_system _sys
    _sys.function = _GSL_func
    set_dimension(&_sys.dimension)
    _sys.params = _GSL_dataholder

    cdef gsl_odeiv2_driver * _GSL_driver = gsl_odeiv2_driver_alloc_scaled_new(&_sys,gsl_odeiv2_step_{{GSL_settings['integrator']}},
                                              {{GSL_settings['dt_start']}},1, 0, 0, 0, _GSL_scale_array)
    gsl_odeiv2_driver_set_nmax(_GSL_driver, {{GSL_settings['max_steps']}})
    gsl_odeiv2_driver_set_hmax(_GSL_driver, {{GSL_settings['dt_start']}})
    # vector code
    for _idx in range(N):
        _vectorisation_idx = _idx

        t = {{t_array}}
        t1 = t + dt

        _GSL_dataholder._idx = _idx
        _fill_y_vector(_GSL_dataholder, _GSL_y, _idx)
        {%if GSL_settings['use_last_timestep']%}
        gsl_odeiv2_driver_reset_hstart(_GSL_driver, {{pointer_last_timestep}})
        {% else %}
        gsl_odeiv2_driver_reset(_GSL_driver)
        {% endif %}
        if ({{'gsl_odeiv2_driver_apply(_GSL_driver, &t, t1, _GSL_y)' if GSL_settings['adaptable_timestep']
                    else 'gsl_odeiv2_driver_apply_fixed_step(_GSL_driver, &t, dt, 1, _GSL_y)'}} != GSL_SUCCESS):
            raise IntegrationError(("GSL integrator failed to integrate the equations."
            {% if GSL_settings['adaptable_timestep'] %}
                                           "\nThis means that the desired error cannot be achieved with the given maximum number of steps. "
                                           "Try using a larger error or a larger number of steps."
            {% else %}
                                           "\n This means that the size of the timestep results in an error larger than that set by absolute_error."
            {% endif %}
                                           ))
        _empty_y_vector(_GSL_dataholder, _GSL_y, _idx)
        {%if GSL_settings['use_last_timestep']%}
        {{pointer_last_timestep}} = _GSL_driver.h
        {% endif %}
        {%if GSL_settings['save_failed_steps']%}
        {{pointer_failed_steps}} = _GSL_driver.e.failed_steps
        {% endif %}
        {%if GSL_settings['save_step_count']%}
        {{pointer_step_count}} = _GSL_driver.n
        {% endif %}
    gsl_odeiv2_driver_free(_GSL_driver)

{% endblock %}