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 the variables that were tagged _gsl_{var}_f{ind} and return var, ind pairs.
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 on 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.
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
- 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 asAuxiliaryVariable
s (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
andother_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 on 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 returndouble 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 instanceCPPStandaloneDevice
.- 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 codeignore : 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_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 codevariables_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 codevariables_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
- dictionary with variable name (str),
- 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.