Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
4bde5db
initial commit
mwhy Apr 1, 2025
a6d3918
Update .gitignore
mwhy Apr 2, 2025
91b085a
Merge branch 'master' of https://github.com/nest/nestml
mwhy Apr 28, 2025
2e4679c
add model transformer for non-dimensionalisation
May 21, 2025
7d56517
add model transformer for non-dimensionalisation
May 26, 2025
df6119d
Update necessary SpiNNaker2 code generation templates
mwhy Jun 2, 2025
2f58435
Add setter for ASTVariables and ASTDataType
mwhy Jun 2, 2025
69e0c85
Add a more robust dynamic import function for generated python package
mwhy Jun 2, 2025
8551db8
Add generation of parameter - value dict needed for initialisation of…
mwhy Jun 2, 2025
1a4bcac
Uncomment synapse section even if not used at the moment
mwhy Jun 2, 2025
770748d
Add SpiNNaker2 to use AddTimestepToInternalsTransformer
mwhy Jun 2, 2025
ed1a6e5
Add SpiNNaker2CodeGeneratorUtils analogous to SpiNNaker1 implementation
mwhy Jun 2, 2025
6ff5d6c
Update spinnaker2_code_generator.py to use namespaces
mwhy Jun 2, 2025
7a0a043
Add filepath to ASTModel as it's needed for use of python_standalone_…
mwhy Jun 2, 2025
06dd673
Remove np.int from list of datatypes during cloning of numeric litera…
mwhy Jun 2, 2025
cbcf018
Add generation of updated state dict - dict with initial values for n…
mwhy Jun 2, 2025
54d460a
Update SpiNNaker2 builder
mwhy Jun 2, 2025
ab5304a
Add iaf_psc_exp neuron model without additional external I_stim curre…
mwhy Jun 2, 2025
0e9e9c6
Add c function call and variable printers for SpiNNaker2
mwhy Jun 2, 2025
2f4769f
Add code generation resources for C and Python
mwhy Jun 2, 2025
83ed260
Add SpiNNaker2TargetTools
mwhy Jun 2, 2025
9bad001
Add test for iaf_psc_exp_neuron_NO_ISTIM to NEST tests
mwhy Jun 2, 2025
976c1db
WIP: development of non-dimensionalisation transformer
mwhy Jun 3, 2025
f91fda6
add factors to the AST (proof-of-concept)
Jun 3, 2025
7d894ad
WIP: add tests for Non- Dimensionalisation- Transformer and package i…
mwhy Jun 12, 2025
4aeddbb
WIP: split up .NESTML test files for Non- Dimensionalisation- Transfo…
mwhy Jun 16, 2025
f06a2c4
WIP: split up PyTest test files for Non- Dimensionalisation- Transfor…
mwhy Jun 16, 2025
91da378
WIP: add a numpy refernce implementation for non dimensinalisation tr…
mwhy Jun 16, 2025
ff34c41
WIP: non dimensinalisation transformer add isinstance() checks
mwhy Jun 16, 2025
cabe11c
Move weight_scaling_factor and simulation_timestep_in_s to neuron par…
mwhy Jun 18, 2025
8ad064e
WIP: Update tests and Unit Transformer
mwhy Jun 19, 2025
7503eac
update tests for non dimensionalisation transformer
mwhy Jun 22, 2025
225d9eb
WIP: split transformer into multiple parts to prevent errors during m…
mwhy Jun 22, 2025
119f3f8
Comment out unused transformer import
mwhy Jun 23, 2025
9ab2422
Set correct memory addresses for code generation
mwhy Jun 27, 2025
f3e651a
Refactoring, put functions in ast_utils and ast_model instead of NEST…
mwhy Jul 1, 2025
d1504d1
merge upstream master
mwhy Jul 1, 2025
04aa8f8
Merge remote-tracking branch 'origin/master' into non-dim-trafo
mwhy Jul 1, 2025
145bec2
update transformer, split into multiple visitors implementing differe…
mwhy Jul 2, 2025
f5d4162
code cleanup
mwhy Jul 3, 2025
888c464
Update non-dim-transformer and test-cases
mwhy Jul 6, 2025
0896801
update non-dim-trafo and tests
mwhy Jul 10, 2025
308dc5c
update non-dim-trafo and tests
mwhy Jul 10, 2025
6865ad0
update transformer to correctly distinguish between variables and uni…
mwhy Jul 13, 2025
283857f
make changing of data type in input port more explicit
mwhy Jul 13, 2025
2d819f4
add Izhikevich neuron numerical integrtation test to non-dim-transformer
mwhy Jul 13, 2025
ad2fb61
comment out functionality in attempt_magnitude_cast() - function shou…
mwhy Jul 13, 2025
96cd7e8
make nest_code_generator consistent with main branch
mwhy Jul 13, 2025
a8c6f08
update gitignore
mwhy Jul 13, 2025
cb5233b
add FE vs. RK45 test for NEST code generation with non-dim-trafo
mwhy Sep 9, 2025
8b57cc9
update non-dim-trafo
mwhy Sep 9, 2025
7191891
add non-dim-trafo tests
mwhy Sep 10, 2025
8aedc37
clean up non-dim-trafo
mwhy Sep 10, 2025
e8e6d3f
delete ressources spinnaker2 from non-dim-trafo branch
mwhy Sep 10, 2025
789a813
Remove .gitignore from repository but keep locally
mwhy Sep 10, 2025
71caf2c
remove spinnaker2 related files
mwhy Sep 10, 2025
9e9443c
delete outdated plots
mwhy Sep 10, 2025
0c3ee22
Stop tracking png
mwhy Sep 10, 2025
6d5514c
Merge remote-tracking branch 'upstream/master' into non-dim-trafo
Oct 2, 2025
26ea4b9
clean up non-dimensionalisation transformer
Oct 2, 2025
4d39707
clean up non-dimensionalisation transformer
Oct 3, 2025
ec316af
clean up non-dimensionalisation transformer
Oct 4, 2025
fd6dd27
clean up non-dimensionalisation transformer
Oct 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions doc/running/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,18 @@ Running NESTML
Running NESTML causes several processing steps to occur:

