GSLCodeGenerator class

(Shortest import: from brian2.codegen.generators import GSLCodeGenerator)

class brian2.codegen.generators.GSL_generator.GSLCodeGenerator(variables, variable_indices, owner, iterate_all, codeobj_class, name, template_name, override_conditional_write=None, allows_scalar_write=False)[source]

Bases: object

GSL code generator.

Notes

Approach is to first let the already existing code generator for a target language do the bulk of the translating from abstract_code to actual code. This generated code is slightly adapted to render it GSL compatible. The most critical part here is that the vector_code that is normally contained in a loop in the `main()` is moved to the function `_GSL_func` that is sent to the GSL integrator. The variables used in the vector_code are added to a struct named `dataholder` and their values are set from the Brian namespace just before the scalar code block.

Methods

add_gsl_variables_as_non_scalar(diff_vars) Add _gsl variables as non-scalar.
add_meta_variables(options)
c_data_type(dtype) Get string version of object dtype that is attached to Brian variables.
diff_var_to_replace(diff_vars) Add differential variable-related strings that need to be replaced to go from normal brian to GSL code
find_differential_variables(code) Find the variables that were tagged _gsl_{var}_f{ind} and return var, ind pairs.
find_function_names() Return a list of used function names in the self.variables dictionary
find_undefined_variables(statements) Find identifiers that are not in self.variables dictionary.
find_used_variables(statements, other_variables) Find all the variables used in the right hand side of the given expressions.
get_dimension_code(diff_num) Generate code for function that sets the dimension of the ODE system.
initialize_array(varname, values) Initialize a static array with given floating point values.
is_constant_and_cpp_standalone(var_obj) Check whether self.cpp_standalone and variable is Constant.
is_cpp_standalone() Check whether we’re running with cpp_standalone.
make_function_code(lines) Add lines of GSL translated vector code to ‘non-changing’ _GSL_func code.
scale_array_code(diff_vars, method_options) Return code for definition of _GSL_scale_array in generated code.
to_replace_vector_vars(variables_in_vector) Create dictionary containing key, value pairs with to be replaced text to translate from conventional Brian to GSL.
translate(code, dtype) Translates an abstract code block into the target language.
translate_scalar_code(code_lines, …) Translate scalar code: if calculated variables are used in the vector_code their value is added to the variable in the _dataholder.
translate_vector_code(code_lines, to_replace) Translate vector code to GSL compatible code by substituting fragments of code.
unpack_namespace(variables_in_vector, …[, …]) Write code that unpacks Brian namespace to cython/cpp namespace.
unpack_namespace_single(var_obj, in_vector, …) Writes the code necessary to pull single variable out of the Brian namespace into the generated code.
var_init_lhs(var, type) Get string version of the left hand side of an initializing expression
write_dataholder(variables_in_vector) Return string with full code for _dataholder struct.
write_dataholder_single(var_obj) Return string declaring a single variable in the _dataholder struct.
yvector_code(diff_vars) Generate code for function dealing with GSLs y vector.

Details

add_gsl_variables_as_non_scalar(diff_vars)[source]

Add _gsl variables as non-scalar.

In GSLStateUpdater the differential equation variables are substituted with GSL tags that describe the information needed to translate the conventional Brian code to GSL compatible code. This function tells Brian that the variables that contain these tags should always be vector variables. If we don’t do this, Brian renders the tag-variables as scalar if no vector variables are used in the right hand side of the expression.

Parameters:

diff_vars : dict

dictionary with variables as keys and differential equation index as value

add_meta_variables(options)[source]
c_data_type(dtype)[source]

Get string version of object dtype that is attached to Brian variables. c pp_generator already has this function, but the Cython generator does not, but we need it for GSL code generation.

diff_var_to_replace(diff_vars)[source]

Add differential variable-related strings that need to be replaced to go from normal brian to GSL code