1. The model is parsed from file and checked (syntax, consistent physical units, and so on).
2. Code is generated from the model by one of the "code generators" selected when NESTML was invoked.
3. If necessary, the code is compiled and built by the "builder" that belongs to the selected code generator.
2. A series of transformation steps are optionally carried out on the model. Which set of transformers is used is automatically determined based on the target platform selected when NESTML was invoked. (See the section "Available transformers" below.)
3. Code is generated from the model by one of the "code generators" selected when NESTML was invoked. If necessary, the code is compiled and built by the "builder" that belongs to the selected code generator. (See the section "Supported target platforms" below.)


Available transformers
----------------------

- **Non-dimensionalisation transformer**

:class:`pynestml.transformers.non_dimensionalisation_transformer.NonDimensionalisationTransformer`

Eliminates physical units from models, converting numerical values to real numbers.


Supported target platforms
Expand Down
5 changes: 2 additions & 3 deletions pynestml/cocos/co_co_function_calls_consistent.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
from pynestml.utils.ast_utils import ASTUtils
from pynestml.utils.logger import Logger, LoggingLevel
from pynestml.utils.messages import Messages
from pynestml.utils.type_caster import TypeCaster
from pynestml.visitors.ast_visitor import ASTVisitor


Expand Down Expand Up @@ -109,5 +108,5 @@ def visit_function_call(self, node):
# variadic type symbol accepts anything
return

if not actual_type.equals(expected_type) and not isinstance(expected_type, TemplateTypeSymbol):
TypeCaster.try_to_recover_or_error(expected_type, actual_type, actual_arg)
# if not actual_type.equals(expected_type) and not isinstance(expected_type, TemplateTypeSymbol):
# TypeCaster.try_to_recover_or_error(expected_type, actual_type, actual_arg)
41 changes: 19 additions & 22 deletions pynestml/cocos/co_co_illegal_expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
from pynestml.utils.logger import LoggingLevel, Logger
from pynestml.utils.logging_helper import LoggingHelper
from pynestml.utils.messages import Messages
from pynestml.utils.type_caster import TypeCaster
from pynestml.visitors.ast_visitor import ASTVisitor


Expand Down Expand Up @@ -68,9 +67,8 @@ def visit_declaration(self, node):
if isinstance(rhs_type, ErrorTypeSymbol):
LoggingHelper.drop_missing_type_error(node)
return
if self.__types_do_not_match(lhs_type, rhs_type):
TypeCaster.try_to_recover_or_error(lhs_type, rhs_type, node.get_expression())
return
# if self.__types_do_not_match(lhs_type, rhs_type):
# TypeCaster.try_to_recover_or_error(lhs_type, rhs_type, node.get_expression())

def visit_inline_expression(self, node):
"""
Expand All @@ -82,8 +80,8 @@ def visit_inline_expression(self, node):
if isinstance(rhs_type, ErrorTypeSymbol):
LoggingHelper.drop_missing_type_error(node)
return
if self.__types_do_not_match(lhs_type, rhs_type):
TypeCaster.try_to_recover_or_error(lhs_type, rhs_type, node.get_expression())
# if self.__types_do_not_match(lhs_type, rhs_type):
# TypeCaster.try_to_recover_or_error(lhs_type, rhs_type, node.get_expression())

def visit_assignment(self, node):
"""
Expand Down Expand Up @@ -120,23 +118,23 @@ def handle_compound_assignment(self, node):
lhs_type_symbol = lhs_variable_symbol.get_type_symbol()

if node.is_compound_product:
if self.__types_do_not_match(lhs_type_symbol, lhs_type_symbol * rhs_type_symbol):
TypeCaster.try_to_recover_or_error(lhs_type_symbol, lhs_type_symbol * rhs_type_symbol,
node.get_expression())
return
# if self.__types_do_not_match(lhs_type_symbol, lhs_type_symbol * rhs_type_symbol):
# TypeCaster.try_to_recover_or_error(lhs_type_symbol, lhs_type_symbol * rhs_type_symbol,
# node.get_expression())
# return
return

if node.is_compound_quotient:
if self.__types_do_not_match(lhs_type_symbol, lhs_type_symbol / rhs_type_symbol):
TypeCaster.try_to_recover_or_error(lhs_type_symbol, lhs_type_symbol / rhs_type_symbol,
node.get_expression())
return
# if self.__types_do_not_match(lhs_type_symbol, lhs_type_symbol / rhs_type_symbol):
# TypeCaster.try_to_recover_or_error(lhs_type_symbol, lhs_type_symbol / rhs_type_symbol,
# node.get_expression())
# return
return

assert node.is_compound_sum or node.is_compound_minus
if self.__types_do_not_match(lhs_type_symbol, rhs_type_symbol):
TypeCaster.try_to_recover_or_error(lhs_type_symbol, rhs_type_symbol,
node.get_expression())
# if self.__types_do_not_match(lhs_type_symbol, rhs_type_symbol):
# TypeCaster.try_to_recover_or_error(lhs_type_symbol, rhs_type_symbol,
# node.get_expression())

@staticmethod
def __types_do_not_match(lhs_type_symbol, rhs_type_symbol):
Expand All @@ -154,11 +152,10 @@ def handle_simple_assignment(self, node):
LoggingHelper.drop_missing_type_error(node)
return

if lhs_variable_symbol is not None and self.__types_do_not_match(lhs_variable_symbol.get_type_symbol(),
rhs_type_symbol):
TypeCaster.try_to_recover_or_error(lhs_variable_symbol.get_type_symbol(), rhs_type_symbol,
node.get_expression())
return
# if lhs_variable_symbol is not None and self.__types_do_not_match(lhs_variable_symbol.get_type_symbol(),
# rhs_type_symbol):
# TypeCaster.try_to_recover_or_error(lhs_variable_symbol.get_type_symbol(), rhs_type_symbol,
# node.get_expression())