From the code generated by Brian’s ‘normal’ generators (cpp_generator or cython_generator a few bits of text need to be replaced to get GSL compatible code. The bits of text related to differential equation variables are put in the replacer dictionary in this function.

Parameters:

diff_vars : dict

dictionary with variables as keys and differential equation index as value

Returns:

to_replace : dict

dictionary with strings that need to be replaced as keys and the strings that will replace them as values

find_differential_variables(code)[source]

Find the variables that were tagged _gsl_{var}_f{ind} and return var, ind pairs.

GSLStateUpdater tagged differential variables and here we extract the information given in these tags.

Parameters:

code : list of strings

A list of strings containing gsl tagged variables

Returns:

diff_vars : dict

A dictionary with variable names as keys and differential equation index as value

find_function_names()[source]

Return a list of used function names in the self.variables dictionary

Functions need to be ignored in the GSL translation process, because the brian generator already sufficiently dealt with them. However, the brian generator also removes them from the variables dict, so there is no way to check whether an identifier is a function after the brian translation process. This function is called before this translation process and the list of function names is stored to be used in the GSL translation.

Returns:

function_names : list

list of strings that are function names used in the code

find_undefined_variables(statements)[source]

Find identifiers that are not in self.variables dictionary.

Brian does not save the _lio_ variables it uses anywhere. This is problematic for our GSL implementation because we save the lio variables in the _dataholder struct (for which we need the datatype of the variables). This function adds the left hand side variables that are used in the vector code to the variable dictionary as AuxiliaryVariables (all we need later is the datatype).

Parameters:

statements : list

list of statement objects (need to have the dtype attribute)

Notes

I keep self.variables and other_variables separate so I can distinguish what variables are in the Brian namespace and which ones are defined in the code itself.

find_used_variables(statements, other_variables)[source]

Find all the variables used in the right hand side of the given expressions.

Parameters:

statements : list

list of statement objects

Returns:

used_variables : dict

dictionary of variables that are used as variable name (str), Variable pairs.

get_dimension_code(diff_num)[source]

Generate code for function that sets the dimension of the ODE system.

GSL needs to know how many differential variables there are in the ODE system. Since the current approach is to have the code in the vector loop the same for all simulations, this dimension is set by an external function. The code for this set_dimension functon is written here. It is assumed the code will be the same for each target language with the exception of some syntactical differences

Parameters:

diff_num : int

Number of differential variables that describe the ODE system

Returns:

set_dimension_code : str

The code describing the target language function in a single string

initialize_array(varname, values)[source]

Initialize a static array with given floating point values. E.g. in C++, when called with arguments array and [1.0, 3.0, 2.0], this method should return double array[] = {1.0, 3.0, 2.0}.

Parameters:

varname : str

The name of the array variable that should be initialized

values : list of float

The values that should be assigned to the array

Returns:

code : str

One or more lines of array initialization code.

is_constant_and_cpp_standalone(var_obj)[source]

Check whether self.cpp_standalone and variable is Constant.

This check is needed because in the case of using the cpp_standalone device we do not want to apply our GSL variable conversion (var –> _GSL_dataholder.var), because the cpp_standalone code generation process involves replacing constants with their actual value (‘freezing’). This results in code that looks like (if for example var = 1.2): _GSL_dataholder.1.2 = 1.2 and _GSL_dataholder->1.2. To prevent repetitive calls to get_device() etc. the outcome of is_cpp_standalone is saved.

Parameters:

var_obj : Variable

instance of brian Variable class describing the variable

Returns:

is_cpp_standalone : bool

whether the used device is cpp_standalone and the given variable is an instance of Constant

is_cpp_standalone()[source]

Check whether we’re running with cpp_standalone.

Test if get_device() is instance CPPStandaloneDevice.

Returns:

is_cpp_standalone : bool

whether currently using cpp_standalone device

See also

is_constant_and_cpp_standalone
uses the returned value
make_function_code(lines)[source]

Add lines of GSL translated vector code to ‘non-changing’ _GSL_func code.

Adds nonchanging aspects of GSL _GSL_func code to lines of code written somewhere else (translate_vector_code). Here these lines are put between the non-changing parts of the code and the target-language specific syntax is added.

Parameters:

lines : str

Code containing GSL version of equations

Returns:

function_code : str

code describing _GSL_func that is sent to GSL integrator.

scale_array_code(diff_vars, method_options)[source]

Return code for definition of _GSL_scale_array in generated code.

Parameters:

diff_vars : dict

dictionary with variable name (str) as key and differential variable index (int) as value

method_options : dict

dictionary containing integrator settings

Returns:

code : str

full code describing a function returning a array containing doubles with the absolute errors for each differential variable (according to their assigned index in the GSL StateUpdater)

to_replace_vector_vars(variables_in_vector, ignore=frozenset())[source]

Create dictionary containing key, value pairs with to be replaced text to translate from conventional Brian to GSL.

Parameters:

variables_in_vector : dict

dictionary with variable name (str), Variable pairs of variables occurring in vector code

ignore : set, optional

set of strings with variable names that should be ignored

Returns:

to_replace : dict

dictionary with strings that need to be replaced i.e. _lio_1 will be _GSL_dataholder._lio_1 (in cython) or _GSL_dataholder->_lio_1 (cpp)

Notes

t will always be added because GSL defines its own t. i.e. for cpp: {‘const t = _ptr_array_defaultclock_t[0];’ : ‘’}

translate(code, dtype)[source]

Translates an abstract code block into the target language.

translate_scalar_code(code_lines, variables_in_scalar, variables_in_vector)[source]

Translate scalar code: if calculated variables are used in the vector_code their value is added to the variable in the _dataholder.

Parameters:

code_lines : list

list of strings containing scalar code

variables_in_vector : dict

dictionary with variable name (str), Variable pairs of variables occurring in vector code

variables_in_scalar : dict

dictionary with variable name (str), Variable pairs of variables occurring in scalar code

Returns:

scalar_code : str

code fragment that should be injected in the main before the loop

translate_vector_code(code_lines, to_replace)[source]

Translate vector code to GSL compatible code by substituting fragments of code.

Parameters:

code_lines : list

list of strings describing the vector_code

to_replace: dict :

dictionary with to be replaced strings (see to_replace_vector_vars and to_replace_diff_vars)

Returns:

vector_code : str

New code that is now to be added to the function that is sent to the GSL integrator

unpack_namespace(variables_in_vector, variables_in_scalar, ignore=frozenset())[source]

Write code that unpacks Brian namespace to cython/cpp namespace.

For vector code this means putting variables in _dataholder (i.e. _GSL_dataholder->var or _GSL_dataholder.var = …) Note that code is written so a variable could occur both in scalar and vector code

Parameters:

variables_in_vector : dict

dictionary with variable name (str), Variable pairs of variables occurring in vector code

variables_in_scalar : dict

dictionary with variable name (str), Variable pairs of variables

occurring in scalar code

ignore : set, optional

set of string names of variables that should be ignored

Returns:

unpack_namespace_code : str

code fragment unpacking the Brian namespace (setting variables in the _dataholder struct in case of vector)

unpack_namespace_single(var_obj, in_vector, in_scalar)[source]

Writes the code necessary to pull single variable out of the Brian namespace into the generated code.

The code created is significantly different between cpp and cython, so I decided to not make this function general over all target languages (i.e. in contrast to most other functions that only have syntactical differences)

var_init_lhs(var, type)[source]

Get string version of the left hand side of an initializing expression

Parameters:

var : str

type : str

Returns:

code : str

For cpp returns type + var, while for cython just var

write_dataholder(variables_in_vector)[source]

Return string with full code for _dataholder struct.

Parameters:

variables_in_vector : dict

dictionary containing variable name as key and Variable as value

Returns:

code : str

code for _dataholder struct

write_dataholder_single(var_obj)[source]

Return string declaring a single variable in the _dataholder struct.

Parameters:

var_obj : Variable

Returns:

code : str

string describing this variable object as required for the _dataholder struct (e.g. double* _array_neurongroup_v)

yvector_code(diff_vars)[source]

Generate code for function dealing with GSLs y vector.

The values of differential variables have to be transferred from Brian’s namespace to a vector that is given to GSL. The transferring from Brian –> y and back from y –> Brian after integration happens in separate functions. The code for these is written here.

Parameters:

diff_vars : dictionary

Dictionary containing variable names as keys (str) and differential variable index as value

Returns:

yvector_code : str

The code for the two functions (_fill_y_vector and _empty_y_vector) as single string.