def visit_if_clause(self, node):
"""
Expand Down
1 change: 1 addition & 0 deletions pynestml/cocos/co_co_output_port_defined_if_emit_call.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def visit_function_call(self, node: ASTFunctionCall):
# types are not equal, but castable
code, message = Messages.get_implicit_cast_rhs_to_lhs(output_block_attr_type_sym.print_symbol(),
emit_spike_arg_type_sym.print_symbol())
# XXX: this should be removed
Logger.log_message(error_position=output_blocks[0].get_source_position(),
code=code, message=message, log_level=LoggingLevel.WARNING)
continue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
from pynestml.symbols.symbol import SymbolKind
from pynestml.utils.logger import LoggingLevel, Logger
from pynestml.utils.messages import Messages
from pynestml.utils.type_caster import TypeCaster


class CoCoUserDefinedFunctionCorrectlyDefined(CoCo):
Expand Down Expand Up @@ -128,9 +127,9 @@ def __check_return_recursively(cls, type_symbol=None, stmts=None, ret_defined=Fa
code, message = Messages.get_type_could_not_be_derived(cls.processed_function.get_name())
Logger.log_message(error_position=stmt.get_source_position(),
code=code, message=message, log_level=LoggingLevel.ERROR)
elif not type_of_return.equals(type_symbol):
TypeCaster.try_to_recover_or_error(type_symbol, type_of_return,
stmt.get_return_stmt().get_expression())
# elif not type_of_return.equals(type_symbol):
# TypeCaster.try_to_recover_or_error(type_symbol, type_of_return,
# stmt.get_return_stmt().get_expression())
elif isinstance(stmt, ASTCompoundStmt):
# otherwise it is a compound stmt, thus check recursively
if stmt.is_if_stmt():
Expand Down
1 change: 0 additions & 1 deletion pynestml/codegeneration/nest_code_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#
# You should have received a copy of the GNU General Public License
# along with NEST. If not, see <http://www.gnu.org/licenses/>.

from typing import Any, Dict, List, Mapping, Optional, Sequence, Tuple

import datetime
Expand Down
79 changes: 0 additions & 79 deletions pynestml/codegeneration/nest_unit_converter.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,4 @@ def _print(self, node: ASTNode) -> str:
return self.print_simple_expression(node)

def print(self, node: ASTNode) -> str:
if node.get_implicit_conversion_factor() and not node.get_implicit_conversion_factor() == 1:
return "(" + str(node.get_implicit_conversion_factor()) + " * (" + self._print(node) + "))"

return self._print(node)
3 changes: 0 additions & 3 deletions pynestml/codegeneration/printers/cpp_expression_printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ class CppExpressionPrinter(ExpressionPrinter):

def print(self, node: ASTNode) -> str:
if isinstance(node, ASTExpression):
if node.get_implicit_conversion_factor() and not node.get_implicit_conversion_factor() == 1:
return "(" + str(node.get_implicit_conversion_factor()) + " * (" + self.print_expression(node) + "))"

return self.print_expression(node)

return self._simple_expression_printer.print(node)
Expand Down
4 changes: 2 additions & 2 deletions pynestml/codegeneration/printers/gsl_variable_printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#
# You should have received a copy of the GNU General Public License
# along with NEST. If not, see <http://www.gnu.org/licenses/>.
from pynestml.codegeneration.nest_unit_converter import NESTUnitConverter

from pynestml.codegeneration.printers.cpp_variable_printer import CppVariablePrinter
from pynestml.meta_model.ast_variable import ASTVariable
from pynestml.symbols.predefined_units import PredefinedUnits
Expand All @@ -45,7 +45,7 @@ def print_variable(self, node: ASTVariable) -> str:
if symbol is None:
# test if variable name can be resolved to a type
if PredefinedUnits.is_unit(node.get_complete_name()):
return str(NESTUnitConverter.get_factor(PredefinedUnits.get_unit(node.get_complete_name()).get_unit()))
return str(PredefinedUnits.get_unit(node.get_complete_name()).get_unit())

code, message = Messages.get_could_not_resolve(node.get_name())
Logger.log_message(log_level=LoggingLevel.ERROR, code=code, message=message,
Expand Down
4 changes: 0 additions & 4 deletions pynestml/codegeneration/printers/latex_expression_printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ class LatexExpressionPrinter(ExpressionPrinter):
"""

def print(self, node: ASTExpressionNode) -> str:
if node.get_implicit_conversion_factor() is not None \
and str(node.get_implicit_conversion_factor()) not in ["1.", "1.0", "1"]:
return str(node.get_implicit_conversion_factor()) + " * (" + self.print_expression(node) + ")"

return self.print_expression(node)

def print_expression(self, node: ASTExpressionNode) -> str:
Expand Down
12 changes: 2 additions & 10 deletions pynestml/codegeneration/printers/nest_variable_printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
from pynestml.codegeneration.nest_code_generator_utils import NESTCodeGeneratorUtils
from pynestml.codegeneration.printers.cpp_variable_printer import CppVariablePrinter
from pynestml.codegeneration.printers.expression_printer import ExpressionPrinter
from pynestml.codegeneration.nest_unit_converter import NESTUnitConverter
from pynestml.meta_model.ast_external_variable import ASTExternalVariable
from pynestml.meta_model.ast_variable import ASTVariable
from pynestml.symbols.predefined_units import PredefinedUnits
Expand Down Expand Up @@ -99,7 +98,7 @@ def print_variable(self, variable: ASTVariable) -> str:
if symbol is None:
# test if variable name can be resolved to a type
if PredefinedUnits.is_unit(variable.get_complete_name()):
return str(NESTUnitConverter.get_factor(PredefinedUnits.get_unit(variable.get_complete_name()).get_unit()))
return str(PredefinedUnits.get_unit(variable.get_complete_name()).get_unit())

code, message = Messages.get_could_not_resolve(variable.get_name())
Logger.log_message(log_level=LoggingLevel.ERROR, code=code, message=message,
Expand All @@ -111,18 +110,11 @@ def print_variable(self, variable: ASTVariable) -> str:
vector_param = "[" + self._expression_printer.print(variable.get_vector_parameter()) + "]"

if symbol.is_buffer():
if isinstance(symbol.get_type_symbol(), UnitTypeSymbol):
units_conversion_factor = NESTUnitConverter.get_factor(symbol.get_type_symbol().unit.unit)
else:
units_conversion_factor = 1
s = ""
if not units_conversion_factor == 1:
s += "(" + str(units_conversion_factor) + " * "
if self.cpp_variable_suffix == "":
s += "B_."
s += self._print_buffer_value(variable)
if not units_conversion_factor == 1:
s += ")"

return s

if symbol.is_inline_expression:
Expand Down
3 changes: 0 additions & 3 deletions pynestml/codegeneration/printers/nestml_expression_printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ class NESTMLExpressionPrinter(ExpressionPrinter):

def print(self, node: ASTNode) -> str:
if isinstance(node, ASTExpression):
if node.get_implicit_conversion_factor() and not node.get_implicit_conversion_factor() == 1:
return "(" + str(node.get_implicit_conversion_factor()) + " * (" + self.print_expression(node) + "))"

return self.print_expression(node)

if isinstance(node, ASTArithmeticOperator):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ def _print(self, node: ASTNode) -> str:
return self.print_simple_expression(node)

def print(self, node: ASTNode) -> str:
if node.get_implicit_conversion_factor() and not node.get_implicit_conversion_factor() == 1:
return "(" + str(node.get_implicit_conversion_factor()) + " * (" + self._print(node) + "))"

return self._print(node)

def print_simple_expression(self, node: ASTSimpleExpression) -> str:
Expand Down
3 changes: 0 additions & 3 deletions pynestml/codegeneration/printers/python_expression_printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ class PythonExpressionPrinter(ExpressionPrinter):

def print(self, node: ASTNode) -> str:
if isinstance(node, ASTExpression):
if node.get_implicit_conversion_factor() and not node.get_implicit_conversion_factor() == 1:
return "(" + str(node.get_implicit_conversion_factor()) + " * (" + self.print_expression(node) + "))"

return self.print_expression(node)

return self._simple_expression_printer.print(node)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,4 @@ def _print(self, node: ASTNode) -> str:
return self.print_simple_expression(node)

def print(self, node: ASTNode) -> str:
if node.get_implicit_conversion_factor() and not node.get_implicit_conversion_factor() == 1:
return "(" + str(node.get_implicit_conversion_factor()) + " * (" + self._print(node) + "))"

return self._print(node)
11 changes: 1 addition & 10 deletions pynestml/codegeneration/printers/python_variable_printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

from __future__ import annotations

from pynestml.codegeneration.nest_unit_converter import NESTUnitConverter
from pynestml.codegeneration.printers.expression_printer import ExpressionPrinter
from pynestml.codegeneration.printers.variable_printer import VariablePrinter
from pynestml.codegeneration.python_code_generator_utils import PythonCodeGeneratorUtils
Expand Down Expand Up @@ -93,7 +92,7 @@ def print_variable(self, variable: ASTVariable) -> str:
if symbol is None:
# test if variable name can be resolved to a type
if PredefinedUnits.is_unit(variable.get_complete_name()):
return str(NESTUnitConverter.get_factor(PredefinedUnits.get_unit(variable.get_complete_name()).get_unit()))
return str(PredefinedUnits.get_unit(variable.get_complete_name()).get_unit())

code, message = Messages.get_could_not_resolve(variable.get_name())
Logger.log_message(log_level=LoggingLevel.ERROR, code=code, message=message,
Expand All @@ -105,17 +104,9 @@ def print_variable(self, variable: ASTVariable) -> str:
vector_param = "[" + self._expression_printer.print(variable.get_vector_parameter()) + "]"

if symbol.is_buffer():
if isinstance(symbol.get_type_symbol(), UnitTypeSymbol):
units_conversion_factor = NESTUnitConverter.get_factor(symbol.get_type_symbol().unit.unit)
else:
units_conversion_factor = 1
s = ""
if not units_conversion_factor == 1:
s += "(" + str(units_conversion_factor) + " * "
s += self._print(variable, symbol, with_origin=self.with_origin) + vector_param
s += vector_param
if not units_conversion_factor == 1:
s += ")"
return s

if symbol.is_inline_expression:
Expand Down
Loading
Loading