From e13d533ebd628dc613ada284ef83ed41d4a77484 Mon Sep 17 00:00:00 2001 From: abi-git-user Date: Tue, 10 Oct 2023 12:23:32 +1300 Subject: [PATCH] Create release v0.5.0-rc.1. --- .github/workflows/deploy-on-release.yml | 44 +- CMakeLists.txt | 9 +- cmake/TestUndefinedSymbolsAllowed.cmake | 1 + cmake/environmentchecks.cmake | 2 + cmake/utils/CMakeLists.txt | 1 + docs/changelogs/changelog_v0.5.0-rc.1.rst | 100 + docs/changelogs/index.rst | 1 + docs/coding_standards.rst | 5 + docs/dev_building_web_assembly.rst | 4 +- docs/index.rst | 1 + src/CMakeLists.txt | 13 +- src/analyser.cpp | 2058 ++++++++++------- src/analyserequation.cpp | 115 +- src/analyserequation_p.h | 20 +- src/analyserequationast.cpp | 121 +- src/analyserequationast_p.h | 14 +- src/analyserexternalvariable.cpp | 52 +- src/analyserexternalvariable_p.h | 14 +- src/analysermodel.cpp | 29 +- src/analysermodel_p.h | 2 +- src/analyservariable.cpp | 52 +- src/analyservariable_p.h | 11 +- src/annotator.cpp | 832 ++++--- src/anycellmlelement_p.h | 2 - src/api/libcellml/analyser.h | 32 +- src/api/libcellml/analyserequation.h | 147 +- src/api/libcellml/analyserequationast.h | 251 +- src/api/libcellml/analyserexternalvariable.h | 52 +- src/api/libcellml/analysermodel.h | 234 +- src/api/libcellml/analyservariable.h | 94 +- src/api/libcellml/component.h | 14 + src/api/libcellml/generator.h | 69 +- src/api/libcellml/generatorprofile.h | 425 +++- src/api/libcellml/issue.h | 8 + src/api/libcellml/model.h | 13 +- .../libcellml/undefines.h} | 25 +- src/api/libcellml/units.h | 33 +- src/bindings/interface/analyserequation.i | 32 +- src/bindings/interface/analyserequationast.i | 6 + src/bindings/interface/analysermodel.i | 3 + src/bindings/interface/analyservariable.i | 11 +- src/bindings/interface/component.i | 3 + src/bindings/interface/generator.i | 3 + src/bindings/interface/generatorprofile.i | 59 +- src/bindings/interface/model.i | 3 + src/bindings/interface/types.i | 38 +- src/bindings/interface/units.i | 6 + src/bindings/javascript/analyserequation.cpp | 12 +- .../javascript/analyserequationast.cpp | 4 +- src/bindings/javascript/analysermodel.cpp | 5 +- src/bindings/javascript/analyservariable.cpp | 3 + src/bindings/javascript/component.cpp | 1 + src/bindings/javascript/generator.cpp | 4 + src/bindings/javascript/generatorprofile.cpp | 21 +- src/bindings/javascript/issue.cpp | 1 + src/bindings/javascript/model.cpp | 1 + src/bindings/javascript/units.cpp | 2 + src/bindings/python/__init__.py | 11 +- src/component.cpp | 68 +- src/component_p.h | 2 +- src/componententity.cpp | 4 +- src/debug.cpp | 304 ++- src/debug.h | 18 +- src/entity.cpp | 1 + src/generator.cpp | 1460 +++++++----- src/generator_p.h | 38 +- src/generatorprofile.cpp | 290 ++- src/generatorprofilesha1values.h | 4 +- src/generatorprofiletools.cpp | 22 +- src/importer.cpp | 363 ++- src/internaltypes.h | 8 + src/issue.cpp | 15 +- src/logger.cpp | 3 +- src/mathmldtd.h | 1 + src/model.cpp | 50 +- src/parser.cpp | 29 +- src/printer.cpp | 57 +- src/types.cpp | 4 + src/units.cpp | 300 +-- src/units_p.h | 69 +- src/utilities.cpp | 326 ++- src/utilities.h | 142 +- src/validator.cpp | 771 +++++- src/variable.cpp | 85 +- src/xmlattribute.cpp | 10 +- src/xmlattribute.h | 2 +- src/xmldoc.cpp | 10 +- src/xmlnode.cpp | 51 +- src/xmlnode.h | 50 +- src/xmlutils.cpp | 8 +- src/xmlutils.h | 3 +- tests/CMakeLists.txt | 17 +- tests/analyser/analyser.cpp | 206 +- tests/annotator/annotator.cpp | 98 +- .../javascript/analyserequation.test.js | 29 +- .../javascript/analyserequationast.test.js | 9 +- .../bindings/javascript/analysermodel.test.js | 9 +- .../javascript/analyservariable.test.js | 15 +- tests/bindings/javascript/annotator.test.js | 18 +- tests/bindings/javascript/component.test.js | 5 + tests/bindings/javascript/generator.test.js | 11 +- .../javascript/generatorprofile.test.js | 72 +- tests/bindings/javascript/model.test.js | 12 +- tests/bindings/javascript/units.test.js | 8 + tests/bindings/javascript/version.test.js | 2 +- tests/bindings/python/test_analyser.py | 40 +- .../python/test_analyser_equation_ast.py | 2 +- tests/bindings/python/test_annotator.py | 25 +- tests/bindings/python/test_component.py | 7 + tests/bindings/python/test_generator.py | 4 + .../bindings/python/test_generator_profile.py | 123 +- tests/bindings/python/test_model.py | 14 + tests/bindings/python/test_units.py | 11 + tests/component/component.cpp | 136 ++ tests/connection/connection.cpp | 86 + tests/coverage/coverage.cpp | 841 ++++++- tests/equality/equality.cpp | 147 ++ tests/generator/generator.cpp | 1278 ++++------ tests/generator/generatorprofile.cpp | 126 +- tests/gtest/src/gtest-all.cc | 2 +- tests/importer/importer.cpp | 136 +- tests/importer/model_flattening.cpp | 897 +++++++ tests/libxml2issues.2.9.10.h | 13 + tests/libxml2issues.2.9.11.h | 14 + tests/libxml2issues.2.9.13.h | 12 + tests/libxml2issues.2.9.4.h | 14 + tests/math/math.cpp | 74 +- tests/model/import_requirement.cpp | 14 + tests/model/model.cpp | 2 +- tests/parser/cellml_1_0.cpp | 24 + tests/parser/parser.cpp | 2 + tests/printer/printer.cpp | 60 + .../analyser/not_equality_statement.cellml | 18 + ...variable.cellml => overconstrained.cellml} | 3 + .../overconstrained_nla_system.cellml | 50 + .../overconstrained_three_variables.cellml | 30 - .../annotator/lots_of_duplicate_ids.cellml | 40 +- .../cardiac_constant_simplified.cellml | 25 + ...iac_constant_simplified_alternative.cellml | 25 + tests/resources/coverage/analyser.cellml | 52 + .../resources/coverage/converttodouble.cellml | 52 + tests/resources/coverage/converttoint.cellml | 25 + tests/resources/coverage/generator/model.c | 604 +++++ .../generator}/model.cellml | 699 +++++- .../coverage => coverage/generator}/model.h | 4 +- .../generator/model.implementation.out | 375 +++ .../generator}/model.interface.out | 4 +- .../generator/model.modified.profile.c | 604 +++++ .../generator}/model.modified.profile.h | 4 +- .../generator}/model.modified.profile.py | 472 ++-- tests/resources/coverage/generator/model.out | 340 +++ .../coverage => coverage/generator}/model.py | 472 ++-- tests/resources/coverage/invalidxmlids.cellml | 21 + .../algebraic_eqn_computed_var_on_rhs/model.c | 22 +- .../model.external.c | 24 +- .../model.external.h | 2 +- .../model.external.py | 16 +- .../algebraic_eqn_computed_var_on_rhs/model.h | 2 +- .../model.py | 14 +- .../algebraic_eqn_const_var_on_rhs/model.c | 22 +- .../algebraic_eqn_const_var_on_rhs/model.h | 2 +- .../algebraic_eqn_const_var_on_rhs/model.py | 14 +- .../algebraic_eqn_constant_on_rhs/model.c | 14 +- .../algebraic_eqn_constant_on_rhs/model.h | 2 +- .../algebraic_eqn_constant_on_rhs/model.py | 6 +- .../algebraic_eqn_derivative_on_rhs/model.c | 24 +- .../algebraic_eqn_derivative_on_rhs/model.h | 4 +- .../algebraic_eqn_derivative_on_rhs/model.py | 8 +- .../model.c | 24 +- .../model.h | 4 +- .../model.py | 8 +- .../algebraic_eqn_state_var_on_rhs/model.c | 24 +- .../algebraic_eqn_state_var_on_rhs/model.h | 4 +- .../algebraic_eqn_state_var_on_rhs/model.py | 8 +- .../model.c | 24 +- .../model.h | 4 +- .../model.py | 8 +- .../model.c | 79 + .../model.cellml | 48 + .../model.external.c | 51 + .../model.external.h | 35 + .../model.external.py | 44 + .../model.h | 32 + .../model.py | 64 + .../model.c | 85 + .../model.cellml | 83 + .../model.h | 32 + .../model.one.external.c | 83 + .../model.one.external.h | 35 + .../model.one.external.py | 69 + .../model.py | 70 + .../model.three.externals.c | 51 + .../model.three.externals.h | 35 + .../model.three.externals.py | 44 + .../model.two.externals.c | 123 + .../model.two.externals.h | 35 + .../model.two.externals.py | 103 + .../model.not.ordered.c | 87 + .../model.not.ordered.cellml | 84 + .../model.not.ordered.h | 32 + .../model.not.ordered.py | 71 + .../model.ordered.c | 87 + .../model.ordered.cellml | 84 + .../model.ordered.h | 32 + .../model.ordered.py | 71 + .../algebraic_unknown_var_on_rhs/model.c | 46 + .../model.cellml} | 19 +- .../algebraic_unknown_var_on_rhs/model.h | 32 + .../algebraic_unknown_var_on_rhs/model.py | 38 + .../generator/cell_geometry_model/model.c | 24 +- .../cell_geometry_model/model.external.c | 24 +- .../cell_geometry_model/model.external.h | 2 +- .../cell_geometry_model/model.external.py | 16 +- .../generator/cell_geometry_model/model.h | 2 +- .../generator/cell_geometry_model/model.py | 16 +- .../model.c | 40 +- .../model.h | 4 +- .../model.py | 24 +- .../model.c | 24 +- .../model.h | 4 +- .../model.py | 8 +- .../cellml_unit_scaling_constant/model.c | 14 +- .../cellml_unit_scaling_constant/model.h | 2 +- .../cellml_unit_scaling_constant/model.py | 6 +- .../cellml_unit_scaling_rate/model.c | 24 +- .../cellml_unit_scaling_rate/model.h | 4 +- .../cellml_unit_scaling_rate/model.py | 8 +- .../cellml_unit_scaling_state/model.c | 24 +- .../cellml_unit_scaling_state/model.h | 4 +- .../cellml_unit_scaling_state/model.py | 8 +- .../model.c | 24 +- .../model.h | 4 +- .../model.py | 8 +- .../model.c | 24 +- .../model.h | 4 +- .../model.py | 8 +- .../cellml_unit_scaling_voi_direct/model.c | 24 +- .../cellml_unit_scaling_voi_direct/model.h | 4 +- .../cellml_unit_scaling_voi_direct/model.py | 8 +- .../cellml_unit_scaling_voi_indirect/model.c | 24 +- .../cellml_unit_scaling_voi_indirect/model.h | 4 +- .../cellml_unit_scaling_voi_indirect/model.py | 8 +- tests/resources/generator/coverage/model.c | 507 ---- .../coverage/model.implementation.out | 301 --- .../coverage/model.modified.profile.c | 507 ---- tests/resources/generator/coverage/model.out | 279 --- .../generator/dae_cellml_1_1_model/model.c | 154 ++ .../dae_cellml_1_1_model/model.cellml | 127 + .../generator/dae_cellml_1_1_model/model.h | 39 + .../generator/dae_cellml_1_1_model/model.py | 127 + .../generator/dependent_eqns/model.c | 32 +- .../generator/dependent_eqns/model.h | 4 +- .../generator/dependent_eqns/model.py | 16 +- .../model.c | 1098 ++++----- .../model.h | 4 +- .../model.py | 1082 ++++----- .../model.c | 836 +++---- .../model.h | 4 +- .../model.py | 820 +++---- .../model.algebraic.c | 114 +- .../model.algebraic.h | 6 +- .../model.algebraic.py | 98 +- .../model.c | 110 +- .../model.computed.constant.c | 114 +- .../model.computed.constant.h | 6 +- .../model.computed.constant.py | 98 +- .../model.constant.c | 114 +- .../model.constant.h | 6 +- .../model.constant.py | 98 +- .../model.dae.c | 563 +++++ .../model.dae.cellml | 575 +++++ .../model.dae.h | 39 + .../model.dae.py | 503 ++++ .../model.dependent.algebraic.c | 116 +- .../model.dependent.algebraic.h | 6 +- .../model.dependent.algebraic.py | 100 +- .../model.dependent.computed.constant.c | 120 +- .../model.dependent.computed.constant.h | 6 +- .../model.dependent.computed.constant.py | 104 +- .../model.dependent.constant.c | 118 +- .../model.dependent.constant.h | 6 +- .../model.dependent.constant.py | 102 +- .../model.dependent.state.c | 74 +- .../model.dependent.state.h | 6 +- .../model.dependent.state.py | 58 +- .../model.external.c | 96 +- .../model.external.h | 6 +- .../model.external.py | 80 +- .../model.h | 4 +- .../model.py | 94 +- .../model.state.c | 112 +- .../model.state.h | 6 +- .../model.state.py | 96 +- .../model_unknown_vars_on_rhs.cellml | 503 ++++ .../generator/noble_model_1962/model.c | 118 +- .../generator/noble_model_1962/model.h | 4 +- .../generator/noble_model_1962/model.py | 102 +- .../generator/ode_computed_var_on_rhs/model.c | 24 +- .../generator/ode_computed_var_on_rhs/model.h | 4 +- .../ode_computed_var_on_rhs/model.py | 8 +- .../model.c | 24 +- .../model.h | 4 +- .../model.py | 8 +- .../generator/ode_const_var_on_rhs/model.c | 24 +- .../generator/ode_const_var_on_rhs/model.h | 4 +- .../generator/ode_const_var_on_rhs/model.py | 8 +- .../model.c | 24 +- .../model.h | 4 +- .../model.py | 8 +- .../generator/ode_constant_on_rhs/model.c | 24 +- .../generator/ode_constant_on_rhs/model.h | 4 +- .../generator/ode_constant_on_rhs/model.py | 8 +- .../ode_constant_on_rhs_one_component/model.c | 24 +- .../ode_constant_on_rhs_one_component/model.h | 4 +- .../model.py | 8 +- .../ode_multiple_dependent_odes/model.c | 24 +- .../ode_multiple_dependent_odes/model.h | 4 +- .../ode_multiple_dependent_odes/model.py | 8 +- .../model.c | 24 +- .../model.h | 4 +- .../model.py | 8 +- .../ode_multiple_odes_with_same_name/model.c | 24 +- .../ode_multiple_odes_with_same_name/model.h | 4 +- .../ode_multiple_odes_with_same_name/model.py | 8 +- .../generator/ode_unknown_var_on_rhs/model.c | 69 + .../ode_unknown_var_on_rhs/model.cellml | 45 + .../generator/ode_unknown_var_on_rhs/model.h | 39 + .../generator/ode_unknown_var_on_rhs/model.py | 56 + .../robertson_model_1966/model.dae.c | 115 + .../robertson_model_1966/model.dae.cellml | 112 + .../robertson_model_1966/model.dae.h | 39 + .../robertson_model_1966/model.dae.py | 91 + .../robertson_model_1966/model.ode.c | 80 + .../robertson_model_1966/model.ode.cellml | 121 + .../robertson_model_1966/model.ode.h | 39 + .../robertson_model_1966/model.ode.py | 66 + .../generator/sine_model_imports/model.c | 50 +- .../generator/sine_model_imports/model.h | 4 +- .../generator/sine_model_imports/model.py | 34 +- .../model.c | 63 + .../model.cellml | 95 + .../model.h | 35 + .../model.py | 56 + .../model.c | 68 + .../model.cellml | 30 + .../model.h | 39 + .../model.py | 55 + .../import-requirements/importExample2.cellml | 15 + .../importer/HHComplete/GateModel.cellml | 69 + .../importer/HHComplete/LeakageModel.cellml | 64 + .../importer/HHComplete/MembraneModel.cellml | 126 + .../HHComplete/MembraneModelController.cellml | 42 + .../HHComplete/PotassiumChannelModel.cellml | 186 ++ .../HHComplete/SodiumChannelModel.cellml | 294 +++ .../importer/bondgraph/cpp_coupling.cellml | 48 + .../bondgraph/cpp_coupling_modules.cellml | 103 + .../bondgraph/cpp_coupling_parameters.cellml | 11 + .../complexbondgraph/cpp_coupling.cellml | 48 + .../cpp_coupling_modules.cellml | 103 + .../cpp_coupling_parameters.cellml | 11 + tests/resources/importer/invalid_model.cellml | 27 + .../mediumbondgraph/cpp_coupling.cellml | 27 + .../cpp_coupling_modules.cellml | 19 + .../cpp_coupling_parameters.cellml | 6 + tests/resources/importer/model1.cellml | 10 + tests/resources/importer/model2.cellml | 6 + .../importer/model_cascaded_units.cellml | 13 + tests/resources/importer/simple_model.cellml | 17 + .../resources/importer/simple_model_2.cellml | 7 + .../simplebondgraph/cpp_coupling.cellml | 13 + .../cpp_coupling_modules.cellml | 18 + .../cpp_coupling_parameters.cellml | 6 + .../importer/triangle_units_base.cellml | 7 + .../importer/triangle_units_opposite.cellml | 10 + .../importer/triangle_units_opposite_I.cellml | 10 + .../importer/triangle_units_point.cellml | 13 + .../importer/triangle_units_point_I.cellml | 13 + .../importer/units/base_model.cellml | 19 + .../units/base_model_illdefined.cellml | 20 + .../importer/units/left_model.cellml | 9 + tests/resources/importer/units/main.cellml | 9 + .../importer/units/right_model.cellml | 12 + .../importer/units/units_definitions.cellml | 16 + ...lidmathmlelementschildrenorsiblings.cellml | 904 ++++++++ .../modelflattening/user_ex_01/child.cellml | 10 + .../modelflattening/user_ex_01/parent.cellml | 13 + .../component_with_multiple_math.cellml | 21 + tests/test_utils.cpp | 3 + tests/test_utils.h | 2 +- tests/units/units.cpp | 679 ++++++ tests/validator/validator.cpp | 378 ++- tests/variable/variable.cpp | 42 + tests/version/version.cpp | 4 +- 393 files changed, 26501 insertions(+), 9950 deletions(-) create mode 100644 docs/changelogs/changelog_v0.5.0-rc.1.rst rename src/{configure/libcellmlconfig_p.in.h => api/libcellml/undefines.h} (61%) create mode 100644 tests/libxml2issues.2.9.10.h create mode 100644 tests/libxml2issues.2.9.11.h create mode 100644 tests/libxml2issues.2.9.13.h create mode 100644 tests/libxml2issues.2.9.4.h create mode 100644 tests/resources/analyser/not_equality_statement.cellml rename tests/resources/analyser/{overconstrained_one_variable.cellml => overconstrained.cellml} (89%) create mode 100644 tests/resources/analyser/overconstrained_nla_system.cellml delete mode 100644 tests/resources/analyser/overconstrained_three_variables.cellml create mode 100644 tests/resources/cellml1X/cardiac_constant_simplified.cellml create mode 100644 tests/resources/cellml1X/cardiac_constant_simplified_alternative.cellml create mode 100644 tests/resources/coverage/analyser.cellml create mode 100644 tests/resources/coverage/converttodouble.cellml create mode 100644 tests/resources/coverage/converttoint.cellml create mode 100644 tests/resources/coverage/generator/model.c rename tests/resources/{generator/coverage => coverage/generator}/model.cellml (77%) rename tests/resources/{generator/coverage => coverage/generator}/model.h (90%) create mode 100644 tests/resources/coverage/generator/model.implementation.out rename tests/resources/{generator/coverage => coverage/generator}/model.interface.out (79%) create mode 100644 tests/resources/coverage/generator/model.modified.profile.c rename tests/resources/{generator/coverage => coverage/generator}/model.modified.profile.h (89%) rename tests/resources/{generator/coverage => coverage/generator}/model.modified.profile.py (57%) create mode 100644 tests/resources/coverage/generator/model.out rename tests/resources/{generator/coverage => coverage/generator}/model.py (57%) create mode 100644 tests/resources/coverage/invalidxmlids.cellml create mode 100644 tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.c create mode 100644 tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.cellml create mode 100644 tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.c create mode 100644 tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.h create mode 100644 tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.py create mode 100644 tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.h create mode 100644 tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.py create mode 100644 tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.c create mode 100644 tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.cellml create mode 100644 tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.h create mode 100644 tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.one.external.c create mode 100644 tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.one.external.h create mode 100644 tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.one.external.py create mode 100644 tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.py create mode 100644 tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.three.externals.c create mode 100644 tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.three.externals.h create mode 100644 tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.three.externals.py create mode 100644 tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.two.externals.c create mode 100644 tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.two.externals.h create mode 100644 tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.two.externals.py create mode 100644 tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.c create mode 100644 tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.cellml create mode 100644 tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.h create mode 100644 tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.py create mode 100644 tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.c create mode 100644 tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.cellml create mode 100644 tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.h create mode 100644 tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.py create mode 100644 tests/resources/generator/algebraic_unknown_var_on_rhs/model.c rename tests/resources/{analyser/overconstrained_two_variables.cellml => generator/algebraic_unknown_var_on_rhs/model.cellml} (53%) create mode 100644 tests/resources/generator/algebraic_unknown_var_on_rhs/model.h create mode 100644 tests/resources/generator/algebraic_unknown_var_on_rhs/model.py delete mode 100644 tests/resources/generator/coverage/model.c delete mode 100644 tests/resources/generator/coverage/model.implementation.out delete mode 100644 tests/resources/generator/coverage/model.modified.profile.c delete mode 100644 tests/resources/generator/coverage/model.out create mode 100644 tests/resources/generator/dae_cellml_1_1_model/model.c create mode 100644 tests/resources/generator/dae_cellml_1_1_model/model.cellml create mode 100644 tests/resources/generator/dae_cellml_1_1_model/model.h create mode 100644 tests/resources/generator/dae_cellml_1_1_model/model.py create mode 100644 tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.c create mode 100644 tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.cellml create mode 100644 tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.h create mode 100644 tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.py create mode 100644 tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model_unknown_vars_on_rhs.cellml create mode 100644 tests/resources/generator/ode_unknown_var_on_rhs/model.c create mode 100644 tests/resources/generator/ode_unknown_var_on_rhs/model.cellml create mode 100644 tests/resources/generator/ode_unknown_var_on_rhs/model.h create mode 100644 tests/resources/generator/ode_unknown_var_on_rhs/model.py create mode 100644 tests/resources/generator/robertson_model_1966/model.dae.c create mode 100644 tests/resources/generator/robertson_model_1966/model.dae.cellml create mode 100644 tests/resources/generator/robertson_model_1966/model.dae.h create mode 100644 tests/resources/generator/robertson_model_1966/model.dae.py create mode 100644 tests/resources/generator/robertson_model_1966/model.ode.c create mode 100644 tests/resources/generator/robertson_model_1966/model.ode.cellml create mode 100644 tests/resources/generator/robertson_model_1966/model.ode.h create mode 100644 tests/resources/generator/robertson_model_1966/model.ode.py create mode 100644 tests/resources/generator/unknown_variable_as_external_variable/model.c create mode 100644 tests/resources/generator/unknown_variable_as_external_variable/model.cellml create mode 100644 tests/resources/generator/unknown_variable_as_external_variable/model.h create mode 100644 tests/resources/generator/unknown_variable_as_external_variable/model.py create mode 100644 tests/resources/generator/variable_initialised_using_a_constant/model.c create mode 100644 tests/resources/generator/variable_initialised_using_a_constant/model.cellml create mode 100644 tests/resources/generator/variable_initialised_using_a_constant/model.h create mode 100644 tests/resources/generator/variable_initialised_using_a_constant/model.py create mode 100644 tests/resources/import-requirements/importExample2.cellml create mode 100644 tests/resources/importer/HHComplete/GateModel.cellml create mode 100644 tests/resources/importer/HHComplete/LeakageModel.cellml create mode 100644 tests/resources/importer/HHComplete/MembraneModel.cellml create mode 100644 tests/resources/importer/HHComplete/MembraneModelController.cellml create mode 100644 tests/resources/importer/HHComplete/PotassiumChannelModel.cellml create mode 100644 tests/resources/importer/HHComplete/SodiumChannelModel.cellml create mode 100644 tests/resources/importer/bondgraph/cpp_coupling.cellml create mode 100644 tests/resources/importer/bondgraph/cpp_coupling_modules.cellml create mode 100644 tests/resources/importer/bondgraph/cpp_coupling_parameters.cellml create mode 100644 tests/resources/importer/complexbondgraph/cpp_coupling.cellml create mode 100644 tests/resources/importer/complexbondgraph/cpp_coupling_modules.cellml create mode 100644 tests/resources/importer/complexbondgraph/cpp_coupling_parameters.cellml create mode 100644 tests/resources/importer/mediumbondgraph/cpp_coupling.cellml create mode 100644 tests/resources/importer/mediumbondgraph/cpp_coupling_modules.cellml create mode 100644 tests/resources/importer/mediumbondgraph/cpp_coupling_parameters.cellml create mode 100644 tests/resources/importer/model1.cellml create mode 100644 tests/resources/importer/model2.cellml create mode 100644 tests/resources/importer/model_cascaded_units.cellml create mode 100644 tests/resources/importer/simple_model.cellml create mode 100644 tests/resources/importer/simple_model_2.cellml create mode 100644 tests/resources/importer/simplebondgraph/cpp_coupling.cellml create mode 100644 tests/resources/importer/simplebondgraph/cpp_coupling_modules.cellml create mode 100644 tests/resources/importer/simplebondgraph/cpp_coupling_parameters.cellml create mode 100644 tests/resources/importer/triangle_units_base.cellml create mode 100644 tests/resources/importer/triangle_units_opposite.cellml create mode 100644 tests/resources/importer/triangle_units_opposite_I.cellml create mode 100644 tests/resources/importer/triangle_units_point.cellml create mode 100644 tests/resources/importer/triangle_units_point_I.cellml create mode 100644 tests/resources/importer/units/base_model.cellml create mode 100644 tests/resources/importer/units/base_model_illdefined.cellml create mode 100644 tests/resources/importer/units/left_model.cellml create mode 100644 tests/resources/importer/units/main.cellml create mode 100644 tests/resources/importer/units/right_model.cellml create mode 100644 tests/resources/importer/units/units_definitions.cellml create mode 100644 tests/resources/invalidmathmlelementschildrenorsiblings.cellml create mode 100644 tests/resources/modelflattening/user_ex_01/child.cellml create mode 100644 tests/resources/modelflattening/user_ex_01/parent.cellml create mode 100644 tests/resources/printer/component_with_multiple_math.cellml diff --git a/.github/workflows/deploy-on-release.yml b/.github/workflows/deploy-on-release.yml index cd2fb1fd0..4cf4f60b5 100644 --- a/.github/workflows/deploy-on-release.yml +++ b/.github/workflows/deploy-on-release.yml @@ -43,7 +43,7 @@ jobs: endforeach() endif() message(STATUS "Setting binaries destination to '${_OUTPUT_LOCATION}'.") - message("::set-output name=BINARIES-DESTINATION::${_OUTPUT_LOCATION}") + file(APPEND $ENV{GITHUB_OUTPUT} "binaries-destination=${_OUTPUT_LOCATION}") - name: Determine next jobs id: do-jobs @@ -67,7 +67,7 @@ jobs: endforeach() endif() message(STATUS "Setting allowed jobs to '${_ALLOWED_JOBS}'.") - message("::set-output name=allowed-jobs::${_ALLOWED_JOBS}") + file(APPEND $ENV{GITHUB_OUTPUT} "allowed-jobs=${_ALLOWED_JOBS}") os-binaries: needs: setup-jobs @@ -99,19 +99,19 @@ jobs: steps: - name: Checkout libCellML - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: ref: ${{ github.event.release.tag_name }} - name: Checkout zlib - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: OpenCMISS-Dependencies/zlib path: zlib ref: v1.2.3 - name: Checkout LibXml2 - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: OpenCMISS-Dependencies/libxml2 path: libxml2 @@ -257,8 +257,7 @@ jobs: # softprops action requires a list of newline separated files. # The %0A will be converted by GitHub actions into '\n'. string(REPLACE ";" "%0A" _DIST_FILES "${_DIST_FILES}") - execute_process( - COMMAND echo "::set-output name=files::${_DIST_FILES}") + file(APPEND $ENV{GITHUB_OUTPUT} "files=${_DIST_FILES}") - name: Publish libraries if: needs.setup-jobs.outputs.binaries-destination == 'Publish' @@ -296,7 +295,7 @@ jobs: steps: - name: Check out libCellML - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: ref: ${{ github.event.release.tag_name }} @@ -308,22 +307,21 @@ jobs: cp src/bindings/python/README.rst src/bindings/python/libcellml/README.rst mv src/bindings/python/cibuildwheel.setup.py src/bindings/python/setup.py v=${{ matrix.py }} - echo "Setting tag as: TAG=${GITHUB_REF#refs/tags/}" - echo ::set-output name=TAG::${GITHUB_REF#refs/tags/} - #echo ::set-output name=TAG::v0.2.0-dev.21 - echo "Setting build as: BUILD=cp${v/./}-*" - echo ::set-output name=BUILD::cp${v/./}-* + echo "Setting tag as: tag=${GITHUB_REF#refs/tags/}" + echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT + echo "Setting build as: build=cp${v/./}-*" + echo "build=cp${v/./}-*" >> $GITHUB_OUTPUT if [[ "macOS" == "${{ matrix.name }}" ]]; then if [[ "${{ matrix.py }}" == "3.8" ]]; then - echo "Setting MACOS_ARCHS as: MACOS_ARCHS='x86_64'" - echo ::set-output name=MACOS_ARCHS::x86_64 + echo "Setting macos_archs as: macos_archs='x86_64'" + echo "macos_archs=x86_64" >> $GITHUB_OUTPUT else - echo "Setting MACOS_ARCHS as: MACOS_ARCHS='x86_64 arm64'" - echo ::set-output name=MACOS_ARCHS::"x86_64 arm64" + echo "Setting macos_archs as: macos_archs='x86_64 arm64'" + echo 'MACOS_ARCHS="x86_64 arm64"' >> $GITHUB_OUTPUT fi else - echo "Setting MACOS_ARCHS as: MACOS_ARCHS='x86_64'" - echo ::set-output name=MACOS_ARCHS::x86_64 + echo "Setting macos_archs as: macos_archs='x86_64'" + echo "macos_archs=x86_64" >> $GITHUB_OUTPUT fi - name: Configure MSVC @@ -380,20 +378,20 @@ jobs: runs-on: macos-12 steps: - name: Checkout libCellML - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: libcellml ref: ${{ github.event.release.tag_name }} - name: Checkout zlib - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: OpenCMISS-Dependencies/zlib path: zlib ref: v1.2.3 - name: Checkout LibXml2 - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: OpenCMISS-Dependencies/libxml2 path: libxml2 @@ -435,7 +433,7 @@ jobs: cd build-libcellml-release/src/bindings/javascript npm pack package=`ls $PWD/libcellml.js-*.tgz` - echo "::set-output name=files::$package" + echo "files=$package" >> $GITHUB_OUTPUT - name: Upload libcellml.js as artifacts if: needs.setup-jobs.outputs.binaries-destination == 'Artifact' diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ec41dd80..0a014b8d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,10 +14,12 @@ cmake_minimum_required(VERSION 3.18.0) +set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15 CACHE STRING "Minimum OS X deployment version.") + set(PROJECT_NAME libCellML) set(PROJECT_URL https://libcellml.org) -set(_PROJECT_VERSION 0.4.0) -set(PROJECT_DEVELOPER_VERSION ) +set(_PROJECT_VERSION 0.5.0) +set(PROJECT_DEVELOPER_VERSION -rc.1) project(${PROJECT_NAME} VERSION ${_PROJECT_VERSION} LANGUAGES CXX) # Set policies that affect the build. @@ -105,7 +107,7 @@ set(_PARAM_ANNOTATION "Build Python wrappers.") if(BINDINGS_AVAILABLE AND PYTHON_BINDINGS_AVAILABLE) set(LIBCELLML_BINDINGS_PYTHON ON CACHE BOOL "${_PARAM_ANNOTATION}") endif() -if(DEFINED BINDINGS_PYTHON AND BINDINGS_AVAILABLE AND Python_Development_FOUND) +if(DEFINED BINDINGS_PYTHON AND BINDINGS_AVAILABLE AND PYTHON_BINDINGS_AVAILABLE) set(LIBCELLML_BINDINGS_PYTHON "${BINDINGS_PYTHON}" CACHE BOOL "${_PARAM_ANNOTATION}" FORCE) elseif(BINDINGS_PYTHON) message(WARNING "Python bindings requested but development files for Python or SWIG were not found!") @@ -276,4 +278,3 @@ endif() # Add target to print out version add_custom_target(print_version COMMAND ${CMAKE_COMMAND} -E echo "version=v${PROJECT_VERSION}${PROJECT_DEVELOPER_VERSION}") - diff --git a/cmake/TestUndefinedSymbolsAllowed.cmake b/cmake/TestUndefinedSymbolsAllowed.cmake index 2ca8d8942..5f02ca7fc 100644 --- a/cmake/TestUndefinedSymbolsAllowed.cmake +++ b/cmake/TestUndefinedSymbolsAllowed.cmake @@ -26,6 +26,7 @@ function(Test_Undefined_Symbols_Allowed) file(WRITE "${test_project_dir}/CMakeLists.txt" " +cmake_minimum_required(VERSION 3.18.0) project(undefined CXX) add_library(foo SHARED \"foo.cpp\") ") diff --git a/cmake/environmentchecks.cmake b/cmake/environmentchecks.cmake index b745fac32..071e33682 100644 --- a/cmake/environmentchecks.cmake +++ b/cmake/environmentchecks.cmake @@ -139,6 +139,8 @@ if(LibXml2_FOUND) set(LIBXML2_TARGET_NAME xml2) elseif(TARGET LibXml2) set(LIBXML2_TARGET_NAME LibXml2) + elseif(TARGET LibXml2::LibXml2) + set(LIBXML2_TARGET_NAME LibXml2::LibXml2) else() message(FATAL_ERROR "FindLibXml2: Found configuration file for LibXml2 but could not determine a target name from it.") endif() diff --git a/cmake/utils/CMakeLists.txt b/cmake/utils/CMakeLists.txt index b914aa19a..f5311581e 100644 --- a/cmake/utils/CMakeLists.txt +++ b/cmake/utils/CMakeLists.txt @@ -35,6 +35,7 @@ target_link_libraries(calculatesha1 PRIVATE cellml) add_custom_command(OUTPUT generatorprofilesha1values.cmake COMMENT "Updating SHA-1 values for C and Python generator profiles." WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS calculatesha1 COMMAND calculatesha1 COMMAND ${CMAKE_COMMAND} -P "${PROJECT_SOURCE_DIR}/cmake/generateprofilesha1header.cmake") add_custom_target(update_generator_profile_sha1_values diff --git a/docs/changelogs/changelog_v0.5.0-rc.1.rst b/docs/changelogs/changelog_v0.5.0-rc.1.rst new file mode 100644 index 000000000..5c0b35f34 --- /dev/null +++ b/docs/changelogs/changelog_v0.5.0-rc.1.rst @@ -0,0 +1,100 @@ +libCellML v0.5.0-rc.1 Changelog +=============================== + +Analyser +-------- + +* Analyser: add support for unknown variables that have been marked as external by `@agarny `_ [`#1184 `_]. +* Analyser: don't optimise the order of variables and equations by `@agarny `_ [`#1090 `_]. +* Analyser: reworked the analysis of a model with external variables by `@agarny `_ [`#1077 `_]. +* Analyser: allow for the unknown variable to be either on the LHS or RHS of an equation by `@agarny `_ [`#1071 `_]. + +Bug +--- + +* Fix flattening segfault by `@hsorby `_ [`#1179 `_]. +* Resolve imports by `@hsorby `_ [`#1177 `_]. +* Flattening is changing imported models by `@hsorby `_ [`#1175 `_]. +* Fix importing units from a common base model by `@hsorby `_ [`#1161 `_]. +* Fix importing in permissive mode by `@hsorby `_ [`#1157 `_]. +* Align assignAllIds with documentation by `@hsorby `_ [`#1151 `_]. +* Analyser/Generator: don't use weak pointers by `@agarny `_ [`#1133 `_]. +* Fix an issue when initialising a state variable using a variable instead of a constant by `@agarny `_ [`#1147 `_]. +* Fix segfault when using Units::equivalent/compatible API by `@hsorby `_ [`#1145 `_]. +* Fix parsing of CellML 1.X models with multiple math in a component by `@hsorby `_ [`#1146 `_]. +* Enable printer to print models that have multiple math documents in a single math container object by `@hsorby `_ [`#1142 `_]. +* Set minimum OSX deployment target that supports std::any by `@hsorby `_ [`#1111 `_]. +* Try using uLong for buffer size in uncompress by `@hsorby `_ [`#1110 `_]. + +Coverage +-------- + +* Resolve branch coverage in validator.cpp by `@hsorby `_ [`#1128 `_]. +* Resolve branch coverage in annotator.cpp by `@hsorby `_ [`#1127 `_]. +* Resolve branch coverage in utilities.cpp by `@hsorby `_ [`#1126 `_]. +* Resolve branch coverage in units.cpp by `@hsorby `_ [`#1125 `_]. +* Resolve branch coverage in importer.cpp by `@hsorby `_ [`#1124 `_]. +* Resolve branch coverage in printer.cpp by `@hsorby `_ [`#1123 `_]. +* Resolve branch coverage in variable.cpp by `@hsorby `_ [`#1122 `_]. +* Resolve branch coverage in component.cpp by `@hsorby `_ [`#1116 `_]. +* Resolve branch coverage in reset.cpp by `@hsorby `_ [`#1120 `_]. +* Resolve branch coverage in model.cpp by `@hsorby `_ [`#1121 `_]. +* Resolve branch coverage in types.cpp by `@hsorby `_ [`#1119 `_]. +* Resolve branch coverage in logger.cpp by `@hsorby `_ [`#1118 `_]. +* Resolve branch coverage in importsource.cpp by `@hsorby `_ [`#1117 `_]. +* Resolve branch coverage in componententity.cpp by `@hsorby `_ [`#1115 `_]. +* Resolve branch coverage in xmlattribute.cpp by `@hsorby `_ [`#1114 `_]. +* Resolve branch coverage in xmlnode.cpp by `@hsorby `_ [`#1113 `_]. +* Resolve branch coverage in xmldoc.cpp by `@hsorby `_ [`#1112 `_]. + +Generator +--------- + +* Generator: cast our malloc() calls by `@agarny `_ [`#1076 `_]. + +Imports +------- + +* Flattening multiple equivalences by `@hsorby `_ [`#1170 `_]. +* Importing units with references to non-standard units by `@hsorby `_ [`#1167 `_]. + +Infrastructure +-------------- + +* Set macOS 10.15 as the minimum deployment target for macOS by `@hsorby `_ [`#1181 `_]. +* GitHub Actions update by `@hsorby `_ [`#1154 `_]. +* CMake: fixed an issue with BINDINGS_PYTHON's value not being taken into account by `@agarny `_ [`#1149 `_]. +* CMake: fixed a warning when running the `UNDEFINED_SYMBOLS_ALLOWED` test by `@agarny `_ [`#1138 `_]. +* Analyser/Generator: cleaning up of code by `@agarny `_ [`#1080 `_]. +* Fix for CI issues by `@hsorby `_ [`#1088 `_]. +* Update environmentchecks.cmake to handle newer LibXml2 CMake configuration by `@hsorby `_ [`#1085 `_]. + +Miscellaneous +------------- + +* Analyser/Generator: added some `xxxAsString()` methods by `@agarny `_ [`#1131 `_]. +* Make gcc 11.3.0 happy on Ubuntu 22.04 LTS by `@agarny `_ [`#1153 `_]. +* Analyser/Generator: replace if...else statements with switch ones wherever possible by `@agarny `_ [`#1135 `_]. +* Tests: added support for libXml2 2.9.11+ by `@agarny `_ [`#1069 `_]. + +No category +----------- + +* AnalyserVariable: hold onto the owning component reference by `@agarny `_ [`#1185 `_]. + +Validation +---------- + +* Improve MathML validation by `@agarny `_ [`#1083 `_]. + +Contributors +------------ + +.. image:: https://avatars.githubusercontent.com/u/778048?v=4 + :target: https://github.com/hsorby + :height: 32 + :width: 32 +.. image:: https://avatars.githubusercontent.com/u/602265?v=4 + :target: https://github.com/agarny + :height: 32 + :width: 32 diff --git a/docs/changelogs/index.rst b/docs/changelogs/index.rst index 26a7b11f9..2f586d192 100644 --- a/docs/changelogs/index.rst +++ b/docs/changelogs/index.rst @@ -4,6 +4,7 @@ Changelogs .. toctree:: + changelog_v0.5.0-rc.1 changelog_v0.4.0 changelog_v0.3.104 changelog_v0.3.103 diff --git a/docs/coding_standards.rst b/docs/coding_standards.rst index 6167ece72..4c6d07c85 100644 --- a/docs/coding_standards.rst +++ b/docs/coding_standards.rst @@ -37,3 +37,8 @@ The following rules for naming of variables should be followed. * Class member variables: :code:`mMyClassMemberVariable`. * Function parameter variables: :code:`myFunctionParameterVariable`. * Local variables: :code:`myLocalVariable`. + +Weak pointers +============= + + * The return value of :code:`std::weak_ptr::lock()` should only be tested if it may be equal to :code:`nullptr`. diff --git a/docs/dev_building_web_assembly.rst b/docs/dev_building_web_assembly.rst index 727686249..2f1446d86 100644 --- a/docs/dev_building_web_assembly.rst +++ b/docs/dev_building_web_assembly.rst @@ -65,11 +65,11 @@ Start by making the current directory the parent of the zlib build directory:: Then, as before, configure the library:: - emcmake cmake -S libxml2 -B build-libxml2-release -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=usr/local -DZLIB_DIR=../usr/local/lib/cmake/ZLIB-1.2.3/ -DBUILD_SHARED_LIBS=OFF -DLIBXML2_WITH_ICONV=OFF -DLIBXML2_WITH_LZMA=OFF -DLIBXML2_WITH_PYTHON=OFF -DLIBXML2_WITH_TESTS=OFF -DLIBXML2_WITH_PROGRAMS=OFF + emcmake cmake -S libxml2 -B build-libxml2-release -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=usr/local -DZLIB_DIR=../usr/local/lib/cmake/ZLIB-1.2.12/ -DBUILD_SHARED_LIBS=OFF -DLIBXML2_WITH_ICONV=OFF -DLIBXML2_WITH_LZMA=OFF -DLIBXML2_WITH_PYTHON=OFF -DLIBXML2_WITH_TESTS=OFF -DLIBXML2_WITH_PROGRAMS=OFF There are seven additions to the configure command this time: -1. We set :code:`ZLIB_DIR` to enable the configuration to find our *zlib* library we just installed, :code:`-DZLIB_DIR=../usr/local/lib/cmake/ZLIB-1.2.3/`. +1. We set :code:`ZLIB_DIR` to enable the configuration to find our *zlib* library we just installed, :code:`-DZLIB_DIR=../usr/local/lib/cmake/ZLIB-1.2.12/`. 2. We turn off building a shared *libxml2* library, -DBUILD_SHARED_LIBS=OFF. 3. We turn off building *libxml2* with iconv, -DLIBXML2_WITH_ICONV=OFF. 4. We turn off building *libxml2* with lzma compression, -DLIBXML2_WITH_LZMA=OFF. diff --git a/docs/index.rst b/docs/index.rst index 7f0f6540f..bcb21b0a7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -39,6 +39,7 @@ Changelogs .. toctree:: + changelogs/changelog_v0.5.0-rc.1 changelogs/changelog_v0.4.0 changelogs/changelog_v0.3.104 changelogs/changelog_v0.3.103 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5ddfbe0eb..2129b330e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,15 +33,6 @@ configure_file( ${LIBCELLML_VERSIONCONFIG_H} ) -set(LIBCELLML_PRIVATECONFIG_IN_H "${CMAKE_CURRENT_SOURCE_DIR}/configure/libcellmlconfig_p.in.h") -set(LIBCELLML_PRIVATECONFIG_H "${CMAKE_CURRENT_BINARY_DIR}/libcellmlconfig_p.h") -if(MSVC) - set(UNCOMPRESS_SIZE_TYPE "unsigned long") -else() - set(UNCOMPRESS_SIZE_TYPE "size_t") -endif() -configure_file(${LIBCELLML_PRIVATECONFIG_IN_H} ${LIBCELLML_PRIVATECONFIG_H}) - list(APPEND CLEAN_FILES ${LIBCELLML_VERSIONCONFIG_H} ${LIBCELLML_EXPORTDEFINITIONS_H}) set(SOURCE_FILES @@ -113,6 +104,7 @@ set(GIT_API_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/reset.h ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/strict.h ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/types.h + ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/undefines.h ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/units.h ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/validator.h ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/variable.h @@ -163,7 +155,6 @@ set(GIT_HEADER_FILES set(HEADER_FILES ${GIT_HEADER_FILES} - ${LIBCELLML_PRIVATECONFIG_H} ${LIBCELLML_VERSIONCONFIG_H} ) @@ -243,6 +234,7 @@ target_include_directories(cellml_debug_utilities set_target_properties(cellml_debug_utilities PROPERTIES CXX_VISIBILITY_PRESET hidden DEBUG_POSTFIX d + POSITION_INDEPENDENT_CODE 1 VISIBILITY_INLINES_HIDDEN 1 ) @@ -383,7 +375,6 @@ set(API_HEADER_FILES ${GIT_API_HEADER_FILES} PARENT_SCOPE) set(MODULE_HEADER_FILES ${MODULE_HEADER_FILES} PARENT_SCOPE) set(HEADER_FILES ${GIT_HEADER_FILES} PARENT_SCOPE) set(GENERATED_HEADER_FILES - ${LIBCELLML_PRIVATECONFIG_H} ${LIBCELLML_VERSIONCONFIG_H} PARENT_SCOPE ) diff --git a/src/analyser.cpp b/src/analyser.cpp index 0dd5e5669..3f12f9f4d 100644 --- a/src/analyser.cpp +++ b/src/analyser.cpp @@ -16,71 +16,77 @@ limitations under the License. #include "libcellml/analyser.h" +#include +#include + #include "libcellml/analyserequation.h" #include "libcellml/analyserequationast.h" #include "libcellml/analyserexternalvariable.h" #include "libcellml/analysermodel.h" #include "libcellml/analyservariable.h" #include "libcellml/component.h" +#include "libcellml/generator.h" +#include "libcellml/generatorprofile.h" #include "libcellml/model.h" #include "libcellml/units.h" #include "libcellml/validator.h" #include "libcellml/variable.h" -#include - #include "analyserequation_p.h" #include "analyserequationast_p.h" #include "analysermodel_p.h" #include "analyservariable_p.h" #include "anycellmlelement_p.h" -#include "generator_p.h" +#include "commonutils.h" #include "issue_p.h" #include "logger_p.h" #include "utilities.h" #include "xmldoc.h" #include "xmlutils.h" -#ifdef TRUE -# undef TRUE -#endif - -#ifdef FALSE -# undef FALSE -#endif - -#ifdef NAN -# undef NAN -#endif +#include "libcellml/undefines.h" namespace libcellml { struct AnalyserInternalEquation; struct AnalyserInternalVariable; +using AnalyserInternalEquationWeakPtr = std::weak_ptr; using AnalyserInternalEquationPtr = std::shared_ptr; using AnalyserInternalVariablePtr = std::shared_ptr; +using AnalyserInternalEquationWeakPtrs = std::vector; +using AnalyserInternalEquationPtrs = std::vector; +using AnalyserInternalVariablePtrs = std::vector; + +using AnalyserEquationPtrs = std::vector; +using AnalyserVariablePtrs = std::vector; +using AnalyserExternalVariablePtrs = std::vector; + struct AnalyserInternalVariable { enum struct Type { UNKNOWN, SHOULD_BE_STATE, + INITIALISED, VARIABLE_OF_INTEGRATION, STATE, CONSTANT, COMPUTED_TRUE_CONSTANT, COMPUTED_VARIABLE_BASED_CONSTANT, + INITIALISED_ALGEBRAIC, ALGEBRAIC, OVERCONSTRAINED }; size_t mIndex = MAX_SIZE_T; Type mType = Type::UNKNOWN; + bool mIsExternal = false; VariablePtr mInitialisingVariable; VariablePtr mVariable; + VariablePtrs mDependencies; static AnalyserInternalVariablePtr create(const VariablePtr &variable); @@ -89,11 +95,12 @@ struct AnalyserInternalVariable void makeVoi(); void makeState(); + void makeConstant(size_t &index); }; AnalyserInternalVariablePtr AnalyserInternalVariable::create(const VariablePtr &variable) { - auto res = std::shared_ptr {new AnalyserInternalVariable {}}; + auto res = AnalyserInternalVariablePtr {new AnalyserInternalVariable {}}; res->setVariable(variable); @@ -104,11 +111,11 @@ void AnalyserInternalVariable::setVariable(const VariablePtr &variable, bool checkInitialValue) { if (checkInitialValue && !variable->initialValue().empty()) { - // The variable has an initial value, so it can either be a constant or - // a state. By default, we consider it to be a constant and, if we find - // an ODE for that variable, we will know that it was actually a state. + // The variable has an initial value, so it can either be a constant, an + // algebraic variable (that needs to be computed using an NLA solver), + // or a state. For now, all we know is that it is initialised. - mType = Type::CONSTANT; + mType = Type::INITIALISED; mInitialisingVariable = variable; } @@ -123,13 +130,26 @@ void AnalyserInternalVariable::makeVoi() void AnalyserInternalVariable::makeState() { - if (mType == Type::UNKNOWN) { + switch (mType) { + case Type::UNKNOWN: mType = Type::SHOULD_BE_STATE; - } else if (mType == Type::CONSTANT) { + + break; + case Type::INITIALISED: mType = Type::STATE; + + break; + default: // Other types we don't care about. + break; } } +void AnalyserInternalVariable::makeConstant(size_t &index) +{ + mIndex = ++index; + mType = Type::CONSTANT; +} + struct AnalyserInternalEquation { enum struct Type @@ -137,23 +157,26 @@ struct AnalyserInternalEquation UNKNOWN, TRUE_CONSTANT, VARIABLE_BASED_CONSTANT, - RATE, + ODE, + NLA, ALGEBRAIC }; - size_t mOrder = MAX_SIZE_T; Type mType = Type::UNKNOWN; VariablePtrs mDependencies; AnalyserEquationAstPtr mAst; - std::vector mVariables; - std::vector mOdeVariables; - std::vector mAllVariables; + ComponentPtr mComponent; - AnalyserInternalVariablePtr mVariable; - ComponentPtr mComponent = nullptr; + AnalyserInternalVariablePtrs mVariables; + AnalyserInternalVariablePtrs mOdeVariables; + AnalyserInternalVariablePtrs mAllVariables; + AnalyserInternalVariablePtrs mUnknownVariables; + + size_t mNlaSystemIndex = MAX_SIZE_T; + AnalyserInternalEquationWeakPtrs mNlaSiblings; bool mComputedTrueConstant = true; bool mComputedVariableBasedConstant = true; @@ -167,16 +190,25 @@ struct AnalyserInternalEquation static bool isKnownVariable(const AnalyserInternalVariablePtr &variable); static bool isKnownOdeVariable(const AnalyserInternalVariablePtr &odeVariable); - static bool hasKnownVariables(const std::vector &variables); - static bool hasNonConstantVariables(const std::vector &variables); + static bool hasKnownVariables(const AnalyserInternalVariablePtrs &variables); + bool hasKnownVariables(); + + static bool isNonConstantVariable(const AnalyserInternalVariablePtr &variable); + + static bool hasNonConstantVariables(const AnalyserInternalVariablePtrs &variables); + bool hasNonConstantVariables(); + + bool variableOnLhsRhs(const AnalyserInternalVariablePtr &variable, + const AnalyserEquationAstPtr &astChild); + bool variableOnRhs(const AnalyserInternalVariablePtr &variable); + bool variableOnLhsOrRhs(const AnalyserInternalVariablePtr &variable); - bool check(size_t &equationOrder, size_t &stateIndex, size_t &variableIndex, - const AnalyserModelPtr &model); + bool check(const AnalyserModelPtr &model, size_t &stateIndex, size_t &variableIndex, bool checkNlaSystems); }; AnalyserInternalEquationPtr AnalyserInternalEquation::create(const ComponentPtr &component) { - auto res = std::shared_ptr {new AnalyserInternalEquation {}}; + auto res = AnalyserInternalEquationPtr {new AnalyserInternalEquation {}}; res->mAst = AnalyserEquationAst::create(); res->mComponent = component; @@ -186,11 +218,12 @@ AnalyserInternalEquationPtr AnalyserInternalEquation::create(const ComponentPtr AnalyserInternalEquationPtr AnalyserInternalEquation::create(const AnalyserInternalVariablePtr &variable) { - auto res = std::shared_ptr {new AnalyserInternalEquation {}}; + auto res = AnalyserInternalEquationPtr {new AnalyserInternalEquation {}}; - res->mVariable = variable; res->mComponent = owningComponent(variable->mVariable); + res->mUnknownVariables.push_back(variable); + return res; } @@ -220,45 +253,83 @@ bool AnalyserInternalEquation::isKnownOdeVariable(const AnalyserInternalVariable return odeVariable->mIndex != MAX_SIZE_T; } -bool AnalyserInternalEquation::hasKnownVariables(const std::vector &variables) +bool AnalyserInternalEquation::hasKnownVariables(const AnalyserInternalVariablePtrs &variables) +{ + return std::any_of(variables.begin(), variables.end(), [](const auto &v) { + return isKnownVariable(v); + }); +} + +bool AnalyserInternalEquation::hasKnownVariables() +{ + return hasKnownVariables(mVariables) || hasKnownVariables(mOdeVariables); +} + +bool AnalyserInternalEquation::isNonConstantVariable(const AnalyserInternalVariablePtr &variable) +{ + // Note: we don't check for AnalyserInternalVariable::Type::CONSTANT because + // a variable's type becomes constant at the very end, i.e. once we + // know for sure that it's neither a state variable nor a variable + // that is computed using an NLA system. + + return variable->mIsExternal + || ((variable->mType != AnalyserInternalVariable::Type::UNKNOWN) + && (variable->mType != AnalyserInternalVariable::Type::INITIALISED) + && (variable->mType != AnalyserInternalVariable::Type::COMPUTED_TRUE_CONSTANT) + && (variable->mType != AnalyserInternalVariable::Type::COMPUTED_VARIABLE_BASED_CONSTANT)); +} + +bool AnalyserInternalEquation::hasNonConstantVariables(const AnalyserInternalVariablePtrs &variables) +{ + return std::any_of(variables.begin(), variables.end(), [](const auto &v) { + return isNonConstantVariable(v); + }); +} + +bool AnalyserInternalEquation::hasNonConstantVariables() +{ + return hasNonConstantVariables(mVariables) || hasNonConstantVariables(mOdeVariables); +} + +bool AnalyserInternalEquation::variableOnLhsRhs(const AnalyserInternalVariablePtr &variable, + const AnalyserEquationAstPtr &astChild) +{ + switch (astChild->type()) { + case AnalyserEquationAst::Type::CI: + return astChild->variable()->name() == variable->mVariable->name(); + case AnalyserEquationAst::Type::DIFF: + return astChild->rightChild()->variable()->name() == variable->mVariable->name(); + default: + return false; + } +} + +bool AnalyserInternalEquation::variableOnRhs(const AnalyserInternalVariablePtr &variable) { - return std::find_if(variables.begin(), variables.end(), [](const AnalyserInternalVariablePtr &variable) { - return isKnownVariable(variable); - }) - != std::end(variables); + return variableOnLhsRhs(variable, mAst->rightChild()); } -bool AnalyserInternalEquation::hasNonConstantVariables(const std::vector &variables) +bool AnalyserInternalEquation::variableOnLhsOrRhs(const AnalyserInternalVariablePtr &variable) { - return std::find_if(variables.begin(), variables.end(), [](const AnalyserInternalVariablePtr &variable) { - return (variable->mType != AnalyserInternalVariable::Type::UNKNOWN) - && (variable->mType != AnalyserInternalVariable::Type::CONSTANT) - && (variable->mType != AnalyserInternalVariable::Type::COMPUTED_TRUE_CONSTANT) - && (variable->mType != AnalyserInternalVariable::Type::COMPUTED_VARIABLE_BASED_CONSTANT); - }) - != std::end(variables); + return variableOnLhsRhs(variable, mAst->leftChild()) + || variableOnRhs(variable); } -bool AnalyserInternalEquation::check(size_t &equationOrder, size_t &stateIndex, - size_t &variableIndex, - const AnalyserModelPtr &model) +bool AnalyserInternalEquation::check(const AnalyserModelPtr &model, + size_t &stateIndex, size_t &variableIndex, + bool checkNlaSystems) { - // Nothing to check if the equation has already been given an order (i.e. - // everything is fine). + // Nothing to check if the equation has a known type. - if (mOrder != MAX_SIZE_T) { + if (mType != Type::UNKNOWN) { return false; } // Determine, from the (new) known (ODE) variables, whether the equation is // used to compute a true constant or a variable-based constant. - mComputedTrueConstant = mComputedTrueConstant - && !hasKnownVariables(mVariables) - && !hasKnownVariables(mOdeVariables); - mComputedVariableBasedConstant = mComputedVariableBasedConstant - && !hasNonConstantVariables(mVariables) - && !hasNonConstantVariables(mOdeVariables); + mComputedTrueConstant = mComputedTrueConstant && !hasKnownVariables(); + mComputedVariableBasedConstant = mComputedVariableBasedConstant && !hasNonConstantVariables(); // Add, as a dependency, the variables used to compute the (new) known (ODE) // variables. @@ -274,67 +345,146 @@ bool AnalyserInternalEquation::check(size_t &equationOrder, size_t &stateIndex, mVariables.erase(std::remove_if(mVariables.begin(), mVariables.end(), isKnownVariable), mVariables.end()); mOdeVariables.erase(std::remove_if(mOdeVariables.begin(), mOdeVariables.end(), isKnownOdeVariable), mOdeVariables.end()); - // If there is no (ODE) variable left then it means that the equation is - // overconstrained). + // If there is no (ODE) variable left then it means that the variables in + // the equation are overconstrained unless one of them was initialised in + // which case it will now be considered as an algebraic variable and this + // equation as an NLA equation. auto unknownVariablesOrOdeVariablesLeft = mVariables.size() + mOdeVariables.size(); + AnalyserInternalVariablePtrs initialisedVariables; - if (unknownVariablesOrOdeVariablesLeft == 0) { + if (checkNlaSystems && (unknownVariablesOrOdeVariablesLeft == 0)) { for (const auto &variable : mAllVariables) { - variable->mType = AnalyserInternalVariable::Type::OVERCONSTRAINED; + switch (variable->mType) { + case AnalyserInternalVariable::Type::INITIALISED: + case AnalyserInternalVariable::Type::INITIALISED_ALGEBRAIC: + // The equation contains an initialised variable, so track it + // and consider it as an algebraic variable. + + initialisedVariables.push_back(variable); + + variable->mType = AnalyserInternalVariable::Type::INITIALISED_ALGEBRAIC; + + break; + default: + break; + } } - return false; - } + if (initialisedVariables.empty()) { + // The equation doesn't contain any initialised variables, which + // means that it is overconstrained. - // If there is one (ODE) variable left then update its variable (to be the - // corresponding one in the component in which the equation is), its type - // (if it is currently unknown), determine its index and determine the type - // of our equation and set its order, if the (ODE) variable is a state, - // computed constant or algebraic variable. + for (const auto &variable : mAllVariables) { + variable->mType = AnalyserInternalVariable::Type::OVERCONSTRAINED; + } - if (unknownVariablesOrOdeVariablesLeft == 1) { - auto variable = mVariables.empty() ? mOdeVariables.front() : mVariables.front(); + return false; + } + } + + // If there is one (ODE) variable left (on its own on the LHS/RHS of the + // equation or in case we check for NLA systems) or some initialised + // variables then update its variable (to be the corresponding one in the + // component in which the equation is), as well as set its type (if it is + // currently unknown) and index (if its type is one of the expected ones). + // Finally, set the type and order of the equation, should everything have + // gone as planned. + + auto unknownVariableLeft = (unknownVariablesOrOdeVariablesLeft == 1) ? + mVariables.empty() ? + mOdeVariables.front() : + mVariables.front() : + nullptr; + + if (((unknownVariableLeft != nullptr) + && (checkNlaSystems || variableOnLhsOrRhs(unknownVariableLeft))) + || !initialisedVariables.empty()) { + auto variables = mVariables.empty() ? + mOdeVariables.empty() ? + initialisedVariables : + mOdeVariables : + mVariables; + + for (const auto &variable : variables) { + auto i = MAX_SIZE_T; + VariablePtr localVariable; + + do { + localVariable = mComponent->variable(++i); + } while (!model->areEquivalentVariables(variable->mVariable, localVariable)); + + variable->setVariable(localVariable, false); + + if (variable->mType == AnalyserInternalVariable::Type::UNKNOWN) { + variable->mType = mComputedTrueConstant ? + AnalyserInternalVariable::Type::COMPUTED_TRUE_CONSTANT : + mComputedVariableBasedConstant ? + AnalyserInternalVariable::Type::COMPUTED_VARIABLE_BASED_CONSTANT : + AnalyserInternalVariable::Type::ALGEBRAIC; + } - for (size_t i = 0; i < mComponent->variableCount(); ++i) { - auto localVariable = mComponent->variable(i); + switch (variable->mType) { + case AnalyserInternalVariable::Type::STATE: + case AnalyserInternalVariable::Type::COMPUTED_TRUE_CONSTANT: + case AnalyserInternalVariable::Type::COMPUTED_VARIABLE_BASED_CONSTANT: + case AnalyserInternalVariable::Type::INITIALISED_ALGEBRAIC: + case AnalyserInternalVariable::Type::ALGEBRAIC: + variable->mIndex = (variable->mType == AnalyserInternalVariable::Type::STATE) ? + ++stateIndex : + ++variableIndex; - if (model->areEquivalentVariables(variable->mVariable, localVariable)) { - variable->setVariable(localVariable, false); + mUnknownVariables.push_back(variable); break; + default: + return false; } } - if (variable->mType == AnalyserInternalVariable::Type::UNKNOWN) { - variable->mType = mComputedTrueConstant ? - AnalyserInternalVariable::Type::COMPUTED_TRUE_CONSTANT : - mComputedVariableBasedConstant ? - AnalyserInternalVariable::Type::COMPUTED_VARIABLE_BASED_CONSTANT : - AnalyserInternalVariable::Type::ALGEBRAIC; - } + // Set the equation's order and type. + // Note: an equation may be used to compute one variable, but if it is + // not on its own on the LHS/RHS of the equation then it needs to + // be solved as an NLA equation. + + if ((unknownVariableLeft == nullptr) + || !variableOnLhsOrRhs(unknownVariableLeft)) { + mType = Type::NLA; + } else { + switch (unknownVariableLeft->mType) { + case AnalyserInternalVariable::Type::STATE: + mType = Type::ODE; - if ((variable->mType == AnalyserInternalVariable::Type::STATE) - || (variable->mType == AnalyserInternalVariable::Type::COMPUTED_TRUE_CONSTANT) - || (variable->mType == AnalyserInternalVariable::Type::COMPUTED_VARIABLE_BASED_CONSTANT) - || (variable->mType == AnalyserInternalVariable::Type::ALGEBRAIC)) { - variable->mIndex = (variable->mType == AnalyserInternalVariable::Type::STATE) ? - ++stateIndex : - ++variableIndex; + break; + case AnalyserInternalVariable::Type::COMPUTED_TRUE_CONSTANT: + mType = Type::TRUE_CONSTANT; - mOrder = ++equationOrder; - mType = (variable->mType == AnalyserInternalVariable::Type::STATE) ? - Type::RATE : - (variable->mType == AnalyserInternalVariable::Type::COMPUTED_TRUE_CONSTANT) ? - Type::TRUE_CONSTANT : - (variable->mType == AnalyserInternalVariable::Type::COMPUTED_VARIABLE_BASED_CONSTANT) ? - Type::VARIABLE_BASED_CONSTANT : - Type::ALGEBRAIC; + break; + case AnalyserInternalVariable::Type::COMPUTED_VARIABLE_BASED_CONSTANT: + mType = Type::VARIABLE_BASED_CONSTANT; - mVariable = variable; + break; + default: + mType = Type::ALGEBRAIC; - return true; + break; + } + } + + // An ODE equation may have a dependency on the state of that ODE (e.g., + // dx/dt = x+3). Similarly, an NLA equation will have a "dependency" on + // its unknown variables. Either way, we must remove our "depenencies" + // on our unknown variables or we will end up in a circular dependency. + + for (const auto &unknownVariable : mUnknownVariables) { + auto it = std::find(mDependencies.begin(), mDependencies.end(), unknownVariable->mVariable); + + if (it != mDependencies.end()) { + mDependencies.erase(it); + } } + + return true; } return false; @@ -356,33 +506,17 @@ class Analyser::AnalyserImpl: public Logger::LoggerImpl AnalyserModelPtr mModel = AnalyserModel::AnalyserModelImpl::create(); - std::vector mExternalVariables; + AnalyserExternalVariablePtrs mExternalVariables; - std::vector mInternalVariables; - std::vector mInternalEquations; + AnalyserInternalVariablePtrs mInternalVariables; + AnalyserInternalEquationPtrs mInternalEquations; - GeneratorPtr mGenerator = libcellml::Generator::create(); + GeneratorProfilePtr mGeneratorProfile = libcellml::GeneratorProfile::create(); std::map mStandardUnits; - std::map mCiCnUnits; + std::map mCiCnUnits; AnalyserImpl(); - ~AnalyserImpl(); - - static bool compareVariablesByComponentAndName(const AnalyserInternalVariablePtr &variable1, - const AnalyserInternalVariablePtr &variable2); - - static bool isStateVariable(const AnalyserInternalVariablePtr &variable); - static bool isConstantOrAlgebraicVariable(const AnalyserInternalVariablePtr &variable); - - static bool compareVariablesByTypeAndIndex(const AnalyserInternalVariablePtr &variable1, - const AnalyserInternalVariablePtr &variable2); - - static bool compareEquationsByVariable(const AnalyserInternalEquationPtr &equation1, - const AnalyserInternalEquationPtr &equation2); - - size_t mathmlChildCount(const XmlNodePtr &node) const; - XmlNodePtr mathmlChildNode(const XmlNodePtr &node, size_t index) const; AnalyserInternalVariablePtr internalVariable(const VariablePtr &variable); @@ -394,6 +528,7 @@ class Analyser::AnalyserImpl: public Logger::LoggerImpl const ComponentPtr &component, const AnalyserInternalEquationPtr &equation); void analyseComponent(const ComponentPtr &component); + void analyseComponentVariables(const ComponentPtr &component); void doEquivalentVariables(const VariablePtr &variable, VariablePtrs &equivalentVariables) const; @@ -462,140 +597,48 @@ class Analyser::AnalyserImpl: public Logger::LoggerImpl double scalingFactor); void scaleEquationAst(const AnalyserEquationAstPtr &ast); + static bool isExternalVariable(const AnalyserInternalVariablePtr &variable); + bool isStateRateBased(const AnalyserEquationPtr &equation, - std::vector &checkedEquations); + AnalyserEquationPtrs &checkedEquations); + + void addInvalidVariableIssue(const AnalyserInternalVariablePtr &variable, + Issue::ReferenceRule referenceRule); void analyseModel(const ModelPtr &model); - std::vector::const_iterator findExternalVariable(const ModelPtr &model, - const std::string &componentName, - const std::string &variableName) const; - std::vector::const_iterator findExternalVariable(const AnalyserExternalVariablePtr &externalVariable) const; + AnalyserExternalVariablePtrs::const_iterator findExternalVariable(const ModelPtr &model, + const std::string &componentName, + const std::string &variableName) const; + AnalyserExternalVariablePtrs::const_iterator findExternalVariable(const AnalyserExternalVariablePtr &externalVariable) const; }; Analyser::AnalyserImpl::AnalyserImpl() { // Customise our generator's profile. - auto profile = mGenerator->profile(); - - profile->setAbsoluteValueString("abs"); - profile->setNaturalLogarithmString("ln"); - profile->setCommonLogarithmString("log"); - profile->setRemString("rem"); - profile->setAsinString("arcsin"); - profile->setAcosString("arccos"); - profile->setAtanString("arctan"); - profile->setAsecString("arcsec"); - profile->setAcscString("arccsc"); - profile->setAcotString("arccot"); - profile->setAsinhString("arcsinh"); - profile->setAcoshString("arccosh"); - profile->setAtanhString("arctanh"); - profile->setAsechString("arcsech"); - profile->setAcschString("arccsch"); - profile->setAcothString("arccoth"); - profile->setTrueString("true"); - profile->setFalseString("false"); - profile->setEString("exponentiale"); - profile->setPiString("pi"); - profile->setInfString("infinity"); - profile->setNanString("notanumber"); - - // Retrieve our generator's profile. - - mGenerator->mPimpl->retrieveLockedModelAndProfile(); -} - -Analyser::AnalyserImpl::~AnalyserImpl() -{ - // Reset our generator's profile. - - mGenerator->mPimpl->resetLockedModelAndProfile(); -} - -bool Analyser::AnalyserImpl::compareVariablesByComponentAndName(const AnalyserInternalVariablePtr &variable1, - const AnalyserInternalVariablePtr &variable2) -{ - auto realComponent1 = owningComponent(variable1->mVariable); - auto realComponent2 = owningComponent(variable2->mVariable); - - if (realComponent1->name() == realComponent2->name()) { - return variable1->mVariable->name() < variable2->mVariable->name(); - } - - return realComponent1->name() < realComponent2->name(); -} - -bool Analyser::AnalyserImpl::isStateVariable(const AnalyserInternalVariablePtr &variable) -{ - return variable->mType == AnalyserInternalVariable::Type::STATE; -} - -bool Analyser::AnalyserImpl::isConstantOrAlgebraicVariable(const AnalyserInternalVariablePtr &variable) -{ - return (variable->mType == AnalyserInternalVariable::Type::CONSTANT) - || (variable->mType == AnalyserInternalVariable::Type::COMPUTED_TRUE_CONSTANT) - || (variable->mType == AnalyserInternalVariable::Type::COMPUTED_VARIABLE_BASED_CONSTANT) - || (variable->mType == AnalyserInternalVariable::Type::ALGEBRAIC); -} - -bool Analyser::AnalyserImpl::compareVariablesByTypeAndIndex(const AnalyserInternalVariablePtr &variable1, - const AnalyserInternalVariablePtr &variable2) -{ - if (isStateVariable(variable1) && isConstantOrAlgebraicVariable(variable2)) { - return true; - } - - if (isConstantOrAlgebraicVariable(variable1) && isStateVariable(variable2)) { - return false; - } - - return variable1->mIndex < variable2->mIndex; -} - -bool Analyser::AnalyserImpl::compareEquationsByVariable(const AnalyserInternalEquationPtr &equation1, - const AnalyserInternalEquationPtr &equation2) -{ - return compareVariablesByTypeAndIndex(equation1->mVariable, equation2->mVariable); -} - -size_t Analyser::AnalyserImpl::mathmlChildCount(const XmlNodePtr &node) const -{ - // Return the number of child elements, in the MathML namespace, for the - // given node. - - auto childNode = node->firstChild(); - size_t res = 0; - - while (childNode != nullptr) { - if (childNode->isMathmlElement()) { - ++res; - } - childNode = childNode->next(); - } - - return res; -} - -XmlNodePtr Analyser::AnalyserImpl::mathmlChildNode(const XmlNodePtr &node, - size_t index) const -{ - // Return the nth child element of the given node, skipping anything that is - // not in the MathML namespace. - - auto res = node->firstChild(); - auto childNodeIndex = res->isMathmlElement() ? 0 : MAX_SIZE_T; - - while ((res != nullptr) && (childNodeIndex != index)) { - res = res->next(); - - if (res && res->isMathmlElement()) { - ++childNodeIndex; - } - } - - return res; + mGeneratorProfile->setAbsoluteValueString("abs"); + mGeneratorProfile->setNaturalLogarithmString("ln"); + mGeneratorProfile->setCommonLogarithmString("log"); + mGeneratorProfile->setRemString("rem"); + mGeneratorProfile->setAsinString("arcsin"); + mGeneratorProfile->setAcosString("arccos"); + mGeneratorProfile->setAtanString("arctan"); + mGeneratorProfile->setAsecString("arcsec"); + mGeneratorProfile->setAcscString("arccsc"); + mGeneratorProfile->setAcotString("arccot"); + mGeneratorProfile->setAsinhString("arcsinh"); + mGeneratorProfile->setAcoshString("arccosh"); + mGeneratorProfile->setAtanhString("arctanh"); + mGeneratorProfile->setAsechString("arcsech"); + mGeneratorProfile->setAcschString("arccsch"); + mGeneratorProfile->setAcothString("arccoth"); + mGeneratorProfile->setTrueString("true"); + mGeneratorProfile->setFalseString("false"); + mGeneratorProfile->setEString("exponentiale"); + mGeneratorProfile->setPiString("pi"); + mGeneratorProfile->setInfString("infinity"); + mGeneratorProfile->setNanString("notanumber"); } AnalyserInternalVariablePtr Analyser::AnalyserImpl::internalVariable(const VariablePtr &variable) @@ -603,24 +646,16 @@ AnalyserInternalVariablePtr Analyser::AnalyserImpl::internalVariable(const Varia // Find and return, if there is one, the internal variable associated with // the given variable. - AnalyserInternalVariablePtr res = nullptr; - for (const auto &internalVariable : mInternalVariables) { if (mModel->areEquivalentVariables(variable, internalVariable->mVariable)) { - res = internalVariable; - - break; + return internalVariable; } } - if (res != nullptr) { - return res; - } - // No internal variable exists for the given variable, so create one, track // it and return it. - res = AnalyserInternalVariable::create(variable); + auto res = AnalyserInternalVariable::create(variable); mInternalVariables.push_back(res); @@ -641,9 +676,9 @@ VariablePtr Analyser::AnalyserImpl::voiFirstOccurrence(const VariablePtr &variab } } - VariablePtr res = nullptr; + VariablePtr res; - for (size_t i = 0; i < component->componentCount() && res == nullptr; ++i) { + for (size_t i = 0; (res == nullptr) && (i < component->componentCount()); ++i) { res = voiFirstOccurrence(variable, component->component(i)); } @@ -658,7 +693,7 @@ void Analyser::AnalyserImpl::analyseNode(const XmlNodePtr &node, { // Create the AST, if needed. - if (ast.get() == nullptr) { + if (ast == nullptr) { ast.reset(new AnalyserEquationAst {}); } @@ -714,22 +749,20 @@ void Analyser::AnalyserImpl::analyseNode(const XmlNodePtr &node, astRightChild = tempAst; } - if (astRightChild != nullptr) { - astRightChild->mPimpl->mParent = ast; - } + astRightChild->mPimpl->mParent = ast; ast->mPimpl->mOwnedRightChild = astRightChild; } - // Assignment, and relational and logical operators. + // Relational and logical operators. } else if (node->isMathmlElement("eq")) { // This element is used both to describe "a = b" and "a == b". We can - // distinguish between the two by checking its grand-parent. If it's a + // distinguish between the two by checking its grandparent. If it's a // "math" element then it means that it is used to describe "a = b" // otherwise it is used to describe "a == b". In the former case, there // is nothing more we need to do since `ast` is already of - // AnalyserEquationAst::Type::ASSIGNMENT type. + // AnalyserEquationAst::Type::EQUALITY type. if (!node->parent()->parent()->isMathmlElement("math")) { ast->mPimpl->populate(AnalyserEquationAst::Type::EQ, astParent); @@ -948,8 +981,7 @@ void Analyser::AnalyserImpl::analyseNode(const XmlNodePtr &node, if (node->parent()->firstChild()->isMathmlElement("diff")) { equation->addOdeVariable(internalVariable(variable)); - } else if (!(node->parent()->isMathmlElement("bvar") - && node->parent()->parent()->firstChild()->isMathmlElement("diff"))) { + } else if (!node->parent()->isMathmlElement("bvar")) { equation->addVariable(internalVariable(variable)); } @@ -1021,7 +1053,10 @@ void Analyser::AnalyserImpl::analyseNode(const XmlNodePtr &node, ast->mPimpl->populate(AnalyserEquationAst::Type::PI, astParent); } else if (node->isMathmlElement("infinity")) { ast->mPimpl->populate(AnalyserEquationAst::Type::INF, astParent); - } else if (node->isMathmlElement("notanumber")) { + } else { + // We have checked for everything, so if we reach this point it means + // that we have a NaN. + ast->mPimpl->populate(AnalyserEquationAst::Type::NAN, astParent); } } @@ -1044,34 +1079,76 @@ void Analyser::AnalyserImpl::analyseComponent(const ComponentPtr &component) mInternalEquations.push_back(internalEquation); // Actually analyse the node. + // Note: we must not test internalEquation->mAst->parent() + // since if it is equal to nullptr then a parent will + // be created by analyseNode(). analyseNode(node, internalEquation->mAst, internalEquation->mAst->parent(), component, internalEquation); + + // Make sure that our internal equation is an equality + // statement. + + if (internalEquation->mAst->mPimpl->mType != AnalyserEquationAst::Type::EQUALITY) { + auto issue = Issue::IssueImpl::create(); + + issue->mPimpl->setDescription("Equation " + expression(internalEquation->mAst) + + " is not an equality statement (i.e. LHS = RHS)."); + issue->mPimpl->setReferenceRule(Issue::ReferenceRule::ANALYSER_EQUATION_NOT_EQUALITY_STATEMENT); + issue->mPimpl->mItem->mPimpl->setComponent(component); + + addIssue(issue); + } } } } } - // Go through the given component's variables and make sure that everything - // makes sense. + // Go through the given component's variables and internally keep track of + // the ones that have an initial value. for (size_t i = 0; i < component->variableCount(); ++i) { - // Retrieve the variable's corresponding internal variable. + // If `variable` has an initial value and the variable held by + // `internalVariable` doesn't, then replace the variable held by + // `internalVariable`. auto variable = component->variable(i); auto internalVariable = Analyser::AnalyserImpl::internalVariable(variable); - // If `variable` has an initial value and the variable held by - // `internalVariable` doesn't, then replace the variable held by - // `internalVariable`. If `variable` and the variable held by - // `internalVariable` are different and both of them have an initial - // value then generate an error. - if (!variable->initialValue().empty() && internalVariable->mVariable->initialValue().empty()) { internalVariable->setVariable(variable); - } else if ((variable != internalVariable->mVariable) - && !variable->initialValue().empty() - && !internalVariable->mVariable->initialValue().empty()) { + } + } + + // Do the same for the components encapsulated by the given component. + + for (size_t i = 0; i < component->componentCount(); ++i) { + analyseComponent(component->component(i)); + } +} + +void Analyser::AnalyserImpl::analyseComponentVariables(const ComponentPtr &component) +{ + // Go through the given component's variables and make sure that everything + // makes sense. + + for (size_t i = 0; i < component->variableCount(); ++i) { + // If `variable` and the variable held by `internalVariable` are + // different then make sure that they don't both have an initial value. + // Alternatively, if the variable held by `internalVariable` has an + // initial value which is the name of another variable then make sure + // that it is of constant type. + // Note: we always have an initialising variable in the second case. + // Indeed, if we were not to have one, it would mean that the + // variable is initialised using a reference to a variable that is + // not defined anywhere, something that is not allowed in CellML + // and will therefore be reported when we validate the model. + + auto variable = component->variable(i); + auto internalVariable = Analyser::AnalyserImpl::internalVariable(variable); + + if ((variable != internalVariable->mVariable) + && !variable->initialValue().empty()) { auto issue = Issue::IssueImpl::create(); auto trackedVariableComponent = owningComponent(internalVariable->mVariable); @@ -1084,23 +1161,13 @@ void Analyser::AnalyserImpl::analyseComponent(const ComponentPtr &component) issue->mPimpl->mItem->mPimpl->setVariable(variable); addIssue(issue); - } - - if (!internalVariable->mVariable->initialValue().empty() - && !isCellMLReal(internalVariable->mVariable->initialValue())) { - // The initial value is not a double, so it has to be an existing - // variable of constant type. - // Note: we always have an initialising variable. Indeed, if we were - // not to have one, it would mean that the variable is - // initialised using a reference to a variable that is not - // defined anywhere, something that is not allowed in CellML - // and will therefore be reported when we validate the model. - + } else if (!internalVariable->mVariable->initialValue().empty() + && !isCellMLReal(internalVariable->mVariable->initialValue())) { auto initialisingComponent = owningComponent(internalVariable->mVariable); auto initialisingVariable = initialisingComponent->variable(internalVariable->mVariable->initialValue()); auto initialisingInternalVariable = Analyser::AnalyserImpl::internalVariable(initialisingVariable); - if (initialisingInternalVariable->mType != AnalyserInternalVariable::Type::CONSTANT) { + if (initialisingInternalVariable->mType != AnalyserInternalVariable::Type::INITIALISED) { auto issue = Issue::IssueImpl::create(); issue->mPimpl->setDescription("Variable '" + variable->name() @@ -1118,7 +1185,7 @@ void Analyser::AnalyserImpl::analyseComponent(const ComponentPtr &component) // Do the same for the components encapsulated by the given component. for (size_t i = 0; i < component->componentCount(); ++i) { - analyseComponent(component->component(i)); + analyseComponentVariables(component->component(i)); } } @@ -1157,15 +1224,14 @@ void Analyser::AnalyserImpl::analyseEquationAst(const AnalyserEquationAstPtr &as // we don't have more than one of it and that it's not initialised. auto astParent = ast->parent(); - auto astGrandParent = (astParent != nullptr) ? astParent->parent() : nullptr; - auto astGreatGrandParent = (astGrandParent != nullptr) ? astGrandParent->parent() : nullptr; + auto astGrandparent = (astParent != nullptr) ? astParent->parent() : nullptr; + auto astGreatGrandparent = (astGrandparent != nullptr) ? astGrandparent->parent() : nullptr; if ((ast->mPimpl->mType == AnalyserEquationAst::Type::CI) - && (astParent != nullptr) && (astParent->mPimpl->mType == AnalyserEquationAst::Type::BVAR) - && (astGrandParent != nullptr) && (astGrandParent->mPimpl->mType == AnalyserEquationAst::Type::DIFF)) { - auto variable = ast->variable(); + && (astParent->mPimpl->mType == AnalyserEquationAst::Type::BVAR)) { + auto astVariable = ast->variable(); - internalVariable(variable)->makeVoi(); + internalVariable(astVariable)->makeVoi(); // Note: we must make the variable a variable of integration in all // cases (i.e. even if there is, for example, already another // variable of integration) otherwise unnecessary issue messages @@ -1179,17 +1245,19 @@ void Analyser::AnalyserImpl::analyseEquationAst(const AnalyserEquationAstPtr &as // to be defined), so go through our components and look for the // first occurrence of our variable of integration. - auto model = owningModel(variable); + auto model = owningModel(astVariable); + auto i = MAX_SIZE_T; + VariablePtr voi; - for (size_t i = 0; i < model->componentCount(); ++i) { - auto voi = voiFirstOccurrence(variable, model->component(i)); + do { + voi = voiFirstOccurrence(astVariable, model->component(++i)); if (voi != nullptr) { // We have found the first occurrence of our variable of - // integration, but now we must ensure neither it (nor any - // of its equivalent variables) is initialised. + // integration, but now we must ensure that it (or any of + // its equivalent variables) is not initialised. - bool isVoiInitialised = false; + auto isVoiInitialised = false; for (const auto &voiEquivalentVariable : equivalentVariables(voi)) { if (!voiEquivalentVariable->initialValue().empty()) { @@ -1211,39 +1279,41 @@ void Analyser::AnalyserImpl::analyseEquationAst(const AnalyserEquationAstPtr &as mModel->mPimpl->mVoi = AnalyserVariable::AnalyserVariableImpl::create(); mModel->mPimpl->mVoi->mPimpl->populate(AnalyserVariable::Type::VARIABLE_OF_INTEGRATION, - 0, nullptr, voi, nullptr); + 0, nullptr, voi, {}); } - - break; } - } - } else if (!mModel->areEquivalentVariables(variable, mModel->mPimpl->mVoi->variable())) { - auto issue = Issue::IssueImpl::create(); + } while (voi == nullptr); + } else { + auto voiVariable = mModel->mPimpl->mVoi->variable(); - issue->mPimpl->setDescription("Variable '" + mModel->mPimpl->mVoi->variable()->name() - + "' in component '" + owningComponent(mModel->mPimpl->mVoi->variable())->name() - + "' and variable '" + variable->name() - + "' in component '" + owningComponent(variable)->name() - + "' cannot both be the variable of integration."); - issue->mPimpl->setReferenceRule(Issue::ReferenceRule::ANALYSER_VOI_SEVERAL); - issue->mPimpl->mItem->mPimpl->setVariable(variable); + if (!mModel->areEquivalentVariables(astVariable, voiVariable)) { + auto issue = Issue::IssueImpl::create(); - addIssue(issue); + issue->mPimpl->setDescription("Variable '" + voiVariable->name() + + "' in component '" + owningComponent(voiVariable)->name() + + "' and variable '" + astVariable->name() + + "' in component '" + owningComponent(astVariable)->name() + + "' cannot both be the variable of integration."); + issue->mPimpl->setReferenceRule(Issue::ReferenceRule::ANALYSER_VOI_SEVERAL); + issue->mPimpl->mItem->mPimpl->setVariable(astVariable); + + addIssue(issue); + } } } // Make sure that we only use first-order ODEs. if ((ast->mPimpl->mType == AnalyserEquationAst::Type::CN) - && (astParent != nullptr) && (astParent->mPimpl->mType == AnalyserEquationAst::Type::DEGREE) - && (astGrandParent != nullptr) && (astGrandParent->mPimpl->mType == AnalyserEquationAst::Type::BVAR) - && (astGreatGrandParent != nullptr) && (astGreatGrandParent->mPimpl->mType == AnalyserEquationAst::Type::DIFF)) { - bool validValue; - double value = convertToDouble(ast->mPimpl->mValue, &validValue); + && (astParent->mPimpl->mType == AnalyserEquationAst::Type::DEGREE) + && (astGrandparent->mPimpl->mType == AnalyserEquationAst::Type::BVAR)) { + double value; - if (!validValue || !areEqual(value, 1.0)) { + convertToDouble(ast->mPimpl->mValue, value); + + if (!areEqual(value, 1.0)) { + auto variable = astGreatGrandparent->mPimpl->mOwnedRightChild->variable(); auto issue = Issue::IssueImpl::create(); - auto variable = astGreatGrandParent->mPimpl->mOwnedRightChild->variable(); issue->mPimpl->setDescription("The differential equation for variable '" + variable->name() + "' in component '" + owningComponent(variable)->name() @@ -1258,7 +1328,7 @@ void Analyser::AnalyserImpl::analyseEquationAst(const AnalyserEquationAstPtr &as // Make a variable a state if it is used in an ODE. if ((ast->mPimpl->mType == AnalyserEquationAst::Type::CI) - && (astParent != nullptr) && (astParent->mPimpl->mType == AnalyserEquationAst::Type::DIFF)) { + && (astParent->mPimpl->mType == AnalyserEquationAst::Type::DIFF)) { internalVariable(ast->variable())->makeState(); } @@ -1340,8 +1410,8 @@ UnitsMap Analyser::AnalyserImpl::multiplyDivideUnitsMaps(const UnitsMap &firstUn // Multiply/divide the given units maps together, following a multiplication // (multiply = true) or a division (multiply = false). - UnitsMap res = firstUnitsMap; - double sign = multiply ? 1.0 : -1.0; + auto res = firstUnitsMap; + auto sign = multiply ? 1.0 : -1.0; for (const auto &units : secondUnitsMap) { auto it = res.find(units.first); @@ -1388,8 +1458,8 @@ UnitsMaps Analyser::AnalyserImpl::multiplyDivideUnitsMaps(const UnitsMaps &units // Multiply/divide the given units maps by the given factor, following a // multiplication (multiply = true) or a division (multiply = false). - UnitsMaps res = unitsMaps; - double realFactor = multiply ? factor : 1.0 / factor; + auto res = unitsMaps; + auto realFactor = multiply ? factor : 1.0 / factor; for (auto &unitsMap : res) { for (auto &unitsItem : unitsMap) { @@ -1456,7 +1526,7 @@ UnitsMultipliers Analyser::AnalyserImpl::powerRootUnitsMultipliers(const UnitsMu // power (power = true) or a root (power = false) operation. UnitsMultipliers res; - double realFactor = power ? factor : 1.0 / factor; + auto realFactor = power ? factor : 1.0 / factor; for (const auto &unitsMultiplier : unitsMultipliers) { res.push_back(realFactor * unitsMultiplier); @@ -1540,7 +1610,7 @@ void Analyser::AnalyserImpl::updateUnitsMultiplier(const ModelPtr &model, if (isStandardUnitName(unitsName)) { newUnitsMultiplier += unitsMultiplier + standardMultiplierList.at(unitsName); } else { - UnitsPtr units = model->units(unitsName); + auto units = model->units(unitsName); if (units->isBaseUnit()) { newUnitsMultiplier += unitsMultiplier; @@ -1572,10 +1642,10 @@ std::string Analyser::AnalyserImpl::componentName(const AnalyserEquationAstPtr & // through the AST, if needed, and returning the component of the first // variable we find on the LHS/RHS. - auto variable = ast->variable(); + auto astVariable = ast->variable(); - if (variable != nullptr) { - return std::dynamic_pointer_cast(variable->parent())->name(); + if (astVariable != nullptr) { + return std::dynamic_pointer_cast(astVariable->parent())->name(); } auto res = (ast->mPimpl->mOwnedLeftChild != nullptr) ? @@ -1600,33 +1670,26 @@ double Analyser::AnalyserImpl::powerValue(const AnalyserEquationAstPtr &ast) } if (ast->value().empty()) { - if ((ast->mPimpl->mOwnedLeftChild == nullptr) && (ast->mPimpl->mOwnedRightChild == nullptr)) { + if (ast->mPimpl->mOwnedLeftChild == nullptr) { return 0.0; } - if (ast->mPimpl->mType == AnalyserEquationAst::Type::TIMES) { + switch (ast->mPimpl->mType) { + case AnalyserEquationAst::Type::TIMES: return powerValue(ast->mPimpl->mOwnedLeftChild) * powerValue(ast->mPimpl->mOwnedRightChild); - } - - if (ast->mPimpl->mType == AnalyserEquationAst::Type::DIVIDE) { + case AnalyserEquationAst::Type::DIVIDE: return areNearlyEqual(powerValue(ast->mPimpl->mOwnedRightChild), 0.0) ? 0.0 : powerValue(ast->mPimpl->mOwnedLeftChild) / powerValue(ast->mPimpl->mOwnedRightChild); - } - - if (ast->mPimpl->mType == AnalyserEquationAst::Type::PLUS) { + case AnalyserEquationAst::Type::PLUS: return powerValue(ast->mPimpl->mOwnedLeftChild) + powerValue(ast->mPimpl->mOwnedRightChild); - } - - if (ast->mPimpl->mType == AnalyserEquationAst::Type::MINUS) { + case AnalyserEquationAst::Type::MINUS: return powerValue(ast->mPimpl->mOwnedLeftChild) - powerValue(ast->mPimpl->mOwnedRightChild); - } - - if (ast->mPimpl->mType == AnalyserEquationAst::Type::DEGREE) { + case AnalyserEquationAst::Type::DEGREE: return powerValue(ast->mPimpl->mOwnedLeftChild); + default: + return 0.0; } - - return 0.0; } return std::stod(ast->value()); @@ -1638,25 +1701,21 @@ std::string Analyser::AnalyserImpl::expression(const AnalyserEquationAstPtr &ast // Return the generated code for the given AST, specifying the equation and // component in which it is, if needed and requested. - std::string res = "'" + mGenerator->mPimpl->generateCode(ast) + "'"; + std::string res = "'" + Generator::equationCode(ast, mGeneratorProfile) + "'"; if (includeHierarchy) { - AnalyserEquationAstPtr equationAst = ast; - AnalyserEquationAstPtr equationAstParent = ast->parent(); - AnalyserEquationAstPtr equationAstGrandParent = (equationAstParent != nullptr) ? - equationAstParent->parent() : - nullptr; + auto equationAst = ast; + auto equationAstParent = ast->parent(); + auto equationAstGrandparent = (equationAstParent != nullptr) ? equationAstParent->parent() : nullptr; while (equationAstParent != nullptr) { equationAst = equationAstParent; - equationAstParent = equationAstGrandParent; - equationAstGrandParent = (equationAstParent != nullptr) ? - equationAstParent->parent() : - nullptr; + equationAstParent = equationAstGrandparent; + equationAstGrandparent = (equationAstParent != nullptr) ? equationAstParent->parent() : nullptr; res += std::string(" in") - + (((equationAstParent == nullptr) && equationAstGrandParent == nullptr) ? " equation" : "") - + " '" + mGenerator->mPimpl->generateCode(equationAst) + "'"; + + ((equationAstParent == nullptr) ? " equation" : "") + + " '" + Generator::equationCode(equationAst, mGeneratorProfile) + "'"; } res += " in component '" + componentName(equationAst) + "'"; @@ -1683,11 +1742,7 @@ std::string Analyser::AnalyserImpl::expressionUnits(const UnitsMaps &unitsMaps, convertToString(unitsMultipliers[i], false); if (exponent != "0") { - unit += "10"; - - if (exponent != "1") { - unit += "^" + exponent; - } + unit += "10^" + exponent; } } @@ -1828,9 +1883,10 @@ void Analyser::AnalyserImpl::analyseEquationUnits(const AnalyserEquationAstPtr & // Check whether we are dealing with a CI/CN element and, if so, retrieve // both its units maps and multipliers. - if ((ast->mPimpl->mType == AnalyserEquationAst::Type::CI) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::CN)) { - auto units = mCiCnUnits[ast].lock(); + switch (ast->mPimpl->mType) { + case AnalyserEquationAst::Type::CI: + case AnalyserEquationAst::Type::CN: { + auto units = mCiCnUnits[ast]; auto model = owningModel(units); defaultUnitsMapsAndMultipliers(unitsMaps, userUnitsMaps, unitsMultipliers); @@ -1849,6 +1905,9 @@ void Analyser::AnalyserImpl::analyseEquationUnits(const AnalyserEquationAstPtr & return; } + default: + break; + } // Check the left and right children. @@ -1860,33 +1919,39 @@ void Analyser::AnalyserImpl::analyseEquationUnits(const AnalyserEquationAstPtr & analyseEquationUnits(ast->mPimpl->mOwnedLeftChild, unitsMaps, userUnitsMaps, unitsMultipliers, issueDescriptions); analyseEquationUnits(ast->mPimpl->mOwnedRightChild, rightUnitsMaps, rightUserUnitsMaps, rightUnitsMultipliers, issueDescriptions); - if ((ast->mPimpl->mType == AnalyserEquationAst::Type::ASSIGNMENT) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::EQ) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::NEQ) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::LT) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::LEQ) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::GT) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::GEQ) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::PLUS) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::MINUS) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::MIN) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::MAX) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::REM)) { - bool sameUnitsMaps = rightUnitsMaps.empty() + switch (ast->mPimpl->mType) { + case AnalyserEquationAst::Type::EQUALITY: + case AnalyserEquationAst::Type::EQ: + case AnalyserEquationAst::Type::NEQ: + case AnalyserEquationAst::Type::LT: + case AnalyserEquationAst::Type::LEQ: + case AnalyserEquationAst::Type::GT: + case AnalyserEquationAst::Type::GEQ: + case AnalyserEquationAst::Type::PLUS: + case AnalyserEquationAst::Type::MINUS: + case AnalyserEquationAst::Type::MIN: + case AnalyserEquationAst::Type::MAX: + case AnalyserEquationAst::Type::REM: { + auto sameUnitsMaps = rightUnitsMaps.empty() || areSameUnitsMaps(unitsMaps, rightUnitsMaps); - bool sameUnitsMultipliers = rightUnitsMaps.empty() + auto sameUnitsMultipliers = rightUnitsMaps.empty() || areSameUnitsMultipliers(unitsMultipliers, rightUnitsMultipliers); if (sameUnitsMaps && sameUnitsMultipliers) { // Relational operators result in a dimensionless unit. - if ((ast->mPimpl->mType == AnalyserEquationAst::Type::EQ) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::NEQ) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::LT) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::LEQ) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::GT) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::GEQ)) { + switch (ast->mPimpl->mType) { + case AnalyserEquationAst::Type::EQ: + case AnalyserEquationAst::Type::NEQ: + case AnalyserEquationAst::Type::LT: + case AnalyserEquationAst::Type::LEQ: + case AnalyserEquationAst::Type::GT: + case AnalyserEquationAst::Type::GEQ: defaultUnitsMapsAndMultipliers(unitsMaps, userUnitsMaps, unitsMultipliers); + + break; + default: + break; } } else if (issueDescriptions.size() == oldNbOfIssueDescriptions) { // Only report inner issues. @@ -1898,7 +1963,8 @@ void Analyser::AnalyserImpl::analyseEquationUnits(const AnalyserEquationAstPtr & issueDescriptions.push_back(issueDescription); } - } else if (ast->mPimpl->mType == AnalyserEquationAst::Type::PIECEWISE) { + } break; + case AnalyserEquationAst::Type::PIECEWISE: unitsMaps.insert(std::end(unitsMaps), std::begin(rightUnitsMaps), std::end(rightUnitsMaps)); @@ -1908,98 +1974,88 @@ void Analyser::AnalyserImpl::analyseEquationUnits(const AnalyserEquationAstPtr & unitsMultipliers.insert(std::end(unitsMultipliers), std::begin(rightUnitsMultipliers), std::end(rightUnitsMultipliers)); - } else if (ast->mPimpl->mType == AnalyserEquationAst::Type::PIECE) { + + break; + case AnalyserEquationAst::Type::PIECE: if (!Analyser::AnalyserImpl::isDimensionlessUnitsMaps(rightUnitsMaps)) { issueDescriptions.push_back("The unit of " + expression(ast->mPimpl->mOwnedRightChild) + " is not dimensionless. " + expressionUnits(ast->mPimpl->mOwnedRightChild, rightUnitsMaps, rightUserUnitsMaps, rightUnitsMultipliers) + "."); } - } else if ((ast->mPimpl->mType == AnalyserEquationAst::Type::AND) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::OR) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::XOR) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::NOT) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::EXP) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::LN) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::LOG)) { - bool isDimensionlessUnitsMaps = Analyser::AnalyserImpl::isDimensionlessUnitsMaps(unitsMaps); - bool isDimensionlessRightUnitsMaps = Analyser::AnalyserImpl::isDimensionlessUnitsMaps(rightUnitsMaps); - - if (!isDimensionlessUnitsMaps || !isDimensionlessRightUnitsMaps) { - std::string issueDescription = "The unit"; - if (!isDimensionlessUnitsMaps && !isDimensionlessRightUnitsMaps) { - issueDescription += "s"; - } + break; + case AnalyserEquationAst::Type::AND: + case AnalyserEquationAst::Type::OR: + case AnalyserEquationAst::Type::XOR: + case AnalyserEquationAst::Type::NOT: + case AnalyserEquationAst::Type::EXP: + case AnalyserEquationAst::Type::LN: + case AnalyserEquationAst::Type::LOG: { + auto isDimensionlessUnitsMaps = Analyser::AnalyserImpl::isDimensionlessUnitsMaps(unitsMaps); - issueDescription += " of "; + if (!isDimensionlessUnitsMaps) { + auto isDimensionlessRightUnitsMaps = Analyser::AnalyserImpl::isDimensionlessUnitsMaps(rightUnitsMaps); + std::string issueDescription = "The unit"; - if (!isDimensionlessUnitsMaps) { - issueDescription += expression(ast->mPimpl->mOwnedLeftChild, false); + if (!isDimensionlessRightUnitsMaps) { + issueDescription += "s"; } - if (!isDimensionlessUnitsMaps && !isDimensionlessRightUnitsMaps) { - issueDescription += " and "; - } + issueDescription += " of " + expression(ast->mPimpl->mOwnedLeftChild, false); if (!isDimensionlessRightUnitsMaps) { - issueDescription += expression(ast->mPimpl->mOwnedRightChild, false); + issueDescription += " and " + expression(ast->mPimpl->mOwnedRightChild, false); } issueDescription += " in " + expression(ast); - if (!isDimensionlessUnitsMaps && !isDimensionlessRightUnitsMaps) { + if (!isDimensionlessRightUnitsMaps) { issueDescription += " are "; } else { issueDescription += " is "; } - issueDescription += "not dimensionless. "; - - if (!isDimensionlessUnitsMaps) { - issueDescription += expressionUnits(ast->mPimpl->mOwnedLeftChild, unitsMaps, userUnitsMaps, unitsMultipliers); - } - - if (!isDimensionlessUnitsMaps && !isDimensionlessRightUnitsMaps) { - issueDescription += " while "; - } + issueDescription += "not dimensionless. " + expressionUnits(ast->mPimpl->mOwnedLeftChild, unitsMaps, userUnitsMaps, unitsMultipliers); if (!isDimensionlessRightUnitsMaps) { - issueDescription += expressionUnits(ast->mPimpl->mOwnedRightChild, rightUnitsMaps, rightUserUnitsMaps, rightUnitsMultipliers); + issueDescription += " while " + expressionUnits(ast->mPimpl->mOwnedRightChild, rightUnitsMaps, rightUserUnitsMaps, rightUnitsMultipliers); } issueDescription += "."; issueDescriptions.push_back(issueDescription); } - } else if ((ast->mPimpl->mType == AnalyserEquationAst::Type::TIMES) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::DIVIDE)) { - unitsMaps = multiplyDivideUnitsMaps(unitsMaps, rightUnitsMaps, - ast->mPimpl->mType == AnalyserEquationAst::Type::TIMES); - userUnitsMaps = multiplyDivideUnitsMaps(userUnitsMaps, rightUserUnitsMaps, - ast->mPimpl->mType == AnalyserEquationAst::Type::TIMES); - unitsMultipliers = multiplyDivideUnitsMultipliers(unitsMultipliers, rightUnitsMultipliers, - ast->mPimpl->mType == AnalyserEquationAst::Type::TIMES); - } else if ((ast->mPimpl->mType == AnalyserEquationAst::Type::POWER) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::ROOT)) { - bool isDimensionlessExponent = true; - - if ((ast->mPimpl->mType == AnalyserEquationAst::Type::POWER) + } break; + case AnalyserEquationAst::Type::TIMES: + case AnalyserEquationAst::Type::DIVIDE: { + auto isTimes = ast->mPimpl->mType == AnalyserEquationAst::Type::TIMES; + + unitsMaps = multiplyDivideUnitsMaps(unitsMaps, rightUnitsMaps, isTimes); + userUnitsMaps = multiplyDivideUnitsMaps(userUnitsMaps, rightUserUnitsMaps, isTimes); + unitsMultipliers = multiplyDivideUnitsMultipliers(unitsMultipliers, rightUnitsMultipliers, isTimes); + } break; + case AnalyserEquationAst::Type::POWER: + case AnalyserEquationAst::Type::ROOT: { + auto isPower = ast->mPimpl->mType == AnalyserEquationAst::Type::POWER; + auto isDimensionlessExponent = true; + + if (isPower || (ast->mPimpl->mOwnedLeftChild->type() == AnalyserEquationAst::Type::DEGREE)) { - isDimensionlessExponent = Analyser::AnalyserImpl::isDimensionlessUnitsMaps((ast->mPimpl->mType == AnalyserEquationAst::Type::POWER) ? + isDimensionlessExponent = Analyser::AnalyserImpl::isDimensionlessUnitsMaps(isPower ? rightUnitsMaps : unitsMaps); if (!isDimensionlessExponent) { - auto baseAst = (ast->mPimpl->mType == AnalyserEquationAst::Type::POWER) ? + auto baseAst = isPower ? ast->mPimpl->mOwnedRightChild : ast->mPimpl->mOwnedLeftChild; - auto exponentUnitsMaps = (ast->mPimpl->mType == AnalyserEquationAst::Type::POWER) ? + auto exponentUnitsMaps = isPower ? rightUnitsMaps : unitsMaps; - auto exponentUserUnitsMaps = (ast->mPimpl->mType == AnalyserEquationAst::Type::POWER) ? + auto exponentUserUnitsMaps = isPower ? rightUserUnitsMaps : userUnitsMaps; - auto exponentUnitsMultipliers = (ast->mPimpl->mType == AnalyserEquationAst::Type::POWER) ? + auto exponentUnitsMultipliers = isPower ? rightUnitsMultipliers : unitsMultipliers; @@ -2012,13 +2068,11 @@ void Analyser::AnalyserImpl::analyseEquationUnits(const AnalyserEquationAstPtr & // Retrieve the exponent and apply it to our units maps and multipliers. if (isDimensionlessExponent) { - double powerRootValue = 0.0; + auto powerRootValue = 0.0; - if (ast->mPimpl->mType == AnalyserEquationAst::Type::POWER) { + if (isPower) { powerRootValue = Analyser::AnalyserImpl::powerValue(ast->mPimpl->mOwnedRightChild); - } else { - // Root case. - + } else { // AnalyserEquationAst::Type::ROOT. if (ast->mPimpl->mOwnedLeftChild->type() == AnalyserEquationAst::Type::DEGREE) { unitsMaps = rightUnitsMaps; userUnitsMaps = rightUserUnitsMaps; @@ -2033,47 +2087,49 @@ void Analyser::AnalyserImpl::analyseEquationUnits(const AnalyserEquationAstPtr & } } - unitsMaps = multiplyDivideUnitsMaps(unitsMaps, powerRootValue, - ast->mPimpl->mType == AnalyserEquationAst::Type::POWER); - userUnitsMaps = multiplyDivideUnitsMaps(userUnitsMaps, powerRootValue, - ast->mPimpl->mType == AnalyserEquationAst::Type::POWER); - unitsMultipliers = powerRootUnitsMultipliers(unitsMultipliers, powerRootValue, - ast->mPimpl->mType == AnalyserEquationAst::Type::POWER); - } - } else if ((ast->mPimpl->mType == AnalyserEquationAst::Type::SIN) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::COS) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::TAN) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::SEC) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::CSC) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::COT) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::SINH) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::COSH) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::TANH) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::SECH) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::CSCH) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::COTH) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::ASIN) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::ACOS) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::ATAN) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::ASEC) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::ACSC) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::ACOT) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::ASINH) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::ACOSH) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::ATANH) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::ASECH) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::ACSCH) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::ACOTH)) { + unitsMaps = multiplyDivideUnitsMaps(unitsMaps, powerRootValue, isPower); + userUnitsMaps = multiplyDivideUnitsMaps(userUnitsMaps, powerRootValue, isPower); + unitsMultipliers = powerRootUnitsMultipliers(unitsMultipliers, powerRootValue, isPower); + } + } break; + case AnalyserEquationAst::Type::SIN: + case AnalyserEquationAst::Type::COS: + case AnalyserEquationAst::Type::TAN: + case AnalyserEquationAst::Type::SEC: + case AnalyserEquationAst::Type::CSC: + case AnalyserEquationAst::Type::COT: + case AnalyserEquationAst::Type::SINH: + case AnalyserEquationAst::Type::COSH: + case AnalyserEquationAst::Type::TANH: + case AnalyserEquationAst::Type::SECH: + case AnalyserEquationAst::Type::CSCH: + case AnalyserEquationAst::Type::COTH: + case AnalyserEquationAst::Type::ASIN: + case AnalyserEquationAst::Type::ACOS: + case AnalyserEquationAst::Type::ATAN: + case AnalyserEquationAst::Type::ASEC: + case AnalyserEquationAst::Type::ACSC: + case AnalyserEquationAst::Type::ACOT: + case AnalyserEquationAst::Type::ASINH: + case AnalyserEquationAst::Type::ACOSH: + case AnalyserEquationAst::Type::ATANH: + case AnalyserEquationAst::Type::ASECH: + case AnalyserEquationAst::Type::ACSCH: + case AnalyserEquationAst::Type::ACOTH: if (!Analyser::AnalyserImpl::isDimensionlessUnitsMaps(unitsMaps)) { issueDescriptions.push_back("The unit of " + expression(ast->mPimpl->mOwnedLeftChild) + " is not dimensionless. " + expressionUnits(ast->mPimpl->mOwnedLeftChild, unitsMaps, userUnitsMaps, unitsMultipliers) + "."); } - } else if (ast->mPimpl->mType == AnalyserEquationAst::Type::DIFF) { + + break; + case AnalyserEquationAst::Type::DIFF: unitsMaps = multiplyDivideUnitsMaps(unitsMaps, rightUnitsMaps); userUnitsMaps = multiplyDivideUnitsMaps(userUnitsMaps, rightUserUnitsMaps); unitsMultipliers = multiplyDivideUnitsMultipliers(unitsMultipliers, rightUnitsMultipliers); - } else if (ast->mPimpl->mType == AnalyserEquationAst::Type::BVAR) { + + break; + case AnalyserEquationAst::Type::BVAR: for (auto &unitsMap : unitsMaps) { for (auto &unitsItem : unitsMap) { unitsItem.second *= -1.0; @@ -2087,13 +2143,19 @@ void Analyser::AnalyserImpl::analyseEquationUnits(const AnalyserEquationAstPtr & } unitsMultipliers = multiplyDivideUnitsMultipliers(0.0, unitsMultipliers, false); - } else if ((ast->mPimpl->mType == AnalyserEquationAst::Type::TRUE) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::FALSE) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::E) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::PI) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::INF) - || (ast->mPimpl->mType == AnalyserEquationAst::Type::NAN)) { + + break; + case AnalyserEquationAst::Type::TRUE: + case AnalyserEquationAst::Type::FALSE: + case AnalyserEquationAst::Type::E: + case AnalyserEquationAst::Type::PI: + case AnalyserEquationAst::Type::INF: + case AnalyserEquationAst::Type::NAN: defaultUnitsMapsAndMultipliers(unitsMaps, userUnitsMaps, unitsMultipliers); + + break; + default: // Other types we don't care about. + break; } } @@ -2161,18 +2223,17 @@ void Analyser::AnalyserImpl::scaleEquationAst(const AnalyserEquationAstPtr &ast) // how we do it depends on whether the rate is to be computed or // used. - auto astGrandParent = astParent->parent(); + auto astGrandparent = astParent->parent(); - if ((astGrandParent->mPimpl->mType == AnalyserEquationAst::Type::ASSIGNMENT) - && (astGrandParent->mPimpl->mOwnedLeftChild == astParent)) { - scaleAst(astGrandParent->mPimpl->mOwnedRightChild, astGrandParent, 1.0 / scalingFactor); + if (astGrandparent->mPimpl->mType == AnalyserEquationAst::Type::EQUALITY) { + scaleAst(astGrandparent->mPimpl->mOwnedRightChild, astGrandparent, 1.0 / scalingFactor); } else { - scaleAst(astParent, astGrandParent, 1.0 / scalingFactor); + scaleAst(astParent, astGrandparent, 1.0 / scalingFactor); } } } - if (((astParent->mPimpl->mType != AnalyserEquationAst::Type::ASSIGNMENT) + if (((astParent->mPimpl->mType != AnalyserEquationAst::Type::EQUALITY) || (astParent->mPimpl->mOwnedLeftChild != ast)) && (astParent->mPimpl->mType != AnalyserEquationAst::Type::BVAR)) { // We are dealing with a variable which is neither a computed @@ -2193,8 +2254,13 @@ void Analyser::AnalyserImpl::scaleEquationAst(const AnalyserEquationAstPtr &ast) } } +bool Analyser::AnalyserImpl::isExternalVariable(const AnalyserInternalVariablePtr &variable) +{ + return variable->mIsExternal; +} + bool Analyser::AnalyserImpl::isStateRateBased(const AnalyserEquationPtr &equation, - std::vector &checkedEquations) + AnalyserEquationPtrs &checkedEquations) { if (std::find(checkedEquations.begin(), checkedEquations.end(), equation) != checkedEquations.end()) { return false; @@ -2203,7 +2269,14 @@ bool Analyser::AnalyserImpl::isStateRateBased(const AnalyserEquationPtr &equatio checkedEquations.push_back(equation); for (const auto &dependency : equation->dependencies()) { - if ((dependency->type() == AnalyserEquation::Type::RATE) + // A rate is computed either through an ODE equation or through an NLA + // equation in case the rate is not on its own on either the LHS or RHS + // of the equation. + + if ((dependency->type() == AnalyserEquation::Type::ODE) + || ((dependency->type() == AnalyserEquation::Type::NLA) + && (dependency->variableCount() == 1) + && (dependency->variable(0)->type() == AnalyserVariable::Type::STATE)) || isStateRateBased(dependency, checkedEquations)) { return true; } @@ -2212,6 +2285,40 @@ bool Analyser::AnalyserImpl::isStateRateBased(const AnalyserEquationPtr &equatio return false; } +void Analyser::AnalyserImpl::addInvalidVariableIssue(const AnalyserInternalVariablePtr &variable, + Issue::ReferenceRule referenceRule) +{ + std::string descriptionStart = "Variable"; + std::string descriptionEnd; + + switch (variable->mType) { + case AnalyserInternalVariable::Type::UNKNOWN: + descriptionStart = "The type of variable"; + descriptionEnd = "is unknown"; + + break; + case AnalyserInternalVariable::Type::SHOULD_BE_STATE: + descriptionEnd = "is used in an ODE, but it is not initialised"; + + break; + default: // AnalyserInternalVariable::Type::OVERCONSTRAINED. + descriptionEnd = "is computed more than once"; + + break; + } + + auto issue = Issue::IssueImpl::create(); + auto realVariable = variable->mVariable; + + issue->mPimpl->setDescription(descriptionStart + " '" + realVariable->name() + + "' in component '" + owningComponent(realVariable)->name() + + "' " + descriptionEnd + "."); + issue->mPimpl->setReferenceRule(referenceRule); + issue->mPimpl->mItem->mPimpl->setVariable(realVariable); + + addIssue(issue); +} + void Analyser::AnalyserImpl::analyseModel(const ModelPtr &model) { // Reset a few things in case this analyser was to be used to analyse more @@ -2231,118 +2338,268 @@ void Analyser::AnalyserImpl::analyseModel(const ModelPtr &model) analyseComponent(model->component(i)); } - // Some more analysis is needed, but it can only be done if we didn't come - // across any errors during the analysis of our components. + // Recursively analyse the model's components' variables. + // Note: we can't do this as part of analyseComponent() since we don't + // necessarily know the state of all the variables. - if (mAnalyser->errorCount() == 0) { - // Analyse our different equations' AST to determine the type of our - // variables. + for (size_t i = 0; i < model->componentCount(); ++i) { + analyseComponentVariables(model->component(i)); + } - for (const auto &internalEquation : mInternalEquations) { - analyseEquationAst(internalEquation->mAst); - } + if (mAnalyser->errorCount() != 0) { + mModel->mPimpl->mType = AnalyserModel::Type::INVALID; + + return; } - if (mAnalyser->errorCount() == 0) { - // Analyse our different equations' units to make sure that everything - // is consistent. + // Mark some variables as external variables, should there be some and + // should they belong to the model being analysed. - for (const auto &internalEquation : mInternalEquations) { - UnitsMaps unitsMaps; - UnitsMaps userUnitsMaps; - UnitsMultipliers unitsMultipliers; - Strings issueDescriptions; + std::map primaryExternalVariables; - analyseEquationUnits(internalEquation->mAst, unitsMaps, - userUnitsMaps, unitsMultipliers, - issueDescriptions); + if (!mExternalVariables.empty()) { + for (const auto &externalVariable : mExternalVariables) { + auto variable = externalVariable->variable(); - for (const auto &issueDescription : issueDescriptions) { + if (owningModel(variable) != model) { auto issue = Issue::IssueImpl::create(); - issue->mPimpl->setDescription(issueDescription); - issue->mPimpl->setLevel(Issue::Level::WARNING); - issue->mPimpl->setReferenceRule(Issue::ReferenceRule::ANALYSER_UNITS); + issue->mPimpl->setDescription("Variable '" + variable->name() + + "' in component '" + owningComponent(variable)->name() + + "' is marked as an external variable, but it belongs to a different model and will therefore be ignored."); + issue->mPimpl->setLevel(Issue::Level::MESSAGE); + issue->mPimpl->setReferenceRule(Issue::ReferenceRule::ANALYSER_EXTERNAL_VARIABLE_DIFFERENT_MODEL); + issue->mPimpl->mItem->mPimpl->setVariable(variable); addIssue(issue); + } else { + auto internalVariable = Analyser::AnalyserImpl::internalVariable(variable); + + primaryExternalVariables[internalVariable->mVariable].push_back(variable); + + if (!internalVariable->mIsExternal) { + internalVariable->mIsExternal = true; + + for (const auto &dependency : externalVariable->dependencies()) { + internalVariable->mDependencies.push_back(Analyser::AnalyserImpl::internalVariable(dependency)->mVariable); + } + } } } } - // Some post-analysis is now needed, but it can only be done if we didn't - // come across any errors during the analysis of our equations' AST. + // Analyse our different equations' AST to determine the type of our + // variables. + + for (const auto &internalEquation : mInternalEquations) { + analyseEquationAst(internalEquation->mAst); + } + + if (mAnalyser->errorCount() != 0) { + mModel->mPimpl->mType = AnalyserModel::Type::INVALID; - if (mAnalyser->errorCount() == 0) { - // Sort our variables, determine the index of our constant variables and - // then loop over our equations, checking which variables, if any, can - // be determined using a given equation. + return; + } - std::sort(mInternalVariables.begin(), mInternalVariables.end(), - compareVariablesByComponentAndName); + // Check that the variables that were marked as external were rightly so. - auto variableIndex = MAX_SIZE_T; + for (const auto &primaryExternalVariable : primaryExternalVariables) { + std::string description; + auto isVoi = (mModel->mPimpl->mVoi != nullptr) + && (primaryExternalVariable.first == mModel->mPimpl->mVoi->variable()); + auto equivalentVariableCount = primaryExternalVariable.second.size(); + auto hasPrimaryVariable = std::find(primaryExternalVariable.second.begin(), + primaryExternalVariable.second.end(), + primaryExternalVariable.first) + != primaryExternalVariable.second.end(); - for (const auto &internalVariable : mInternalVariables) { - if (internalVariable->mType == AnalyserInternalVariable::Type::CONSTANT) { - internalVariable->mIndex = ++variableIndex; - } - } + if (isVoi || (equivalentVariableCount > 1) || !hasPrimaryVariable) { + description += (equivalentVariableCount == 2) ? "Both " : ""; - auto equationOrder = MAX_SIZE_T; - auto stateIndex = MAX_SIZE_T; - bool relevantCheck; + for (size_t i = 0; i < equivalentVariableCount; ++i) { + if (i != 0) { + description += (i != equivalentVariableCount - 1) ? ", " : " and "; + } - do { - relevantCheck = false; + auto variableString = ((i == 0) && (equivalentVariableCount != 2)) ? + std::string("Variable") : + std::string("variable"); - for (const auto &internalEquation : mInternalEquations) { - relevantCheck = internalEquation->check(equationOrder, stateIndex, variableIndex, mModel) - || relevantCheck; + description += variableString + " '" + primaryExternalVariable.second[i]->name() + + "' in component '" + owningComponent(primaryExternalVariable.second[i])->name() + + "'"; } - } while (relevantCheck); - - // Make sure that our variables are valid. - - for (const auto &internalVariable : mInternalVariables) { - std::string issueType; - Issue::ReferenceRule referenceRule = Issue::ReferenceRule::UNSPECIFIED; - - if (internalVariable->mType == AnalyserInternalVariable::Type::UNKNOWN) { - issueType = "is unused"; - referenceRule = Issue::ReferenceRule::ANALYSER_VARIABLE_UNUSED; - } else if (internalVariable->mType == AnalyserInternalVariable::Type::SHOULD_BE_STATE) { - issueType = "is used in an ODE, but it is not initialised"; - referenceRule = Issue::ReferenceRule::ANALYSER_STATE_NOT_INITIALISED; - } else if (internalVariable->mType == AnalyserInternalVariable::Type::OVERCONSTRAINED) { - issueType = "is computed more than once"; - referenceRule = Issue::ReferenceRule::ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE; + + Issue::ReferenceRule referenceRule; + + if (isVoi) { + description += (equivalentVariableCount == 1) ? + " is marked as an external variable, but it is" : + " are marked as external variables, but they are"; + + if ((equivalentVariableCount == 1) && hasPrimaryVariable) { + description += " the"; + } else { + description += " equivalent to variable '" + primaryExternalVariable.first->name() + + "' in component '" + owningComponent(primaryExternalVariable.first)->name() + + "', the primary"; + } + + description += " variable of integration which cannot be used as an external variable."; + + referenceRule = Issue::ReferenceRule::ANALYSER_EXTERNAL_VARIABLE_VOI; + } else { + description += (equivalentVariableCount == 1) ? + " is marked as an external variable, but it is not a primary variable." : + " are marked as external variables, but they are"; + description += (equivalentVariableCount > 2) ? " all" : ""; + description += (equivalentVariableCount == 1) ? "" : " equivalent."; + description += " Variable '" + primaryExternalVariable.first->name() + + "' in component '" + owningComponent(primaryExternalVariable.first)->name() + + "' is"; + description += hasPrimaryVariable ? + " the" : + (equivalentVariableCount == 1) ? + " its corresponding" : + " their corresponding"; + description += " primary variable and will therefore be the one used as an external variable."; + + referenceRule = Issue::ReferenceRule::ANALYSER_EXTERNAL_VARIABLE_USE_PRIMARY_VARIABLE; } - if (!issueType.empty()) { - auto issue = Issue::IssueImpl::create(); - auto realVariable = internalVariable->mVariable; + auto issue = Issue::IssueImpl::create(); - issue->mPimpl->setDescription("Variable '" + realVariable->name() - + "' in component '" + owningComponent(realVariable)->name() - + "' " + issueType + "."); - issue->mPimpl->setReferenceRule(referenceRule); - issue->mPimpl->mItem->mPimpl->setVariable(realVariable); + issue->mPimpl->setDescription(description); + issue->mPimpl->setLevel(Issue::Level::MESSAGE); + issue->mPimpl->setReferenceRule(referenceRule); + issue->mPimpl->mItem->mPimpl->setVariable(primaryExternalVariable.first); - addIssue(issue); + addIssue(issue); + } + } + + // Analyse our different equations' units to make sure that everything is + // consistent. + + for (const auto &internalEquation : mInternalEquations) { + UnitsMaps unitsMaps; + UnitsMaps userUnitsMaps; + UnitsMultipliers unitsMultipliers; + Strings issueDescriptions; + + analyseEquationUnits(internalEquation->mAst, unitsMaps, + userUnitsMaps, unitsMultipliers, + issueDescriptions); + + for (const auto &issueDescription : issueDescriptions) { + auto issue = Issue::IssueImpl::create(); + + issue->mPimpl->setDescription(issueDescription); + issue->mPimpl->setLevel(Issue::Level::WARNING); + issue->mPimpl->setReferenceRule(Issue::ReferenceRule::ANALYSER_UNITS); + + addIssue(issue); + } + } + + // Detmerine whether some variables have been marked as external. + + auto hasExternalVariables = std::any_of(mInternalVariables.begin(), mInternalVariables.end(), [](const auto &iv) { + return iv->mIsExternal; + }); + + // Loop over our equations, checking which variables, if any, can be + // determined using a given equation. + // Note: we loop twice by checking the model with the view of: + // 1) getting an ODE system WITHOUT any NLA systems; and then + // 2) getting an ODE system WITH one or several NLA systems. + // After those two loops, if we still have some unknown variables and + // they have been marked as external, then we consider them as + // initialised and we go through the two loops one more time. This is + // to account for models that have unknown variables (rendering the + // model invalid) that have been marked as external (rendering the + // model valid). + + auto stateIndex = MAX_SIZE_T; + auto variableIndex = MAX_SIZE_T; + auto loopNumber = 1; + bool relevantCheck; + auto checkNlaSystems = false; + + do { + relevantCheck = false; + + for (const auto &internalEquation : mInternalEquations) { + relevantCheck = internalEquation->check(mModel, stateIndex, variableIndex, checkNlaSystems) + || relevantCheck; + } + + if (((loopNumber == 1) || (loopNumber == 3)) && !relevantCheck) { + ++loopNumber; + + relevantCheck = true; + checkNlaSystems = true; + } else if ((loopNumber == 2) && !relevantCheck) { + // We have gone through the two loops and we still have some unknown + // variables, so we consider as initialised those that have been + // marked as external and we go through the two loops one more time. + + for (const auto &internalVariable : mInternalVariables) { + if (internalVariable->mIsExternal + && (internalVariable->mType == AnalyserInternalVariable::Type::UNKNOWN)) { + internalVariable->mType = AnalyserInternalVariable::Type::INITIALISED; + } + } + + if (hasExternalVariables) { + ++loopNumber; + + relevantCheck = true; + checkNlaSystems = false; } } + } while (relevantCheck); + + // Make sure that our variables are valid. + + for (const auto &internalVariable : mInternalVariables) { + switch (internalVariable->mType) { + case AnalyserInternalVariable::Type::UNKNOWN: + addInvalidVariableIssue(internalVariable, Issue::ReferenceRule::ANALYSER_VARIABLE_UNUSED); + + break; + case AnalyserInternalVariable::Type::SHOULD_BE_STATE: + addInvalidVariableIssue(internalVariable, Issue::ReferenceRule::ANALYSER_STATE_NOT_INITIALISED); - // Determine the type of our model. + break; + case AnalyserInternalVariable::Type::INITIALISED: + // The variable is (still) initialised so it has to be a constant. + + internalVariable->makeConstant(variableIndex); + + break; + case AnalyserInternalVariable::Type::OVERCONSTRAINED: + addInvalidVariableIssue(internalVariable, Issue::ReferenceRule::ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE); + + break; + default: // Other types we don't care about. + break; + } + } - auto hasUnderconstrainedVariables = std::find_if(mInternalVariables.begin(), mInternalVariables.end(), [](const AnalyserInternalVariablePtr &variable) { - return (variable->mType == AnalyserInternalVariable::Type::UNKNOWN) - || (variable->mType == AnalyserInternalVariable::Type::SHOULD_BE_STATE); - }) - != std::end(mInternalVariables); - auto hasOverconstrainedVariables = std::find_if(mInternalVariables.begin(), mInternalVariables.end(), [](const AnalyserInternalVariablePtr &variable) { - return variable->mType == AnalyserInternalVariable::Type::OVERCONSTRAINED; - }) - != std::end(mInternalVariables); + if (mAnalyser->errorCount() != 0) { + auto hasUnderconstrainedVariables = std::any_of(mInternalVariables.begin(), mInternalVariables.end(), [](const auto &iv) { + switch (iv->mType) { + case AnalyserInternalVariable::Type::UNKNOWN: + case AnalyserInternalVariable::Type::SHOULD_BE_STATE: + return true; + default: + return false; + } + }); + auto hasOverconstrainedVariables = std::any_of(mInternalVariables.begin(), mInternalVariables.end(), [](const auto &iv) { + return iv->mType == AnalyserInternalVariable::Type::OVERCONSTRAINED; + }); if (hasUnderconstrainedVariables) { if (hasOverconstrainedVariables) { @@ -2350,355 +2607,478 @@ void Analyser::AnalyserImpl::analyseModel(const ModelPtr &model) } else { mModel->mPimpl->mType = AnalyserModel::Type::UNDERCONSTRAINED; } - } else if (hasOverconstrainedVariables) { + } else { mModel->mPimpl->mType = AnalyserModel::Type::OVERCONSTRAINED; - } else if (mModel->mPimpl->mVoi != nullptr) { - mModel->mPimpl->mType = AnalyserModel::Type::ODE; - } else if (!mInternalVariables.empty()) { - mModel->mPimpl->mType = AnalyserModel::Type::ALGEBRAIC; } - } else { - mModel->mPimpl->mType = AnalyserModel::Type::INVALID; + + return; } - // Some final post-analysis is now needed, if we have a valid model. + // Make sure that our equations are valid. - if ((mModel->mPimpl->mType == AnalyserModel::Type::ODE) - || (mModel->mPimpl->mType == AnalyserModel::Type::ALGEBRAIC)) { - // Add a dummy equation for each of our true (i.e. non-computed) - // constants. - // Note: this is only so that we can mark a constant as an external - // variable. + AnalyserInternalVariablePtrs addedExternalVariables; + AnalyserInternalEquationPtrs addedInternalEquations; + AnalyserInternalEquationPtrs removedInternalEquations; + auto nlaSystemIndex = MAX_SIZE_T; - for (const auto &internalVariable : mInternalVariables) { - if (internalVariable->mType == AnalyserInternalVariable::Type::CONSTANT) { - mInternalEquations.push_back(AnalyserInternalEquation::create(internalVariable)); + for (const auto &internalEquation : mInternalEquations) { + // Account for the unknown variables, in an NLA equation, that have been + // marked as an external variable. This means removing them from + // mUnknownVariables and adding a new equation for them so that the NLA + // equation can have a dependency on them. + + if (internalEquation->mType == AnalyserInternalEquation::Type::NLA) { + for (const auto &unknownVariable : internalEquation->mUnknownVariables) { + if (unknownVariable->mIsExternal + && (std::find(addedExternalVariables.begin(), addedExternalVariables.end(), unknownVariable) == addedExternalVariables.end())) { + addedExternalVariables.push_back(unknownVariable); + addedInternalEquations.push_back(AnalyserInternalEquation::create(unknownVariable)); + } } + + internalEquation->mUnknownVariables.erase(std::remove_if(internalEquation->mUnknownVariables.begin(), internalEquation->mUnknownVariables.end(), isExternalVariable), internalEquation->mUnknownVariables.end()); } - // Mark some variables as external variables, if needed. + // Discard the equation if we have no unknown variables left. - std::map externalVariables; + if (internalEquation->mUnknownVariables.empty()) { + removedInternalEquations.push_back(internalEquation); + } - if (!mExternalVariables.empty()) { - // Check whether an external variable belongs to the model being - // analysed, or whether it is marked as an external variable more - // than once through equivalence or is (equivalent to) the variable - // of integration. + // Make the NLA equations that compute the same variables aware of one + // another and assign them an index for the NLA system in which they are + // used. - std::map primaryExternalVariables; + if (internalEquation->mType == AnalyserInternalEquation::Type::NLA) { + if (internalEquation->mNlaSystemIndex == MAX_SIZE_T) { + internalEquation->mNlaSystemIndex = ++nlaSystemIndex; + } - for (const auto &externalVariable : mExternalVariables) { - auto variable = externalVariable->variable(); + for (const auto &otherInternalEquation : mInternalEquations) { + if ((otherInternalEquation != internalEquation) + && (otherInternalEquation->mType == AnalyserInternalEquation::Type::NLA)) { + // Check what common unknown variables there are between + // internalEquation and otherInternalEquation, if any. + // Note: we would normally use std::set_intersection() for + // this, but this would require + // internalEquation->mUnknownVariables and + // otherInternalEquation->mUnknownVariables to be + // sorted which neither of them is and it's not worth + // sorting them for such a trivial case, hence we do + // the intersection ourselves. + + AnalyserInternalVariablePtrs commonUnknownVariables; + + for (const auto &unknownVariable : internalEquation->mUnknownVariables) { + if (std::find(otherInternalEquation->mUnknownVariables.begin(), otherInternalEquation->mUnknownVariables.end(), unknownVariable) != otherInternalEquation->mUnknownVariables.end()) { + commonUnknownVariables.push_back(unknownVariable); + } + } - if (variable != nullptr) { - if (owningModel(variable) != model) { - auto issue = Issue::IssueImpl::create(); + // Consider otherInternalEquation as an NLA sibling of + // internalEquation, if there are some common unknown + // variables, and make sure that it has the same NLA system + // index as internalEquation. - issue->mPimpl->setDescription("Variable '" + variable->name() - + "' in component '" + owningComponent(variable)->name() - + "' is marked as an external variable, but it belongs to a different model and will therefore be ignored."); - issue->mPimpl->setLevel(Issue::Level::MESSAGE); - issue->mPimpl->setReferenceRule(Issue::ReferenceRule::ANALYSER_EXTERNAL_VARIABLE_DIFFERENT_MODEL); - issue->mPimpl->mItem->mPimpl->setVariable(variable); + if (!commonUnknownVariables.empty()) { + internalEquation->mNlaSiblings.push_back(otherInternalEquation); - addIssue(issue); - } else { - auto internalVariable = Analyser::AnalyserImpl::internalVariable(variable); + otherInternalEquation->mNlaSystemIndex = internalEquation->mNlaSystemIndex; + } + } + } + } + } - primaryExternalVariables[internalVariable->mVariable].push_back(variable); + // Add/remove some internal equations. - if (((mModel->mPimpl->mVoi == nullptr) - || (internalVariable->mVariable != mModel->mPimpl->mVoi->variable())) - && (externalVariables.count(internalVariable) == 0)) { - VariablePtrs dependencies; + for (const auto &addedInternalEquation : addedInternalEquations) { + mInternalEquations.push_back(addedInternalEquation); + } - for (const auto &dependency : externalVariable->dependencies()) { - dependencies.push_back(Analyser::AnalyserImpl::internalVariable(dependency)->mVariable); - } + for (const auto &removedInternalEquation : removedInternalEquations) { + mInternalEquations.erase(std::find(mInternalEquations.begin(), mInternalEquations.end(), removedInternalEquation)); + } - externalVariables.emplace(internalVariable, dependencies); - } - } + // Confirm that equations that compute a variable-based constant are still + // of that type. + // Note: indeed, when originally qualifying such an equation, all we know + // about the variables on which the equation depends is that they have + // an initial value. However, those variables may then have been + // proven to be computed using an NLA system, in which case the + // equation should now be considered as an algebraic equation and the + // variable it computes an algebraic variable. + + // Confirm that the variables in an NLA system are not overconstrained. + // Note: this may happen if an NLA system contains too many NLA equations + // to compute its unknown variables and/or if some internal equations + // were removed (as a result of some variables in an NLA equation + // having been marked as external). + + AnalyserInternalVariablePtrs overconstrainedVariables; + + for (const auto &internalEquation : mInternalEquations) { + switch (internalEquation->mType) { + case AnalyserInternalEquation::Type::VARIABLE_BASED_CONSTANT: { + auto unknownVariable = internalEquation->mUnknownVariables.front(); + + for (const auto &variable : internalEquation->mAllVariables) { + if ((variable != unknownVariable) + && (variable->mType != AnalyserInternalVariable::Type::CONSTANT) + && (variable->mType != AnalyserInternalVariable::Type::COMPUTED_TRUE_CONSTANT) + && (variable->mType != AnalyserInternalVariable::Type::COMPUTED_VARIABLE_BASED_CONSTANT)) { + // We are supposed to compute a variable-based constant, yet + // we have come across a variable which is not some kind of + // a constant. In fact, it was an algebraic variable (with + // an initial guess) that needs to be computed using an NLA + // system. So, requalify the unknown variable and equation. + + unknownVariable->mType = AnalyserInternalVariable::Type::ALGEBRAIC; + internalEquation->mType = AnalyserInternalEquation::Type::ALGEBRAIC; + + break; } } + } break; + case AnalyserInternalEquation::Type::NLA: + if (internalEquation->mNlaSiblings.size() + 1 > internalEquation->mUnknownVariables.size()) { + // There are more NLA equations than unknown variables, so all + // the unknown variables involved in the NLA system should be + // considered as overconstrained. - for (const auto &primaryExternalVariable : primaryExternalVariables) { - std::string description; - auto isVoi = (mModel->mPimpl->mVoi != nullptr) - && (primaryExternalVariable.first == mModel->mPimpl->mVoi->variable()); - auto equivalentVariableCount = primaryExternalVariable.second.size(); - auto hasPrimaryVariable = std::find(primaryExternalVariable.second.begin(), - primaryExternalVariable.second.end(), - primaryExternalVariable.first) - != primaryExternalVariable.second.end(); - - if (isVoi || (equivalentVariableCount > 1) || !hasPrimaryVariable) { - description += (equivalentVariableCount == 2) ? "Both " : ""; - - for (size_t i = 0; i < equivalentVariableCount; ++i) { - if (i != 0) { - description += (i != equivalentVariableCount - 1) ? ", " : " and "; - } + for (const auto &unknownVariable : internalEquation->mUnknownVariables) { + if (std::find(overconstrainedVariables.begin(), overconstrainedVariables.end(), unknownVariable) == overconstrainedVariables.end()) { + unknownVariable->mType = AnalyserInternalVariable::Type::OVERCONSTRAINED; - auto variableString = ((i == 0) && (equivalentVariableCount != 2)) ? - std::string("Variable") : - std::string("variable"); + addInvalidVariableIssue(unknownVariable, Issue::ReferenceRule::ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE); - description += variableString + " '" + primaryExternalVariable.second[i]->name() - + "' in component '" + owningComponent(primaryExternalVariable.second[i])->name() - + "'"; + overconstrainedVariables.push_back(unknownVariable); } + } + } + + break; + default: // Other types we don't care about. + break; + } + } - Issue::ReferenceRule referenceRule; + if (mAnalyser->errorCount() != 0) { + mModel->mPimpl->mType = AnalyserModel::Type::OVERCONSTRAINED; - if (isVoi) { - description += (equivalentVariableCount == 1) ? - " is marked as an external variable, but it is" : - " are marked as external variables, but they are"; + return; + } - if ((equivalentVariableCount == 1) && hasPrimaryVariable) { - description += " the"; - } else { - description += " equivalent to variable '" + primaryExternalVariable.first->name() - + "' in component '" + owningComponent(primaryExternalVariable.first)->name() - + "', the primary"; - } + // Determine the type of our model. - description += " variable of integration which cannot be used as an external variable."; + auto hasNlaEquations = std::any_of(mInternalEquations.begin(), mInternalEquations.end(), [=](const auto &ie) { + if (ie->mType == AnalyserInternalEquation::Type::NLA) { + // Make sure that not all the variables involved in the NLA system + // have been marked as external - referenceRule = Issue::ReferenceRule::ANALYSER_EXTERNAL_VARIABLE_VOI; - } else { - description += (equivalentVariableCount == 1) ? - " is marked as an external variable, but it is not a primary variable." : - " are marked as external variables, but they are"; - description += (equivalentVariableCount > 2) ? " all" : ""; - description += (equivalentVariableCount == 1) ? "" : " equivalent."; - description += " Variable '" + primaryExternalVariable.first->name() - + "' in component '" + owningComponent(primaryExternalVariable.first)->name() - + "' is"; - description += hasPrimaryVariable ? - " the" : - (equivalentVariableCount == 1) ? - " its corresponding" : - " their corresponding"; - description += " primary variable and will therefore be the one used as an external variable."; - - referenceRule = Issue::ReferenceRule::ANALYSER_EXTERNAL_VARIABLE_USE_PRIMARY_VARIABLE; - } + return std::any_of(ie->mUnknownVariables.begin(), ie->mUnknownVariables.end(), [](const auto &uv) { + return !uv->mIsExternal; + }); + } - auto issue = Issue::IssueImpl::create(); + return false; + }); - issue->mPimpl->setDescription(description); - issue->mPimpl->setLevel(Issue::Level::MESSAGE); - issue->mPimpl->setReferenceRule(referenceRule); - issue->mPimpl->mItem->mPimpl->setVariable(primaryExternalVariable.first); + if (mModel->mPimpl->mVoi != nullptr) { + mModel->mPimpl->mType = hasNlaEquations ? + AnalyserModel::Type::DAE : + AnalyserModel::Type::ODE; + } else if (!mInternalVariables.empty()) { + mModel->mPimpl->mType = hasNlaEquations ? + AnalyserModel::Type::NLA : + AnalyserModel::Type::ALGEBRAIC; + } - addIssue(issue); - } - } + if (!mModel->isValid()) { + return; + } + + // Add a dummy equation for each of our true (i.e. non-computed) constants. + // Note: this is so that a constant can be marked as an external variable. + + for (const auto &internalVariable : mInternalVariables) { + if (internalVariable->mType == AnalyserInternalVariable::Type::CONSTANT) { + mInternalEquations.push_back(AnalyserInternalEquation::create(internalVariable)); } + } - // Carry on, but only if there are no errors (i.e. warnings are fine). + // Make it known through our API whether the model has some external + // variables. - if (mAnalyser->errorCount() == 0) { - // Make it known through our API whether the model has some external - // variables. + mModel->mPimpl->mHasExternalVariables = hasExternalVariables; - mModel->mPimpl->mHasExternalVariables = !externalVariables.empty(); + // Create a mapping between our internal equations and our future equations + // in the API. - // Sort our internal variables and equations. + std::map aie2aeMappings; + std::map v2aeMappings; - std::sort(mInternalVariables.begin(), mInternalVariables.end(), - compareVariablesByTypeAndIndex); - std::sort(mInternalEquations.begin(), mInternalEquations.end(), - compareEquationsByVariable); + for (const auto &internalEquation : mInternalEquations) { + auto equation = AnalyserEquation::AnalyserEquationImpl::create(); - std::map equationMappings; - std::map variableMappings; + aie2aeMappings.emplace(internalEquation, equation); + v2aeMappings.emplace(internalEquation->mUnknownVariables.front()->mVariable, equation); + } - for (const auto &internalEquation : mInternalEquations) { - equationMappings.emplace(internalEquation->mVariable->mVariable, std::shared_ptr {new AnalyserEquation {}}); - } + // Make our internal variables available through our API. - // Make our internal variables available through our API. + std::map aiv2avMappings; + std::map v2avMappings; - auto stateIndex = MAX_SIZE_T; - auto variableIndex = MAX_SIZE_T; + stateIndex = MAX_SIZE_T; + variableIndex = MAX_SIZE_T; - for (const auto &internalVariable : mInternalVariables) { - // Determine the type of the variable. - - AnalyserVariable::Type type; - - if (externalVariables.count(internalVariable) == 1) { - type = AnalyserVariable::Type::EXTERNAL; - } else if (internalVariable->mType == AnalyserInternalVariable::Type::STATE) { - type = AnalyserVariable::Type::STATE; - } else if (internalVariable->mType == AnalyserInternalVariable::Type::CONSTANT) { - type = AnalyserVariable::Type::CONSTANT; - } else if ((internalVariable->mType == AnalyserInternalVariable::Type::COMPUTED_TRUE_CONSTANT) - || (internalVariable->mType == AnalyserInternalVariable::Type::COMPUTED_VARIABLE_BASED_CONSTANT)) { - type = AnalyserVariable::Type::COMPUTED_CONSTANT; - } else if (internalVariable->mType == AnalyserInternalVariable::Type::ALGEBRAIC) { - type = AnalyserVariable::Type::ALGEBRAIC; - } else { - // This is the variable of integration, so skip it. + for (const auto &internalVariable : mInternalVariables) { + // Determine the type of the variable. - continue; - } + AnalyserVariable::Type type; - // Populate and keep track of the state/variable. + if (internalVariable->mIsExternal) { + type = AnalyserVariable::Type::EXTERNAL; + } else { + switch (internalVariable->mType) { + case AnalyserInternalVariable::Type::STATE: + type = AnalyserVariable::Type::STATE; + + break; + case AnalyserInternalVariable::Type::CONSTANT: + type = AnalyserVariable::Type::CONSTANT; - auto stateOrVariable = AnalyserVariable::AnalyserVariableImpl::create(); - auto equation = equationMappings[internalVariable->mVariable]; + break; + case AnalyserInternalVariable::Type::COMPUTED_TRUE_CONSTANT: + case AnalyserInternalVariable::Type::COMPUTED_VARIABLE_BASED_CONSTANT: + type = AnalyserVariable::Type::COMPUTED_CONSTANT; - stateOrVariable->mPimpl->populate(type, - (type == AnalyserVariable::Type::STATE) ? - ++stateIndex : - ++variableIndex, - (type == AnalyserVariable::Type::EXTERNAL) ? - nullptr : - internalVariable->mInitialisingVariable, - internalVariable->mVariable, - equation); + break; + case AnalyserInternalVariable::Type::ALGEBRAIC: + case AnalyserInternalVariable::Type::INITIALISED_ALGEBRAIC: + type = AnalyserVariable::Type::ALGEBRAIC; - variableMappings.emplace(equation, stateOrVariable); + break; + default: // AnalyserVariable::Type::VARIABLE_OF_INTEGRATION. + // This is the variable of integration, so skip it. - if (type == AnalyserVariable::Type::STATE) { - mModel->mPimpl->mStates.push_back(stateOrVariable); - } else { - mModel->mPimpl->mVariables.push_back(stateOrVariable); - } + continue; + } + } + + // Populate and keep track of the state/variable. + + auto variable = AnalyserVariable::AnalyserVariableImpl::create(); + AnalyserEquationPtrs equations; + + for (const auto &internalEquation : mInternalEquations) { + if (std::find(internalEquation->mUnknownVariables.begin(), internalEquation->mUnknownVariables.end(), internalVariable) != internalEquation->mUnknownVariables.end()) { + equations.push_back(aie2aeMappings[internalEquation]); } + } - // Make our internal equations available through our API. + variable->mPimpl->populate(type, + (type == AnalyserVariable::Type::STATE) ? + ++stateIndex : + ++variableIndex, + (type == AnalyserVariable::Type::EXTERNAL) ? + nullptr : + internalVariable->mInitialisingVariable, + internalVariable->mVariable, + equations); - std::vector externallyDependentVariables; + aiv2avMappings.emplace(internalVariable, variable); + v2avMappings.emplace(internalVariable->mVariable, variable); - for (const auto &internalEquation : mInternalEquations) { - // Determine the type of the equation. + if (type == AnalyserVariable::Type::STATE) { + mModel->mPimpl->mStates.push_back(variable); + } else { + mModel->mPimpl->mVariables.push_back(variable); + } + } - auto equation = equationMappings[internalEquation->mVariable->mVariable]; - auto stateOrVariable = variableMappings[equation]; - AnalyserEquation::Type type; + // Make our internal equations available through our API. - if (stateOrVariable->type() == AnalyserVariable::Type::EXTERNAL) { - type = AnalyserEquation::Type::EXTERNAL; - } else if (internalEquation->mType == AnalyserInternalEquation::Type::TRUE_CONSTANT) { - type = AnalyserEquation::Type::TRUE_CONSTANT; - } else if (internalEquation->mType == AnalyserInternalEquation::Type::VARIABLE_BASED_CONSTANT) { - // An equation for a variable-based constant may now rely on - // external variables, be it directly or indirectly. If this - // is the case then we need to requalify that equation as an - // algebraic equation. + for (const auto &internalEquation : mInternalEquations) { + // Determine all the variables computed by the equation, as well as + // whether the equation is an external one. - type = AnalyserEquation::Type::VARIABLE_BASED_CONSTANT; + AnalyserVariablePtrs variables; + auto externalEquation = true; - for (const auto &variable : internalEquation->mAllVariables) { - if ((externalVariables.count(variable) == 1) - || (std::find(externallyDependentVariables.begin(), externallyDependentVariables.end(), variable) != externallyDependentVariables.end())) { - type = AnalyserEquation::Type::ALGEBRAIC; + for (const auto &unknownVariable : internalEquation->mUnknownVariables) { + auto variable = aiv2avMappings[unknownVariable]; - stateOrVariable->mPimpl->mType = AnalyserVariable::Type::ALGEBRAIC; + variables.push_back(variable); - externallyDependentVariables.push_back(internalEquation->mVariable); + if (variable->type() != AnalyserVariable::Type::EXTERNAL) { + externalEquation = false; + } + } - break; - } - } - } else if (internalEquation->mType == AnalyserInternalEquation::Type::RATE) { - type = AnalyserEquation::Type::RATE; - } else if (internalEquation->mType == AnalyserInternalEquation::Type::ALGEBRAIC) { - type = AnalyserEquation::Type::ALGEBRAIC; - } else { - // The equation type is unknown, which means that it is a - // dummy equation for a true (i.e. non-computed) constant - // (so that it could have been marked as an external - // variable), so we skip it since the constant wasn't marked - // as an external variable. + // Determine the type of the equation. - continue; - } + AnalyserEquation::Type type; - // Scale our internal equation's AST to take into account the - // fact that we may have mapped variables that use compatible - // units rather than equivalent ones. + if (externalEquation) { + type = AnalyserEquation::Type::EXTERNAL; + } else { + switch (internalEquation->mType) { + case AnalyserInternalEquation::Type::TRUE_CONSTANT: + type = AnalyserEquation::Type::TRUE_CONSTANT; - scaleEquationAst(internalEquation->mAst); + break; + case AnalyserInternalEquation::Type::VARIABLE_BASED_CONSTANT: + type = AnalyserEquation::Type::VARIABLE_BASED_CONSTANT; - // Determine the equation's dependencies, i.e. the equations for - // the variables on which this equation depends. - // Note: an equation may depend on the variable of integration, - // for which there is no equation, hence we need to test - // equationDependency against nullptr. + break; + case AnalyserInternalEquation::Type::ODE: + type = AnalyserEquation::Type::ODE; - VariablePtrs variableDependencies = (type == AnalyserEquation::Type::EXTERNAL) ? - externalVariables.find(internalEquation->mVariable)->second : - internalEquation->mDependencies; - std::vector equationDependencies; + break; + case AnalyserInternalEquation::Type::NLA: + type = AnalyserEquation::Type::NLA; - for (const auto &variableDependency : variableDependencies) { - auto equationDependency = equationMappings[variableDependency]; + break; + case AnalyserInternalEquation::Type::ALGEBRAIC: + type = AnalyserEquation::Type::ALGEBRAIC; - if (equationDependency != nullptr) { - equationDependencies.push_back(equationDependency); - } - } + break; + default: // AnalyserEquation::Type::UNKNOWN. + // The equation type is unknown, which means that it is a dummy + // equation for a true (i.e. non-computed) constant (so that it + // could have been marked as an external variable), so we skip + // it since the constant wasn't marked as an external variable. + + continue; + } + } + + // Scale our internal equation's AST to take into account the fact that + // we may have mapped variables that use compatible units rather than + // equivalent ones. + + scaleEquationAst(internalEquation->mAst); + + // Manipulate the equation, if needed. - // Populate and keep track of the equation. + switch (type) { + case AnalyserEquation::Type::NLA: + // The equation is currently of the form LHS = RHS, but we want it + // in the form LHS-RHS, so replace the equality element with a minus + // one. - equation->mPimpl->populate(type, - (type == AnalyserEquation::Type::EXTERNAL) ? - nullptr : - internalEquation->mAst, - equationDependencies, - stateOrVariable); + internalEquation->mAst->setType(AnalyserEquationAst::Type::MINUS); - mModel->mPimpl->mEquations.push_back(equation); + break; + case AnalyserEquation::Type::EXTERNAL: + // Do nothing. + + break; + default: + // Swap the LHS and RHS of the equation if its unknown variable is + // on its RHS. + + if (internalEquation->variableOnRhs(internalEquation->mUnknownVariables.front())) { + internalEquation->mAst->swapLeftAndRightChildren(); } - // Clean up our equations' dependencies. - // Note: indeed, some equations may have a dependency on one or - // several true (i.e. non-computed) constants, for which there - // are no proper equations. So, we need to remove those - // dependencies, and obviously this can only be done once all - // our equations are ready. + break; + } + + // Determine the equation's dependencies, i.e. the equations for the + // variables on which this equation depends. - for (const auto &equation : mModel->mPimpl->mEquations) { - equation->mPimpl->cleanUpDependencies(); + VariablePtrs variableDependencies; + + if (type == AnalyserEquation::Type::EXTERNAL) { + for (const auto &unknownVariable : internalEquation->mUnknownVariables) { + for (const auto &dependency : unknownVariable->mDependencies) { + variableDependencies.push_back(dependency); + } } + } else { + variableDependencies = internalEquation->mDependencies; + } - // Determine whether our equations are state/rate based. - // Note: obviously, this can only be done once all our equations are - // ready. + AnalyserEquationPtrs equationDependencies; - for (const auto &equation : mModel->mPimpl->mEquations) { - std::vector checkedEquations; + for (const auto &variableDependency : variableDependencies) { + auto variable = v2avMappings[variableDependency]; - equation->mPimpl->mIsStateRateBased = isStateRateBased(equation, checkedEquations); + if (variable != nullptr) { + for (const auto &equation : variable->equations()) { + if (std::find(equationDependencies.begin(), equationDependencies.end(), equation) == equationDependencies.end()) { + equationDependencies.push_back(equation); + } + } } } + + // Determine the equation's NLA siblings, i.e. the equations that should + // be computed as part of an NLA system, should this equation be an NLA + // one. + + AnalyserEquationPtrs equationNlaSiblings; + + for (const auto &nlaSibling : internalEquation->mNlaSiblings) { + equationNlaSiblings.push_back(aie2aeMappings[nlaSibling.lock()]); + } + + // Populate and keep track of the equation. + + auto equation = aie2aeMappings[internalEquation]; + + equation->mPimpl->populate(type, + (type == AnalyserEquation::Type::EXTERNAL) ? + nullptr : + internalEquation->mAst, + equationDependencies, + internalEquation->mNlaSystemIndex, + equationNlaSiblings, + variables); + + mModel->mPimpl->mEquations.push_back(equation); + } + + // Clean up our equations' dependencies. + // Note: indeed, some equations may have a dependency on the variable of + // integration (for which there is no equation) and/or one or several + // true (i.e. non-computed) constants (for which there are no proper + // equations). So, we need to remove those dependencies, and obviously + // this can only be done once all our equations are ready. + + for (const auto &equation : mModel->mPimpl->mEquations) { + equation->mPimpl->cleanUpDependencies(); + } + + // Determine whether our equations are state/rate based. + // Note: obviously, this can only be done once all our equations are ready. + + for (const auto &equation : mModel->mPimpl->mEquations) { + AnalyserEquationPtrs checkedEquations; + + equation->mPimpl->mIsStateRateBased = isStateRateBased(equation, checkedEquations); } } -std::vector::const_iterator Analyser::AnalyserImpl::findExternalVariable(const ModelPtr &model, - const std::string &componentName, - const std::string &variableName) const +AnalyserExternalVariablePtrs::const_iterator Analyser::AnalyserImpl::findExternalVariable(const ModelPtr &model, + const std::string &componentName, + const std::string &variableName) const { - return std::find_if(mExternalVariables.begin(), mExternalVariables.end(), [=](const AnalyserExternalVariablePtr &ev) { - auto v = ev->variable(); + return std::find_if(mExternalVariables.begin(), mExternalVariables.end(), [=](const auto &ev) { + auto variable = ev->variable(); - return (v != nullptr) - && (owningModel(v) == model) - && (owningComponent(v)->name() == componentName) - && (v->name() == variableName); + return (owningModel(variable) == model) + && (owningComponent(variable)->name() == componentName) + && (variable->name() == variableName); }); } -std::vector::const_iterator Analyser::AnalyserImpl::findExternalVariable(const AnalyserExternalVariablePtr &externalVariable) const +AnalyserExternalVariablePtrs::const_iterator Analyser::AnalyserImpl::findExternalVariable(const AnalyserExternalVariablePtr &externalVariable) const { - return std::find_if(mExternalVariables.begin(), mExternalVariables.end(), [=](const AnalyserExternalVariablePtr &ev) { + return std::find_if(mExternalVariables.begin(), mExternalVariables.end(), [=](const auto &ev) { return ev == externalVariable; }); } @@ -2714,7 +3094,7 @@ const Analyser::AnalyserImpl *Analyser::pFunc() const } Analyser::Analyser() - : Logger(new Analyser::AnalyserImpl()) + : Logger(new AnalyserImpl()) { pFunc()->mAnalyser = this; } diff --git a/src/analyserequation.cpp b/src/analyserequation.cpp index 95338c0a2..228dd119e 100644 --- a/src/analyserequation.cpp +++ b/src/analyserequation.cpp @@ -16,36 +16,48 @@ limitations under the License. #include "libcellml/analyserequation.h" +#include +#include + #include "analyserequation_p.h" namespace libcellml { +AnalyserEquationPtr AnalyserEquation::AnalyserEquationImpl::create() +{ + return std::shared_ptr {new AnalyserEquation {}}; +} + void AnalyserEquation::AnalyserEquationImpl::populate(AnalyserEquation::Type type, const AnalyserEquationAstPtr &ast, const std::vector &dependencies, - const AnalyserVariablePtr &variable) + size_t nlaSystemIndex, + const std::vector &nlaSiblings, + const std::vector &variables) { mType = type; mAst = ast; + mNlaSystemIndex = nlaSystemIndex; - for (const auto &dependency : dependencies) { - mDependencies.push_back(dependency); - } - - mVariable = variable; + std::copy(dependencies.begin(), dependencies.end(), back_inserter(mDependencies)); + std::copy(nlaSiblings.begin(), nlaSiblings.end(), back_inserter(mNlaSiblings)); + std::copy(variables.begin(), variables.end(), back_inserter(mVariables)); } -void AnalyserEquation::AnalyserEquationImpl::cleanUpDependencies() +bool AnalyserEquation::AnalyserEquationImpl::isEmptyDependency(const AnalyserEquationWeakPtr &dependency) { - std::vector dependencies; + auto variables = dependency.lock()->variables(); - for (const auto &dependency : mDependencies) { - if (dependency.lock()->variable() != nullptr) { - dependencies.push_back(dependency); - } + if (std::any_of(variables.begin(), variables.end(), [](const auto &v) { return v != nullptr; })) { + return false; } - mDependencies = dependencies; + return true; +} + +void AnalyserEquation::AnalyserEquationImpl::cleanUpDependencies() +{ + mDependencies.erase(std::remove_if(mDependencies.begin(), mDependencies.end(), isEmptyDependency), mDependencies.end()); } AnalyserEquation::AnalyserEquation() @@ -63,9 +75,27 @@ AnalyserEquation::Type AnalyserEquation::type() const return mPimpl->mType; } +static const std::map typeToString = { + {AnalyserEquation::Type::TRUE_CONSTANT, "true_constant"}, + {AnalyserEquation::Type::VARIABLE_BASED_CONSTANT, "variable_based_constant"}, + {AnalyserEquation::Type::ODE, "ode"}, + {AnalyserEquation::Type::NLA, "nla"}, + {AnalyserEquation::Type::ALGEBRAIC, "algebraic"}, + {AnalyserEquation::Type::EXTERNAL, "external"}}; + +std::string AnalyserEquation::typeAsString(Type type) +{ + return typeToString.at(type); +} + AnalyserEquationAstPtr AnalyserEquation::ast() const { - return mPimpl->mAst.lock(); + return mPimpl->mAst; +} + +size_t AnalyserEquation::dependencyCount() const +{ + return mPimpl->mDependencies.size(); } std::vector AnalyserEquation::dependencies() const @@ -79,14 +109,67 @@ std::vector AnalyserEquation::dependencies() const return res; } +AnalyserEquationPtr AnalyserEquation::dependency(size_t index) const +{ + if (index >= mPimpl->mDependencies.size()) { + return {}; + } + + return mPimpl->mDependencies[index].lock(); +} + +size_t AnalyserEquation::nlaSystemIndex() const +{ + return mPimpl->mNlaSystemIndex; +} + +size_t AnalyserEquation::nlaSiblingCount() const +{ + return mPimpl->mNlaSiblings.size(); +} + +std::vector AnalyserEquation::nlaSiblings() const +{ + std::vector res; + + for (const auto &nlaSibling : mPimpl->mNlaSiblings) { + res.push_back(nlaSibling.lock()); + } + + return res; +} + +AnalyserEquationPtr AnalyserEquation::nlaSibling(size_t index) const +{ + if (index >= mPimpl->mNlaSiblings.size()) { + return {}; + } + + return mPimpl->mNlaSiblings[index].lock(); +} + bool AnalyserEquation::isStateRateBased() const { return mPimpl->mIsStateRateBased; } -AnalyserVariablePtr AnalyserEquation::variable() const +size_t AnalyserEquation::variableCount() const +{ + return mPimpl->mVariables.size(); +} + +std::vector AnalyserEquation::variables() const +{ + return mPimpl->mVariables; +} + +AnalyserVariablePtr AnalyserEquation::variable(size_t index) const { - return mPimpl->mVariable.lock(); + if (index >= mPimpl->mVariables.size()) { + return {}; + } + + return mPimpl->mVariables[index]; } } // namespace libcellml diff --git a/src/analyserequation_p.h b/src/analyserequation_p.h index 939533a19..79d9fa63a 100644 --- a/src/analyserequation_p.h +++ b/src/analyserequation_p.h @@ -18,11 +18,9 @@ limitations under the License. #include "libcellml/analyserequation.h" -namespace libcellml { +#include "internaltypes.h" -using AnalyserEquationWeakPtr = std::weak_ptr; /**< Type definition for weak analyser equation pointer. */ -using AnalyserEquationAstWeakPtr = std::weak_ptr; /**< Type definition for weak analyser equation AST pointer. */ -using AnalyserVariableWeakPtr = std::weak_ptr; /**< Type definition for weak analyser variable pointer. */ +namespace libcellml { /** * @brief The AnalyserEquation::AnalyserEquationImpl struct. @@ -32,15 +30,23 @@ using AnalyserVariableWeakPtr = std::weak_ptr; /**< Type defin struct AnalyserEquation::AnalyserEquationImpl { AnalyserEquation::Type mType = AnalyserEquation::Type::ALGEBRAIC; - AnalyserEquationAstWeakPtr mAst; + AnalyserEquationAstPtr mAst; std::vector mDependencies; + size_t mNlaSystemIndex; + std::vector mNlaSiblings; bool mIsStateRateBased = false; - AnalyserVariableWeakPtr mVariable; + std::vector mVariables; + + static AnalyserEquationPtr create(); void populate(AnalyserEquation::Type type, const AnalyserEquationAstPtr &ast, const std::vector &dependencies, - const AnalyserVariablePtr &variable); + size_t nlaSystemIndex, + const std::vector &nlaSiblings, + const std::vector &variables); + + static bool isEmptyDependency(const AnalyserEquationWeakPtr &dependency); void cleanUpDependencies(); }; diff --git a/src/analyserequationast.cpp b/src/analyserequationast.cpp index 07bfa4084..f543f766f 100644 --- a/src/analyserequationast.cpp +++ b/src/analyserequationast.cpp @@ -18,6 +18,8 @@ limitations under the License. #include "analyserequationast_p.h" +#include "libcellml/undefines.h" + namespace libcellml { void AnalyserEquationAst::AnalyserEquationAstImpl::populate(AnalyserEquationAst::Type type, @@ -65,6 +67,104 @@ AnalyserEquationAst::Type AnalyserEquationAst::type() const return mPimpl->mType; } +static const std::map typeToString = { + // Equality. + + {AnalyserEquationAst::Type::EQUALITY, "equality"}, + + // Relational and logical operators. + + {AnalyserEquationAst::Type::EQ, "eq"}, + {AnalyserEquationAst::Type::NEQ, "neq"}, + {AnalyserEquationAst::Type::LT, "lt"}, + {AnalyserEquationAst::Type::LEQ, "leq"}, + {AnalyserEquationAst::Type::GT, "gt"}, + {AnalyserEquationAst::Type::GEQ, "geq"}, + {AnalyserEquationAst::Type::AND, "and"}, + {AnalyserEquationAst::Type::OR, "or"}, + {AnalyserEquationAst::Type::XOR, "xor"}, + {AnalyserEquationAst::Type::NOT, "not"}, + + // Arithmetic operators. + + {AnalyserEquationAst::Type::PLUS, "plus"}, + {AnalyserEquationAst::Type::MINUS, "minus"}, + {AnalyserEquationAst::Type::TIMES, "times"}, + {AnalyserEquationAst::Type::DIVIDE, "divide"}, + {AnalyserEquationAst::Type::POWER, "power"}, + {AnalyserEquationAst::Type::ROOT, "root"}, + {AnalyserEquationAst::Type::ABS, "abs"}, + {AnalyserEquationAst::Type::EXP, "exp"}, + {AnalyserEquationAst::Type::LN, "ln"}, + {AnalyserEquationAst::Type::LOG, "log"}, + {AnalyserEquationAst::Type::CEILING, "ceiling"}, + {AnalyserEquationAst::Type::FLOOR, "floor"}, + {AnalyserEquationAst::Type::MIN, "min"}, + {AnalyserEquationAst::Type::MAX, "max"}, + {AnalyserEquationAst::Type::REM, "rem"}, + + // Calculus elements. + + {AnalyserEquationAst::Type::DIFF, "diff"}, + + // Trigonometric operators. + + {AnalyserEquationAst::Type::SIN, "sin"}, + {AnalyserEquationAst::Type::COS, "cos"}, + {AnalyserEquationAst::Type::TAN, "tan"}, + {AnalyserEquationAst::Type::SEC, "sec"}, + {AnalyserEquationAst::Type::CSC, "csc"}, + {AnalyserEquationAst::Type::COT, "cot"}, + {AnalyserEquationAst::Type::SINH, "sinh"}, + {AnalyserEquationAst::Type::COSH, "cosh"}, + {AnalyserEquationAst::Type::TANH, "tanh"}, + {AnalyserEquationAst::Type::SECH, "sech"}, + {AnalyserEquationAst::Type::CSCH, "csch"}, + {AnalyserEquationAst::Type::COTH, "coth"}, + {AnalyserEquationAst::Type::ASIN, "asin"}, + {AnalyserEquationAst::Type::ACOS, "acos"}, + {AnalyserEquationAst::Type::ATAN, "atan"}, + {AnalyserEquationAst::Type::ASEC, "asec"}, + {AnalyserEquationAst::Type::ACSC, "acsc"}, + {AnalyserEquationAst::Type::ACOT, "acot"}, + {AnalyserEquationAst::Type::ASINH, "asinh"}, + {AnalyserEquationAst::Type::ACOSH, "acosh"}, + {AnalyserEquationAst::Type::ATANH, "atanh"}, + {AnalyserEquationAst::Type::ASECH, "asech"}, + {AnalyserEquationAst::Type::ACSCH, "acsch"}, + {AnalyserEquationAst::Type::ACOTH, "acoth"}, + + // Piecewise statement. + + {AnalyserEquationAst::Type::PIECEWISE, "piecewise"}, + {AnalyserEquationAst::Type::PIECE, "piece"}, + {AnalyserEquationAst::Type::OTHERWISE, "otherwise"}, + + // Token elements. + + {AnalyserEquationAst::Type::CI, "ci"}, + {AnalyserEquationAst::Type::CN, "cn"}, + + // Qualifier elements. + + {AnalyserEquationAst::Type::DEGREE, "degree"}, + {AnalyserEquationAst::Type::LOGBASE, "logbase"}, + {AnalyserEquationAst::Type::BVAR, "bvar"}, + + // Constants. + + {AnalyserEquationAst::Type::TRUE, "true"}, + {AnalyserEquationAst::Type::FALSE, "false"}, + {AnalyserEquationAst::Type::E, "e"}, + {AnalyserEquationAst::Type::PI, "pi"}, + {AnalyserEquationAst::Type::INF, "inf"}, + {AnalyserEquationAst::Type::NAN, "nan"}}; + +std::string AnalyserEquationAst::typeAsString(Type type) +{ + return typeToString.at(type); +} + void AnalyserEquationAst::setType(Type type) { mPimpl->mType = type; @@ -82,7 +182,7 @@ void AnalyserEquationAst::setValue(const std::string &value) VariablePtr AnalyserEquationAst::variable() const { - return mPimpl->mVariable.lock(); + return mPimpl->mVariable; } void AnalyserEquationAst::setVariable(const VariablePtr &variable) @@ -106,7 +206,7 @@ AnalyserEquationAstPtr AnalyserEquationAst::leftChild() const return mPimpl->mOwnedLeftChild; } - return mPimpl->mLeftChild.lock(); + return mPimpl->mLeftChild; } void AnalyserEquationAst::setLeftChild(const AnalyserEquationAstPtr &leftChild) @@ -121,7 +221,7 @@ AnalyserEquationAstPtr AnalyserEquationAst::rightChild() const return mPimpl->mOwnedRightChild; } - return mPimpl->mRightChild.lock(); + return mPimpl->mRightChild; } void AnalyserEquationAst::setRightChild(const AnalyserEquationAstPtr &rightChild) @@ -130,4 +230,19 @@ void AnalyserEquationAst::setRightChild(const AnalyserEquationAstPtr &rightChild mPimpl->mRightChild = rightChild; } +void AnalyserEquationAst::swapLeftAndRightChildren() +{ + auto oldOwnedLeftChild = mPimpl->mOwnedLeftChild; + auto oldOwnedRightChild = mPimpl->mOwnedRightChild; + + mPimpl->mOwnedLeftChild = oldOwnedRightChild; + mPimpl->mOwnedRightChild = oldOwnedLeftChild; + + auto oldLeftChild = mPimpl->mLeftChild; + auto oldRightChild = mPimpl->mRightChild; + + mPimpl->mLeftChild = oldRightChild; + mPimpl->mRightChild = oldLeftChild; +} + } // namespace libcellml diff --git a/src/analyserequationast_p.h b/src/analyserequationast_p.h index e64fec347..6b9c534be 100644 --- a/src/analyserequationast_p.h +++ b/src/analyserequationast_p.h @@ -22,8 +22,6 @@ limitations under the License. namespace libcellml { -using AnalyserEquationAstWeakPtr = std::weak_ptr; /**< Type definition for weak analyser equation AST pointer. */ - /** * @brief The AnalyserEquationAst::AnalyserEquationAstImpl struct. * @@ -31,14 +29,14 @@ using AnalyserEquationAstWeakPtr = std::weak_ptr; /**< Type */ struct AnalyserEquationAst::AnalyserEquationAstImpl { - AnalyserEquationAst::Type mType = Type::ASSIGNMENT; + AnalyserEquationAst::Type mType = Type::EQUALITY; std::string mValue; - VariableWeakPtr mVariable; + VariablePtr mVariable; AnalyserEquationAstWeakPtr mParent; - AnalyserEquationAstPtr mOwnedLeftChild = nullptr; - AnalyserEquationAstPtr mOwnedRightChild = nullptr; - AnalyserEquationAstWeakPtr mLeftChild; - AnalyserEquationAstWeakPtr mRightChild; + AnalyserEquationAstPtr mOwnedLeftChild; + AnalyserEquationAstPtr mOwnedRightChild; + AnalyserEquationAstPtr mLeftChild; + AnalyserEquationAstPtr mRightChild; void populate(AnalyserEquationAst::Type type, const AnalyserEquationAstPtr &parent); diff --git a/src/analyserexternalvariable.cpp b/src/analyserexternalvariable.cpp index 305f957d6..41a9606ff 100644 --- a/src/analyserexternalvariable.cpp +++ b/src/analyserexternalvariable.cpp @@ -16,9 +16,8 @@ limitations under the License. #include "libcellml/analyserexternalvariable.h" -#include "libcellml/component.h" - #include "analyserexternalvariable_p.h" +#include "commonutils.h" #include "utilities.h" namespace libcellml { @@ -28,24 +27,21 @@ AnalyserExternalVariable::AnalyserExternalVariableImpl::AnalyserExternalVariable { } -std::vector::iterator AnalyserExternalVariable::AnalyserExternalVariableImpl::findDependency(const ModelPtr &model, - const std::string &componentName, - const std::string &variableName) +std::vector::iterator AnalyserExternalVariable::AnalyserExternalVariableImpl::findDependency(const ModelPtr &model, + const std::string &componentName, + const std::string &variableName) { - return std::find_if(mDependencies.begin(), mDependencies.end(), [=](const VariableWeakPtr &v) { - auto variable = v.lock(); - - return (variable != nullptr) - && (owningModel(variable) == model) - && (owningComponent(variable)->name() == componentName) - && (variable->name() == variableName); + return std::find_if(mDependencies.begin(), mDependencies.end(), [=](const auto &v) { + return (owningModel(v) == model) + && (owningComponent(v)->name() == componentName) + && (v->name() == variableName); }); } -std::vector::iterator AnalyserExternalVariable::AnalyserExternalVariableImpl::findDependency(const VariablePtr &variable) +std::vector::iterator AnalyserExternalVariable::AnalyserExternalVariableImpl::findDependency(const VariablePtr &variable) { - return std::find_if(mDependencies.begin(), mDependencies.end(), [=](const VariableWeakPtr &v) { - return v.lock() == variable; + return std::find_if(mDependencies.begin(), mDependencies.end(), [=](const auto &v) { + return v == variable; }); } @@ -66,7 +62,7 @@ AnalyserExternalVariablePtr AnalyserExternalVariable::create(const VariablePtr & VariablePtr AnalyserExternalVariable::variable() const { - return mPimpl->mVariable.lock(); + return mPimpl->mVariable; } bool AnalyserExternalVariable::addDependency(const VariablePtr &variable) @@ -143,11 +139,9 @@ bool AnalyserExternalVariable::containsDependency(const VariablePtr &variable) c VariablePtr AnalyserExternalVariable::dependency(size_t index) const { - if (index < mPimpl->mDependencies.size()) { - return mPimpl->mDependencies.at(index).lock(); - } - - return nullptr; + return (index < mPimpl->mDependencies.size()) ? + mPimpl->mDependencies.at(index) : + nullptr; } VariablePtr AnalyserExternalVariable::dependency(const ModelPtr &model, @@ -156,22 +150,14 @@ VariablePtr AnalyserExternalVariable::dependency(const ModelPtr &model, { auto result = mPimpl->findDependency(model, componentName, variableName); - if (result != mPimpl->mDependencies.end()) { - return (*result).lock(); - } - - return nullptr; + return (result != mPimpl->mDependencies.end()) ? + *result : + nullptr; } std::vector AnalyserExternalVariable::dependencies() const { - std::vector res; - - for (const auto &dependency : mPimpl->mDependencies) { - res.push_back(dependency.lock()); - } - - return res; + return mPimpl->mDependencies; } size_t AnalyserExternalVariable::dependencyCount() const diff --git a/src/analyserexternalvariable_p.h b/src/analyserexternalvariable_p.h index 6b835dd69..d87fdbe19 100644 --- a/src/analyserexternalvariable_p.h +++ b/src/analyserexternalvariable_p.h @@ -20,8 +20,6 @@ limitations under the License. namespace libcellml { -using VariableWeakPtr = std::weak_ptr; /**< Type definition for weak variable pointer. */ - /** * @brief The AnalyserExternalVariable::AnalyserExternalVariableImpl struct. * @@ -29,15 +27,15 @@ using VariableWeakPtr = std::weak_ptr; /**< Type definition for weak v */ struct AnalyserExternalVariable::AnalyserExternalVariableImpl { - VariableWeakPtr mVariable; - std::vector mDependencies; + VariablePtr mVariable; + std::vector mDependencies; explicit AnalyserExternalVariableImpl(const VariablePtr &variable); - std::vector::iterator findDependency(const ModelPtr &model, - const std::string &componentName, - const std::string &variableName); - std::vector::iterator findDependency(const VariablePtr &variable); + std::vector::iterator findDependency(const ModelPtr &model, + const std::string &componentName, + const std::string &variableName); + std::vector::iterator findDependency(const VariablePtr &variable); }; } // namespace libcellml diff --git a/src/analysermodel.cpp b/src/analysermodel.cpp index 2c0be99b9..35788e543 100644 --- a/src/analysermodel.cpp +++ b/src/analysermodel.cpp @@ -38,8 +38,15 @@ AnalyserModel::~AnalyserModel() bool AnalyserModel::isValid() const { - return (mPimpl->mType == AnalyserModel::Type::ALGEBRAIC) - || (mPimpl->mType == AnalyserModel::Type::ODE); + switch (mPimpl->mType) { + case AnalyserModel::Type::ODE: + case AnalyserModel::Type::DAE: + case AnalyserModel::Type::NLA: + case AnalyserModel::Type::ALGEBRAIC: + return true; + default: + return false; + } } AnalyserModel::Type AnalyserModel::type() const @@ -47,6 +54,22 @@ AnalyserModel::Type AnalyserModel::type() const return mPimpl->mType; } +static const std::map typeToString = { + {AnalyserModel::Type::UNKNOWN, "unknown"}, + {AnalyserModel::Type::ODE, "ode"}, + {AnalyserModel::Type::DAE, "dae"}, + {AnalyserModel::Type::NLA, "nla"}, + {AnalyserModel::Type::ALGEBRAIC, "algebraic"}, + {AnalyserModel::Type::INVALID, "invalid"}, + {AnalyserModel::Type::UNDERCONSTRAINED, "underconstrained"}, + {AnalyserModel::Type::OVERCONSTRAINED, "overconstrained"}, + {AnalyserModel::Type::UNSUITABLY_CONSTRAINED, "unsuitably_constrained"}}; + +std::string AnalyserModel::typeAsString(Type type) +{ + return typeToString.at(type); +} + bool AnalyserModel::hasExternalVariables() const { if (!isValid()) { @@ -391,7 +414,7 @@ bool AnalyserModel::areEquivalentVariables(const VariablePtr &variable1, return cacheKey->second; } - bool res = libcellml::areEquivalentVariables(variable1, variable2); + auto res = libcellml::areEquivalentVariables(variable1, variable2); mPimpl->mCachedEquivalentVariables.emplace(key, res); diff --git a/src/analysermodel_p.h b/src/analysermodel_p.h index 9eea7230c..3ed1939d6 100644 --- a/src/analysermodel_p.h +++ b/src/analysermodel_p.h @@ -31,7 +31,7 @@ struct AnalyserModel::AnalyserModelImpl bool mHasExternalVariables = false; - AnalyserVariablePtr mVoi = nullptr; + AnalyserVariablePtr mVoi; std::vector mStates; std::vector mVariables; std::vector mEquations; diff --git a/src/analyservariable.cpp b/src/analyservariable.cpp index 4ee38fb63..3c03d8473 100644 --- a/src/analyservariable.cpp +++ b/src/analyservariable.cpp @@ -16,7 +16,12 @@ limitations under the License. #include "libcellml/analyservariable.h" +#include + +#include "libcellml/variable.h" + #include "analyservariable_p.h" +#include "commonutils.h" namespace libcellml { @@ -29,13 +34,15 @@ void AnalyserVariable::AnalyserVariableImpl::populate(AnalyserVariable::Type typ size_t index, const VariablePtr &initialisingVariable, const VariablePtr &variable, - const AnalyserEquationPtr &equation) + const std::vector &equations) { mType = type; mIndex = index; mInitialisingVariable = initialisingVariable; mVariable = variable; - mEquation = equation; + mComponent = owningComponent(mVariable); + + std::copy(equations.begin(), equations.end(), back_inserter(mEquations)); } AnalyserVariable::AnalyserVariable() @@ -53,6 +60,19 @@ AnalyserVariable::Type AnalyserVariable::type() const return mPimpl->mType; } +static const std::map typeToString = { + {AnalyserVariable::Type::VARIABLE_OF_INTEGRATION, "variable_of_integration"}, + {AnalyserVariable::Type::STATE, "state"}, + {AnalyserVariable::Type::CONSTANT, "constant"}, + {AnalyserVariable::Type::COMPUTED_CONSTANT, "computed_constant"}, + {AnalyserVariable::Type::ALGEBRAIC, "algebraic"}, + {AnalyserVariable::Type::EXTERNAL, "external"}}; + +std::string AnalyserVariable::typeAsString(Type type) +{ + return typeToString.at(type); +} + size_t AnalyserVariable::index() const { return mPimpl->mIndex; @@ -60,17 +80,37 @@ size_t AnalyserVariable::index() const VariablePtr AnalyserVariable::initialisingVariable() const { - return mPimpl->mInitialisingVariable.lock(); + return mPimpl->mInitialisingVariable; } VariablePtr AnalyserVariable::variable() const { - return mPimpl->mVariable.lock(); + return mPimpl->mVariable; +} + +size_t AnalyserVariable::equationCount() const +{ + return mPimpl->mEquations.size(); +} + +std::vector AnalyserVariable::equations() const +{ + std::vector res; + + for (const auto &equation : mPimpl->mEquations) { + res.push_back(equation.lock()); + } + + return res; } -AnalyserEquationPtr AnalyserVariable::equation() const +AnalyserEquationPtr AnalyserVariable::equation(size_t index) const { - return mPimpl->mEquation.lock(); + if (index >= mPimpl->mEquations.size()) { + return {}; + } + + return mPimpl->mEquations[index].lock(); } } // namespace libcellml diff --git a/src/analyservariable_p.h b/src/analyservariable_p.h index 11eb135b0..98f0462a9 100644 --- a/src/analyservariable_p.h +++ b/src/analyservariable_p.h @@ -22,8 +22,6 @@ limitations under the License. namespace libcellml { -using AnalyserEquationWeakPtr = std::weak_ptr; /**< Type definition for weak analyser equation pointer. */ - /** * @brief The AnalyserVariable::AnalyserVariableImpl struct. * @@ -33,16 +31,17 @@ struct AnalyserVariable::AnalyserVariableImpl { AnalyserVariable::Type mType = Type::CONSTANT; size_t mIndex = 0; - VariableWeakPtr mInitialisingVariable; - VariableWeakPtr mVariable; - AnalyserEquationWeakPtr mEquation; + VariablePtr mInitialisingVariable; + VariablePtr mVariable; + ComponentPtr mComponent; + std::vector mEquations; static AnalyserVariablePtr create(); void populate(AnalyserVariable::Type type, size_t index, const VariablePtr &initialisingVariable, const VariablePtr &variable, - const AnalyserEquationPtr &equation); + const std::vector &equations); }; } // namespace libcellml diff --git a/src/annotator.cpp b/src/annotator.cpp index 37ffd9f38..715997d9a 100644 --- a/src/annotator.cpp +++ b/src/annotator.cpp @@ -23,40 +23,22 @@ limitations under the License. #include "libcellml/component.h" #include "libcellml/importsource.h" #include "libcellml/model.h" -#include "libcellml/namedentity.h" -#include "libcellml/printer.h" #include "libcellml/reset.h" #include "libcellml/types.h" #include "libcellml/units.h" #include "libcellml/variable.h" #include "anycellmlelement_p.h" +#include "commonutils.h" #include "internaltypes.h" #include "issue_p.h" #include "logger_p.h" -#include "namespaces.h" #include "utilities.h" namespace libcellml { using ItemList = std::multimap; -static const std::map typeToString = { - {CellmlElementType::COMPONENT, "component"}, - {CellmlElementType::COMPONENT_REF, "component_ref"}, - {CellmlElementType::CONNECTION, "connection"}, - {CellmlElementType::ENCAPSULATION, "encapsulation"}, - {CellmlElementType::IMPORT, "import"}, - {CellmlElementType::MAP_VARIABLES, "map_variables"}, - {CellmlElementType::MODEL, "model"}, - {CellmlElementType::RESET, "reset"}, - {CellmlElementType::RESET_VALUE, "reset_value"}, - {CellmlElementType::TEST_VALUE, "test_value"}, - {CellmlElementType::UNDEFINED, "undefined"}, - {CellmlElementType::UNIT, "unit"}, - {CellmlElementType::UNITS, "units"}, - {CellmlElementType::VARIABLE, "variable"}}; - /** * @brief The Annotator::AnnotatorImpl class. * @@ -82,6 +64,8 @@ class Annotator::AnnotatorImpl: public Logger::LoggerImpl void update(); void buildIdList(); + size_t idCount(); + std::string makeUniqueId(); std::string id(const AnyCellmlElementPtr &item); @@ -97,17 +81,23 @@ class Annotator::AnnotatorImpl: public Logger::LoggerImpl void doSetImportSourceIds(); void doSetUnitsIds(); void doSetUnitsItemIds(); - void doSetComponentIds(const ComponentPtr &parent); - void doSetVariableIds(const ComponentPtr &parent); - void doSetResetIds(const ComponentPtr &parent); - void doSetResetValueIds(const ComponentPtr &parent); - void doSetTestValueIds(const ComponentPtr &parent); void doSetEncapsulationIds(); - void doSetConnectionIds(const ComponentPtr &parent); - void doSetMapVariablesIds(const ComponentPtr &parent); - void doSetComponentEncapsulationIds(const ComponentPtr &parent); void doClearComponentIds(const ComponentPtr &component); + /** + * @brief Set ids for a type that resides within the component tree. + * + * Set ids for a type that resides within the component tree. + * If @p all is @c true it will override whatever is given for @p type + * and set ids to all types. + * If @p all is @c false only ids for the given @p type will be set. + * + * @param component The component in the tree to set ids to. + * @param type The type of id to set. + * @param all Set @c true to ignore the type and apply ids to all types. + */ + void doSetComponentTreeTypeIds(const ComponentPtr &component, CellmlElementType type, bool all = false); + /** * @brief Test to determine if the given @p id at the given @p index exists. * @@ -179,7 +169,7 @@ void Annotator::AnnotatorImpl::listComponentIdsAndItems(const ComponentPtr &comp } // Imports. ImportSourcePtr importSource = component->importSource(); - if (component->isImport() && (importSource != nullptr)) { + if (importSource != nullptr) { id = importSource->id(); if (!id.empty()) { auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); @@ -221,12 +211,10 @@ void Annotator::AnnotatorImpl::listComponentIdsAndItems(const ComponentPtr &comp // Make sure it's also a MAP_VARIABLES item. if (it->second->type() == CellmlElementType::MAP_VARIABLES) { auto testPair = it->second->variablePair(); - if (testPair) { - VariableWeakPtr variable1Weak = testPair->variable1(); - VariableWeakPtr variable2Weak = testPair->variable2(); - if (equals(variable1Weak, weakEquivalentVariable) && equals(variable2Weak, weakVariable)) { - found = true; - } + VariableWeakPtr variable1Weak = testPair->variable1(); + VariableWeakPtr variable2Weak = testPair->variable2(); + if (equals(variable1Weak, weakEquivalentVariable) && equals(variable2Weak, weakVariable)) { + found = true; } } } @@ -252,12 +240,10 @@ void Annotator::AnnotatorImpl::listComponentIdsAndItems(const ComponentPtr &comp // Make sure it's also a CONNECTION item. if (it->second->type() == CellmlElementType::CONNECTION) { auto testPair = it->second->variablePair(); - if (testPair) { - if ((owningComponent(testPair->variable1()) == owningComponent(equivalentVariable)) && (owningComponent(testPair->variable2()) == owningComponent(variable))) { - found = true; - } else if ((owningComponent(testPair->variable2()) == owningComponent(equivalentVariable)) && (owningComponent(testPair->variable1()) == owningComponent(variable))) { - found = true; - } + if ((owningComponent(testPair->variable1()) == owningComponent(equivalentVariable)) && (owningComponent(testPair->variable2()) == owningComponent(variable))) { + found = true; + } else if ((owningComponent(testPair->variable2()) == owningComponent(equivalentVariable)) && (owningComponent(testPair->variable1()) == owningComponent(variable))) { + found = true; } } } @@ -332,7 +318,7 @@ ItemList Annotator::AnnotatorImpl::listIdsAndItems(const ModelPtr &model) idList.insert(std::make_pair(id, convertToWeak(entry))); } } - if (units->isImport() && units->importSource() != nullptr) { + if (units->isImport()) { ImportSourcePtr importSource = units->importSource(); id = importSource->id(); if (!id.empty()) { @@ -366,37 +352,46 @@ AnyCellmlElementPtr Annotator::AnnotatorImpl::convertToWeak(const AnyCellmlEleme converted->mPimpl->mType = type; - if ((type == CellmlElementType::COMPONENT) - || (type == CellmlElementType::COMPONENT_REF)) { + switch (item->type()) { + case CellmlElementType::COMPONENT: + case CellmlElementType::COMPONENT_REF: { ComponentWeakPtr weakComponent = item->component(); converted->mPimpl->mItem = weakComponent; - } else if ((type == CellmlElementType::CONNECTION) - || (type == CellmlElementType::MAP_VARIABLES)) { + } break; + case CellmlElementType::CONNECTION: + case CellmlElementType::MAP_VARIABLES: // We don't store a weak pointer for connections / map variables because // the map is the owner of the VariablePair object. converted->mPimpl->mItem = item->variablePair(); - } else if ((type == CellmlElementType::ENCAPSULATION) - || (type == CellmlElementType::MODEL)) { + break; + case CellmlElementType::ENCAPSULATION: + case CellmlElementType::MODEL: { ModelWeakPtr weakModel = item->model(); converted->mPimpl->mItem = weakModel; - } else if (type == CellmlElementType::IMPORT) { + } break; + case CellmlElementType::IMPORT: { ImportSourceWeakPtr weakImportSource = item->importSource(); converted->mPimpl->mItem = weakImportSource; - } else if ((type == CellmlElementType::RESET) - || (type == CellmlElementType::RESET_VALUE) - || (type == CellmlElementType::TEST_VALUE)) { + } break; + case CellmlElementType::RESET: + case CellmlElementType::RESET_VALUE: + case CellmlElementType::TEST_VALUE: { ResetWeakPtr weakReset = item->reset(); converted->mPimpl->mItem = weakReset; - } else if (type == CellmlElementType::UNIT) { + } break; + case CellmlElementType::UNIT: // We don't store a weak pointer for units item because the map is the // owner of the UnitsItem object. converted->mPimpl->mItem = item->unitsItem(); - } else if (type == CellmlElementType::UNITS) { + break; + case CellmlElementType::UNITS: { UnitsWeakPtr weakUnits = item->units(); converted->mPimpl->mItem = weakUnits; - } else if (type == CellmlElementType::VARIABLE) { + } break; + default: { /* CellmlElementType::VARIABLE */ VariableWeakPtr weakVariable = item->variable(); converted->mPimpl->mItem = weakVariable; + } break; } return converted; @@ -407,61 +402,59 @@ AnyCellmlElementPtr Annotator::AnnotatorImpl::convertToShared(const AnyCellmlEle auto converted = AnyCellmlElement::AnyCellmlElementImpl::create(); auto type = item->type(); - if ((type == CellmlElementType::COMPONENT) - || (type == CellmlElementType::COMPONENT_REF)) { - auto component = std::any_cast(item->mPimpl->mItem).lock(); - if (component != nullptr) { - converted->mPimpl->setComponent(component, type); - } - } else if ((type == CellmlElementType::CONNECTION) - || (type == CellmlElementType::MAP_VARIABLES)) { - // Connections and map variables are not held as weak pointers. - auto variablePair = item->variablePair(); - if ((variablePair != nullptr) && variablePair->isValid()) { - converted->mPimpl->setVariablePair(variablePair, type); - } - } else if ((type == CellmlElementType::ENCAPSULATION) - || (type == CellmlElementType::MODEL)) { - auto model = std::any_cast(item->mPimpl->mItem).lock(); - if (model != nullptr) { - converted->mPimpl->setModel(model, type); - } - } else if (type == CellmlElementType::IMPORT) { - auto importSource = std::any_cast(item->mPimpl->mItem).lock(); - if (importSource != nullptr) { - converted->mPimpl->setImportSource(importSource); - } - } else if (type == CellmlElementType::RESET) { - auto reset = std::any_cast(item->mPimpl->mItem).lock(); - if (reset != nullptr) { - converted->mPimpl->setReset(reset); - } - } else if (type == CellmlElementType::RESET_VALUE) { - auto reset = std::any_cast(item->mPimpl->mItem).lock(); - if (reset != nullptr) { - converted->mPimpl->setResetValue(reset); - } - } else if (type == CellmlElementType::TEST_VALUE) { - auto reset = std::any_cast(item->mPimpl->mItem).lock(); - if (reset != nullptr) { - converted->mPimpl->setTestValue(reset); - } - } else if (type == CellmlElementType::UNIT) { - // Unit items are not held as weak pointers. - auto unitsItem = item->unitsItem(); - if ((unitsItem != nullptr) && unitsItem->isValid()) { - converted->mPimpl->setUnitsItem(unitsItem); - } - } else if (type == CellmlElementType::UNITS) { - auto units = std::any_cast(item->mPimpl->mItem).lock(); - if (units != nullptr) { - converted->mPimpl->setUnits(units); - } - } else if (type == CellmlElementType::VARIABLE) { - auto variable = std::any_cast(item->mPimpl->mItem).lock(); - if (variable != nullptr) { - converted->mPimpl->setVariable(variable); - } + ComponentPtr component; + ImportSourcePtr importSource; + ModelPtr model; + ResetPtr reset; + UnitsPtr units; + UnitsItemPtr unitsItem; + VariablePtr variable; + VariablePairPtr variablePair; + + switch (item->type()) { + case CellmlElementType::COMPONENT: + case CellmlElementType::COMPONENT_REF: + component = std::any_cast(item->mPimpl->mItem).lock(); + converted->mPimpl->setComponent(component, type); + break; + case CellmlElementType::CONNECTION: + case CellmlElementType::MAP_VARIABLES: + variablePair = item->variablePair(); + converted->mPimpl->setVariablePair(variablePair, type); + break; + case CellmlElementType::ENCAPSULATION: + case CellmlElementType::MODEL: + model = std::any_cast(item->mPimpl->mItem).lock(); + converted->mPimpl->setModel(model, type); + break; + case CellmlElementType::IMPORT: + importSource = std::any_cast(item->mPimpl->mItem).lock(); + converted->mPimpl->setImportSource(importSource); + break; + case CellmlElementType::RESET: + reset = std::any_cast(item->mPimpl->mItem).lock(); + converted->mPimpl->setReset(reset); + break; + case CellmlElementType::RESET_VALUE: + reset = std::any_cast(item->mPimpl->mItem).lock(); + converted->mPimpl->setResetValue(reset); + break; + case CellmlElementType::TEST_VALUE: + reset = std::any_cast(item->mPimpl->mItem).lock(); + converted->mPimpl->setTestValue(reset); + break; + case CellmlElementType::UNIT: + unitsItem = item->unitsItem(); + converted->mPimpl->setUnitsItem(unitsItem); + break; + case CellmlElementType::UNITS: + units = std::any_cast(item->mPimpl->mItem).lock(); + converted->mPimpl->setUnits(units); + break; + default: /* CellmlElementType::VARIABLE */ + variable = std::any_cast(item->mPimpl->mItem).lock(); + converted->mPimpl->setVariable(variable); + break; } return converted; @@ -473,6 +466,11 @@ void Annotator::AnnotatorImpl::buildIdList() mIdList = listIdsAndItems(mModel.lock()); } +size_t Annotator::AnnotatorImpl::idCount() +{ + return mIdList.size(); +} + void Annotator::AnnotatorImpl::update() { removeAllIssues(); @@ -584,7 +582,7 @@ std::vector Annotator::duplicateIds() for (auto i = pFunc()->mIdList.begin(), end = pFunc()->mIdList.end(); i != end; i = pFunc()->mIdList.upper_bound(i->first)) { auto next = i; ++next; - if ((next != end) && (next->first == i->first) && !i->first.empty()) { + if ((next != end) && (next->first == i->first)) { ids.push_back(i->first); } } @@ -596,9 +594,7 @@ std::vector Annotator::ids() pFunc()->update(); std::vector ids; for (auto i = pFunc()->mIdList.begin(), end = pFunc()->mIdList.end(); i != end; i = pFunc()->mIdList.upper_bound(i->first)) { - if (!i->first.empty()) { - ids.push_back(i->first); - } + ids.push_back(i->first); } return ids; } @@ -797,8 +793,9 @@ bool Annotator::assignAllIds() { auto model = pFunc()->mModel.lock(); if (model != nullptr) { + size_t initialSize = pFunc()->idCount(); pFunc()->doSetAllAutomaticIds(); - return true; + return pFunc()->idCount() > initialSize; } pFunc()->addIssueNoModel(); return false; @@ -819,270 +816,190 @@ bool Annotator::assignAllIds(ModelPtr &model) bool Annotator::assignIds(CellmlElementType type) { auto model = pFunc()->mModel.lock(); - bool changed = false; - if (model != nullptr) { - changed = true; - switch (type) { - case CellmlElementType::COMPONENT: - for (size_t index = 0; index < model->componentCount(); ++index) { - pFunc()->doSetComponentIds(model->component(index)); - } - break; - case CellmlElementType::COMPONENT_REF: - for (size_t index = 0; index < model->componentCount(); ++index) { - pFunc()->doSetComponentEncapsulationIds(model->component(index)); - } - break; - case CellmlElementType::CONNECTION: - for (size_t index = 0; index < model->componentCount(); ++index) { - pFunc()->doSetConnectionIds(model->component(index)); - } - break; - case CellmlElementType::ENCAPSULATION: - pFunc()->doSetEncapsulationIds(); - break; - case CellmlElementType::IMPORT: - pFunc()->doSetImportSourceIds(); - break; - case CellmlElementType::MAP_VARIABLES: - for (size_t index = 0; index < model->componentCount(); ++index) { - pFunc()->doSetMapVariablesIds(model->component(index)); - } - break; - case CellmlElementType::MODEL: - pFunc()->doSetModelIds(); - break; - case CellmlElementType::RESET: - for (size_t index = 0; index < model->componentCount(); ++index) { - pFunc()->doSetResetIds(model->component(index)); - } - break; - case CellmlElementType::RESET_VALUE: - for (size_t index = 0; index < model->componentCount(); ++index) { - pFunc()->doSetResetValueIds(model->component(index)); - } - break; - case CellmlElementType::TEST_VALUE: - for (size_t index = 0; index < model->componentCount(); ++index) { - pFunc()->doSetTestValueIds(model->component(index)); - } - break; - case CellmlElementType::UNIT: - pFunc()->doSetUnitsItemIds(); - break; - case CellmlElementType::UNITS: - pFunc()->doSetUnitsIds(); - break; - case CellmlElementType::VARIABLE: - for (size_t index = 0; index < model->componentCount(); ++index) { - pFunc()->doSetVariableIds(model->component(index)); - } - break; - case CellmlElementType::MATH: - case CellmlElementType::UNDEFINED: - changed = false; - break; - } - setModel(model); - } else { + if (model == nullptr) { pFunc()->addIssueNoModel(); + return false; } - return changed; -} -void Annotator::AnnotatorImpl::doSetImportSourceIds() -{ - // Import items. - auto model = mModel.lock(); - auto importSources = getAllImportSources(model); - for (auto &importSource : importSources) { - if (importSource->id().empty()) { - auto id = makeUniqueId(); - importSource->setId(id); - auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); - entry->mPimpl->setImportSource(importSource); - mIdList.insert(std::make_pair(id, convertToWeak(entry))); + size_t initialSize = pFunc()->idCount(); + + switch (type) { + case CellmlElementType::COMPONENT: + case CellmlElementType::COMPONENT_REF: + case CellmlElementType::CONNECTION: + case CellmlElementType::MAP_VARIABLES: + case CellmlElementType::RESET: + case CellmlElementType::RESET_VALUE: + case CellmlElementType::TEST_VALUE: + case CellmlElementType::VARIABLE: + for (size_t index = 0; index < model->componentCount(); ++index) { + pFunc()->doSetComponentTreeTypeIds(model->component(index), type); } + break; + case CellmlElementType::ENCAPSULATION: + pFunc()->doSetEncapsulationIds(); + break; + case CellmlElementType::IMPORT: + pFunc()->doSetImportSourceIds(); + break; + case CellmlElementType::MODEL: + pFunc()->doSetModelIds(); + break; + case CellmlElementType::UNIT: + pFunc()->doSetUnitsItemIds(); + break; + case CellmlElementType::UNITS: + pFunc()->doSetUnitsIds(); + break; + case CellmlElementType::MATH: + default: /* case CellmlElementType::UNDEFINED */ + break; } + + setModel(model); + + return pFunc()->idCount() > initialSize; } -void Annotator::AnnotatorImpl::doSetUnitsIds() +bool assignEncapsulationId(const ComponentPtr &component, CellmlElementType type, bool all) { - // Units and unit items. - auto model = mModel.lock(); - for (size_t u = 0; u < model->unitsCount(); ++u) { - auto us = model->units(u); - if (us->id().empty()) { - auto id = makeUniqueId(); - us->setId(id); - auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); - entry->mPimpl->setUnits(us); - mIdList.insert(std::make_pair(id, convertToWeak(entry))); - } - } + bool inHierarchy = std::dynamic_pointer_cast(component->parent()) == nullptr || component->componentCount() > 0; + return ((type == CellmlElementType::COMPONENT_REF) || all) + && component->encapsulationId().empty() + && inHierarchy; } -void Annotator::AnnotatorImpl::doSetUnitsItemIds() +void Annotator::AnnotatorImpl::doSetComponentTreeTypeIds(const ComponentPtr &component, CellmlElementType type, bool all) { - auto model = mModel.lock(); - for (size_t u = 0; u < model->unitsCount(); ++u) { - auto us = model->units(u); - for (size_t i = 0; i < us->unitCount(); i++) { - if (us->unitId(i).empty()) { + if (((type == CellmlElementType::COMPONENT) || all) + && component->id().empty()) { + auto id = makeUniqueId(); + component->setId(id); + auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); + entry->mPimpl->setComponent(component); + mIdList.insert(std::make_pair(id, convertToWeak(entry))); + } + if (assignEncapsulationId(component, type, all)) { + auto id = makeUniqueId(); + component->setEncapsulationId(id); + auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); + entry->mPimpl->setComponentRef(component); + mIdList.insert(std::make_pair(id, convertToWeak(entry))); + } + if ((type == CellmlElementType::VARIABLE) || all) { + for (size_t vIndex = 0; vIndex < component->variableCount(); ++vIndex) { + auto v = component->variable(vIndex); + if (v->id().empty()) { auto id = makeUniqueId(); - us->setUnitId(i, id); + v->setId(id); auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); - entry->mPimpl->setUnitsItem(UnitsItem::create(us, i)); + entry->mPimpl->setVariable(v); mIdList.insert(std::make_pair(id, convertToWeak(entry))); } } } -} - -void Annotator::AnnotatorImpl::doSetComponentIds(const ComponentPtr &parent) -{ - if (parent->id().empty()) { - auto id = makeUniqueId(); - parent->setId(id); - auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); - entry->mPimpl->setComponent(parent); - mIdList.insert(std::make_pair(id, convertToWeak(entry))); + for (size_t vIndex = 0; vIndex < component->variableCount(); ++vIndex) { + auto v1 = component->variable(vIndex); + for (size_t eIndex = 0; eIndex < v1->equivalentVariableCount(); ++eIndex) { + auto v2 = v1->equivalentVariable(eIndex); + if (((type == CellmlElementType::CONNECTION) || all) + && Variable::equivalenceConnectionId(v1, v2).empty()) { + auto id = makeUniqueId(); + Variable::setEquivalenceConnectionId(v1, v2, id); + auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); + entry->mPimpl->setConnection(v1, v2); + mIdList.insert(std::make_pair(id, convertToWeak(entry))); + } + if (((type == CellmlElementType::MAP_VARIABLES) || all) + && Variable::equivalenceMappingId(v1, v2).empty()) { + auto id = makeUniqueId(); + Variable::setEquivalenceMappingId(v1, v2, id); + auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); + entry->mPimpl->setMapVariables(v1, v2); + mIdList.insert(std::make_pair(id, convertToWeak(entry))); + } + } } - for (size_t c = 0; c < parent->componentCount(); ++c) { - if (parent->component(c)->id().empty()) { + for (size_t rIndex = 0; rIndex < component->resetCount(); ++rIndex) { + auto r = component->reset(rIndex); + if (((type == CellmlElementType::RESET) || all) + && r->id().empty()) { auto id = makeUniqueId(); - parent->component(c)->setId(id); + r->setId(id); auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); - entry->mPimpl->setComponent(parent->component(c)); + entry->mPimpl->setReset(r); mIdList.insert(std::make_pair(id, convertToWeak(entry))); } - doSetComponentIds(parent->component(c)); - } -} - -void Annotator::AnnotatorImpl::doSetVariableIds(const ComponentPtr &parent) -{ - for (size_t v = 0; v < parent->variableCount(); ++v) { - if (parent->variable(v)->id().empty()) { + if (((type == CellmlElementType::RESET_VALUE) || all) + && r->resetValueId().empty()) { auto id = makeUniqueId(); - parent->variable(v)->setId(id); + r->setResetValueId(id); auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); - entry->mPimpl->setVariable(parent->variable(v)); + entry->mPimpl->setResetValue(r); mIdList.insert(std::make_pair(id, convertToWeak(entry))); } - } - for (size_t c = 0; c < parent->componentCount(); ++c) { - doSetVariableIds(parent->component(c)); - } -} - -void Annotator::AnnotatorImpl::doSetResetIds(const ComponentPtr &parent) -{ - for (size_t r = 0; r < parent->resetCount(); ++r) { - if (parent->reset(r)->id().empty()) { + if (((type == CellmlElementType::TEST_VALUE) || all) + && r->testValueId().empty()) { auto id = makeUniqueId(); - parent->reset(r)->setId(id); + r->setTestValueId(id); auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); - entry->mPimpl->setReset(parent->reset(r)); + entry->mPimpl->setTestValue(r); mIdList.insert(std::make_pair(id, convertToWeak(entry))); } } - for (size_t c = 0; c < parent->componentCount(); ++c) { - doSetResetIds(parent->component(c)); + + for (size_t c = 0; c < component->componentCount(); ++c) { + doSetComponentTreeTypeIds(component->component(c), type, all); } } -void Annotator::AnnotatorImpl::doSetResetValueIds(const ComponentPtr &parent) +void Annotator::AnnotatorImpl::doSetImportSourceIds() { - for (size_t r = 0; r < parent->resetCount(); ++r) { - if (parent->reset(r)->resetValueId().empty()) { + // Import items. + auto model = mModel.lock(); + auto importSources = getAllImportSources(model); + for (auto &importSource : importSources) { + if (importSource->id().empty()) { auto id = makeUniqueId(); - parent->reset(r)->setResetValueId(id); + importSource->setId(id); auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); - entry->mPimpl->setResetValue(parent->reset(r)); + entry->mPimpl->setImportSource(importSource); mIdList.insert(std::make_pair(id, convertToWeak(entry))); } } - for (size_t c = 0; c < parent->componentCount(); ++c) { - doSetResetValueIds(parent->component(c)); - } } -void Annotator::AnnotatorImpl::doSetTestValueIds(const ComponentPtr &parent) +void Annotator::AnnotatorImpl::doSetUnitsIds() { - for (size_t r = 0; r < parent->resetCount(); ++r) { - if (parent->reset(r)->testValueId().empty()) { + // Units and unit items. + auto model = mModel.lock(); + for (size_t u = 0; u < model->unitsCount(); ++u) { + auto us = model->units(u); + if (us->id().empty()) { auto id = makeUniqueId(); - parent->reset(r)->setTestValueId(id); + us->setId(id); auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); - entry->mPimpl->setTestValue(parent->reset(r)); + entry->mPimpl->setUnits(us); mIdList.insert(std::make_pair(id, convertToWeak(entry))); } } - for (size_t c = 0; c < parent->componentCount(); ++c) { - doSetTestValueIds(parent->component(c)); - } } -void Annotator::AnnotatorImpl::doSetConnectionIds(const ComponentPtr &parent) -{ - for (size_t v = 0; v < parent->variableCount(); ++v) { - auto v1 = parent->variable(v); - for (size_t e = 0; e < v1->equivalentVariableCount(); ++e) { - auto v2 = v1->equivalentVariable(e); - if (Variable::equivalenceConnectionId(v1, v2).empty()) { - auto id = makeUniqueId(); - Variable::setEquivalenceConnectionId(v1, v2, id); - auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); - entry->mPimpl->setConnection(v1, v2); - mIdList.insert(std::make_pair(id, convertToWeak(entry))); - } - } - } - for (size_t c = 0; c < parent->componentCount(); ++c) { - doSetConnectionIds(parent->component(c)); - } -} - -void Annotator::AnnotatorImpl::doSetMapVariablesIds(const ComponentPtr &parent) +void Annotator::AnnotatorImpl::doSetUnitsItemIds() { - for (size_t v = 0; v < parent->variableCount(); ++v) { - auto v1 = parent->variable(v); - for (size_t e = 0; e < v1->equivalentVariableCount(); ++e) { - auto v2 = v1->equivalentVariable(e); - if (Variable::equivalenceMappingId(v1, v2).empty()) { + auto model = mModel.lock(); + for (size_t u = 0; u < model->unitsCount(); ++u) { + auto us = model->units(u); + for (size_t i = 0; i < us->unitCount(); i++) { + if (us->unitId(i).empty()) { auto id = makeUniqueId(); - Variable::setEquivalenceMappingId(v1, v2, id); + us->setUnitId(i, id); auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); - entry->mPimpl->setMapVariables(v1, v2); + entry->mPimpl->setUnitsItem(UnitsItem::create(us, i)); mIdList.insert(std::make_pair(id, convertToWeak(entry))); } } } - for (size_t c = 0; c < parent->componentCount(); ++c) { - doSetMapVariablesIds(parent->component(c)); - } -} - -void Annotator::AnnotatorImpl::doSetComponentEncapsulationIds(const ComponentPtr &parent) -{ - if (parent->encapsulationId().empty() && parent->componentCount() > 0) { - auto id = makeUniqueId(); - parent->setEncapsulationId(id); - auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); - entry->mPimpl->setComponentRef(parent); - mIdList.insert(std::make_pair(id, convertToWeak(entry))); - } - for (size_t c = 0; c < parent->componentCount(); ++c) { - if (parent->component(c)->encapsulationId().empty()) { - auto id = makeUniqueId(); - parent->component(c)->setEncapsulationId(id); - auto entry = AnyCellmlElement::AnyCellmlElementImpl::create(); - entry->mPimpl->setComponentRef(parent->component(c)); - mIdList.insert(std::make_pair(id, convertToWeak(entry))); - } - doSetComponentEncapsulationIds(parent->component(c)); - } } void Annotator::AnnotatorImpl::doSetEncapsulationIds() @@ -1118,14 +1035,7 @@ void Annotator::AnnotatorImpl::doSetAllAutomaticIds() auto model = mModel.lock(); for (size_t index = 0; index < model->componentCount(); ++index) { auto component = model->component(index); - doSetComponentIds(component); - doSetVariableIds(component); - doSetResetIds(component); - doSetResetValueIds(component); - doSetTestValueIds(component); - doSetConnectionIds(component); - doSetMapVariablesIds(component); - doSetComponentEncapsulationIds(component); + doSetComponentTreeTypeIds(component, CellmlElementType::UNDEFINED, true); } doSetEncapsulationIds(); } @@ -1156,200 +1066,232 @@ std::string Annotator::AnnotatorImpl::makeUniqueId() std::string Annotator::AnnotatorImpl::id(const AnyCellmlElementPtr &item) { std::string id; - CellmlElementType type = item->type(); - if (type == CellmlElementType::COMPONENT) { + switch (item->type()) { + case CellmlElementType::COMPONENT: id = item->component()->id(); - } else if (type == CellmlElementType::COMPONENT_REF) { + break; + case CellmlElementType::COMPONENT_REF: id = item->component()->encapsulationId(); - } else if (type == CellmlElementType::CONNECTION) { + break; + case CellmlElementType::CONNECTION: { auto variablePair = item->variablePair(); id = Variable::equivalenceConnectionId(variablePair->variable1(), variablePair->variable2()); - } else if (type == CellmlElementType::ENCAPSULATION) { + } break; + case CellmlElementType::ENCAPSULATION: id = item->model()->encapsulationId(); - } else if (type == CellmlElementType::IMPORT) { + break; + case CellmlElementType::IMPORT: id = item->importSource()->id(); - } else if (type == CellmlElementType::MAP_VARIABLES) { + break; + case CellmlElementType::MAP_VARIABLES: { auto variablePair = item->variablePair(); id = Variable::equivalenceMappingId(variablePair->variable1(), variablePair->variable2()); - } else if (type == CellmlElementType::MODEL) { + } break; + case CellmlElementType::MODEL: id = item->model()->id(); - } else if (type == CellmlElementType::RESET) { + break; + case CellmlElementType::RESET: id = item->reset()->id(); - } else if (type == CellmlElementType::RESET_VALUE) { + break; + case CellmlElementType::RESET_VALUE: id = item->reset()->resetValueId(); - } else if (type == CellmlElementType::TEST_VALUE) { + break; + case CellmlElementType::TEST_VALUE: id = item->reset()->testValueId(); - } else if (type == CellmlElementType::UNIT) { + break; + case CellmlElementType::UNIT: { auto unitItem = item->unitsItem(); id = unitItem->units()->unitId(unitItem->index()); - } else if (type == CellmlElementType::UNITS) { + } break; + case CellmlElementType::UNITS: id = item->units()->id(); - } else if (type == CellmlElementType::VARIABLE) { + break; + default: /* CellmlElementType::VARIABLE */ id = item->variable()->id(); + break; } return id; } void Annotator::AnnotatorImpl::setId(const AnyCellmlElementPtr &item, const std::string &id) { - CellmlElementType type = item->type(); - if (type == CellmlElementType::COMPONENT) { + switch (item->type()) { + case CellmlElementType::COMPONENT: item->component()->setId(id); - } else if (type == CellmlElementType::COMPONENT_REF) { + break; + case CellmlElementType::COMPONENT_REF: item->component()->setEncapsulationId(id); - } else if (type == CellmlElementType::CONNECTION) { + break; + case CellmlElementType::CONNECTION: { auto variablePair = item->variablePair(); Variable::setEquivalenceConnectionId(variablePair->variable1(), variablePair->variable2(), id); - } else if (type == CellmlElementType::ENCAPSULATION) { + } break; + case CellmlElementType::ENCAPSULATION: item->model()->setEncapsulationId(id); - } else if (type == CellmlElementType::IMPORT) { + break; + case CellmlElementType::IMPORT: item->importSource()->setId(id); - } else if (type == CellmlElementType::MAP_VARIABLES) { + break; + case CellmlElementType::MAP_VARIABLES: { auto variablePair = item->variablePair(); Variable::setEquivalenceMappingId(variablePair->variable1(), variablePair->variable2(), id); - } else if (type == CellmlElementType::MODEL) { + } break; + case CellmlElementType::MODEL: item->model()->setId(id); - } else if (type == CellmlElementType::RESET) { + break; + case CellmlElementType::RESET: item->reset()->setId(id); - } else if (type == CellmlElementType::RESET_VALUE) { + break; + case CellmlElementType::RESET_VALUE: item->reset()->setResetValueId(id); - } else if (type == CellmlElementType::TEST_VALUE) { + break; + case CellmlElementType::TEST_VALUE: item->reset()->setTestValueId(id); - } else if (type == CellmlElementType::UNIT) { + break; + case CellmlElementType::UNIT: { auto unitsItem = item->unitsItem(); unitsItem->units()->setUnitId(unitsItem->index(), id); - } else if (type == CellmlElementType::UNITS) { + } break; + case CellmlElementType::UNITS: item->units()->setId(id); - } else if (type == CellmlElementType::VARIABLE) { + break; + default: /* CellmlElementType::VARIABLE */ item->variable()->setId(id); + break; } } bool Annotator::AnnotatorImpl::isOwnedByModel(const AnyCellmlElementPtr &item) const { - bool modelBased = false; - CellmlElementType type = item->type(); auto model = mModel.lock(); - if ((type == CellmlElementType::COMPONENT) - || (type == CellmlElementType::COMPONENT_REF)) { - modelBased = owningModel(item->component()) == model; - } else if ((type == CellmlElementType::CONNECTION) - || (type == CellmlElementType::MAP_VARIABLES)) { + ModelPtr itemModel = nullptr; + switch (item->type()) { + case CellmlElementType::COMPONENT: + case CellmlElementType::COMPONENT_REF: + itemModel = owningModel(item->component()); + break; + case CellmlElementType::CONNECTION: + case CellmlElementType::MAP_VARIABLES: { auto variablePair = item->variablePair(); - modelBased = (owningModel(variablePair->variable1()) == model) - && (owningModel(variablePair->variable2()) == model); - } else if ((type == CellmlElementType::ENCAPSULATION) - || (type == CellmlElementType::MODEL)) { - modelBased = item->model() == model; - } else if (type == CellmlElementType::IMPORT) { - modelBased = true; - } else if (type == CellmlElementType::RESET) { - modelBased = owningModel(item->reset()) == model; - } else if (type == CellmlElementType::RESET_VALUE) { - modelBased = owningModel(item->reset()) == model; - } else if (type == CellmlElementType::TEST_VALUE) { - modelBased = owningModel(item->reset()) == model; - } else if (type == CellmlElementType::UNIT) { - modelBased = owningModel(item->unitsItem()->units()) == model; - } else if (type == CellmlElementType::UNITS) { - modelBased = owningModel(item->units()) == model; - } else if (type == CellmlElementType::VARIABLE) { - modelBased = owningModel(item->variable()) == model; + if (model == owningModel(variablePair->variable1())) { + itemModel = owningModel(variablePair->variable2()); + } + } break; + case CellmlElementType::ENCAPSULATION: + case CellmlElementType::MODEL: + itemModel = item->model(); + break; + case CellmlElementType::IMPORT: + itemModel = model; + break; + case CellmlElementType::RESET: + case CellmlElementType::RESET_VALUE: + case CellmlElementType::TEST_VALUE: + itemModel = owningModel(item->reset()); + break; + case CellmlElementType::UNIT: + // Unit is not actually stored as a weak pointer so we can compare shared pointers directly. + itemModel = owningModel(item->unitsItem()->units()); + break; + case CellmlElementType::UNITS: + itemModel = owningModel(item->units()); + break; + default: /* CellmlElementType::VARIABLE */ + itemModel = owningModel(item->variable()); + break; } - return modelBased; + + return itemModel == model; } bool Annotator::AnnotatorImpl::itemsEqual(const AnyCellmlElementPtr &itemWeak, const AnyCellmlElementPtr &itemShared) { bool itemsEqual = false; auto item = convertToWeak(itemShared); - CellmlElementType type = itemWeak->type(); - if ((type == CellmlElementType::COMPONENT) - || (type == CellmlElementType::COMPONENT_REF)) { + switch (itemWeak->type()) { + case CellmlElementType::COMPONENT: + case CellmlElementType::COMPONENT_REF: itemsEqual = equals(std::any_cast(itemWeak->mPimpl->mItem), std::any_cast(item->mPimpl->mItem)); - } else if ((type == CellmlElementType::CONNECTION) - || (type == CellmlElementType::MAP_VARIABLES)) { + break; + case CellmlElementType::CONNECTION: + case CellmlElementType::MAP_VARIABLES: // Connections and map variables are not stored as a weak pointer so we can compare // shared pointers directly. itemsEqual = itemWeak->variablePair() == item->variablePair(); - } else if ((type == CellmlElementType::ENCAPSULATION) - || (type == CellmlElementType::MODEL)) { + break; + case CellmlElementType::ENCAPSULATION: + case CellmlElementType::MODEL: itemsEqual = equals(std::any_cast(itemWeak->mPimpl->mItem), std::any_cast(item->mPimpl->mItem)); - } else if (type == CellmlElementType::IMPORT) { + break; + case CellmlElementType::IMPORT: itemsEqual = equals(std::any_cast(itemWeak->mPimpl->mItem), std::any_cast(item->mPimpl->mItem)); - } else if ((type == CellmlElementType::RESET) - || (type == CellmlElementType::RESET_VALUE) - || (type == CellmlElementType::TEST_VALUE)) { + break; + case CellmlElementType::RESET: + case CellmlElementType::RESET_VALUE: + case CellmlElementType::TEST_VALUE: itemsEqual = equals(std::any_cast(itemWeak->mPimpl->mItem), std::any_cast(item->mPimpl->mItem)); - } else if (type == CellmlElementType::UNIT) { + break; + case CellmlElementType::UNIT: // Unit is not actually stored as a weak pointer so we can compare shared pointers directly. itemsEqual = itemWeak->unitsItem() == itemShared->unitsItem(); - } else if (type == CellmlElementType::UNITS) { + break; + case CellmlElementType::UNITS: itemsEqual = equals(std::any_cast(itemWeak->mPimpl->mItem), std::any_cast(item->mPimpl->mItem)); - } else if (type == CellmlElementType::VARIABLE) { + break; + default: /* CellmlElementType::VARIABLE */ itemsEqual = equals(std::any_cast(itemWeak->mPimpl->mItem), std::any_cast(item->mPimpl->mItem)); + break; } + return itemsEqual; } bool Annotator::AnnotatorImpl::validItem(const AnyCellmlElementPtr &item) { - CellmlElementType type = item->type(); - if ((type == CellmlElementType::COMPONENT) - || (type == CellmlElementType::COMPONENT_REF)) { - if (item->component() != nullptr) { - return true; - } - } else if ((type == CellmlElementType::CONNECTION) - || (type == CellmlElementType::MAP_VARIABLES)) { + bool result = false; + switch (item->type()) { + case CellmlElementType::COMPONENT: + case CellmlElementType::COMPONENT_REF: + result = item->component() != nullptr; + break; + case CellmlElementType::CONNECTION: + case CellmlElementType::MAP_VARIABLES: { auto variablePair = item->variablePair(); - if ((variablePair != nullptr) - && (variablePair->variable1() != nullptr) - && (variablePair->variable2() != nullptr)) { - return true; - } - } else if ((type == CellmlElementType::ENCAPSULATION) - || (type == CellmlElementType::MODEL)) { - if (item->model() != nullptr) { - return true; - } - } else if (type == CellmlElementType::IMPORT) { - if (item->importSource() != nullptr) { - return true; - } - } else if (type == CellmlElementType::RESET) { - if (item->reset() != nullptr) { - return true; - } - } else if (type == CellmlElementType::RESET_VALUE) { - if (item->reset() != nullptr) { - return true; - } - } else if (type == CellmlElementType::TEST_VALUE) { - if (item->reset() != nullptr) { - return true; - } - } else if (type == CellmlElementType::UNIT) { + result = (variablePair != nullptr) + && (variablePair->variable1() != nullptr) + && (variablePair->variable2() != nullptr); + } break; + case CellmlElementType::ENCAPSULATION: + case CellmlElementType::MODEL: + result = item->model() != nullptr; + break; + case CellmlElementType::IMPORT: + result = item->importSource() != nullptr; + break; + case CellmlElementType::RESET: + case CellmlElementType::RESET_VALUE: + case CellmlElementType::TEST_VALUE: + result = item->reset() != nullptr; + break; + case CellmlElementType::UNIT: { auto unitsItem = item->unitsItem(); - if ((unitsItem != nullptr) && (unitsItem->units() != nullptr)) { - return true; - } - } else if (type == CellmlElementType::UNITS) { - if (item->units() != nullptr) { - return true; - } - } else if (type == CellmlElementType::VARIABLE) { - if (item->variable() != nullptr) { - return true; - } + result = (unitsItem != nullptr) && (unitsItem->units() != nullptr); + } break; + case CellmlElementType::UNITS: + result = item->units() != nullptr; + break; + default: /* CellmlElementType::VARIABLE */ + result = item->variable() != nullptr; + break; } - return false; + + return result; } void Annotator::AnnotatorImpl::removeId(const AnyCellmlElementPtr &item, const std::string &id) diff --git a/src/anycellmlelement_p.h b/src/anycellmlelement_p.h index 986a3f537..c850e8ea3 100644 --- a/src/anycellmlelement_p.h +++ b/src/anycellmlelement_p.h @@ -18,8 +18,6 @@ limitations under the License. #include -#include "internaltypes.h" - namespace libcellml { /** diff --git a/src/api/libcellml/analyser.h b/src/api/libcellml/analyser.h index 79439f31a..765c4a994 100644 --- a/src/api/libcellml/analyser.h +++ b/src/api/libcellml/analyser.h @@ -50,11 +50,11 @@ class LIBCELLML_EXPORT Analyser: public Logger static AnalyserPtr create() noexcept; /** - * @brief Analyse the @c Model. + * @brief Analyse the @ref Model. * - * Analyse the @c Model using this @ref Analyser. + * Analyse the @ref Model using this @ref Analyser. * - * @param model The @c Model to analyse. + * @param model The @ref Model to analyse. */ void analyseModel(const ModelPtr &model); @@ -87,16 +87,16 @@ class LIBCELLML_EXPORT Analyser: public Logger * @overload * * @brief Remove the @ref AnalyserExternalVariable with the given - * @p variableName in the @c Component with the given @p componentName in + * @p variableName in the @ref Component with the given @p componentName in * the given @p model. * * Remove the @ref AnalyserExternalVariable found that matches the given - * @p variableName in the @c Component with the given @p componentName in + * @p variableName in the @ref Component with the given @p componentName in * the given @p model. * - * @param model The pointer to the @c Model which contains the + * @param model The pointer to the @ref Model which contains the * @ref AnalyserExternalVariable to remove. - * @param componentName The name of the @c Component which contains the + * @param componentName The name of the @ref Component which contains the * @ref AnalyserExternalVariable to remove. * @param variableName The name of the @ref AnalyserExternalVariable to * remove. @@ -134,18 +134,18 @@ class LIBCELLML_EXPORT Analyser: public Logger /** * @brief Test to see if the @ref AnalyserExternalVariable with the given - * @p variableName in the @c Component with the given @p componentName in + * @p variableName in the @ref Component with the given @p componentName in * the given @p model is contained within this @ref Analyser. * * Test to see if the @ref AnalyserExternalVariable with the the given - * @p variableName in the @c Component with the given @p componentName in + * @p variableName in the @ref Component with the given @p componentName in * the given @p model is contained within this @ref Analyser. Return @c true * if the @ref AnalyserExternalVariable is in the @ref Analyser and @c false * otherwise. * - * @param model The pointer to the @c Model which contains the + * @param model The pointer to the @ref Model which contains the * @ref AnalyserExternalVariable to test. - * @param componentName The name of the @c Component which contains the + * @param componentName The name of the @ref Component which contains the * @ref AnalyserExternalVariable to test. * @param variableName The name of the @ref AnalyserExternalVariable to test. * @@ -192,19 +192,19 @@ class LIBCELLML_EXPORT Analyser: public Logger * @brief Get the @ref AnalyserExternalVariable with the given @p name. * * Return the @ref AnalyserExternalVariable with the given @p variableName in - * the @c Component with the given @p componentName in the given @p model. + * the @ref Component with the given @p componentName in the given @p model. * If no such @ref AnalyserExternalVariable is contained within the * @ref Analyser, a @c nullptr is returned. * - * @param model The pointer to the @c Model which contains the + * @param model The pointer to the @ref Model which contains the * @ref AnalyserExternalVariable to retrieve. - * @param componentName The name of the @c Component which contains the + * @param componentName The name of the @ref Component which contains the * @ref AnalyserExternalVariable to retrieve. * @param variableName The name of the @ref AnalyserExternalVariable to * retrieve. * * @return The @ref AnalyserExternalVariable with the given @p variableName in - * the @c Component with the given @p componentName in the given @p model on + * the @ref Component with the given @p componentName in the given @p model on * success, @c nullptr on failure. */ AnalyserExternalVariablePtr externalVariable(const ModelPtr &model, @@ -230,7 +230,7 @@ class LIBCELLML_EXPORT Analyser: public Logger * variable of integration, states, variables, equations, and whether it * needs some specific mathematical functions. * - * @return The analysed model for the @c Model analysed by this @ref Analyser. + * @return The analysed model for the @ref Model analysed by this @ref Analyser. */ AnalyserModelPtr model() const; diff --git a/src/api/libcellml/analyserequation.h b/src/api/libcellml/analyserequation.h index 783e0904a..d8a961e6b 100644 --- a/src/api/libcellml/analyserequation.h +++ b/src/api/libcellml/analyserequation.h @@ -34,21 +34,18 @@ class LIBCELLML_EXPORT AnalyserEquation /** * @brief The type of an equation. * - * An equation can be of one of the following types: - * - TRUE_CONSTANT: an equation that computes a true constant, e.g. x = 3; - * - VARIABLE_BASED_CONSTANT: an equation that computes a variable-based - * constant, e.g. x = y+z where y and z are true constants; - * - RATE: an equation that computes a rate, e.g. d(y)/dt = f(t, x); or - * - ALGEBRAIC: an equation that computes an algebraic variable, e.g. - * y = f(x). + * The type of an equation, i.e. whether it is used to compute a true + * constant, a variable-based constant, a rate, an algebraic variable, + * or whether it is placeholder for an external variable. */ enum class Type { - TRUE_CONSTANT, - VARIABLE_BASED_CONSTANT, - RATE, - ALGEBRAIC, - EXTERNAL + TRUE_CONSTANT, /**< An equation that defines a true constant, e.g. x = 3. */ + VARIABLE_BASED_CONSTANT, /**< An equation that describes a variable-based constant, e.g. x = y+z where y and z are true constants. */ + ODE, /**< An equation that describes an ordinary differential equation, e.g. d(y)/dt = f(t, x). */ + NLA, /**< An equation that is used to compute one or several algebraic variables, e.g. x+y = f(z) where x and y are known, but not z. */ + ALGEBRAIC, /**< An equation that is used to compute an algebraic variable, e.g. y = f(x). */ + EXTERNAL /**< A placeholder equation to capture the dependency of the model on an external variable. */ }; ~AnalyserEquation(); /**< Destructor, @private. */ @@ -57,53 +54,145 @@ class LIBCELLML_EXPORT AnalyserEquation AnalyserEquation &operator=(AnalyserEquation rhs) = delete; /**< Assignment operator, @private. */ /** - * @brief Get the @c Type of this @c AnalyserEquation. + * @brief Get the @ref Type of this @ref AnalyserEquation. * - * Return the @c Type of this @c AnalyserEquation. + * Return the @ref Type of this @ref AnalyserEquation. * - * @return The @c Type. + * @return The @ref Type. */ Type type() const; /** - * @brief Get the @c AnalyserEquationAst for this @c AnalyserEquation. + * @brief Get the string version of a @ref Type. * - * Return the @c AnalyserEquationAst for this @c AnalyserEquation. + * Return the string version of a @ref Type. * - * @return The @c AnalyserEquationAst. + * @param type The type for which we want the string version. + * + * @return The string version of the @ref Type. + */ + static std::string typeAsString(Type type); + + /** + * @brief Get the @ref AnalyserEquationAst for this @ref AnalyserEquation. + * + * Return the @ref AnalyserEquationAst for this @ref AnalyserEquation. + * + * @return The @ref AnalyserEquationAst. */ AnalyserEquationAstPtr ast() const; /** - * @brief Get the list of @c AnalyserEquation dependencies. + * @brief Get the number of dependencies for this @ref AnalyserEquation. * - * Return the list of @c AnalyserEquation items which correspond to the - * equations on which this @c AnalyserEquation depends. + * Return the number of dependencies for this @ref AnalyserEquation. * - * @return The list of @c AnalyserEquation dependencies. + * @return The number of dependencies for this @ref AnalyserEquation. + */ + size_t dependencyCount() const; + + /** + * @brief Get the list of @ref AnalyserEquation dependencies. + * + * Return the list of @ref AnalyserEquation items which correspond to the + * equations on which this @ref AnalyserEquation depends. + * + * @return The dependencies as a @c std::vector. */ std::vector dependencies() const; /** - * @brief Test to determine if this @c AnalyserEquation relies on states + * @brief Get the dependency, at @p index, for this @ref AnalyserEquation. + * + * Return the dependency, at @p index, for this @ref AnalyserEquation. + * + * @param index The index of the dependency to return. + * + * @return The dependency, at @p index, on success, @c nullptr on failure. + */ + AnalyserEquationPtr dependency(size_t index) const; + + /** + * @brief Get the index of the NLA system of this @ref AnalyserEquation. + * + * Return the index of the NLA system where this @ref AnalyserEquation is + * used. A value of MAX_SIZE_T indicates that this @ref AnalyserEquation is + * not used in an NLA system. + * + * @return The index of the NLA system. + */ + size_t nlaSystemIndex() const; + + /** + * @brief Get the number of NLA siblings for this @ref AnalyserEquation. + * + * Return the number of NLA siblings for this @ref AnalyserEquation. + * + * @return The number of NLA siblings for this @ref AnalyserEquation. + */ + size_t nlaSiblingCount() const; + + /** + * @brief Get the list of @ref AnalyserEquation NLA siblings. + * + * Return the list of @ref AnalyserEquation items which are NLA siblings of + * this @ref AnalyserEquation. + * + * @return The NLA siblings as a @c std::vector. + */ + std::vector nlaSiblings() const; + + /** + * @brief Get the NLA sibling, at @p index, for this @ref AnalyserEquation. + * + * Return the NLA sibling, at @p index, for this @ref AnalyserEquation. + * + * @param index The index of the NLA sibling to return. + * + * @return The NLA sibling, at @p index, on success, @c nullptr on failure. + */ + AnalyserEquationPtr nlaSibling(size_t index) const; + + /** + * @brief Test to determine if this @ref AnalyserEquation relies on states * and/or rates. * - * Test to determine if this @c AnalyserEquation relies on states and/or + * Test to determine if this @ref AnalyserEquation relies on states and/or * rates, return @c true if it does and @c false otherwise. * - * @return @c true if this @c AnalyserEquation relies on states and/or + * @return @c true if this @ref AnalyserEquation relies on states and/or * rates, @c false otherwise. */ bool isStateRateBased() const; /** - * @brief Get the @c AnalyserVariable for this @c AnalyserEquation. + * @brief Get the number of variables computed by this @ref AnalyserEquation. + * + * Return the number of variables computed by this @ref AnalyserEquation. + * + * @return The number of variables. + */ + size_t variableCount() const; + + /** + * @brief Get the variables computed by this @ref AnalyserEquation. + * + * Return the variables computed by this @ref AnalyserEquation. + * + * @return The variables as a @c std::vector. + */ + std::vector variables() const; + + /** + * @brief Get the variable, at @p index, computed by this @ref AnalyserEquation. + * + * Return the variable, at @p index, computed by this @ref AnalyserEquation. * - * Return the @c AnalyserVariable for this @c AnalyserEquation. + * @param index The index of the variable to return. * - * @return The @c AnalyserVariable. + * @return The variable, at @p index, on success, @c nullptr on failure. */ - AnalyserVariablePtr variable() const; + AnalyserVariablePtr variable(size_t index) const; private: AnalyserEquation(); /**< Constructor, @private. */ diff --git a/src/api/libcellml/analyserequationast.h b/src/api/libcellml/analyserequationast.h index d084206c3..2b805708d 100644 --- a/src/api/libcellml/analyserequationast.h +++ b/src/api/libcellml/analyserequationast.h @@ -18,9 +18,7 @@ limitations under the License. #include "libcellml/analyser.h" -#ifdef NAN -# undef NAN -#endif +#include "libcellml/undefines.h" namespace libcellml { @@ -38,177 +36,104 @@ class LIBCELLML_EXPORT AnalyserEquationAst /** * @brief The type of a node in an abstract syntax tree (AST). * - * A node in an abstract syntax tree (AST) can be of one of the following - * types: - * - Assignment type: - * - ASSIGNMENT: the assignment operator - * - Relational and logical operators: - * - EQ: the equal to function; - * - NEQ: the not equal to function; - * - LT: the less than function; - * - LEQ: the less than or equal to function; - * - GT: the greater than function; - * - GEQ: the greater than or equal to function; - * - AND: the and function; - * - OR: the or function - * - XOR: the exclusive or function; - * - NOT: the not function; - * - Arithmetic operators: - * - PLUS: the plus operator; - * - MINUS: the minus operator; - * - TIMES: the times operator; - * - DIVIDE: the divide operator; - * - POWER: the power operator; - * - ROOT: the root operator; - * - ABS: the absolute value function; - * - EXP: the exponential function; - * - LN: the natural logarithm function; - * - LOG: the common logarithm function; - * - CEILING: the ceiling function; - * - FLOOR: the floor function; - * - MIN: the minimum function; - * - MAX: the maximum function; - * - REM: the remainder function; - * - Calculus elements: - * - DIFF: the differentiation operator; - * - Trigonometric operators: - * - SIN: the sine function; - * - COS: the cosine function; - * - TAN: the tangent function; - * - SEC: the secant function; - * - CSC: the cosecant function; - * - COT: the cotangent function; - * - SINH: the hyperbolic sine function; - * - COSH: the hyperbolic cosine function; - * - TANH: the hyperbolic tangent function; - * - SECH: the hyperbolic secant function; - * - CSCH: the hyperbolic cosecant function; - * - COTH: the hyperbolic cotangent function; - * - ASIN: the arc sine function; - * - ACOS: the arc cosine function; - * - ATAN: the arc tangent function; - * - ASEC: the arc secant function; - * - ACSC: the arc cosecant function; - * - ACOT: the arc cotangent function; - * - ASINH: the arc hyperbolic sine function; - * - ACOSH: the arc hyperbolic cosine function; - * - ATANH: the arc hyperbolic tangent function; - * - ASECH: the arc hyperbolic secant function; - * - ACSCH: the arc hyperbolic cosecant function; - * - ACOTH: the arc hyperbolic cotangent function; - * - Piecewise statement: - * - PIECEWISE: the "piecewise" statement; - * - PIECE: the "piece" part of a "piecewise" statement; - * - OTHERWISE: the "otherwise" part of a "piecewise" statement; - * - Token elements: - * - CI: an identifier (i.e. the name of a model variable); - * - CN: a number; - * - Qualifier elements: - * - DEGREE: the degree of a root operator (it is only used when its - * value is not 2); - * - LOGBASE: the base with respect to which the logarithm is taken; - * - BVAR: the bound variable of a differential equation; - * - Constants: - * - TRUE: the "true" boolean; - * - FALSE: the "false" boolean; - * - E: Euler's number; - * - PI: the π constant; - * - INF: the infinity value; or - * - NAN: the not-a-number value. + * The type of a node in an abstract syntax tree (AST), i.e. whether it is + * an equality type, a relational or a logical operator, an arithmetic + * operator, a calculus element, a trigonometric operator, a piecewise + * statement, a token element, a qualifier element, or a constant. */ enum class Type { - // Assignment. + // Equality. - ASSIGNMENT, + EQUALITY, /**< The equality operator. */ // Relational and logical operators. - EQ, - NEQ, - LT, - LEQ, - GT, - GEQ, - AND, - OR, - XOR, - NOT, + EQ, /**< The equal to operator. */ + NEQ, /**< The not equal to operator. */ + LT, /**< The less than operator. */ + LEQ, /**< The less than or equal to operator. */ + GT, /**< The greater than operator. */ + GEQ, /**< The greater than or equal to operator. */ + AND, /**< The and operator. */ + OR, /**< The or operator. */ + XOR, /**< The exclusive or operator. */ + NOT, /**< The not operator. */ // Arithmetic operators. - PLUS, - MINUS, - TIMES, - DIVIDE, - POWER, - ROOT, - ABS, - EXP, - LN, - LOG, - CEILING, - FLOOR, - MIN, - MAX, - REM, + PLUS, /**< The plus operator. */ + MINUS, /**< The minus operator. */ + TIMES, /**< The times operator. */ + DIVIDE, /**< The divide operator. */ + POWER, /**< The power operator. */ + ROOT, /**< The root operator. */ + ABS, /**< The absolute value function. */ + EXP, /**< The exponential function. */ + LN, /**< The natural logarithm function. */ + LOG, /**< The common logarithm function. */ + CEILING, /**< The ceiling function. */ + FLOOR, /**< The floor function. */ + MIN, /**< The minimum function. */ + MAX, /**< The maximum function. */ + REM, /**< The remainder function. */ // Calculus elements. - DIFF, + DIFF, /**< The differentiation operator. */ // Trigonometric operators. - SIN, - COS, - TAN, - SEC, - CSC, - COT, - SINH, - COSH, - TANH, - SECH, - CSCH, - COTH, - ASIN, - ACOS, - ATAN, - ASEC, - ACSC, - ACOT, - ASINH, - ACOSH, - ATANH, - ASECH, - ACSCH, - ACOTH, + SIN, /**< The sine function. */ + COS, /**< The cosine function. */ + TAN, /**< The tangent function. */ + SEC, /**< The secant function. */ + CSC, /**< The cosecant function. */ + COT, /**< The cotangent function. */ + SINH, /**< The hyperbolic sine function. */ + COSH, /**< The hyperbolic cosine function. */ + TANH, /**< The hyperbolic tangent function. */ + SECH, /**< The hyperbolic secant function. */ + CSCH, /**< The hyperbolic cosecant function. */ + COTH, /**< The hyperbolic cotangent function. */ + ASIN, /**< The arc sine function. */ + ACOS, /**< The arc cosine function. */ + ATAN, /**< The arc tangent function. */ + ASEC, /**< The arc secant function. */ + ACSC, /**< The arc cosecant function. */ + ACOT, /**< The arc cotangent function. */ + ASINH, /**< The arc hyperbolic sine function. */ + ACOSH, /**< The arc hyperbolic cosine function. */ + ATANH, /**< The arc hyperbolic tangent function. */ + ASECH, /**< The arc hyperbolic secant function. */ + ACSCH, /**< The arc hyperbolic cosecant function. */ + ACOTH, /**< The arc hyperbolic cotangent function. */ // Piecewise statement. - PIECEWISE, - PIECE, - OTHERWISE, + PIECEWISE, /**< The "piecewise" statement. */ + PIECE, /**< The "piece" part of a "piecewise" statement. */ + OTHERWISE, /**< The "otherwise" part of a "piecewise" statement. */ // Token elements. - CI, - CN, + CI, /**< An identifier (i.e. the name of a model variable). */ + CN, /**< A number. */ // Qualifier elements. - DEGREE, - LOGBASE, - BVAR, + DEGREE, /**< The degree of a root operator (it is only used when its value is not 2). */ + LOGBASE, /**< The base with respect to which the logarithm is taken. */ + BVAR, /**< The bound variable of a differential equation. */ // Constants. - TRUE, - FALSE, - E, - PI, - INF, - NAN + TRUE, /**< The "true" boolean. */ + FALSE, /**< The "false" boolean. */ + E, /**< Euler's number. */ + PI, /**< The π constant. */ + INF, /**< The infinity value. */ + NAN /**< The not-a-number value. */ }; ~AnalyserEquationAst(); /**< Destructor, @private. */ @@ -231,14 +156,25 @@ class LIBCELLML_EXPORT AnalyserEquationAst static AnalyserEquationAstPtr create() noexcept; /** - * @brief Get the @c Type of this @ref AnalyserEquationAst. + * @brief Get the @ref Type of this @ref AnalyserEquationAst. * - * Return the @c Type of this @ref AnalyserEquationAst. + * Return the @ref Type of this @ref AnalyserEquationAst. * - * @return The @c Type. + * @return The @ref Type. */ Type type() const; + /** + * @brief Get the string version of a @ref Type. + * + * Return the string version of a @ref Type. + * + * @param type The type for which we want the string version. + * + * @return The string version of the @ref Type. + */ + static std::string typeAsString(Type type); + /** * @brief Set the type of this @ref AnalyserEquationAst. * @@ -268,20 +204,20 @@ class LIBCELLML_EXPORT AnalyserEquationAst void setValue(const std::string &value); /** - * @brief Get the @c Variable for this @ref AnalyserEquationAst. + * @brief Get the @ref Variable for this @ref AnalyserEquationAst. * - * Return the @c Variable for this @ref AnalyserEquationAst. + * Return the @ref Variable for this @ref AnalyserEquationAst. * * @return The variable. */ VariablePtr variable() const; /** - * @brief Set the @c Variable for this @ref AnalyserEquationAst. + * @brief Set the @ref Variable for this @ref AnalyserEquationAst. * - * Set the @c Variable for this @ref AnalyserEquationAst. + * Set the @ref Variable for this @ref AnalyserEquationAst. * - * @param variable The @c Variable to be set as the variable for this + * @param variable The @ref Variable to be set as the variable for this * @ref AnalyserEquationAst. */ void setVariable(const VariablePtr &variable); @@ -343,6 +279,13 @@ class LIBCELLML_EXPORT AnalyserEquationAst */ void setRightChild(const AnalyserEquationAstPtr &rightChild); + /** + * @brief Swap the left and right children of this @ref AnalyserEquationAst. + * + * Swap the left and right children of this @ref AnalyserEquationAst. + */ + void swapLeftAndRightChildren(); + private: AnalyserEquationAst(); /**< Constructor, @private. */ diff --git a/src/api/libcellml/analyserexternalvariable.h b/src/api/libcellml/analyserexternalvariable.h index 131e07c46..12e12f719 100644 --- a/src/api/libcellml/analyserexternalvariable.h +++ b/src/api/libcellml/analyserexternalvariable.h @@ -29,7 +29,17 @@ namespace libcellml { * * The AnalyserExternalVariable class is for representing an external variable * in the context of a CellML Analyser, i.e. a variable which is not set or - * computed by this model, but set externally. + * computed by this model, but set externally. It is therefore the + * responsibility of the user to set an external variable (see + * @ref GeneratorProfile::externalVariableMethodTypeDefinitionString and + * @ref GeneratorProfile::setExternalVariableMethodTypeDefinitionString). + * + * Also, say that the analysis of a model fails because the type of one or + * several of its variables could not be determined (i.e. the model is + * underconstrained). To add those variables as external variables will allow + * the analysis to succeed. This is because the analyser will have considered + * those variables as initialised. Once again, it is the responsibility of the + * user to ensure that it all makes sense. */ class LIBCELLML_EXPORT AnalyserExternalVariable { @@ -40,31 +50,31 @@ class LIBCELLML_EXPORT AnalyserExternalVariable AnalyserExternalVariable &operator=(AnalyserExternalVariable rhs) = delete; /**< Assignment operator, @private. */ /** - * @brief Create an @c AnalyserExternalVariable object. + * @brief Create an @ref AnalyserExternalVariable object. * - * Factory method to create an @c AnalyserExternalVariable. Create an + * Factory method to create an @ref AnalyserExternalVariable. Create an * analyser external variable with:: * * auto variable = libcellml::Variable::create(); * auto analyserExternalVariable = libcellml::AnalyserExternalVariable::create(variable); * - * @return A smart pointer to a @c AnalyserExternalVariable object. + * @return A smart pointer to a @ref AnalyserExternalVariable object. */ static AnalyserExternalVariablePtr create(const VariablePtr &variable) noexcept; /** * @brief Get the @ref Variable associated with this - * @c AnalyserExternalVariable. + * @ref AnalyserExternalVariable. * * Return a reference to the @ref Variable associated with this - * @c AnalyserExternalVariable. + * @ref AnalyserExternalVariable. * * @return The @ref Variable associated with this @ref AnalyserExternalVariable. */ VariablePtr variable() const; /** - * @brief Add a dependency to this @c AnalyserExternalVariable. + * @brief Add a dependency to this @ref AnalyserExternalVariable. * * Add the given @ref Variable as a dependency of this * @ref AnalyserExternalVariable, but only if the given @ref Variable or its @@ -92,14 +102,14 @@ class LIBCELLML_EXPORT AnalyserExternalVariable * @overload * * @brief Remove the dependency with the given @p variableName in the - * @c Component with the given @p componentName in the given @p model. + * @ref Component with the given @p componentName in the given @p model. * * Remove the dependency found that matches the given @p variableName in the - * @c Component with the given @p componentName in the given @p model. + * @ref Component with the given @p componentName in the given @p model. * - * @param model The pointer to the @c Model which contains the dependency to + * @param model The pointer to the @ref Model which contains the dependency to * remove. - * @param componentName The name of the @c Component which contains the + * @param componentName The name of the @ref Component which contains the * dependency to remove. * @param variableName The name of the dependency to remove. * @@ -132,18 +142,18 @@ class LIBCELLML_EXPORT AnalyserExternalVariable /** * @brief Test to see if the dependency with the given @p variableName in - * the @c Component with the given @p componentName in the given @p model is + * the @ref Component with the given @p componentName in the given @p model is * contained within this @ref AnalyserExternalVariable's list of dependencies. * * Test to see if the dependency with the the given @p variableName in the - * @c Component with the given @p componentName in the given @p model is + * @ref Component with the given @p componentName in the given @p model is * contained within this @ref AnalyserExternalVariable's list of dependencies. * Return @c true if the dependency is in this @ref AnalyserExternalVariable's * list of dependencies and @c false otherwise. * - * @param model The pointer to the @c Model which contains the dependency to + * @param model The pointer to the @ref Model which contains the dependency to * test. - * @param componentName The name of the @c Component which contains the + * @param componentName The name of the @ref Component which contains the * dependency to test. * @param variableName The name of the dependency to test. * @@ -190,18 +200,18 @@ class LIBCELLML_EXPORT AnalyserExternalVariable * * @brief Get the dependency with the given @p name. * - * Return the dependency with the given @p variableName in the @c Component + * Return the dependency with the given @p variableName in the @ref Component * with the given @p componentName in the given @p model. If no such * dependency is contained within the @ref AnalyserExternalVariable, a * @c nullptr is returned. * - * @param model The pointer to the @c Model which contains the dependency to + * @param model The pointer to the @ref Model which contains the dependency to * retrieve. - * @param componentName The name of the @c Component which contains the + * @param componentName The name of the @ref Component which contains the * dependency to retrieve. * @param variableName The name of the dependency to retrieve. * - * @return The dependency with the given @p variableName in the @c Component + * @return The dependency with the given @p variableName in the @ref Component * with the given @p componentName in the given @p model on success, * @c nullptr on failure. */ @@ -213,9 +223,9 @@ class LIBCELLML_EXPORT AnalyserExternalVariable * @brief Get the list of @ref Variable dependencies. * * Return the list of @ref Variable items on which this - * @c AnalyserExternalVariable depends. + * @ref AnalyserExternalVariable depends. * - * @return The list of @ref Variable dependencies. + * @return The dependencies as a @c std::vector. */ std::vector dependencies() const; diff --git a/src/api/libcellml/analysermodel.h b/src/api/libcellml/analysermodel.h index 6fdb40ee6..dc8c81f9d 100644 --- a/src/api/libcellml/analysermodel.h +++ b/src/api/libcellml/analysermodel.h @@ -34,24 +34,23 @@ class LIBCELLML_EXPORT AnalyserModel /** * @brief The type of a model. * - * A model can be of one of the following types: - * - UNKNOWN: the type of the model is unknown; - * - ALGEBRAIC: the model defines a system of algebraic equations; - * - ODE: the model defines a system of ordinary differential equations; - * - INVALID: the model is invalid; - * - UNDERCONSTRAINED: the model is underconstrainted; - * - OVERCONSTRAINED: the model is overconstrained; or - * - UNSUITABLY_CONSTRAINED: the model is unsuitably constrained. + * The type of a model, i.e. whether it is unknown, invalid, + * underconstrained, overconstrained, or unsuitably constrained, or whether + * it defines a system of algebraic equations, a system of non-linear + * algebraic equations, a system of ordinary differential equations, or + * a system of differential algebraic equations. */ enum class Type { - UNKNOWN, - ALGEBRAIC, - ODE, - INVALID, - UNDERCONSTRAINED, - OVERCONSTRAINED, - UNSUITABLY_CONSTRAINED + UNKNOWN, /**< The type of the model is unknown. */ + ALGEBRAIC, /**< The model defines a system of algebraic equations that can be solved directly. */ + DAE, /**< The model defines a system of differential algebraic equations that require both an external ODE solver (e.g., CVODE) and an external NLA solver (e.g., KINSOL) to solve. */ + INVALID, /**< The model is invalid. */ + NLA, /**< The model defines a system of (potentially non-linear) algebraic equations that require an external NLA solver (e.g., KINSOL) to solve. */ + ODE, /**< The model defines a system of ordinary differential equations that require an external ODE solver (e.g., CVODE) to solve. */ + OVERCONSTRAINED, /**< The model is overconstrained. */ + UNDERCONSTRAINED, /**< The model is underconstrainted. */ + UNSUITABLY_CONSTRAINED /**< The model is unsuitably constrained. */ }; ~AnalyserModel(); /**< Destructor, @private. */ @@ -60,43 +59,54 @@ class LIBCELLML_EXPORT AnalyserModel AnalyserModel &operator=(AnalyserModel rhs) = delete; /**< Assignment operator, @private. */ /** - * @brief Test to determine if @c AnalyserModel is a valid model. + * @brief Test to determine if @ref AnalyserModel is a valid model. * - * Test to determine if @c AnalyserModel is a valid model, return @c true if + * Test to determine if @ref AnalyserModel is a valid model, return @c true if * it is a valid model (i.e. either an algebraic or an ODE model) and * @c false otherwise. * - * @return @c true if @c AnalyserModel is a valid model, @c false otherwise. + * @return @c true if @ref AnalyserModel is a valid model, @c false otherwise. */ bool isValid() const; /** - * @brief Get the @c Type of the @c AnalyserModel. + * @brief Get the @ref Type of the @ref AnalyserModel. * - * Return the @c Type of the @c AnalyserModel. + * Return the @ref Type of the @ref AnalyserModel. * - * @return The @c Type. + * @return The @ref Type. */ Type type() const; /** - * @brief Test to determine if this @c AnalyserModel has external variables. + * @brief Get the string version of a @ref Type. * - * Test to determine if this @c AnalyserModel has external variables, return + * Return the string version of a @ref Type. + * + * @param type The type for which we want the string version. + * + * @return The string version of the @ref Type. + */ + static std::string typeAsString(Type type); + + /** + * @brief Test to determine if this @ref AnalyserModel has external variables. + * + * Test to determine if this @ref AnalyserModel has external variables, return * @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel has external variables, @c false + * @return @c true if @ref AnalyserModel has external variables, @c false * otherwise. */ bool hasExternalVariables() const; /** - * @brief Get the @c Variable of integration. + * @brief Get the @ref Variable of integration. * - * Return the @c Variable of integration of the @c AnalyserModel, in the + * Return the @ref Variable of integration of the @ref AnalyserModel, in the * case of an ODE model, @c nullptr otherwise. * - * @return The @c Variable of integration, if an ODE model, @c nullptr + * @return The @ref Variable of integration, if an ODE model, @c nullptr * otherwise. */ AnalyserVariablePtr voi() const; @@ -104,7 +114,7 @@ class LIBCELLML_EXPORT AnalyserModel /** * @brief Get the number of states. * - * Return the number of states in the @c AnalyserModel. + * Return the number of states in the @ref AnalyserModel. * * @return The number of states. */ @@ -113,7 +123,7 @@ class LIBCELLML_EXPORT AnalyserModel /** * @brief Get the states. * - * Return the states in the @c AnalyserModel. + * Return the states in the @ref AnalyserModel. * * @return The states as a @c std::vector. */ @@ -122,7 +132,7 @@ class LIBCELLML_EXPORT AnalyserModel /** * @brief Get the state at @p index. * - * Return the state at the index @p index for the @c AnalyserModel. + * Return the state at the index @p index for the @ref AnalyserModel. * * @param index The index of the state to return. * @@ -134,7 +144,7 @@ class LIBCELLML_EXPORT AnalyserModel /** * @brief Get the number of variables. * - * Return the number of variables in the @c AnalyserModel. + * Return the number of variables in the @ref AnalyserModel. * * @return The number of variables. */ @@ -143,7 +153,7 @@ class LIBCELLML_EXPORT AnalyserModel /** * @brief Get the variables. * - * Return the variables in the @c AnalyserModel. + * Return the variables in the @ref AnalyserModel. * * @return The variables as a @c std::vector. */ @@ -152,7 +162,7 @@ class LIBCELLML_EXPORT AnalyserModel /** * @brief Get the variable at @p index. * - * Return the variable at the index @p index for the @c AnalyserModel. + * Return the variable at the index @p index for the @ref AnalyserModel. * * @param index The index of the variable to return. * @@ -164,7 +174,7 @@ class LIBCELLML_EXPORT AnalyserModel /** * @brief Get the number of equations. * - * Return the number of equations in the @c AnalyserModel. + * Return the number of equations in the @ref AnalyserModel. * * @return The number of equations. */ @@ -173,7 +183,7 @@ class LIBCELLML_EXPORT AnalyserModel /** * @brief Get the equations. * - * Return the equations in the @c AnalyserModel. + * Return the equations in the @ref AnalyserModel. * * @return The equations as a @c std::vector. */ @@ -182,7 +192,7 @@ class LIBCELLML_EXPORT AnalyserModel /** * @brief Get the equation at @p index. * - * Return the equation at the index @p index for the @c AnalyserModel. + * Return the equation at the index @p index for the @ref AnalyserModel. * * @param index The index of the equation to return. * @@ -192,282 +202,282 @@ class LIBCELLML_EXPORT AnalyserModel AnalyserEquationPtr equation(size_t index) const; /** - * @brief Test to determine if @c AnalyserModel needs an "equal to" + * @brief Test to determine if @ref AnalyserModel needs an "equal to" * function. * - * Test to determine if @c AnalyserModel needs an "equal to" function, + * Test to determine if @ref AnalyserModel needs an "equal to" function, * return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs an "equal to" function, + * @return @c true if @ref AnalyserModel needs an "equal to" function, * @c false otherwise. */ bool needEqFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "not equal to" + * @brief Test to determine if @ref AnalyserModel needs a "not equal to" * function. * - * Test to determine if @c AnalyserModel needs a "not equal to" function, + * Test to determine if @ref AnalyserModel needs a "not equal to" function, * return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "not equal to" function, + * @return @c true if @ref AnalyserModel needs a "not equal to" function, * @c false otherwise. */ bool needNeqFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "less than" + * @brief Test to determine if @ref AnalyserModel needs a "less than" * function. * - * Test to determine if @c AnalyserModel needs a "less than" function, + * Test to determine if @ref AnalyserModel needs a "less than" function, * return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "less than" function, + * @return @c true if @ref AnalyserModel needs a "less than" function, * @c false otherwise. */ bool needLtFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "less than or equal + * @brief Test to determine if @ref AnalyserModel needs a "less than or equal * to" function. * - * Test to determine if @c AnalyserModel needs a "less than or equal to" + * Test to determine if @ref AnalyserModel needs a "less than or equal to" * function, return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "less than or equal to" + * @return @c true if @ref AnalyserModel needs a "less than or equal to" * function, @c false otherwise. */ bool needLeqFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "greater than" + * @brief Test to determine if @ref AnalyserModel needs a "greater than" * function. * - * Test to determine if @c AnalyserModel needs a "greater than" function, + * Test to determine if @ref AnalyserModel needs a "greater than" function, * return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "greater than" function, + * @return @c true if @ref AnalyserModel needs a "greater than" function, * @c false otherwise. */ bool needGtFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "greater than or + * @brief Test to determine if @ref AnalyserModel needs a "greater than or * equal to" function. * - * Test to determine if @c AnalyserModel needs a "greater than or equal to" + * Test to determine if @ref AnalyserModel needs a "greater than or equal to" * function, return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "greater than or equal to" + * @return @c true if @ref AnalyserModel needs a "greater than or equal to" * function, @c false otherwise. */ bool needGeqFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs an "and" function. + * @brief Test to determine if @ref AnalyserModel needs an "and" function. * - * Test to determine if @c AnalyserModel needs an "and" function, return + * Test to determine if @ref AnalyserModel needs an "and" function, return * @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs an "and" function, @c false + * @return @c true if @ref AnalyserModel needs an "and" function, @c false * otherwise. */ bool needAndFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs an "or" function. + * @brief Test to determine if @ref AnalyserModel needs an "or" function. * - * Test to determine if @c AnalyserModel needs an "or" function, return + * Test to determine if @ref AnalyserModel needs an "or" function, return * @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs an "or" function, @c false + * @return @c true if @ref AnalyserModel needs an "or" function, @c false * otherwise. */ bool needOrFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "exclusive or" + * @brief Test to determine if @ref AnalyserModel needs a "exclusive or" * function. * - * Test to determine if @c AnalyserModel needs a "exclusive or" function, + * Test to determine if @ref AnalyserModel needs a "exclusive or" function, * return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "exclusive or" function, + * @return @c true if @ref AnalyserModel needs a "exclusive or" function, * @c false otherwise. */ bool needXorFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "not" function. + * @brief Test to determine if @ref AnalyserModel needs a "not" function. * - * Test to determine if @c AnalyserModel needs a "not" function, return + * Test to determine if @ref AnalyserModel needs a "not" function, return * @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "not" function, @c false + * @return @c true if @ref AnalyserModel needs a "not" function, @c false * otherwise. */ bool needNotFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "minimum" function. + * @brief Test to determine if @ref AnalyserModel needs a "minimum" function. * - * Test to determine if @c AnalyserModel needs a "minimum" function, return + * Test to determine if @ref AnalyserModel needs a "minimum" function, return * @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "minimum" function, @c false + * @return @c true if @ref AnalyserModel needs a "minimum" function, @c false * otherwise. */ bool needMinFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "maximum" function. + * @brief Test to determine if @ref AnalyserModel needs a "maximum" function. * - * Test to determine if @c AnalyserModel needs a "maximum" function, return + * Test to determine if @ref AnalyserModel needs a "maximum" function, return * @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "maximum" function, @c false + * @return @c true if @ref AnalyserModel needs a "maximum" function, @c false * otherwise. */ bool needMaxFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "secant" function. + * @brief Test to determine if @ref AnalyserModel needs a "secant" function. * - * Test to determine if @c AnalyserModel needs a "secant" function, return + * Test to determine if @ref AnalyserModel needs a "secant" function, return * @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "secant" function, @c false + * @return @c true if @ref AnalyserModel needs a "secant" function, @c false * otherwise. */ bool needSecFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "cosecant" function. + * @brief Test to determine if @ref AnalyserModel needs a "cosecant" function. * - * Test to determine if @c AnalyserModel needs a "cosecant" function, return + * Test to determine if @ref AnalyserModel needs a "cosecant" function, return * @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "cosecant" function, @c false + * @return @c true if @ref AnalyserModel needs a "cosecant" function, @c false * otherwise. */ bool needCscFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "cotangent" + * @brief Test to determine if @ref AnalyserModel needs a "cotangent" * function. * - * Test to determine if @c AnalyserModel needs a "cotangent" function, + * Test to determine if @ref AnalyserModel needs a "cotangent" function, * return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "cotangent" function, + * @return @c true if @ref AnalyserModel needs a "cotangent" function, * @c false otherwise. */ bool needCotFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "hyperbolic secant" + * @brief Test to determine if @ref AnalyserModel needs a "hyperbolic secant" * function. * - * Test to determine if @c AnalyserModel needs a "hyperbolic secant" + * Test to determine if @ref AnalyserModel needs a "hyperbolic secant" * function, return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "hyperbolic secant" function, + * @return @c true if @ref AnalyserModel needs a "hyperbolic secant" function, * @c false otherwise. */ bool needSechFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "hyperbolic + * @brief Test to determine if @ref AnalyserModel needs a "hyperbolic * cosecant" function. * - * Test to determine if @c AnalyserModel needs a "hyperbolic cosecant" + * Test to determine if @ref AnalyserModel needs a "hyperbolic cosecant" * function, return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "hyperbolic cosecant" + * @return @c true if @ref AnalyserModel needs a "hyperbolic cosecant" * function, @c false otherwise. */ bool needCschFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs a "hyperbolic + * @brief Test to determine if @ref AnalyserModel needs a "hyperbolic * cotangent" function. * - * Test to determine if @c AnalyserModel needs a "hyperbolic cotangent" + * Test to determine if @ref AnalyserModel needs a "hyperbolic cotangent" * function, return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs a "hyperbolic cotangent" + * @return @c true if @ref AnalyserModel needs a "hyperbolic cotangent" * function, @c false otherwise. */ bool needCothFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs an "arc secant" + * @brief Test to determine if @ref AnalyserModel needs an "arc secant" * function. * - * Test to determine if @c AnalyserModel needs an "arc secant" function, + * Test to determine if @ref AnalyserModel needs an "arc secant" function, * return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs an "arc secant" function, + * @return @c true if @ref AnalyserModel needs an "arc secant" function, * @c false otherwise. */ bool needAsecFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs an "arc cosecant" + * @brief Test to determine if @ref AnalyserModel needs an "arc cosecant" * function. * - * Test to determine if @c AnalyserModel needs an "arc cosecant" function, + * Test to determine if @ref AnalyserModel needs an "arc cosecant" function, * return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs an "arc cosecant" function, + * @return @c true if @ref AnalyserModel needs an "arc cosecant" function, * @c false otherwise. */ bool needAcscFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs an "arc cotangent" + * @brief Test to determine if @ref AnalyserModel needs an "arc cotangent" * function. * - * Test to determine if @c AnalyserModel needs an "arc cotangent" function, + * Test to determine if @ref AnalyserModel needs an "arc cotangent" function, * return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs an "arc cotangent" function, + * @return @c true if @ref AnalyserModel needs an "arc cotangent" function, * @c false otherwise. */ bool needAcotFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs an "arc hyperbolic + * @brief Test to determine if @ref AnalyserModel needs an "arc hyperbolic * secant" function. * - * Test to determine if @c AnalyserModel needs an "arc hyperbolic secant" + * Test to determine if @ref AnalyserModel needs an "arc hyperbolic secant" * function, return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs an "arc hyperbolic secant" + * @return @c true if @ref AnalyserModel needs an "arc hyperbolic secant" * function, @c false otherwise. */ bool needAsechFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs an "arc hyperbolic + * @brief Test to determine if @ref AnalyserModel needs an "arc hyperbolic * cosecant" function. * - * Test to determine if @c AnalyserModel needs an "arc hyperbolic cosecant" + * Test to determine if @ref AnalyserModel needs an "arc hyperbolic cosecant" * function, return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs an "arc hyperbolic cosecant" + * @return @c true if @ref AnalyserModel needs an "arc hyperbolic cosecant" * function, @c false otherwise. */ bool needAcschFunction() const; /** - * @brief Test to determine if @c AnalyserModel needs an "arc hyperbolic + * @brief Test to determine if @ref AnalyserModel needs an "arc hyperbolic * cotangent" function. * - * Test to determine if @c AnalyserModel needs an "arc hyperbolic + * Test to determine if @ref AnalyserModel needs an "arc hyperbolic * cotangent" function, return @c true if it does and @c false otherwise. * - * @return @c true if @c AnalyserModel needs an "arc hyperbolic cotangent" + * @return @c true if @ref AnalyserModel needs an "arc hyperbolic cotangent" * function, @c false otherwise. */ bool needAcothFunction() const; @@ -484,13 +494,13 @@ class LIBCELLML_EXPORT AnalyserModel * and their result cached. So, if you test two variables that were tested * during the analysis then the cached result will be returned otherwise the * two variables will be properly tested and their result cached. This works - * because an @c AnalyserModel always refers to a static version of a - * @c Model. However, this might break if a @c Model is modified after it + * because an @ref AnalyserModel always refers to a static version of a + * @ref Model. However, this might break if a @ref Model is modified after it * has been analysed. * - * @param variable1 The @c Variable to test if it is equivalent to + * @param variable1 The @ref Variable to test if it is equivalent to * @p variable2. - * @param variable2 The @c Variable that is potentially equivalent to + * @param variable2 The @ref Variable that is potentially equivalent to * @p variable1. * * @return @c true if @p variable1 is equivalent to @p variable2 and diff --git a/src/api/libcellml/analyservariable.h b/src/api/libcellml/analyservariable.h index 2022874c2..24d8566d6 100644 --- a/src/api/libcellml/analyservariable.h +++ b/src/api/libcellml/analyservariable.h @@ -24,8 +24,7 @@ namespace libcellml { * @brief The AnalyserVariable class. * * The AnalyserVariable class is for representing a variable in the context of a - * CellML Analyser, i.e. a constant, a computed constant or an algebraic - * variable. + * CellML Analyser. */ class LIBCELLML_EXPORT AnalyserVariable { @@ -35,22 +34,18 @@ class LIBCELLML_EXPORT AnalyserVariable /** * @brief The type of a variable. * - * A variable can be of one of the following types: - * - VARIABLE_OF_INTEGRATION: the variable is the variable of integration; - * - STATE: the variable is a state; - * - CONSTANT: the variable is a constant (e.g. x = 3); - * - COMPUTED_CONSTANT: the variable is a computed constant (e.g. x = 3+5, - * x = 3+z, x = y+z where y and z are constants); or - * - ALGEBRAIC: the variable is an algebraic variable. + * The type of a variable, i.e. whether it is the variable of integration, a + * state, a constant, a computed constant, an algebraic variable, or an + * external variable. */ enum class Type { - VARIABLE_OF_INTEGRATION, - STATE, - CONSTANT, - COMPUTED_CONSTANT, - ALGEBRAIC, - EXTERNAL + VARIABLE_OF_INTEGRATION, /**< The variable is the variable of integration. */ + STATE, /**< The variable is a state. */ + CONSTANT, /**< The variable is a constant (e.g. x = 3). */ + COMPUTED_CONSTANT, /**< The variable is a computed constant (e.g. x = 3+5, x = 3+z, x = y+z where y and z are constants). */ + ALGEBRAIC, /**< The variable is an algebraic variable. */ + EXTERNAL /**< The variable is an external variable, i.e. not computed as part of the model. */ }; ~AnalyserVariable(); /**< Destructor, @private. */ @@ -59,29 +54,40 @@ class LIBCELLML_EXPORT AnalyserVariable AnalyserVariable &operator=(AnalyserVariable rhs) = delete; /**< Assignment operator, @private. */ /** - * @brief Get the @c Type of this @c AnalyserVariable. + * @brief Get the @ref Type of this @ref AnalyserVariable. * - * Return the @c Type of this @c AnalyserVariable. + * Return the @ref Type of this @ref AnalyserVariable. * - * @return The @c Type. + * @return The @ref Type. */ Type type() const; /** - * @brief Get the index of this @c AnalyserVariable. + * @brief Get the string version of a @ref Type. * - * Return the index of this @c AnalyserVariable. + * Return the string version of a @ref Type. + * + * @param type The type for which we want the string version. + * + * @return The string version of the @ref Type. + */ + static std::string typeAsString(Type type); + + /** + * @brief Get the index of this @ref AnalyserVariable. + * + * Return the index of this @ref AnalyserVariable. * * @return The index. */ size_t index() const; /** - * @brief Get the initialising @c Variable for this @c AnalyserVariable. + * @brief Get the initialising @ref Variable for this @ref AnalyserVariable. * - * Return the initialising @c Variable for this @c AnalyserVariable. It is - * used to retrieve the initial value of the @c Variable, if there is one. - * It may or may not be the same @c Variable as the one returned by + * Return the initialising @ref Variable for this @ref AnalyserVariable. It is + * used to retrieve the initial value of the @ref Variable, if there is one. + * It may or may not be the same @ref Variable as the one returned by * @sa variable. If it is not the same (e.g., a state variable is * initialised in one component and computed in another) then the initial * value retrieved from this variable may have to be scaled to account for @@ -92,35 +98,55 @@ class LIBCELLML_EXPORT AnalyserVariable * @sa variable * @sa scalingFactor * - * @return The initialising @c Variable, if there is one, or @c nullptr. + * @return The initialising @ref Variable, if there is one, or @c nullptr. */ VariablePtr initialisingVariable() const; /** - * @brief Get the (primary) @c Variable for this @c AnalyserVariable. + * @brief Get the (primary) @ref Variable for this @ref AnalyserVariable. * - * Return the (primary) @c Variable for this @c AnalyserVariable. Its - * @c Component is the one in which the @c Variable is first defined (in the + * Return the (primary) @ref Variable for this @ref AnalyserVariable. Its + * @ref Component is the one in which the @ref Variable is first defined (in the * case of the variable of integration), initialised (in the case of a * constant) or computed (in the case of a state, computed constant or - * algebraic variable). It may or may not be the same @c Variable as the one + * algebraic variable). It may or may not be the same @ref Variable as the one * returned by @sa initialisingVariable (e.g., a state variable is * initialised in one component and computed in another). * * @sa initialisingVariable * - * @return The @c Variable. + * @return The @ref Variable. */ VariablePtr variable() const; /** - * @brief Get the @c AnalyserEquation for this @c AnalyserVariable. + * @brief Get the number of equations used to compute this @ref AnalyserVariable. + * + * Return the number of equations used to compute this @ref AnalyserVariable. + * + * @return The number of equations used to compute this @ref AnalyserVariable. + */ + size_t equationCount() const; + + /** + * @brief Get the equations used to compute this @ref AnalyserVariable. + * + * Return the equations used to compute this @ref AnalyserVariable. + * + * @return The equations as a @c std::vector. + */ + std::vector equations() const; + + /** + * @brief Get the equation, at @p index, used to compute this @ref AnalyserVariable. + * + * Return the equation, at @p index, used to compute this @ref AnalyserVariable.. * - * Return the @c AnalyserEquation for this @c AnalyserVariable. + * @param index The index of the equation to return. * - * @return The @c AnalyserEquation. + * @return The equation, at @p index, on success, @c nullptr on failure. */ - AnalyserEquationPtr equation() const; + AnalyserEquationPtr equation(size_t index) const; private: AnalyserVariable(); /**< Constructor, @private. */ diff --git a/src/api/libcellml/component.h b/src/api/libcellml/component.h index 97ef1587c..6bc45d969 100644 --- a/src/api/libcellml/component.h +++ b/src/api/libcellml/component.h @@ -403,6 +403,20 @@ class LIBCELLML_EXPORT Component: public ComponentEntity, public ImportedEntity */ bool hasReset(const ResetPtr &reset) const; + /** + * @brief Tests whether this component is defined or not. + * + * Analyses the component and determines if the component is fully defined. + * A fully defined component will have no unresolved imports, all variables + * will have fully defined units, and all math constant units will be fully defined. + * If the component is fully defined it will return @c true, @c false otherwise. + * + * @see Units::isDefined() + * + * @return @c true if the component is fully defined, @c false otherwise. + */ + bool isDefined() const; + /** * @brief Create a clone of this component. * diff --git a/src/api/libcellml/generator.h b/src/api/libcellml/generator.h index 7177efe7d..85d5b71eb 100644 --- a/src/api/libcellml/generator.h +++ b/src/api/libcellml/generator.h @@ -30,8 +30,6 @@ namespace libcellml { */ class LIBCELLML_EXPORT Generator { - friend class Analyser; - public: ~Generator(); /**< Destructor, @private. */ Generator(const Generator &rhs) = delete; /**< Copy constructor, @private. */ @@ -39,74 +37,99 @@ class LIBCELLML_EXPORT Generator Generator &operator=(Generator rhs) = delete; /**< Assignment operator, @private. */ /** - * @brief Create a @c Generator object. + * @brief Create a @ref Generator object. * - * Factory method to create a @c Generator. Create a generator with:: + * Factory method to create a @ref Generator. Create a generator with:: * * @code * auto generator = libcellml::Generator::create(); * @endcode * - * @return A smart pointer to a @c Generator object. + * @return A smart pointer to a @ref Generator object. */ static GeneratorPtr create() noexcept; /** - * @brief Get the @c GeneratorProfile. + * @brief Get the @ref GeneratorProfile. * - * Get the @c GeneratorProfile used by this @c Generator. + * Get the @ref GeneratorProfile used by this @ref Generator. * - * @return The @c GeneratorProfile used. + * @return The @ref GeneratorProfile used. */ GeneratorProfilePtr profile(); /** - * @brief Set the @c GeneratorProfile. + * @brief Set the @ref GeneratorProfile. * - * Set the @c GeneratorProfile to be used by this @c Generator. + * Set the @ref GeneratorProfile to be used by this @ref Generator. * - * @param profile The @c GeneratorProfile to set. + * @param profile The @ref GeneratorProfile to set. */ void setProfile(const GeneratorProfilePtr &profile); /** - * @brief Get the @c AnalyserModel. + * @brief Get the @ref AnalyserModel. * - * Get the @c AnalyserModel used by this @c Generator. + * Get the @ref AnalyserModel used by this @ref Generator. * - * @return The @c AnalyserModel used. + * @return The @ref AnalyserModel used. */ AnalyserModelPtr model(); /** - * @brief Set the @c AnalyserModel. + * @brief Set the @ref AnalyserModel. * - * Set the @c AnalyserModel to be used by this @c Generator. + * Set the @ref AnalyserModel to be used by this @ref Generator. * - * @param model The @c AnalyserModel to set. + * @param model The @ref AnalyserModel to set. */ void setModel(const AnalyserModelPtr &model); /** - * @brief Get the interface code for the @c AnalyserModel. + * @brief Get the interface code for the @ref AnalyserModel. * - * Return the interface code for the @c AnalyserModel, using the - * @c GeneratorProfile. + * Return the interface code for the @ref AnalyserModel, using the + * @ref GeneratorProfile. * * @return The interface code as a @c std::string. */ std::string interfaceCode() const; /** - * @brief Get the implementation code for the @c AnalyserModel. + * @brief Get the implementation code for the @ref AnalyserModel. * - * Return the implementation code for the @c AnalyserModel, using the - * @c GeneratorProfile. + * Return the implementation code for the @ref AnalyserModel, using the + * @ref GeneratorProfile. * * @return The implementation code as a @c std::string. */ std::string implementationCode() const; + /** + * @brief Get the equation code for the given @ref AnalyserEquationAst. + * + * Return the equation code for the given @ref AnalyserEquationAst using @ref GeneratorProfile. + * + * @param ast The @ref AnalyserEquationAst for which we want to generate some code. + * @param generatorProfile The @ref GeneratorProfile, if any, to use to generate the equation code. If no + * @ref GeneratorProfile is provided then the default @ref GeneratorProfile is used. + * + * @return The equation code as a @c std::string. + */ + static std::string equationCode(const AnalyserEquationAstPtr &ast, + const GeneratorProfilePtr &generatorProfile); + + /** + * @brief Get the equation code for the given @ref AnalyserEquationAst using a default @ref GeneratorProfile. + * + * Return the equation code for the given @ref AnalyserEquationAst using a default @ref GeneratorProfile. + * + * @param ast The @ref AnalyserEquationAst for which we want to generate some code. + * + * @return The equation code as a @c std::string. + */ + static std::string equationCode(const AnalyserEquationAstPtr &ast); + private: Generator(); /**< Constructor, @private. */ diff --git a/src/api/libcellml/generatorprofile.h b/src/api/libcellml/generatorprofile.h index 390fa11ad..10335d24d 100644 --- a/src/api/libcellml/generatorprofile.h +++ b/src/api/libcellml/generatorprofile.h @@ -50,87 +50,97 @@ class LIBCELLML_EXPORT GeneratorProfile GeneratorProfile &operator=(GeneratorProfile rhs) = delete; /**< Assignment operator, @private. */ /** - * @brief Create a @c GeneratorProfile object. + * @brief Create a @ref GeneratorProfile object. * - * Factory method to create a @c GeneratorProfile. Create a + * Factory method to create a @ref GeneratorProfile. Create a * generator profile with:: * * GeneratorProfilePtr generatorProfile = libcellml::GeneratorProfile::create(); * - * @return A smart pointer to a @c GeneratorProfile object. + * @return A smart pointer to a @ref GeneratorProfile object. */ static GeneratorProfilePtr create(Profile profile = Profile::C) noexcept; // Whether the profile is official. /** - * @brief Get the @c Profile for this @c GeneratorProfile. + * @brief Get the @ref Profile for this @ref GeneratorProfile. * - * Return the @c Profile for this @c GeneratorProfile. + * Return the @ref Profile for this @ref GeneratorProfile. * - * @return The @c Profile for this @c GeneratorProfile. + * @return The @ref Profile for this @ref GeneratorProfile. */ Profile profile() const; /** - * @brief Set the @c Profile. + * @brief Get the string version of a @ref Profile. * - * Set this @c GeneratorProfile to the given @c Profile . + * Return the string version of a @ref Profile. * - * @param profile The @c Profile to use. + * @param profile The profile for which we want the string version. + * + * @return The string version of the @ref Profile. + */ + static std::string profileAsString(Profile profile); + + /** + * @brief Set the @ref Profile. + * + * Set this @ref GeneratorProfile to the given @ref Profile . + * + * @param profile The @ref Profile to use. */ void setProfile(Profile profile); // Whether the profile requires an interface to be generated. /** - * @brief Test if this @c GeneratorProfile requires an interface to be + * @brief Test if this @ref GeneratorProfile requires an interface to be * generated. * - * Test if this @c GeneratorProfile has an requires an interface to be + * Test if this @ref GeneratorProfile has an requires an interface to be * generated. * - * @return @c true if the @c GeneratorProfile has an requires an interface + * @return @c true if the @ref GeneratorProfile has an requires an interface * to be generated, * @c false otherwise. */ bool hasInterface() const; /** - * @brief Set whether this @c GeneratorProfile has an requires an interface + * @brief Set whether this @ref GeneratorProfile has an requires an interface * to be generated. * - * Set whether this @c GeneratorProfile has an requires an interface to be + * Set whether this @ref GeneratorProfile has an requires an interface to be * generated. * * @param hasInterface A @c bool to determine whether this - * @c GeneratorProfile has an requires an interface to be generated. + * @ref GeneratorProfile has an requires an interface to be generated. */ void setHasInterface(bool hasInterface); - // Assignment. + // Equality. /** - * @brief Get the @c std::string representing the MathML "assignment" + * @brief Get the @c std::string representing the MathML "equality" * operator. * - * Return the @c std::string representing the MathML "assignment" operator. + * Return the @c std::string representing the MathML "equality" operator. * - * @return The @c std::string representing the MathML "assignment" - * operator. + * @return The @c std::string representing the MathML "equality" operator. */ - std::string assignmentString() const; + std::string equalityString() const; /** - * @brief Set the @c std::string representing the MathML "assignment" + * @brief Set the @c std::string representing the MathML "equality" * operator. * - * Set the @c std::string representing the MathML "assignment" operator. + * Set the @c std::string representing the MathML "equality" operator. * - * @param assignmentString The @c std::string representing the MathML - * "assignment" operator. + * @param equalityString The @c std::string representing the MathML + * "equality" operator. */ - void setAssignmentString(const std::string &assignmentString); + void setEqualityString(const std::string &equalityString); // Relational and logical operators. @@ -350,213 +360,213 @@ class LIBCELLML_EXPORT GeneratorProfile void setNotString(const std::string ¬String); /** - * @brief Test if this @c GeneratorProfile has an "equal to" operator. + * @brief Test if this @ref GeneratorProfile has an "equal to" operator. * - * Test if this @c GeneratorProfile has an "equal to" operator. + * Test if this @ref GeneratorProfile has an "equal to" operator. * - * @return @c true if the @c GeneratorProfile has an "equal to" operator, + * @return @c true if the @ref GeneratorProfile has an "equal to" operator, * @c false otherwise. */ bool hasEqOperator() const; /** - * @brief Set whether this @c GeneratorProfile has an "equal to" operator. + * @brief Set whether this @ref GeneratorProfile has an "equal to" operator. * - * Set whether this @c GeneratorProfile has an "equal to" operator. + * Set whether this @ref GeneratorProfile has an "equal to" operator. * * @param hasEqOperator A @c bool to determine whether this - * @c GeneratorProfile has an "equal to" operator. + * @ref GeneratorProfile has an "equal to" operator. */ void setHasEqOperator(bool hasEqOperator); /** - * @brief Test if this @c GeneratorProfile has a "not equal to" operator. + * @brief Test if this @ref GeneratorProfile has a "not equal to" operator. * - * Test if this @c GeneratorProfile has a "not equal to" operator. + * Test if this @ref GeneratorProfile has a "not equal to" operator. * - * @return @c true if the @c GeneratorProfile has a "not equal to" + * @return @c true if the @ref GeneratorProfile has a "not equal to" * operator, @c false otherwise. */ bool hasNeqOperator() const; /** - * @brief Set whether this @c GeneratorProfile has a "not equal to" + * @brief Set whether this @ref GeneratorProfile has a "not equal to" * operator. * - * Set whether this @c GeneratorProfile has a "not equal to" operator. + * Set whether this @ref GeneratorProfile has a "not equal to" operator. * * @param hasNeqOperator A @c bool to determine whether this - * @c GeneratorProfile has a "not equal to" operator. + * @ref GeneratorProfile has a "not equal to" operator. */ void setHasNeqOperator(bool hasNeqOperator); /** - * @brief Test if this @c GeneratorProfile has a "less than" operator. + * @brief Test if this @ref GeneratorProfile has a "less than" operator. * - * Test if this @c GeneratorProfile has a "less than" operator. + * Test if this @ref GeneratorProfile has a "less than" operator. * - * @return @c true if the @c GeneratorProfile has a "less than" operator, + * @return @c true if the @ref GeneratorProfile has a "less than" operator, * @c false otherwise. */ bool hasLtOperator() const; /** - * @brief Set whether this @c GeneratorProfile has a "less than" operator. + * @brief Set whether this @ref GeneratorProfile has a "less than" operator. * - * Set whether this @c GeneratorProfile has a "less than" operator. + * Set whether this @ref GeneratorProfile has a "less than" operator. * * @param hasLtOperator A @c bool to determine whether this - * @c GeneratorProfile has a "less than" operator. + * @ref GeneratorProfile has a "less than" operator. */ void setHasLtOperator(bool hasLtOperator); /** - * @brief Test if this @c GeneratorProfile has a "less than or equal to" + * @brief Test if this @ref GeneratorProfile has a "less than or equal to" * operator. * - * Test if this @c GeneratorProfile has a "less than or equal to" operator. + * Test if this @ref GeneratorProfile has a "less than or equal to" operator. * - * @return @c true if the @c GeneratorProfile has a "less than or equal to" + * @return @c true if the @ref GeneratorProfile has a "less than or equal to" * operator, * @c false otherwise. */ bool hasLeqOperator() const; /** - * @brief Set whether this @c GeneratorProfile has a "less than or equal to" + * @brief Set whether this @ref GeneratorProfile has a "less than or equal to" * operator. * - * Set whether this @c GeneratorProfile has a "less than or equal to" + * Set whether this @ref GeneratorProfile has a "less than or equal to" * operator. * * @param hasLeqOperator A @c bool to determine whether this - * @c GeneratorProfile has a "less than or equal to" operator. + * @ref GeneratorProfile has a "less than or equal to" operator. */ void setHasLeqOperator(bool hasLeqOperator); /** - * @brief Test if this @c GeneratorProfile has a "greater than" operator. + * @brief Test if this @ref GeneratorProfile has a "greater than" operator. * - * Test if this @c GeneratorProfile has a "greater than" operator. + * Test if this @ref GeneratorProfile has a "greater than" operator. * - * @return @c true if the @c GeneratorProfile has a "greater than" operator, + * @return @c true if the @ref GeneratorProfile has a "greater than" operator, * @c false otherwise. */ bool hasGtOperator() const; /** - * @brief Set whether this @c GeneratorProfile has a "greater than" + * @brief Set whether this @ref GeneratorProfile has a "greater than" * operator. * - * Set whether this @c GeneratorProfile has a "greater than" operator. + * Set whether this @ref GeneratorProfile has a "greater than" operator. * * @param hasGtOperator A @c bool to determine whether this - * @c GeneratorProfile has a "greater than" operator. + * @ref GeneratorProfile has a "greater than" operator. */ void setHasGtOperator(bool hasGtOperator); /** - * @brief Test if this @c GeneratorProfile has a "greater than or equal to" + * @brief Test if this @ref GeneratorProfile has a "greater than or equal to" * operator. * - * Test if this @c GeneratorProfile has a "greater than or equal to" operator. + * Test if this @ref GeneratorProfile has a "greater than or equal to" operator. * - * @return @c true if the @c GeneratorProfile has a "greater than or equal + * @return @c true if the @ref GeneratorProfile has a "greater than or equal * to" operator, * @c false otherwise. */ bool hasGeqOperator() const; /** - * @brief Set whether this @c GeneratorProfile has a "greater than or equal + * @brief Set whether this @ref GeneratorProfile has a "greater than or equal * to" operator. * - * Set whether this @c GeneratorProfile has a "greater than or equal to" + * Set whether this @ref GeneratorProfile has a "greater than or equal to" * operator. * * @param hasGeqOperator A @c bool to determine whether this - * @c GeneratorProfile has a "greater than or equal to" operator. + * @ref GeneratorProfile has a "greater than or equal to" operator. */ void setHasGeqOperator(bool hasGeqOperator); /** - * @brief Test if this @c GeneratorProfile has an "and" operator. + * @brief Test if this @ref GeneratorProfile has an "and" operator. * - * Test if this @c GeneratorProfile has an "and" operator. + * Test if this @ref GeneratorProfile has an "and" operator. * - * @return @c true if the @c GeneratorProfile has an "and" operator, + * @return @c true if the @ref GeneratorProfile has an "and" operator, * @c false otherwise. */ bool hasAndOperator() const; /** - * @brief Set whether this @c GeneratorProfile has an "and" operator. + * @brief Set whether this @ref GeneratorProfile has an "and" operator. * - * Set whether this @c GeneratorProfile has an "and" operator. + * Set whether this @ref GeneratorProfile has an "and" operator. * * @param hasAndOperator A @c bool to determine whether this - * @c GeneratorProfile has an "and" operator. + * @ref GeneratorProfile has an "and" operator. */ void setHasAndOperator(bool hasAndOperator); /** - * @brief Test if this @c GeneratorProfile has an "or" operator. + * @brief Test if this @ref GeneratorProfile has an "or" operator. * - * Test if this @c GeneratorProfile has an "or" operator. + * Test if this @ref GeneratorProfile has an "or" operator. * - * @return @c true if the @c GeneratorProfile has an "or" operator, + * @return @c true if the @ref GeneratorProfile has an "or" operator, * @c false otherwise. */ bool hasOrOperator() const; /** - * @brief Set whether this @c GeneratorProfile has an "or" operator. + * @brief Set whether this @ref GeneratorProfile has an "or" operator. * - * Set whether this @c GeneratorProfile has an "or" operator. + * Set whether this @ref GeneratorProfile has an "or" operator. * * @param hasOrOperator A @c bool to determine whether this - * @c GeneratorProfile has an "or" operator. + * @ref GeneratorProfile has an "or" operator. */ void setHasOrOperator(bool hasOrOperator); /** - * @brief Test if this @c GeneratorProfile has a "exclusive or" operator. + * @brief Test if this @ref GeneratorProfile has a "exclusive or" operator. * - * Test if this @c GeneratorProfile has a "exclusive or" operator. + * Test if this @ref GeneratorProfile has a "exclusive or" operator. * - * @return @c true if the @c GeneratorProfile has a "exclusive or" operator, + * @return @c true if the @ref GeneratorProfile has a "exclusive or" operator, * @c false otherwise. */ bool hasXorOperator() const; /** - * @brief Set whether this @c GeneratorProfile has a "exclusive or" + * @brief Set whether this @ref GeneratorProfile has a "exclusive or" * operator. * - * Set whether this @c GeneratorProfile has a "exclusive or" operator. + * Set whether this @ref GeneratorProfile has a "exclusive or" operator. * * @param hasXorOperator A @c bool to determine whether this - * @c GeneratorProfile has a "exclusive or" operator. + * @ref GeneratorProfile has a "exclusive or" operator. */ void setHasXorOperator(bool hasXorOperator); /** - * @brief Test if this @c GeneratorProfile has a "not" operator. + * @brief Test if this @ref GeneratorProfile has a "not" operator. * - * Test if this @c GeneratorProfile has a "not" operator. + * Test if this @ref GeneratorProfile has a "not" operator. * - * @return @c true if the @c GeneratorProfile has a "not" operator, + * @return @c true if the @ref GeneratorProfile has a "not" operator, * @c false otherwise. */ bool hasNotOperator() const; /** - * @brief Set whether this @c GeneratorProfile has a "not" operator. + * @brief Set whether this @ref GeneratorProfile has a "not" operator. * - * Set whether this @c GeneratorProfile has a "not" operator. + * Set whether this @ref GeneratorProfile has a "not" operator. * * @param hasNotOperator A @c bool to determine whether this - * @c GeneratorProfile has a "not" operator. + * @ref GeneratorProfile has a "not" operator. */ void setHasNotOperator(bool hasNotOperator); @@ -895,22 +905,22 @@ class LIBCELLML_EXPORT GeneratorProfile void setRemString(const std::string &remString); /** - * @brief Test if this @c GeneratorProfile has a "power" operator. + * @brief Test if this @ref GeneratorProfile has a "power" operator. * - * Test if this @c GeneratorProfile has a "power" operator. + * Test if this @ref GeneratorProfile has a "power" operator. * - * @return @c true if the @c GeneratorProfile has a "power" operator, + * @return @c true if the @ref GeneratorProfile has a "power" operator, * @c false otherwise. */ bool hasPowerOperator() const; /** - * @brief Set whether this @c GeneratorProfile has a "power" operator. + * @brief Set whether this @ref GeneratorProfile has a "power" operator. * - * Set whether this @c GeneratorProfile has a "power" operator. + * Set whether this @ref GeneratorProfile has a "power" operator. * * @param hasPowerOperator A @c bool to determine whether this - * @c GeneratorProfile has a "power" operator. + * @ref GeneratorProfile has a "power" operator. */ void setHasPowerOperator(bool hasPowerOperator); @@ -1552,22 +1562,22 @@ class LIBCELLML_EXPORT GeneratorProfile void setPiecewiseElseString(const std::string &piecewiseElseString); /** - * @brief Test if this @c GeneratorProfile has a "conditional" operator. + * @brief Test if this @ref GeneratorProfile has a "conditional" operator. * - * Test if this @c GeneratorProfile has a "conditional" operator. + * Test if this @ref GeneratorProfile has a "conditional" operator. * - * @return @c true if the @c GeneratorProfile has a "conditional" operator, + * @return @c true if the @ref GeneratorProfile has a "conditional" operator, * @c false otherwise. */ bool hasConditionalOperator() const; /** - * @brief Set whether this @c GeneratorProfile has a "conditional" operator. + * @brief Set whether this @ref GeneratorProfile has a "conditional" operator. * - * Set whether this @c GeneratorProfile has a "conditional" operator. + * Set whether this @ref GeneratorProfile has a "conditional" operator. * * @param hasConditionalOperator A @c bool to determine whether this - * @c GeneratorProfile has a "conditional" operator. + * @ref GeneratorProfile has a "conditional" operator. */ void setHasConditionalOperator(bool hasConditionalOperator); @@ -3007,6 +3017,225 @@ class LIBCELLML_EXPORT GeneratorProfile void setExternalVariableMethodCallString(bool forDifferentialModel, const std::string &externalVariableMethodCallString); + /** + * @brief Get the @c std::string for the data structure for the root finding + * information object. + * + * Return the @c std::string for the data structure for the root finding + * information object. + * + * @param forDifferentialModel Whether the call to the root finding + * information object is for a differential model, as opposed to an + * algebraic model. + * + * @return The @c std::string for the data structure for the root finding + * information object. + */ + std::string rootFindingInfoObjectString(bool forDifferentialModel) const; + + /** + * @brief Set the @c std::string for the data structure for the root finding + * information object. + * + * Set the @c std::string for the data structure for the root finding + * information object. + * + * @param forDifferentialModel Whether the call to the root finding + * information object is for a differential model, as opposed to an + * algebraic model. + * @param rootFindingInfoObjectString The @c std::string to use for the data + * structure for the root finding information object. + */ + void setRootFindingInfoObjectString(bool forDifferentialModel, + const std::string &rootFindingInfoObjectString); + + /** + * @brief Get the @c std::string for the external NLA solve method. + * + * Return the @c std::string for the external NLA solve method. + * + * @return The @c std::string for the external NLA solve method. + */ + std::string externNlaSolveMethodString() const; + + /** + * @brief Set the @c std::string for the external NLA solve method. + * + * Set the @c std::string for the external NLA solve method. + * + * @param externNlaSolveMethodString The @c std::string to use for the + * external NLA solve method. + */ + void setExternNlaSolveMethodString(const std::string &externNlaSolveMethodString); + + /** + * @brief Get the @c std::string for the call to the find root method. + * + * Return the @c std::string for the call to the find root method. + * + * @param forDifferentialModel Whether the call to the find root method is + * for a differential model, as opposed to an algebraic model. + * + * @return The @c std::string for the call to the find root method. + */ + std::string findRootCallString(bool forDifferentialModel) const; + + /** + * @brief Set the @c std::string for the call to the find root method. + * + * Set the @c std::string for the call to the find root method. To be + * useful, the string should contain the [INDEX] tag, which will be replaced + * with the index of the NLA system for which we want to find the root(s). + * + * @param forDifferentialModel Whether the call to the find root method is + * for a differential model, as opposed to an algebraic model. + * @param findRootCallString The @c std::string to use for the call to the + * find root method. + */ + void setFindRootCallString(bool forDifferentialModel, + const std::string &findRootCallString); + + /** + * @brief Get the @c std::string for the find root method. + * + * Return the @c std::string for the find root method. + * + * @param forDifferentialModel Whether the call to the find root method is + * for a differential model, as opposed to an algebraic model. + * + * @return The @c std::string for the find root method. + */ + std::string findRootMethodString(bool forDifferentialModel) const; + + /** + * @brief Set the @c std::string for the find root method. + * + * Set the @c std::string for the find root method. To be useful, the string + * should contain the [INDEX], [SIZE], and [CODE] tags, which will be + * replaced with the index of the NLA system for which we want to find the + * root(s), the size of the @c u array, and some code to find the root(s), + * respectively. + * + * @sa uArrayString, setUArrayString + * + * @param forDifferentialModel Whether the call to the find root method is + * for a differential model, as opposed to an algebraic model. + * @param findRootMethodString The @c std::string to use for the find root + * method. + */ + void setFindRootMethodString(bool forDifferentialModel, + const std::string &findRootMethodString); + + /** + * @brief Get the @c std::string for the call to the NLA solve method. + * + * Return the @c std::string for the call to the NLA solve method. + * + * @param forDifferentialModel Whether the call to the NLA solve method is + * for a differential model, as opposed to an algebraic model. + * + * @return The @c std::string for the call to the NLA solve method. + */ + std::string nlaSolveCallString(bool forDifferentialModel) const; + + /** + * @brief Set the @c std::string for the call to the NLA solve method. + * + * Set the @c std::string for the call to the NLA solve method. To be + * useful, the string should contain the [INDEX] and [SIZE] tags, which will + * be replaced with the index of the NLA system for which we want to find + * the root(s) and the size of the @c u array, respectively. + * + * @sa uArrayString, setUArrayString + * + * @param forDifferentialModel Whether the call to the NLA solve method is + * for a differential model, as opposed to an algebraic model. + * @param nlaSolveCallString The @c std::string to use for the call to the + * NLA solve method. + */ + void setNlaSolveCallString(bool forDifferentialModel, + const std::string &nlaSolveCallString); + + /** + * @brief Get the @c std::string for the objective function method. + * + * Return the @c std::string for the objective function method. + * + * @param forDifferentialModel Whether the call to the objective function + * method is for a differential model, as opposed to an algebraic model. + * + * @return The @c std::string for the objective function method. + */ + std::string objectiveFunctionMethodString(bool forDifferentialModel) const; + + /** + * @brief Set the @c std::string for the objective function method. + * + * Set the @c std::string for the objective function method. To be useful, + * the string should contain the [INDEX] and [CODE] tags, which will be + * replaced with the index of the NLA system for which we want to find the + * root(s) and some code to compute the objective function, respectively. + * + * @param forDifferentialModel Whether the call to the objective function + * method is for a differential model, as opposed to an algebraic model. + * @param objectiveFunctionMethodString The @c std::string to use for the + * objective function method. + */ + void setObjectiveFunctionMethodString(bool forDifferentialModel, + const std::string &objectiveFunctionMethodString); + + /** + * @brief Get the @c std::string for the @c u array used in the objective + * function and find root methods. + * + * Return the @c std::string for the @c u array used in the objective function + * and find root methods. The @c u array is used to keep track of the value of + * the different unknown variables in a system of non-linear algebraic equations. + * + * @return The @c std::string for the @c u array used in the objective function + * and find root methods. + */ + std::string uArrayString() const; + + /** + * @brief Set the @c std::string for the @c u array used in the objective + * function and find root methods. + * + * Set the @c std::string for the @c u array used in the objective function and + * find root methods. The @c u array is used to keep track of the value of the + * different unknown variables in a system of non-linear algebraic equations. + * + * @param uArrayString The @c std::string to use for the @c u array used in the + * objective function and find root methods. + */ + void setUArrayString(const std::string &uArrayString); + + /** + * @brief Get the @c std::string for the @f array used in the objective + * function and find root methods. + * + * Return the @c std::string for the @f array used in the objective function + * and find root methods. The @c f array is used to keep track of the value of + * the different objective functions in a system of non-linear algebraic equations. + * + * @return The @c std::string for the @f array used in the objective function + * and find root methods. + */ + std::string fArrayString() const; + + /** + * @brief Set the @c std::string for the @f array used in the objective + * function and find root methods. + * + * Set the @c std::string for the @f array used in the objective function and + * find root methods. The @c f array is used to keep track of the value of the + * different objective functions in a system of non-linear algebraic equations. + * + * @param fArrayString The @c std::string to use for the @f array used in the + * objective function and find root methods. + */ + void setFArrayString(const std::string &fArrayString); + /** * @brief Get the @c std::string for the interface to create the states * array. diff --git a/src/api/libcellml/issue.h b/src/api/libcellml/issue.h index 3cb5ccd5b..98eac31a4 100644 --- a/src/api/libcellml/issue.h +++ b/src/api/libcellml/issue.h @@ -21,6 +21,10 @@ limitations under the License. #include "libcellml/exportdefinitions.h" #include "libcellml/types.h" +#ifdef ERROR +# undef ERROR +#endif + namespace libcellml { /** @@ -158,8 +162,11 @@ class LIBCELLML_EXPORT Issue IMPORTER_MISSING_COMPONENT, IMPORTER_MISSING_UNITS, IMPORTER_NULL_MODEL, + IMPORTER_UNDEFINED_MODEL, + IMPORTER_UNRESOLVED_IMPORTS, // Analyser issues: + ANALYSER_EQUATION_NOT_EQUALITY_STATEMENT, ANALYSER_UNITS, ANALYSER_UNLINKED_UNITS, ANALYSER_VARIABLE_INITIALISED_MORE_THAN_ONCE, @@ -169,6 +176,7 @@ class LIBCELLML_EXPORT Issue ANALYSER_ODE_NOT_FIRST_ORDER, ANALYSER_VARIABLE_UNUSED, ANALYSER_STATE_NOT_INITIALISED, + ANALYSER_STATE_RATE_AS_ALGEBRAIC, ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE, ANALYSER_EXTERNAL_VARIABLE_DIFFERENT_MODEL, ANALYSER_EXTERNAL_VARIABLE_VOI, diff --git a/src/api/libcellml/model.h b/src/api/libcellml/model.h index 24a362eba..311e96190 100644 --- a/src/api/libcellml/model.h +++ b/src/api/libcellml/model.h @@ -312,12 +312,21 @@ class LIBCELLML_EXPORT Model: public ComponentEntity /** * @brief Test if this model has unresolved imports. * - * Test if this model has unresolved imports. + * Test all components and units of this model and determine if the imported entities are fully resolved. * - * @return True if the @c Model has unresolved imports and false otherwise. + * @return @c true if the @c Model has unresolved imports and @c false otherwise. */ bool hasUnresolvedImports() const; + /** + * @brief Test if this model is fully defined. + * + * Test all components and units of this model and determine if they are all fully defined. + * + * @return @c true if the @c Model is defined, @c false otherwise. + */ + bool isDefined() const; + /** * @brief Create a clone of this model. * diff --git a/src/configure/libcellmlconfig_p.in.h b/src/api/libcellml/undefines.h similarity index 61% rename from src/configure/libcellmlconfig_p.in.h rename to src/api/libcellml/undefines.h index b9790d4d3..907c24e4c 100644 --- a/src/configure/libcellmlconfig_p.in.h +++ b/src/api/libcellml/undefines.h @@ -14,13 +14,20 @@ See the License for the specific language governing permissions and limitations under the License. */ -#pragma once +// Note that: +// 1) this header file MUST NOT start with #pragma once; and that +// 2) this header file MUST be included LAST by a .cpp/.h file. +// +// This ensures that TRUE, FALSE, and NAN can be safely used in AnalyserEquationAst::Type. -/** - * @brief Define a size type for the zlib uncompress function. - * - * Windows and Unices have opposite ideas about the size type - * required for zlib's uncompress function. This typedef is - * configured to work dependent on the platform. - */ -typedef @UNCOMPRESS_SIZE_TYPE@ UNCOMPRESS_SIZE_TYPE; +#ifdef TRUE +# undef TRUE +#endif + +#ifdef FALSE +# undef FALSE +#endif + +#ifdef NAN +# undef NAN +#endif diff --git a/src/api/libcellml/units.h b/src/api/libcellml/units.h index 3d86d8a44..db0a0e98d 100644 --- a/src/api/libcellml/units.h +++ b/src/api/libcellml/units.h @@ -345,6 +345,17 @@ class LIBCELLML_EXPORT Units: public NamedEntity, public ImportedEntity */ std::string unitAttributeReference(size_t index) const; + /** + * @brief Set the reference attribute for the unit at the given @p index. + * + * Set the reference attribute for the unit at the given @p index. The index must + * be in the range [0, \#unit). + * + * @param index The @c size_t index of the unit in this units to set the reference attribute for. + * @param reference The @c std::string reference to set. + */ + void setUnitAttributeReference(size_t index, const std::string &reference); + /** * @brief Get the prefix attribute for the unit at the given @p index. * @@ -489,11 +500,26 @@ class LIBCELLML_EXPORT Units: public NamedEntity, public ImportedEntity */ bool requiresImports() const; + /** + * @brief Tests whether this units is defined or not. + * + * Analyses the units and determines if the units is fully defined. + * A fully defined units will have no unresolved imports, and no unit that + * is not a base units, standard units, or a units fully defined in the model. + * If the units is fully defined it will return @c true, @c false otherwise. + * + * @return @c true if the units is fully defined, @c false otherwise. + */ + bool isDefined() const; + /** * @brief Return the scaling factor difference between two @ref Units. * * This can be interpreted as `factor`, where units2 = factor*units1. If compatibility checking is - * turned on and the units are not compatible the factor returned is 0.0. + * turned on and the units are not compatible the factor returned is 0.0. Both @p units1 + * and @p units2 must be fully defined, otherwise a scale factor of 0.0 will be returned. + * + * @see Units::isDefined() * * @param units1 The first units to compare. * @param units2 The second units to compare. @@ -510,7 +536,10 @@ class LIBCELLML_EXPORT Units: public NamedEntity, public ImportedEntity * * Two @ref Units are considered to be compatible if they share the same units, * independently of their scaling (e.g. volt and volt are compatible as are - * volt and millivolt). + * volt and millivolt). The units of @p units1 and @p units2 will not be compared if + * either is not fully defined or is @c null. + * + * @see Units::isDefined() * * @param units1 The first units to compare. * @param units2 The second units to compare. diff --git a/src/bindings/interface/analyserequation.i b/src/bindings/interface/analyserequation.i index 887c81394..208290c49 100644 --- a/src/bindings/interface/analyserequation.i +++ b/src/bindings/interface/analyserequation.i @@ -13,18 +13,44 @@ %feature("docstring") libcellml::AnalyserEquation::type "Returns the :enum:`AnalyserEquation::Type` for this :class:`AnalyserEquation` object."; +%feature("docstring") libcellml::AnalyserEquation::typeAsString +"Returns the :enum:`AnalyserEquation::Type` as a string for this :class:`AnalyserEquation` object."; + %feature("docstring") libcellml::AnalyserEquation::ast "Returns the :class:`AnalyserEquationAst` object for this :class:`AnalyserEquation` object."; +%feature("docstring") libcellml::AnalyserEquation::dependencyCount +"Returns the number of dependencies for this :class:`AnalyserEquation` object."; + %feature("docstring") libcellml::AnalyserEquation::dependencies -"Returns the list of :class:`AnalyserEquation` objects which corresponds to the equations on which this -:class:`AnalyserEquation` object depends."; +"Returns the dependencies for this :class:`AnalyserEquation` object."; + +%feature("docstring") libcellml::AnalyserEquation::dependency +"Returns the dependency, at the given index, for this :class:`AnalyserEquation` object."; + +%feature("docstring") libcellml::AnalyserEquation::nlaSystemIndex +"Returns the index of the NLA system for this :class:`AnalyserEquation` object."; + +%feature("docstring") libcellml::AnalyserEquation::nlaSiblingCount +"Returns the number of NLA siblings for this :class:`AnalyserEquation` object."; + +%feature("docstring") libcellml::AnalyserEquation::nlaSiblings +"Returns the NLA siblings for this :class:`AnalyserEquation` object."; + +%feature("docstring") libcellml::AnalyserEquation::nlaSibling +"Returns the NLA sibling, at the given index, for this :class:`AnalyserEquation` object."; %feature("docstring") libcellml::AnalyserEquation::isStateRateBased "Tests if this :class:`AnalyserEquation` object relies on states and/or rates."; +%feature("docstring") libcellml::AnalyserEquation::variableCount +"Returns the number of variables computed by this :class:`AnalyserEquation` object."; + +%feature("docstring") libcellml::AnalyserEquation::variables +"Returns the variables computed by this :class:`AnalyserEquation` object."; + %feature("docstring") libcellml::AnalyserEquation::variable -"Returns the :class:`AnalyserVariable` object for this :class:`AnalyserEquation` object."; +"Returns the variable, at the given index, computed by this :class:`AnalyserEquation` object."; %{ #include "libcellml/analyserequation.h" diff --git a/src/bindings/interface/analyserequationast.i b/src/bindings/interface/analyserequationast.i index 2d5cd1ddd..3d064c706 100644 --- a/src/bindings/interface/analyserequationast.i +++ b/src/bindings/interface/analyserequationast.i @@ -13,6 +13,9 @@ %feature("docstring") libcellml::AnalyserEquationAst::type "Returns the :enum:`AnalyserEquationAst::Type` for this :class:`AnalyserEquationAst` object."; +%feature("docstring") libcellml::AnalyserEquationAst::typeAsString +"Returns the :enum:`AnalyserEquationAst::Type` as a string for this :class:`AnalyserEquationAst` object."; + %feature("docstring") libcellml::AnalyserEquationAst::setType "Sets the :enum:`AnalyserEquationAst::Type` for this :class:`AnalyserEquationAst` object."; @@ -46,6 +49,9 @@ %feature("docstring") libcellml::AnalyserEquationAst::setRightChild "Sets the :class:`AnalyserEquationAst` right child for this :class:`AnalyserEquationAst` object."; +%feature("docstring") libcellml::AnalyserEquationAst::swapLeftAndRightChildren +"Swaps the left and right children of this :class:`AnalyserEquationAst` object."; + %{ #include "libcellml/analyserequationast.h" %} diff --git a/src/bindings/interface/analysermodel.i b/src/bindings/interface/analysermodel.i index c6a7a8bf3..704d3e2f4 100644 --- a/src/bindings/interface/analysermodel.i +++ b/src/bindings/interface/analysermodel.i @@ -16,6 +16,9 @@ %feature("docstring") libcellml::AnalyserModel::type "Returns the :enum:`AnalyserModel::Type`."; +%feature("docstring") libcellml::AnalyserModel::typeAsString +"Returns the :enum:`AnalyserModel::Type` as a string."; + %feature("docstring") libcellml::AnalyserModel::hasExternalVariables "Tests if this :class:`AnalyserModel` object has external variables."; diff --git a/src/bindings/interface/analyservariable.i b/src/bindings/interface/analyservariable.i index 97a00ab77..12ef9550b 100644 --- a/src/bindings/interface/analyservariable.i +++ b/src/bindings/interface/analyservariable.i @@ -12,6 +12,9 @@ %feature("docstring") libcellml::AnalyserVariable::type "Returns the :enum:`AnalyserVariable::Type`."; +%feature("docstring") libcellml::AnalyserVariable::typeAsString +"Returns the :enum:`AnalyserVariable::Type` as a string."; + %feature("docstring") libcellml::AnalyserVariable::index "Returns the index."; @@ -21,8 +24,14 @@ %feature("docstring") libcellml::AnalyserVariable::variable "Returns the :class:`Variable`."; +%feature("docstring") libcellml::AnalyserVariable::equationCount +"Returns the number of equations used to compute this :class:`AnalyserVariable` object."; + +%feature("docstring") libcellml::AnalyserVariable::equations +"Returns the equations used to compute this :class:`AnalyserVariable` object."; + %feature("docstring") libcellml::AnalyserVariable::equation -"Returns the :class:`AnalyserEquation`."; +"Returns the equation, at the given index, used to compute this :class:`AnalyserVariable` object."; %{ #include "libcellml/analyservariable.h" diff --git a/src/bindings/interface/component.i b/src/bindings/interface/component.i index d4a7a1e6d..ffec6ccc9 100644 --- a/src/bindings/interface/component.i +++ b/src/bindings/interface/component.i @@ -97,6 +97,9 @@ range for the index is [0, #resets)."; resets. Returns True if the :param: reset is in this component's resets and False otherwise."; +%feature("docstring") libcellml::Component::isDefined +"Tests if this component is defined."; + %feature("docstring") libcellml::Component::clone "Create a copy of this component."; diff --git a/src/bindings/interface/generator.i b/src/bindings/interface/generator.i index 96e4f4fa8..95c710249 100644 --- a/src/bindings/interface/generator.i +++ b/src/bindings/interface/generator.i @@ -29,6 +29,9 @@ %feature("docstring") libcellml::Generator::implementationCode "Returns the implementation code."; +%feature("docstring") libcellml::Generator::equationCode +"Returns the equation code for a given equation AST."; + %{ #include "libcellml/generator.h" %} diff --git a/src/bindings/interface/generatorprofile.i b/src/bindings/interface/generatorprofile.i index d8d41c907..603ccd5b0 100644 --- a/src/bindings/interface/generatorprofile.i +++ b/src/bindings/interface/generatorprofile.i @@ -13,6 +13,9 @@ %feature("docstring") libcellml::GeneratorProfile::profile "Returns the :enum:`GeneratorProfile::Profile` for this :class:`GeneratorProfile`."; +%feature("docstring") libcellml::GeneratorProfile::profileAsString +"Returns the :enum:`GeneratorProfile::Profile` as a string for this :class:`GeneratorProfile`."; + %feature("docstring") libcellml::GeneratorProfile::setProfile "Sets the :enum:`GeneratorProfile::Profile` for this :class:`GeneratorProfile`."; @@ -22,11 +25,11 @@ %feature("docstring") libcellml::GeneratorProfile::setHasInterface "Sets whether this :class:`GeneratorProfile` requires an interface."; -%feature("docstring") libcellml::GeneratorProfile::assignmentString -"Returns the string representing the MathML \"assigment\" operator."; +%feature("docstring") libcellml::GeneratorProfile::equalityString +"Returns the string representing the MathML \"equality\" operator."; -%feature("docstring") libcellml::GeneratorProfile::setAssignmentString -"Sets the string representing the MathML \"assigment\" operator."; +%feature("docstring") libcellml::GeneratorProfile::setEqualityString +"Sets the string representing the MathML \"equality\" operator."; %feature("docstring") libcellml::GeneratorProfile::eqString "Returns the string representing the MathML \"equal to\" operator."; @@ -822,6 +825,54 @@ and units of a variable respectively."; %feature("docstring") libcellml::GeneratorProfile::setExternalVariableMethodCallString "Sets the string for the call to the external variable method."; +%feature("docstring") libcellml::GeneratorProfile::rootFindingInfoObjectString +"Returns the string for the data structure for the root finding information object."; + +%feature("docstring") libcellml::GeneratorProfile::setRootFindingInfoObjectString +"Sets the string for the data structure for the root finding information object."; + +%feature("docstring") libcellml::GeneratorProfile::externNlaSolveMethodString +"Returns the string for the external NLA solve method."; + +%feature("docstring") libcellml::GeneratorProfile::setExternNlaSolveMethodString +"Sets the string for the external NLA solve method."; + +%feature("docstring") libcellml::GeneratorProfile::findRootCallString +"Returns the string for the call to the find root method."; + +%feature("docstring") libcellml::GeneratorProfile::setFindRootCallString +"Sets the string for the call to the find root method."; + +%feature("docstring") libcellml::GeneratorProfile::findRootMethodString +"Returns the string for the find root method."; + +%feature("docstring") libcellml::GeneratorProfile::setFindRootMethodString +"Sets the string for the find root method."; + +%feature("docstring") libcellml::GeneratorProfile::nlaSolveCallString +"Returns the string for the call to the NLA solve method."; + +%feature("docstring") libcellml::GeneratorProfile::setNlaSolveCallString +"Sets the string for the call to the NLA solve method."; + +%feature("docstring") libcellml::GeneratorProfile::objectiveFunctionMethodString +"Returns the string for the objective function method."; + +%feature("docstring") libcellml::GeneratorProfile::setObjectiveFunctionMethodString +"Sets the string for the objective function method."; + +%feature("docstring") libcellml::GeneratorProfile::uArrayString +"Returns the string for the u array used in the objective function and find root methods."; + +%feature("docstring") libcellml::GeneratorProfile::setUArrayString +"Sets the string for the u array used in the objective function and find root methods."; + +%feature("docstring") libcellml::GeneratorProfile::fArrayString +"Returns the string for the f array used in the objective function and find root methods."; + +%feature("docstring") libcellml::GeneratorProfile::setFArrayString +"Sets the string for the f array used in the objective function and find root methods."; + %feature("docstring") libcellml::GeneratorProfile::setReturnCreatedArrayString "Sets the string for returning a created array. To be useful, the string should contain the tag, which will be replaced with the size of the array to be created."; diff --git a/src/bindings/interface/model.i b/src/bindings/interface/model.i index f9cc7d3ea..fa193393f 100644 --- a/src/bindings/interface/model.i +++ b/src/bindings/interface/model.i @@ -52,6 +52,9 @@ Only the first matching Units is removed and returned."; %feature("docstring") libcellml::Model::hasUnresolvedImports "Tests if this model has unresolved imports."; +%feature("docstring") libcellml::Model::isDefined +"Tests if this model is defined."; + %feature("docstring") libcellml::Model::clone "Create a copy of this model."; diff --git a/src/bindings/interface/types.i b/src/bindings/interface/types.i index f1f460972..01c6b8c17 100644 --- a/src/bindings/interface/types.i +++ b/src/bindings/interface/types.i @@ -116,12 +116,48 @@ Provides support for shared pointers declared in types.h. // Shared typemaps +%typemap(in) libcellml::AnalyserEquation::Type (int val, int ecode) { + ecode = SWIG_AsVal(int)($input, &val); + if (!SWIG_IsOK(ecode)) { + %argument_fail(ecode, "$type", $symname, $argnum); + } else { + if (val < %static_cast($type::TRUE_CONSTANT, int) || %static_cast($type::EXTERNAL, int) < val) { + %argument_fail(ecode, "$type is not a valid value for the enumeration.", $symname, $argnum); + } + $1 = %static_cast(val, $basetype); + } +} + %typemap(in) libcellml::AnalyserEquationAst::Type (int val, int ecode) { ecode = SWIG_AsVal(int)($input, &val); if (!SWIG_IsOK(ecode)) { %argument_fail(ecode, "$type", $symname, $argnum); } else { - if (val < %static_cast($type::ASSIGNMENT, int) || %static_cast($type::NAN, int) < val) { + if (val < %static_cast($type::EQUALITY, int) || %static_cast($type::NAN, int) < val) { + %argument_fail(ecode, "$type is not a valid value for the enumeration.", $symname, $argnum); + } + $1 = %static_cast(val, $basetype); + } +} + +%typemap(in) libcellml::AnalyserModel::Type (int val, int ecode) { + ecode = SWIG_AsVal(int)($input, &val); + if (!SWIG_IsOK(ecode)) { + %argument_fail(ecode, "$type", $symname, $argnum); + } else { + if (val < %static_cast($type::UNKNOWN, int) || %static_cast($type::UNSUITABLY_CONSTRAINED, int) < val) { + %argument_fail(ecode, "$type is not a valid value for the enumeration.", $symname, $argnum); + } + $1 = %static_cast(val, $basetype); + } +} + +%typemap(in) libcellml::AnalyserVariable::Type (int val, int ecode) { + ecode = SWIG_AsVal(int)($input, &val); + if (!SWIG_IsOK(ecode)) { + %argument_fail(ecode, "$type", $symname, $argnum); + } else { + if (val < %static_cast($type::VARIABLE_OF_INTEGRATION, int) || %static_cast($type::EXTERNAL, int) < val) { %argument_fail(ecode, "$type is not a valid value for the enumeration.", $symname, $argnum); } $1 = %static_cast(val, $basetype); diff --git a/src/bindings/interface/units.i b/src/bindings/interface/units.i index 0d0b91fcc..6756dd2a3 100644 --- a/src/bindings/interface/units.i +++ b/src/bindings/interface/units.i @@ -86,6 +86,9 @@ extract the units with the given `name`."; %feature("docstring") libcellml::Units::equivalent "Tests if two Units are equivalent in base units as well as scaling factor."; +%feature("docstring") libcellml::Units::isDefined +"Tests if this units is defined."; + %feature("docstring") libcellml::Units::clone "Create a copy of this units."; @@ -98,6 +101,9 @@ extract the units with the given `name`."; %feature("docstring") libcellml::Units::unitAttributeReference "Get the reference from the unit attribute."; +%feature("docstring") libcellml::Units::setUnitAttributeReference +"Set the reference unit attribute."; + %feature("docstring") libcellml::Units::unitAttributePrefix "Get the prefix from the unit attribute."; diff --git a/src/bindings/javascript/analyserequation.cpp b/src/bindings/javascript/analyserequation.cpp index b71fe3707..d7579751f 100644 --- a/src/bindings/javascript/analyserequation.cpp +++ b/src/bindings/javascript/analyserequation.cpp @@ -26,7 +26,8 @@ EMSCRIPTEN_BINDINGS(libcellml_analyserequation) enum_("AnalyserEquation.Type") .value("TRUE_CONSTANT", libcellml::AnalyserEquation::Type::TRUE_CONSTANT) .value("VARIABLE_BASED_CONSTANT", libcellml::AnalyserEquation::Type::VARIABLE_BASED_CONSTANT) - .value("RATE", libcellml::AnalyserEquation::Type::RATE) + .value("ODE", libcellml::AnalyserEquation::Type::ODE) + .value("NLA", libcellml::AnalyserEquation::Type::NLA) .value("ALGEBRAIC", libcellml::AnalyserEquation::Type::ALGEBRAIC) .value("EXTERNAL", libcellml::AnalyserEquation::Type::EXTERNAL) ; @@ -34,9 +35,18 @@ EMSCRIPTEN_BINDINGS(libcellml_analyserequation) class_("AnalyserEquation") .smart_ptr>("AnalyserEquation") .function("type", &libcellml::AnalyserEquation::type) + .class_function("typeAsString", &libcellml::AnalyserEquation::typeAsString) .function("ast", &libcellml::AnalyserEquation::ast) + .function("dependencyCount", &libcellml::AnalyserEquation::dependencyCount) .function("dependencies", &libcellml::AnalyserEquation::dependencies) + .function("dependency", &libcellml::AnalyserEquation::dependency) + .function("nlaSystemIndex", &libcellml::AnalyserEquation::nlaSystemIndex) + .function("nlaSiblingCount", &libcellml::AnalyserEquation::nlaSiblingCount) + .function("nlaSiblings", &libcellml::AnalyserEquation::nlaSiblings) + .function("nlaSibling", &libcellml::AnalyserEquation::nlaSibling) .function("isStateRateBased", &libcellml::AnalyserEquation::isStateRateBased) + .function("variableCount", &libcellml::AnalyserEquation::variableCount) + .function("variables", &libcellml::AnalyserEquation::variables) .function("variable", &libcellml::AnalyserEquation::variable) ; diff --git a/src/bindings/javascript/analyserequationast.cpp b/src/bindings/javascript/analyserequationast.cpp index d44527a71..00d53dbf9 100644 --- a/src/bindings/javascript/analyserequationast.cpp +++ b/src/bindings/javascript/analyserequationast.cpp @@ -24,7 +24,7 @@ using namespace emscripten; EMSCRIPTEN_BINDINGS(libcellml_analyserequationast) { enum_("AnalyserEquationAst.Type") - .value("ASSIGNMENT", libcellml::AnalyserEquationAst::Type::ASSIGNMENT) + .value("EQUALITY", libcellml::AnalyserEquationAst::Type::EQUALITY) .value("EQ", libcellml::AnalyserEquationAst::Type::EQ) .value("NEQ", libcellml::AnalyserEquationAst::Type::NEQ) .value("LT", libcellml::AnalyserEquationAst::Type::LT) @@ -94,6 +94,7 @@ EMSCRIPTEN_BINDINGS(libcellml_analyserequationast) class_("AnalyserEquationAst") .smart_ptr_constructor("AnalyserEquationAst", &libcellml::AnalyserEquationAst::create) .function("type", &libcellml::AnalyserEquationAst::type) + .class_function("typeAsString", &libcellml::AnalyserEquationAst::typeAsString) .function("setType", &libcellml::AnalyserEquationAst::setType) .function("value", &libcellml::AnalyserEquationAst::value) .function("setValue", &libcellml::AnalyserEquationAst::setValue) @@ -105,6 +106,7 @@ EMSCRIPTEN_BINDINGS(libcellml_analyserequationast) .function("setLeftChild", &libcellml::AnalyserEquationAst::setLeftChild) .function("rightChild", &libcellml::AnalyserEquationAst::rightChild) .function("setRightChild", &libcellml::AnalyserEquationAst::setRightChild) + .function("swapLeftAndRightChildren", &libcellml::AnalyserEquationAst::swapLeftAndRightChildren) ; EM_ASM( diff --git a/src/bindings/javascript/analysermodel.cpp b/src/bindings/javascript/analysermodel.cpp index 4cd30d87d..87a74085f 100644 --- a/src/bindings/javascript/analysermodel.cpp +++ b/src/bindings/javascript/analysermodel.cpp @@ -25,8 +25,10 @@ EMSCRIPTEN_BINDINGS(libcellml_analysermodel) { enum_("AnalyserModel.Type") .value("UNKNOWN", libcellml::AnalyserModel::Type::UNKNOWN) - .value("ALGEBRAIC", libcellml::AnalyserModel::Type::ALGEBRAIC) .value("ODE", libcellml::AnalyserModel::Type::ODE) + .value("DAE", libcellml::AnalyserModel::Type::DAE) + .value("NLA", libcellml::AnalyserModel::Type::NLA) + .value("ALGEBRAIC", libcellml::AnalyserModel::Type::ALGEBRAIC) .value("INVALID", libcellml::AnalyserModel::Type::INVALID) .value("UNDERCONSTRAINED", libcellml::AnalyserModel::Type::UNDERCONSTRAINED) .value("OVERCONSTRAINED", libcellml::AnalyserModel::Type::OVERCONSTRAINED) @@ -37,6 +39,7 @@ EMSCRIPTEN_BINDINGS(libcellml_analysermodel) .smart_ptr>("AnalyserModel") .function("isValid", &libcellml::AnalyserModel::isValid) .function("type", &libcellml::AnalyserModel::type) + .class_function("typeAsString", &libcellml::AnalyserModel::typeAsString) .function("hasExternalVariables", &libcellml::AnalyserModel::hasExternalVariables) .function("voi", &libcellml::AnalyserModel::voi) .function("stateCount", &libcellml::AnalyserModel::stateCount) diff --git a/src/bindings/javascript/analyservariable.cpp b/src/bindings/javascript/analyservariable.cpp index 2698d4d9d..0462c5a61 100644 --- a/src/bindings/javascript/analyservariable.cpp +++ b/src/bindings/javascript/analyservariable.cpp @@ -35,9 +35,12 @@ EMSCRIPTEN_BINDINGS(libcellml_analyservariable) class_("AnalyserVariable") .smart_ptr>("AnalyserVariable") .function("type", &libcellml::AnalyserVariable::type) + .class_function("typeAsString", &libcellml::AnalyserVariable::typeAsString) .function("index", &libcellml::AnalyserVariable::index) .function("initialisingVariable", &libcellml::AnalyserVariable::initialisingVariable) .function("variable", &libcellml::AnalyserVariable::variable) + .function("equationCount", &libcellml::AnalyserVariable::equationCount) + .function("equations", &libcellml::AnalyserVariable::equations) .function("equation", &libcellml::AnalyserVariable::equation) ; diff --git a/src/bindings/javascript/component.cpp b/src/bindings/javascript/component.cpp index 95bdac802..d7a81bb6f 100644 --- a/src/bindings/javascript/component.cpp +++ b/src/bindings/javascript/component.cpp @@ -63,6 +63,7 @@ EMSCRIPTEN_BINDINGS(libcellml_component) { .function("importReference", &libcellml::Component::importReference) .function("setImportReference", &libcellml::Component::setImportReference) .function("isResolved", &libcellml::Component::isResolved) + .function("isDefined", &libcellml::Component::isDefined) ; } diff --git a/src/bindings/javascript/generator.cpp b/src/bindings/javascript/generator.cpp index 6f1501fd7..1315315a5 100644 --- a/src/bindings/javascript/generator.cpp +++ b/src/bindings/javascript/generator.cpp @@ -16,7 +16,9 @@ limitations under the License. #include +#include "libcellml/analyserequationast.h" #include "libcellml/generator.h" +#include "libcellml/generatorprofile.h" using namespace emscripten; @@ -30,5 +32,7 @@ EMSCRIPTEN_BINDINGS(libcellml_generator) .function("setModel", &libcellml::Generator::setModel) .function("interfaceCode", &libcellml::Generator::interfaceCode) .function("implementationCode", &libcellml::Generator::implementationCode) + .class_function("equationCode", select_overload(&libcellml::Generator::equationCode)) + .class_function("equationCodeByProfile", select_overload(&libcellml::Generator::equationCode)) ; } diff --git a/src/bindings/javascript/generatorprofile.cpp b/src/bindings/javascript/generatorprofile.cpp index 57e29fa6e..41e4115fe 100644 --- a/src/bindings/javascript/generatorprofile.cpp +++ b/src/bindings/javascript/generatorprofile.cpp @@ -31,11 +31,12 @@ EMSCRIPTEN_BINDINGS(libcellml_generatorprofile) class_("GeneratorProfile") .smart_ptr_constructor("GeneratorProfile", &libcellml::GeneratorProfile::create) .function("profile", &libcellml::GeneratorProfile::profile) + .class_function("profileAsString", &libcellml::GeneratorProfile::profileAsString) .function("setProfile", &libcellml::GeneratorProfile::setProfile) .function("hasInterface", &libcellml::GeneratorProfile::hasInterface) .function("setHasInterface", &libcellml::GeneratorProfile::setHasInterface) - .function("assignmentString", &libcellml::GeneratorProfile::assignmentString) - .function("setAssignmentString", &libcellml::GeneratorProfile::setAssignmentString) + .function("equalityString", &libcellml::GeneratorProfile::equalityString) + .function("setEqualityString", &libcellml::GeneratorProfile::setEqualityString) .function("eqString", &libcellml::GeneratorProfile::eqString) .function("setEqString", &libcellml::GeneratorProfile::setEqString) .function("neqString", &libcellml::GeneratorProfile::neqString) @@ -296,6 +297,22 @@ EMSCRIPTEN_BINDINGS(libcellml_generatorprofile) .function("setExternalVariableMethodTypeDefinitionString", &libcellml::GeneratorProfile::setExternalVariableMethodTypeDefinitionString) .function("externalVariableMethodCallString", &libcellml::GeneratorProfile::externalVariableMethodCallString) .function("setExternalVariableMethodCallString", &libcellml::GeneratorProfile::setExternalVariableMethodCallString) + .function("rootFindingInfoObjectString", &libcellml::GeneratorProfile::rootFindingInfoObjectString) + .function("setRootFindingInfoObjectString", &libcellml::GeneratorProfile::setRootFindingInfoObjectString) + .function("externNlaSolveMethodString", &libcellml::GeneratorProfile::externNlaSolveMethodString) + .function("setExternNlaSolveMethodString", &libcellml::GeneratorProfile::setExternNlaSolveMethodString) + .function("findRootCallString", &libcellml::GeneratorProfile::findRootCallString) + .function("setFindRootCallString", &libcellml::GeneratorProfile::setFindRootCallString) + .function("findRootMethodString", &libcellml::GeneratorProfile::findRootMethodString) + .function("setFindRootMethodString", &libcellml::GeneratorProfile::setFindRootMethodString) + .function("nlaSolveCallString", &libcellml::GeneratorProfile::nlaSolveCallString) + .function("setNlaSolveCallString", &libcellml::GeneratorProfile::setNlaSolveCallString) + .function("objectiveFunctionMethodString", &libcellml::GeneratorProfile::objectiveFunctionMethodString) + .function("setObjectiveFunctionMethodString", &libcellml::GeneratorProfile::setObjectiveFunctionMethodString) + .function("uArrayString", &libcellml::GeneratorProfile::uArrayString) + .function("setUArrayString", &libcellml::GeneratorProfile::setUArrayString) + .function("fArrayString", &libcellml::GeneratorProfile::fArrayString) + .function("setFArrayString", &libcellml::GeneratorProfile::setFArrayString) .function("interfaceCreateStatesArrayMethodString", &libcellml::GeneratorProfile::interfaceCreateStatesArrayMethodString) .function("setInterfaceCreateStatesArrayMethodString", &libcellml::GeneratorProfile::setInterfaceCreateStatesArrayMethodString) .function("implementationCreateStatesArrayMethodString", &libcellml::GeneratorProfile::implementationCreateStatesArrayMethodString) diff --git a/src/bindings/javascript/issue.cpp b/src/bindings/javascript/issue.cpp index 9eb1e91fa..fba9ddbdc 100644 --- a/src/bindings/javascript/issue.cpp +++ b/src/bindings/javascript/issue.cpp @@ -122,6 +122,7 @@ EMSCRIPTEN_BINDINGS(libcellml_issue) { .value("ANALYSER_ODE_NOT_FIRST_ORDER", libcellml::Issue::ReferenceRule::ANALYSER_ODE_NOT_FIRST_ORDER) .value("ANALYSER_VARIABLE_UNUSED", libcellml::Issue::ReferenceRule::ANALYSER_VARIABLE_UNUSED) .value("ANALYSER_STATE_NOT_INITIALISED", libcellml::Issue::ReferenceRule::ANALYSER_STATE_NOT_INITIALISED) + .value("ANALYSER_STATE_RATE_AS_ALGEBRAIC", libcellml::Issue::ReferenceRule::ANALYSER_STATE_RATE_AS_ALGEBRAIC) .value("ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE", libcellml::Issue::ReferenceRule::ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE) .value("ANALYSER_EXTERNAL_VARIABLE_DIFFERENT_MODEL", libcellml::Issue::ReferenceRule::ANALYSER_EXTERNAL_VARIABLE_DIFFERENT_MODEL) .value("ANALYSER_EXTERNAL_VARIABLE_VOI", libcellml::Issue::ReferenceRule::ANALYSER_EXTERNAL_VARIABLE_VOI) diff --git a/src/bindings/javascript/model.cpp b/src/bindings/javascript/model.cpp index 86780f0ce..f3b48450d 100644 --- a/src/bindings/javascript/model.cpp +++ b/src/bindings/javascript/model.cpp @@ -42,6 +42,7 @@ EMSCRIPTEN_BINDINGS(libcellml_model) { .function("linkUnits", &libcellml::Model::linkUnits) .function("hasUnlinkedUnits", &libcellml::Model::hasUnlinkedUnits) .function("hasImports", &libcellml::Model::hasImports) + .function("isDefined", &libcellml::Model::isDefined) .function("hasUnresolvedImports", &libcellml::Model::hasUnresolvedImports) .function("clone", &libcellml::Model::clone) .function("fixVariableInterfaces", &libcellml::Model::fixVariableInterfaces) diff --git a/src/bindings/javascript/units.cpp b/src/bindings/javascript/units.cpp index 6e9ce3b0d..36855a24d 100644 --- a/src/bindings/javascript/units.cpp +++ b/src/bindings/javascript/units.cpp @@ -99,6 +99,7 @@ EMSCRIPTEN_BINDINGS(libcellml_units) { .function("addUnitByStandardUnitExponent", select_overload(&libcellml::Units::addUnit)) .function("addUnitByStandardUnit", select_overload(&libcellml::Units::addUnit)) .function("unitAttributeReference", &libcellml::Units::unitAttributeReference) + .function("setUnitAttributeReference", &libcellml::Units::setUnitAttributeReference) .function("unitAttributePrefix", &libcellml::Units::unitAttributePrefix) .function("unitAttributeExponent", &libcellml::Units::unitAttributeExponent) .function("unitAttributeMultiplier", &libcellml::Units::unitAttributeMultiplier) @@ -118,6 +119,7 @@ EMSCRIPTEN_BINDINGS(libcellml_units) { .function("importReference", &libcellml::Units::importReference) .function("setImportReference", &libcellml::Units::setImportReference) .function("isResolved", &libcellml::Units::isResolved) + .function("isDefined", &libcellml::Units::isDefined) .class_function("scalingFactor", &libcellml::Units::scalingFactor) .class_function("compatible", &libcellml::Units::compatible) .class_function("equivalent", &libcellml::Units::equivalent) diff --git a/src/bindings/python/__init__.py b/src/bindings/python/__init__.py index 86a91c061..4ae2736eb 100644 --- a/src/bindings/python/__init__.py +++ b/src/bindings/python/__init__.py @@ -57,11 +57,13 @@ class Object: convert(AnalyserEquation, 'Type', [ 'TRUE_CONSTANT', 'VARIABLE_BASED_CONSTANT', - 'RATE', + 'ODE', + 'NLA', 'ALGEBRAIC', + 'EXTERNAL', ]) convert(AnalyserEquationAst, 'Type', [ - 'ASSIGNMENT', + 'EQUALITY', # Relational and logical operators. @@ -153,8 +155,10 @@ class Object: ]) convert(AnalyserModel, 'Type', [ 'UNKNOWN', - 'ALGEBRAIC', 'ODE', + 'DAE', + 'NLA', + 'ALGEBRAIC', 'INVALID', 'UNDERCONSTRAINED', 'OVERCONSTRAINED', @@ -166,6 +170,7 @@ class Object: 'CONSTANT', 'COMPUTED_CONSTANT', 'ALGEBRAIC', + 'EXTERNAL', ]) convert(GeneratorProfile, 'Profile', [ 'C', diff --git a/src/component.cpp b/src/component.cpp index 25283f139..207d731e6 100644 --- a/src/component.cpp +++ b/src/component.cpp @@ -27,6 +27,7 @@ limitations under the License. #include "libcellml/reset.h" #include "libcellml/variable.h" +#include "commonutils.h" #include "component_p.h" #include "reset_p.h" #include "utilities.h" @@ -104,34 +105,55 @@ ComponentPtr Component::create(const std::string &name) noexcept return std::shared_ptr {new Component {name}}; } -bool Component::ComponentImpl::isResolvedWithHistory(History &history, const ComponentConstPtr &component) const +bool Component::ComponentImpl::performTestWithHistory(History &history, const ComponentConstPtr &component, TestType type) const { - bool resolved = true; if (mComponent->isImport()) { auto model = mComponent->importSource()->model(); if (model == nullptr) { - resolved = false; - } else { - auto importedComponent = model->component(mComponent->importReference()); - if (importedComponent == nullptr) { - resolved = false; - } else { - auto h = createHistoryEpoch(component, importeeModelUrl(history, mComponent->importSource()->url())); - if (checkForImportCycles(history, h)) { - resolved = false; - } else { - history.push_back(h); - resolved = importedComponent->pFunc()->isResolvedWithHistory(history, importedComponent); - } + return false; + } + + auto importedComponent = model->component(mComponent->importReference()); + if (importedComponent == nullptr) { + return false; + } + + auto h = createHistoryEpoch(component, importeeModelUrl(history, mComponent->importSource()->url())); + if (checkForImportCycles(history, h)) { + return false; + } + + history.push_back(h); + bool result = importedComponent->pFunc()->performTestWithHistory(history, importedComponent, type); + history.pop_back(); + return result; + } + + auto model = std::dynamic_pointer_cast(mComponent->parent()); + if ((model == nullptr) && (mComponent->parent() != nullptr)) { + model = owningModel(mComponent->parent()); + } + + auto tmpComponent = mComponent->clone(); + auto units = unitsUsed(model, tmpComponent); + for (const auto &u : units) { + if ((type == TestType::RESOLVED) && !u->isResolved()) { + return false; + } else if (type == TestType::DEFINED) { + if (!u->isDefined() || (model == nullptr) || !model->hasUnits(u)) { + return false; } } } - for (size_t i = 0; (i < mComponent->componentCount()) && resolved; ++i) { + + for (size_t i = 0; i < mComponent->componentCount(); ++i) { auto currentComponent = mComponent->component(i); - resolved = currentComponent->pFunc()->isResolvedWithHistory(history, currentComponent); + if (!currentComponent->pFunc()->performTestWithHistory(history, currentComponent, type)) { + return false; + } } - return resolved; + return true; } bool Component::doAddComponent(const ComponentPtr &component) @@ -146,7 +168,7 @@ bool Component::doAddComponent(const ComponentPtr &component) if (parent != newParent) { removeComponentFromEntity(parent, component); } - } else if (!hasParent && hasAncestor(component)) { + } else if (hasAncestor(component)) { return false; } else if (newParent == component) { return false; @@ -437,10 +459,16 @@ bool Component::requiresImports() const return doRequiresImport(shared_from_this()); } +bool Component::isDefined() const +{ + History history; + return pFunc()->performTestWithHistory(history, shared_from_this(), TestType::DEFINED); +} + bool Component::doIsResolved() const { History history; - return pFunc()->isResolvedWithHistory(history, shared_from_this()); + return pFunc()->performTestWithHistory(history, shared_from_this(), TestType::RESOLVED); } bool Component::doEquals(const EntityPtr &other) const diff --git a/src/component_p.h b/src/component_p.h index 5862aa9bd..8fddcb349 100644 --- a/src/component_p.h +++ b/src/component_p.h @@ -45,7 +45,7 @@ class Component::ComponentImpl: public ComponentEntityImpl bool equalVariables(const ComponentPtr &other) const; bool equalResets(const ComponentPtr &other) const; - bool isResolvedWithHistory(History &history, const ComponentConstPtr &component) const; + bool performTestWithHistory(History &history, const ComponentConstPtr &component, TestType type) const; }; } // namespace libcellml diff --git a/src/componententity.cpp b/src/componententity.cpp index c5cdaa347..7b2c0cd6a 100644 --- a/src/componententity.cpp +++ b/src/componententity.cpp @@ -220,7 +220,7 @@ bool ComponentEntity::replaceComponent(size_t index, const ComponentPtr &newComp bool status = false; auto oldComponent = component(index); ParentedEntityPtr parent = nullptr; - if (oldComponent != nullptr && oldComponent->hasParent()) { + if (oldComponent != nullptr) { parent = oldComponent->parent(); } @@ -285,8 +285,8 @@ bool ComponentEntity::doEquals(const EntityPtr &other) const return false; } } + return true; } - return true; } return false; diff --git a/src/debug.cpp b/src/debug.cpp index e04ae2cbc..17a75ae54 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -16,18 +16,150 @@ limitations under the License. #include "debug.h" +#include "libcellml/analyserequation.h" #include "libcellml/analyserequationast.h" +#include "libcellml/analysermodel.h" +#include "libcellml/analyservariable.h" #include "libcellml/component.h" #include "libcellml/generator.h" +#include "libcellml/generatorprofile.h" #include "libcellml/model.h" #include "libcellml/variable.h" -#ifdef NAN -# undef NAN -#endif +#include "libcellml/undefines.h" + +#include "commonutils.h" namespace libcellml { +std::string astAsCode(const AnalyserEquationAstPtr &ast) +{ + if (ast == nullptr) { + return "nullptr"; + } + + static GeneratorProfilePtr generatorProfile = nullptr; + + if (generatorProfile == nullptr) { + generatorProfile = GeneratorProfile::create(); + + generatorProfile->setAbsoluteValueString("abs"); + generatorProfile->setNaturalLogarithmString("ln"); + generatorProfile->setCommonLogarithmString("log"); + generatorProfile->setRemString("rem"); + generatorProfile->setAsinString("arcsin"); + generatorProfile->setAcosString("arccos"); + generatorProfile->setAtanString("arctan"); + generatorProfile->setAsecString("arcsec"); + generatorProfile->setAcscString("arccsc"); + generatorProfile->setAcotString("arccot"); + generatorProfile->setAsinhString("arcsinh"); + generatorProfile->setAcoshString("arccosh"); + generatorProfile->setAtanhString("arctanh"); + generatorProfile->setAsechString("arcsech"); + generatorProfile->setAcschString("arccsch"); + generatorProfile->setAcothString("arccoth"); + generatorProfile->setTrueString("true"); + generatorProfile->setFalseString("false"); + generatorProfile->setEString("exponentiale"); + generatorProfile->setPiString("pi"); + generatorProfile->setInfString("infinity"); + generatorProfile->setNanString("notanumber"); + } + + return Generator::equationCode(ast, generatorProfile); +} + +void printAnalyserModelEquations(const AnalyserModelPtr &model) +{ + size_t eqnNb = 0; + + for (const auto &eqn : model->equations()) { + Debug() << "\n---------------------------------------[API equation #" << ++eqnNb << "]"; + + if (eqn->ast() != nullptr) { + Debug() << "\n" << astAsCode(eqn->ast()); + } else { + Debug() << "\nNo equation"; + } + + Debug() << "\nType: " << AnalyserEquation::typeAsString(eqn->type()); + + if (eqn->variableCount() != 0) { + Debug() << "\nVariables:"; + + for (const auto &var : eqn->variables()) { + Debug() << " - " << var->variable()->name(); + } + } else { + Debug() << "\nNo variables"; + } + + if (eqn->dependencyCount() != 0) { + Debug() << "\nDependencies:"; + + for (const auto &dep : eqn->dependencies()) { + if (dep->ast() != nullptr) { + Debug() << " - " << astAsCode(dep->ast()); + } else if (dep->type() == AnalyserEquation::Type::EXTERNAL) { + Debug() << " - External equation for '" << dep->variable(0)->variable()->name() << "'"; + } else { + Debug() << " - ??? [" << AnalyserEquation::typeAsString(dep->type()) << "]"; + } + } + } else { + Debug() << "\nNo dependencies"; + } + + if (eqn->type() == AnalyserEquation::Type::NLA) { + if (eqn->nlaSiblingCount() != 0) { + Debug() << "\nNLA siblings:"; + + for (const auto &nlaSibling : eqn->nlaSiblings()) { + if (nlaSibling->ast() != nullptr) { + Debug() << " - " << astAsCode(nlaSibling->ast()); + } else if (nlaSibling->type() == AnalyserEquation::Type::EXTERNAL) { + Debug() << " - External equation for '" << nlaSibling->variable(0)->variable()->name() << "'"; + } else { + Debug() << " - ??? [" << AnalyserEquation::typeAsString(nlaSibling->type()) << "]"; + } + } + } else { + Debug() << "\nNo NLA siblings"; + } + } + } + + Debug() << "\n---------------------------------------[END]\n"; +} + +void printAnalyserModelVariables(const AnalyserModelPtr &model) +{ + size_t varNb = 0; + + for (const auto &var : model->variables()) { + Debug() << "\n---------------------------------------[API variable " << ++varNb << "]"; + Debug() << "\nName: " << var->variable()->name(); + Debug() << "Type: " << AnalyserVariable::typeAsString(var->type()); + + if (var->equationCount() != 0) { + Debug() << "\nEquations:"; + + for (const auto &eqn : var->equations()) { + if (eqn->ast() != nullptr) { + Debug() << " - " << astAsCode(eqn->ast()); + } else if (eqn->type() == AnalyserEquation::Type::EXTERNAL) { + Debug() << " - External equation for '" << eqn->variable(0)->variable()->name() << "'"; + } else { + Debug() << " - ??? [" << AnalyserEquation::typeAsString(eqn->type()) << "]"; + } + } + } else { + Debug() << "\nNo equations"; + } + } +} + void printHistory(const History &history) { for (const auto &h : history) { @@ -118,6 +250,21 @@ void printConnectionMap(const ConnectionMap &map) } } +void printComponentMap(const ComponentMap &map) +{ + Debug() << "Print out of component map"; + for (const auto &iter : map) { + auto key = iter.first; + auto value = iter.second; + Debug() << "first: " << key->name(); + if (value) { + Debug() << "second: " << value->name(); + } else { + Debug() << "second: null"; + } + } +} + void printStringStringMap(const StringStringMap &map) { Debug() << "Print out of string -> string map"; @@ -145,31 +292,31 @@ AnalyserEquationAstTrunk::AnalyserEquationAstTrunk(AnalyserEquationAstTrunk *pre { } -void doPrintAst(AnalyserEquationAstTrunk *trunk) +std::string doPrintAstAsTree(AnalyserEquationAstTrunk *trunk) { if (trunk == nullptr) { - return; + return {}; } - doPrintAst(trunk->mPrev); + auto res = doPrintAstAsTree(trunk->mPrev); if ((trunk->mPrev != nullptr) && (trunk->mPrev->mStr == SPACES) && ((trunk->mStr == SPACES) || (trunk->mStr == TRUNK))) { - std::cout << " "; + res += " "; } - std::cout << trunk->mStr; + return res + trunk->mStr; } -std::string doPrintAst(const AnalyserEquationAstPtr &ast) +std::string doPrintAstAsTree(const AnalyserEquationAstPtr &ast) { std::string res; switch (ast->type()) { - // Assignment. + // Equality. - case AnalyserEquationAst::Type::ASSIGNMENT: - res = "ASSIGNMENT"; + case AnalyserEquationAst::Type::EQUALITY: + res = "EQUALITY"; break; @@ -402,10 +549,15 @@ std::string doPrintAst(const AnalyserEquationAstPtr &ast) // Token elements. - case AnalyserEquationAst::Type::CI: - res = ast->variable()->name(); + case AnalyserEquationAst::Type::CI: { + auto astVariable = ast->variable(); + + if (astVariable != nullptr) { + res = astVariable->name(); + } break; + } case AnalyserEquationAst::Type::CN: res = ast->value(); @@ -457,17 +609,21 @@ std::string doPrintAst(const AnalyserEquationAstPtr &ast) return res; } -void doPrintAst(const AnalyserEquationAstPtr &ast, +std::string doPrintAstAsTree(const AnalyserEquationAstPtr &ast, AnalyserEquationAstTrunk *prevTrunk, bool isLeft) { if (ast == nullptr) { - return; + return {}; } + std::string res; std::string prevStr = SPACES; AnalyserEquationAstTrunk trunk(prevTrunk, prevStr); + auto astLeftChild = ast->leftChild(); - doPrintAst(ast->leftChild(), &trunk, true); + if (astLeftChild != nullptr) { + res += doPrintAstAsTree(astLeftChild, &trunk, true); + } if (prevTrunk == nullptr) { trunk.mStr = "──"; @@ -479,9 +635,7 @@ void doPrintAst(const AnalyserEquationAstPtr &ast, prevTrunk->mStr = prevStr; } - doPrintAst(&trunk); - - std::cout << doPrintAst(ast) << std::endl; + res += doPrintAstAsTree(&trunk) + doPrintAstAsTree(ast) + "\n"; if (prevTrunk != nullptr) { prevTrunk->mStr = prevStr; @@ -489,12 +643,23 @@ void doPrintAst(const AnalyserEquationAstPtr &ast, trunk.mStr = TRUNK; - doPrintAst(ast->rightChild(), &trunk, false); + auto astRightChild = ast->rightChild(); + + if (astRightChild != nullptr) { + res += doPrintAstAsTree(astRightChild, &trunk, false); + } + + return res; +} + +void printAstAsTree(const AnalyserEquationAstPtr &ast) +{ + Debug() << doPrintAstAsTree(ast, nullptr, false); } -void printAst(const AnalyserEquationAstPtr &ast) +void printAstAsCode(const AnalyserEquationAstPtr &ast) { - doPrintAst(ast, nullptr, false); + Debug() << astAsCode(ast); } void printImportLibrary(const ImportLibrary &importlibrary) @@ -510,4 +675,97 @@ void printImportLibrary(const ImportLibrary &importlibrary) Debug() << " == "; } +void printVariableMap(const VariableMap &map) +{ + Debug() << " == Variable map =="; + for (const auto &entry : map) { + auto v1 = entry->variable1(); + auto v2 = entry->variable2(); + + Debug(false) << "v1: "; + if (v1 == nullptr) { + Debug(false) << "(nullptr)"; + } else { + Debug(false) << v1->name(); + } + Debug(false) << " - v2: "; + if (v2 == nullptr) { + Debug(false) << "(nullptr)"; + } else { + Debug(false) << v2->name(); + } + Debug() << ""; + } +} + +void printNamedPath(const ParentedEntityPtr &parented) +{ + if (parented != nullptr) { + std::vector names; + auto named = std::dynamic_pointer_cast(parented); + if (named != nullptr) { + names.push_back(named->name()); + auto parent = named->parent(); + while (parent != nullptr) { + auto named = std::dynamic_pointer_cast(parent); + if (named != nullptr) { + names.push_back(named->name()); + } + parent = parent->parent(); + } + } + + while (!names.empty()) { + Debug(false) << "/" << names.back(); + names.pop_back(); + } + } else { + Debug() << "nullptr variable."; + } +} + +void printEquivalences(const VariablePtr &variable) +{ + Debug(false) << "Equivalence for: "; + printNamedPath(variable); + Debug(); + if (variable != nullptr) { + for (size_t j = 0; j < variable->equivalentVariableCount(); ++j) { + Debug(false) << " - "; + printNamedPath(variable->equivalentVariable(j)); + Debug(); + } + } +} + +void printUnits(const UnitsPtr &units) +{ + Debug(false) << "Units: " << (units ? units->name() : "nullptr"); + if (units) { + if (units->isImport()) { + Debug(false) << " (is imported)"; + } + Debug() << ""; + auto model = owningModel(units); + for (size_t i = 0; i < units->unitCount(); ++i) { + const std::string ref = units->unitAttributeReference(i); + Debug(false) << " - " << (i + 1) << ": " << ref; + if (model) { + Debug() << ", " << model->hasUnits(ref); + } else { + Debug() << ", modelless units."; + } + } + } + Debug() << "*****"; +} + +void listModelsUnits(const ModelPtr &model) +{ + Debug() << "Model name: " << model->name() << ", units count: " << model->unitsCount(); + for (size_t i = 0; i < model->unitsCount(); ++i) { + printUnits(model->units(i)); + } +} + } // namespace libcellml diff --git a/src/debug.h b/src/debug.h index 2662bfe3f..afdb418bb 100644 --- a/src/debug.h +++ b/src/debug.h @@ -93,15 +93,23 @@ struct Debug bool mNewLine; }; -void printStack(const IndexStack &stack); -void printStackWithModelInfo(const IndexStack &stack, const ModelPtr &model); +void printAnalyserModelEquations(const AnalyserModelPtr &model); +void printAnalyserModelVariables(const AnalyserModelPtr &model); +void printAst(const AnalyserEquationAstPtr &ast); +void printComponentMap(const ComponentMap &map); +void printConnectionMap(const ConnectionMap &map); void printEquivalenceMap(const EquivalenceMap &map); void printEquivalenceMapWithModelInfo(const EquivalenceMap &map, const ModelPtr &model); -void printStringStringMap(const StringStringMap &map); -void printConnectionMap(const ConnectionMap &map); -void printAst(const AnalyserEquationAstPtr &ast); void printHistory(const History &history); void printHistoryEpoch(const HistoryEpochPtr &historyEpoch); void printImportLibrary(const ImportLibrary &importlibrary); +void printStack(const IndexStack &stack); +void printStackWithModelInfo(const IndexStack &stack, const ModelPtr &model); +void printStringStringMap(const StringStringMap &map); +void printVariableMap(const VariableMap &map); +void printUnits(const UnitsPtr &units); +void listModelsUnits(const ModelPtr &model); +void printNamedPath(const ParentedEntityPtr &parented); +void printEquivalences(const VariablePtr &variable); } // namespace libcellml diff --git a/src/entity.cpp b/src/entity.cpp index b3a4f10f0..fd58d32b3 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -56,6 +56,7 @@ bool Entity::doEquals(const EntityPtr &other) const if (other == nullptr) { return false; } + return pFunc()->mId == other->id(); } diff --git a/src/generator.cpp b/src/generator.cpp index a46c8e6d2..cb34ea19b 100644 --- a/src/generator.cpp +++ b/src/generator.cpp @@ -27,30 +27,41 @@ limitations under the License. #include "libcellml/units.h" #include "libcellml/version.h" -#include "analyserequationast_p.h" +#include "commonutils.h" #include "generator_p.h" #include "generatorprofilesha1values.h" #include "generatorprofiletools.h" #include "utilities.h" -#ifdef NAN -# undef NAN -#endif +#include "libcellml/undefines.h" namespace libcellml { -bool Generator::GeneratorImpl::retrieveLockedModelAndProfile() +void Generator::GeneratorImpl::reset() { - mLockedModel = mGenerator->model(); - mLockedProfile = mGenerator->profile(); + mCode = {}; +} - return (mLockedModel != nullptr) && (mLockedProfile != nullptr); +bool Generator::GeneratorImpl::modelHasOdes() const +{ + switch (mModel->type()) { + case AnalyserModel::Type::ODE: + case AnalyserModel::Type::DAE: + return true; + default: + return false; + } } -void Generator::GeneratorImpl::resetLockedModelAndProfile() +bool Generator::GeneratorImpl::modelHasNlas() const { - mLockedModel = nullptr; - mLockedProfile = nullptr; + switch (mModel->type()) { + case AnalyserModel::Type::NLA: + case AnalyserModel::Type::DAE: + return true; + default: + return false; + } } AnalyserVariablePtr Generator::GeneratorImpl::analyserVariable(const VariablePtr &variable) const @@ -58,14 +69,15 @@ AnalyserVariablePtr Generator::GeneratorImpl::analyserVariable(const VariablePtr // Find and return the analyser variable associated with the given variable. AnalyserVariablePtr res; - auto modelVoi = mLockedModel->voi(); + auto modelVoi = mModel->voi(); + VariablePtr modelVoiVariable = (modelVoi != nullptr) ? modelVoi->variable() : nullptr; - if ((modelVoi != nullptr) - && mLockedModel->areEquivalentVariables(variable, modelVoi->variable())) { + if ((modelVoiVariable != nullptr) + && mModel->areEquivalentVariables(variable, modelVoiVariable)) { res = modelVoi; } else { - for (const auto &modelState : mLockedModel->states()) { - if (mLockedModel->areEquivalentVariables(variable, modelState->variable())) { + for (const auto &modelState : mModel->states()) { + if (mModel->areEquivalentVariables(variable, modelState->variable())) { res = modelState; break; @@ -73,13 +85,30 @@ AnalyserVariablePtr Generator::GeneratorImpl::analyserVariable(const VariablePtr } if (res == nullptr) { - for (const auto &modelVariable : mLockedModel->variables()) { - if (mLockedModel->areEquivalentVariables(variable, modelVariable->variable())) { - res = modelVariable; - - break; + // Normally, we would have: + // + // for (const auto &modelVariable : mModel->variables()) { + // if (mModel->areEquivalentVariables(variable, modelVariable->variable())) { + // res = modelVariable; + // + // break; + // } + // } + // + // but we always have variables, so llvm-cov will complain that the + // false branch of our for loop is never reached. The below code is + // a bit more verbose but at least it makes llvm-cov happy. + + auto modelVariables = mModel->variables(); + auto modelVariable = modelVariables.begin(); + + do { + if (mModel->areEquivalentVariables(variable, (*modelVariable)->variable())) { + res = *modelVariable; + } else { + ++modelVariable; } - } + } while (res == nullptr); } } @@ -93,38 +122,55 @@ double Generator::GeneratorImpl::scalingFactor(const VariablePtr &variable) cons return Units::scalingFactor(variable->units(), analyserVariable(variable)->variable()->units()); } +bool Generator::GeneratorImpl::isNegativeNumber(const AnalyserEquationAstPtr &ast) const +{ + if (ast->type() == AnalyserEquationAst::Type::CN) { + double doubleValue; + + convertToDouble(ast->value(), doubleValue); + + return doubleValue < 0.0; + } + + return false; +} + bool Generator::GeneratorImpl::isRelationalOperator(const AnalyserEquationAstPtr &ast) const { - return ((ast->type() == AnalyserEquationAst::Type::EQ) - && mLockedProfile->hasEqOperator()) - || ((ast->type() == AnalyserEquationAst::Type::NEQ) - && mLockedProfile->hasNeqOperator()) - || ((ast->type() == AnalyserEquationAst::Type::LT) - && mLockedProfile->hasLtOperator()) - || ((ast->type() == AnalyserEquationAst::Type::LEQ) - && mLockedProfile->hasLeqOperator()) - || ((ast->type() == AnalyserEquationAst::Type::GT) - && mLockedProfile->hasGtOperator()) - || ((ast->type() == AnalyserEquationAst::Type::GEQ) - && mLockedProfile->hasGeqOperator()); + switch (ast->type()) { + case AnalyserEquationAst::Type::EQ: + return mProfile->hasEqOperator(); + case AnalyserEquationAst::Type::NEQ: + return mProfile->hasNeqOperator(); + case AnalyserEquationAst::Type::LT: + return mProfile->hasLtOperator(); + case AnalyserEquationAst::Type::LEQ: + return mProfile->hasLeqOperator(); + case AnalyserEquationAst::Type::GT: + return mProfile->hasGtOperator(); + case AnalyserEquationAst::Type::GEQ: + return mProfile->hasGeqOperator(); + default: + return false; + } } bool Generator::GeneratorImpl::isAndOperator(const AnalyserEquationAstPtr &ast) const { return (ast->type() == AnalyserEquationAst::Type::AND) - && mLockedProfile->hasAndOperator(); + && mProfile->hasAndOperator(); } bool Generator::GeneratorImpl::isOrOperator(const AnalyserEquationAstPtr &ast) const { return (ast->type() == AnalyserEquationAst::Type::OR) - && mLockedProfile->hasOrOperator(); + && mProfile->hasOrOperator(); } bool Generator::GeneratorImpl::isXorOperator(const AnalyserEquationAstPtr &ast) const { return (ast->type() == AnalyserEquationAst::Type::XOR) - && mLockedProfile->hasXorOperator(); + && mProfile->hasXorOperator(); } bool Generator::GeneratorImpl::isLogicalOperator(const AnalyserEquationAstPtr &ast) const @@ -159,19 +205,19 @@ bool Generator::GeneratorImpl::isDivideOperator(const AnalyserEquationAstPtr &as bool Generator::GeneratorImpl::isPowerOperator(const AnalyserEquationAstPtr &ast) const { return (ast->type() == AnalyserEquationAst::Type::POWER) - && mLockedProfile->hasPowerOperator(); + && mProfile->hasPowerOperator(); } bool Generator::GeneratorImpl::isRootOperator(const AnalyserEquationAstPtr &ast) const { return (ast->type() == AnalyserEquationAst::Type::ROOT) - && mLockedProfile->hasPowerOperator(); + && mProfile->hasPowerOperator(); } bool Generator::GeneratorImpl::isPiecewiseStatement(const AnalyserEquationAstPtr &ast) const { return (ast->type() == AnalyserEquationAst::Type::PIECEWISE) - && mLockedProfile->hasConditionalOperator(); + && mProfile->hasConditionalOperator(); } void Generator::GeneratorImpl::updateVariableInfoSizes(size_t &componentSize, @@ -179,9 +225,10 @@ void Generator::GeneratorImpl::updateVariableInfoSizes(size_t &componentSize, size_t &unitsSize, const AnalyserVariablePtr &variable) const { - auto variableComponentSize = owningComponent(variable->variable())->name().length() + 1; - auto variableNameSize = variable->variable()->name().length() + 1; - auto variableUnitsSize = variable->variable()->units()->name().length() + 1; + auto variableVariable = variable->variable(); + auto variableComponentSize = owningComponent(variableVariable)->name().length() + 1; + auto variableNameSize = variableVariable->name().length() + 1; + auto variableUnitsSize = variableVariable->units()->name().length() + 1; // Note: +1 to account for the end of string termination. componentSize = (componentSize > variableComponentSize) ? componentSize : variableComponentSize; @@ -191,57 +238,56 @@ void Generator::GeneratorImpl::updateVariableInfoSizes(size_t &componentSize, bool Generator::GeneratorImpl::modifiedProfile() const { - std::string profileContents = generatorProfileAsString(mLockedProfile); + std::string profileContents = generatorProfileAsString(mProfile); - return (mLockedProfile->profile() == GeneratorProfile::Profile::C) ? + return (mProfile->profile() == GeneratorProfile::Profile::C) ? sha1(profileContents) != C_GENERATOR_PROFILE_SHA1 : sha1(profileContents) != PYTHON_GENERATOR_PROFILE_SHA1; } +std::string Generator::GeneratorImpl::newLineIfNeeded() +{ + return mCode.empty() ? "" : "\n"; +} + void Generator::GeneratorImpl::addOriginCommentCode() { - if (!mLockedProfile->commentString().empty() - && !mLockedProfile->originCommentString().empty()) { + if (!mProfile->commentString().empty() + && !mProfile->originCommentString().empty()) { std::string profileInformation = modifiedProfile() ? "a modified " : "the "; - profileInformation += (mLockedProfile->profile() == GeneratorProfile::Profile::C) ? + profileInformation += (mProfile->profile() == GeneratorProfile::Profile::C) ? "C" : "Python"; profileInformation += " profile of"; - mCode += replace(mLockedProfile->commentString(), - "[CODE]", replace(replace(mLockedProfile->originCommentString(), "[PROFILE_INFORMATION]", profileInformation), "[LIBCELLML_VERSION]", versionString())); + mCode += replace(mProfile->commentString(), + "[CODE]", replace(replace(mProfile->originCommentString(), "[PROFILE_INFORMATION]", profileInformation), "[LIBCELLML_VERSION]", versionString())); } } void Generator::GeneratorImpl::addInterfaceHeaderCode() { - if (!mLockedProfile->interfaceHeaderString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->interfaceHeaderString(); + if (!mProfile->interfaceHeaderString().empty()) { + mCode += newLineIfNeeded() + + mProfile->interfaceHeaderString(); } } void Generator::GeneratorImpl::addImplementationHeaderCode() { - bool hasInterfaceFileName = mLockedProfile->implementationHeaderString().empty() ? + auto hasInterfaceFileName = mProfile->implementationHeaderString().empty() ? false : - (mLockedProfile->implementationHeaderString().find("[INTERFACE_FILE_NAME]") != std::string::npos); + (mProfile->implementationHeaderString().find("[INTERFACE_FILE_NAME]") != std::string::npos); - if (!mLockedProfile->implementationHeaderString().empty() - && ((hasInterfaceFileName && !mLockedProfile->interfaceFileNameString().empty()) + if (!mProfile->implementationHeaderString().empty() + && ((hasInterfaceFileName && !mProfile->interfaceFileNameString().empty()) || !hasInterfaceFileName)) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += replace(mLockedProfile->implementationHeaderString(), - "[INTERFACE_FILE_NAME]", mLockedProfile->interfaceFileNameString()); + mCode += newLineIfNeeded() + + replace(mProfile->implementationHeaderString(), + "[INTERFACE_FILE_NAME]", mProfile->interfaceFileNameString()); } } @@ -249,26 +295,26 @@ void Generator::GeneratorImpl::addVersionAndLibcellmlVersionCode(bool interface) { std::string versionAndLibcellmlCode; - if ((interface && !mLockedProfile->interfaceVersionString().empty()) - || (!interface && !mLockedProfile->implementationVersionString().empty())) { + if ((interface && !mProfile->interfaceVersionString().empty()) + || (!interface && !mProfile->implementationVersionString().empty())) { if (interface) { - versionAndLibcellmlCode += mLockedProfile->interfaceVersionString(); + versionAndLibcellmlCode += mProfile->interfaceVersionString(); } else { if (modifiedProfile()) { - std::regex regEx("([0-9]+\\.[0-9]+\\.[0-9]+)"); + static const std::regex regEx("([0-9]+\\.[0-9]+\\.[0-9]+)"); - versionAndLibcellmlCode += std::regex_replace(mLockedProfile->implementationVersionString(), regEx, "$1.post0"); + versionAndLibcellmlCode += std::regex_replace(mProfile->implementationVersionString(), regEx, "$1.post0"); } else { - versionAndLibcellmlCode += mLockedProfile->implementationVersionString(); + versionAndLibcellmlCode += mProfile->implementationVersionString(); } } } - if ((interface && !mLockedProfile->interfaceLibcellmlVersionString().empty()) - || (!interface && !mLockedProfile->implementationLibcellmlVersionString().empty())) { + if ((interface && !mProfile->interfaceLibcellmlVersionString().empty()) + || (!interface && !mProfile->implementationLibcellmlVersionString().empty())) { versionAndLibcellmlCode += interface ? - mLockedProfile->interfaceLibcellmlVersionString() : - replace(mLockedProfile->implementationLibcellmlVersionString(), + mProfile->interfaceLibcellmlVersionString() : + replace(mProfile->implementationLibcellmlVersionString(), "[LIBCELLML_VERSION]", versionString()); } @@ -283,21 +329,21 @@ void Generator::GeneratorImpl::addStateAndVariableCountCode(bool interface) { std::string stateAndVariableCountCode; - if ((mLockedModel->type() == AnalyserModel::Type::ODE) - && ((interface && !mLockedProfile->interfaceStateCountString().empty()) - || (!interface && !mLockedProfile->implementationStateCountString().empty()))) { + if (modelHasOdes() + && ((interface && !mProfile->interfaceStateCountString().empty()) + || (!interface && !mProfile->implementationStateCountString().empty()))) { stateAndVariableCountCode += interface ? - mLockedProfile->interfaceStateCountString() : - replace(mLockedProfile->implementationStateCountString(), - "[STATE_COUNT]", std::to_string(mLockedModel->stateCount())); + mProfile->interfaceStateCountString() : + replace(mProfile->implementationStateCountString(), + "[STATE_COUNT]", std::to_string(mModel->stateCount())); } - if ((interface && !mLockedProfile->interfaceVariableCountString().empty()) - || (!interface && !mLockedProfile->implementationVariableCountString().empty())) { + if ((interface && !mProfile->interfaceVariableCountString().empty()) + || (!interface && !mProfile->implementationVariableCountString().empty())) { stateAndVariableCountCode += interface ? - mLockedProfile->interfaceVariableCountString() : - replace(mLockedProfile->implementationVariableCountString(), - "[VARIABLE_COUNT]", std::to_string(mLockedModel->variableCount())); + mProfile->interfaceVariableCountString() : + replace(mProfile->implementationVariableCountString(), + "[VARIABLE_COUNT]", std::to_string(mModel->variableCount())); } if (!stateAndVariableCountCode.empty()) { @@ -309,15 +355,12 @@ void Generator::GeneratorImpl::addStateAndVariableCountCode(bool interface) void Generator::GeneratorImpl::addVariableTypeObjectCode() { - auto variableTypeObjectString = mLockedProfile->variableTypeObjectString(mLockedModel->type() == AnalyserModel::Type::ODE, - mLockedModel->hasExternalVariables()); + auto variableTypeObjectString = mProfile->variableTypeObjectString(modelHasOdes(), + mModel->hasExternalVariables()); if (!variableTypeObjectString.empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += variableTypeObjectString; + mCode += newLineIfNeeded() + + variableTypeObjectString; } } @@ -327,15 +370,15 @@ std::string Generator::GeneratorImpl::generateVariableInfoObjectCode(const std:: size_t nameSize = 0; size_t unitsSize = 0; - if (mLockedModel->type() == AnalyserModel::Type::ODE) { - updateVariableInfoSizes(componentSize, nameSize, unitsSize, mLockedModel->voi()); + if (modelHasOdes()) { + updateVariableInfoSizes(componentSize, nameSize, unitsSize, mModel->voi()); - for (const auto &state : mLockedModel->states()) { + for (const auto &state : mModel->states()) { updateVariableInfoSizes(componentSize, nameSize, unitsSize, state); } } - for (const auto &variable : mLockedModel->variables()) { + for (const auto &variable : mModel->variables()) { updateVariableInfoSizes(componentSize, nameSize, unitsSize, variable); } @@ -347,12 +390,9 @@ std::string Generator::GeneratorImpl::generateVariableInfoObjectCode(const std:: void Generator::GeneratorImpl::addVariableInfoObjectCode() { - if (!mLockedProfile->variableInfoObjectString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += generateVariableInfoObjectCode(mLockedProfile->variableInfoObjectString()); + if (!mProfile->variableInfoObjectString().empty()) { + mCode += newLineIfNeeded() + + generateVariableInfoObjectCode(mProfile->variableInfoObjectString()); } } @@ -361,7 +401,7 @@ std::string Generator::GeneratorImpl::generateVariableInfoEntryCode(const std::s const std::string &component, const std::string &type) const { - return replace(replace(replace(replace(mLockedProfile->variableInfoEntryString(), + return replace(replace(replace(replace(mProfile->variableInfoEntryString(), "[NAME]", name), "[UNITS]", units), "[COMPONENT]", component), @@ -372,18 +412,18 @@ void Generator::GeneratorImpl::addInterfaceVoiStateAndVariableInfoCode() { std::string interfaceVoiStateAndVariableInfoCode; - if ((mLockedModel->type() == AnalyserModel::Type::ODE) - && !mLockedProfile->interfaceVoiInfoString().empty()) { - interfaceVoiStateAndVariableInfoCode += mLockedProfile->interfaceVoiInfoString(); + if (modelHasOdes() + && !mProfile->interfaceVoiInfoString().empty()) { + interfaceVoiStateAndVariableInfoCode += mProfile->interfaceVoiInfoString(); } - if ((mLockedModel->type() == AnalyserModel::Type::ODE) - && !mLockedProfile->interfaceStateInfoString().empty()) { - interfaceVoiStateAndVariableInfoCode += mLockedProfile->interfaceStateInfoString(); + if (modelHasOdes() + && !mProfile->interfaceStateInfoString().empty()) { + interfaceVoiStateAndVariableInfoCode += mProfile->interfaceStateInfoString(); } - if (!mLockedProfile->interfaceVariableInfoString().empty()) { - interfaceVoiStateAndVariableInfoCode += mLockedProfile->interfaceVariableInfoString(); + if (!mProfile->interfaceVariableInfoString().empty()) { + interfaceVoiStateAndVariableInfoCode += mProfile->interfaceVariableInfoString(); } if (!interfaceVoiStateAndVariableInfoCode.empty()) { @@ -395,98 +435,100 @@ void Generator::GeneratorImpl::addInterfaceVoiStateAndVariableInfoCode() void Generator::GeneratorImpl::addImplementationVoiInfoCode() { - if ((mLockedModel->type() == AnalyserModel::Type::ODE) - && !mLockedProfile->implementationVoiInfoString().empty() - && !mLockedProfile->variableInfoEntryString().empty() - && !mLockedProfile->variableOfIntegrationVariableTypeString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } + if (modelHasOdes() + && !mProfile->implementationVoiInfoString().empty() + && !mProfile->variableInfoEntryString().empty() + && !mProfile->variableOfIntegrationVariableTypeString().empty()) { + auto voiVariable = mModel->voi()->variable(); + auto name = voiVariable->name(); + auto units = voiVariable->units()->name(); + auto component = owningComponent(voiVariable)->name(); + auto type = mProfile->variableOfIntegrationVariableTypeString(); - auto name = mLockedModel->voi()->variable()->name(); - auto units = mLockedModel->voi()->variable()->units()->name(); - auto component = owningComponent(mLockedModel->voi()->variable())->name(); - auto type = mLockedProfile->variableOfIntegrationVariableTypeString(); - - mCode += replace(mLockedProfile->implementationVoiInfoString(), - "[CODE]", generateVariableInfoEntryCode(name, units, component, type)); + mCode += newLineIfNeeded() + + replace(mProfile->implementationVoiInfoString(), + "[CODE]", generateVariableInfoEntryCode(name, units, component, type)); } } void Generator::GeneratorImpl::addImplementationStateInfoCode() { - if ((mLockedModel->type() == AnalyserModel::Type::ODE) - && !mLockedProfile->implementationStateInfoString().empty() - && !mLockedProfile->variableInfoEntryString().empty() - && !mLockedProfile->stateVariableTypeString().empty() - && !mLockedProfile->arrayElementSeparatorString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - + if (modelHasOdes() + && !mProfile->implementationStateInfoString().empty() + && !mProfile->variableInfoEntryString().empty() + && !mProfile->stateVariableTypeString().empty() + && !mProfile->arrayElementSeparatorString().empty()) { std::string infoElementsCode; - auto type = mLockedProfile->stateVariableTypeString(); + auto type = mProfile->stateVariableTypeString(); - for (const auto &state : mLockedModel->states()) { + for (const auto &state : mModel->states()) { if (!infoElementsCode.empty()) { - infoElementsCode += mLockedProfile->arrayElementSeparatorString() + "\n"; + infoElementsCode += mProfile->arrayElementSeparatorString() + "\n"; } - infoElementsCode += mLockedProfile->indentString() - + generateVariableInfoEntryCode(state->variable()->name(), - state->variable()->units()->name(), - owningComponent(state->variable())->name(), + auto stateVariable = state->variable(); + + infoElementsCode += mProfile->indentString() + + generateVariableInfoEntryCode(stateVariable->name(), + stateVariable->units()->name(), + owningComponent(stateVariable)->name(), type); } - if (!infoElementsCode.empty()) { - infoElementsCode += "\n"; - } + infoElementsCode += "\n"; - mCode += replace(mLockedProfile->implementationStateInfoString(), - "[CODE]", infoElementsCode); + mCode += newLineIfNeeded() + + replace(mProfile->implementationStateInfoString(), + "[CODE]", infoElementsCode); } } void Generator::GeneratorImpl::addImplementationVariableInfoCode() { - if (!mLockedProfile->implementationVariableInfoString().empty() - && !mLockedProfile->variableInfoEntryString().empty() - && !mLockedProfile->arrayElementSeparatorString().empty() - && !mLockedProfile->variableOfIntegrationVariableTypeString().empty() - && !mLockedProfile->stateVariableTypeString().empty() - && !mLockedProfile->constantVariableTypeString().empty() - && !mLockedProfile->computedConstantVariableTypeString().empty() - && !mLockedProfile->algebraicVariableTypeString().empty() - && !mLockedProfile->externalVariableTypeString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - + if (!mProfile->implementationVariableInfoString().empty() + && !mProfile->variableInfoEntryString().empty() + && !mProfile->arrayElementSeparatorString().empty() + && !mProfile->variableOfIntegrationVariableTypeString().empty() + && !mProfile->stateVariableTypeString().empty() + && !mProfile->constantVariableTypeString().empty() + && !mProfile->computedConstantVariableTypeString().empty() + && !mProfile->algebraicVariableTypeString().empty() + && !mProfile->externalVariableTypeString().empty()) { std::string infoElementsCode; - for (const auto &variable : mLockedModel->variables()) { + for (const auto &variable : mModel->variables()) { if (!infoElementsCode.empty()) { - infoElementsCode += mLockedProfile->arrayElementSeparatorString() + "\n"; + infoElementsCode += mProfile->arrayElementSeparatorString() + "\n"; } std::string variableType; - if (variable->type() == AnalyserVariable::Type::CONSTANT) { - variableType = mLockedProfile->constantVariableTypeString(); - } else if (variable->type() == AnalyserVariable::Type::COMPUTED_CONSTANT) { - variableType = mLockedProfile->computedConstantVariableTypeString(); - } else if (variable->type() == AnalyserVariable::Type::ALGEBRAIC) { - variableType = mLockedProfile->algebraicVariableTypeString(); - } else if (variable->type() == AnalyserVariable::Type::EXTERNAL) { - variableType = mLockedProfile->externalVariableTypeString(); + switch (variable->type()) { + case AnalyserVariable::Type::CONSTANT: + variableType = mProfile->constantVariableTypeString(); + + break; + case AnalyserVariable::Type::COMPUTED_CONSTANT: + variableType = mProfile->computedConstantVariableTypeString(); + + break; + case AnalyserVariable::Type::ALGEBRAIC: + variableType = mProfile->algebraicVariableTypeString(); + + break; + default: // AnalyserVariable::Type::EXTERNAL. + variableType = mProfile->externalVariableTypeString(); + + break; } - infoElementsCode += mLockedProfile->indentString() - + replace(replace(replace(replace(mLockedProfile->variableInfoEntryString(), - "[NAME]", variable->variable()->name()), - "[UNITS]", variable->variable()->units()->name()), - "[COMPONENT]", owningComponent(variable->variable())->name()), + auto variableVariable = variable->variable(); + + infoElementsCode += mProfile->indentString() + + replace(replace(replace(replace(mProfile->variableInfoEntryString(), + "[NAME]", variableVariable->name()), + "[UNITS]", variableVariable->units()->name()), + "[COMPONENT]", owningComponent(variableVariable)->name()), "[TYPE]", variableType); } @@ -494,230 +536,159 @@ void Generator::GeneratorImpl::addImplementationVariableInfoCode() infoElementsCode += "\n"; } - mCode += replace(mLockedProfile->implementationVariableInfoString(), - "[CODE]", infoElementsCode); + mCode += newLineIfNeeded() + + replace(mProfile->implementationVariableInfoString(), + "[CODE]", infoElementsCode); } } void Generator::GeneratorImpl::addArithmeticFunctionsCode() { - if (mLockedModel->needEqFunction() && !mLockedProfile->hasEqOperator() - && !mLockedProfile->eqFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->eqFunctionString(); + if (mModel->needEqFunction() && !mProfile->hasEqOperator() + && !mProfile->eqFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->eqFunctionString(); } - if (mLockedModel->needNeqFunction() && !mLockedProfile->hasNeqOperator() - && !mLockedProfile->neqFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->neqFunctionString(); + if (mModel->needNeqFunction() && !mProfile->hasNeqOperator() + && !mProfile->neqFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->neqFunctionString(); } - if (mLockedModel->needLtFunction() && !mLockedProfile->hasLtOperator() - && !mLockedProfile->ltFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->ltFunctionString(); + if (mModel->needLtFunction() && !mProfile->hasLtOperator() + && !mProfile->ltFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->ltFunctionString(); } - if (mLockedModel->needLeqFunction() && !mLockedProfile->hasLeqOperator() - && !mLockedProfile->leqFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->leqFunctionString(); + if (mModel->needLeqFunction() && !mProfile->hasLeqOperator() + && !mProfile->leqFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->leqFunctionString(); } - if (mLockedModel->needGtFunction() && !mLockedProfile->hasGtOperator() - && !mLockedProfile->gtFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->gtFunctionString(); + if (mModel->needGtFunction() && !mProfile->hasGtOperator() + && !mProfile->gtFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->gtFunctionString(); } - if (mLockedModel->needGeqFunction() && !mLockedProfile->hasGeqOperator() - && !mLockedProfile->geqFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->geqFunctionString(); + if (mModel->needGeqFunction() && !mProfile->hasGeqOperator() + && !mProfile->geqFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->geqFunctionString(); } - if (mLockedModel->needAndFunction() && !mLockedProfile->hasAndOperator() - && !mLockedProfile->andFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->andFunctionString(); + if (mModel->needAndFunction() && !mProfile->hasAndOperator() + && !mProfile->andFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->andFunctionString(); } - if (mLockedModel->needOrFunction() && !mLockedProfile->hasOrOperator() - && !mLockedProfile->orFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->orFunctionString(); + if (mModel->needOrFunction() && !mProfile->hasOrOperator() + && !mProfile->orFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->orFunctionString(); } - if (mLockedModel->needXorFunction() && !mLockedProfile->hasXorOperator() - && !mLockedProfile->xorFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->xorFunctionString(); + if (mModel->needXorFunction() && !mProfile->hasXorOperator() + && !mProfile->xorFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->xorFunctionString(); } - if (mLockedModel->needNotFunction() && !mLockedProfile->hasNotOperator() - && !mLockedProfile->notFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->notFunctionString(); + if (mModel->needNotFunction() && !mProfile->hasNotOperator() + && !mProfile->notFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->notFunctionString(); } - if (mLockedModel->needMinFunction() - && !mLockedProfile->minFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->minFunctionString(); + if (mModel->needMinFunction() + && !mProfile->minFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->minFunctionString(); } - if (mLockedModel->needMaxFunction() - && !mLockedProfile->maxFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->maxFunctionString(); + if (mModel->needMaxFunction() + && !mProfile->maxFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->maxFunctionString(); } } void Generator::GeneratorImpl::addTrigonometricFunctionsCode() { - if (mLockedModel->needSecFunction() - && !mLockedProfile->secFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->secFunctionString(); + if (mModel->needSecFunction() + && !mProfile->secFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->secFunctionString(); } - if (mLockedModel->needCscFunction() - && !mLockedProfile->cscFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->cscFunctionString(); + if (mModel->needCscFunction() + && !mProfile->cscFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->cscFunctionString(); } - if (mLockedModel->needCotFunction() - && !mLockedProfile->cotFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->cotFunctionString(); + if (mModel->needCotFunction() + && !mProfile->cotFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->cotFunctionString(); } - if (mLockedModel->needSechFunction() - && !mLockedProfile->sechFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->sechFunctionString(); + if (mModel->needSechFunction() + && !mProfile->sechFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->sechFunctionString(); } - if (mLockedModel->needCschFunction() - && !mLockedProfile->cschFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->cschFunctionString(); + if (mModel->needCschFunction() + && !mProfile->cschFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->cschFunctionString(); } - if (mLockedModel->needCothFunction() - && !mLockedProfile->cothFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->cothFunctionString(); + if (mModel->needCothFunction() + && !mProfile->cothFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->cothFunctionString(); } - if (mLockedModel->needAsecFunction() - && !mLockedProfile->asecFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->asecFunctionString(); + if (mModel->needAsecFunction() + && !mProfile->asecFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->asecFunctionString(); } - if (mLockedModel->needAcscFunction() - && !mLockedProfile->acscFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->acscFunctionString(); + if (mModel->needAcscFunction() + && !mProfile->acscFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->acscFunctionString(); } - if (mLockedModel->needAcotFunction() - && !mLockedProfile->acotFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->acotFunctionString(); + if (mModel->needAcotFunction() + && !mProfile->acotFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->acotFunctionString(); } - if (mLockedModel->needAsechFunction() - && !mLockedProfile->asechFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->asechFunctionString(); + if (mModel->needAsechFunction() + && !mProfile->asechFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->asechFunctionString(); } - if (mLockedModel->needAcschFunction() - && !mLockedProfile->acschFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->acschFunctionString(); + if (mModel->needAcschFunction() + && !mProfile->acschFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->acschFunctionString(); } - if (mLockedModel->needAcothFunction() - && !mLockedProfile->acothFunctionString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->acothFunctionString(); + if (mModel->needAcothFunction() + && !mProfile->acothFunctionString().empty()) { + mCode += newLineIfNeeded() + + mProfile->acothFunctionString(); } } @@ -725,17 +696,17 @@ void Generator::GeneratorImpl::addInterfaceCreateDeleteArrayMethodsCode() { std::string interfaceCreateDeleteArraysCode; - if ((mLockedModel->type() == AnalyserModel::Type::ODE) - && !mLockedProfile->interfaceCreateStatesArrayMethodString().empty()) { - interfaceCreateDeleteArraysCode += mLockedProfile->interfaceCreateStatesArrayMethodString(); + if (modelHasOdes() + && !mProfile->interfaceCreateStatesArrayMethodString().empty()) { + interfaceCreateDeleteArraysCode += mProfile->interfaceCreateStatesArrayMethodString(); } - if (!mLockedProfile->interfaceCreateVariablesArrayMethodString().empty()) { - interfaceCreateDeleteArraysCode += mLockedProfile->interfaceCreateVariablesArrayMethodString(); + if (!mProfile->interfaceCreateVariablesArrayMethodString().empty()) { + interfaceCreateDeleteArraysCode += mProfile->interfaceCreateVariablesArrayMethodString(); } - if (!mLockedProfile->interfaceDeleteArrayMethodString().empty()) { - interfaceCreateDeleteArraysCode += mLockedProfile->interfaceDeleteArrayMethodString(); + if (!mProfile->interfaceDeleteArrayMethodString().empty()) { + interfaceCreateDeleteArraysCode += mProfile->interfaceDeleteArrayMethodString(); } if (!interfaceCreateDeleteArraysCode.empty()) { @@ -747,56 +718,164 @@ void Generator::GeneratorImpl::addInterfaceCreateDeleteArrayMethodsCode() void Generator::GeneratorImpl::addExternalVariableMethodTypeDefinitionCode() { - if (mLockedModel->hasExternalVariables()) { - auto externalVariableMethodTypeDefinitionString = mLockedProfile->externalVariableMethodTypeDefinitionString(mLockedModel->type() == AnalyserModel::Type::ODE); + if (mModel->hasExternalVariables()) { + auto externalVariableMethodTypeDefinitionString = mProfile->externalVariableMethodTypeDefinitionString(modelHasOdes()); if (!externalVariableMethodTypeDefinitionString.empty()) { - mCode += "\n"; - mCode += externalVariableMethodTypeDefinitionString; + mCode += "\n" + + externalVariableMethodTypeDefinitionString; } } } void Generator::GeneratorImpl::addImplementationCreateStatesArrayMethodCode() { - if ((mLockedModel->type() == AnalyserModel::Type::ODE) - && !mLockedProfile->implementationCreateStatesArrayMethodString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->implementationCreateStatesArrayMethodString(); + if (modelHasOdes() + && !mProfile->implementationCreateStatesArrayMethodString().empty()) { + mCode += newLineIfNeeded() + + mProfile->implementationCreateStatesArrayMethodString(); } } void Generator::GeneratorImpl::addImplementationCreateVariablesArrayMethodCode() { - if (!mLockedProfile->implementationCreateVariablesArrayMethodString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - - mCode += mLockedProfile->implementationCreateVariablesArrayMethodString(); + if (!mProfile->implementationCreateVariablesArrayMethodString().empty()) { + mCode += newLineIfNeeded() + + mProfile->implementationCreateVariablesArrayMethodString(); } } void Generator::GeneratorImpl::addImplementationDeleteArrayMethodCode() { - if (!mLockedProfile->implementationDeleteArrayMethodString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } + if (!mProfile->implementationDeleteArrayMethodString().empty()) { + mCode += newLineIfNeeded() + + mProfile->implementationDeleteArrayMethodString(); + } +} - mCode += mLockedProfile->implementationDeleteArrayMethodString(); +void Generator::GeneratorImpl::addRootFindingInfoObjectCode() +{ + if (modelHasNlas() + && !mProfile->rootFindingInfoObjectString(modelHasOdes()).empty()) { + mCode += newLineIfNeeded() + + mProfile->rootFindingInfoObjectString(modelHasOdes()); + } +} + +void Generator::GeneratorImpl::addExternNlaSolveMethodCode() +{ + if (modelHasNlas() + && !mProfile->externNlaSolveMethodString().empty()) { + mCode += newLineIfNeeded() + + mProfile->externNlaSolveMethodString(); + } +} + +void Generator::GeneratorImpl::addNlaSystemsCode() +{ + if (modelHasNlas() + && !mProfile->objectiveFunctionMethodString(modelHasOdes()).empty() + && !mProfile->findRootMethodString(modelHasOdes()).empty() + && !mProfile->nlaSolveCallString(modelHasOdes()).empty()) { + std::vector handledNlaEquations; + + for (const auto &equation : mModel->equations()) { + if ((equation->type() == AnalyserEquation::Type::NLA) + && (std::find(handledNlaEquations.begin(), handledNlaEquations.end(), equation) == handledNlaEquations.end())) { + std::string methodBody; + auto i = MAX_SIZE_T; + auto variables = equation->variables(); + auto variablesSize = variables.size(); + + for (i = 0; i < variablesSize; ++i) { + auto arrayString = (variables[i]->type() == AnalyserVariable::Type::STATE) ? + mProfile->ratesArrayString() : + mProfile->variablesArrayString(); + + methodBody += mProfile->indentString() + + arrayString + mProfile->openArrayString() + convertToString(variables[i]->index()) + mProfile->closeArrayString() + + mProfile->equalityString() + + mProfile->uArrayString() + mProfile->openArrayString() + convertToString(i) + mProfile->closeArrayString() + + mProfile->commandSeparatorString() + "\n"; + } + + methodBody += newLineIfNeeded(); + + i = MAX_SIZE_T; + + methodBody += mProfile->indentString() + + mProfile->fArrayString() + mProfile->openArrayString() + convertToString(++i) + mProfile->closeArrayString() + + mProfile->equalityString() + + generateCode(equation->ast()) + + mProfile->commandSeparatorString() + "\n"; + + handledNlaEquations.push_back(equation); + + for (const auto &nlaSibling : equation->nlaSiblings()) { + methodBody += mProfile->indentString() + + mProfile->fArrayString() + mProfile->openArrayString() + convertToString(++i) + mProfile->closeArrayString() + + mProfile->equalityString() + + generateCode(nlaSibling->ast()) + + mProfile->commandSeparatorString() + "\n"; + + handledNlaEquations.push_back(nlaSibling); + } + + mCode += newLineIfNeeded() + + replace(replace(mProfile->objectiveFunctionMethodString(modelHasOdes()), + "[INDEX]", convertToString(equation->nlaSystemIndex())), + "[CODE]", generateMethodBodyCode(methodBody)); + + methodBody = {}; + + for (i = 0; i < variablesSize; ++i) { + auto arrayString = (variables[i]->type() == AnalyserVariable::Type::STATE) ? + mProfile->ratesArrayString() : + mProfile->variablesArrayString(); + + methodBody += mProfile->indentString() + + mProfile->uArrayString() + mProfile->openArrayString() + convertToString(i) + mProfile->closeArrayString() + + mProfile->equalityString() + + arrayString + mProfile->openArrayString() + convertToString(variables[i]->index()) + mProfile->closeArrayString() + + mProfile->commandSeparatorString() + "\n"; + } + + methodBody += newLineIfNeeded() + + mProfile->indentString() + + replace(replace(mProfile->nlaSolveCallString(modelHasOdes()), + "[INDEX]", convertToString(equation->nlaSystemIndex())), + "[SIZE]", convertToString(equation->variableCount())); + + methodBody += newLineIfNeeded(); + + for (i = 0; i < variablesSize; ++i) { + auto arrayString = (variables[i]->type() == AnalyserVariable::Type::STATE) ? + mProfile->ratesArrayString() : + mProfile->variablesArrayString(); + + methodBody += mProfile->indentString() + + arrayString + mProfile->openArrayString() + convertToString(variables[i]->index()) + mProfile->closeArrayString() + + mProfile->equalityString() + + mProfile->uArrayString() + mProfile->openArrayString() + convertToString(i) + mProfile->closeArrayString() + + mProfile->commandSeparatorString() + "\n"; + } + + mCode += newLineIfNeeded() + + replace(replace(replace(mProfile->findRootMethodString(modelHasOdes()), + "[INDEX]", convertToString(equation->nlaSystemIndex())), + "[SIZE]", convertToString(variablesSize)), + "[CODE]", generateMethodBodyCode(methodBody)); + } + } } } std::string Generator::GeneratorImpl::generateMethodBodyCode(const std::string &methodBody) const { return methodBody.empty() ? - mLockedProfile->emptyMethodString().empty() ? + mProfile->emptyMethodString().empty() ? "" : - mLockedProfile->indentString() + mLockedProfile->emptyMethodString() : + mProfile->indentString() + mProfile->emptyMethodString() : methodBody; } @@ -823,46 +902,39 @@ std::string Generator::GeneratorImpl::generateDoubleOrConstantVariableNameCode(c auto initValueVariable = owningComponent(variable)->variable(variable->initialValue()); auto analyserInitialValueVariable = analyserVariable(initValueVariable); - std::ostringstream index; - index << analyserInitialValueVariable->index(); - - return mLockedProfile->variablesArrayString() + mLockedProfile->openArrayString() + index.str() + mLockedProfile->closeArrayString(); + return mProfile->variablesArrayString() + mProfile->openArrayString() + convertToString(analyserInitialValueVariable->index()) + mProfile->closeArrayString(); } std::string Generator::GeneratorImpl::generateVariableNameCode(const VariablePtr &variable, - const AnalyserEquationAstPtr &ast) const + bool state) const { // Generate some code for a variable name, but only if we have a model. If // we don't have a model, it means that we are using the generator from the // analyser, in which case we just want to return the original name of the // variable. - if (mLockedModel == nullptr) { + if (mModel == nullptr) { return variable->name(); } auto analyserVariable = Generator::GeneratorImpl::analyserVariable(variable); if (analyserVariable->type() == AnalyserVariable::Type::VARIABLE_OF_INTEGRATION) { - return mLockedProfile->voiString(); + return mProfile->voiString(); } std::string arrayName; if (analyserVariable->type() == AnalyserVariable::Type::STATE) { - arrayName = ((ast != nullptr) && (ast->parent()->type() == AnalyserEquationAst::Type::DIFF)) ? - mLockedProfile->ratesArrayString() : - mLockedProfile->statesArrayString(); + arrayName = state ? + mProfile->statesArrayString() : + mProfile->ratesArrayString(); } else { - arrayName = mLockedProfile->variablesArrayString(); + arrayName = mProfile->variablesArrayString(); } - std::ostringstream index; - - index << analyserVariable->index(); - - return arrayName + mLockedProfile->openArrayString() + index.str() + mLockedProfile->closeArrayString(); + return arrayName + mProfile->openArrayString() + convertToString(analyserVariable->index()) + mProfile->closeArrayString(); } std::string Generator::GeneratorImpl::generateOperatorCode(const std::string &op, @@ -870,6 +942,7 @@ std::string Generator::GeneratorImpl::generateOperatorCode(const std::string &op { // Generate the code for the left and right branches of the given AST. + std::string res; auto astLeftChild = ast->leftChild(); auto astRightChild = ast->rightChild(); auto astLeftChildCode = generateCode(astLeftChild); @@ -910,10 +983,12 @@ std::string Generator::GeneratorImpl::generateOperatorCode(const std::string &op astLeftChildCode = "(" + astLeftChildCode + ")"; } - if (isRelationalOperator(astRightChild) + if (isNegativeNumber(astRightChild) + || isRelationalOperator(astRightChild) || isLogicalOperator(astRightChild) || isMinusOperator(astRightChild) - || isPiecewiseStatement(astRightChild)) { + || isPiecewiseStatement(astRightChild) + || (astRightChildCode.rfind(mProfile->minusString(), 0) == 0)) { astRightChildCode = "(" + astRightChildCode + ")"; } else if (isPlusOperator(astRightChild)) { if (astRightChild->rightChild() != nullptr) { @@ -967,8 +1042,8 @@ std::string Generator::GeneratorImpl::generateOperatorCode(const std::string &op } } } else if (isAndOperator(ast)) { - // Note: according to the precedence rules above, we only need to add - // parentheses around OR and PIECEWISE. However, it looks + // Note: according to the precedence rules above, we only need to + // add parentheses around OR and PIECEWISE. However, it looks // better/clearer to have some around some other operators // (agreed, this is somewhat subjective). @@ -1004,10 +1079,10 @@ std::string Generator::GeneratorImpl::generateOperatorCode(const std::string &op astRightChildCode = "(" + astRightChildCode + ")"; } } else if (isOrOperator(ast)) { - // Note: according to the precedence rules above, we only need to add - // parentheses around PIECEWISE. However, it looks better/clearer - // to have some around some other operators (agreed, this is - // somewhat subjective). + // Note: according to the precedence rules above, we only need to + // add parentheses around PIECEWISE. However, it looks + // better/clearer to have some around some other operators + // (agreed, this is somewhat subjective). if (isRelationalOperator(astLeftChild) || isAndOperator(astLeftChild) @@ -1041,10 +1116,10 @@ std::string Generator::GeneratorImpl::generateOperatorCode(const std::string &op astRightChildCode = "(" + astRightChildCode + ")"; } } else if (isXorOperator(ast)) { - // Note: according to the precedence rules above, we only need to add - // parentheses around AND, OR and PIECEWISE. However, it looks - // better/clearer to have some around some other operators - // (agreed, this is somewhat subjective). + // Note: according to the precedence rules above, we only need to + // add parentheses around AND, OR and PIECEWISE. However, it + // looks better/clearer to have some around some other + // operators (agreed, this is somewhat subjective). if (isRelationalOperator(astLeftChild) || isAndOperator(astLeftChild) @@ -1159,7 +1234,7 @@ std::string Generator::GeneratorImpl::generateMinusUnaryCode(const AnalyserEquat code = "(" + code + ")"; } - return mLockedProfile->minusString() + code; + return mProfile->minusString() + code; } std::string Generator::GeneratorImpl::generateOneParameterFunctionCode(const std::string &function, @@ -1177,115 +1252,120 @@ std::string Generator::GeneratorImpl::generateTwoParameterFunctionCode(const std std::string Generator::GeneratorImpl::generatePiecewiseIfCode(const std::string &condition, const std::string &value) const { - return replace(replace(mLockedProfile->hasConditionalOperator() ? - mLockedProfile->conditionalOperatorIfString() : - mLockedProfile->piecewiseIfString(), + return replace(replace(mProfile->hasConditionalOperator() ? + mProfile->conditionalOperatorIfString() : + mProfile->piecewiseIfString(), "[CONDITION]", condition), "[IF_STATEMENT]", value); } std::string Generator::GeneratorImpl::generatePiecewiseElseCode(const std::string &value) const { - return replace(mLockedProfile->hasConditionalOperator() ? - mLockedProfile->conditionalOperatorElseString() : - mLockedProfile->piecewiseElseString(), + return replace(mProfile->hasConditionalOperator() ? + mProfile->conditionalOperatorElseString() : + mProfile->piecewiseElseString(), "[ELSE_STATEMENT]", value); } std::string Generator::GeneratorImpl::generateCode(const AnalyserEquationAstPtr &ast) const { // Generate the code for the given AST. + // Note: AnalyserEquationAst::Type::BVAR is only relevant when there is no + // model (in which case we want to generate something like dx/dt, as + // is in the case of the analyser when we want to mention an equation) + // since otherwise we don't need to generate any code for it (since we + // will, instead, want to generate something like rates[0]). std::string code; switch (ast->type()) { - case AnalyserEquationAst::Type::ASSIGNMENT: - code = generateOperatorCode(mLockedProfile->assignmentString(), ast); + case AnalyserEquationAst::Type::EQUALITY: + code = generateOperatorCode(mProfile->equalityString(), ast); break; case AnalyserEquationAst::Type::EQ: - if (mLockedProfile->hasEqOperator()) { - code = generateOperatorCode(mLockedProfile->eqString(), ast); + if (mProfile->hasEqOperator()) { + code = generateOperatorCode(mProfile->eqString(), ast); } else { - code = generateTwoParameterFunctionCode(mLockedProfile->eqString(), ast); + code = generateTwoParameterFunctionCode(mProfile->eqString(), ast); } break; case AnalyserEquationAst::Type::NEQ: - if (mLockedProfile->hasNeqOperator()) { - code = generateOperatorCode(mLockedProfile->neqString(), ast); + if (mProfile->hasNeqOperator()) { + code = generateOperatorCode(mProfile->neqString(), ast); } else { - code = generateTwoParameterFunctionCode(mLockedProfile->neqString(), ast); + code = generateTwoParameterFunctionCode(mProfile->neqString(), ast); } break; case AnalyserEquationAst::Type::LT: - if (mLockedProfile->hasLtOperator()) { - code = generateOperatorCode(mLockedProfile->ltString(), ast); + if (mProfile->hasLtOperator()) { + code = generateOperatorCode(mProfile->ltString(), ast); } else { - code = generateTwoParameterFunctionCode(mLockedProfile->ltString(), ast); + code = generateTwoParameterFunctionCode(mProfile->ltString(), ast); } break; case AnalyserEquationAst::Type::LEQ: - if (mLockedProfile->hasLeqOperator()) { - code = generateOperatorCode(mLockedProfile->leqString(), ast); + if (mProfile->hasLeqOperator()) { + code = generateOperatorCode(mProfile->leqString(), ast); } else { - code = generateTwoParameterFunctionCode(mLockedProfile->leqString(), ast); + code = generateTwoParameterFunctionCode(mProfile->leqString(), ast); } break; case AnalyserEquationAst::Type::GT: - if (mLockedProfile->hasGtOperator()) { - code = generateOperatorCode(mLockedProfile->gtString(), ast); + if (mProfile->hasGtOperator()) { + code = generateOperatorCode(mProfile->gtString(), ast); } else { - code = generateTwoParameterFunctionCode(mLockedProfile->gtString(), ast); + code = generateTwoParameterFunctionCode(mProfile->gtString(), ast); } break; case AnalyserEquationAst::Type::GEQ: - if (mLockedProfile->hasGeqOperator()) { - code = generateOperatorCode(mLockedProfile->geqString(), ast); + if (mProfile->hasGeqOperator()) { + code = generateOperatorCode(mProfile->geqString(), ast); } else { - code = generateTwoParameterFunctionCode(mLockedProfile->geqString(), ast); + code = generateTwoParameterFunctionCode(mProfile->geqString(), ast); } break; case AnalyserEquationAst::Type::AND: - if (mLockedProfile->hasAndOperator()) { - code = generateOperatorCode(mLockedProfile->andString(), ast); + if (mProfile->hasAndOperator()) { + code = generateOperatorCode(mProfile->andString(), ast); } else { - code = generateTwoParameterFunctionCode(mLockedProfile->andString(), ast); + code = generateTwoParameterFunctionCode(mProfile->andString(), ast); } break; case AnalyserEquationAst::Type::OR: - if (mLockedProfile->hasOrOperator()) { - code = generateOperatorCode(mLockedProfile->orString(), ast); + if (mProfile->hasOrOperator()) { + code = generateOperatorCode(mProfile->orString(), ast); } else { - code = generateTwoParameterFunctionCode(mLockedProfile->orString(), ast); + code = generateTwoParameterFunctionCode(mProfile->orString(), ast); } break; case AnalyserEquationAst::Type::XOR: - if (mLockedProfile->hasXorOperator()) { - code = generateOperatorCode(mLockedProfile->xorString(), ast); + if (mProfile->hasXorOperator()) { + code = generateOperatorCode(mProfile->xorString(), ast); } else { - code = generateTwoParameterFunctionCode(mLockedProfile->xorString(), ast); + code = generateTwoParameterFunctionCode(mProfile->xorString(), ast); } break; case AnalyserEquationAst::Type::NOT: - if (mLockedProfile->hasNotOperator()) { - code = mLockedProfile->notString() + generateCode(ast->leftChild()); + if (mProfile->hasNotOperator()) { + code = mProfile->notString() + generateCode(ast->leftChild()); } else { - code = generateOneParameterFunctionCode(mLockedProfile->notString(), ast); + code = generateOneParameterFunctionCode(mProfile->notString(), ast); } break; case AnalyserEquationAst::Type::PLUS: if (ast->rightChild() != nullptr) { - code = generateOperatorCode(mLockedProfile->plusString(), ast); + code = generateOperatorCode(mProfile->plusString(), ast); } else { code = generateCode(ast->leftChild()); } @@ -1293,51 +1373,49 @@ std::string Generator::GeneratorImpl::generateCode(const AnalyserEquationAstPtr break; case AnalyserEquationAst::Type::MINUS: if (ast->rightChild() != nullptr) { - code = generateOperatorCode(mLockedProfile->minusString(), ast); + code = generateOperatorCode(mProfile->minusString(), ast); } else { code = generateMinusUnaryCode(ast); } break; case AnalyserEquationAst::Type::TIMES: - code = generateOperatorCode(mLockedProfile->timesString(), ast); + code = generateOperatorCode(mProfile->timesString(), ast); break; case AnalyserEquationAst::Type::DIVIDE: - code = generateOperatorCode(mLockedProfile->divideString(), ast); + code = generateOperatorCode(mProfile->divideString(), ast); break; case AnalyserEquationAst::Type::POWER: { auto stringValue = generateCode(ast->rightChild()); - bool validConversion; - double doubleValue = convertToDouble(stringValue, &validConversion); + double doubleValue; + auto validConversion = convertToDouble(stringValue, doubleValue); if (validConversion && areEqual(doubleValue, 0.5)) { - code = generateOneParameterFunctionCode(mLockedProfile->squareRootString(), ast); + code = generateOneParameterFunctionCode(mProfile->squareRootString(), ast); } else if (validConversion && areEqual(doubleValue, 2.0) - && !mLockedProfile->squareString().empty()) { - code = generateOneParameterFunctionCode(mLockedProfile->squareString(), ast); + && !mProfile->squareString().empty()) { + code = generateOneParameterFunctionCode(mProfile->squareString(), ast); } else { - code = mLockedProfile->hasPowerOperator() ? - generateOperatorCode(mLockedProfile->powerString(), ast) : - mLockedProfile->powerString() + "(" + generateCode(ast->leftChild()) + ", " + stringValue + ")"; + code = mProfile->hasPowerOperator() ? + generateOperatorCode(mProfile->powerString(), ast) : + mProfile->powerString() + "(" + generateCode(ast->leftChild()) + ", " + stringValue + ")"; } - } - - break; + } break; case AnalyserEquationAst::Type::ROOT: { auto astRightChild = ast->rightChild(); if (astRightChild != nullptr) { auto astLeftChild = ast->leftChild(); - bool validConversion; - double doubleValue = convertToDouble(generateCode(astLeftChild), &validConversion); + double doubleValue; - if (validConversion && areEqual(doubleValue, 2.0)) { - code = mLockedProfile->squareRootString() + "(" + generateCode(astRightChild) + ")"; + if (convertToDouble(generateCode(astLeftChild), doubleValue) + && areEqual(doubleValue, 2.0)) { + code = mProfile->squareRootString() + "(" + generateCode(astRightChild) + ")"; } else { - if (mLockedProfile->hasPowerOperator()) { - code = generateOperatorCode(mLockedProfile->powerString(), ast); + if (mProfile->hasPowerOperator()) { + code = generateOperatorCode(mProfile->powerString(), ast); } else { auto rootValueAst = AnalyserEquationAst::create(); @@ -1353,25 +1431,23 @@ std::string Generator::GeneratorImpl::generateCode(const AnalyserEquationAstPtr rootValueAst->setLeftChild(leftChild); rootValueAst->setRightChild(astLeftChild->leftChild()); - code = mLockedProfile->powerString() + "(" + generateCode(astRightChild) + ", " + generateOperatorCode(mLockedProfile->divideString(), rootValueAst) + ")"; + code = mProfile->powerString() + "(" + generateCode(astRightChild) + ", " + generateOperatorCode(mProfile->divideString(), rootValueAst) + ")"; } } } else { - code = generateOneParameterFunctionCode(mLockedProfile->squareRootString(), ast); + code = generateOneParameterFunctionCode(mProfile->squareRootString(), ast); } - } - - break; + } break; case AnalyserEquationAst::Type::ABS: - code = generateOneParameterFunctionCode(mLockedProfile->absoluteValueString(), ast); + code = generateOneParameterFunctionCode(mProfile->absoluteValueString(), ast); break; case AnalyserEquationAst::Type::EXP: - code = generateOneParameterFunctionCode(mLockedProfile->exponentialString(), ast); + code = generateOneParameterFunctionCode(mProfile->exponentialString(), ast); break; case AnalyserEquationAst::Type::LN: - code = generateOneParameterFunctionCode(mLockedProfile->naturalLogarithmString(), ast); + code = generateOneParameterFunctionCode(mProfile->naturalLogarithmString(), ast); break; case AnalyserEquationAst::Type::LOG: { @@ -1379,138 +1455,140 @@ std::string Generator::GeneratorImpl::generateCode(const AnalyserEquationAstPtr if (astRightChild != nullptr) { auto stringValue = generateCode(ast->leftChild()); - bool validConversion; - double doubleValue = convertToDouble(stringValue, &validConversion); + double doubleValue; - if (validConversion && areEqual(doubleValue, 10.0)) { - code = mLockedProfile->commonLogarithmString() + "(" + generateCode(astRightChild) + ")"; + if (convertToDouble(stringValue, doubleValue) + && areEqual(doubleValue, 10.0)) { + code = mProfile->commonLogarithmString() + "(" + generateCode(astRightChild) + ")"; } else { - code = mLockedProfile->naturalLogarithmString() + "(" + generateCode(astRightChild) + ")/" + mLockedProfile->naturalLogarithmString() + "(" + stringValue + ")"; + code = mProfile->naturalLogarithmString() + "(" + generateCode(astRightChild) + ")/" + mProfile->naturalLogarithmString() + "(" + stringValue + ")"; } } else { - code = generateOneParameterFunctionCode(mLockedProfile->commonLogarithmString(), ast); + code = generateOneParameterFunctionCode(mProfile->commonLogarithmString(), ast); } - } - - break; + } break; case AnalyserEquationAst::Type::CEILING: - code = generateOneParameterFunctionCode(mLockedProfile->ceilingString(), ast); + code = generateOneParameterFunctionCode(mProfile->ceilingString(), ast); break; case AnalyserEquationAst::Type::FLOOR: - code = generateOneParameterFunctionCode(mLockedProfile->floorString(), ast); + code = generateOneParameterFunctionCode(mProfile->floorString(), ast); break; case AnalyserEquationAst::Type::MIN: - code = generateTwoParameterFunctionCode(mLockedProfile->minString(), ast); + code = generateTwoParameterFunctionCode(mProfile->minString(), ast); break; case AnalyserEquationAst::Type::MAX: - code = generateTwoParameterFunctionCode(mLockedProfile->maxString(), ast); + code = generateTwoParameterFunctionCode(mProfile->maxString(), ast); break; case AnalyserEquationAst::Type::REM: - code = generateTwoParameterFunctionCode(mLockedProfile->remString(), ast); + code = generateTwoParameterFunctionCode(mProfile->remString(), ast); break; case AnalyserEquationAst::Type::DIFF: - code = generateCode(ast->rightChild()); + if (mModel != nullptr) { + code = generateCode(ast->rightChild()); + } else { + code = "d" + generateCode(ast->rightChild()) + "/d" + generateCode(ast->leftChild()); + } break; case AnalyserEquationAst::Type::SIN: - code = generateOneParameterFunctionCode(mLockedProfile->sinString(), ast); + code = generateOneParameterFunctionCode(mProfile->sinString(), ast); break; case AnalyserEquationAst::Type::COS: - code = generateOneParameterFunctionCode(mLockedProfile->cosString(), ast); + code = generateOneParameterFunctionCode(mProfile->cosString(), ast); break; case AnalyserEquationAst::Type::TAN: - code = generateOneParameterFunctionCode(mLockedProfile->tanString(), ast); + code = generateOneParameterFunctionCode(mProfile->tanString(), ast); break; case AnalyserEquationAst::Type::SEC: - code = generateOneParameterFunctionCode(mLockedProfile->secString(), ast); + code = generateOneParameterFunctionCode(mProfile->secString(), ast); break; case AnalyserEquationAst::Type::CSC: - code = generateOneParameterFunctionCode(mLockedProfile->cscString(), ast); + code = generateOneParameterFunctionCode(mProfile->cscString(), ast); break; case AnalyserEquationAst::Type::COT: - code = generateOneParameterFunctionCode(mLockedProfile->cotString(), ast); + code = generateOneParameterFunctionCode(mProfile->cotString(), ast); break; case AnalyserEquationAst::Type::SINH: - code = generateOneParameterFunctionCode(mLockedProfile->sinhString(), ast); + code = generateOneParameterFunctionCode(mProfile->sinhString(), ast); break; case AnalyserEquationAst::Type::COSH: - code = generateOneParameterFunctionCode(mLockedProfile->coshString(), ast); + code = generateOneParameterFunctionCode(mProfile->coshString(), ast); break; case AnalyserEquationAst::Type::TANH: - code = generateOneParameterFunctionCode(mLockedProfile->tanhString(), ast); + code = generateOneParameterFunctionCode(mProfile->tanhString(), ast); break; case AnalyserEquationAst::Type::SECH: - code = generateOneParameterFunctionCode(mLockedProfile->sechString(), ast); + code = generateOneParameterFunctionCode(mProfile->sechString(), ast); break; case AnalyserEquationAst::Type::CSCH: - code = generateOneParameterFunctionCode(mLockedProfile->cschString(), ast); + code = generateOneParameterFunctionCode(mProfile->cschString(), ast); break; case AnalyserEquationAst::Type::COTH: - code = generateOneParameterFunctionCode(mLockedProfile->cothString(), ast); + code = generateOneParameterFunctionCode(mProfile->cothString(), ast); break; case AnalyserEquationAst::Type::ASIN: - code = generateOneParameterFunctionCode(mLockedProfile->asinString(), ast); + code = generateOneParameterFunctionCode(mProfile->asinString(), ast); break; case AnalyserEquationAst::Type::ACOS: - code = generateOneParameterFunctionCode(mLockedProfile->acosString(), ast); + code = generateOneParameterFunctionCode(mProfile->acosString(), ast); break; case AnalyserEquationAst::Type::ATAN: - code = generateOneParameterFunctionCode(mLockedProfile->atanString(), ast); + code = generateOneParameterFunctionCode(mProfile->atanString(), ast); break; case AnalyserEquationAst::Type::ASEC: - code = generateOneParameterFunctionCode(mLockedProfile->asecString(), ast); + code = generateOneParameterFunctionCode(mProfile->asecString(), ast); break; case AnalyserEquationAst::Type::ACSC: - code = generateOneParameterFunctionCode(mLockedProfile->acscString(), ast); + code = generateOneParameterFunctionCode(mProfile->acscString(), ast); break; case AnalyserEquationAst::Type::ACOT: - code = generateOneParameterFunctionCode(mLockedProfile->acotString(), ast); + code = generateOneParameterFunctionCode(mProfile->acotString(), ast); break; case AnalyserEquationAst::Type::ASINH: - code = generateOneParameterFunctionCode(mLockedProfile->asinhString(), ast); + code = generateOneParameterFunctionCode(mProfile->asinhString(), ast); break; case AnalyserEquationAst::Type::ACOSH: - code = generateOneParameterFunctionCode(mLockedProfile->acoshString(), ast); + code = generateOneParameterFunctionCode(mProfile->acoshString(), ast); break; case AnalyserEquationAst::Type::ATANH: - code = generateOneParameterFunctionCode(mLockedProfile->atanhString(), ast); + code = generateOneParameterFunctionCode(mProfile->atanhString(), ast); break; case AnalyserEquationAst::Type::ASECH: - code = generateOneParameterFunctionCode(mLockedProfile->asechString(), ast); + code = generateOneParameterFunctionCode(mProfile->asechString(), ast); break; case AnalyserEquationAst::Type::ACSCH: - code = generateOneParameterFunctionCode(mLockedProfile->acschString(), ast); + code = generateOneParameterFunctionCode(mProfile->acschString(), ast); break; case AnalyserEquationAst::Type::ACOTH: - code = generateOneParameterFunctionCode(mLockedProfile->acothString(), ast); + code = generateOneParameterFunctionCode(mProfile->acothString(), ast); break; case AnalyserEquationAst::Type::PIECEWISE: { @@ -1518,16 +1596,14 @@ std::string Generator::GeneratorImpl::generateCode(const AnalyserEquationAstPtr if (astRightChild != nullptr) { if (astRightChild->type() == AnalyserEquationAst::Type::PIECE) { - code = generateCode(ast->leftChild()) + generatePiecewiseElseCode(generateCode(astRightChild) + generatePiecewiseElseCode(mLockedProfile->nanString())); + code = generateCode(ast->leftChild()) + generatePiecewiseElseCode(generateCode(astRightChild) + generatePiecewiseElseCode(mProfile->nanString())); } else { code = generateCode(ast->leftChild()) + generatePiecewiseElseCode(generateCode(astRightChild)); } } else { - code = generateCode(ast->leftChild()) + generatePiecewiseElseCode(mLockedProfile->nanString()); + code = generateCode(ast->leftChild()) + generatePiecewiseElseCode(mProfile->nanString()); } - } - - break; + } break; case AnalyserEquationAst::Type::PIECE: code = generatePiecewiseIfCode(generateCode(ast->rightChild()), generateCode(ast->leftChild())); @@ -1537,7 +1613,7 @@ std::string Generator::GeneratorImpl::generateCode(const AnalyserEquationAstPtr break; case AnalyserEquationAst::Type::CI: - code = generateVariableNameCode(ast->variable(), ast); + code = generateVariableNameCode(ast->variable(), ast->parent()->type() != AnalyserEquationAst::Type::DIFF); break; case AnalyserEquationAst::Type::CN: @@ -1546,32 +1622,35 @@ std::string Generator::GeneratorImpl::generateCode(const AnalyserEquationAstPtr break; case AnalyserEquationAst::Type::DEGREE: case AnalyserEquationAst::Type::LOGBASE: + code = generateCode(ast->leftChild()); + + break; case AnalyserEquationAst::Type::BVAR: code = generateCode(ast->leftChild()); break; case AnalyserEquationAst::Type::TRUE: - code = mLockedProfile->trueString(); + code = mProfile->trueString(); break; case AnalyserEquationAst::Type::FALSE: - code = mLockedProfile->falseString(); + code = mProfile->falseString(); break; case AnalyserEquationAst::Type::E: - code = mLockedProfile->eString(); + code = mProfile->eString(); break; case AnalyserEquationAst::Type::PI: - code = mLockedProfile->piString(); + code = mProfile->piString(); break; case AnalyserEquationAst::Type::INF: - code = mLockedProfile->infString(); + code = mProfile->infString(); break; - case AnalyserEquationAst::Type::NAN: - code = mLockedProfile->nanString(); + default: // AnalyserEquationAst::Type::NAN. + code = mProfile->nanString(); break; } @@ -1579,83 +1658,156 @@ std::string Generator::GeneratorImpl::generateCode(const AnalyserEquationAstPtr return code; } +bool Generator::GeneratorImpl::isToBeComputedAgain(const AnalyserEquationPtr &equation) const +{ + // NLA and algebraic equations that are state/rate-based and external + // equations are to be computed again (in the computeVariables() method). + + switch (equation->type()) { + case AnalyserEquation::Type::NLA: + case AnalyserEquation::Type::ALGEBRAIC: + return equation->isStateRateBased(); + case AnalyserEquation::Type::EXTERNAL: + return true; + default: + return false; + } +} + +bool Generator::GeneratorImpl::isSomeConstant(const AnalyserEquationPtr &equation) const +{ + switch (equation->type()) { + case AnalyserEquation::Type::TRUE_CONSTANT: + case AnalyserEquation::Type::VARIABLE_BASED_CONSTANT: + return true; + default: + return false; + } +} + +std::string Generator::GeneratorImpl::generateZeroInitialisationCode(const AnalyserVariablePtr &variable) const +{ + return mProfile->indentString() + + generateVariableNameCode(variable->variable(), false) + + mProfile->equalityString() + + "0.0" + + mProfile->commandSeparatorString() + "\n"; +} + std::string Generator::GeneratorImpl::generateInitialisationCode(const AnalyserVariablePtr &variable) const { + auto initialisingVariable = variable->initialisingVariable(); + auto scalingFactor = Generator::GeneratorImpl::scalingFactor(initialisingVariable); std::string scalingFactorCode; - auto scalingFactor = Generator::GeneratorImpl::scalingFactor(variable->initialisingVariable()); if (!areNearlyEqual(scalingFactor, 1.0)) { - scalingFactorCode = generateDoubleCode(convertToString(1.0 / scalingFactor)) + mLockedProfile->timesString(); + scalingFactorCode = generateDoubleCode(convertToString(1.0 / scalingFactor)) + mProfile->timesString(); } - return mLockedProfile->indentString() + generateVariableNameCode(variable->variable()) + " = " - + scalingFactorCode + generateDoubleOrConstantVariableNameCode(variable->initialisingVariable()) - + mLockedProfile->commandSeparatorString() + "\n"; + return mProfile->indentString() + + generateVariableNameCode(variable->variable()) + + mProfile->equalityString() + + scalingFactorCode + generateDoubleOrConstantVariableNameCode(initialisingVariable) + + mProfile->commandSeparatorString() + "\n"; } std::string Generator::GeneratorImpl::generateEquationCode(const AnalyserEquationPtr &equation, std::vector &remainingEquations, - bool forComputeVariables) const + std::vector &equationsForComputeVariables) { std::string res; if (std::find(remainingEquations.begin(), remainingEquations.end(), equation) != remainingEquations.end()) { - if ((equation->type() == AnalyserEquation::Type::RATE) - || (equation->type() == AnalyserEquation::Type::ALGEBRAIC) - || (equation->type() == AnalyserEquation::Type::EXTERNAL)) { + // Stop tracking the equation and its NLA siblings, if any. + // Note: we need to do this as soon as possible to avoid recursive + // calls, something that would happen if we were to do this at the + // end of this if statement. + + remainingEquations.erase(std::find(remainingEquations.begin(), remainingEquations.end(), equation)); + + for (const auto &nlaSibling : equation->nlaSiblings()) { + remainingEquations.erase(std::find(remainingEquations.begin(), remainingEquations.end(), nlaSibling)); + } + + // Generate any dependency that this equation may have. + // Note: this accounts for the special case of the computeVariables() + // method. + + if (!isSomeConstant(equation)) { for (const auto &dependency : equation->dependencies()) { - if ((dependency->type() != AnalyserEquation::Type::RATE) - && (!forComputeVariables - || ((dependency->type() == AnalyserEquation::Type::ALGEBRAIC) - && dependency->isStateRateBased()) - || (dependency->type() == AnalyserEquation::Type::EXTERNAL))) { - res += generateEquationCode(dependency, remainingEquations, forComputeVariables); + if ((dependency->type() != AnalyserEquation::Type::ODE) + && !isSomeConstant(dependency) + && (equationsForComputeVariables.empty() + || isToBeComputedAgain(dependency) + || (std::find(equationsForComputeVariables.begin(), equationsForComputeVariables.end(), dependency) != equationsForComputeVariables.end()))) { + res += generateEquationCode(dependency, remainingEquations, equationsForComputeVariables); } } } - if (equation->type() == AnalyserEquation::Type::EXTERNAL) { - std::ostringstream index; + // Generate the equation code itself, based on the equation type. - index << equation->variable()->index(); + switch (equation->type()) { + case AnalyserEquation::Type::EXTERNAL: + for (const auto &variable : equation->variables()) { + res += mProfile->indentString() + + generateVariableNameCode(variable->variable()) + + mProfile->equalityString() + + replace(mProfile->externalVariableMethodCallString(modelHasOdes()), + "[INDEX]", convertToString(variable->index())) + + mProfile->commandSeparatorString() + "\n"; + } - res += mLockedProfile->indentString() + generateVariableNameCode(equation->variable()->variable()) + " = " - + replace(mLockedProfile->externalVariableMethodCallString(mLockedModel->type() == AnalyserModel::Type::ODE), - "[INDEX]", index.str()) - + mLockedProfile->commandSeparatorString() + "\n"; - } else { - res += mLockedProfile->indentString() + generateCode(equation->ast()) + mLockedProfile->commandSeparatorString() + "\n"; - } + break; + case AnalyserEquation::Type::NLA: + if (!mProfile->findRootCallString(modelHasOdes()).empty()) { + res += mProfile->indentString() + + replace(mProfile->findRootCallString(modelHasOdes()), + "[INDEX]", convertToString(equation->nlaSystemIndex())); + } - remainingEquations.erase(std::find(remainingEquations.begin(), remainingEquations.end(), equation)); + break; + default: + res += mProfile->indentString() + generateCode(equation->ast()) + mProfile->commandSeparatorString() + "\n"; + + break; + } } return res; } +std::string Generator::GeneratorImpl::generateEquationCode(const AnalyserEquationPtr &equation, + std::vector &remainingEquations) +{ + std::vector dummyEquationsForComputeVariables; + + return generateEquationCode(equation, remainingEquations, dummyEquationsForComputeVariables); +} + void Generator::GeneratorImpl::addInterfaceComputeModelMethodsCode() { - auto interfaceInitialiseVariablesMethodString = mLockedProfile->interfaceInitialiseVariablesMethodString(mLockedModel->type() == AnalyserModel::Type::ODE, - mLockedModel->hasExternalVariables()); + auto interfaceInitialiseVariablesMethodString = mProfile->interfaceInitialiseVariablesMethodString(modelHasOdes(), + mModel->hasExternalVariables()); std::string interfaceComputeModelMethodsCode; if (!interfaceInitialiseVariablesMethodString.empty()) { interfaceComputeModelMethodsCode += interfaceInitialiseVariablesMethodString; } - if (!mLockedProfile->interfaceComputeComputedConstantsMethodString().empty()) { - interfaceComputeModelMethodsCode += mLockedProfile->interfaceComputeComputedConstantsMethodString(); + if (!mProfile->interfaceComputeComputedConstantsMethodString().empty()) { + interfaceComputeModelMethodsCode += mProfile->interfaceComputeComputedConstantsMethodString(); } - auto interfaceComputeRatesMethodString = mLockedProfile->interfaceComputeRatesMethodString(mLockedModel->hasExternalVariables()); + auto interfaceComputeRatesMethodString = mProfile->interfaceComputeRatesMethodString(mModel->hasExternalVariables()); - if ((mLockedModel->type() == AnalyserModel::Type::ODE) + if (modelHasOdes() && !interfaceComputeRatesMethodString.empty()) { interfaceComputeModelMethodsCode += interfaceComputeRatesMethodString; } - auto interfaceComputeVariablesMethodString = mLockedProfile->interfaceComputeVariablesMethodString(mLockedModel->type() == AnalyserModel::Type::ODE, - mLockedModel->hasExternalVariables()); + auto interfaceComputeVariablesMethodString = mProfile->interfaceComputeVariablesMethodString(modelHasOdes(), + mModel->hasExternalVariables()); if (!interfaceComputeVariablesMethodString.empty()) { interfaceComputeModelMethodsCode += interfaceComputeVariablesMethodString; @@ -1670,126 +1822,158 @@ void Generator::GeneratorImpl::addInterfaceComputeModelMethodsCode() void Generator::GeneratorImpl::addImplementationInitialiseVariablesMethodCode(std::vector &remainingEquations) { - auto implementationInitialiseVariablesMethodString = mLockedProfile->implementationInitialiseVariablesMethodString(mLockedModel->type() == AnalyserModel::Type::ODE, - mLockedModel->hasExternalVariables()); + auto implementationInitialiseVariablesMethodString = mProfile->implementationInitialiseVariablesMethodString(modelHasOdes(), + mModel->hasExternalVariables()); if (!implementationInitialiseVariablesMethodString.empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } + // Initialise our constants and our algebraic variables that have an + // initial value. Also use an initial guess of zero for computed + // constants and algebraic variables computed using an NLA system. + // Note: a variable which is the only unknown in an equation, but which + // is not on its own on either the LHS or RHS of that equation + // (e.g., x = y+z with x and y known and z unknown) is (currently) + // to be computed using an NLA system for which we need an initial + // guess. We use an initial guess of zero, which is fine since + // such an NLA system has only one solution. std::string methodBody; - for (const auto &variable : mLockedModel->variables()) { - if (variable->type() == AnalyserVariable::Type::CONSTANT) { + for (const auto &variable : mModel->variables()) { + switch (variable->type()) { + case AnalyserVariable::Type::CONSTANT: methodBody += generateInitialisationCode(variable); + + break; + case AnalyserVariable::Type::COMPUTED_CONSTANT: + case AnalyserVariable::Type::ALGEBRAIC: + if (variable->initialisingVariable() != nullptr) { + methodBody += generateInitialisationCode(variable); + } else if (variable->equation(0)->type() == AnalyserEquation::Type::NLA) { + methodBody += generateZeroInitialisationCode(variable); + } + + break; + default: // Other types we don't care about. + break; } } - for (const auto &equation : mLockedModel->equations()) { + // Initialise our true constants. + + for (const auto &equation : mModel->equations()) { if (equation->type() == AnalyserEquation::Type::TRUE_CONSTANT) { methodBody += generateEquationCode(equation, remainingEquations); } } - for (const auto &state : mLockedModel->states()) { + // Initialise our states. + + for (const auto &state : mModel->states()) { methodBody += generateInitialisationCode(state); } - if (mLockedModel->hasExternalVariables()) { - auto equations = mLockedModel->equations(); + // Use an initial guess of zero for rates computed using an NLA system + // (see the note above). + + for (const auto &state : mModel->states()) { + if (state->equation(0)->type() == AnalyserEquation::Type::NLA) { + methodBody += generateZeroInitialisationCode(state); + } + } + + // Initialise our external variables. + + if (mModel->hasExternalVariables()) { + auto equations = mModel->equations(); std::vector remainingExternalEquations; std::copy_if(equations.begin(), equations.end(), std::back_inserter(remainingExternalEquations), [](const AnalyserEquationPtr &equation) { return equation->type() == AnalyserEquation::Type::EXTERNAL; }); - for (const auto &equation : mLockedModel->equations()) { + for (const auto &equation : mModel->equations()) { if (equation->type() == AnalyserEquation::Type::EXTERNAL) { methodBody += generateEquationCode(equation, remainingExternalEquations); } } } - mCode += replace(implementationInitialiseVariablesMethodString, "[CODE]", generateMethodBodyCode(methodBody)); + mCode += newLineIfNeeded() + + replace(implementationInitialiseVariablesMethodString, + "[CODE]", generateMethodBodyCode(methodBody)); } } void Generator::GeneratorImpl::addImplementationComputeComputedConstantsMethodCode(std::vector &remainingEquations) { - if (!mLockedProfile->implementationComputeComputedConstantsMethodString().empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - + if (!mProfile->implementationComputeComputedConstantsMethodString().empty()) { std::string methodBody; - for (const auto &equation : mLockedModel->equations()) { + for (const auto &equation : mModel->equations()) { if (equation->type() == AnalyserEquation::Type::VARIABLE_BASED_CONSTANT) { methodBody += generateEquationCode(equation, remainingEquations); } } - mCode += replace(mLockedProfile->implementationComputeComputedConstantsMethodString(), - "[CODE]", generateMethodBodyCode(methodBody)); + mCode += newLineIfNeeded() + + replace(mProfile->implementationComputeComputedConstantsMethodString(), + "[CODE]", generateMethodBodyCode(methodBody)); } } void Generator::GeneratorImpl::addImplementationComputeRatesMethodCode(std::vector &remainingEquations) { - auto implementationComputeRatesMethodString = mLockedProfile->implementationComputeRatesMethodString(mLockedModel->hasExternalVariables()); + auto implementationComputeRatesMethodString = mProfile->implementationComputeRatesMethodString(mModel->hasExternalVariables()); - if ((mLockedModel->type() == AnalyserModel::Type::ODE) + if (modelHasOdes() && !implementationComputeRatesMethodString.empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - std::string methodBody; - for (const auto &equation : mLockedModel->equations()) { - if (equation->type() == AnalyserEquation::Type::RATE) { + for (const auto &equation : mModel->equations()) { + // A rate is computed either through an ODE equation or through an + // NLA equation in case the rate is not on its own on either the LHS + // or RHS of the equation. + + if ((equation->type() == AnalyserEquation::Type::ODE) + || ((equation->type() == AnalyserEquation::Type::NLA) + && (equation->variableCount() == 1) + && (equation->variable(0)->type() == AnalyserVariable::Type::STATE))) { methodBody += generateEquationCode(equation, remainingEquations); } } - mCode += replace(implementationComputeRatesMethodString, - "[CODE]", generateMethodBodyCode(methodBody)); + mCode += newLineIfNeeded() + + replace(implementationComputeRatesMethodString, + "[CODE]", generateMethodBodyCode(methodBody)); } } void Generator::GeneratorImpl::addImplementationComputeVariablesMethodCode(std::vector &remainingEquations) { - auto implementationComputeVariablesMethodString = mLockedProfile->implementationComputeVariablesMethodString(mLockedModel->type() == AnalyserModel::Type::ODE, - mLockedModel->hasExternalVariables()); + auto implementationComputeVariablesMethodString = mProfile->implementationComputeVariablesMethodString(modelHasOdes(), + mModel->hasExternalVariables()); if (!implementationComputeVariablesMethodString.empty()) { - if (!mCode.empty()) { - mCode += "\n"; - } - std::string methodBody; - auto equations = mLockedModel->equations(); + auto equations = mModel->equations(); std::vector newRemainingEquations {std::begin(equations), std::end(equations)}; for (const auto &equation : equations) { if ((std::find(remainingEquations.begin(), remainingEquations.end(), equation) != remainingEquations.end()) - || ((equation->type() == AnalyserEquation::Type::ALGEBRAIC) - && equation->isStateRateBased()) - || (equation->type() == AnalyserEquation::Type::EXTERNAL)) { - methodBody += generateEquationCode(equation, newRemainingEquations, true); + || isToBeComputedAgain(equation)) { + methodBody += generateEquationCode(equation, newRemainingEquations, remainingEquations); } } - mCode += replace(implementationComputeVariablesMethodString, - "[CODE]", generateMethodBodyCode(methodBody)); + mCode += newLineIfNeeded() + + replace(implementationComputeVariablesMethodString, + "[CODE]", generateMethodBodyCode(methodBody)); } } Generator::Generator() : mPimpl(new GeneratorImpl()) { - mPimpl->mGenerator = this; } Generator::~Generator() @@ -1804,22 +1988,17 @@ GeneratorPtr Generator::create() noexcept GeneratorProfilePtr Generator::profile() { - if (mPimpl->mOwnedProfile != nullptr) { - return mPimpl->mOwnedProfile; - } - - return mPimpl->mProfile.lock(); + return mPimpl->mProfile; } void Generator::setProfile(const GeneratorProfilePtr &profile) { - mPimpl->mOwnedProfile = nullptr; mPimpl->mProfile = profile; } AnalyserModelPtr Generator::model() { - return mPimpl->mModel.lock(); + return mPimpl->mModel; } void Generator::setModel(const AnalyserModelPtr &model) @@ -1829,17 +2008,18 @@ void Generator::setModel(const AnalyserModelPtr &model) std::string Generator::interfaceCode() const { - if (!mPimpl->retrieveLockedModelAndProfile() - || !mPimpl->mLockedModel->isValid() - || !mPimpl->mLockedProfile->hasInterface()) { - mPimpl->resetLockedModelAndProfile(); - + if ((mPimpl->mModel == nullptr) + || (mPimpl->mProfile == nullptr) + || !mPimpl->mModel->isValid() + || !mPimpl->mProfile->hasInterface()) { return {}; } - // Add code for the origin comment. + // Get ourselves ready. - mPimpl->mCode = {}; + mPimpl->reset(); + + // Add code for the origin comment. mPimpl->addOriginCommentCode(); @@ -1877,23 +2057,22 @@ std::string Generator::interfaceCode() const mPimpl->addInterfaceComputeModelMethodsCode(); - mPimpl->resetLockedModelAndProfile(); - return mPimpl->mCode; } std::string Generator::implementationCode() const { - if (!mPimpl->retrieveLockedModelAndProfile() - || !mPimpl->mLockedModel->isValid()) { - mPimpl->resetLockedModelAndProfile(); - + if ((mPimpl->mModel == nullptr) + || (mPimpl->mProfile == nullptr) + || !mPimpl->mModel->isValid()) { return {}; } - // Add code for the origin comment. + // Get ourselves ready. - mPimpl->mCode = {}; + mPimpl->reset(); + + // Add code for the origin comment. mPimpl->addOriginCommentCode(); @@ -1912,7 +2091,7 @@ std::string Generator::implementationCode() const // Add code for the variable information related objects. - if (!mPimpl->mLockedProfile->hasInterface()) { + if (!mPimpl->mProfile->hasInterface()) { mPimpl->addVariableTypeObjectCode(); mPimpl->addVariableInfoObjectCode(); } @@ -1935,9 +2114,15 @@ std::string Generator::implementationCode() const mPimpl->addImplementationCreateVariablesArrayMethodCode(); mPimpl->addImplementationDeleteArrayMethodCode(); + // Add code for the NLA solver. + + mPimpl->addRootFindingInfoObjectCode(); + mPimpl->addExternNlaSolveMethodCode(); + mPimpl->addNlaSystemsCode(); + // Add code for the implementation to initialise our variables. - auto equations = mPimpl->mLockedModel->equations(); + auto equations = mPimpl->mModel->equations(); std::vector remainingEquations {std::begin(equations), std::end(equations)}; mPimpl->addImplementationInitialiseVariablesMethodCode(remainingEquations); @@ -1961,9 +2146,24 @@ std::string Generator::implementationCode() const mPimpl->addImplementationComputeVariablesMethodCode(remainingEquations); - mPimpl->resetLockedModelAndProfile(); - return mPimpl->mCode; } +std::string Generator::equationCode(const AnalyserEquationAstPtr &ast, + const GeneratorProfilePtr &generatorProfile) +{ + GeneratorPtr generator = libcellml::Generator::create(); + + if (generatorProfile != nullptr) { + generator->setProfile(generatorProfile); + } + + return generator->mPimpl->generateCode(ast); +} + +std::string Generator::equationCode(const AnalyserEquationAstPtr &ast) +{ + return Generator::equationCode(ast, nullptr); +} + } // namespace libcellml diff --git a/src/generator_p.h b/src/generator_p.h index c25ddb7d4..01135d354 100644 --- a/src/generator_p.h +++ b/src/generator_p.h @@ -20,10 +20,9 @@ limitations under the License. #include "libcellml/generatorprofile.h" -namespace libcellml { +#include "utilities.h" -using AnalyserModelWeakPtr = std::weak_ptr; /**< Type definition for weak analyser model pointer. */ -using GeneratorProfileWeakPtr = std::weak_ptr; /**< Type definition for weak generator profile pointer. */ +namespace libcellml { /** * @brief The Generator::GeneratorImpl struct. @@ -32,24 +31,23 @@ using GeneratorProfileWeakPtr = std::weak_ptr; /**< Type defin */ struct Generator::GeneratorImpl { - Generator *mGenerator = nullptr; - - AnalyserModelWeakPtr mModel; - AnalyserModelPtr mLockedModel; + AnalyserModelPtr mModel; std::string mCode; - GeneratorProfilePtr mOwnedProfile = GeneratorProfile::create(); - GeneratorProfileWeakPtr mProfile; - GeneratorProfilePtr mLockedProfile; + GeneratorProfilePtr mProfile = GeneratorProfile::create(); - bool retrieveLockedModelAndProfile(); - void resetLockedModelAndProfile(); + void reset(); + + bool modelHasOdes() const; + bool modelHasNlas() const; AnalyserVariablePtr analyserVariable(const VariablePtr &variable) const; double scalingFactor(const VariablePtr &variable) const; + bool isNegativeNumber(const AnalyserEquationAstPtr &ast) const; + bool isRelationalOperator(const AnalyserEquationAstPtr &ast) const; bool isAndOperator(const AnalyserEquationAstPtr &ast) const; bool isOrOperator(const AnalyserEquationAstPtr &ast) const; @@ -69,6 +67,8 @@ struct Generator::GeneratorImpl bool modifiedProfile() const; + std::string newLineIfNeeded(); + void addOriginCommentCode(); void addInterfaceHeaderCode(); @@ -103,12 +103,16 @@ struct Generator::GeneratorImpl void addImplementationCreateVariablesArrayMethodCode(); void addImplementationDeleteArrayMethodCode(); + void addRootFindingInfoObjectCode(); + void addExternNlaSolveMethodCode(); + void addNlaSystemsCode(); + std::string generateMethodBodyCode(const std::string &methodBody) const; std::string generateDoubleCode(const std::string &value) const; std::string generateDoubleOrConstantVariableNameCode(const VariablePtr &variable) const; std::string generateVariableNameCode(const VariablePtr &variable, - const AnalyserEquationAstPtr &ast = nullptr) const; + bool state = true) const; std::string generateOperatorCode(const std::string &op, const AnalyserEquationAstPtr &ast) const; @@ -122,10 +126,16 @@ struct Generator::GeneratorImpl std::string generatePiecewiseElseCode(const std::string &value) const; std::string generateCode(const AnalyserEquationAstPtr &ast) const; + bool isToBeComputedAgain(const AnalyserEquationPtr &equation) const; + bool isSomeConstant(const AnalyserEquationPtr &equation) const; + + std::string generateZeroInitialisationCode(const AnalyserVariablePtr &variable) const; std::string generateInitialisationCode(const AnalyserVariablePtr &variable) const; std::string generateEquationCode(const AnalyserEquationPtr &equation, std::vector &remainingEquations, - bool forComputeVariables = false) const; + std::vector &equationsForComputeVariables); + std::string generateEquationCode(const AnalyserEquationPtr &equation, + std::vector &remainingEquations); void addInterfaceComputeModelMethodsCode(); void addImplementationInitialiseVariablesMethodCode(std::vector &remainingEquations); diff --git a/src/generatorprofile.cpp b/src/generatorprofile.cpp index d9d3e086c..1a28739f0 100644 --- a/src/generatorprofile.cpp +++ b/src/generatorprofile.cpp @@ -41,9 +41,9 @@ struct GeneratorProfile::GeneratorProfileImpl bool mHasInterface = true; - // Assignment. + // Equality. - std::string mAssignmentString; + std::string mEqualityString; // Relational and logical operators. @@ -224,6 +224,20 @@ struct GeneratorProfile::GeneratorProfileImpl std::string mExternalVariableMethodCallFamString; std::string mExternalVariableMethodCallFdmString; + std::string mRootFindingInfoObjectFamString; + std::string mRootFindingInfoObjectFdmString; + std::string mExternNlaSolveMethodString; + std::string mFindRootCallFamString; + std::string mFindRootCallFdmString; + std::string mFindRootMethodFamString; + std::string mFindRootMethodFdmString; + std::string mNlaSolveCallFamString; + std::string mNlaSolveCallFdmString; + std::string mObjectiveFunctionMethodFamString; + std::string mObjectiveFunctionMethodFdmString; + std::string mUArrayString; + std::string mFArrayString; + std::string mInterfaceCreateStatesArrayMethodString; std::string mImplementationCreateStatesArrayMethodString; @@ -294,9 +308,9 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi mHasInterface = true; - // Assignment. + // Equality. - mAssignmentString = " = "; + mEqualityString = " = "; // Relational and logical operators. @@ -483,7 +497,7 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi "#include \n"; mInterfaceVersionString = "extern const char VERSION[];\n"; - mImplementationVersionString = "const char VERSION[] = \"0.3.0\";\n"; + mImplementationVersionString = "const char VERSION[] = \"0.4.0\";\n"; mInterfaceLibcellmlVersionString = "extern const char LIBCELLML_VERSION[];\n"; mImplementationLibcellmlVersionString = "const char LIBCELLML_VERSION[] = \"[LIBCELLML_VERSION]\";\n"; @@ -557,21 +571,80 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi mVariablesArrayString = "variables"; mExternalVariableMethodTypeDefinitionFamString = "typedef double (* ExternalVariable)(double *variables, size_t index);\n"; - mExternalVariableMethodTypeDefinitionFdmString = "typedef double (* ExternalVariable)(double voi, double *states, double *variables, size_t index);\n"; + mExternalVariableMethodTypeDefinitionFdmString = "typedef double (* ExternalVariable)(double voi, double *states, double *rates, double *variables, size_t index);\n"; mExternalVariableMethodCallFamString = "externalVariable(variables, [INDEX])"; - mExternalVariableMethodCallFdmString = "externalVariable(voi, states, variables, [INDEX])"; + mExternalVariableMethodCallFdmString = "externalVariable(voi, states, rates, variables, [INDEX])"; + + mRootFindingInfoObjectFamString = "typedef struct {\n" + " double *variables;\n" + "} RootFindingInfo;\n"; + mRootFindingInfoObjectFdmString = "typedef struct {\n" + " double voi;\n" + " double *states;\n" + " double *rates;\n" + " double *variables;\n" + "} RootFindingInfo;\n"; + mExternNlaSolveMethodString = "extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *),\n" + " double *u, int n, void *data);\n"; + mFindRootCallFamString = "findRoot[INDEX](variables);\n"; + mFindRootCallFdmString = "findRoot[INDEX](voi, states, rates, variables);\n"; + mFindRootMethodFamString = "void findRoot[INDEX](double *variables)\n" + "{\n" + " RootFindingInfo rfi = { variables };\n" + " double u[[SIZE]];\n" + "\n" + "[CODE]" + "}\n"; + mFindRootMethodFdmString = "void findRoot[INDEX](double voi, double *states, double *rates, double *variables)\n" + "{\n" + " RootFindingInfo rfi = { voi, states, rates, variables };\n" + " double u[[SIZE]];\n" + "\n" + "[CODE]" + "}\n"; + mNlaSolveCallFamString = "nlaSolve(objectiveFunction[INDEX], u, [SIZE], &rfi);\n"; + mNlaSolveCallFdmString = "nlaSolve(objectiveFunction[INDEX], u, [SIZE], &rfi);\n"; + mObjectiveFunctionMethodFamString = "void objectiveFunction[INDEX](double *u, double *f, void *data)\n" + "{\n" + " double *variables = ((RootFindingInfo *) data)->variables;\n" + "\n" + "[CODE]" + "}\n"; + mObjectiveFunctionMethodFdmString = "void objectiveFunction[INDEX](double *u, double *f, void *data)\n" + "{\n" + " double voi = ((RootFindingInfo *) data)->voi;\n" + " double *states = ((RootFindingInfo *) data)->states;\n" + " double *rates = ((RootFindingInfo *) data)->rates;\n" + " double *variables = ((RootFindingInfo *) data)->variables;\n" + "\n" + "[CODE]" + "}\n"; + mUArrayString = "u"; + mFArrayString = "f"; mInterfaceCreateStatesArrayMethodString = "double * createStatesArray();\n"; mImplementationCreateStatesArrayMethodString = "double * createStatesArray()\n" "{\n" - " return malloc(STATE_COUNT*sizeof(double));\n" + " double *res = (double *) malloc(STATE_COUNT*sizeof(double));\n" + "\n" + " for (size_t i = 0; i < STATE_COUNT; ++i) {\n" + " res[i] = NAN;\n" + " }\n" + "\n" + " return res;\n" "}\n"; mInterfaceCreateVariablesArrayMethodString = "double * createVariablesArray();\n"; mImplementationCreateVariablesArrayMethodString = "double * createVariablesArray()\n" "{\n" - " return malloc(VARIABLE_COUNT*sizeof(double));\n" + " double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double));\n" + "\n" + " for (size_t i = 0; i < VARIABLE_COUNT; ++i) {\n" + " res[i] = NAN;\n" + " }\n" + "\n" + " return res;\n" "}\n"; mInterfaceDeleteArrayMethodString = "void deleteArray(double *array);\n"; @@ -592,14 +665,14 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi "[CODE]" "}\n"; - mInterfaceInitialiseVariablesMethodFdmWoevString = "void initialiseVariables(double *states, double *variables);\n"; - mImplementationInitialiseVariablesMethodFdmWoevString = "void initialiseVariables(double *states, double *variables)\n" + mInterfaceInitialiseVariablesMethodFdmWoevString = "void initialiseVariables(double *states, double *rates, double *variables);\n"; + mImplementationInitialiseVariablesMethodFdmWoevString = "void initialiseVariables(double *states, double *rates, double *variables)\n" "{\n" "[CODE]" "}\n"; - mInterfaceInitialiseVariablesMethodFdmWevString = "void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable);\n"; - mImplementationInitialiseVariablesMethodFdmWevString = "void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable)\n" + mInterfaceInitialiseVariablesMethodFdmWevString = "void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable);\n"; + mImplementationInitialiseVariablesMethodFdmWevString = "void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable)\n" "{\n" "[CODE]" "}\n"; @@ -659,14 +732,14 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi mStringDelimiterString = "\""; mCommandSeparatorString = ";"; - } else if (profile == GeneratorProfile::Profile::PYTHON) { + } else { // GeneratorProfile::Profile::PYTHON. // Whether the profile requires an interface to be generated. mHasInterface = false; - // Assignment. + // Equality. - mAssignmentString = " = "; + mEqualityString = " = "; // Relational and logical operators. @@ -853,7 +926,7 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi "\n"; mInterfaceVersionString = ""; - mImplementationVersionString = "__version__ = \"0.3.1\"\n"; + mImplementationVersionString = "__version__ = \"0.4.0\"\n"; mInterfaceLibcellmlVersionString = ""; mImplementationLibcellmlVersionString = "LIBCELLML_VERSION = \"[LIBCELLML_VERSION]\"\n"; @@ -929,7 +1002,42 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi mExternalVariableMethodTypeDefinitionFdmString = ""; mExternalVariableMethodCallFamString = "external_variable(variables, [INDEX])"; - mExternalVariableMethodCallFdmString = "external_variable(voi, states, variables, [INDEX])"; + mExternalVariableMethodCallFdmString = "external_variable(voi, states, rates, variables, [INDEX])"; + + mRootFindingInfoObjectFamString = ""; + mRootFindingInfoObjectFdmString = ""; + mExternNlaSolveMethodString = "\n" + "from nlasolver import nla_solve" + "\n"; + mFindRootCallFamString = "find_root_[INDEX](variables)\n"; + mFindRootCallFdmString = "find_root_[INDEX](voi, states, rates, variables)\n"; + mFindRootMethodFamString = "\n" + "def find_root_[INDEX](variables):\n" + " u = [nan]*[SIZE]\n" + "\n" + "[CODE]"; + mFindRootMethodFdmString = "\n" + "def find_root_[INDEX](voi, states, rates, variables):\n" + " u = [nan]*[SIZE]\n" + "\n" + "[CODE]"; + mNlaSolveCallFamString = "u = nla_solve(objective_function_[INDEX], u, [SIZE], [variables])\n"; + mNlaSolveCallFdmString = "u = nla_solve(objective_function_[INDEX], u, [SIZE], [voi, states, rates, variables])\n"; + mObjectiveFunctionMethodFamString = "\n" + "def objective_function_[INDEX](u, f, data):\n" + " variables = data[0]\n" + "\n" + "[CODE]"; + mObjectiveFunctionMethodFdmString = "\n" + "def objective_function_[INDEX](u, f, data):\n" + " voi = data[0]\n" + " states = data[1]\n" + " rates = data[2]\n" + " variables = data[3]\n" + "\n" + "[CODE]"; + mUArrayString = "u"; + mFArrayString = "f"; mInterfaceCreateStatesArrayMethodString = ""; mImplementationCreateStatesArrayMethodString = "\n" @@ -956,12 +1064,12 @@ void GeneratorProfile::GeneratorProfileImpl::loadProfile(GeneratorProfile::Profi mInterfaceInitialiseVariablesMethodFdmWoevString = ""; mImplementationInitialiseVariablesMethodFdmWoevString = "\n" - "def initialise_variables(states, variables):\n" + "def initialise_variables(states, rates, variables):\n" "[CODE]"; mInterfaceInitialiseVariablesMethodFdmWevString = ""; mImplementationInitialiseVariablesMethodFdmWevString = "\n" - "def initialise_variables(voi, states, variables, external_variable):\n" + "def initialise_variables(voi, states, rates, variables, external_variable):\n" "[CODE]"; mInterfaceComputeComputedConstantsMethodString = ""; @@ -1038,6 +1146,15 @@ GeneratorProfile::Profile GeneratorProfile::profile() const return mPimpl->mProfile; } +static const std::map profileToString = { + {GeneratorProfile::Profile::C, "c"}, + {GeneratorProfile::Profile::PYTHON, "python"}}; + +std::string GeneratorProfile::profileAsString(Profile profile) +{ + return profileToString.at(profile); +} + void GeneratorProfile::setProfile(Profile profile) { mPimpl->loadProfile(profile); @@ -1053,14 +1170,14 @@ void GeneratorProfile::setHasInterface(bool hasInterface) mPimpl->mHasInterface = hasInterface; } -std::string GeneratorProfile::assignmentString() const +std::string GeneratorProfile::equalityString() const { - return mPimpl->mAssignmentString; + return mPimpl->mEqualityString; } -void GeneratorProfile::setAssignmentString(const std::string &assignmentString) +void GeneratorProfile::setEqualityString(const std::string &equalityString) { - mPimpl->mAssignmentString = assignmentString; + mPimpl->mEqualityString = equalityString; } std::string GeneratorProfile::eqString() const @@ -2408,6 +2525,131 @@ void GeneratorProfile::setExternalVariableMethodCallString(bool forDifferentialM } } +std::string GeneratorProfile::rootFindingInfoObjectString(bool forDifferentialModel) const +{ + if (forDifferentialModel) { + return mPimpl->mRootFindingInfoObjectFdmString; + } + + return mPimpl->mRootFindingInfoObjectFamString; +} + +void GeneratorProfile::setRootFindingInfoObjectString(bool forDifferentialModel, + const std::string &rootFindingInfoObjectString) +{ + if (forDifferentialModel) { + mPimpl->mRootFindingInfoObjectFdmString = rootFindingInfoObjectString; + } else { + mPimpl->mRootFindingInfoObjectFamString = rootFindingInfoObjectString; + } +} + +std::string GeneratorProfile::externNlaSolveMethodString() const +{ + return mPimpl->mExternNlaSolveMethodString; +} + +void GeneratorProfile::setExternNlaSolveMethodString(const std::string &externNlaSolveMethodString) +{ + mPimpl->mExternNlaSolveMethodString = externNlaSolveMethodString; +} + +std::string GeneratorProfile::findRootCallString(bool forDifferentialModel) const +{ + if (forDifferentialModel) { + return mPimpl->mFindRootCallFdmString; + } + + return mPimpl->mFindRootCallFamString; +} + +void GeneratorProfile::setFindRootCallString(bool forDifferentialModel, + const std::string &findRootCallString) +{ + if (forDifferentialModel) { + mPimpl->mFindRootCallFdmString = findRootCallString; + } else { + mPimpl->mFindRootCallFamString = findRootCallString; + } +} + +std::string GeneratorProfile::findRootMethodString(bool forDifferentialModel) const +{ + if (forDifferentialModel) { + return mPimpl->mFindRootMethodFdmString; + } + + return mPimpl->mFindRootMethodFamString; +} + +void GeneratorProfile::setFindRootMethodString(bool forDifferentialModel, + const std::string &findRootMethodString) +{ + if (forDifferentialModel) { + mPimpl->mFindRootMethodFdmString = findRootMethodString; + } else { + mPimpl->mFindRootMethodFamString = findRootMethodString; + } +} + +std::string GeneratorProfile::nlaSolveCallString(bool forDifferentialModel) const +{ + if (forDifferentialModel) { + return mPimpl->mNlaSolveCallFdmString; + } + + return mPimpl->mNlaSolveCallFamString; +} + +void GeneratorProfile::setNlaSolveCallString(bool forDifferentialModel, + const std::string &nlaSolveCallString) +{ + if (forDifferentialModel) { + mPimpl->mNlaSolveCallFdmString = nlaSolveCallString; + } else { + mPimpl->mNlaSolveCallFamString = nlaSolveCallString; + } +} + +std::string GeneratorProfile::objectiveFunctionMethodString(bool forDifferentialModel) const +{ + if (forDifferentialModel) { + return mPimpl->mObjectiveFunctionMethodFdmString; + } + + return mPimpl->mObjectiveFunctionMethodFamString; +} + +void GeneratorProfile::setObjectiveFunctionMethodString(bool forDifferentialModel, + const std::string &objectiveFunctionMethodString) +{ + if (forDifferentialModel) { + mPimpl->mObjectiveFunctionMethodFdmString = objectiveFunctionMethodString; + } else { + mPimpl->mObjectiveFunctionMethodFamString = objectiveFunctionMethodString; + } +} + +std::string GeneratorProfile::uArrayString() const +{ + return mPimpl->mUArrayString; +} + +void GeneratorProfile::setUArrayString(const std::string &uArrayString) +{ + mPimpl->mUArrayString = uArrayString; +} + +std::string GeneratorProfile::fArrayString() const +{ + return mPimpl->mFArrayString; +} + +void GeneratorProfile::setFArrayString(const std::string &fArrayString) +{ + mPimpl->mFArrayString = fArrayString; +} + std::string GeneratorProfile::interfaceCreateStatesArrayMethodString() const { return mPimpl->mInterfaceCreateStatesArrayMethodString; diff --git a/src/generatorprofilesha1values.h b/src/generatorprofilesha1values.h index 421785206..c5d9d11e5 100644 --- a/src/generatorprofilesha1values.h +++ b/src/generatorprofilesha1values.h @@ -24,7 +24,7 @@ namespace libcellml { * The content of this file is generated, do not edit this file directly. * See docs/dev_utilities.rst for further information. */ -static const char C_GENERATOR_PROFILE_SHA1[] = "aeb5a3f6a296f649f7b7cdc8cb0a4184a0bf8220"; -static const char PYTHON_GENERATOR_PROFILE_SHA1[] = "000bc7b4704b9ada831099a93109a68e524cb3de"; +static const char C_GENERATOR_PROFILE_SHA1[] = "13b0c2b84e4d199dbaacfa93f448b84b9c2af91d"; +static const char PYTHON_GENERATOR_PROFILE_SHA1[] = "41f70a8d0486fdb3638b310814ebaa7d3ddd6771"; } // namespace libcellml diff --git a/src/generatorprofiletools.cpp b/src/generatorprofiletools.cpp index 991555380..2dce65f31 100644 --- a/src/generatorprofiletools.cpp +++ b/src/generatorprofiletools.cpp @@ -274,9 +274,9 @@ std::string generatorProfileAsString(const GeneratorProfilePtr &generatorProfile TRUE_VALUE : FALSE_VALUE; - // Assignment. + // Equality. - profileContents += generatorProfile->assignmentString(); + profileContents += generatorProfile->equalityString(); // Relational and logical operators. @@ -482,6 +482,20 @@ std::string generatorProfileAsString(const GeneratorProfilePtr &generatorProfile profileContents += generatorProfile->externalVariableMethodCallString(false) + generatorProfile->externalVariableMethodCallString(true); + profileContents += generatorProfile->rootFindingInfoObjectString(false) + + generatorProfile->rootFindingInfoObjectString(true) + + generatorProfile->externNlaSolveMethodString() + + generatorProfile->findRootCallString(false) + + generatorProfile->findRootCallString(true) + + generatorProfile->findRootMethodString(false) + + generatorProfile->findRootMethodString(true) + + generatorProfile->nlaSolveCallString(false) + + generatorProfile->nlaSolveCallString(true) + + generatorProfile->objectiveFunctionMethodString(false) + + generatorProfile->objectiveFunctionMethodString(true) + + generatorProfile->uArrayString() + + generatorProfile->fArrayString(); + profileContents += generatorProfile->interfaceCreateStatesArrayMethodString() + generatorProfile->implementationCreateStatesArrayMethodString(); @@ -540,10 +554,6 @@ std::string generatorProfileAsString(const GeneratorProfilePtr &generatorProfile profileContents += generatorProfile->commandSeparatorString(); - // Add some x's to ensure 100% coverage in our SHA-1 utility. - - profileContents += "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; - return profileContents; } diff --git a/src/importer.cpp b/src/importer.cpp index 6608d0eb8..40b7afb2a 100644 --- a/src/importer.cpp +++ b/src/importer.cpp @@ -32,6 +32,7 @@ limitations under the License. #include "libcellml/variable.h" #include "anycellmlelement_p.h" +#include "commonutils.h" #include "issue_p.h" #include "logger_p.h" #include "utilities.h" @@ -73,7 +74,17 @@ class Importer::ImporterImpl: public Logger::LoggerImpl bool checkUnitsForCycles(const UnitsPtr &units, History &history); bool checkComponentForCycles(const ComponentPtr &component, History &history); - bool hasImportCycles(const ModelPtr &model); + /** + * @brief Test for any import issues. + * + * Test the given @p model for import issues. + * This method will test for cyclic imports, and missing imports. + * Returns @c true if an import issue is found, @c false otherwise. + * + * @param model The model to test import issues of. + * @return @c true if the model has import issues, @c false otherwise. + */ + bool hasImportIssues(const ModelPtr &model); }; Importer::ImporterImpl *Importer::pFunc() @@ -136,17 +147,11 @@ bool Importer::ImporterImpl::checkUnitsForCycles(const UnitsPtr &units, History { // Even if these units are not imported, they might have imported children. if (!units->isImport()) { - for (size_t u = 0; u < units->unitCount(); ++u) { - std::string ref; - std::string prefix; - std::string id; - double multiplier; - double exponent; - - units->unitAttributes(u, ref, prefix, exponent, multiplier, id); + for (size_t index = 0; index < units->unitCount(); ++index) { + std::string ref = units->unitAttributeReference(index); // If the child units are imported, check them too. auto model = owningModel(units); - if ((model != nullptr) && model->hasUnits(ref)) { + if (model->hasUnits(ref)) { if (checkUnitsForCycles(model->units(ref), history)) { return true; } @@ -202,35 +207,33 @@ bool Importer::ImporterImpl::checkComponentForCycles(const ComponentPtr &compone history.push_back(h); // If the dependencies have not been recorded already, then check it. - if (component->isImport()) { - auto model = component->importSource()->model(); - if (model == nullptr) { - auto issue = Issue::IssueImpl::create(); - issue->mPimpl->setDescription("Component '" + component->name() + "' requires a model imported from '" + resolvingUrl + "' which is not available in the importer."); - issue->mPimpl->mItem->mPimpl->setImportSource(component->importSource()); - issue->mPimpl->setReferenceRule(Issue::ReferenceRule::IMPORTER_NULL_MODEL); - addIssue(issue); - return true; - } - auto importedComponent = model->component(component->importReference(), true); - if (importedComponent == nullptr) { - auto issue = Issue::IssueImpl::create(); - issue->mPimpl->setDescription("Component '" + component->name() + "' imports a component named '" + component->importReference() + "' from the model imported from '" + resolvingUrl + "'. The component could not be found."); - issue->mPimpl->mItem->mPimpl->setImportSource(component->importSource()); - issue->mPimpl->setReferenceRule(Issue::ReferenceRule::IMPORTER_MISSING_COMPONENT); - addIssue(issue); - return true; - } + auto model = component->importSource()->model(); + if (model == nullptr) { + auto issue = Issue::IssueImpl::create(); + issue->mPimpl->setDescription("Component '" + component->name() + "' requires a model imported from '" + resolvingUrl + "' which is not available in the importer."); + issue->mPimpl->mItem->mPimpl->setImportSource(component->importSource()); + issue->mPimpl->setReferenceRule(Issue::ReferenceRule::IMPORTER_NULL_MODEL); + addIssue(issue); + return true; + } + auto importedComponent = model->component(component->importReference(), true); + if (importedComponent == nullptr) { + auto issue = Issue::IssueImpl::create(); + issue->mPimpl->setDescription("Component '" + component->name() + "' imports a component named '" + component->importReference() + "' from the model imported from '" + resolvingUrl + "'. The component could not be found."); + issue->mPimpl->mItem->mPimpl->setImportSource(component->importSource()); + issue->mPimpl->setReferenceRule(Issue::ReferenceRule::IMPORTER_MISSING_COMPONENT); + addIssue(issue); + return true; + } - if (importedComponent->isImport() && checkComponentForCycles(importedComponent, history)) { - return true; - } + if (importedComponent->isImport() && checkComponentForCycles(importedComponent, history)) { + return true; } return false; } -bool Importer::ImporterImpl::hasImportCycles(const ModelPtr &model) +bool Importer::ImporterImpl::hasImportIssues(const ModelPtr &model) { History history; @@ -248,6 +251,15 @@ bool Importer::ImporterImpl::hasImportCycles(const ModelPtr &model) } } + if (model->hasUnresolvedImports()) { + auto issue = Issue::IssueImpl::create(); + issue->mPimpl->setDescription("The model has unresolved imports."); + issue->mPimpl->mItem->mPimpl->setModel(model); + issue->mPimpl->setReferenceRule(Issue::ReferenceRule::IMPORTER_UNRESOLVED_IMPORTS); + addIssue(issue); + return true; + } + return false; } @@ -358,7 +370,9 @@ bool Importer::ImporterImpl::fetchModel(const ImportSourcePtr &importSource, con auto issue = Issue::IssueImpl::create(); issue->mPimpl->setDescription("The attempt to import the model at '" + url + "' failed: the file is not valid XML."); issue->mPimpl->mItem->mPimpl->setImportSource(importSource); - issue->mPimpl->setReferenceRule(Issue::ReferenceRule::IMPORTER_NULL_MODEL); + if (mImporter->isStrict()) { + issue->mPimpl->setReferenceRule(Issue::ReferenceRule::IMPORTER_NULL_MODEL); + } addIssue(issue); return false; } @@ -455,12 +469,14 @@ bool Importer::ImporterImpl::fetchComponent(const ComponentPtr &importComponent, size_t endIndex = mImporter->errorCount(); bool encounteredRelatedError = false; - for (size_t index = endIndex - 1; (startIndex <= index) && (index < endIndex); --index) { - auto error = mImporter->error(index); - removeError(index); + if (endIndex > startIndex) { + for (size_t index = endIndex; startIndex < index; --index) { + auto error = mImporter->error(index - 1); + removeError(index - 1); - if (!encounteredRelatedError && isErrorRelatedToComponent(error, sourceComponent)) { - encounteredRelatedError = true; + if (!encounteredRelatedError && isErrorRelatedToComponent(error, sourceComponent)) { + encounteredRelatedError = true; + } } } @@ -544,12 +560,14 @@ bool Importer::ImporterImpl::fetchUnits(const UnitsPtr &importUnits, const std:: bool encounteredRelatedError = false; size_t endIndex = mImporter->errorCount(); - for (size_t index = endIndex - 1; (startIndex <= index) && (index < endIndex); --index) { - auto error = mImporter->error(index); - auto errorUnits = error->item()->units(); - removeError(index); - if (!encounteredRelatedError && (errorUnits != nullptr) && (errorUnits->name() == importUnits->importReference())) { - encounteredRelatedError = true; + if (endIndex > startIndex) { + for (size_t index = endIndex; startIndex < index; --index) { + auto error = mImporter->error(index - 1); + auto errorUnits = error->item()->units(); + removeError(index - 1); + if (!encounteredRelatedError && (errorUnits != nullptr) && (errorUnits->name() == importUnits->importReference())) { + encounteredRelatedError = true; + } } } @@ -585,13 +603,8 @@ bool Importer::ImporterImpl::fetchUnits(const UnitsPtr &importUnits, const std:: return false; } - for (size_t u = 0; u < sourceUnits->unitCount(); ++u) { - std::string reference; - std::string prefix; - std::string id; - double exponent; - double multiplier; - sourceUnits->unitAttributes(u, reference, prefix, exponent, multiplier, id); + for (size_t unit_index = 0; unit_index < sourceUnits->unitCount(); ++unit_index) { + std::string reference = sourceUnits->unitAttributeReference(unit_index); if (isStandardUnitName(reference)) { continue; } @@ -604,7 +617,7 @@ bool Importer::ImporterImpl::fetchUnits(const UnitsPtr &importUnits, const std:: addIssue(issue); return false; } - if (sourceUnit->isImport() && !sourceUnit->isResolved()) { + if (sourceUnit->isImport()) { if (!fetchUnits(sourceUnit, newBase, history)) { return false; } @@ -629,6 +642,15 @@ bool Importer::resolveImports(ModelPtr &model, const std::string &basePath) History history; pFunc()->removeAllIssues(); + + if (model == nullptr) { + auto issue = Issue::IssueImpl::create(); + issue->mPimpl->setDescription("Cannot resolve imports for null model."); + issue->mPimpl->setReferenceRule(Issue::ReferenceRule::IMPORTER_NULL_MODEL); + pFunc()->addIssue(issue); + return false; + } + clearImports(model); auto normalisedBasePath = normalisePath(basePath); @@ -676,15 +698,129 @@ void Importer::clearImports(ModelPtr &model) } } -void flattenComponent(const ComponentEntityPtr &parent, ComponentPtr &component, size_t index) +UnitsPtr modelsEquivalentUnits(const ModelPtr &model, const UnitsPtr &units) +{ + for (size_t i = 0; i < model->unitsCount(); ++i) { + const UnitsPtr u = model->units(i); + if (Units::equivalent(u, units)) { + return u; + } + } + + return nullptr; +} + +void updateComponentsVariablesUnitsNames(const std::string &name, const ComponentPtr &component, const UnitsPtr &units) +{ + for (size_t variableIndex = 0; variableIndex < component->variableCount(); ++variableIndex) { + auto variable = component->variable(variableIndex); + if (component->isImport()) { + auto importModel = component->importSource()->model(); + auto importComponent = importModel->component(component->importReference()); + variable = importComponent->variable(variable->name()); + } + if (variable->units()->name() == name) { + variable->setUnits(units); + } + } + for (size_t index = 0; index < component->componentCount(); ++index) { + auto childComponent = component->component(index); + updateComponentsVariablesUnitsNames(name, childComponent, units); + } +} + +void updateUnitsNameUsages(const std::string &oldName, const std::string &newName, const ComponentPtr &component, const UnitsPtr &units) +{ + if (component != nullptr) { + findAndReplaceComponentsCnUnitsNames(component, oldName, newName); + updateComponentsVariablesUnitsNames(oldName, component, units); + } +} + +StringStringMap transferUnitsRenamingIfRequired(const ModelPtr &sourceModel, const ModelPtr &targetModel, const UnitsPtr &units, const ComponentPtr &component) +{ + StringStringMap changedNames; + + std::string newName = units->name(); + UnitsPtr targetUnits = modelsEquivalentUnits(targetModel, units); + if (targetUnits == nullptr) { + for (size_t unitIndex = 0; unitIndex < units->unitCount(); ++unitIndex) { + std::string reference = units->unitAttributeReference(unitIndex); + if (!reference.empty() && !isStandardUnitName(reference) && sourceModel->hasUnits(reference)) { + auto clonedChildUnits = sourceModel->units(reference)->clone(); + transferUnitsRenamingIfRequired(sourceModel, targetModel, clonedChildUnits, component); + units->setUnitAttributeReference(unitIndex, clonedChildUnits->name()); + } + } + + size_t count = 0; + const std::string originalName = newName; + targetUnits = targetModel->units(newName); + while (targetModel->hasUnits(newName)) { + newName = originalName + "_" + convertToString(++count); + units->setName(newName); + targetUnits = targetModel->units(newName); + } + + targetModel->addUnits(units); + if (originalName != newName) { + updateUnitsNameUsages(originalName, newName, component, units); + changedNames.emplace(originalName, newName); + } + } else if (targetUnits->name() != units->name()) { + const std::string originalName = units->name(); + newName = targetUnits->name(); + updateUnitsNameUsages(originalName, newName, component, targetUnits); + changedNames.emplace(originalName, newName); + } + + return changedNames; +} + +void flattenUnitsImports(const ModelPtr &flatModel, const UnitsPtr &units, size_t index, const ComponentPtr &component); + +void retrieveUnitsDependencies(const ModelPtr &flatModel, const ModelPtr &model, const UnitsPtr &u, const ComponentPtr &component) +{ + for (size_t unitIndex = 0; unitIndex < u->unitCount(); ++unitIndex) { + std::string reference = u->unitAttributeReference(unitIndex); + if (!reference.empty() && !isStandardUnitName(reference) && model->hasUnits(reference)) { + auto childUnits = model->units(reference); + if (childUnits->isImport()) { + size_t flatModelUnitsIndex = flatModel->unitsCount(); + UnitsPtr clonedChildUnits = childUnits->clone(); + flatModel->addUnits(clonedChildUnits); + flattenUnitsImports(flatModel, clonedChildUnits, flatModelUnitsIndex, component); + } else { + auto clonedChildUnits = childUnits->clone(); + transferUnitsRenamingIfRequired(model, flatModel, clonedChildUnits, component); + u->setUnitAttributeReference(unitIndex, clonedChildUnits->name()); + retrieveUnitsDependencies(flatModel, model, clonedChildUnits, component); + } + } + } +} + +void flattenUnitsImports(const ModelPtr &flatModel, const UnitsPtr &units, size_t index, const ComponentPtr &component) +{ + auto importSource = units->importSource(); + auto importingModel = importSource->model(); + auto importedUnits = importingModel->units(units->importReference()); + auto importedUnitsCopy = importedUnits->clone(); + importedUnitsCopy->setName(units->name()); + flatModel->replaceUnits(index, importedUnitsCopy); + retrieveUnitsDependencies(flatModel, importingModel, importedUnitsCopy, component); +} + +ComponentPtr flattenComponent(const ComponentEntityPtr &parent, ComponentPtr &component, size_t index) { if (component->isImport()) { auto model = owningModel(component); auto importSource = component->importSource(); auto importModel = importSource->model(); auto importedComponent = importModel->component(component->importReference()); + // Clone import model to not affect origin import model units. + auto clonedImportModel = importModel->clone(); - // Determine names of components already in use. NameList compNames = componentNames(model); // Determine the stack for the destination component. @@ -708,30 +844,38 @@ void flattenComponent(const ComponentEntityPtr &parent, ComponentPtr &component, importedComponentCopy->addComponent(component->component(i)); } - // Get list of required units from component's variables. - std::vector requiredUnits = unitsUsed(importModel, importedComponentCopy); + // Get list of required units from component's variables and math cn elements. + std::vector requiredUnits = unitsUsed(clonedImportModel, importedComponentCopy); + + std::vector uniqueRequiredUnits; + StringStringMap aliasedUnitsNames; + for (const auto &units : requiredUnits) { + const auto iterator = std::find_if(uniqueRequiredUnits.begin(), uniqueRequiredUnits.end(), + [=](const UnitsPtr &u) -> bool { return Units::equivalent(u, units); }); + if (iterator == uniqueRequiredUnits.end()) { + uniqueRequiredUnits.push_back(units); + } else if ((*iterator)->name() != units->name()) { + aliasedUnitsNames.emplace(units->name(), (*iterator)->name()); + } + } // Add all required units to a model so referenced units can be resolved. auto requiredUnitsModel = Model::create(); - for (const auto &units : requiredUnits) { + for (const auto &units : uniqueRequiredUnits) { // Cloning units present elsewhere so that they don't get moved by the addUnits function. - if (units->parent() == nullptr) { - requiredUnitsModel->addUnits(units); - } else { - auto cloned = units->clone(); - requiredUnitsModel->addUnits(cloned); - } + requiredUnitsModel->addUnits(units->clone()); } // Make a map of component name to component pointer. ComponentNameMap newComponentNames = createComponentNamesMap(importedComponentCopy); for (const auto &entry : newComponentNames) { - std::string newName = entry.first; + std::string originalName = entry.first; size_t count = 0; + std::string newName = originalName; while (std::find(compNames.begin(), compNames.end(), newName) != compNames.end()) { - newName += "_" + convertToString(++count); + newName = originalName + "_" + convertToString(++count); } - if (newName != entry.first) { + if (originalName != newName) { entry.second->setName(newName); } } @@ -743,43 +887,67 @@ void flattenComponent(const ComponentEntityPtr &parent, ComponentPtr &component, for (size_t j = 0; j < placeholderVariable->equivalentVariableCount(); ++j) { auto localModelVariable = placeholderVariable->equivalentVariable(j); auto importedComponentVariable = importedComponentCopy->variable(placeholderVariable->name()); - Variable::removeEquivalence(placeholderVariable, localModelVariable); Variable::addEquivalence(importedComponentVariable, localModelVariable); } } parent->replaceComponent(index, importedComponentCopy); + auto flatModel = owningModel(importedComponentCopy); // Apply the re-based equivalence map onto the modified model. - applyEquivalenceMapToModel(rebasedMap, model); - - // Copy over units used in imported component to this model. - std::map unitsNamesToReplace; - for (const auto &u : requiredUnits) { - if (!model->hasUnits(u)) { - auto originalName = u->name(); - size_t count = 0; - while (!model->hasUnits(u) && model->hasUnits(u->name())) { - auto name = u->name(); - name += "_" + convertToString(++count); - u->setName(name); + applyEquivalenceMapToModel(rebasedMap, flatModel); + + StringStringMap unitNamesToReplace; + for (const auto &units : uniqueRequiredUnits) { + // If the required units are imported units, we will resolve those units here. + size_t unitsIndex = 0; + UnitsPtr flattenedUnits = nullptr; + if (units->isImport()) { + auto foundUnits = clonedImportModel->units(units->name()); + while (flattenedUnits == nullptr) { + if (foundUnits->name() == clonedImportModel->units(unitsIndex)->name()) { + flattenUnitsImports(clonedImportModel, units, unitsIndex, importedComponentCopy); + flattenedUnits = clonedImportModel->units(unitsIndex); + } + unitsIndex += 1; } - model->addUnits(u); - if (originalName != u->name()) { - unitsNamesToReplace.emplace(originalName, u->name()); + } + + auto replacementUnits = (flattenedUnits != nullptr) ? flattenedUnits->clone() : units; + + for (size_t unitIndex = 0; unitIndex < replacementUnits->unitCount(); ++unitIndex) { + const std::string ref = replacementUnits->unitAttributeReference(unitIndex); + for (const auto &entry : unitNamesToReplace) { + if (ref == entry.first) { + replacementUnits->setUnitAttributeReference(unitIndex, entry.second); + } } } + StringStringMap changedNames = transferUnitsRenamingIfRequired(clonedImportModel, flatModel, replacementUnits, importedComponentCopy); + if (!changedNames.empty()) { + unitNamesToReplace.merge(changedNames); + } + } + + for (const auto &alias : aliasedUnitsNames) { + std::string finalUnitsName = alias.second; + const auto match = unitNamesToReplace.find(finalUnitsName); + if (match != unitNamesToReplace.end()) { + finalUnitsName = match->second; + } + UnitsPtr targetUnits = flatModel->units(finalUnitsName); + updateUnitsNameUsages(alias.first, finalUnitsName, importedComponentCopy, targetUnits); } - findAndReplaceComponentsCnUnitsNames(importedComponentCopy, unitsNamesToReplace); } + + return parent->component(index); } -void flattenComponentTree(const ComponentEntityPtr &parent, ComponentPtr &component, size_t componentIndex) +void flattenComponentImports(const ComponentEntityPtr &parent, ComponentPtr &component, size_t componentIndex) { - flattenComponent(parent, component, componentIndex); - auto flattenedComponent = parent->component(componentIndex); + auto flattenedComponent = flattenComponent(parent, component, componentIndex); for (size_t index = 0; index < flattenedComponent->componentCount(); ++index) { auto c = flattenedComponent->component(index); - flattenComponentTree(flattenedComponent, c, index); + flattenComponentImports(flattenedComponent, c, index); } } @@ -796,7 +964,16 @@ ModelPtr Importer::flattenModel(const ModelPtr &model) return flatModel; } - if (pFunc()->hasImportCycles(model)) { + if (pFunc()->hasImportIssues(model)) { + return flatModel; + } + + if (!model->isDefined()) { + auto issue = Issue::IssueImpl::create(); + issue->mPimpl->setReferenceRule(Issue::ReferenceRule::IMPORTER_UNDEFINED_MODEL); + issue->mPimpl->setDescription("The model is not fully defined."); + pFunc()->addIssue(issue); + return flatModel; } @@ -807,18 +984,14 @@ ModelPtr Importer::flattenModel(const ModelPtr &model) for (size_t index = 0; index < flatModel->unitsCount(); ++index) { auto u = flatModel->units(index); if (u->isImport()) { - auto importSource = u->importSource(); - auto importedUnits = importSource->model()->units(u->importReference()); - auto importedUnitsCopy = importedUnits->clone(); - importedUnitsCopy->setName(u->name()); - flatModel->replaceUnits(index, importedUnitsCopy); + flattenUnitsImports(flatModel, u, index, nullptr); } } // Go through Components and instantiate any imported Components. for (size_t index = 0; index < flatModel->componentCount(); ++index) { auto c = flatModel->component(index); - flattenComponentTree(flatModel, c, index); + flattenComponentImports(flatModel, c, index); } } diff --git a/src/internaltypes.h b/src/internaltypes.h index 1e5462c67..87ec6455a 100644 --- a/src/internaltypes.h +++ b/src/internaltypes.h @@ -52,6 +52,8 @@ using IdMap = std::map>>; / using ImportLibrary = std::map; /** Type definition for library map of imported models. */ using IdList = std::unordered_set; /**< Type definition for list of identifiers. */ +using AnalyserEquationAstWeakPtr = std::weak_ptr; /**< Type definition for weak analyser equation AST pointer. */ +using AnalyserEquationWeakPtr = std::weak_ptr; /**< Type definition for weak analyser equation pointer. */ using ComponentWeakPtr = std::weak_ptr; /**< Type definition for weak component pointer. */ using ImportSourceWeakPtr = std::weak_ptr; /**< Type definition for weak import source pointer. */ using ModelWeakPtr = std::weak_ptr; /**< Type definition for weak model pointer. */ @@ -131,4 +133,10 @@ using History = std::vector; /**< Type definition for history.* using Strings = std::vector; /**< Type definition for strings.*/ +enum class TestType +{ + RESOLVED, + DEFINED, +}; + } // namespace libcellml diff --git a/src/issue.cpp b/src/issue.cpp index f192e1dbd..45c4259b2 100644 --- a/src/issue.cpp +++ b/src/issue.cpp @@ -16,7 +16,6 @@ limitations under the License. #include "libcellml/issue.h" -#include "anycellmlelement_p.h" #include "issue_p.h" #include "utilities.h" @@ -174,8 +173,11 @@ static const std::map> ruleToInfo {Issue::ReferenceRule::IMPORTER_MISSING_COMPONENT, {"IMPORTER_MISSING_COMPONENT", "", docsUrl, ""}}, {Issue::ReferenceRule::IMPORTER_MISSING_UNITS, {"IMPORTER_MISSING_UNITS", "", docsUrl, ""}}, {Issue::ReferenceRule::IMPORTER_NULL_MODEL, {"IMPORTER_NULL_MODEL", "", docsUrl, ""}}, + {Issue::ReferenceRule::IMPORTER_UNDEFINED_MODEL, {"IMPORTER_UNDEFINED_MODEL", "", docsUrl, ""}}, + {Issue::ReferenceRule::IMPORTER_UNRESOLVED_IMPORTS, {"IMPORTER_UNRESOLVED_IMPORTS", "", docsUrl, ""}}, // Analyser issues: + {Issue::ReferenceRule::ANALYSER_EQUATION_NOT_EQUALITY_STATEMENT, {"ANALYSER_EQUATION_NOT_EQUALITY_STATEMENT", "", docsUrl, ""}}, {Issue::ReferenceRule::ANALYSER_UNITS, {"ANALYSER_UNITS", "", docsUrl, ""}}, {Issue::ReferenceRule::ANALYSER_UNLINKED_UNITS, {"ANALYSER_UNLINKED_UNITS", "", docsUrl, ""}}, {Issue::ReferenceRule::ANALYSER_VARIABLE_INITIALISED_MORE_THAN_ONCE, {"ANALYSER_VARIABLE_INITIALISED_MORE_THAN_ONCE", "", docsUrl, ""}}, @@ -185,6 +187,7 @@ static const std::map> ruleToInfo {Issue::ReferenceRule::ANALYSER_ODE_NOT_FIRST_ORDER, {"ANALYSER_ODE_NOT_FIRST_ORDER", "", docsUrl, ""}}, {Issue::ReferenceRule::ANALYSER_VARIABLE_UNUSED, {"ANALYSER_VARIABLE_UNUSED", "", docsUrl, ""}}, {Issue::ReferenceRule::ANALYSER_STATE_NOT_INITIALISED, {"ANALYSER_STATE_NOT_INITIALISED", "", docsUrl, ""}}, + {Issue::ReferenceRule::ANALYSER_STATE_RATE_AS_ALGEBRAIC, {"ANALYSER_STATE_RATE_AS_ALGEBRAIC", "", docsUrl, ""}}, {Issue::ReferenceRule::ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE, {"ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE", "", docsUrl, ""}}, {Issue::ReferenceRule::ANALYSER_EXTERNAL_VARIABLE_DIFFERENT_MODEL, {"ANALYSER_EXTERNAL_VARIABLE_DIFFERENT_MODEL", "", docsUrl, ""}}, {Issue::ReferenceRule::ANALYSER_EXTERNAL_VARIABLE_VOI, {"ANALYSER_EXTERNAL_VARIABLE_VOI", "", docsUrl, ""}}, @@ -201,18 +204,18 @@ static const std::map> ruleToInfo std::string Issue::referenceHeading() const { - return ruleToInformation.find(referenceRule())->second[1]; + return ruleToInformation.at(referenceRule())[1]; } std::string Issue::url() const { - auto search = ruleToInformation.find(referenceRule()); + auto search = ruleToInformation.at(referenceRule()); - if (search->second[1].empty()) { - return search->second[2] + "?issue=" + search->second[0]; + if (search[1].empty()) { + return search[2] + "?issue=" + search[0]; } - return search->second[2] + search->second[3] + ".html?issue=" + search->second[0]; + return search[2] + search[3] + ".html?issue=" + search[0]; } } // namespace libcellml diff --git a/src/logger.cpp b/src/logger.cpp index 0059773cb..a4594b73f 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -112,7 +112,8 @@ void Logger::LoggerImpl::addIssue(const IssuePtr &issue) case libcellml::Issue::Level::WARNING: mWarnings.push_back(index); break; - case libcellml::Issue::Level::MESSAGE: + default: + // Only remaining level is MESSAGE. mMessages.push_back(index); break; } diff --git a/src/mathmldtd.h b/src/mathmldtd.h index cbd9de58c..8f5139688 100644 --- a/src/mathmldtd.h +++ b/src/mathmldtd.h @@ -16,6 +16,7 @@ limitations under the License. #pragma once +#include #include namespace libcellml { diff --git a/src/model.cpp b/src/model.cpp index 47857aa3c..7f89305de 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -30,6 +30,7 @@ limitations under the License. #include "libcellml/units.h" #include "libcellml/variable.h" +#include "commonutils.h" #include "component_p.h" #include "componententity_p.h" #include "internaltypes.h" @@ -273,23 +274,36 @@ bool Model::hasUnlinkedUnits() return unlinkedUnits; } +bool Model::isDefined() const +{ + bool defined = true; + for (size_t index = 0; (index < unitsCount()) && defined; ++index) { + defined = units(index)->isDefined(); + } + for (size_t index = 0; (index < componentCount()) && defined; ++index) { + defined = component(index)->isDefined(); + } + return defined; +} + bool Model::hasUnresolvedImports() const { bool unresolvedImports = false; - for (size_t n = 0; n < unitsCount() && !unresolvedImports; ++n) { - unresolvedImports = !units(n)->isResolved(); + for (size_t index = 0; (index < unitsCount()) && !unresolvedImports; ++index) { + unresolvedImports = !units(index)->isResolved(); } - for (size_t n = 0; (n < componentCount()) && !unresolvedImports; ++n) { - unresolvedImports = !component(n)->isResolved(); + for (size_t index = 0; (index < componentCount()) && !unresolvedImports; ++index) { + unresolvedImports = !component(index)->isResolved(); } + return unresolvedImports; } bool hasComponentImports(const ComponentEntityConstPtr &componentEntity) { bool importsPresent = false; - for (size_t n = 0; (n < componentEntity->componentCount()) && !importsPresent; ++n) { - libcellml::ComponentPtr childComponent = componentEntity->component(n); + for (size_t index = 0; (index < componentEntity->componentCount()) && !importsPresent; ++index) { + libcellml::ComponentPtr childComponent = componentEntity->component(index); importsPresent = childComponent->isImport(); if (!importsPresent) { importsPresent = hasComponentImports(childComponent); @@ -298,14 +312,28 @@ bool hasComponentImports(const ComponentEntityConstPtr &componentEntity) return importsPresent; } +bool hasUnitsImports(const UnitsPtr &units) +{ + bool importPresent = units->isImport(); + auto model = owningModel(units); + size_t unistCount = units->unitCount(); + for (size_t index = 0; !importPresent && (index < unistCount); ++index) { + std::string reference = units->unitAttributeReference(index); + if (!reference.empty() && !isStandardUnitName(reference)) { + if (model->hasUnits(reference)) { + importPresent = hasUnitsImports(model->units(reference)); + } + } + } + return importPresent; +} + bool Model::hasImports() const { bool importsPresent = false; - for (size_t n = 0; (n < unitsCount()) && !importsPresent; ++n) { - libcellml::UnitsPtr units = Model::units(n); - if (units->isImport()) { - importsPresent = true; - } + for (size_t index = 0; (index < unitsCount()) && !importsPresent; ++index) { + libcellml::UnitsPtr units = Model::units(index); + importsPresent = hasUnitsImports(units); } if (!importsPresent) { diff --git a/src/parser.cpp b/src/parser.cpp index 948eebb72..679a62278 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -281,9 +281,7 @@ ModelPtr Parser::ParserImpl::parseModel(const std::string &input) if (input.empty()) { auto issue = Issue::IssueImpl::create(); issue->mPimpl->setDescription("Model string is empty."); - if (mParser->isStrict()) { - issue->mPimpl->setReferenceRule(Issue::ReferenceRule::XML); - } + issue->mPimpl->setReferenceRule(Issue::ReferenceRule::XML); addIssue(issue); } else { model = Model::create(); @@ -389,9 +387,7 @@ void Parser::ParserImpl::loadModel(const ModelPtr &model, const std::string &inp for (size_t i = 0; i < doc->xmlErrorCount(); ++i) { auto issue = Issue::IssueImpl::create(); issue->mPimpl->setDescription("LibXml2 error: " + doc->xmlError(i)); - if (mParser->isStrict()) { - issue->mPimpl->setReferenceRule(Issue::ReferenceRule::XML); - } + issue->mPimpl->setReferenceRule(Issue::ReferenceRule::XML); addIssue(issue); } } @@ -462,6 +458,7 @@ void Parser::ParserImpl::loadModel(const ModelPtr &model, const std::string &inp } attribute = attribute->next(); } + // Get model children (CellML entities). XmlNodePtr childNode = node->firstChild(); std::vector connectionNodes; @@ -611,10 +608,10 @@ void Parser::ParserImpl::loadComponent(const ComponentPtr &component, const XmlN // If transforming, manipulate the math sub-document CellML namespaces. if (mParsing1XVersion) { // Find all attributes using old CellML namespace. - auto cellmlAttributes = attributesWithCellml1XNamespace(childNode); + auto cellmlAttributes = attributesWithCellml1XNamespace(childNode->firstChild()); // Remove all old CellML namespace definitions and references. - removeCellml1XNamespaces(childNode); + removeCellml1XNamespaces(childNode, true); if (!cellmlAttributes.empty()) { // Add CellML 2.0 namespace to MathML element. @@ -629,7 +626,7 @@ void Parser::ParserImpl::loadComponent(const ComponentPtr &component, const XmlN // Copy any namespaces that do not feature as a namespace definition // of the math node into the math node. auto mathElementDefinedNamespaces = childNode->definedNamespaces(); - auto possiblyUndefinedNamespaces = traverseTreeForUndefinedNamespaces(childNode); + auto possiblyUndefinedNamespaces = traverseTreeForUndefinedNamespaces(childNode->firstChild()); auto undefinedNamespaces = determineMissingNamespaces(possiblyUndefinedNamespaces, mathElementDefinedNamespaces); XmlNamespaceMap::const_iterator it; for (it = undefinedNamespaces.begin(); it != undefinedNamespaces.end(); ++it) { @@ -775,11 +772,7 @@ void Parser::ParserImpl::loadUnit(const UnitsPtr &units, const XmlNodePtr &node) prefix = attribute->value(); } else if (attribute->isType("exponent")) { if (isCellMLReal(attribute->value())) { - bool validConversion; - double tmpExponent = convertToDouble(attribute->value(), &validConversion); - if (validConversion) { - exponent = tmpExponent; - } else { + if (!convertToDouble(attribute->value(), exponent)) { // This value won't be saved for validation later, so it does need to be reported now. auto issue = Issue::IssueImpl::create(); issue->mPimpl->setDescription("Unit referencing '" + node->attribute("units") + "' in units '" + units->name() + "' has an exponent with the value '" + attribute->value() + "' that is a representation of a CellML real valued number, but out of range of the 'double' type."); @@ -797,11 +790,7 @@ void Parser::ParserImpl::loadUnit(const UnitsPtr &units, const XmlNodePtr &node) } } else if (attribute->isType("multiplier")) { if (isCellMLReal(attribute->value())) { - bool validConversion; - double tmpMultiplier = convertToDouble(attribute->value(), &validConversion); - if (validConversion) { - multiplier = tmpMultiplier; - } else { + if (!convertToDouble(attribute->value(), multiplier)) { // This value won't be saved for validation later, so it does need to be reported now. auto issue = Issue::IssueImpl::create(); issue->mPimpl->setDescription("Unit referencing '" + node->attribute("units") + "' in units '" + units->name() + "' has a multiplier with the value '" + attribute->value() + "' that is a representation of a CellML real valued number, but out of range of the 'double' type."); @@ -1587,7 +1576,7 @@ void Parser::ParserImpl::loadReset(const ResetPtr &reset, const ComponentPtr &co orderDefined = true; orderValid = isCellMLInteger(attribute->value()); if (orderValid) { - order = convertToInt(attribute->value(), &orderValid); + orderValid = convertToInt(attribute->value(), order); if (!orderValid) { std::string variableName; if (reset->variable() != nullptr) { diff --git a/src/printer.cpp b/src/printer.cpp index 1055caaa8..db5ca8727 100644 --- a/src/printer.cpp +++ b/src/printer.cpp @@ -33,14 +33,13 @@ limitations under the License. #include "libcellml/variable.h" #include "anycellmlelement_p.h" +#include "commonutils.h" #include "internaltypes.h" #include "issue_p.h" #include "logger_p.h" #include "utilities.h" #include "xmldoc.h" -#include - namespace libcellml { /** @@ -86,11 +85,10 @@ std::string printConnections(const ComponentMap &componentMap, const VariableMap ComponentPtr currentComponent1 = iterPair->first; ComponentPtr currentComponent2 = iterPair->second; ComponentPair currentComponentPair = std::make_pair(currentComponent1, currentComponent2); - ComponentPair reciprocalCurrentComponentPair = std::make_pair(currentComponent2, currentComponent1); // Check whether this set of connections has already been serialised. bool pairFound = false; for (const auto &serialisedIterPair : serialisedComponentMap) { - if ((serialisedIterPair == currentComponentPair) || (serialisedIterPair == reciprocalCurrentComponentPair)) { + if (serialisedIterPair == currentComponentPair) { pairFound = true; break; } @@ -117,10 +115,7 @@ std::string printConnections(const ComponentMap &componentMap, const VariableMap ++componentMapIndex2; } // Serialise out the new connection. - connections += "name() + "\""; - } + connections += "name() + "\""; if (currentComponent2 != nullptr) { connections += " component_2=\"" + currentComponent2->name() + "\""; } @@ -139,17 +134,24 @@ std::string printConnections(const ComponentMap &componentMap, const VariableMap std::string Printer::PrinterImpl::printMath(const std::string &math) { + static const std::string wrapElementName = "math_wrap_as_single_root_element"; static const std::regex before(">[\\s\n\t]*"); static const std::regex after("[\\s\n\t]*<"); static const std::regex xmlDeclaration(R"|(<\?xml[[:space:]]+version=.*\?>)|"); XmlDocPtr xmlDoc = std::make_shared(); xmlKeepBlanksDefault(0); - xmlDoc->parse(math); + // Remove any XML declarations from the string. + std::string normalisedMath = std::regex_replace(math, xmlDeclaration, ""); + xmlDoc->parse("<" + wrapElementName + ">" + normalisedMath + ""); if (xmlDoc->xmlErrorCount() == 0) { - auto result = xmlDoc->prettyPrint(); - // Remove any XML declarations from the string. - result = std::regex_replace(result, xmlDeclaration, ""); + auto rootNode = xmlDoc->rootNode(); + auto childNode = rootNode->firstChild(); + std::string result; + while (childNode != nullptr) { + result += childNode->convertToStrippedString(); + childNode = childNode->next(); + } // Clean whitespace in the math. result = std::regex_replace(result, before, ">"); return std::regex_replace(result, after, "<"); @@ -171,23 +173,20 @@ void buildMapsForComponentsVariables(const ComponentPtr &component, ComponentMap VariablePtr variable = component->variable(i); for (size_t j = 0; j < variable->equivalentVariableCount(); ++j) { VariablePtr equivalentVariable = variable->equivalentVariable(j); - if (equivalentVariable->hasEquivalentVariable(variable)) { - VariablePairPtr variablePair = VariablePair::create(variable, equivalentVariable); - auto pairFound = std::find_if(variableMap.begin(), variableMap.end(), - [variable, equivalentVariable](const VariablePairPtr &in) { - return ((in->variable1() == equivalentVariable) && (in->variable2() == variable)) - || ((in->variable1() == variable) && (in->variable2() == equivalentVariable)); - }); - if (pairFound == variableMap.end()) { - // Get parent components. - ComponentPtr component1 = owningComponent(variable); - ComponentPtr component2 = owningComponent(equivalentVariable); - // Add new unique variable equivalence pair to the VariableMap. - variableMap.push_back(variablePair); - // Also create a component map pair corresponding with the variable map pair. - ComponentPair componentPair = std::make_pair(component1, component2); - componentMap.push_back(componentPair); - } + VariablePairPtr variablePair = VariablePair::create(variable, equivalentVariable); + auto pairFound = std::find_if(variableMap.begin(), variableMap.end(), + [variable, equivalentVariable](const VariablePairPtr &in) { + return (in->variable1() == equivalentVariable) && (in->variable2() == variable); + }); + if (pairFound == variableMap.end()) { + // Add new unique variable equivalence pair to the VariableMap. + variableMap.push_back(variablePair); + // Get parent components. + ComponentPtr component1 = owningComponent(variable); + ComponentPtr component2 = owningComponent(equivalentVariable); + // Also create a component map pair corresponding with the variable map pair. + ComponentPair componentPair = std::make_pair(component1, component2); + componentMap.push_back(componentPair); } } } diff --git a/src/types.cpp b/src/types.cpp index 99d87a5a7..c011be60a 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -16,12 +16,16 @@ limitations under the License. #include "libcellml/types.h" +#include + #include "libcellml/units.h" #include "libcellml/variable.h" #include "anycellmlelement_p.h" #include "internaltypes.h" +#include + namespace libcellml { /** diff --git a/src/units.cpp b/src/units.cpp index b88d42ea3..87800cdd8 100644 --- a/src/units.cpp +++ b/src/units.cpp @@ -30,11 +30,67 @@ limitations under the License. #include #include +#include "commonutils.h" #include "units_p.h" #include "utilities.h" namespace libcellml { +static const std::map prefixToString = { + {Units::Prefix::ATTO, "atto"}, + {Units::Prefix::CENTI, "centi"}, + {Units::Prefix::DECA, "deca"}, + {Units::Prefix::DECI, "deci"}, + {Units::Prefix::EXA, "exa"}, + {Units::Prefix::FEMTO, "femto"}, + {Units::Prefix::GIGA, "giga"}, + {Units::Prefix::HECTO, "hecto"}, + {Units::Prefix::KILO, "kilo"}, + {Units::Prefix::MEGA, "mega"}, + {Units::Prefix::MICRO, "micro"}, + {Units::Prefix::MILLI, "milli"}, + {Units::Prefix::NANO, "nano"}, + {Units::Prefix::PETA, "peta"}, + {Units::Prefix::PICO, "pico"}, + {Units::Prefix::TERA, "tera"}, + {Units::Prefix::YOCTO, "yocto"}, + {Units::Prefix::YOTTA, "yotta"}, + {Units::Prefix::ZEPTO, "zepto"}, + {Units::Prefix::ZETTA, "zetta"}}; + +static const std::map standardUnitToString = { + {Units::StandardUnit::AMPERE, "ampere"}, + {Units::StandardUnit::BECQUEREL, "becquerel"}, + {Units::StandardUnit::CANDELA, "candela"}, + {Units::StandardUnit::COULOMB, "coulomb"}, + {Units::StandardUnit::DIMENSIONLESS, "dimensionless"}, + {Units::StandardUnit::FARAD, "farad"}, + {Units::StandardUnit::GRAM, "gram"}, + {Units::StandardUnit::GRAY, "gray"}, + {Units::StandardUnit::HENRY, "henry"}, + {Units::StandardUnit::HERTZ, "hertz"}, + {Units::StandardUnit::JOULE, "joule"}, + {Units::StandardUnit::KATAL, "katal"}, + {Units::StandardUnit::KELVIN, "kelvin"}, + {Units::StandardUnit::KILOGRAM, "kilogram"}, + {Units::StandardUnit::LITRE, "litre"}, + {Units::StandardUnit::LUMEN, "lumen"}, + {Units::StandardUnit::LUX, "lux"}, + {Units::StandardUnit::METRE, "metre"}, + {Units::StandardUnit::MOLE, "mole"}, + {Units::StandardUnit::NEWTON, "newton"}, + {Units::StandardUnit::OHM, "ohm"}, + {Units::StandardUnit::PASCAL, "pascal"}, + {Units::StandardUnit::RADIAN, "radian"}, + {Units::StandardUnit::SECOND, "second"}, + {Units::StandardUnit::SIEMENS, "siemens"}, + {Units::StandardUnit::SIEVERT, "sievert"}, + {Units::StandardUnit::STERADIAN, "steradian"}, + {Units::StandardUnit::TESLA, "tesla"}, + {Units::StandardUnit::VOLT, "volt"}, + {Units::StandardUnit::WATT, "watt"}, + {Units::StandardUnit::WEBER, "weber"}}; + std::vector::const_iterator Units::UnitsImpl::findUnit(const std::string &reference) const { return std::find_if(mUnitDefinitions.begin(), mUnitDefinitions.end(), @@ -78,19 +134,17 @@ bool Units::UnitsImpl::isBaseUnitWithHistory(History &history, const UnitsConstP { if (mUnits->isImport()) { ImportSourcePtr importedSource = mUnits->importSource(); - if (importedSource != nullptr) { - ModelPtr model = importedSource->model(); - if (model != nullptr) { - auto h = createHistoryEpoch(units, importeeModelUrl(history, mUnits->importSource()->url())); - if (checkForImportCycles(history, h)) { - return false; - } - history.push_back(h); - if (model->hasUnits(mUnits->importReference())) { - auto importedUnits = model->units(mUnits->importReference()); - // Call isBaseUnit recursively until unit is no longer an import. - return importedUnits->pFunc()->isBaseUnitWithHistory(history, importedUnits); - } + ModelPtr model = importedSource->model(); + if (model != nullptr) { + auto h = createHistoryEpoch(units, importeeModelUrl(history, mUnits->importSource()->url())); + if (checkForImportCycles(history, h)) { + return false; + } + history.push_back(h); + if (model->hasUnits(mUnits->importReference())) { + auto importedUnits = model->units(mUnits->importReference()); + // Call isBaseUnit recursively until unit is no longer an import. + return importedUnits->pFunc()->isBaseUnitWithHistory(history, importedUnits); } } return false; @@ -104,52 +158,47 @@ bool Units::UnitsImpl::isBaseUnitWithHistory(History &history, const UnitsConstP return (mUnits->unitCount() == 0) && standardUnitCheck; } -bool Units::UnitsImpl::isResolvedWithHistory(History &history, const UnitsConstPtr &units) const +bool Units::UnitsImpl::performTestWithHistory(History &history, const UnitsConstPtr &units, TestType type) const { - if (!mUnits->isImport()) { - return true; - } - - auto model = mUnits->importSource()->model(); - if (model == nullptr) { - return false; - } + ModelPtr model; + if (mUnits->isImport()) { + model = mUnits->importSource()->model(); + if (model == nullptr) { + return false; + } - auto importedUnits = model->units(mUnits->importReference()); - if (importedUnits == nullptr) { - return false; - } + auto importedUnits = model->units(mUnits->importReference()); + if (importedUnits == nullptr) { + return false; + } - auto h = createHistoryEpoch(units, importeeModelUrl(history, mUnits->importSource()->url())); - if (checkForImportCycles(history, h)) { - return false; - } + auto h = createHistoryEpoch(units, importeeModelUrl(history, mUnits->importSource()->url())); + if (checkForImportCycles(history, h)) { + return false; + } - if (importedUnits->isImport()) { history.push_back(h); - return importedUnits->pFunc()->isResolvedWithHistory(history, importedUnits); + return importedUnits->pFunc()->performTestWithHistory(history, importedUnits, type); } - for (size_t u = 0; (u < importedUnits->unitCount()); ++u) { - std::string reference; - std::string prefix; - std::string id; - double exponent; - double multiplier; - importedUnits->unitAttributes(u, reference, prefix, exponent, multiplier, id); + model = std::dynamic_pointer_cast(mUnits->parent()); + for (size_t unitIndex = 0; unitIndex < mUnits->unitCount(); ++unitIndex) { + std::string reference = mUnits->unitAttributeReference(unitIndex); if (isStandardUnitName(reference)) { continue; } - auto childUnits = model->units(reference); - if (childUnits == nullptr) { - return false; - } - - history.push_back(h); - - if (!childUnits->pFunc()->isResolvedWithHistory(history, childUnits)) { + if (model != nullptr) { + auto childUnits = model->units(reference); + if (childUnits != nullptr) { + if (!childUnits->pFunc()->performTestWithHistory(history, childUnits, type)) { + return false; + } + } else if (type == TestType::DEFINED) { + return false; + } + } else if (type == TestType::DEFINED) { return false; } } @@ -173,11 +222,17 @@ bool Units::UnitsImpl::isResolvedWithHistory(History &history, const UnitsConstP bool updateUnitMultiplier(const UnitsPtr &units, int direction, double &multiplier) { double localMultiplier = 0; - bool updated = false; - if (units->unitCount() == 0) { - updated = true; - } else { + if (units->isImport()) { + if (units->isResolved()) { + auto importSource = units->importSource(); + auto importedUnits = importSource->model()->units(units->importReference()); + updateUnitMultiplier(importedUnits, 1, localMultiplier); + multiplier += localMultiplier * direction; + } else { + return false; + } + } else if (units->unitCount() > 0) { std::string ref; std::string pre; std::string id; @@ -191,7 +246,6 @@ bool updateUnitMultiplier(const UnitsPtr &units, int direction, double &multipli mult = std::log10(expMult); bool ok; - prefixMult = convertPrefixToInt(pre, &ok); if (!ok) { return false; @@ -203,27 +257,23 @@ bool updateUnitMultiplier(const UnitsPtr &units, int direction, double &multipli localMultiplier += mult + standardMult * exp + prefixMult; } else { auto model = owningModel(units); - if (model != nullptr) { - auto refUnits = model->units(ref); - if (refUnits == nullptr) { - return false; - } - double branchMult = 0.0; - // Return false when we can't find a valid prefix. - if (!updateUnitMultiplier(refUnits, 1, branchMult)) { - return false; - } - // Make the direction positive on all branches, direction is only applied at the end. - localMultiplier += mult + branchMult * exp + prefixMult; - } else { + auto refUnits = model->units(ref); + if (refUnits == nullptr) { + return false; + } + double branchMult = 0.0; + // Return false when we can't find a valid prefix. + if (!updateUnitMultiplier(refUnits, 1, branchMult)) { return false; } + // Make the direction positive on all branches, direction is only applied at the end. + localMultiplier += mult + branchMult * exp + prefixMult; } } multiplier += localMultiplier * direction; - updated = true; } - return updated; + + return true; } UnitsPtr Units::create() noexcept @@ -256,9 +306,6 @@ bool Units::doEquals(const EntityPtr &other) const return false; } - // Check unit definitions match. - static const auto PTRDIFF_T_MAX = size_t(std::numeric_limits::max()); - std::string reference; std::string prefix; double exponent; @@ -286,7 +333,7 @@ bool Units::doEquals(const EntityPtr &other) const } } - if (!unitFound || (index >= PTRDIFF_T_MAX)) { + if (!unitFound) { return false; } @@ -326,16 +373,13 @@ void Units::addUnit(const std::string &reference, const std::string &prefix, dou void Units::addUnit(const std::string &reference, Prefix prefix, double exponent, double multiplier, const std::string &id) { - auto search = prefixToString.find(prefix); - const std::string prefixString = search->second; - addUnit(reference, prefixString, exponent, multiplier, id); + addUnit(reference, prefixToString.at(prefix), exponent, multiplier, id); } void Units::addUnit(const std::string &reference, int prefix, double exponent, double multiplier, const std::string &id) { - const std::string prefixString = convertToString(prefix); - addUnit(reference, prefixString, exponent, multiplier, id); + addUnit(reference, convertToString(prefix), exponent, multiplier, id); } void Units::addUnit(const std::string &reference, double exponent, const std::string &id) @@ -351,51 +395,41 @@ void Units::addUnit(const std::string &reference) void Units::addUnit(StandardUnit standardUnit, const std::string &prefix, double exponent, double multiplier, const std::string &id) { - const std::string reference = standardUnitToString.find(standardUnit)->second; - addUnit(reference, prefix, exponent, multiplier, id); + addUnit(standardUnitToString.at(standardUnit), prefix, exponent, multiplier, id); } void Units::addUnit(StandardUnit standardUnit, Prefix prefix, double exponent, double multiplier, const std::string &id) { - const std::string reference = standardUnitToString.find(standardUnit)->second; - const std::string prefixString = prefixToString.find(prefix)->second; - addUnit(reference, prefixString, exponent, multiplier, id); + addUnit(standardUnitToString.at(standardUnit), prefixToString.at(prefix), exponent, multiplier, id); } void Units::addUnit(StandardUnit standardUnit, int prefix, double exponent, double multiplier, const std::string &id) { - const std::string reference = standardUnitToString.find(standardUnit)->second; - const std::string prefixString = convertToString(prefix); - addUnit(reference, prefixString, exponent, multiplier, id); + addUnit(standardUnitToString.at(standardUnit), convertToString(prefix), exponent, multiplier, id); } void Units::addUnit(StandardUnit standardUnit, double exponent, const std::string &id) { - const std::string reference = standardUnitToString.find(standardUnit)->second; - addUnit(reference, "0", exponent, 1.0, id); + addUnit(standardUnitToString.at(standardUnit), "0", exponent, 1.0, id); } void Units::addUnit(StandardUnit standardUnit) { - const std::string reference = standardUnitToString.find(standardUnit)->second; - addUnit(reference, "0", 1.0, 1.0, ""); + addUnit(standardUnitToString.at(standardUnit), "0", 1.0, 1.0, ""); } void Units::unitAttributes(StandardUnit standardUnit, std::string &prefix, double &exponent, double &multiplier, std::string &id) const { std::string dummyReference; - const std::string reference = standardUnitToString.find(standardUnit)->second; - auto result = pFunc()->findUnit(reference); - unitAttributes(size_t(result - pFunc()->mUnitDefinitions.begin()), dummyReference, prefix, exponent, multiplier, id); + unitAttributes(static_cast(pFunc()->findUnit(standardUnitToString.at(standardUnit)) - pFunc()->mUnitDefinitions.begin()), dummyReference, prefix, exponent, multiplier, id); } void Units::unitAttributes(const std::string &reference, std::string &prefix, double &exponent, double &multiplier, std::string &id) const { std::string dummyReference; - auto result = pFunc()->findUnit(reference); - unitAttributes(size_t(result - pFunc()->mUnitDefinitions.begin()), dummyReference, prefix, exponent, multiplier, id); + unitAttributes(static_cast(pFunc()->findUnit(reference) - pFunc()->mUnitDefinitions.begin()), dummyReference, prefix, exponent, multiplier, id); } void Units::unitAttributes(size_t index, std::string &reference, std::string &prefix, double &exponent, double &multiplier, std::string &id) const @@ -422,6 +456,15 @@ std::string Units::unitAttributeReference(size_t index) const return ref; } +void Units::setUnitAttributeReference(size_t index, const std::string &reference) +{ + if (index < pFunc()->mUnitDefinitions.size()) { + UnitDefinition unitDefinition = pFunc()->mUnitDefinitions.at(index); + unitDefinition.mReference = reference; + pFunc()->mUnitDefinitions[index] = unitDefinition; + } +} + std::string Units::unitAttributePrefix(size_t index) const { std::string ref; @@ -543,8 +586,7 @@ using UnitsMap = std::map; void updateUnitsMapWithStandardUnit(const std::string &name, UnitsMap &unitsMap, double exp) { - auto unitsListIter = standardUnitsList.find(name); - for (const auto &baseUnitsComponent : unitsListIter->second) { + for (const auto &baseUnitsComponent : standardUnitsList.at(name)) { auto unitsMapIter = unitsMap.find(baseUnitsComponent.first); if (unitsMapIter == unitsMap.end()) { unitsMap.emplace(baseUnitsComponent.first, 0.0); @@ -553,7 +595,7 @@ void updateUnitsMapWithStandardUnit(const std::string &name, UnitsMap &unitsMap, } } -bool updateUnitsMap(const UnitsPtr &units, UnitsMap &unitsMap, double exp = 1.0) +void updateUnitsMap(const UnitsPtr &units, UnitsMap &unitsMap, double exp = 1.0) { if (units->isBaseUnit()) { auto unitsName = units->name(); @@ -565,6 +607,10 @@ bool updateUnitsMap(const UnitsPtr &units, UnitsMap &unitsMap, double exp = 1.0) } } else if (isStandardUnit(units)) { updateUnitsMapWithStandardUnit(units->name(), unitsMap, exp); + } else if (units->isImport()) { + auto importSource = units->importSource(); + auto importedUnits = importSource->model()->units(units->importReference()); + updateUnitsMap(importedUnits, unitsMap); } else { for (size_t i = 0; i < units->unitCount(); ++i) { std::string ref; @@ -577,33 +623,18 @@ bool updateUnitsMap(const UnitsPtr &units, UnitsMap &unitsMap, double exp = 1.0) updateUnitsMapWithStandardUnit(ref, unitsMap, uExp * exp); } else { auto model = owningModel(units); - if (model == nullptr) { - // We cannot resolve the reference for this units so we add - // what we do know. - unitsMap.emplace(ref, uExp * exp); - } else { - auto refUnits = model->units(ref); - if ((refUnits == nullptr) || refUnits->isImport()) { - return false; - } - if (!updateUnitsMap(refUnits, unitsMap, uExp * exp)) { - return false; - } - } + auto refUnits = model->units(ref); + updateUnitsMap(refUnits, unitsMap, uExp * exp); } } } - return true; } -UnitsMap createUnitsMap(const UnitsPtr &units, bool &isValid) +UnitsMap defineUnitsMap(const UnitsPtr &units) { UnitsMap unitsMap; - isValid = true; - if (!updateUnitsMap(units, unitsMap)) { - isValid = false; - return unitsMap; - } + + updateUnitsMap(units, unitsMap); // Checking for exponents of zero in the map, which can be removed. auto it = unitsMap.begin(); @@ -628,16 +659,10 @@ bool Units::requiresImports() const auto model = owningModel(shared_from_this()); if (model != nullptr) { - std::string ref; - std::string prefix; - double exponent; - double multiplier; - std::string id; - for (size_t u = 0; u < unitCount(); ++u) { - unitAttributes(u, ref, prefix, exponent, multiplier, id); + const std::string ref = unitAttributeReference(u); auto child = model->units(ref); - if (child == nullptr) { + if ((child == nullptr) || (this == child.get())) { continue; } if (child->requiresImports()) { @@ -654,22 +679,13 @@ bool Units::compatible(const UnitsPtr &units1, const UnitsPtr &units2) if ((units1 == nullptr) || (units2 == nullptr)) { return false; } - if ((units1->isImport()) || (units2->isImport())) { - return false; - } - if ((units1->requiresImports()) || (units2->requiresImports())) { - return false; - } - bool isValid; - auto units1Map = createUnitsMap(units1, isValid); - if (!isValid) { - return false; - } - auto units2Map = createUnitsMap(units2, isValid); - if (!isValid) { + if ((!units1->isDefined()) || (!units2->isDefined())) { return false; } + UnitsMap units1Map = defineUnitsMap(units1); + UnitsMap units2Map = defineUnitsMap(units2); + if (units1Map.size() == units2Map.size()) { for (const auto &units : units1Map) { std::string unit = units.first; @@ -682,8 +698,10 @@ bool Units::compatible(const UnitsPtr &units1, const UnitsPtr &units2) return false; } } + return true; } + return false; } @@ -719,10 +737,16 @@ UnitsPtr Units::clone() const return units; } +bool Units::isDefined() const +{ + History history; + return pFunc()->performTestWithHistory(history, shared_from_this(), TestType::DEFINED); +} + bool Units::doIsResolved() const { History history; - return pFunc()->isResolvedWithHistory(history, shared_from_this()); + return pFunc()->performTestWithHistory(history, shared_from_this(), TestType::RESOLVED); } } // namespace libcellml diff --git a/src/units_p.h b/src/units_p.h index 45f5cf9e3..a07fb49d9 100644 --- a/src/units_p.h +++ b/src/units_p.h @@ -18,76 +18,11 @@ limitations under the License. #include "libcellml/units.h" +#include "internaltypes.h" #include "namedentity_p.h" -#include "utilities.h" namespace libcellml { -/** - * @brief Map Prefix to their string forms. - * - * An internal map used to convert a Prefix into its string form. - */ -static const std::map prefixToString = { - {Units::Prefix::ATTO, "atto"}, - {Units::Prefix::CENTI, "centi"}, - {Units::Prefix::DECA, "deca"}, - {Units::Prefix::DECI, "deci"}, - {Units::Prefix::EXA, "exa"}, - {Units::Prefix::FEMTO, "femto"}, - {Units::Prefix::GIGA, "giga"}, - {Units::Prefix::HECTO, "hecto"}, - {Units::Prefix::KILO, "kilo"}, - {Units::Prefix::MEGA, "mega"}, - {Units::Prefix::MICRO, "micro"}, - {Units::Prefix::MILLI, "milli"}, - {Units::Prefix::NANO, "nano"}, - {Units::Prefix::PETA, "peta"}, - {Units::Prefix::PICO, "pico"}, - {Units::Prefix::TERA, "tera"}, - {Units::Prefix::YOCTO, "yocto"}, - {Units::Prefix::YOTTA, "yotta"}, - {Units::Prefix::ZEPTO, "zepto"}, - {Units::Prefix::ZETTA, "zetta"}}; - -/** - * @brief Map StandardUnit to their string forms. - * - * An internal map used to convert a standard unit into its string form. - */ -static const std::map standardUnitToString = { - {Units::StandardUnit::AMPERE, "ampere"}, - {Units::StandardUnit::BECQUEREL, "becquerel"}, - {Units::StandardUnit::CANDELA, "candela"}, - {Units::StandardUnit::COULOMB, "coulomb"}, - {Units::StandardUnit::DIMENSIONLESS, "dimensionless"}, - {Units::StandardUnit::FARAD, "farad"}, - {Units::StandardUnit::GRAM, "gram"}, - {Units::StandardUnit::GRAY, "gray"}, - {Units::StandardUnit::HENRY, "henry"}, - {Units::StandardUnit::HERTZ, "hertz"}, - {Units::StandardUnit::JOULE, "joule"}, - {Units::StandardUnit::KATAL, "katal"}, - {Units::StandardUnit::KELVIN, "kelvin"}, - {Units::StandardUnit::KILOGRAM, "kilogram"}, - {Units::StandardUnit::LITRE, "litre"}, - {Units::StandardUnit::LUMEN, "lumen"}, - {Units::StandardUnit::LUX, "lux"}, - {Units::StandardUnit::METRE, "metre"}, - {Units::StandardUnit::MOLE, "mole"}, - {Units::StandardUnit::NEWTON, "newton"}, - {Units::StandardUnit::OHM, "ohm"}, - {Units::StandardUnit::PASCAL, "pascal"}, - {Units::StandardUnit::RADIAN, "radian"}, - {Units::StandardUnit::SECOND, "second"}, - {Units::StandardUnit::SIEMENS, "siemens"}, - {Units::StandardUnit::SIEVERT, "sievert"}, - {Units::StandardUnit::STERADIAN, "steradian"}, - {Units::StandardUnit::TESLA, "tesla"}, - {Units::StandardUnit::VOLT, "volt"}, - {Units::StandardUnit::WATT, "watt"}, - {Units::StandardUnit::WEBER, "weber"}}; - /** * @brief The UnitDefinition struct. * @@ -132,7 +67,7 @@ class Units::UnitsImpl: public NamedEntityImpl bool isBaseUnitWithHistory(History &history, const UnitsConstPtr &units) const; - bool isResolvedWithHistory(History &history, const UnitsConstPtr &units) const; + bool performTestWithHistory(History &history, const UnitsConstPtr &units, TestType type) const; Units *mUnits = nullptr; }; diff --git a/src/utilities.cpp b/src/utilities.cpp index b53ca2c50..d59a96337 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -34,34 +34,62 @@ limitations under the License. #include "libcellml/units.h" #include "libcellml/variable.h" +#include "commonutils.h" #include "xmldoc.h" #include "xmlutils.h" namespace libcellml { -double convertToDouble(const std::string &in, bool *ok) +static const std::map standardPrefixList = { + {"yotta", 24}, + {"zetta", 21}, + {"exa", 18}, + {"peta", 15}, + {"tera", 12}, + {"giga", 9}, + {"mega", 6}, + {"kilo", 3}, + {"hecto", 2}, + {"deca", 1}, + {"deci", -1}, + {"centi", -2}, + {"milli", -3}, + {"micro", -6}, + {"nano", -9}, + {"pico", -12}, + {"femto", -15}, + {"atto", -18}, + {"zepto", -21}, + {"yocto", -24}}; + +bool stringToDouble(const std::string &in, double &out) { - double out = 0.0; - if (ok != nullptr) { - *ok = true; + try { + out = std::stod(in); + } catch (std::out_of_range &) { + return false; } - if (!isCellMLReal(in)) { - if (ok != nullptr) { - *ok = false; - } + return true; +} - return out; +bool canConvertToBasicDouble(const std::string &in) +{ + if (!isCellMLBasicReal(in)) { + return false; } - try { - out = std::stod(in); - } catch (std::out_of_range &) { - if (ok != nullptr) { - *ok = false; - } + double temp; + return stringToDouble(in, temp); +} + +bool convertToDouble(const std::string &in, double &out) +{ + if (!isCellMLReal(in)) { + return false; } - return out; + + return stringToDouble(in, out); } bool hasNonWhitespaceCharacters(const std::string &input) @@ -96,29 +124,18 @@ std::string convertToString(double value, bool fullPrecision) return strs.str(); } -int convertToInt(const std::string &in, bool *ok) +bool convertToInt(const std::string &in, int &out) { - int out = 0; - if (ok != nullptr) { - *ok = true; - } - if (!isCellMLInteger(in)) { - if (ok != nullptr) { - *ok = false; - } - - return out; + return false; } try { out = std::stoi(in); } catch (std::out_of_range &) { - if (ok != nullptr) { - *ok = false; - } + return false; } - return out; + return true; } int convertPrefixToInt(const std::string &in, bool *ok) @@ -132,7 +149,10 @@ int convertPrefixToInt(const std::string &in, bool *ok) if (isStandardPrefixName(in)) { prefixInt = standardPrefixList.at(in); } else if (!in.empty()) { - prefixInt = convertToInt(in, ok); + bool success = convertToInt(in, prefixInt); + if (ok != nullptr) { + *ok = success; + } } return prefixInt; } @@ -345,7 +365,7 @@ bool isStandardUnitName(const std::string &name) bool isStandardUnit(const UnitsPtr &units) { - return (units != nullptr) && (units->unitCount() == 0) && isStandardUnitName(units->name()); + return (units->unitCount() == 0) && isStandardUnitName(units->name()); } bool isStandardPrefixName(const std::string &name) @@ -388,7 +408,7 @@ bool isEntityChildOf(const ParentedEntityPtr &entity1, const ParentedEntityPtr & bool areEntitiesSiblings(const ParentedEntityPtr &entity1, const ParentedEntityPtr &entity2) { auto entity1Parent = entity1->parent(); - return entity1Parent != nullptr && entity1Parent == entity2->parent(); + return entity1Parent == entity2->parent(); } using PublicPrivateRequiredPair = std::pair; @@ -413,7 +433,7 @@ PublicPrivateRequiredPair publicAndOrPrivateInterfaceTypeRequired(const Variable auto equivalentVariable = variable->equivalentVariable(index); auto componentOfVariable = variable->parent(); auto componentOfEquivalentVariable = equivalentVariable->parent(); - if (componentOfVariable == nullptr || componentOfEquivalentVariable == nullptr) { + if (componentOfEquivalentVariable == nullptr) { return std::make_pair(false, false); } if (areEntitiesSiblings(componentOfVariable, componentOfEquivalentVariable) @@ -464,9 +484,7 @@ void findAllVariablesWithEquivalences(const ComponentPtr &component, VariablePtr for (size_t index = 0; index < component->variableCount(); ++index) { auto variable = component->variable(index); if (variable->equivalentVariableCount() > 0) { - if (std::find(variables.begin(), variables.end(), variable) == variables.end()) { - variables.push_back(variable); - } + variables.push_back(variable); } } for (size_t index = 0; index < component->componentCount(); ++index) { @@ -474,17 +492,37 @@ void findAllVariablesWithEquivalences(const ComponentPtr &component, VariablePtr } } +/** + * @brief Return a list of names taken from MathML cn units attribute. + * + * Search the given @p node for MathML @c cn elements. + * For all @c cn elements return the units reference if it is not empty + * or a reference to a standard unit. + * + * @param node The node to search for MathML @c cn elements. + * @return A list of units references. + */ NameList findCnUnitsNames(const XmlNodePtr &node); -NameList findComponentCnUnitsNames(const ComponentPtr &component); -void findAndReplaceCnUnitsNames(const XmlNodePtr &node, const StringStringMap &replaceMap); -void findAndReplaceComponentCnUnitsNames(const ComponentPtr &component, const StringStringMap &replaceMap); + +/** + * @brief Find all MathML @c cn elements units attributes in the given component's math string. + * + * Search through the @p component's math string and return a list of units references found + * on MathML @c cn elements units attribute. + * + * @param component The component to search. + * @return A list of units references. + */ +NameList findComponentCnUnitsNames(const ComponentConstPtr &component); + +void findAndReplaceCnUnitsNames(const XmlNodePtr &node, const std::string &oldName, const std::string &newName); +void findAndReplaceComponentCnUnitsNames(const ComponentPtr &component, const std::string &oldName, const std::string &newName); size_t getComponentIndexInComponentEntity(const ComponentEntityPtr &componentParent, const ComponentEntityPtr &component); IndexStack indexStackOf(const VariablePtr &variable); VariablePtr getVariableLocatedAt(const IndexStack &stack, const ModelPtr &model); void makeEquivalence(const IndexStack &stack1, const IndexStack &stack2, const ModelPtr &model); IndexStack rebaseIndexStack(const IndexStack &stack, const IndexStack &originStack, const IndexStack &destinationStack); void componentNames(const ComponentPtr &component, NameList &names); -std::vector referencedUnits(const ModelPtr &model, const UnitsPtr &units); NameList findCnUnitsNames(const XmlNodePtr &node) { @@ -505,7 +543,7 @@ NameList findCnUnitsNames(const XmlNodePtr &node) return names; } -NameList findComponentCnUnitsNames(const ComponentPtr &component) +NameList findComponentCnUnitsNames(const ComponentConstPtr &component) { NameList names; // Inspect the MathML in this component for any specified constant units. @@ -525,23 +563,22 @@ NameList findComponentCnUnitsNames(const ComponentPtr &component) return names; } -void findAndReplaceCnUnitsNames(const XmlNodePtr &node, const StringStringMap &replaceMap) +void findAndReplaceCnUnitsNames(const XmlNodePtr &node, const std::string &oldName, const std::string &newName) { XmlNodePtr childNode = node->firstChild(); while (childNode != nullptr) { if (childNode->isMathmlElement("cn")) { std::string unitsName = childNode->attribute("units"); - auto foundNameIter = replaceMap.find(unitsName); - if (foundNameIter != replaceMap.end()) { - childNode->setAttribute("units", foundNameIter->second.c_str()); + if (unitsName == oldName) { + childNode->setAttribute("units", newName.c_str()); } } - findAndReplaceCnUnitsNames(childNode, replaceMap); + findAndReplaceCnUnitsNames(childNode, oldName, newName); childNode = childNode->next(); } } -void findAndReplaceComponentCnUnitsNames(const ComponentPtr &component, const StringStringMap &replaceMap) +void findAndReplaceComponentCnUnitsNames(const ComponentPtr &component, const std::string &oldName, const std::string &newName) { std::string mathContent = component->math(); if (mathContent.empty()) { @@ -554,7 +591,7 @@ void findAndReplaceComponentCnUnitsNames(const ComponentPtr &component, const St auto rootNode = doc->rootNode(); if (rootNode->isMathmlElement("math")) { auto originalMath = rootNode->convertToString(); - findAndReplaceCnUnitsNames(rootNode, replaceMap); + findAndReplaceCnUnitsNames(rootNode, oldName, newName); auto newMath = rootNode->convertToString(); newMathContent += newMath; if (newMath != originalMath) { @@ -568,12 +605,12 @@ void findAndReplaceComponentCnUnitsNames(const ComponentPtr &component, const St } } -void findAndReplaceComponentsCnUnitsNames(const ComponentPtr &component, const StringStringMap &replaceMap) +void findAndReplaceComponentsCnUnitsNames(const ComponentPtr &component, const std::string &oldName, const std::string &newName) { - findAndReplaceComponentCnUnitsNames(component, replaceMap); + findAndReplaceComponentCnUnitsNames(component, oldName, newName); for (size_t index = 0; index < component->componentCount(); ++index) { auto childComponent = component->component(index); - findAndReplaceComponentCnUnitsNames(childComponent, replaceMap); + findAndReplaceComponentCnUnitsNames(childComponent, oldName, newName); } } @@ -581,7 +618,7 @@ size_t getComponentIndexInComponentEntity(const ComponentEntityPtr &componentPar { size_t index = 0; bool found = false; - while ((index < componentParent->componentCount()) && !found) { + while (!found) { if (componentParent->component(index) == component) { found = true; } else { @@ -625,23 +662,21 @@ EquivalenceMap rebaseEquivalenceMap(const EquivalenceMap &map, const IndexStack for (const auto &entry : map) { auto key = entry.first; auto rebasedKey = rebaseIndexStack(key, originStack, destinationStack); - if (!rebasedKey.empty()) { - auto vector = entry.second; - std::vector rebasedVector; - for (auto stack : vector) { - // Temporarily remove the variable index whilst we rebase the component part of the stack. - size_t variableIndex = stack.back(); - stack.pop_back(); - auto rebasedTarget = rebaseIndexStack(stack, originStack, destinationStack); - if (!rebasedTarget.empty()) { - rebasedTarget.push_back(variableIndex); - rebasedVector.push_back(rebasedTarget); - } + auto vector = entry.second; + std::vector rebasedVector; + for (auto stack : vector) { + // Temporarily remove the variable index whilst we rebase the component part of the stack. + size_t variableIndex = stack.back(); + stack.pop_back(); + auto rebasedTarget = rebaseIndexStack(stack, originStack, destinationStack); + if (!rebasedTarget.empty()) { + rebasedTarget.push_back(variableIndex); + rebasedVector.push_back(rebasedTarget); } + } - if (!rebasedVector.empty()) { - rebasedMap.emplace(rebasedKey, rebasedVector); - } + if (!rebasedVector.empty()) { + rebasedMap.emplace(rebasedKey, rebasedVector); } } @@ -685,49 +720,51 @@ std::vector referencedUnits(const ModelPtr &model, const UnitsPtr &uni { std::vector requiredUnits; - std::string ref; - std::string pre; - std::string id; - double expMult; - double uExp; - for (size_t index = 0; index < units->unitCount(); ++index) { - units->unitAttributes(index, ref, pre, uExp, expMult, id); + const std::string ref = units->unitAttributeReference(index); if (!isStandardUnitName(ref)) { auto refUnits = model->units(ref); - if (refUnits != nullptr) { - auto requiredUnitsUnits = referencedUnits(model, refUnits); - requiredUnits.insert(requiredUnits.end(), requiredUnitsUnits.begin(), requiredUnitsUnits.end()); - requiredUnits.push_back(refUnits); - } + auto requiredUnitsUnits = referencedUnits(model, refUnits); + requiredUnits.insert(requiredUnits.end(), requiredUnitsUnits.begin(), requiredUnitsUnits.end()); + requiredUnits.push_back(refUnits); } } return requiredUnits; } -std::vector unitsUsed(const ModelPtr &model, const ComponentPtr &component) +std::vector unitsUsed(const ModelPtr &model, const ComponentConstPtr &component) { std::vector usedUnits; + + // Get all the units used by variables in this component. + for (size_t i = 0; i < component->variableCount(); ++i) { auto v = component->variable(i); auto u = v->units(); - if ((u != nullptr) && !isStandardUnitName(u->name())) { - auto requiredUnits = referencedUnits(model, u); + if ((u != nullptr) && !isStandardUnitName(u->name()) && (model != nullptr)) { + auto modelUnits = model->units(u->name()); + auto availableUnits = modelUnits ? modelUnits : u; + auto requiredUnits = referencedUnits(model, availableUnits); usedUnits.insert(usedUnits.end(), requiredUnits.begin(), requiredUnits.end()); + usedUnits.push_back(availableUnits); + } else if (model == nullptr) { usedUnits.push_back(u); } } + + // Get all the units used by cn elements in the components maths. + auto componentCnUnitsNames = findComponentCnUnitsNames(component); for (const auto &unitsName : componentCnUnitsNames) { auto u = model->units(unitsName); - if ((u != nullptr) && !isStandardUnitName(u->name())) { - auto requiredUnits = referencedUnits(model, u); - usedUnits.insert(usedUnits.end(), requiredUnits.begin(), requiredUnits.end()); - usedUnits.push_back(u); - } + auto requiredUnits = referencedUnits(model, u); + usedUnits.insert(usedUnits.end(), requiredUnits.begin(), requiredUnits.end()); + usedUnits.push_back(u); } + // Get all the units used by child components of this component. + for (size_t i = 0; i < component->componentCount(); ++i) { auto childComponent = component->component(i); auto childUsedUnits = unitsUsed(model, childComponent); @@ -839,12 +876,11 @@ void listComponentIds(const ComponentPtr &component, IdList &idList) idList.insert(id); } // Imports. - if (component->isImport()) { - if (component->importSource() != nullptr) { - id = component->importSource()->id(); - if (!id.empty()) { - idList.insert(id); - } + auto importSource = component->importSource(); + if (importSource != nullptr) { + id = importSource->id(); + if (!id.empty()) { + idList.insert(id); } } // Component reference in encapsulation structure. @@ -854,19 +890,20 @@ void listComponentIds(const ComponentPtr &component, IdList &idList) } // Variables. for (size_t v = 0; v < component->variableCount(); ++v) { - id = component->variable(v)->id(); + auto variable = component->variable(v); + id = variable->id(); if (!id.empty()) { idList.insert(id); } - for (size_t e = 0; e < component->variable(v)->equivalentVariableCount(); ++e) { + for (size_t e = 0; e < variable->equivalentVariableCount(); ++e) { // Equivalent variable mappings. - id = Variable::equivalenceMappingId(component->variable(v), component->variable(v)->equivalentVariable(e)); + id = Variable::equivalenceMappingId(variable, variable->equivalentVariable(e)); if (!id.empty()) { idList.insert(id); } // Connections. - id = Variable::equivalenceConnectionId(component->variable(v), component->variable(v)->equivalentVariable(e)); + id = Variable::equivalenceConnectionId(variable, variable->equivalentVariable(e)); if (!id.empty()) { idList.insert(id); } @@ -874,15 +911,16 @@ void listComponentIds(const ComponentPtr &component, IdList &idList) } // Resets. for (size_t r = 0; r < component->resetCount(); ++r) { - id = component->reset(r)->id(); + auto reset = component->reset(r); + id = reset->id(); if (!id.empty()) { idList.insert(id); } - id = component->reset(r)->testValueId(); + id = reset->testValueId(); if (!id.empty()) { idList.insert(id); } - id = component->reset(r)->resetValueId(); + id = reset->resetValueId(); if (!id.empty()) { idList.insert(id); } @@ -914,20 +952,19 @@ IdList listIds(const ModelPtr &model) idList.insert(id); } // Imports. - if (units->isImport()) { - if (units->importSource() != nullptr) { - id = units->importSource()->id(); - if (!id.empty()) { - idList.insert(id); - } + auto importSource = units->importSource(); + if (importSource != nullptr) { + id = importSource->id(); + if (!id.empty()) { + idList.insert(id); } } - for (size_t i = 0; i < model->units(u)->unitCount(); ++i) { + for (size_t i = 0; i < units->unitCount(); ++i) { std::string prefix; std::string reference; double exponent; double multiplier; - model->units(u)->unitAttributes(i, reference, prefix, exponent, multiplier, id); + units->unitAttributes(i, reference, prefix, exponent, multiplier, id); if (!id.empty()) { idList.insert(id); } @@ -1112,7 +1149,7 @@ bool equalEntities(const EntityPtr &owner, const std::vector &entitie } } } - if (entityFound && index < size_t(std::numeric_limits::max())) { + if (entityFound) { // We are going to assume here that nobody is going to add more // than 2,147,483,647 units to this component. And much more than // that in a 64-bit environment. @@ -1201,4 +1238,71 @@ std::string formDescriptionOfCyclicDependency(const History &history, const std: return msgHeader + msgHistory; } +size_t nonCommentChildCount(const XmlNodePtr &node) +{ + size_t res = 0; + auto childNode = node->firstChild(); + + while (childNode != nullptr) { + if (!childNode->isComment()) { + ++res; + } + + childNode = childNode->next(); + } + + return res; +} + +XmlNodePtr nonCommentChildNode(const XmlNodePtr &node, size_t index) +{ + // Note: we assume that there is always a non-comment child at the given + // index, hence we never test res for nullptr. + + auto res = node->firstChild(); + auto childNodeIndex = res->isComment() ? MAX_SIZE_T : 0; + + while (childNodeIndex != index) { + res = res->next(); + + if (!res->isComment()) { + ++childNodeIndex; + } + } + + return res; +} + +size_t mathmlChildCount(const XmlNodePtr &node) +{ + size_t res = 0; + auto childNode = node->firstChild(); + + while (childNode != nullptr) { + if (childNode->isMathmlElement()) { + ++res; + } + + childNode = childNode->next(); + } + + return res; +} + +XmlNodePtr mathmlChildNode(const XmlNodePtr &node, size_t index) +{ + auto res = node->firstChild(); + auto childNodeIndex = res->isMathmlElement() ? 0 : MAX_SIZE_T; + + while ((res != nullptr) && (childNodeIndex != index)) { + res = res->next(); + + if ((res != nullptr) && res->isMathmlElement()) { + ++childNodeIndex; + } + } + + return res; +} + } // namespace libcellml diff --git a/src/utilities.h b/src/utilities.h index 737adfe5a..74516691b 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -18,6 +18,7 @@ limitations under the License. #include #include +#include #include #include #include @@ -25,8 +26,8 @@ limitations under the License. #include "libcellml/types.h" #include "libcellml/variable.h" -#include "commonutils.h" #include "internaltypes.h" +#include "xmldoc.h" namespace libcellml { @@ -123,31 +124,6 @@ static const std::map standardMultiplierList = { {"watt", 0.0}, {"weber", 0.0}}; -/** - * Map connecting prefix strings to their exponent (eg: "kilo" -> 10^3). - */ -static const std::map standardPrefixList = { - {"yotta", 24}, - {"zetta", 21}, - {"exa", 18}, - {"peta", 15}, - {"tera", 12}, - {"giga", 9}, - {"mega", 6}, - {"kilo", 3}, - {"hecto", 2}, - {"deca", 1}, - {"deci", -1}, - {"centi", -2}, - {"milli", -3}, - {"micro", -6}, - {"nano", -9}, - {"pico", -12}, - {"femto", -15}, - {"atto", -18}, - {"zepto", -21}, - {"yocto", -24}}; - /** * List of MathML elements supported by CellML. */ @@ -170,41 +146,62 @@ static const std::map interfaceTypeToStrin {Variable::InterfaceType::PUBLIC, "public"}, {Variable::InterfaceType::PUBLIC_AND_PRIVATE, "public_and_private"}}; +/** + * @brief Check whether the @p in @c std::string can be converted to a basic @c double. + * + * Try to convert the @p in @c std::string to a basic @c double. Return true if the conversion succeeded and @c false + * if it didn't. + * + * If the @p in is not a CellML basic real the conversion will not succeed. + * + * @sa isCellMLBasicReal + * + * @param in The @c std::string value to convert to a basic @c double. + * + * @return @c true if @p in could be converted to a basic @c double and @c false otherwise. + */ +bool canConvertToBasicDouble(const std::string &in); + /** * @brief Convert the @p in @c std::string to a @c double. * * Convert the @p in @c std::string to a @c double. - * If given, sets the parameter @p ok to @c true if the conversion succeeded + * Returns @c true if the conversion succeeded * and @c false if it didn't. * * If the @p in is not a CellML real the conversion will not succeed. + * If the @p in is a number bigger than a double can represent the + * conversion will also not succeed. * * @sa isCellMLReal * * @param in The @c std::string value to convert to a @c double. - * @param ok Optional parameter returns @c true if the conversion was successful and @c false if it wasn't. + * @param out The value of the @p in as a doulbe if the conversion was successful, + * left unchanged if the conversion fails. * - * @return The double value of @p in. + * @return @c true if the conversion succeeded, @c false otherwise. */ -double convertToDouble(const std::string &in, bool *ok = nullptr); +bool convertToDouble(const std::string &in, double &out); /** * @brief Convert the @p in @c std::string to an @c int. * * Convert the @p in @c std::string to an @c int. - * If given, sets the parameter @p ok to @c true if the conversion succeeded + * Returns @c true if the conversion succeeded * and @c false if it didn't. * * If @p in is not a CellML integer the conversion will not succeed. + * If @p in is a number bigger than an int can represent the conversion + * will also not succeed. * * @sa isCellMLInteger * * @param in The @c std::string value to convert to an @c int. - * @param ok Optional parameter returns @c true if the conversion was successful and @c false if it wasn't. + * @param out The integer value of the @p in. * - * @return The integer value of @p in. + * @return @c true if the conversion was successful and @c false if it wasn't. */ -int convertToInt(const std::string &in, bool *ok = nullptr); +bool convertToInt(const std::string &in, int &out); /** * @brief Convert a units prefix to an int. @@ -294,6 +291,19 @@ bool isNonNegativeCellMLInteger(const std::string &candidate); */ bool isCellMLInteger(const std::string &candidate); +/** + * @brief Test if the @p candidate @c std::string is in the form of a CellML basic real. + * + * The candidate string must consist of european numeric characters. It may optionally + * have a basic Latin hyphen character '-' to indicate sign. It may also optionally + * use the basic Latin fullstop character '.' to indicate a decimal point. The candidate + * string must represent a number in base 10. + * + * @param candidate The string to test and determine whether or not it is a CellML basic real. + * @return @c true if the @p candidate is a CellML basic real and @c false otherwise. + */ +bool isCellMLBasicReal(const std::string &candidate); + /** * @brief Test if the @p candidate @c std::string is in the form of a CellML real. * @@ -796,8 +806,68 @@ void applyEquivalenceMapToModel(const EquivalenceMap &map, const ModelPtr &model NameList componentNames(const ModelPtr &model); NameList unitsNamesUsed(const ComponentPtr &component); EquivalenceMap rebaseEquivalenceMap(const EquivalenceMap &map, const IndexStack &originStack, const IndexStack &destinationStack); -std::vector unitsUsed(const ModelPtr &model, const ComponentPtr &component); +std::vector unitsUsed(const ModelPtr &model, const ComponentConstPtr &component); ComponentNameMap createComponentNamesMap(const ComponentPtr &component); -void findAndReplaceComponentsCnUnitsNames(const ComponentPtr &component, const StringStringMap &replaceMap); + +/** + * @brief Change all matching cn CellML units attributes names. + * + * Find all cn elements with a CellML units attribute with the value @p oldName + * and replace it with @p newName. + * + * The find and replace is done recursively through the component's component + * tree hierarchy. + * + * @param component The component to find and replace in. + * @param oldName The old name to match. + * @param newName The new name to replace the old name with. + */ +void findAndReplaceComponentsCnUnitsNames(const ComponentPtr &component, const std::string &oldName, const std::string &newName); + +/** + * @brief Return the number of non-comment children. + * + * Return the number of non-comment children for the given node. + * + * @param node The node for which we want the number of non-comment children. + * + * @return The number of non-comment children. + */ +size_t nonCommentChildCount(const XmlNodePtr &node); + +/** + * @brief Return the non-comment child at a given index. + * + * Return the non-comment child, at @p index, of the given node. + * + * @param node The node from which we want the non-comment child at @p index. + * @param index The index of the non-comment child. + * + * @return The non-comment child at @p index. + */ +XmlNodePtr nonCommentChildNode(const XmlNodePtr &node, size_t index); + +/** + * @brief Return the number of MathML children. + * + * Return the number of MathML children for the given node. + * + * @param node The node for which we want the number of MathML children. + * + * @return The number of MathML children. + */ +size_t mathmlChildCount(const XmlNodePtr &node); + +/** + * @brief Return the index'th MathML child for the given node. + * + * Return the @p index'th MathML child for the given node. + * + * @param node The node from which we want the @p index'th MathML child. + * @param index The index of the MathML child. + * + * @return The @p index'th MathML child. + */ +XmlNodePtr mathmlChildNode(const XmlNodePtr &node, size_t index); } // namespace libcellml diff --git a/src/validator.cpp b/src/validator.cpp index 9783e00b1..47c9dd65c 100644 --- a/src/validator.cpp +++ b/src/validator.cpp @@ -20,6 +20,7 @@ limitations under the License. #include #include #include +#include #include #include #include @@ -32,6 +33,7 @@ limitations under the License. #include "libcellml/variable.h" #include "anycellmlelement_p.h" +#include "commonutils.h" #include "issue_p.h" #include "logger_p.h" #include "namespaces.h" @@ -150,18 +152,42 @@ bool isNameStartChar(uint32_t startChar) || ((0x41U <= startChar) && (startChar <= 0x5AU)) || (startChar == 0x5FU) || ((0x61U <= startChar) && (startChar <= 0x7AU)) - || ((0xC0U <= startChar) && (startChar <= 0xD6U)) - || ((0xD8U <= startChar) && (startChar <= 0xF6U)) - || ((0xF8U <= startChar) && (startChar <= 0x2FFU)) - || ((0x370U <= startChar) && (startChar <= 0x37DU)) - || ((0x37FU <= startChar) && (startChar <= 0x1FFFU)) - || ((0x200CU <= startChar) && (startChar <= 0x200DU)) - || ((0x2070U <= startChar) && (startChar <= 0x218FU)) - || ((0x2C00U <= startChar) && (startChar <= 0x2FEFU)) - || ((0x3001U <= startChar) && (startChar <= 0xD7FFU)) - || ((0xF900U <= startChar) && (startChar <= 0xFDCFU)) - || ((0xFDF0U <= startChar) && (startChar <= 0xFFFDU)) - || ((0x10000U <= startChar) && (startChar <= 0xEFFFFU)); + || ((0xC380U <= startChar) && (startChar <= 0xC396U)) + || ((0xC398U <= startChar) && (startChar <= 0xC3B6U)) + || ((0xC3B8U <= startChar) && (startChar <= 0xCBBFU)) + || ((0xCDB0U <= startChar) && (startChar <= 0xCDBDU)) + || ((0xCDBFU <= startChar) && (startChar <= 0xE1BFBFU)) + || ((0xE2808CU <= startChar) && (startChar <= 0xE2808DU)) + || ((0xE281B0U <= startChar) && (startChar <= 0xE2868FU)) + || ((0xE2B080U <= startChar) && (startChar <= 0xE2BFAFU)) + || ((0xE38081U <= startChar) && (startChar <= 0xED9FBFU)) + || ((0xEFA480U <= startChar) && (startChar <= 0xEFB78FU)) + || ((0xEFB7B0U <= startChar) && (startChar <= 0xEFBFBDU)) + || ((0xF0908080U <= startChar) && (startChar <= 0xF3AFBFBFU)); +} + +/** + * @brief Test to determine if @p nameChar is a valid XML name character. + * + * An XML name character is defined here: https://www.w3.org/TR/xml11/#NT-NameChar. + * + * @param nameChar The character to test. + * + * @return True if the character is in the allowed Unicode ranges for an XML name character. + */ +bool isNameChar(uint32_t nameChar) +{ + if (isNameStartChar(nameChar)) { + return true; + } + + // "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] + return ((0x30U <= nameChar) && (nameChar <= 0x39U)) + || (nameChar == 0x2DU) + || (nameChar == 0x2EU) + || (nameChar == 0xC2B7U) + || ((0xCC80U <= nameChar) && (nameChar <= 0xCDAFU)) + || ((0xE280BFU <= nameChar) && (nameChar <= 0xE28180U)); } /** @@ -180,7 +206,7 @@ uint32_t convertTextToUint32(const std::string &text, size_t initialValue = 0) uint32_t value = 0; size_t index = 0; for (size_t j = initialValue; j < 4; ++j) { - auto tempValue = static_cast(text[index++]) << bitShifts[j]; + auto tempValue = static_cast(static_cast(text[index++])) << bitShifts[j]; value |= tempValue; } @@ -204,7 +230,7 @@ std::vector characterBreakdown(const std::string &text) for (size_t i = 0; i < text.length();) { size_t codePointLength = 1; uint32_t value = 0; - auto unsignedText = static_cast(text[i]); + auto unsignedText = static_cast((unsigned char)text[i]); if ((unsignedText & 0xf8U) == 0xf0U) { codePointLength = 4; breakdown.push_back(convertTextToUint32(text.substr(i, codePointLength))); @@ -226,29 +252,6 @@ std::vector characterBreakdown(const std::string &text) return breakdown; } -/** - * @brief Test to determine if @p nameChar is a valid XML name character. - * - * An XML name character is defined here: https://www.w3.org/TR/xml11/#NT-NameChar. - * - * @param nameChar The character to test. - * - * @return True if the character is in the allowed Unicode ranges for an XML name character. - */ -bool isNameChar(uint32_t nameChar) -{ - if (isNameStartChar(nameChar)) { - return true; - } - // "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] - return ((0x30U <= nameChar) && (nameChar <= 0x39U)) - || (nameChar == 0x2DU) - || (nameChar == 0x2EU) - || (nameChar == 0xB7U) - || ((0x0300U <= nameChar) && (nameChar <= 0x036FU)) - || ((0x203FU <= nameChar) && (nameChar <= 0x2040U)); -} - /** * @brief Test to determine if @p name is a valid XML name. * @@ -344,8 +347,9 @@ class Validator::ValidatorImpl: public LoggerImpl * @param units The units to validate. * @param history The history of units visited. * @param modelsVisited The list of visited models. + * @param sourceUrl The source URL of the @p units. */ - void validateUnits(const UnitsPtr &units, History &history, std::vector &modelsVisited); + void validateUnits(const UnitsPtr &units, History &history, std::vector &modelsVisited, const std::string &sourceUrl = ORIGIN_MODEL_REF); /** * @brief Validate the variable connections in the @p model using the CellML 2.0 Specification. @@ -492,6 +496,69 @@ class Validator::ValidatorImpl: public LoggerImpl */ void validateAndCleanMathCiCnNodes(XmlNodePtr &node, const ComponentPtr &component, const NameList &variableNames); + /** + * @brief Add a MathML-related issue. + * + * Add a MathML-related issue. + * + * @param description The description for the MathML-related issue. + * @param referenceRule The reference rule for the MathML-related issue. + * @param component The component where the MathML-related issue occurred. + */ + void addMathmlIssue(const std::string &description, + Issue::ReferenceRule referenceRule, + const ComponentPtr &component); + + bool hasOneMathmlSibling(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component); + bool hasAtLeastOneMathmlSibling(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component); + bool hasTwoMathmlSiblings(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component); + bool hasAtLeastTwoMathmlSiblings(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component); + size_t hasOneOrTwoMathmlSiblings(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component); + + bool isFirstMathmlSibling(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component); + bool isSecondMathmlSibling(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component); + + bool hasFirstMathmlSiblingWithName(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const std::string &name, + const ComponentPtr &component); + + bool hasOneMathmlChild(const XmlNodePtr &node, + const ComponentPtr &component); + bool hasAtLeastOneMathmlChild(const XmlNodePtr &node, + const ComponentPtr &component); + bool hasTwoMathmlChildren(const XmlNodePtr &node, + const ComponentPtr &component); + bool hasOneOrTwoMathmlChildren(const XmlNodePtr &node, + const ComponentPtr &component); + + /** + * @brief Traverse the node tree for invalid MathML elements' + * children/siblings. + * + * Traverse the XML node tree checking that all MathML elements have the + * correct number of children/siblings and that their type is as expected. + * + * @param node The node to check children and siblings. + * @param component The component the MathML belongs to. + */ + void validateMathMLElementsChildrenAndSiblings(const XmlNodePtr &node, + const ComponentPtr &component); + /** * @brief Check if the provided @p node is a supported MathML element. * @@ -617,7 +684,7 @@ class Validator::ValidatorImpl: public LoggerImpl bool checkForLocalCycles(const History &history, const HistoryEpochPtr &h) { return std::find_if(history.begin(), history.end(), - [=](const HistoryEpochPtr &i) -> bool { return i->mName == h->mName; }) + [=](const HistoryEpochPtr &i) -> bool { return (i->mName == h->mName) && (i->mSourceUrl == h->mSourceUrl); }) != history.end(); } @@ -925,11 +992,11 @@ std::set namesInCycle(NameList allNames) allNames.pop_back(); std::reverse(allNames.begin(), allNames.end()); std::set namesInCycle = {cycleStartName}; - for (const auto &name : allNames) { - if (name == cycleStartName) { - break; - } + std::string name = *allNames.begin(); + while (name != cycleStartName) { namesInCycle.emplace(name); + allNames.erase(allNames.begin()); + name = *allNames.begin(); } return namesInCycle; @@ -939,7 +1006,7 @@ bool Validator::ValidatorImpl::hasCycleAlreadyBeenReported(NameList names) const { std::set testNamesInCycle = namesInCycle(std::move(names)); bool found = false; - for (size_t i = 0; (i < mValidator->issueCount()) && !found; ++i) { + for (size_t i = 0; !found && (i < mValidator->issueCount()); ++i) { auto issue = mValidator->issue(i); if (issue->description().substr(0, 20) == "Cyclic units exist: ") { // Remove prefix to loop information. @@ -966,9 +1033,9 @@ bool Validator::ValidatorImpl::checkIssuesForDuplications(const std::string &des return false; } -void Validator::ValidatorImpl::validateUnits(const UnitsPtr &units, History &history, std::vector &modelsVisited) +void Validator::ValidatorImpl::validateUnits(const UnitsPtr &units, History &history, std::vector &modelsVisited, const std::string &sourceUrl) { - auto h = createHistoryEpoch(units, ORIGIN_MODEL_REF); + auto h = createHistoryEpoch(units, sourceUrl); if (checkForLocalCycles(history, h)) { history.push_back(h); std::string des; @@ -1039,7 +1106,7 @@ void Validator::ValidatorImpl::validateUnits(const UnitsPtr &units, History &his // Check if we already have another import from the same source with the same units_ref. // (This looks for matching entries at the same position in the source and ref vectors). - if ((unitsWithImportSource > 1) && !foundImportIssue) { + if (!foundImportIssue && (unitsWithImportSource > 1)) { auto description = "Model '" + model->name() + "' contains multiple imported units from '" + unitsImportUrl + "' with the same units_ref attribute '" + unitsRef + "'."; if (!checkIssuesForDuplications(description)) { auto issue = Issue::IssueImpl::create(); @@ -1070,7 +1137,7 @@ void Validator::ValidatorImpl::validateUnits(const UnitsPtr &units, History &his } else { modelsVisited.push_back(importSourceModel); history.push_back(h); - validateUnits(importedUnits, history, modelsVisited); + validateUnits(importedUnits, history, modelsVisited, importSource->url()); modelsVisited.pop_back(); } } else { @@ -1246,7 +1313,7 @@ void Validator::ValidatorImpl::validateVariable(const VariablePtr &variable, con addIssue(issue); } else if (!isStandardUnitName(unitsName)) { ModelPtr model = owningModel(component); - if ((model != nullptr) && !model->hasUnits(unitsName)) { + if (!model->hasUnits(unitsName)) { auto issue = Issue::IssueImpl::create(); issue->mPimpl->setDescription("Variable '" + variableName + "' in component '" + component->name() + "' has a units reference '" + unitsName + "' which is neither standard nor defined in the parent model."); issue->mPimpl->mItem->mPimpl->setVariable(variable); @@ -1448,7 +1515,6 @@ void Validator::ValidatorImpl::validateMath(const std::string &input, const Comp issue->mPimpl->setDescription("Math root node is of invalid type '" + node->name() + "' on component '" + component->name() + "'. A valid math root node should be of type 'math'."); issue->mPimpl->mItem->mPimpl->setComponent(component); issue->mPimpl->setReferenceRule(Issue::ReferenceRule::XML); - addIssue(issue); return; } @@ -1489,6 +1555,17 @@ void Validator::ValidatorImpl::validateMath(const std::string &input, const Comp addIssue(issue); } } + + // Make sure that the different MathML elements for the right number of + // children/siblings, type, etc. + + mathNode = mathmlDoc->rootNode(); + + auto childCount = mathmlChildCount(mathNode); + + for (size_t i = 0; i < childCount; ++i) { + validateMathMLElementsChildrenAndSiblings(mathmlChildNode(mathNode, i), component); + } } } @@ -1635,6 +1712,535 @@ void Validator::ValidatorImpl::validateMathMLElements(const XmlNodePtr &node, co } } +void Validator::ValidatorImpl::addMathmlIssue(const std::string &description, + Issue::ReferenceRule referenceRule, + const ComponentPtr &component) +{ + auto issue = Issue::IssueImpl::create(); + + issue->mPimpl->setDescription(description); + issue->mPimpl->mItem->mPimpl->setMath(component); + issue->mPimpl->setReferenceRule(referenceRule); + + addIssue(issue); +} + +bool Validator::ValidatorImpl::hasOneMathmlSibling(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component) +{ + if (mathmlChildCount(parentNode) != 2) { + addMathmlIssue("Math has a '" + node->name() + "' element without exactly one MathML sibling.", + Issue::ReferenceRule::MATH_MATHML, + component); + + return false; + } + + return true; +} + +bool Validator::ValidatorImpl::hasAtLeastOneMathmlSibling(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component) +{ + if (mathmlChildCount(parentNode) < 2) { + addMathmlIssue("Math has a '" + node->name() + "' element without at least one MathML sibling.", + Issue::ReferenceRule::MATH_MATHML, + component); + + return false; + } + + return true; +} + +bool Validator::ValidatorImpl::hasTwoMathmlSiblings(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component) +{ + if (mathmlChildCount(parentNode) != 3) { + addMathmlIssue("Math has a '" + node->name() + "' element without exactly two MathML siblings.", + Issue::ReferenceRule::MATH_MATHML, + component); + + return false; + } + + return true; +} + +bool Validator::ValidatorImpl::hasAtLeastTwoMathmlSiblings(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component) +{ + if (mathmlChildCount(parentNode) < 3) { + addMathmlIssue("Math has a '" + node->name() + "' element without at least two MathML siblings.", + Issue::ReferenceRule::MATH_MATHML, + component); + + return false; + } + + return true; +} + +size_t Validator::ValidatorImpl::hasOneOrTwoMathmlSiblings(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component) +{ + auto childCount = mathmlChildCount(parentNode); + + if ((childCount != 2) && (childCount != 3)) { + addMathmlIssue("Math has a '" + node->name() + "' element without exactly one or two MathML siblings.", + Issue::ReferenceRule::MATH_MATHML, + component); + + return 0; + } + + return childCount - 1; +} + +bool Validator::ValidatorImpl::isFirstMathmlSibling(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component) +{ + if (!mathmlChildNode(parentNode, 0)->equals(node)) { + addMathmlIssue("Math has a '" + node->name() + "' element which is not the first MathML sibling.", + Issue::ReferenceRule::MATH_MATHML, + component); + + return false; + } + + return true; +} + +bool Validator::ValidatorImpl::isSecondMathmlSibling(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const ComponentPtr &component) +{ + if (!mathmlChildNode(parentNode, 1)->equals(node)) { + addMathmlIssue("Math has a '" + node->name() + "' element which is not the second MathML sibling.", + Issue::ReferenceRule::MATH_MATHML, + component); + + return false; + } + + return true; +} + +bool Validator::ValidatorImpl::hasFirstMathmlSiblingWithName(const XmlNodePtr &parentNode, + const XmlNodePtr &node, + const std::string &name, + const ComponentPtr &component) +{ + auto childNode = mathmlChildNode(parentNode, 0); + + if (childNode->equals(node)) { + childNode = mathmlChildNode(parentNode, 1); + } + + if (childNode->name() != name) { + addMathmlIssue("Math has a '" + node->name() + "' element which first sibling is not a '" + name + "' element.", + Issue::ReferenceRule::MATH_MATHML, + component); + + return false; + } + + return true; +} + +bool Validator::ValidatorImpl::hasOneMathmlChild(const XmlNodePtr &node, + const ComponentPtr &component) +{ + if (mathmlChildCount(node) != 1) { + addMathmlIssue("Math has a '" + node->name() + "' element without exactly one MathML child.", + Issue::ReferenceRule::MATH_MATHML, + component); + + return false; + } + + return true; +} + +bool Validator::ValidatorImpl::hasAtLeastOneMathmlChild(const XmlNodePtr &node, + const ComponentPtr &component) +{ + if (mathmlChildCount(node) < 1) { + addMathmlIssue("Math has a '" + node->name() + "' element without at least one MathML child.", + Issue::ReferenceRule::MATH_MATHML, + component); + + return false; + } + + return true; +} + +bool Validator::ValidatorImpl::hasTwoMathmlChildren(const XmlNodePtr &node, + const ComponentPtr &component) +{ + if (mathmlChildCount(node) != 2) { + addMathmlIssue("Math has a '" + node->name() + "' element without exactly two MathML children.", + Issue::ReferenceRule::MATH_MATHML, + component); + + return false; + } + + return true; +} + +bool Validator::ValidatorImpl::hasOneOrTwoMathmlChildren(const XmlNodePtr &node, + const ComponentPtr &component) +{ + auto childCount = mathmlChildCount(node); + + if ((childCount != 1) && (childCount != 2)) { + addMathmlIssue("Math has a '" + node->name() + "' element without exactly one or two MathML children.", + Issue::ReferenceRule::MATH_MATHML, + component); + + return false; + } + + return true; +} + +void Validator::ValidatorImpl::validateMathMLElementsChildrenAndSiblings(const XmlNodePtr &node, + const ComponentPtr &component) +{ + // Check the current node against the MathML elements listed in + // supportedMathMLElements. + // Note: we don't have to do anything for 'true', 'false, 'exponentiale', + // 'pi', 'infinity', and 'notanumber' since they must be empty and if + // they are not then this will be caught by the DTD. + + // Basic content elements. + + if (node->isMathmlElement("apply")) { + if (hasAtLeastOneMathmlChild(node, component)) { + for (size_t i = 0, iMax = mathmlChildCount(node); i < iMax; ++i) { + validateMathMLElementsChildrenAndSiblings(mathmlChildNode(node, i), component); + } + } + + // Relational and logical operators. + + } else if (node->isMathmlElement("eq") + || node->isMathmlElement("neq") + || node->isMathmlElement("lt") + || node->isMathmlElement("leq") + || node->isMathmlElement("gt") + || node->isMathmlElement("geq")) { + auto parentNode = node->parent(); + + hasTwoMathmlSiblings(parentNode, node, component) + && isFirstMathmlSibling(parentNode, node, component); + } else if (node->isMathmlElement("and") + || node->isMathmlElement("or") + || node->isMathmlElement("xor")) { + auto parentNode = node->parent(); + + hasAtLeastTwoMathmlSiblings(parentNode, node, component) + && isFirstMathmlSibling(parentNode, node, component); + } else if (node->isMathmlElement("not")) { + auto parentNode = node->parent(); + + hasOneMathmlSibling(parentNode, node, component) + && isFirstMathmlSibling(parentNode, node, component); + + // Arithmetic operators. + + } else if (node->isMathmlElement("plus")) { + auto parentNode = node->parent(); + + hasAtLeastOneMathmlSibling(parentNode, node, component) + && isFirstMathmlSibling(parentNode, node, component); + } else if (node->isMathmlElement("minus")) { + auto parentNode = node->parent(); + + hasOneOrTwoMathmlSiblings(parentNode, node, component) + && isFirstMathmlSibling(parentNode, node, component); + } else if (node->isMathmlElement("times")) { + auto parentNode = node->parent(); + + hasAtLeastTwoMathmlSiblings(parentNode, node, component) + && isFirstMathmlSibling(parentNode, node, component); + } else if (node->isMathmlElement("divide")) { + auto parentNode = node->parent(); + + hasTwoMathmlSiblings(parentNode, node, component) + && isFirstMathmlSibling(parentNode, node, component); + } else if (node->isMathmlElement("power")) { + auto parentNode = node->parent(); + + hasTwoMathmlSiblings(parentNode, node, component) + && isFirstMathmlSibling(parentNode, node, component); + } else if (node->isMathmlElement("root")) { + // A 'root' element can have either one or two siblings, depending on + // whether a 'degree' element is specified, e.g. + // + // + // + // a + // + // + // and + // + // + // + // + // 3 + // + // a + // + + auto parentNode = node->parent(); + auto siblingCount = hasOneOrTwoMathmlSiblings(parentNode, node, component); + + if ((siblingCount != 0) + && isFirstMathmlSibling(parentNode, node, component)) { + (siblingCount == 2) + && hasFirstMathmlSiblingWithName(parentNode, node, "degree", component); + } + } else if (node->isMathmlElement("abs") + || node->isMathmlElement("exp") + || node->isMathmlElement("ln")) { + auto parentNode = node->parent(); + + hasOneMathmlSibling(parentNode, node, component) + && isFirstMathmlSibling(parentNode, node, component); + } else if (node->isMathmlElement("log")) { + // A 'log' element can have either one or two siblings, depending on + // whether a 'logbase' element is specified, e.g. + // + // + // + // a + // + // + // and + // + // + // + // + // 3 + // + // a + // + + auto parentNode = node->parent(); + auto siblingCount = hasOneOrTwoMathmlSiblings(parentNode, node, component); + + if ((siblingCount != 0) + && isFirstMathmlSibling(parentNode, node, component)) { + (siblingCount == 2) + && hasFirstMathmlSiblingWithName(parentNode, node, "logbase", component); + } + } else if (node->isMathmlElement("ceiling") + || node->isMathmlElement("floor")) { + auto parentNode = node->parent(); + + hasOneMathmlSibling(parentNode, node, component) + && isFirstMathmlSibling(parentNode, node, component); + } else if (node->isMathmlElement("min")) { + } else if (node->isMathmlElement("max")) { + } else if (node->isMathmlElement("rem")) { + // Calculus elements. + + } else if (node->isMathmlElement("diff")) { + auto parentNode = node->parent(); + + hasTwoMathmlSiblings(parentNode, node, component) + && isFirstMathmlSibling(parentNode, node, component) + && hasFirstMathmlSiblingWithName(parentNode, node, "bvar", component); + + // Trigonometric operators. + + } else if (node->isMathmlElement("sin") + || node->isMathmlElement("cos") + || node->isMathmlElement("tan") + || node->isMathmlElement("sec") + || node->isMathmlElement("csc") + || node->isMathmlElement("cot") + || node->isMathmlElement("sinh") + || node->isMathmlElement("cosh") + || node->isMathmlElement("tanh") + || node->isMathmlElement("sech") + || node->isMathmlElement("csch") + || node->isMathmlElement("coth") + || node->isMathmlElement("arcsin") + || node->isMathmlElement("arccos") + || node->isMathmlElement("arctan") + || node->isMathmlElement("arcsec") + || node->isMathmlElement("arccsc") + || node->isMathmlElement("arccot") + || node->isMathmlElement("arcsinh") + || node->isMathmlElement("arccosh") + || node->isMathmlElement("arctanh") + || node->isMathmlElement("arcsech") + || node->isMathmlElement("arccsch") + || node->isMathmlElement("arccoth")) { + auto parentNode = node->parent(); + + hasOneMathmlSibling(parentNode, node, component) + && isFirstMathmlSibling(parentNode, node, component); + + // Piecewise statement. + + } else if (node->isMathmlElement("piecewise")) { + for (size_t i = 0, iMax = mathmlChildCount(node); i < iMax; ++i) { + validateMathMLElementsChildrenAndSiblings(mathmlChildNode(node, i), component); + } + } else if (node->isMathmlElement("piece")) { + if (hasTwoMathmlChildren(node, component)) { + validateMathMLElementsChildrenAndSiblings(mathmlChildNode(node, 0), component); + validateMathMLElementsChildrenAndSiblings(mathmlChildNode(node, 1), component); + } + } else if (node->isMathmlElement("otherwise")) { + if (hasOneMathmlChild(node, component)) { + validateMathMLElementsChildrenAndSiblings(mathmlChildNode(node, 0), component); + } + + // Token elements. + + } else if (node->isMathmlElement("ci")) { + auto ok = (nonCommentChildCount(node) != 1) ? false : !nonCommentChildNode(node, 0)->convertToStrippedString().empty(); + + if (!ok) { + addMathmlIssue("Math has a 'ci' element with no identifier as a child.", + Issue::ReferenceRule::MATH_CI_VARIABLE_REF, + component); + } + } else if (node->isMathmlElement("cn")) { + auto cnBase = node->attribute("base"); + + if (!cnBase.empty() && (cnBase != "10")) { + addMathmlIssue("Math has a 'cn' element which is not in base 10.", + Issue::ReferenceRule::MATH_CN_BASE10, + component); + + return; + } + + auto cnType = node->attribute("type"); + + if (cnType.empty() || (cnType == "real")) { + auto ok = (nonCommentChildCount(node) != 1) ? false : nonCommentChildNode(node, 0)->isBasicReal(); + + if (!ok) { + addMathmlIssue("Math has a 'cn' element of 'real' type with no valid text node (representing a basic number) as a child.", + Issue::ReferenceRule::MATH_CN_FORMAT, + component); + } + } else if (cnType == "e-notation") { + auto ok = false; + + if (nonCommentChildCount(node) == 3) { + ok = nonCommentChildNode(node, 0)->isBasicReal() + && nonCommentChildNode(node, 1)->isMathmlElement("sep") + && nonCommentChildNode(node, 2)->isInteger(); + } + + if (!ok) { + addMathmlIssue("Math has a 'cn' element of 'e-notation' type with no valid text node (representing a basic number), no 'sep' element, and/or no valid text node (representing an integer) as children.", + Issue::ReferenceRule::MATH_CN_FORMAT, + component); + } + } else { + addMathmlIssue("Math has a 'cn' element which is not of 'real' or 'e-notation' type.", + Issue::ReferenceRule::MATH_CN_FORMAT, + component); + } + + // Qualifier elements. + + } else if (node->isMathmlElement("degree")) { + // A 'degree' element can be used either with a 'root' element or within + // a 'bvar' element, e.g. + // + // + // + // + // t + // + // 2 + // + // + // x + // + // + // and + // + // + // + // + // 3 + // + // a + // + + auto parentNode = node->parent(); + auto siblingCount = hasOneOrTwoMathmlSiblings(parentNode, node, component); + + if (siblingCount == 1) { + // Used with a 'degree' element. + + isSecondMathmlSibling(parentNode, node, component) + && hasOneMathmlChild(node, component); + } else if (siblingCount == 2) { + // Used with a 'root' element. + + hasFirstMathmlSiblingWithName(parentNode, node, "root", component) + && isSecondMathmlSibling(parentNode, node, component) + && hasOneMathmlChild(node, component); + } + } else if (node->isMathmlElement("logbase")) { + auto parentNode = node->parent(); + + hasTwoMathmlSiblings(parentNode, node, component) + && hasFirstMathmlSiblingWithName(parentNode, node, "log", component) + && isSecondMathmlSibling(parentNode, node, component) + && hasOneMathmlChild(node, component); + } else if (node->isMathmlElement("bvar")) { + // A 'bvar' element can have one or two children, e.g. + // + // + // + // + // t + // + // x + // + // + // and + // + // + // + // + // t + // + // 2 + // + // + // x + // + + auto parentNode = node->parent(); + + hasTwoMathmlSiblings(parentNode, node, component) + && hasFirstMathmlSiblingWithName(parentNode, node, "diff", component) + && isSecondMathmlSibling(parentNode, node, component) + && hasOneOrTwoMathmlChildren(node, component); + } +} + /** * @brief Test to see if the given variables are reachable from their parent components. * @@ -1662,8 +2268,7 @@ bool reachableEquivalence(const VariablePtr &variable1, const VariablePtr &varia bool interfaceTypeIsCompatible(Variable::InterfaceType interfaceTypeMinimumRequired, const std::string &interfaceTypeCompatibleWith) { - std::string interfaceTypeMinimumRequiredString = interfaceTypeToString.find(interfaceTypeMinimumRequired)->second; - return interfaceTypeCompatibleWith.find(interfaceTypeMinimumRequiredString) != std::string::npos; + return interfaceTypeCompatibleWith.find(interfaceTypeToString.at(interfaceTypeMinimumRequired)) != std::string::npos; } void Validator::ValidatorImpl::validateVariableInterface(const VariablePtr &variable, VariableMap &alreadyReported) @@ -1756,15 +2361,13 @@ void Validator::ValidatorImpl::validateEquivalenceStructure(const VariablePtr &v { for (size_t index = 0; index < variable->equivalentVariableCount(); ++index) { auto equivalentVariable = variable->equivalentVariable(index); - if (equivalentVariable->hasEquivalentVariable(variable)) { - auto component = owningComponent(equivalentVariable); - if (component == nullptr) { - IssuePtr err = Issue::IssueImpl::create(); - err->mPimpl->setDescription("Variable '" + equivalentVariable->name() + "' is an equivalent variable to '" + variable->name() + "' but '" + equivalentVariable->name() + "' has no parent component."); - err->mPimpl->mItem->mPimpl->setMapVariables(variable, equivalentVariable); - err->mPimpl->setReferenceRule(Issue::ReferenceRule::MAP_VARIABLES_VARIABLE1); - addIssue(err); - } + auto component = owningComponent(equivalentVariable); + if (component == nullptr) { + IssuePtr err = Issue::IssueImpl::create(); + err->mPimpl->setDescription("Variable '" + equivalentVariable->name() + "' is an equivalent variable to '" + variable->name() + "' but '" + equivalentVariable->name() + "' has no parent component."); + err->mPimpl->mItem->mPimpl->setMapVariables(variable, equivalentVariable); + err->mPimpl->setReferenceRule(Issue::ReferenceRule::MAP_VARIABLES_VARIABLE1); + addIssue(err); } } } @@ -1809,7 +2412,7 @@ IssuePtr Validator::ValidatorImpl::makeIssueIllegalIdentifier(const std::string } else if (referenceRule == Issue::ReferenceRule::DATA_REPR_IDENTIFIER_BEGIN_EURO_NUM) { // Does not start with numeric character. issue->mPimpl->setDescription("CellML identifiers must not begin with a European numeric character [0-9]."); - } else if (referenceRule == Issue::ReferenceRule::DATA_REPR_IDENTIFIER_LATIN_ALPHANUM) { + } else { /* referenceRule == Issue::ReferenceRule::DATA_REPR_IDENTIFIER_LATIN_ALPHANUM */ // Basic Latin alphanumeric characters and underscores. issue->mPimpl->setDescription("CellML identifiers must not contain any characters other than [a-zA-Z0-9_]."); } @@ -1829,43 +2432,41 @@ bool unitsAreEquivalent(const ModelPtr &model, unitMap.emplace(baseUnits, 0.0); } - std::string ref; hints = ""; multiplier = 0.0; - if (model->hasUnits(v1->units()->name())) { + std::string v1UnitsName = v1->units()->name(); + if (model->hasUnits(v1UnitsName)) { UnitsPtr u1 = Units::create(); - u1 = model->units(v1->units()->name()); + u1 = model->units(v1UnitsName); updateBaseUnitCount(model, unitMap, multiplier, u1->name(), 1, 0, 1); - } else if (unitMap.find(v1->units()->name()) != unitMap.end()) { - ref = v1->units()->name(); - unitMap.at(ref) += 1.0; - } else if (isStandardUnitName(v1->units()->name())) { - updateBaseUnitCount(model, unitMap, multiplier, v1->units()->name(), 1, 0, 1); + } else if (unitMap.find(v1UnitsName) != unitMap.end()) { + unitMap.at(v1UnitsName) += 1.0; + } else if (isStandardUnitName(v1UnitsName)) { + updateBaseUnitCount(model, unitMap, multiplier, v1UnitsName, 1, 0, 1); } - if (model->hasUnits(v2->units()->name())) { + std::string v2UnitsName = v2->units()->name(); + if (model->hasUnits(v2UnitsName)) { UnitsPtr u2 = Units::create(); - u2 = model->units(v2->units()->name()); + u2 = model->units(v2UnitsName); updateBaseUnitCount(model, unitMap, multiplier, u2->name(), 1, 0, -1); - } else if (unitMap.find(v2->units()->name()) != unitMap.end()) { - ref = v2->units()->name(); - unitMap.at(v2->units()->name()) -= 1.0; - } else if (isStandardUnitName(v2->units()->name())) { - updateBaseUnitCount(model, unitMap, multiplier, v2->units()->name(), 1, 0, -1); + } else if (unitMap.find(v2UnitsName) != unitMap.end()) { + unitMap.at(v2UnitsName) -= 1.0; + } else if (isStandardUnitName(v2UnitsName)) { + updateBaseUnitCount(model, unitMap, multiplier, v2UnitsName, 1, 0, -1); } // Remove "dimensionless" from base unit testing. unitMap.erase("dimensionless"); + static const std::regex fullStopAtEndRegex(".$"); bool status = true; for (const auto &basePair : unitMap) { if (basePair.second != 0.0) { std::string num = std::to_string(basePair.second); num.erase(num.find_last_not_of('0') + 1, num.length()); - if (num.back() == '.') { - num.pop_back(); - } + num = std::regex_replace(num, fullStopAtEndRegex, ""); hints += basePair.first + "^" + num + ", "; status = false; } @@ -1877,9 +2478,7 @@ bool unitsAreEquivalent(const ModelPtr &model, std::string num = std::to_string(multiplier); num.erase(num.find_last_not_of('0') + 1, num.length()); - if (num.back() == '.') { - num.pop_back(); - } + num = std::regex_replace(num, fullStopAtEndRegex, ""); hints += "multiplication factor of 10^" + num + ", "; } @@ -1951,7 +2550,7 @@ void Validator::ValidatorImpl::checkUniqueIds(const ModelPtr &model) desc += ";\n"; } else if (i == iMax - 1) { desc += "; and\n"; - } else if (i == iMax) { + } else { /* i == iMax */ desc += ".\n"; } } @@ -2010,7 +2609,7 @@ IdMap Validator::ValidatorImpl::buildModelIdMap(const ModelPtr &model) addIdMapItem(id, info, idMap); } } - if (units->isImport() && units->importSource() != nullptr && !units->importSource()->id().empty()) { + if ((units->importSource() != nullptr) && !units->importSource()->id().empty()) { info = " - import source for units '" + units->name() + "'"; addIdMapItem(units->importSource()->id(), info, idMap); } @@ -2141,7 +2740,7 @@ void Validator::ValidatorImpl::buildComponentIdMap(const ComponentPtr &component buildMathIdMap(info, idMap, component->math()); // Imports. - if (component->isImport() && (component->importSource() != nullptr) && !component->importSource()->id().empty()) { + if ((component->importSource() != nullptr) && !component->importSource()->id().empty()) { info = " - import source for component '" + component->name() + "'"; addIdMapItem(component->importSource()->id(), info, idMap); } diff --git a/src/variable.cpp b/src/variable.cpp index f5b3053a3..66c1dcee8 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -123,10 +123,13 @@ bool Variable::addEquivalence(const VariablePtr &variable1, const VariablePtr &v bool Variable::removeEquivalence(const VariablePtr &variable1, const VariablePtr &variable2) { - bool equivalence_1 = variable1 != nullptr ? variable1->pFunc()->unsetEquivalentTo(variable2) : false; - bool equivalence_2 = variable2 != nullptr ? variable2->pFunc()->unsetEquivalentTo(variable1) : false; + if ((variable1 != nullptr) && (variable2 != nullptr)) { + if (variable1->pFunc()->unsetEquivalentTo(variable2)) { + return variable2->pFunc()->unsetEquivalentTo(variable1); + } + } - return equivalence_1 && equivalence_2; + return false; } void Variable::removeAllEquivalences() @@ -357,9 +360,7 @@ void Variable::setInterfaceType(const std::string &interfaceType) void Variable::setInterfaceType(Variable::InterfaceType interfaceType) { - auto search = interfaceTypeToString.find(interfaceType); - const std::string interfaceTypeString = search->second; - setInterfaceType(interfaceTypeString); + setInterfaceType(interfaceTypeToString.at(interfaceType)); } std::string Variable::interfaceType() const @@ -377,14 +378,14 @@ bool Variable::hasInterfaceType(InterfaceType interfaceType) const if (interfaceType == Variable::InterfaceType::NONE && pFunc()->mInterfaceType.empty()) { return true; } - return pFunc()->mInterfaceType == interfaceTypeToString.find(interfaceType)->second; + return pFunc()->mInterfaceType == interfaceTypeToString.at(interfaceType); } bool Variable::permitsInterfaceType(InterfaceType interfaceType) const { - std::string testString = interfaceTypeToString.find(interfaceType)->second; + std::string testString = interfaceTypeToString.at(interfaceType); - if ((testString == "none") || testString.empty()) { + if (testString == "none") { return true; } if (pFunc()->mInterfaceType == "public_and_private") { @@ -395,23 +396,27 @@ bool Variable::permitsInterfaceType(InterfaceType interfaceType) const void Variable::setEquivalenceMappingId(const VariablePtr &variable1, const VariablePtr &variable2, const std::string &mappingId) { - if (variable1->hasEquivalentVariable(variable2, true) && variable2->hasEquivalentVariable(variable1, true)) { - variable1->pFunc()->setEquivalentMappingId(variable2, mappingId); - variable2->pFunc()->setEquivalentMappingId(variable1, mappingId); + if ((variable1 != nullptr) && (variable2 != nullptr)) { + if (variable1->hasEquivalentVariable(variable2, true)) { + variable1->pFunc()->setEquivalentMappingId(variable2, mappingId); + variable2->pFunc()->setEquivalentMappingId(variable1, mappingId); + } } } void Variable::setEquivalenceConnectionId(const VariablePtr &variable1, const VariablePtr &variable2, const std::string &connectionId) { - if (variable1->hasEquivalentVariable(variable2, true) && variable2->hasEquivalentVariable(variable1, true)) { - auto map = createConnectionMap(variable1, variable2); - for (auto &it : map) { - it.first->pFunc()->setEquivalentConnectionId(it.second, connectionId); - it.second->pFunc()->setEquivalentConnectionId(it.first, connectionId); - } - if (map.empty()) { - variable1->pFunc()->setEquivalentConnectionId(variable2, connectionId); - variable2->pFunc()->setEquivalentConnectionId(variable1, connectionId); + if ((variable1 != nullptr) && (variable2 != nullptr)) { + if (variable1->hasEquivalentVariable(variable2, true)) { + auto map = createConnectionMap(variable1, variable2); + for (auto &it : map) { + it.first->pFunc()->setEquivalentConnectionId(it.second, connectionId); + it.second->pFunc()->setEquivalentConnectionId(it.first, connectionId); + } + if (map.empty()) { + variable1->pFunc()->setEquivalentConnectionId(variable2, connectionId); + variable2->pFunc()->setEquivalentConnectionId(variable1, connectionId); + } } } } @@ -419,8 +424,10 @@ void Variable::setEquivalenceConnectionId(const VariablePtr &variable1, const Va std::string Variable::equivalenceMappingId(const VariablePtr &variable1, const VariablePtr &variable2) { std::string id; - if (variable1->hasEquivalentVariable(variable2, true) && variable2->hasEquivalentVariable(variable1, true)) { - id = variable1->pFunc()->equivalentMappingId(variable2); + if ((variable1 != nullptr) && (variable2 != nullptr)) { + if (variable1->hasEquivalentVariable(variable2, true)) { + id = variable1->pFunc()->equivalentMappingId(variable2); + } } return id; } @@ -428,13 +435,15 @@ std::string Variable::equivalenceMappingId(const VariablePtr &variable1, const V std::string Variable::equivalenceConnectionId(const VariablePtr &variable1, const VariablePtr &variable2) { std::string id; - if (variable1->hasEquivalentVariable(variable2, true) && variable2->hasEquivalentVariable(variable1, true)) { - auto map = createConnectionMap(variable1, variable2); - for (auto &it : map) { - id = it.first->pFunc()->equivalentConnectionId(it.second); - } - if (id.empty()) { - id = variable1->pFunc()->equivalentConnectionId(variable2); + if ((variable1 != nullptr) && (variable2 != nullptr)) { + if (variable1->hasEquivalentVariable(variable2, true)) { + auto map = createConnectionMap(variable1, variable2); + for (auto &it : map) { + id = it.first->pFunc()->equivalentConnectionId(it.second); + } + if (id.empty()) { + id = variable1->pFunc()->equivalentConnectionId(variable2); + } } } return id; @@ -442,17 +451,21 @@ std::string Variable::equivalenceConnectionId(const VariablePtr &variable1, cons void Variable::removeEquivalenceConnectionId(const VariablePtr &variable1, const VariablePtr &variable2) { - if (variable1->hasEquivalentVariable(variable2, true) && variable2->hasEquivalentVariable(variable1, true)) { - variable1->pFunc()->setEquivalentConnectionId(variable2, ""); - variable2->pFunc()->setEquivalentConnectionId(variable1, ""); + if ((variable1 != nullptr) && (variable2 != nullptr)) { + if (variable1->hasEquivalentVariable(variable2, true)) { + variable1->pFunc()->setEquivalentConnectionId(variable2, ""); + variable2->pFunc()->setEquivalentConnectionId(variable1, ""); + } } } void Variable::removeEquivalenceMappingId(const VariablePtr &variable1, const VariablePtr &variable2) { - if (variable1->hasEquivalentVariable(variable2, true) && variable2->hasEquivalentVariable(variable1, true)) { - variable1->pFunc()->setEquivalentMappingId(variable2, ""); - variable2->pFunc()->setEquivalentMappingId(variable1, ""); + if ((variable1 != nullptr) && (variable2 != nullptr)) { + if (variable1->hasEquivalentVariable(variable2, true)) { + variable1->pFunc()->setEquivalentMappingId(variable2, ""); + variable2->pFunc()->setEquivalentMappingId(variable1, ""); + } } } diff --git a/src/xmlattribute.cpp b/src/xmlattribute.cpp index 65c2cfa4a..dd5eeb2f4 100644 --- a/src/xmlattribute.cpp +++ b/src/xmlattribute.cpp @@ -61,7 +61,7 @@ std::string XmlAttribute::namespaceUri() const std::string XmlAttribute::namespacePrefix() const { - if (mPimpl->mXmlAttributePtr->ns == nullptr || mPimpl->mXmlAttributePtr->ns->prefix == nullptr) { + if (mPimpl->mXmlAttributePtr->ns == nullptr) { return {}; } return reinterpret_cast(mPimpl->mXmlAttributePtr->ns->prefix); @@ -91,11 +91,9 @@ std::string XmlAttribute::name() const std::string XmlAttribute::value() const { std::string valueString; - if ((mPimpl->mXmlAttributePtr->name != nullptr) && (mPimpl->mXmlAttributePtr->parent != nullptr)) { - xmlChar *value = xmlGetProp(mPimpl->mXmlAttributePtr->parent, mPimpl->mXmlAttributePtr->name); - valueString = std::string(reinterpret_cast(value)); - xmlFree(value); - } + xmlChar *value = xmlGetProp(mPimpl->mXmlAttributePtr->parent, mPimpl->mXmlAttributePtr->name); + valueString = std::string(reinterpret_cast(value)); + xmlFree(value); return valueString; } diff --git a/src/xmlattribute.h b/src/xmlattribute.h index cb1f8f82b..bd8de31e7 100644 --- a/src/xmlattribute.h +++ b/src/xmlattribute.h @@ -102,7 +102,7 @@ class XmlAttribute * * Checks whether this XmlAttribute has the argument attribute type name in * the CellML 2.0 namespace. - * Returns @ true if so, and @c false otherwise. + * Returns @c true if so, and @c false otherwise. * * @param name The @c char attribute type name to check for. * diff --git a/src/xmldoc.cpp b/src/xmldoc.cpp index f4cce427b..450fa256a 100644 --- a/src/xmldoc.cpp +++ b/src/xmldoc.cpp @@ -19,6 +19,7 @@ limitations under the License. #include #include #include +#include #include #include #include @@ -26,7 +27,6 @@ limitations under the License. #include #include "internaltypes.h" -#include "libcellmlconfig_p.h" #include "mathmldtd.h" #include "xmlnode.h" @@ -44,11 +44,9 @@ namespace libcellml { */ void structuredErrorCallback(void *userData, xmlErrorPtr error) { - std::string errorString = std::string(error->message); + static const std::regex newLineRegex("\\n"); // Swap libxml2 carriage return for a period. - if (errorString.substr(errorString.length() - 1) == "\n") { - errorString.replace(errorString.end() - 1, errorString.end(), "."); - } + std::string errorString = std::regex_replace(error->message, newLineRegex, "."); auto context = reinterpret_cast(userData); auto doc = reinterpret_cast(context->_private); doc->addXmlError(errorString); @@ -97,7 +95,7 @@ void XmlDoc::parse(const std::string &input) std::string decompressMathMLDTD() { std::vector mathmlDTD; - UNCOMPRESS_SIZE_TYPE sizeMathmlDTDUncompressedResize = MATHML_DTD_LEN; + uLong sizeMathmlDTDUncompressedResize = MATHML_DTD_LEN; mathmlDTD.resize(sizeMathmlDTDUncompressedResize); const unsigned char *a = compressedMathMLDTD(); diff --git a/src/xmlnode.cpp b/src/xmlnode.cpp index b6fac315c..93a273ac0 100644 --- a/src/xmlnode.cpp +++ b/src/xmlnode.cpp @@ -21,6 +21,7 @@ limitations under the License. #include #include "namespaces.h" +#include "utilities.h" #include "xmlattribute.h" namespace libcellml { @@ -124,10 +125,8 @@ bool XmlNode::hasNamespaceDefinition(const std::string &uri) if (mPimpl->mXmlNodePtr->nsDef != nullptr) { auto next = mPimpl->mXmlNodePtr->nsDef; while (next != nullptr) { - std::string href; - if (next->href != nullptr) { - href = std::string(reinterpret_cast(next->href)); - } + // If you have a namespace, the href cannot be empty. + std::string href = std::string(reinterpret_cast(next->href)); if (href == uri) { return true; } @@ -147,10 +146,8 @@ XmlNamespaceMap XmlNode::definedNamespaces() const if (next->prefix != nullptr) { prefix = std::string(reinterpret_cast(next->prefix)); } - std::string href; - if (next->href != nullptr) { - href = std::string(reinterpret_cast(next->href)); - } + // If you have a namespace, the href cannot be empty. + std::string href = std::string(reinterpret_cast(next->href)); namespaceMap.emplace(prefix, href); next = next->next; } @@ -209,6 +206,17 @@ bool XmlNode::isText() const return mPimpl->mXmlNodePtr->type == XML_TEXT_NODE; } +bool XmlNode::isBasicReal() const +{ + return canConvertToBasicDouble(convertToStrippedString()); +} + +bool XmlNode::isInteger() const +{ + int dummyInt; + return convertToInt(convertToStrippedString(), dummyInt); +} + bool XmlNode::isComment() const { return mPimpl->mXmlNodePtr->type == XML_COMMENT_NODE; @@ -221,12 +229,8 @@ std::string XmlNode::name() const bool XmlNode::hasAttribute(const char *attributeName) const { - bool found = false; xmlAttrPtr attribute = xmlHasProp(mPimpl->mXmlNodePtr, reinterpret_cast(attributeName)); - if (attribute != nullptr) { - found = true; - } - return found; + return attribute != nullptr; } xmlNsPtr getAttributeNamespace(const xmlNodePtr &node, const char *attributeName) @@ -264,6 +268,11 @@ XmlAttributePtr XmlNode::firstAttribute() const return attributeHandle; } +bool XmlNode::equals(const XmlNodePtr &node) const +{ + return mPimpl->mXmlNodePtr == node->mPimpl->mXmlNodePtr; +} + XmlNodePtr XmlNode::firstChild() const { xmlNodePtr child = mPimpl->mXmlNodePtr->children; @@ -272,7 +281,7 @@ XmlNodePtr XmlNode::firstChild() const childHandle = std::make_shared(); childHandle->setXmlNode(child); bool textNode = childHandle->isText(); - if (!textNode || (textNode && !childHandle->convertToStrippedString().empty())) { + if (!textNode || !childHandle->convertToStrippedString().empty()) { break; } child = child->next; @@ -294,23 +303,17 @@ XmlNodePtr XmlNode::next() const XmlNodePtr XmlNode::parent() const { xmlNodePtr parent = mPimpl->mXmlNodePtr->parent; - XmlNodePtr parentHandle = nullptr; - if (parent != nullptr) { - parentHandle = std::make_shared(); - parentHandle->setXmlNode(parent); - } + XmlNodePtr parentHandle = std::make_shared(); + parentHandle->setXmlNode(parent); return parentHandle; } std::string XmlNode::convertToString() const { - std::string contentString; xmlKeepBlanksDefault(1); xmlBufferPtr buffer = xmlBufferCreate(); - int len = xmlNodeDump(buffer, mPimpl->mXmlNodePtr->doc, mPimpl->mXmlNodePtr, 0, 0); - if (len > 0) { - contentString = std::string(reinterpret_cast(buffer->content)); - } + xmlNodeDump(buffer, mPimpl->mXmlNodePtr->doc, mPimpl->mXmlNodePtr, 0, 0); + std::string contentString = std::string(reinterpret_cast(buffer->content)); xmlBufferFree(buffer); return contentString; } diff --git a/src/xmlnode.h b/src/xmlnode.h index 00ae9c942..1cfcae3f7 100644 --- a/src/xmlnode.h +++ b/src/xmlnode.h @@ -240,17 +240,39 @@ class XmlNode * @brief Check if this @c XmlNode is a text node. * * Checks whether this @c XmlNode is a text node. - * Returns @ true if so, and @c false otherwise. + * Returns @c true if so, and @c false otherwise. * * @return @c true if this @c XmlNode is a text node and @c false otherwise. */ bool isText() const; + /** + * @brief Check if this @c XmlNode is a text node representing a basic real number. + * + * Checks whether this @c XmlNode is a text node representing a basic real number. + * Returns @c true if so, and @c false otherwise. + * + * @return @c true if this @c XmlNode is a text node representing a basic real number + * and @c false otherwise. + */ + bool isBasicReal() const; + + /** + * @brief Check if this @c XmlNode is a text node representing an integer. + * + * Checks whether this @c XmlNode is a text node representing an integer. + * Returns @c true if so, and @c false otherwise. + * + * @return @c true if this @c XmlNode is a text node representing an integer + * and @c false otherwise. + */ + bool isInteger() const; + /** * @brief Check if this @c XmlNode is a comment node. * * Checks whether this @c XmlNode is a comment node. - * Returns @ true if so, and @c false otherwise. + * Returns @c true if so, and @c false otherwise. * * @return @c true if this @c XmlNode is a comment node and @c false * otherwise. @@ -270,7 +292,7 @@ class XmlNode * @brief Check if this @c XmlNode has the specified attribute. * * Checks whether this @c XmlNode has an attribute of the type - * specified by the argument @p attributeName. Returns @ true + * specified by the argument @p attributeName. Returns @c true * if so, and @c false otherwise. * * @param attributeName The @c char attribute type to check for. @@ -293,6 +315,16 @@ class XmlNode */ std::string attribute(const char *attributeName) const; + /** + * @brief Set the attribute of the given name to the given value. + * + * Set the attribute of the given @p attributeName to the given @p attributeValue. + * The attribute name must already exist. + * If the attribute name does not already exist the attibute value will not be modified. + * + * @param attributeName The @c char attribute type. + * @param attributeValue The @c char value of the attribute to set. + */ void setAttribute(const char *attributeName, const char *attributeValue); /** @@ -306,6 +338,18 @@ class XmlNode */ XmlAttributePtr firstAttribute() const; + /** + * @brief Test if this @c XmlNode is the given node. + * + * Test if this @c XmlNode is the given node. If it is true is returned, + * otherwise false is. + * + * @param node The @c XmlNode to test against. + * + * @return true if this @c XmlNode is the given node, false otherwise. + */ + bool equals(const XmlNodePtr &node) const; + /** * @brief Get the first child for this @c XmlNode. * diff --git a/src/xmlutils.cpp b/src/xmlutils.cpp index 96d2785be..086a4d716 100644 --- a/src/xmlutils.cpp +++ b/src/xmlutils.cpp @@ -106,7 +106,7 @@ std::vector attributesWithCellml1XNamespace(const XmlNodePtr &n return attributes; } -void removeCellml1XNamespaces(const XmlNodePtr &node) +void removeCellml1XNamespaces(const XmlNodePtr &node, bool childrenOnly) { auto tempNode = node; while (tempNode != nullptr) { @@ -122,7 +122,11 @@ void removeCellml1XNamespaces(const XmlNodePtr &node) removeCellml1XNamespaces(tempNode->firstChild()); - tempNode = tempNode->next(); + if (childrenOnly) { + tempNode = nullptr; + } else { + tempNode = tempNode->next(); + } } } diff --git a/src/xmlutils.h b/src/xmlutils.h index a18ff8549..dfe1dec60 100644 --- a/src/xmlutils.h +++ b/src/xmlutils.h @@ -57,8 +57,9 @@ XmlNamespaceMap traverseTreeForUndefinedNamespaces(const XmlNodePtr &node); * CellML 1.0 or CellML 1.1 namespaces. * * @param node The root node of the tree to traverse. + * @param childrenOnly Only traverse children of the given @p node, **do not** traverse siblings [optional, default is false]. */ -void removeCellml1XNamespaces(const XmlNodePtr &node); +void removeCellml1XNamespaces(const XmlNodePtr &node, bool childrenOnly = false); /** * @brief Find all attributes that use the CellML 1.0 or CellML 1.1 namespace. diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 74c34716c..cf64a66c2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -53,6 +53,20 @@ set(TEST_EXPORTDEFINITIONS_H "${CMAKE_CURRENT_BINARY_DIR}/test_exportdefinitions set(TEST_UTILS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/test_utils.cpp) set(TEST_UTILS_HDR ${CMAKE_CURRENT_SOURCE_DIR}/test_utils.h) +if(NOT DEFINED LIBXML2_VERSION_STRING) + set(LIBXML2_VERSION_STRING "2.9.10") +elseif(LIBXML2_VERSION_STRING VERSION_GREATER_EQUAL "2.9.13") + set(LIBXML2_VERSION_STRING "2.9.13") +elseif(LIBXML2_VERSION_STRING VERSION_GREATER_EQUAL "2.9.11") + set(LIBXML2_VERSION_STRING "2.9.11") +endif() + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/libxml2issues.${LIBXML2_VERSION_STRING}.h + ${CMAKE_CURRENT_BINARY_DIR}/libxml2issues.h + COPYONLY +) + add_library(test_utils SHARED ${TEST_UTILS_SRC} ${TEST_UTILS_HDR} ${TEST_EXPORTDEFINITIONS_H}) target_link_libraries(test_utils PUBLIC cellml gtest) target_include_directories(test_utils PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) @@ -132,9 +146,6 @@ if(LIBCELLML_COVERAGE) DEPENDS clean_coverage ${TEST_LIST} COMMAND ${CMAKE_CTEST_COMMAND} > /dev/null COMMENT "Prepare for coverage tests") - if(TARGET python_bindings) - add_dependencies(prepare_coverage python_bindings) - endif() add_custom_target(coverage COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gcovr-4.1.1.zip -r ${GCOV_PREFIX_PATH} --gcov-executable=${GCOV_EXE} ${GCOV_ANALYSIS_PATH} diff --git a/tests/analyser/analyser.cpp b/tests/analyser/analyser.cpp index d8c11ae51..b2a0f2c7b 100644 --- a/tests/analyser/analyser.cpp +++ b/tests/analyser/analyser.cpp @@ -58,6 +58,32 @@ TEST(Analyser, unlinkedUnitsInModel) analyser); } +TEST(Analyser, notEqualityStatement) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("analyser/not_equality_statement.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); + + const std::vector expectedIssues = { + "Equation 'x+y+z' in component 'my_component' is not an equality statement (i.e. LHS = RHS).", + }; + + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(model); + + EXPECT_EQ_ISSUES_CELLMLELEMENTTYPES_LEVELS_REFERENCERULES_URLS(expectedIssues, + expectedCellmlElementTypes(expectedIssues.size(), libcellml::CellmlElementType::COMPONENT), + expectedLevels(expectedIssues.size(), libcellml::Issue::Level::ERROR), + expectedReferenceRules(expectedIssues.size(), libcellml::Issue::ReferenceRule::ANALYSER_EQUATION_NOT_EQUALITY_STATEMENT), + expectedUrls(expectedIssues.size(), "https://libcellml.org/documentation/guides/latest/runtime_codes/index?issue=ANALYSER_EQUATION_NOT_EQUALITY_STATEMENT"), + analyser); + + EXPECT_EQ(libcellml::AnalyserModel::Type::INVALID, analyser->model()->type()); + EXPECT_EQ("invalid", libcellml::AnalyserModel::typeAsString(analyser->model()->type())); +} + TEST(Analyser, initialisedVariableOfIntegration) { auto parser = libcellml::Parser::create(); @@ -296,7 +322,7 @@ TEST(Analyser, underconstrained) EXPECT_EQ(size_t(0), parser->issueCount()); const std::vector expectedIssues = { - "Variable 'x' in component 'my_component' is unused.", + "The type of variable 'x' in component 'my_component' is unknown.", }; auto analyser = libcellml::Analyser::create(); @@ -313,68 +339,15 @@ TEST(Analyser, underconstrained) EXPECT_EQ(libcellml::AnalyserModel::Type::UNDERCONSTRAINED, analyser->model()->type()); } -TEST(Analyser, overconstrainedOneVariable) -{ - auto parser = libcellml::Parser::create(); - auto model = parser->parseModel(fileContents("analyser/overconstrained_one_variable.cellml")); - - EXPECT_EQ(size_t(0), parser->issueCount()); - - const std::vector expectedIssues = { - "Variable 'x' in component 'my_component' is computed more than once.", - }; - - auto analyser = libcellml::Analyser::create(); - - analyser->analyseModel(model); - - EXPECT_EQ_ISSUES_CELLMLELEMENTTYPES_LEVELS_REFERENCERULES_URLS(expectedIssues, - expectedCellmlElementTypes(expectedIssues.size(), libcellml::CellmlElementType::VARIABLE), - expectedLevels(expectedIssues.size(), libcellml::Issue::Level::ERROR), - expectedReferenceRules(expectedIssues.size(), libcellml::Issue::ReferenceRule::ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE), - expectedUrls(expectedIssues.size(), "https://libcellml.org/documentation/guides/latest/runtime_codes/index?issue=ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE"), - analyser); - - EXPECT_EQ(libcellml::AnalyserModel::Type::OVERCONSTRAINED, analyser->model()->type()); -} - -TEST(Analyser, overconstrainedTwoVariables) -{ - auto parser = libcellml::Parser::create(); - auto model = parser->parseModel(fileContents("analyser/overconstrained_two_variables.cellml")); - - EXPECT_EQ(size_t(0), parser->issueCount()); - - const std::vector expectedIssues = { - "Variable 'x' in component 'my_component' is computed more than once.", - "Variable 'y' in component 'my_component' is computed more than once.", - }; - - auto analyser = libcellml::Analyser::create(); - - analyser->analyseModel(model); - - EXPECT_EQ_ISSUES_CELLMLELEMENTTYPES_LEVELS_REFERENCERULES_URLS(expectedIssues, - expectedCellmlElementTypes(expectedIssues.size(), libcellml::CellmlElementType::VARIABLE), - expectedLevels(expectedIssues.size(), libcellml::Issue::Level::ERROR), - expectedReferenceRules(expectedIssues.size(), libcellml::Issue::ReferenceRule::ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE), - expectedUrls(expectedIssues.size(), "https://libcellml.org/documentation/guides/latest/runtime_codes/index?issue=ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE"), - analyser); - - EXPECT_EQ(libcellml::AnalyserModel::Type::OVERCONSTRAINED, analyser->model()->type()); -} - -TEST(Analyser, overconstrainedThreeVariables) +TEST(Analyser, overconstrained) { auto parser = libcellml::Parser::create(); - auto model = parser->parseModel(fileContents("analyser/overconstrained_three_variables.cellml")); + auto model = parser->parseModel(fileContents("analyser/overconstrained.cellml")); EXPECT_EQ(size_t(0), parser->issueCount()); const std::vector expectedIssues = { "Variable 'x' in component 'my_component' is computed more than once.", - "Variable 'y' in component 'my_component' is computed more than once.", - "Variable 'z' in component 'my_component' is computed more than once.", }; auto analyser = libcellml::Analyser::create(); @@ -399,16 +372,16 @@ TEST(Analyser, unsuitablyConstrained) EXPECT_EQ(size_t(0), parser->issueCount()); const std::vector expectedIssues = { - "Variable 'x' in component 'my_component' is unused.", "Variable 'y' in component 'my_component' is computed more than once.", + "The type of variable 'x' in component 'my_component' is unknown.", }; const std::vector expectedReferenceRules = { - libcellml::Issue::ReferenceRule::ANALYSER_VARIABLE_UNUSED, libcellml::Issue::ReferenceRule::ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE, + libcellml::Issue::ReferenceRule::ANALYSER_VARIABLE_UNUSED, }; const std::vector expectedUrls = { - "https://libcellml.org/documentation/guides/latest/runtime_codes/index?issue=ANALYSER_VARIABLE_UNUSED", "https://libcellml.org/documentation/guides/latest/runtime_codes/index?issue=ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE", + "https://libcellml.org/documentation/guides/latest/runtime_codes/index?issue=ANALYSER_VARIABLE_UNUSED", }; auto analyser = libcellml::Analyser::create(); @@ -509,8 +482,11 @@ TEST(Analyser, removeExternalVariableByName) analyser->addExternalVariable(libcellml::AnalyserExternalVariable::create(model->component("membrane")->variable("V"))); - EXPECT_TRUE(analyser->removeExternalVariable(model, "membrane", "V")); + EXPECT_FALSE(analyser->removeExternalVariable(nullptr, "membrane", "V")); + EXPECT_FALSE(analyser->removeExternalVariable(model, "X", "V")); EXPECT_FALSE(analyser->removeExternalVariable(model, "membrane", "X")); + EXPECT_TRUE(analyser->removeExternalVariable(model, "membrane", "V")); + EXPECT_FALSE(analyser->removeExternalVariable(model, "membrane", "V")); } TEST(Analyser, removeExternalVariableByPointer) @@ -527,9 +503,9 @@ TEST(Analyser, removeExternalVariableByPointer) analyser->addExternalVariable(externalVariable); + EXPECT_FALSE(analyser->removeExternalVariable(nullptr)); EXPECT_TRUE(analyser->removeExternalVariable(externalVariable)); EXPECT_FALSE(analyser->removeExternalVariable(externalVariable)); - EXPECT_FALSE(analyser->removeExternalVariable(nullptr)); } TEST(Analyser, removeAllExternalVariables) @@ -914,64 +890,84 @@ TEST(Analyser, threeEquivalentExternalVariablesNotIncludingPrimaryVariable) analyser); } -TEST(Analyser, coverage) +TEST(Analyser, algebraicSystemWithThreeLinkedUnknownsWithOneExternalVariable) { + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/algebraic_system_with_three_linked_unknowns/model.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); + + const std::vector expectedIssues = { + "Variable 'y' in component 'my_algebraic_system' is computed more than once.", + "Variable 'z' in component 'my_algebraic_system' is computed more than once.", + }; + auto analyser = libcellml::Analyser::create(); - analyser->analyseModel(nullptr); + analyser->addExternalVariable(libcellml::AnalyserExternalVariable::create(model->component("my_algebraic_system")->variable("x"))); - EXPECT_EQ(size_t(1), analyser->issueCount()); + analyser->analyseModel(model); - auto analyserModel = analyser->model(); + EXPECT_EQ_ISSUES_CELLMLELEMENTTYPES_LEVELS_REFERENCERULES_URLS(expectedIssues, + expectedCellmlElementTypes(expectedIssues.size(), libcellml::CellmlElementType::VARIABLE), + expectedLevels(expectedIssues.size(), libcellml::Issue::Level::ERROR), + expectedReferenceRules(expectedIssues.size(), libcellml::Issue::ReferenceRule::ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE), + expectedUrls(expectedIssues.size(), "https://libcellml.org/documentation/guides/latest/runtime_codes/index?issue=ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE"), + analyser); - EXPECT_FALSE(analyserModel->isValid()); + EXPECT_EQ(libcellml::AnalyserModel::Type::OVERCONSTRAINED, analyser->model()->type()); +} - EXPECT_EQ(libcellml::AnalyserModel::Type::UNKNOWN, analyserModel->type()); +TEST(Analyser, algebraicSystemWithThreeLinkedUnknownsWithTwoExternalVariables) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/algebraic_system_with_three_linked_unknowns/model.cellml")); - EXPECT_EQ(nullptr, analyserModel->voi()); + EXPECT_EQ(size_t(0), parser->issueCount()); - EXPECT_FALSE(analyserModel->hasExternalVariables()); + const std::vector expectedIssues = { + "Variable 'y' in component 'my_algebraic_system' is computed more than once.", + }; + + auto analyser = libcellml::Analyser::create(); - EXPECT_EQ(size_t(0), analyserModel->stateCount()); - EXPECT_EQ(size_t(0), analyserModel->states().size()); + analyser->addExternalVariable(libcellml::AnalyserExternalVariable::create(model->component("my_algebraic_system")->variable("x"))); + analyser->addExternalVariable(libcellml::AnalyserExternalVariable::create(model->component("my_algebraic_system")->variable("z"))); - EXPECT_EQ(size_t(0), analyserModel->variableCount()); - EXPECT_EQ(size_t(0), analyserModel->variables().size()); + analyser->analyseModel(model); - EXPECT_EQ(size_t(0), analyserModel->equationCount()); - EXPECT_EQ(size_t(0), analyserModel->equations().size()); + EXPECT_EQ_ISSUES_CELLMLELEMENTTYPES_LEVELS_REFERENCERULES_URLS(expectedIssues, + expectedCellmlElementTypes(expectedIssues.size(), libcellml::CellmlElementType::VARIABLE), + expectedLevels(expectedIssues.size(), libcellml::Issue::Level::ERROR), + expectedReferenceRules(expectedIssues.size(), libcellml::Issue::ReferenceRule::ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE), + expectedUrls(expectedIssues.size(), "https://libcellml.org/documentation/guides/latest/runtime_codes/index?issue=ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE"), + analyser); - EXPECT_FALSE(analyserModel->needEqFunction()); - EXPECT_FALSE(analyserModel->needNeqFunction()); - EXPECT_FALSE(analyserModel->needLtFunction()); - EXPECT_FALSE(analyserModel->needLeqFunction()); - EXPECT_FALSE(analyserModel->needGtFunction()); - EXPECT_FALSE(analyserModel->needGeqFunction()); - EXPECT_FALSE(analyserModel->needAndFunction()); - EXPECT_FALSE(analyserModel->needOrFunction()); - EXPECT_FALSE(analyserModel->needXorFunction()); - EXPECT_FALSE(analyserModel->needNotFunction()); - EXPECT_FALSE(analyserModel->needMinFunction()); - EXPECT_FALSE(analyserModel->needMaxFunction()); - EXPECT_FALSE(analyserModel->needSecFunction()); - EXPECT_FALSE(analyserModel->needCscFunction()); - EXPECT_FALSE(analyserModel->needCotFunction()); - EXPECT_FALSE(analyserModel->needSechFunction()); - EXPECT_FALSE(analyserModel->needCschFunction()); - EXPECT_FALSE(analyserModel->needCothFunction()); - EXPECT_FALSE(analyserModel->needAsecFunction()); - EXPECT_FALSE(analyserModel->needAcscFunction()); - EXPECT_FALSE(analyserModel->needAcotFunction()); - EXPECT_FALSE(analyserModel->needAsechFunction()); - EXPECT_FALSE(analyserModel->needAcschFunction()); - EXPECT_FALSE(analyserModel->needAcothFunction()); + EXPECT_EQ(libcellml::AnalyserModel::Type::OVERCONSTRAINED, analyser->model()->type()); +} - auto ast = libcellml::AnalyserEquationAst::create(); +TEST(Analyser, overconstrainedNlaSystem) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("analyser/overconstrained_nla_system.cellml")); - EXPECT_NE(nullptr, ast); + EXPECT_EQ(size_t(0), parser->issueCount()); - ast->setType(libcellml::AnalyserEquationAst::Type::ASSIGNMENT); - ast->setValue({}); - ast->setVariable(libcellml::Variable::create()); - ast->setParent(libcellml::AnalyserEquationAst::create()); + const std::vector expectedIssues = { + "Variable 'x' in component 'my_algebraic_system' is computed more than once.", + "Variable 'y' in component 'my_algebraic_system' is computed more than once.", + }; + + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(model); + + EXPECT_EQ_ISSUES_CELLMLELEMENTTYPES_LEVELS_REFERENCERULES_URLS(expectedIssues, + expectedCellmlElementTypes(expectedIssues.size(), libcellml::CellmlElementType::VARIABLE), + expectedLevels(expectedIssues.size(), libcellml::Issue::Level::ERROR), + expectedReferenceRules(expectedIssues.size(), libcellml::Issue::ReferenceRule::ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE), + expectedUrls(expectedIssues.size(), "https://libcellml.org/documentation/guides/latest/runtime_codes/index?issue=ANALYSER_VARIABLE_COMPUTED_MORE_THAN_ONCE"), + analyser); + + EXPECT_EQ(libcellml::AnalyserModel::Type::OVERCONSTRAINED, analyser->model()->type()); } diff --git a/tests/annotator/annotator.cpp b/tests/annotator/annotator.cpp index 0379d3d80..3cd9c092a 100644 --- a/tests/annotator/annotator.cpp +++ b/tests/annotator/annotator.cpp @@ -506,21 +506,21 @@ TEST(Annotator, automaticIdsOnEverything) EXPECT_EQ("b4da5b", model->units(3)->id()); EXPECT_EQ("b4da5c", model->units(1)->unitId(0)); + EXPECT_EQ("b4da61", libcellml::Variable::equivalenceConnectionId(c2v1, c4v1)); EXPECT_EQ("b4da64", model->component("component2")->id()); - EXPECT_EQ("b4da65", model->component("component2")->component(0)->id()); + EXPECT_EQ("b4da65", model->component("component2")->encapsulationId()); EXPECT_EQ("b4da66", model->component("component2")->variable(0)->id()); EXPECT_EQ("b4da67", model->component("component2")->variable(1)->id()); - EXPECT_EQ("b4da68", model->component("component2")->component(0)->variable(0)->id()); - EXPECT_EQ("b4da69", model->component("component2")->component(0)->variable(1)->id()); - EXPECT_EQ("b4da6a", model->component("component2")->reset(0)->id()); - EXPECT_EQ("b4da6b", model->component("component2")->reset(0)->resetValueId()); - EXPECT_EQ("b4da6c", model->component("component2")->reset(0)->testValueId()); - EXPECT_EQ("b4da6d", libcellml::Variable::equivalenceConnectionId(c2v1, c3v1)); - EXPECT_EQ("b4da61", libcellml::Variable::equivalenceConnectionId(c2v1, c4v1)); - EXPECT_EQ("b4da6e", libcellml::Variable::equivalenceMappingId(c2v1, c3v1)); - EXPECT_EQ("b4da6f", libcellml::Variable::equivalenceMappingId(c2v2, c3v2)); - EXPECT_EQ("b4da70", model->component("component2")->encapsulationId()); - EXPECT_EQ("b4da71", model->component("component3")->encapsulationId()); + EXPECT_EQ("b4da68", libcellml::Variable::equivalenceConnectionId(c2v1, c3v1)); + EXPECT_EQ("b4da69", libcellml::Variable::equivalenceMappingId(c2v1, c3v1)); + EXPECT_EQ("b4da6a", libcellml::Variable::equivalenceMappingId(c2v2, c3v2)); + EXPECT_EQ("b4da6b", model->component("component2")->reset(0)->id()); + EXPECT_EQ("b4da6c", model->component("component2")->reset(0)->resetValueId()); + EXPECT_EQ("b4da6d", model->component("component2")->reset(0)->testValueId()); + EXPECT_EQ("b4da6e", model->component("component2")->component(0)->id()); + EXPECT_EQ("b4da6f", model->component("component3")->encapsulationId()); + EXPECT_EQ("b4da70", model->component("component2")->component(0)->variable(0)->id()); + EXPECT_EQ("b4da71", model->component("component2")->component(0)->variable(1)->id()); EXPECT_EQ("b4da72", model->encapsulationId()); } @@ -543,7 +543,7 @@ TEST(Annotator, automaticIdsComponents) EXPECT_EQ("", component2->id()); EXPECT_EQ("", component3->id()); - annotator->assignIds(libcellml::CellmlElementType::COMPONENT); + EXPECT_TRUE(annotator->assignIds(libcellml::CellmlElementType::COMPONENT)); EXPECT_TRUE(annotator->hasModel()); @@ -575,7 +575,7 @@ TEST(Annotator, automaticIdsComponentEncapsulations) EXPECT_EQ("", component2->encapsulationId()); EXPECT_EQ("", component3->encapsulationId()); - annotator->assignIds(libcellml::CellmlElementType::COMPONENT_REF); + EXPECT_TRUE(annotator->assignIds(libcellml::CellmlElementType::COMPONENT_REF)); EXPECT_TRUE(annotator->hasModel()); EXPECT_EQ("", model->id()); @@ -620,7 +620,7 @@ TEST(Annotator, automaticIdsConnection) EXPECT_EQ("", libcellml::Variable::equivalenceConnectionId(variable1, variable3)); EXPECT_EQ("", libcellml::Variable::equivalenceConnectionId(variable4, variable2)); - annotator->assignIds(libcellml::CellmlElementType::CONNECTION); + EXPECT_TRUE(annotator->assignIds(libcellml::CellmlElementType::CONNECTION)); EXPECT_TRUE(annotator->hasModel()); EXPECT_EQ("", model->id()); @@ -642,7 +642,7 @@ TEST(Annotator, automaticIdsEncapsulation) annotator->setModel(model); EXPECT_EQ("", model->encapsulationId()); - annotator->assignIds(libcellml::CellmlElementType::ENCAPSULATION); + EXPECT_TRUE(annotator->assignIds(libcellml::CellmlElementType::ENCAPSULATION)); EXPECT_TRUE(annotator->hasModel()); EXPECT_EQ("", model->id()); @@ -673,7 +673,7 @@ TEST(Annotator, automaticIdsImportSource) EXPECT_EQ("", model->units(0)->id()); EXPECT_EQ("", model->component(0)->id()); - annotator->assignIds(libcellml::CellmlElementType::IMPORT); + EXPECT_TRUE(annotator->assignIds(libcellml::CellmlElementType::IMPORT)); EXPECT_TRUE(annotator->hasModel()); EXPECT_EQ("", model->id()); @@ -716,7 +716,7 @@ TEST(Annotator, automaticIdsMapVariables) EXPECT_EQ("", libcellml::Variable::equivalenceMappingId(variable1, variable3)); EXPECT_EQ("", libcellml::Variable::equivalenceMappingId(variable2, variable4)); - annotator->assignIds(libcellml::CellmlElementType::MAP_VARIABLES); + EXPECT_TRUE(annotator->assignIds(libcellml::CellmlElementType::MAP_VARIABLES)); EXPECT_TRUE(annotator->hasModel()); EXPECT_EQ("", model->id()); @@ -739,7 +739,7 @@ TEST(Annotator, automaticIdsModel) EXPECT_EQ("", model->id()); - annotator->assignIds(libcellml::CellmlElementType::MODEL); + EXPECT_TRUE(annotator->assignIds(libcellml::CellmlElementType::MODEL)); EXPECT_TRUE(annotator->hasModel()); EXPECT_EQ("b4da55", model->id()); @@ -750,7 +750,7 @@ TEST(Annotator, automaticIdsNoModel) const std::string e = "This Annotator object does not have a model to work with."; auto annotator = libcellml::Annotator::create(); - annotator->assignIds(libcellml::CellmlElementType::MODEL); + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::MODEL)); EXPECT_FALSE(annotator->hasModel()); EXPECT_EQ(size_t(1), annotator->errorCount()); @@ -786,7 +786,7 @@ TEST(Annotator, automaticIdsResets) EXPECT_EQ("", reset2->id()); EXPECT_EQ("", reset3->id()); - annotator->assignIds(libcellml::CellmlElementType::RESET); + EXPECT_TRUE(annotator->assignIds(libcellml::CellmlElementType::RESET)); EXPECT_TRUE(annotator->hasModel()); EXPECT_EQ("", model->id()); @@ -833,7 +833,7 @@ TEST(Annotator, automaticIdsResetValues) EXPECT_EQ("", reset2->resetValueId()); EXPECT_EQ("", reset3->resetValueId()); - annotator->assignIds(libcellml::CellmlElementType::RESET_VALUE); + EXPECT_TRUE(annotator->assignIds(libcellml::CellmlElementType::RESET_VALUE)); EXPECT_TRUE(annotator->hasModel()); EXPECT_EQ("", model->id()); @@ -883,7 +883,7 @@ TEST(Annotator, automaticIdsTestValues) EXPECT_EQ("", reset2->testValueId()); EXPECT_EQ("", reset3->testValueId()); - annotator->assignIds(libcellml::CellmlElementType::TEST_VALUE); + EXPECT_TRUE(annotator->assignIds(libcellml::CellmlElementType::TEST_VALUE)); EXPECT_TRUE(annotator->hasModel()); EXPECT_EQ("", model->id()); @@ -916,7 +916,7 @@ TEST(Annotator, automaticIdsUnits) EXPECT_EQ("", units->unitId(0)); EXPECT_EQ("", units->unitId(1)); - annotator->assignIds(libcellml::CellmlElementType::UNIT); + EXPECT_TRUE(annotator->assignIds(libcellml::CellmlElementType::UNIT)); EXPECT_TRUE(annotator->hasModel()); EXPECT_EQ("", model->id()); @@ -946,7 +946,7 @@ TEST(Annotator, automaticIdsUnitsItems) EXPECT_EQ("", units1->unitId(1)); EXPECT_EQ("", units2->id()); - annotator->assignIds(libcellml::CellmlElementType::UNITS); + EXPECT_TRUE(annotator->assignIds(libcellml::CellmlElementType::UNITS)); EXPECT_TRUE(annotator->hasModel()); EXPECT_EQ("", model->id()); @@ -984,7 +984,7 @@ TEST(Annotator, automaticIdsVariables) EXPECT_EQ("", variable3->id()); EXPECT_EQ("", variable4->id()); - annotator->assignIds(libcellml::CellmlElementType::VARIABLE); + EXPECT_TRUE(annotator->assignIds(libcellml::CellmlElementType::VARIABLE)); EXPECT_TRUE(annotator->hasModel()); EXPECT_EQ("", model->id()); @@ -1019,6 +1019,30 @@ TEST(Annotator, automaticIdsMath) EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::MATH)); } +TEST(Annotator, automaticIdsAlreadyExisting) +{ + // Adding test for coverage purposes. + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(modelStringUniqueIds); + auto annotator = libcellml::Annotator::create(); + + annotator->setModel(model); + + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::COMPONENT)); + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::COMPONENT_REF)); + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::CONNECTION)); + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::ENCAPSULATION)); + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::IMPORT)); + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::MAP_VARIABLES)); + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::MODEL)); + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::RESET)); + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::RESET_VALUE)); + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::TEST_VALUE)); + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::UNIT)); + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::UNITS)); + EXPECT_FALSE(annotator->assignIds(libcellml::CellmlElementType::VARIABLE)); +} + TEST(Annotator, automaticIdAllItemsNoId) { auto parser = libcellml::Parser::create(); @@ -1151,7 +1175,10 @@ TEST(Annotator, assignImportSourceIdBadInput) TEST(Annotator, assignVariablePairIdBadInput) { auto annotator = libcellml::Annotator::create(); + auto dummyVariable = libcellml::Variable::create("dummy"); + EXPECT_EQ("", annotator->assignId(libcellml::VariablePair::create(nullptr, nullptr))); + EXPECT_EQ("", annotator->assignId(libcellml::VariablePair::create(dummyVariable, nullptr))); EXPECT_EQ("", annotator->assignId(libcellml::VariablePair::create(nullptr, nullptr), libcellml::CellmlElementType::MODEL)); } @@ -1583,11 +1610,11 @@ TEST(Annotator, assignAllIdsBlankModel) auto model = parser->parseModel(modelStringNoIds); auto annotator = libcellml::Annotator::create(); - annotator->assignAllIds(model); + EXPECT_TRUE(annotator->assignAllIds(model)); EXPECT_EQ(size_t(0), annotator->errorCount()); libcellml::ModelPtr nullModel; - annotator->assignAllIds(nullModel); + EXPECT_FALSE(annotator->assignAllIds(nullModel)); EXPECT_EQ(size_t(0), annotator->errorCount()); } @@ -1598,11 +1625,23 @@ TEST(Annotator, assignAllIdsNonblankModel) auto model = parser->parseModel(modelStringUniqueIds); auto annotator = libcellml::Annotator::create(); - annotator->assignAllIds(model); + EXPECT_FALSE(annotator->assignAllIds(model)); EXPECT_EQ(size_t(0), annotator->errorCount()); EXPECT_EQ(modelStringUniqueIds, printer->printModel(model)); } +TEST(Annotator, assignAllIdsDuplicateIdsModel) +{ + auto parser = libcellml::Parser::create(); + auto printer = libcellml::Printer::create(); + auto model = parser->parseModel(modelStringLotsOfDuplicateIds); + auto annotator = libcellml::Annotator::create(); + + EXPECT_FALSE(annotator->assignAllIds(model)); + EXPECT_EQ(size_t(0), annotator->errorCount()); + EXPECT_EQ(modelStringLotsOfDuplicateIds, printer->printModel(model)); +} + TEST(Annotator, clearAllIdsNoModelPresent) { std::vector expectedErrors = { @@ -1718,7 +1757,6 @@ TEST(Annotator, listAllIds) ids = annotator->ids(); EXPECT_EQ(std::vector(), ids); } - TEST(Annotator, retrieveDuplicateIdItemLists) { std::vector ids = { diff --git a/tests/bindings/javascript/analyserequation.test.js b/tests/bindings/javascript/analyserequation.test.js index 40b42f016..4f1a5cc31 100644 --- a/tests/bindings/javascript/analyserequation.test.js +++ b/tests/bindings/javascript/analyserequation.test.js @@ -43,16 +43,41 @@ describe("Analyser Equation tests", () => { eqn = am.equation(0) }); test('Checking Analyser Equation type.', () => { - expect(eqn.type().value).toBe(libcellml.AnalyserEquation.Type.RATE.value) + expect(eqn.type().value).toBe(libcellml.AnalyserEquation.Type.ODE.value) + expect(libcellml.AnalyserEquation.typeAsString(eqn.type())).toBe("ode") }); test('Checking Analyser Equation isStateRateBased.', () => { expect(eqn.isStateRateBased()).toBe(false) }); + test('Checking Analyser Equation dependencyCount.', () => { + expect(eqn.dependencyCount()).toBe(0) + }); test('Checking Analyser Equation dependencies.', () => { expect(eqn.dependencies().size()).toBe(0) }); + test('Checking Analyser Equation dependency.', () => { + expect(eqn.dependency(0)).toBe(null) + }); + test('Checking Analyser Equation nlaSystemIndex.', () => { + expect(eqn.nlaSystemIndex()).toBe(4294967295) + }); + test('Checking Analyser Equation nlaSiblingCount.', () => { + expect(eqn.nlaSiblingCount()).toBe(0) + }); + test('Checking Analyser Equation nlaSiblings.', () => { + expect(eqn.nlaSiblings().size()).toBe(0) + }); + test('Checking Analyser Equation nlaSibling.', () => { + expect(eqn.nlaSibling(0)).toBe(null) + }); + test('Checking Analyser Equation variableCount.', () => { + expect(eqn.variableCount()).toBe(1) + }); + test('Checking Analyser Equation variables.', () => { + expect(eqn.variables().size()).toBe(1) + }); test('Checking Analyser Equation variable.', () => { - expect(eqn.variable().variable().name()).toBe("x") + expect(eqn.variable(0).variable().name()).toBe("x") }); test('Checking Analyser Equation AST.', () => { expect(eqn.ast().value()).toBe("") diff --git a/tests/bindings/javascript/analyserequationast.test.js b/tests/bindings/javascript/analyserequationast.test.js index 8df6f4303..33592e86a 100644 --- a/tests/bindings/javascript/analyserequationast.test.js +++ b/tests/bindings/javascript/analyserequationast.test.js @@ -25,13 +25,15 @@ describe("Analyser Equation AST tests", () => { test('Checking Analyser Equation AST type.', () => { const aea = new libcellml.AnalyserEquationAst() - expect(aea.type().value).toBe(libcellml.AnalyserEquationAst.Type.ASSIGNMENT.value) - expect(aea.type()).toStrictEqual(libcellml.AnalyserEquationAst.Type.ASSIGNMENT) + expect(aea.type().value).toBe(libcellml.AnalyserEquationAst.Type.EQUALITY.value) + expect(libcellml.AnalyserEquationAst.typeAsString(aea.type())).toBe("equality") + expect(aea.type()).toStrictEqual(libcellml.AnalyserEquationAst.Type.EQUALITY) expect(aea.type()).not.toStrictEqual(libcellml.AnalyserEquationAst.Type.OTHERWISE) aea.setType(libcellml.AnalyserEquationAst.Type.OTHERWISE) expect(aea.type().value).toBe(libcellml.AnalyserEquationAst.Type.OTHERWISE.value) + expect(libcellml.AnalyserEquationAst.typeAsString(aea.type())).toBe("otherwise") }); test('Checking Analyser Equation AST value.', () => { const aea = new libcellml.AnalyserEquationAst() @@ -56,6 +58,9 @@ describe("Analyser Equation AST tests", () => { }); test('Checking Analyser Equation AST tree manipulations.', () => { const aea = new libcellml.AnalyserEquationAst() + + aea.swapLeftAndRightChildren() + const paea = new libcellml.AnalyserEquationAst() const laea = new libcellml.AnalyserEquationAst() const raea = new libcellml.AnalyserEquationAst() diff --git a/tests/bindings/javascript/analysermodel.test.js b/tests/bindings/javascript/analysermodel.test.js index 59cc0a697..a84ad5e3d 100644 --- a/tests/bindings/javascript/analysermodel.test.js +++ b/tests/bindings/javascript/analysermodel.test.js @@ -39,6 +39,7 @@ describe("Analyser Model tests", () => { }); test('Checking Analyser Model type.', () => { expect(am.type().value).toBe(libcellml.AnalyserModel.Type.ODE.value) + expect(libcellml.AnalyserModel.typeAsString(am.type())).toBe("ode") }); test('Checking Analyser Model isValid.', () => { expect(am.isValid()).toBe(true) @@ -52,18 +53,18 @@ describe("Analyser Model tests", () => { test('Checking Analyser Model equations related API.', () => { expect(am.equationCount()).toBe(17) expect(am.equations().size()).toBe(17) - expect(am.equations().get(1).type().value).toBe(libcellml.AnalyserEquation.Type.RATE.value) - expect(am.equation(1).type().value).toBe(libcellml.AnalyserEquation.Type.RATE.value) + expect(am.equations().get(1).type().value).toBe(libcellml.AnalyserEquation.Type.ODE.value) + expect(am.equation(1).type().value).toBe(libcellml.AnalyserEquation.Type.ODE.value) }); test('Checking Analyser Model states related API.', () => { expect(am.stateCount()).toBe(4) expect(am.states().size()).toBe(4) - expect(am.state(2).variable().name()).toBe("n") + expect(am.state(2).variable().name()).toBe("m") }); test('Checking Analyser Model variables related API.', () => { expect(am.variableCount()).toBe(18) expect(am.variables().size()).toBe(18) - expect(am.variable(2).variable().name()).toBe("E_R") + expect(am.variable(2).variable().name()).toBe("i_K") }); test('Checking Analyser Model need* API.', () => { expect(am.needEqFunction()).toBe(false) diff --git a/tests/bindings/javascript/analyservariable.test.js b/tests/bindings/javascript/analyservariable.test.js index 68086134c..52b5ef749 100644 --- a/tests/bindings/javascript/analyservariable.test.js +++ b/tests/bindings/javascript/analyservariable.test.js @@ -40,23 +40,32 @@ describe("Analyser Variable tests", () => { expect(am.variableCount()).toBe(18) }); test('Checking Analyser Variable type.', () => { - const av = am.variable(5) + const av = am.variable(0) expect(av.type().value).toBe(libcellml.AnalyserVariable.Type.ALGEBRAIC.value) + expect(libcellml.AnalyserVariable.typeAsString(av.type())).toBe("algebraic") }); test('Checking Analyser Variable index.', () => { const av = am.variable(7) expect(av.index()).toBe(7) }); test('Checking Analyser Variable initialising variable.', () => { - const av = am.variable(3) + const av = am.variable(15) expect(av.initialisingVariable().name()).toBe("g_K") }); test('Checking Analyser Variable variable.', () => { const av = am.variable(10) expect(av.variable().name()).toBe("alpha_m") }); + test('Checking Analyser Equation equationCount.', () => { + const av = am.variable(14) + expect(av.equationCount()).toBe(1) + }); + test('Checking Analyser Variable equations.', () => { + const av = am.variable(14) + expect(av.equations().size()).toBe(1) + }); test('Checking Analyser Variable equation.', () => { const av = am.variable(14) - expect(av.equation().type().value).toBe(libcellml.AnalyserEquation.Type.VARIABLE_BASED_CONSTANT.value) + expect(av.equation(0).type().value).toBe(libcellml.AnalyserEquation.Type.VARIABLE_BASED_CONSTANT.value) }); }) diff --git a/tests/bindings/javascript/annotator.test.js b/tests/bindings/javascript/annotator.test.js index af0e67545..e70bfbdd3 100644 --- a/tests/bindings/javascript/annotator.test.js +++ b/tests/bindings/javascript/annotator.test.js @@ -59,7 +59,7 @@ describe("Annotator tests", () => { expect(a.assignAllIds()).toBe(true) expect(a.itemCount("b4da55")).toBe(1) - expect(a.assignAllIdsByModel(m)).toBe(true) + expect(a.assignAllIdsByModel(m)).toBe(false) a.clearAllIdsByModel(m) @@ -120,8 +120,8 @@ describe("Annotator tests", () => { expect(a.component("b4da5e").name()).toBe("component4") expect(a.componentByIndex("b4da5e", 0).name()).toBe("component4") - expect(a.componentEncapsulation("b4da70").name()).toBe("component2") - expect(a.componentEncapsulationByIndex("b4da70", 0).name()).toBe("component2") + expect(a.componentEncapsulation("b4da65").name()).toBe("component2") + expect(a.componentEncapsulationByIndex("b4da65", 0).name()).toBe("component2") expect(a.connection("b4da61").isValid()).toBe(true) expect(a.connectionByIndex("b4da61", 0).isValid()).toBe(true) @@ -138,14 +138,14 @@ describe("Annotator tests", () => { expect(a.modelById("b4da55").name()).toBe("everything") expect(a.modelByIdIndex("b4da55", 0).name()).toBe("everything") - expect(a.reset("b4da6a").order()).toBe(1) - expect(a.resetByIndex("b4da6a", 0).order()).toBe(1) + expect(a.reset("b4da6b").order()).toBe(1) + expect(a.resetByIndex("b4da6b", 0).order()).toBe(1) - expect(a.resetValue("b4da6b").variable().name()).toBe("variable1") - expect(a.resetValueByIndex("b4da6b", 0).variable().name()).toBe("variable1") + expect(a.resetValue("b4da6c").variable().name()).toBe("variable1") + expect(a.resetValueByIndex("b4da6c", 0).variable().name()).toBe("variable1") - expect(a.testValue("b4da6c").testVariable().name()).toBe("variable2") - expect(a.testValueByIndex("b4da6c", 0).testVariable().name()).toBe("variable2") + expect(a.testValue("b4da6d").testVariable().name()).toBe("variable2") + expect(a.testValueByIndex("b4da6d", 0).testVariable().name()).toBe("variable2") expect(a.unitsItem("b4da5c").index()).toBe(0) expect(a.unitsItemByIndex("b4da5c", 0).index()).toBe(0) diff --git a/tests/bindings/javascript/component.test.js b/tests/bindings/javascript/component.test.js index f1169c9b5..efc49a5a8 100644 --- a/tests/bindings/javascript/component.test.js +++ b/tests/bindings/javascript/component.test.js @@ -277,4 +277,9 @@ describe("Component tests", () => { c.setImportReference("this_thing") expect(c.isResolved()).toBe(false) }) + test('Checking Component is defined.', () => { + const c = new libcellml.Component() + + expect(c.isDefined()).toBe(true) + }) }) diff --git a/tests/bindings/javascript/generator.test.js b/tests/bindings/javascript/generator.test.js index 2ff93b42e..0fd13e18a 100644 --- a/tests/bindings/javascript/generator.test.js +++ b/tests/bindings/javascript/generator.test.js @@ -50,7 +50,7 @@ describe("Generator tests", () => { expect(g.model()).toBeDefined() expect(g.model().stateCount()).toBe(1) }) - test('Checking Generator code generation.', () => { + test('Checking Generator code generation.', () => { const g = new libcellml.Generator() const p = new libcellml.Parser(true) @@ -65,6 +65,13 @@ describe("Generator tests", () => { expect(interface_lines.length).toBe(40) const implementation_lines = g.implementationCode().split('\n') - expect(implementation_lines.length).toBe(55) + expect(implementation_lines.length).toBe(67) + + const equation_line_1 = libcellml.Generator.equationCode(a.model().equation(0).ast()) + expect(equation_line_1.length).toBe(14) + + const gp = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.PYTHON) + const equation_line_2 = libcellml.Generator.equationCodeByProfile(a.model().equation(0).ast(), gp) + expect(equation_line_2.length).toBe(14) }) }) diff --git a/tests/bindings/javascript/generatorprofile.test.js b/tests/bindings/javascript/generatorprofile.test.js index 2a259fb2e..be6ff9f39 100644 --- a/tests/bindings/javascript/generatorprofile.test.js +++ b/tests/bindings/javascript/generatorprofile.test.js @@ -23,9 +23,12 @@ describe("GeneratorProfile tests", () => { }); test("Checking GeneratorProfile.profile.", () => { const x = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.C) + expect(x.profile()).toBe(libcellml.GeneratorProfile.Profile.C) + expect(libcellml.GeneratorProfile.profileAsString(x.profile())).toBe("c") x.setProfile(libcellml.GeneratorProfile.Profile.PYTHON) expect(x.profile()).toBe(libcellml.GeneratorProfile.Profile.PYTHON) + expect(libcellml.GeneratorProfile.profileAsString(x.profile())).toBe("python") }); test("Checking GeneratorProfile.hasInterface.", () => { const x = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.C) @@ -33,11 +36,11 @@ describe("GeneratorProfile tests", () => { x.setHasInterface(true) expect(x.hasInterface()).toBe(true) }); - test("Checking GeneratorProfile.assignmentString.", () => { + test("Checking GeneratorProfile.equalityString.", () => { const x = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.C) - x.setAssignmentString("something") - expect(x.assignmentString()).toBe("something") + x.setEqualityString("something") + expect(x.equalityString()).toBe("something") }); test("Checking GeneratorProfile.eqString.", () => { const x = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.C) @@ -789,6 +792,69 @@ describe("GeneratorProfile tests", () => { x.setVariableInfoEntryString("something") expect(x.variableInfoEntryString()).toBe("something") }); + test("Checking GeneratorProfile.rootFindingInfoObjectString.", () => { + const x = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.C) + + x.setRootFindingInfoObjectString(false, "something") + expect(x.rootFindingInfoObjectString(false)).toBe("something") + + x.setRootFindingInfoObjectString(true, "something") + expect(x.rootFindingInfoObjectString(true)).toBe("something") + }); + test("Checking GeneratorProfile.externNlaSolveMethodString.", () => { + const x = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.C) + + x.setExternNlaSolveMethodString("something") + expect(x.externNlaSolveMethodString()).toBe("something") + }); + test("Checking GeneratorProfile.findRootCallString.", () => { + const x = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.C) + + x.setFindRootCallString(false, "something") + expect(x.findRootCallString(false)).toBe("something") + + x.setFindRootCallString(true, "something") + expect(x.findRootCallString(true)).toBe("something") + }); + test("Checking GeneratorProfile.findRootMethodString.", () => { + const x = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.C) + + x.setFindRootMethodString(false, "something") + expect(x.findRootMethodString(false)).toBe("something") + + x.setFindRootMethodString(true, "something") + expect(x.findRootMethodString(true)).toBe("something") + }); + test("Checking GeneratorProfile.nlaSolveCallString.", () => { + const x = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.C) + + x.setNlaSolveCallString(false, "something") + expect(x.nlaSolveCallString(false)).toBe("something") + + x.setNlaSolveCallString(true, "something") + expect(x.nlaSolveCallString(true)).toBe("something") + }); + test("Checking GeneratorProfile.objectiveFunctionMethodString.", () => { + const x = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.C) + + x.setObjectiveFunctionMethodString(false, "something") + expect(x.objectiveFunctionMethodString(false)).toBe("something") + + x.setObjectiveFunctionMethodString(true, "something") + expect(x.objectiveFunctionMethodString(true)).toBe("something") + }); + test("Checking GeneratorProfile.uArrayString.", () => { + const x = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.C) + + x.setUArrayString("something") + expect(x.uArrayString()).toBe("something") + }); + test("Checking GeneratorProfile.fArrayString.", () => { + const x = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.C) + + x.setFArrayString("something") + expect(x.fArrayString()).toBe("something") + }); test("Checking GeneratorProfile.voiString.", () => { const x = new libcellml.GeneratorProfile(libcellml.GeneratorProfile.Profile.C) diff --git a/tests/bindings/javascript/model.test.js b/tests/bindings/javascript/model.test.js index bc63c0bd8..551ad26ae 100644 --- a/tests/bindings/javascript/model.test.js +++ b/tests/bindings/javascript/model.test.js @@ -23,10 +23,20 @@ describe("Model tests", () => { }); test('Checking Model name.', () => { const m = new libcellml.Model() - + expect(m.name()).toBe(''); m.setName('model-test') expect(m.name()).toBe('model-test'); }); + test('Checking Model has resolved imports.', () => { + const m = new libcellml.Model() + + expect(m.hasUnresolvedImports()).toBe(false); + }); + test('Checking Model is defined.', () => { + const m = new libcellml.Model() + + expect(m.isDefined()).toBe(true); + }); }) diff --git a/tests/bindings/javascript/units.test.js b/tests/bindings/javascript/units.test.js index bce0f7078..881fa1f1c 100644 --- a/tests/bindings/javascript/units.test.js +++ b/tests/bindings/javascript/units.test.js @@ -118,6 +118,9 @@ describe("Units tests", () => { expect(u.unitCount()).toBe(1) expect(u.unitAttributeReference(0)).toBe("farad") + + u.setUnitAttributeReference(0, "mole") + expect(u.unitAttributeReference(0)).toBe("mole") }) test('Checking Units unit attribute prefix.', () => { const u = new libcellml.Units() @@ -259,6 +262,11 @@ describe("Units tests", () => { u.setImportReference("this_thing") expect(u.isResolved()).toBe(false) }) + test('Checking Units is defined.', () => { + const u = new libcellml.Units() + + expect(u.isDefined()).toBe(true) + }) test('Checking Units scaling factor.', () => { const u1 = new libcellml.Units("second") let u2 = new libcellml.Units("millisecond") diff --git a/tests/bindings/javascript/version.test.js b/tests/bindings/javascript/version.test.js index baab58d86..924305b29 100644 --- a/tests/bindings/javascript/version.test.js +++ b/tests/bindings/javascript/version.test.js @@ -22,6 +22,6 @@ describe("Version tests", () => { libcellml = await libCellMLModule(); }); test('Checking version string.', () => { - expect(libcellml.versionString()).toBe('0.4.0'); + expect(libcellml.versionString()).toBe('0.5.0'); }); }) diff --git a/tests/bindings/python/test_analyser.py b/tests/bindings/python/test_analyser.py index ce2129b27..654daf1a2 100644 --- a/tests/bindings/python/test_analyser.py +++ b/tests/bindings/python/test_analyser.py @@ -29,6 +29,7 @@ def test_analyse_model(self): from libcellml import Analyser from libcellml import AnalyserModel from libcellml import Model + from libcellml.analysermodel import AnalyserModel_typeAsString # Analyse an empty model and make sure that we get no errors and an # UNKNOWN type for the analyser model. @@ -40,6 +41,8 @@ def test_analyse_model(self): self.assertEqual(0, a.errorCount()) self.assertEqual(AnalyserModel.Type.UNKNOWN, a.model().type()) + self.assertEqual("unknown", AnalyserModel.typeAsString(a.model().type())) + self.assertEqual("unknown", AnalyserModel_typeAsString(a.model().type())) def test_coverage(self): from libcellml import Analyser @@ -50,6 +53,9 @@ def test_coverage(self): from libcellml import AnalyserVariable from libcellml import Model from libcellml import Parser + from libcellml.analyserequation import AnalyserEquation_typeAsString + from libcellml.analyserequationast import AnalyserEquationAst_typeAsString + from libcellml.analyservariable import AnalyserVariable_typeAsString from test_resources import file_contents # Try to create an analyser equation/model/variable, something that is not allowed. @@ -149,32 +155,56 @@ def test_coverage(self): av = am.variable(3) self.assertEqual(AnalyserVariable.Type.CONSTANT, av.type()) + self.assertEqual("constant", AnalyserVariable.typeAsString(av.type())) + self.assertEqual("constant", AnalyserVariable_typeAsString(av.type())) self.assertEqual(3, av.index()) self.assertIsNotNone(av.initialisingVariable()) self.assertIsNotNone(av.variable()) - self.assertIsNone(av.equation()) + self.assertEqual(1, av.equationCount()) + self.assertIsNotNone(av.equations()) + self.assertIsNone(av.equation(0)) # Ensure coverage for AnalyserEquation. ae = am.equation(3) - self.assertEqual(AnalyserEquation.Type.RATE, ae.type()) + self.assertEqual(AnalyserEquation.Type.ALGEBRAIC, ae.type()) + self.assertEqual("algebraic", AnalyserEquation.typeAsString(ae.type())) + self.assertEqual("algebraic", AnalyserEquation_typeAsString(ae.type())) self.assertIsNotNone(ae.ast()) + self.assertEqual(2, ae.dependencyCount()) self.assertIsNotNone(ae.dependencies()) + self.assertIsNotNone(ae.dependency(0)) + self.assertEqual(18446744073709551615, ae.nlaSystemIndex()) + self.assertEqual(0, ae.nlaSiblingCount()) + self.assertIsNotNone(ae.nlaSiblings()) + self.assertIsNone(ae.nlaSibling(0)) self.assertTrue(ae.isStateRateBased()) - self.assertIsNotNone(ae.variable()) + self.assertEqual(1, ae.variableCount()) + self.assertIsNotNone(ae.variables()) + self.assertIsNotNone(ae.variable(0)) + + # Check Analyser Equation type with invalid values. + + self.assertRaises(RuntimeError, AnalyserEquation.typeAsString, -1) + self.assertRaises(RuntimeError, AnalyserEquation_typeAsString, -1) + self.assertRaises(RuntimeError, AnalyserEquation.typeAsString, 999) + self.assertRaises(RuntimeError, AnalyserEquation_typeAsString, 999) # Ensure coverage for AnalyserEquationAst. aea = ae.ast() - self.assertEqual(AnalyserEquationAst.Type.ASSIGNMENT, aea.type()) + self.assertEqual(AnalyserEquationAst.Type.EQUALITY, aea.type()) + self.assertEqual("equality", AnalyserEquationAst.typeAsString(aea.type())) + self.assertEqual("equality", AnalyserEquationAst_typeAsString(aea.type())) self.assertEqual('', aea.value()) self.assertIsNone(aea.variable()) self.assertIsNone(aea.parent()) self.assertIsNotNone(aea.leftChild()) self.assertIsNotNone(aea.rightChild()) + aea.swapLeftAndRightChildren() aea.setType(AnalyserEquationAst.Type.EQ) aea.setValue(AnalyserTestCase.VALUE) aea.setVariable(av.variable()) @@ -183,6 +213,8 @@ def test_coverage(self): aea.setRightChild(None) self.assertEqual(AnalyserEquationAst.Type.EQ, aea.type()) + self.assertEqual("eq", AnalyserEquationAst.typeAsString(aea.type())) + self.assertEqual("eq", AnalyserEquationAst_typeAsString(aea.type())) self.assertEqual(AnalyserTestCase.VALUE, aea.value()) self.assertIsNotNone(aea.variable()) self.assertIsNotNone(aea.parent()) diff --git a/tests/bindings/python/test_analyser_equation_ast.py b/tests/bindings/python/test_analyser_equation_ast.py index 6c766a65f..ffca0ced6 100644 --- a/tests/bindings/python/test_analyser_equation_ast.py +++ b/tests/bindings/python/test_analyser_equation_ast.py @@ -17,7 +17,7 @@ def test_analyser_equation_ast(self): # Create an equation AST and check its default settings. ast = AnalyserEquationAst() - self.assertEqual(AnalyserEquationAst.Type.ASSIGNMENT, ast.type()) + self.assertEqual(AnalyserEquationAst.Type.EQUALITY, ast.type()) self.assertEqual('', ast.value()) self.assertIsNone(ast.variable()) self.assertIsNone(ast.parent()) diff --git a/tests/bindings/python/test_annotator.py b/tests/bindings/python/test_annotator.py index 706137443..98f8ee956 100644 --- a/tests/bindings/python/test_annotator.py +++ b/tests/bindings/python/test_annotator.py @@ -267,27 +267,28 @@ def test_auto_ids(self): self.assertEqual("b4da5c", model.units(1).unitId(0)) self.assertEqual("b4da5d", model.component(0).id()) self.assertEqual("b4da5e", model.component(1).id()) - self.assertEqual("b4da5f", model.component(1).component(0).id()) self.assertEqual("b4da60", model.component(1).variable(0).id()) self.assertEqual("b4da61", model.component(1).variable(1).id()) - self.assertEqual("b4da62", model.component(1).component(0).variable(0).id()) - self.assertEqual("b4da63", model.component(1).component(0).variable(1).id()) + self.assertEqual("b4da6a", model.component(1).component(0).variable(0).id()) + self.assertEqual("b4da6b", model.component(1).component(0).variable(1).id()) - self.assertEqual("b4da64", model.component(1).reset(0).id()) - self.assertEqual("b4da65", model.component(1).reset(0).resetValueId()) - self.assertEqual("b4da66", model.component(1).reset(0).testValueId()) + self.assertEqual("b4da65", model.component(1).reset(0).id()) + self.assertEqual("b4da66", model.component(1).reset(0).resetValueId()) + self.assertEqual("b4da67", model.component(1).reset(0).testValueId()) + + self.assertEqual("b4da68", model.component(1).component(0).id()) c2v1 = model.component("component2").variable("variable1") c2v2 = model.component("component2").variable("variable2") c3v1 = model.component("component3").variable("variable1") c3v2 = model.component("component3").variable("variable2") - self.assertEqual("b4da67", Variable.equivalenceConnectionId(c2v1, c3v1)) - self.assertEqual("b4da67", Variable.equivalenceConnectionId(c2v2, c3v2)) - self.assertEqual("b4da68", Variable.equivalenceMappingId(c2v1, c3v1)) - self.assertEqual("b4da69", Variable.equivalenceMappingId(c2v2, c3v2)) - self.assertEqual("b4da6a", model.component("component2").encapsulationId()) - self.assertEqual("b4da6b", model.component("component3").encapsulationId()) + self.assertEqual("b4da62", Variable.equivalenceConnectionId(c2v1, c3v1)) + self.assertEqual("b4da62", Variable.equivalenceConnectionId(c2v2, c3v2)) + self.assertEqual("b4da63", Variable.equivalenceMappingId(c2v1, c3v1)) + self.assertEqual("b4da64", Variable.equivalenceMappingId(c2v2, c3v2)) + self.assertEqual("b4da5f", model.component("component2").encapsulationId()) + self.assertEqual("b4da69", model.component("component3").encapsulationId()) self.assertEqual("b4da6c", model.encapsulationId()) def test_assign_id(self): diff --git a/tests/bindings/python/test_component.py b/tests/bindings/python/test_component.py index c35eb5699..9590f994c 100644 --- a/tests/bindings/python/test_component.py +++ b/tests/bindings/python/test_component.py @@ -280,6 +280,13 @@ def test_misc(self): self.assertRaises(AttributeError, ComponentEntity) + def test_is_defined(self): + from libcellml import Component + + c = Component("MyComponent") + + self.assertTrue(c.isDefined()) + def test_requires_imports(self): from libcellml import Component diff --git a/tests/bindings/python/test_generator.py b/tests/bindings/python/test_generator.py index 688fb1e68..833dc3c95 100644 --- a/tests/bindings/python/test_generator.py +++ b/tests/bindings/python/test_generator.py @@ -16,6 +16,7 @@ def test_algebraic_eqn_computed_var_on_rhs(self): from libcellml import Analyser from libcellml import AnalyserModel from libcellml import Generator + from libcellml.generator import Generator_equationCode from libcellml import GeneratorProfile from libcellml import Parser from test_resources import file_contents @@ -51,6 +52,9 @@ def test_algebraic_eqn_computed_var_on_rhs(self): self.assertEqual(GeneratorProfile.Profile.PYTHON, g.profile().profile()) + self.assertEqual("x = a", Generator.equationCode(am.equation(0).ast())) + self.assertEqual("x = a", Generator_equationCode(am.equation(0).ast())) + if __name__ == '__main__': unittest.main() diff --git a/tests/bindings/python/test_generator_profile.py b/tests/bindings/python/test_generator_profile.py index 5bc16eea5..983b53267 100644 --- a/tests/bindings/python/test_generator_profile.py +++ b/tests/bindings/python/test_generator_profile.py @@ -15,14 +15,19 @@ def test_create_destroy(self): def test_generator_profile(self): from libcellml import GeneratorProfile + from libcellml.generatorprofile import GeneratorProfile_profileAsString # Create a default, i.e. C, profile. p = GeneratorProfile() self.assertEqual(GeneratorProfile.Profile.C, p.profile()) + self.assertEqual("c", GeneratorProfile.profileAsString(p.profile())) + self.assertEqual("c", GeneratorProfile_profileAsString(p.profile())) # Make the profile a Python profile. p.setProfile(GeneratorProfile.Profile.PYTHON) self.assertEqual(GeneratorProfile.Profile.PYTHON, p.profile()) + self.assertEqual("python", GeneratorProfile.profileAsString(p.profile())) + self.assertEqual("python", GeneratorProfile_profileAsString(p.profile())) # Create a Python profile. pp = GeneratorProfile(GeneratorProfile.Profile.PYTHON) @@ -310,14 +315,14 @@ def test_asinh_string(self): g.setAsinhString(GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.asinhString()) - def test_assignment_string(self): + def test_equality_string(self): from libcellml import GeneratorProfile g = GeneratorProfile() - self.assertEqual(' = ', g.assignmentString()) - g.setAssignmentString(GeneratorProfileTestCase.VALUE) - self.assertEqual(GeneratorProfileTestCase.VALUE, g.assignmentString()) + self.assertEqual(' = ', g.equalityString()) + g.setEqualityString(GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.equalityString()) def test_atan_string(self): from libcellml import GeneratorProfile @@ -813,7 +818,7 @@ def test_implementation_create_states_array_method_string(self): g = GeneratorProfile() self.assertEqual( - 'double * createStatesArray()\n{\n return malloc(STATE_COUNT*sizeof(double));\n}\n', + 'double * createStatesArray()\n{\n double *res = (double *) malloc(STATE_COUNT*sizeof(double));\n\n for (size_t i = 0; i < STATE_COUNT; ++i) {\n res[i] = NAN;\n }\n\n return res;\n}\n', g.implementationCreateStatesArrayMethodString()) g.setImplementationCreateStatesArrayMethodString(GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.implementationCreateStatesArrayMethodString()) @@ -824,7 +829,7 @@ def test_implementation_create_variables_array_method_string(self): g = GeneratorProfile() self.assertEqual( - 'double * createVariablesArray()\n{\n return malloc(VARIABLE_COUNT*sizeof(double));\n}\n', + 'double * createVariablesArray()\n{\n double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double));\n\n for (size_t i = 0; i < VARIABLE_COUNT; ++i) {\n res[i] = NAN;\n }\n\n return res;\n}\n', g.implementationCreateVariablesArrayMethodString()) g.setImplementationCreateVariablesArrayMethodString(GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.implementationCreateVariablesArrayMethodString()) @@ -864,12 +869,12 @@ def test_implementation_initialise_constants_method_string(self): g.setImplementationInitialiseVariablesMethodString(False, True, GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.implementationInitialiseVariablesMethodString(False, True)) - self.assertEqual('void initialiseVariables(double *states, double *variables)\n{\n[CODE]}\n', + self.assertEqual('void initialiseVariables(double *states, double *rates, double *variables)\n{\n[CODE]}\n', g.implementationInitialiseVariablesMethodString(True, False)) g.setImplementationInitialiseVariablesMethodString(True, False, GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.implementationInitialiseVariablesMethodString(True, False)) - self.assertEqual('void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable)\n{\n[CODE]}\n', + self.assertEqual('void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable)\n{\n[CODE]}\n', g.implementationInitialiseVariablesMethodString(True, True)) g.setImplementationInitialiseVariablesMethodString(True, True, GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.implementationInitialiseVariablesMethodString(True, True)) @@ -926,7 +931,7 @@ def test_implementation_version_string(self): g = GeneratorProfile() - self.assertEqual('const char VERSION[] = "0.3.0";\n', g.implementationVersionString()) + self.assertEqual('const char VERSION[] = "0.4.0";\n', g.implementationVersionString()) g.setImplementationVersionString(GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.implementationVersionString()) @@ -1073,12 +1078,12 @@ def test_interface_initialise_constants_method_string(self): g.setInterfaceInitialiseVariablesMethodString(False, True, GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.interfaceInitialiseVariablesMethodString(False, True)) - self.assertEqual('void initialiseVariables(double *states, double *variables);\n', + self.assertEqual('void initialiseVariables(double *states, double *rates, double *variables);\n', g.interfaceInitialiseVariablesMethodString(True, False)) g.setInterfaceInitialiseVariablesMethodString(True, False, GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.interfaceInitialiseVariablesMethodString(True, False)) - self.assertEqual('void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable);\n', + self.assertEqual('void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable);\n', g.interfaceInitialiseVariablesMethodString(True, True)) g.setInterfaceInitialiseVariablesMethodString(True, True, GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.interfaceInitialiseVariablesMethodString(True, True)) @@ -1587,7 +1592,7 @@ def test_external_variable_method_type_definition_string(self): self.assertEqual(GeneratorProfileTestCase.VALUE, g.externalVariableMethodTypeDefinitionString(False)) self.assertEqual( - 'typedef double (* ExternalVariable)(double voi, double *states, double *variables, size_t index);\n', + 'typedef double (* ExternalVariable)(double voi, double *states, double *rates, double *variables, size_t index);\n', g.externalVariableMethodTypeDefinitionString(True)) g.setExternalVariableMethodTypeDefinitionString(True, GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.externalVariableMethodTypeDefinitionString(True)) @@ -1602,11 +1607,103 @@ def test_external_variable_method_call_string(self): g.setExternalVariableMethodCallString(False, GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.externalVariableMethodCallString(False)) - self.assertEqual('externalVariable(voi, states, variables, [INDEX])', + self.assertEqual('externalVariable(voi, states, rates, variables, [INDEX])', g.externalVariableMethodCallString(True)) g.setExternalVariableMethodCallString(True, GeneratorProfileTestCase.VALUE) self.assertEqual(GeneratorProfileTestCase.VALUE, g.externalVariableMethodCallString(True)) + def test_root_finding_info_object_string(self): + from libcellml import GeneratorProfile + + g = GeneratorProfile() + + self.assertEqual('typedef struct {\n double *variables;\n} RootFindingInfo;\n', g.rootFindingInfoObjectString(False)) + g.setRootFindingInfoObjectString(False, GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.rootFindingInfoObjectString(False)) + + self.assertEqual('typedef struct {\n double voi;\n double *states;\n double *rates;\n double *variables;\n} RootFindingInfo;\n', g.rootFindingInfoObjectString(True)) + g.setRootFindingInfoObjectString(True, GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.rootFindingInfoObjectString(True)) + + def test_extern_nla_solve_method_string(self): + from libcellml import GeneratorProfile + + g = GeneratorProfile() + + self.assertEqual('extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *),\n double *u, int n, void *data);\n', g.externNlaSolveMethodString()) + g.setExternNlaSolveMethodString(GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.externNlaSolveMethodString()) + + def test_find_root_call_string(self): + from libcellml import GeneratorProfile + + g = GeneratorProfile() + + self.assertEqual('findRoot[INDEX](variables);\n', g.findRootCallString(False)) + g.setFindRootCallString(False, GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.findRootCallString(False)) + + self.assertEqual('findRoot[INDEX](voi, states, rates, variables);\n', g.findRootCallString(True)) + g.setFindRootCallString(True, GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.findRootCallString(True)) + + def test_find_root_method_string(self): + from libcellml import GeneratorProfile + + g = GeneratorProfile() + + self.assertEqual('void findRoot[INDEX](double *variables)\n{\n RootFindingInfo rfi = { variables };\n double u[[SIZE]];\n\n[CODE]}\n', g.findRootMethodString(False)) + g.setFindRootMethodString(False, GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.findRootMethodString(False)) + + self.assertEqual('void findRoot[INDEX](double voi, double *states, double *rates, double *variables)\n{\n RootFindingInfo rfi = { voi, states, rates, variables };\n double u[[SIZE]];\n\n[CODE]}\n', g.findRootMethodString(True)) + g.setFindRootMethodString(True, GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.findRootMethodString(True)) + + def test_nla_solve_call_string(self): + from libcellml import GeneratorProfile + + g = GeneratorProfile() + + self.assertEqual('nlaSolve(objectiveFunction[INDEX], u, [SIZE], &rfi);\n', g.nlaSolveCallString(False)) + g.setNlaSolveCallString(False, GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.nlaSolveCallString(False)) + + self.assertEqual('nlaSolve(objectiveFunction[INDEX], u, [SIZE], &rfi);\n', g.nlaSolveCallString(True)) + g.setNlaSolveCallString(True, GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.nlaSolveCallString(True)) + + def test_objective_function_method_string(self): + from libcellml import GeneratorProfile + + g = GeneratorProfile() + + self.assertEqual('void objectiveFunction[INDEX](double *u, double *f, void *data)\n{\n double *variables = ((RootFindingInfo *) data)->variables;\n\n[CODE]}\n', g.objectiveFunctionMethodString(False)) + g.setObjectiveFunctionMethodString(False, GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.objectiveFunctionMethodString(False)) + + self.assertEqual('void objectiveFunction[INDEX](double *u, double *f, void *data)\n{\n double voi = ((RootFindingInfo *) data)->voi;\n double *states = ((RootFindingInfo *) data)->states;\n double *rates = ((RootFindingInfo *) data)->rates;\n double *variables = ((RootFindingInfo *) data)->variables;\n\n[CODE]}\n', g.objectiveFunctionMethodString(True)) + g.setObjectiveFunctionMethodString(True, GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.objectiveFunctionMethodString(True)) + + def test_u_array_string(self): + from libcellml import GeneratorProfile + + g = GeneratorProfile() + + self.assertEqual('u', g.uArrayString()) + g.setUArrayString(GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.uArrayString()) + + def test_f_array_string(self): + from libcellml import GeneratorProfile + + g = GeneratorProfile() + + self.assertEqual('f', g.fArrayString()) + g.setFArrayString(GeneratorProfileTestCase.VALUE) + self.assertEqual(GeneratorProfileTestCase.VALUE, g.fArrayString()) + def test_voi_string(self): from libcellml import GeneratorProfile diff --git a/tests/bindings/python/test_model.py b/tests/bindings/python/test_model.py index 88a81c7b4..d74ed6b94 100644 --- a/tests/bindings/python/test_model.py +++ b/tests/bindings/python/test_model.py @@ -227,6 +227,20 @@ def test_units_count(self): self.assertEqual(m.unitsCount(), 0) del m + def test_is_defined(self): + from libcellml import Model, Component, Variable, Units + + m = Model() + c = Component() + v = Variable() + u = Units() + + m.addUnits(u) + v.setUnits(u) + c.addVariable(v) + m.addComponent(c) + self.assertTrue(m.isDefined()) + def test_has_unresolved_imports(self): from libcellml import Model, Component, ImportSource diff --git a/tests/bindings/python/test_units.py b/tests/bindings/python/test_units.py index 79d93f22b..b942a8536 100644 --- a/tests/bindings/python/test_units.py +++ b/tests/bindings/python/test_units.py @@ -343,6 +343,17 @@ def test_unit_attributes_single(self): self.assertEqual(1.2, u.unitAttributeExponent(0)) self.assertEqual(3.4, u.unitAttributeMultiplier(0)) + u.setUnitAttributeReference(0, 'arrdee') + self.assertEqual('arrdee', u.unitAttributeReference(0)) + + def test_is_defined(self): + from libcellml import Units + + u = Units("BigVolts") + u.addUnit("volt", 0, 1, 1000) + + self.assertTrue(u.isDefined()) + if __name__ == '__main__': unittest.main() diff --git a/tests/component/component.cpp b/tests/component/component.cpp index 9e020379d..9447d9d6c 100644 --- a/tests/component/component.cpp +++ b/tests/component/component.cpp @@ -153,6 +153,28 @@ TEST(Component, contains) EXPECT_TRUE(c->containsComponent(c21)); } +TEST(Component, containsEncapsulatedComponent) +{ + libcellml::ModelPtr m = createModelWithComponent(); + libcellml::ComponentPtr c = m->component(0); + c->setName("child0"); + libcellml::ComponentPtr c1 = libcellml::Component::create("child1"); + libcellml::ComponentPtr c2 = libcellml::Component::create("child2"); + libcellml::ComponentPtr c3 = libcellml::Component::create("child3"); + libcellml::ComponentPtr c4 = libcellml::Component::create("child4"); + libcellml::ComponentPtr c5 = libcellml::Component::create("child5"); + libcellml::ComponentPtr c6 = libcellml::Component::create("child6"); + + c->addComponent(c1); + c->addComponent(c2); + c1->addComponent(c4); + c1->addComponent(c5); + c1->addComponent(c6); + + EXPECT_FALSE(m->containsComponent("child4", false)); + EXPECT_TRUE(m->containsComponent(c4, true)); +} + TEST(Component, addChildrenAndSerialise) { const std::string e1 = @@ -287,6 +309,30 @@ TEST(Component, removeComponentMethods) EXPECT_EQ(size_t(0), c->componentCount()); } +TEST(Component, removeEncapsulatedComponent) +{ + libcellml::ModelPtr m = createModelWithComponent(); + libcellml::ComponentPtr c = m->component(0); + c->setName("child0"); + libcellml::ComponentPtr c1 = libcellml::Component::create("child1"); + libcellml::ComponentPtr c2 = libcellml::Component::create("child2"); + libcellml::ComponentPtr c3 = libcellml::Component::create("child3"); + libcellml::ComponentPtr c4 = libcellml::Component::create("child4"); + libcellml::ComponentPtr c5 = libcellml::Component::create("child5"); + libcellml::ComponentPtr c6 = libcellml::Component::create("child6"); + + c->addComponent(c1); + c->addComponent(c2); + c1->addComponent(c4); + c1->addComponent(c5); + c1->addComponent(c6); + + EXPECT_FALSE(m->removeComponent("child4", false)); + EXPECT_TRUE(m->removeComponent("child4", true)); + EXPECT_FALSE(m->removeComponent(c5, false)); + EXPECT_TRUE(m->removeComponent(c5, true)); +} + TEST(Component, componentMethods) { const std::string e1 = @@ -357,6 +403,8 @@ TEST(Component, componentMethods) libcellml::ComponentPtr cSn = c->component("gus"); EXPECT_EQ("gus", cSn->name()); + EXPECT_EQ(nullptr, c->component("child1", false)); + a = printer->printModel(m); EXPECT_EQ(e2, a); } @@ -396,6 +444,28 @@ TEST(Component, takeComponentMethods) EXPECT_EQ(e, a); } +TEST(Component, takeEncapsulatedComponent) +{ + libcellml::ModelPtr m = createModelWithComponent(); + libcellml::ComponentPtr c = m->component(0); + c->setName("child0"); + libcellml::ComponentPtr c1 = libcellml::Component::create("child1"); + libcellml::ComponentPtr c2 = libcellml::Component::create("child2"); + libcellml::ComponentPtr c3 = libcellml::Component::create("child3"); + libcellml::ComponentPtr c4 = libcellml::Component::create("child4"); + libcellml::ComponentPtr c5 = libcellml::Component::create("child5"); + libcellml::ComponentPtr c6 = libcellml::Component::create("child6"); + + c->addComponent(c1); + c->addComponent(c2); + c1->addComponent(c4); + c1->addComponent(c5); + c1->addComponent(c6); + + EXPECT_EQ(nullptr, m->takeComponent("child4", false)); + EXPECT_EQ(c4, m->takeComponent("child4", true)); +} + TEST(Component, addComponentMultipleTimes) { auto model = libcellml::Model::create("model"); @@ -493,6 +563,31 @@ TEST(Component, replaceComponentMethods) EXPECT_EQ(e_after, a); } +TEST(Component, replaceEncapsulatedComponent) +{ + libcellml::ModelPtr m = createModelWithComponent(); + libcellml::ComponentPtr c = m->component(0); + c->setName("child0"); + libcellml::ComponentPtr c1 = libcellml::Component::create("child1"); + libcellml::ComponentPtr c2 = libcellml::Component::create("child2"); + libcellml::ComponentPtr c3 = libcellml::Component::create("child3"); + libcellml::ComponentPtr c4 = libcellml::Component::create("child4"); + libcellml::ComponentPtr c5 = libcellml::Component::create("child5"); + libcellml::ComponentPtr c6 = libcellml::Component::create("child6"); + + c->addComponent(c1); + c->addComponent(c2); + c1->addComponent(c4); + c1->addComponent(c5); + c1->addComponent(c6); + + EXPECT_FALSE(m->replaceComponent("child4", c3, false)); + EXPECT_FALSE(m->replaceComponent(c4, c3, false)); + + EXPECT_TRUE(m->replaceComponent("child4", c3)); + EXPECT_TRUE(m->replaceComponent(c6, c4)); +} + TEST(Component, constructors) { const std::string e = @@ -604,3 +699,44 @@ TEST(Component, preventSegfaultInAddSomething) EXPECT_FALSE(model->addComponent(nullptr)); EXPECT_FALSE(model->addUnits(nullptr)); } + +TEST(Component, isDefined) +{ + libcellml::ComponentPtr c = libcellml::Component::create("a_component"); + + EXPECT_TRUE(c->isDefined()); +} + +TEST(Component, isNotDefinedWithUndefinedUnits) +{ + libcellml::ComponentPtr c = libcellml::Component::create("a_component"); + libcellml::VariablePtr v = libcellml::Variable::create("a_variable"); + libcellml::UnitsPtr u = libcellml::Units::create("improper_units"); + u->addUnit("battle"); + + c->addVariable(v); + v->setUnits(u); + + EXPECT_FALSE(c->isDefined()); +} + +TEST(Component, definedComponentImport) +{ + libcellml::ComponentPtr c = libcellml::Component::create("a_component"); + libcellml::ComponentPtr importComponent = libcellml::Component::create("import_component"); + libcellml::VariablePtr v = libcellml::Variable::create("a_variable"); + libcellml::UnitsPtr u = libcellml::Units::create("only_standard_units"); + + libcellml::ImportSourcePtr importSource = libcellml::ImportSource::create(); + importSource->setUrl("I_am_a_url"); + + importComponent->setImportSource(importSource); + importComponent->setImportReference("ref"); + + importComponent->addVariable(v); + v->setUnits(u); + + c->addComponent(importComponent); + + EXPECT_FALSE(c->isDefined()); +} diff --git a/tests/connection/connection.cpp b/tests/connection/connection.cpp index a876efa70..653c4052b 100644 --- a/tests/connection/connection.cpp +++ b/tests/connection/connection.cpp @@ -609,6 +609,70 @@ TEST(Connection, removeEquivalentVariableMethods) EXPECT_EQ(e3, a); } +TEST(Connection, setMappingIdForConnection) +{ + libcellml::ModelPtr m = libcellml::Model::create(); + libcellml::ComponentPtr comp1 = libcellml::Component::create(); + libcellml::ComponentPtr comp2 = libcellml::Component::create(); + libcellml::VariablePtr v1 = libcellml::Variable::create(); + libcellml::VariablePtr v2 = libcellml::Variable::create(); + comp1->setName("component1"); + comp2->setName("component2"); + v1->setName("variable1"); + v2->setName("variable2"); + + comp1->addVariable(v1); + comp2->addVariable(v2); + m->addComponent(comp1); + m->addComponent(comp2); + + libcellml::Variable::setEquivalenceMappingId(v1, v2, "mappingId"); + EXPECT_EQ("", libcellml::Variable::equivalenceMappingId(v1, v2)); + libcellml::Variable::setEquivalenceMappingId(v1, nullptr, "mappingId"); + EXPECT_EQ("", libcellml::Variable::equivalenceMappingId(v1, nullptr)); + libcellml::Variable::setEquivalenceMappingId(nullptr, v2, "mappingId"); + EXPECT_EQ("", libcellml::Variable::equivalenceMappingId(nullptr, v2)); + libcellml::Variable::setEquivalenceMappingId(nullptr, nullptr, "mappingId"); + EXPECT_EQ("", libcellml::Variable::equivalenceMappingId(nullptr, nullptr)); + + libcellml::Variable::addEquivalence(v1, v2); + + libcellml::Variable::setEquivalenceMappingId(v1, v2, "mappingId"); + EXPECT_EQ("mappingId", libcellml::Variable::equivalenceMappingId(v1, v2)); +} + +TEST(Connection, setConnectionIdForConnection) +{ + libcellml::ModelPtr m = libcellml::Model::create(); + libcellml::ComponentPtr comp1 = libcellml::Component::create(); + libcellml::ComponentPtr comp2 = libcellml::Component::create(); + libcellml::VariablePtr v1 = libcellml::Variable::create(); + libcellml::VariablePtr v2 = libcellml::Variable::create(); + comp1->setName("component1"); + comp2->setName("component2"); + v1->setName("variable1"); + v2->setName("variable2"); + + comp1->addVariable(v1); + comp2->addVariable(v2); + m->addComponent(comp1); + m->addComponent(comp2); + + libcellml::Variable::setEquivalenceConnectionId(v1, v2, "mappingId"); + EXPECT_EQ("", libcellml::Variable::equivalenceConnectionId(v1, v2)); + libcellml::Variable::setEquivalenceConnectionId(v1, nullptr, "mappingId"); + EXPECT_EQ("", libcellml::Variable::equivalenceConnectionId(v1, nullptr)); + libcellml::Variable::setEquivalenceConnectionId(nullptr, v2, "mappingId"); + EXPECT_EQ("", libcellml::Variable::equivalenceConnectionId(nullptr, v2)); + libcellml::Variable::setEquivalenceConnectionId(nullptr, nullptr, "mappingId"); + EXPECT_EQ("", libcellml::Variable::equivalenceConnectionId(nullptr, nullptr)); + + libcellml::Variable::addEquivalence(v1, v2); + + libcellml::Variable::setEquivalenceMappingId(v1, v2, "mappingId"); + EXPECT_EQ("mappingId", libcellml::Variable::equivalenceMappingId(v1, v2)); +} + TEST(Connection, removeConnectionIdFromConnection) { const std::string eWithConnectionId = @@ -664,6 +728,17 @@ TEST(Connection, removeConnectionIdFromConnection) a = printer->printModel(m); EXPECT_EQ(eWithOutConnectionId, a); + + libcellml::Variable::removeEquivalence(v1, v2); + + libcellml::Variable::removeEquivalenceConnectionId(v1, v2); + EXPECT_EQ("", libcellml::Variable::equivalenceConnectionId(v1, v2)); + libcellml::Variable::removeEquivalenceConnectionId(v1, nullptr); + EXPECT_EQ("", libcellml::Variable::equivalenceConnectionId(v1, nullptr)); + libcellml::Variable::removeEquivalenceConnectionId(nullptr, v2); + EXPECT_EQ("", libcellml::Variable::equivalenceConnectionId(nullptr, v2)); + libcellml::Variable::removeEquivalenceConnectionId(nullptr, nullptr); + EXPECT_EQ("", libcellml::Variable::equivalenceConnectionId(nullptr, nullptr)); } TEST(Connection, removeMappingIdFromConnection) @@ -721,6 +796,17 @@ TEST(Connection, removeMappingIdFromConnection) a = printer->printModel(m); EXPECT_EQ(eWithOutMappingId, a); + + libcellml::Variable::removeEquivalence(v1, v2); + + libcellml::Variable::removeEquivalenceMappingId(v1, v2); + EXPECT_EQ("", libcellml::Variable::equivalenceMappingId(v1, v2)); + libcellml::Variable::removeEquivalenceMappingId(v1, nullptr); + EXPECT_EQ("", libcellml::Variable::equivalenceMappingId(v1, nullptr)); + libcellml::Variable::removeEquivalenceMappingId(nullptr, v2); + EXPECT_EQ("", libcellml::Variable::equivalenceMappingId(nullptr, v2)); + libcellml::Variable::removeEquivalenceMappingId(nullptr, nullptr); + EXPECT_EQ("", libcellml::Variable::equivalenceMappingId(nullptr, nullptr)); } TEST(Connection, removeVariablesFromConnections) diff --git a/tests/coverage/coverage.cpp b/tests/coverage/coverage.cpp index 4d2d62b7a..811dd9ead 100644 --- a/tests/coverage/coverage.cpp +++ b/tests/coverage/coverage.cpp @@ -86,7 +86,7 @@ TEST(Coverage, entityHasParent) EXPECT_FALSE(c3->hasParent()); } -TEST(Annotator, automaticIdsUndefined) +TEST(AnnotatorCoverage, automaticIdsUndefined) { auto annotator = libcellml::Annotator::create(); auto model = libcellml::Model::create(); @@ -101,9 +101,26 @@ TEST(Annotator, automaticIdsUndefined) TEST(Coverage, unitsItem) { - auto unitsItem = libcellml::UnitsItem::create(nullptr, 0); + auto units = libcellml::Units::create("units"); + units->addUnit("second"); - EXPECT_FALSE(unitsItem->isValid()); + auto unitsItemValid = libcellml::UnitsItem::create(units, 0); + auto unitsItemInvalid = libcellml::UnitsItem::create(nullptr, 0); + + EXPECT_TRUE(unitsItemValid->isValid()); + EXPECT_FALSE(unitsItemInvalid->isValid()); +} + +TEST(Coverage, variablePair) +{ + auto v = libcellml::Variable::create("var"); + auto variablePair1 = libcellml::VariablePair::create(nullptr, v); + auto variablePair2 = libcellml::VariablePair::create(v, nullptr); + auto variablePair3 = libcellml::VariablePair::create(v, v); + + EXPECT_FALSE(variablePair1->isValid()); + EXPECT_FALSE(variablePair2->isValid()); + EXPECT_TRUE(variablePair3->isValid()); } TEST(Coverage, parserBranchesCellml10RelationshipRef) @@ -175,3 +192,821 @@ TEST(Coverage, strictParsingWithNonXmlModel) EXPECT_EQ(size_t(2), parser->issueCount()); } + +TEST(Coverage, sha1) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/algebraic_eqn_const_var_on_rhs/model.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); + + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(model); + + EXPECT_EQ(size_t(0), analyser->errorCount()); + + auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); + auto generatorProfile = libcellml::GeneratorProfile::create(); + + generator->setModel(analyserModel); + generator->setProfile(generatorProfile); + + std::string xs = {}; + + for (int i = 0; i < 64; ++i) { + xs += "x"; + // Note: the x's eventually ensure 100% coverage in our SHA-1 utility. + + generatorProfile->setVoiString(xs); + + generator->implementationCode(); + } +} + +TEST(ImporterCoverage, importingComponentWithCnUnitsThatAreEmpty) +{ + const std::vector expectedIssues = { + "Imported component 'c' is not valid because:\n" + " -> Component 'c' importing 'myComponent' from 'not_required_resolving_import_manually' has an error:\n" + " - Variable 'a' in component 'myComponent' does not have a valid units attribute. The attribute given is ''. CellML identifiers must contain one or more basic Latin alphabetic characters.", + "Imported component 'c' is not valid because:\n" + " -> Component 'c' importing 'myComponent' from 'not_required_resolving_import_manually' has an error:\n" + " - Math cn element with the value '1' does not have a valid cellml:units attribute. CellML identifiers must contain one or more basic Latin alphabetic characters.", + "Imported component 'c' is not valid because:\n" + " -> Component 'c' importing 'myComponent' from 'not_required_resolving_import_manually' has an error:\n" + " - W3C MathML DTD error: No declaration for attribute bobs of element cn.", + "Units '' does not have a valid name attribute. CellML identifiers must contain one or more basic Latin alphabetic characters.", + }; + + const std::string in = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " " + " \n" + " a\n" + " 1\n" + " \n" + " \n" + " \n" + ""; + + // Create the model by parsing the string above. + auto parser = libcellml::Parser::create(); + auto importedModel = parser->parseModel(in); + auto importer = libcellml::Importer::create(); + auto validator = libcellml::Validator::create(); + + auto model = libcellml::Model::create("myModel"); + auto u = libcellml::Units::create(""); + u->addUnit("metre"); + model->addUnits(u); + + auto c = libcellml::Component::create("c"); + + auto importSource = libcellml::ImportSource::create(); + importSource->setUrl("not_required_resolving_import_manually"); + importSource->setModel(importedModel); + + c->setImportReference("myComponent"); + c->setImportSource(importSource); + model->addComponent(c); + + EXPECT_FALSE(model->hasUnresolvedImports()); + + validator->validateModel(model); + EXPECT_EQ(size_t(4), validator->errorCount()); + expectEqualIssues(expectedIssues, validator); + + model = importer->flattenModel(model); + + validator->validateModel(model); + EXPECT_EQ(size_t(1), validator->errorCount()); + EXPECT_EQ("The model is null.", validator->error(0)->description()); +} + +TEST(ImporterCoverage, importingComponentWithCnUnitsThatReferenceEmptyNamedUnits) +{ + const std::vector expectedIssuesModel = { + "Imported component 'c' is not valid because:\n" + " -> Component 'c' importing 'myComponent' from 'not_required_resolving_import_manually' has an error:\n" + " - Variable 'a' in component 'myComponent' does not have a valid units attribute. The attribute given is ''. CellML identifiers must contain one or more basic Latin alphabetic characters.", + "Imported component 'c' is not valid because:\n" + " -> Component 'c' importing 'myComponent' from 'not_required_resolving_import_manually' has an error:\n" + " - Math cn element with the value '1' does not have a valid cellml:units attribute. CellML identifiers must contain one or more basic Latin alphabetic characters.", + "Imported component 'c' is not valid because:\n" + " -> Component 'c' importing 'myComponent' from 'not_required_resolving_import_manually' has an error:\n" + " - W3C MathML DTD error: No declaration for attribute unuts of element cn.", + }; + + const std::vector expectedIssuesFLatModel = { + "Math cn element with the value '1' does not have a valid cellml:units attribute. CellML identifiers must contain one or more basic Latin alphabetic characters.", + "W3C MathML DTD error: No declaration for attribute unuts of element cn.", + }; + + const std::string in = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " " + " \n" + " a\n" + " 1\n" + " \n" + " \n" + " \n" + ""; + + // Create the model by parsing the string above. + auto parser = libcellml::Parser::create(); + auto importedModel = parser->parseModel(in); + auto importer = libcellml::Importer::create(); + auto validator = libcellml::Validator::create(); + + auto model = libcellml::Model::create("myModel"); + auto u = libcellml::Units::create("mm"); + u->addUnit("metre", "milli"); + model->addUnits(u); + + auto c = libcellml::Component::create("c"); + + auto importSource = libcellml::ImportSource::create(); + importSource->setUrl("not_required_resolving_import_manually"); + importSource->setModel(importedModel); + + c->setImportReference("myComponent"); + c->setImportSource(importSource); + model->addComponent(c); + + EXPECT_FALSE(model->hasUnresolvedImports()); + + validator->validateModel(model); + EXPECT_EQ(size_t(3), validator->errorCount()); + expectEqualIssues(expectedIssuesModel, validator); + + model = importer->flattenModel(model); + + validator->validateModel(model); + EXPECT_EQ(size_t(2), validator->errorCount()); + expectEqualIssues(expectedIssuesFLatModel, validator); +} + +TEST(Coverage, analyser) +{ + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(nullptr); + + EXPECT_EQ(size_t(1), analyser->issueCount()); + + auto analyserModel = analyser->model(); + + EXPECT_FALSE(analyserModel->isValid()); + + EXPECT_EQ(libcellml::AnalyserModel::Type::UNKNOWN, analyserModel->type()); + EXPECT_EQ("unknown", libcellml::AnalyserModel::typeAsString(analyserModel->type())); + + EXPECT_EQ(nullptr, analyserModel->voi()); + + EXPECT_FALSE(analyserModel->hasExternalVariables()); + + EXPECT_EQ(size_t(0), analyserModel->stateCount()); + EXPECT_EQ(size_t(0), analyserModel->states().size()); + EXPECT_EQ(nullptr, analyserModel->state(0)); + + EXPECT_EQ(size_t(0), analyserModel->variableCount()); + EXPECT_EQ(size_t(0), analyserModel->variables().size()); + EXPECT_EQ(nullptr, analyserModel->variable(0)); + + EXPECT_EQ(size_t(0), analyserModel->equationCount()); + EXPECT_EQ(size_t(0), analyserModel->equations().size()); + EXPECT_EQ(nullptr, analyserModel->equation(0)); + + EXPECT_FALSE(analyserModel->needEqFunction()); + EXPECT_FALSE(analyserModel->needNeqFunction()); + EXPECT_FALSE(analyserModel->needLtFunction()); + EXPECT_FALSE(analyserModel->needLeqFunction()); + EXPECT_FALSE(analyserModel->needGtFunction()); + EXPECT_FALSE(analyserModel->needGeqFunction()); + EXPECT_FALSE(analyserModel->needAndFunction()); + EXPECT_FALSE(analyserModel->needOrFunction()); + EXPECT_FALSE(analyserModel->needXorFunction()); + EXPECT_FALSE(analyserModel->needNotFunction()); + EXPECT_FALSE(analyserModel->needMinFunction()); + EXPECT_FALSE(analyserModel->needMaxFunction()); + EXPECT_FALSE(analyserModel->needSecFunction()); + EXPECT_FALSE(analyserModel->needCscFunction()); + EXPECT_FALSE(analyserModel->needCotFunction()); + EXPECT_FALSE(analyserModel->needSechFunction()); + EXPECT_FALSE(analyserModel->needCschFunction()); + EXPECT_FALSE(analyserModel->needCothFunction()); + EXPECT_FALSE(analyserModel->needAsecFunction()); + EXPECT_FALSE(analyserModel->needAcscFunction()); + EXPECT_FALSE(analyserModel->needAcotFunction()); + EXPECT_FALSE(analyserModel->needAsechFunction()); + EXPECT_FALSE(analyserModel->needAcschFunction()); + EXPECT_FALSE(analyserModel->needAcothFunction()); + + auto ast = libcellml::AnalyserEquationAst::create(); + + EXPECT_NE(nullptr, ast); + + ast->setType(libcellml::AnalyserEquationAst::Type::EQUALITY); + ast->setValue({}); + ast->setVariable(libcellml::Variable::create()); + ast->setParent(libcellml::AnalyserEquationAst::create()); + + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("coverage/analyser.cellml")); + + analyser->analyseModel(model); +} + +TEST(Coverage, analyserConvertToInt) +{ + auto analyser = libcellml::Analyser::create(); + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("coverage/converttoint.cellml")); + + analyser->analyseModel(model); +} + +TEST(Coverage, analyserConvertToDouble) +{ + auto analyser = libcellml::Analyser::create(); + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("coverage/converttodouble.cellml")); + + analyser->analyseModel(model); +} + +TEST(Coverage, analyserExternalVariable) +{ + auto externalVariable = libcellml::AnalyserExternalVariable::create(nullptr); + + EXPECT_EQ(nullptr, externalVariable->variable()); + EXPECT_EQ(false, externalVariable->addDependency(nullptr)); + + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.cellml")); + auto other_model = parser->parseModel(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.cellml")); + + externalVariable = libcellml::AnalyserExternalVariable::create(model->component("membrane")->variable("V")); + + externalVariable->addDependency(model->component("membrane")->variable("Cm")); + + EXPECT_EQ(false, externalVariable->removeDependency(nullptr, "membrane", "Cm")); + EXPECT_EQ(false, externalVariable->removeDependency(model, "not_membrane", "Cm")); +} + +TEST(Coverage, analyserTypes) +{ + auto analyser = libcellml::Analyser::create(); + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.cellml")); + + analyser->analyseModel(model); + + auto analyserModel = analyser->model(); + + EXPECT_EQ("algebraic", libcellml::AnalyserEquation::typeAsString(analyserModel->equation(0)->type())); + EXPECT_EQ("algebraic", libcellml::AnalyserVariable::typeAsString(analyserModel->variable(0)->type())); +} + +void checkAstTypeAsString(const libcellml::AnalyserEquationAstPtr &ast) +{ + if (ast != nullptr) { + libcellml::AnalyserEquationAst::typeAsString(ast->type()); + + checkAstTypeAsString(ast->leftChild()); + checkAstTypeAsString(ast->rightChild()); + } +} + +TEST(Coverage, generator) +{ + static const std::string EMPTY_STRING; + + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("coverage/generator/model.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); + + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(model); + + EXPECT_EQ(size_t(0), analyser->errorCount()); + + auto analyserModel = analyser->model(); + + EXPECT_EQ(libcellml::AnalyserModel::Type::DAE, analyserModel->type()); + EXPECT_EQ("dae", libcellml::AnalyserModel::typeAsString(analyserModel->type())); + + EXPECT_EQ(size_t(1), analyserModel->stateCount()); + EXPECT_EQ(size_t(209), analyserModel->variableCount()); + EXPECT_EQ(size_t(203), analyserModel->equationCount()); + + EXPECT_NE(nullptr, analyserModel->voi()); + EXPECT_EQ(size_t(0), analyserModel->voi()->equationCount()); + EXPECT_EQ(size_t(0), analyserModel->voi()->equations().size()); + EXPECT_EQ(nullptr, analyserModel->voi()->equation(0)); + EXPECT_NE(nullptr, analyserModel->state(0)); + EXPECT_NE(size_t(0), analyserModel->state(0)->equationCount()); + EXPECT_NE(size_t(0), analyserModel->state(0)->equations().size()); + EXPECT_NE(nullptr, analyserModel->state(0)->equation(0)); + EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); + EXPECT_NE(nullptr, analyserModel->variable(0)); + EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); + EXPECT_NE(nullptr, analyserModel->equation(199)); + EXPECT_NE(size_t(0), analyserModel->equation(199)->dependencyCount()); + EXPECT_NE(size_t(0), analyserModel->equation(199)->dependencies().size()); + EXPECT_NE(nullptr, analyserModel->equation(199)->dependency(0)); + EXPECT_EQ(nullptr, analyserModel->equation(199)->dependency(analyserModel->equation(199)->dependencyCount())); + EXPECT_EQ(size_t(1), analyserModel->equation(199)->nlaSiblingCount()); + EXPECT_EQ(size_t(1), analyserModel->equation(199)->nlaSiblings().size()); + EXPECT_NE(nullptr, analyserModel->equation(199)->nlaSibling(0)); + EXPECT_EQ(nullptr, analyserModel->equation(199)->nlaSibling(analyserModel->equation(199)->nlaSiblingCount())); + EXPECT_NE(size_t(0), analyserModel->equation(199)->variableCount()); + EXPECT_NE(size_t(0), analyserModel->equation(199)->variables().size()); + EXPECT_NE(nullptr, analyserModel->equation(199)->variable(0)); + EXPECT_EQ(nullptr, analyserModel->equation(199)->variable(analyserModel->equation(199)->variableCount())); + EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); + + for (const auto &equation : analyserModel->equations()) { + checkAstTypeAsString(equation->ast()); + } + + auto generator = libcellml::Generator::create(); + + EXPECT_EQ(nullptr, analyserModel->voi()->initialisingVariable()); + + for (size_t i = 0; i < analyserModel->stateCount(); ++i) { + EXPECT_NE(nullptr, analyserModel->state(i)->initialisingVariable()); + } + + for (size_t i = 0; i < analyserModel->variableCount(); ++i) { + if ((i == 1) || (i == 2) || (i == 6) || (i == 18) || (i == 179) || (i == 180) || (i == 182) || (i == 205) || (i == 206)) { + EXPECT_TRUE(analyserModel->variable(i)->initialisingVariable() != nullptr); + } + } + + EXPECT_EQ(nullptr, generator->model()); + EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); + EXPECT_EQ(EMPTY_STRING, generator->implementationCode()); + + generator->setModel(analyserModel); + + EXPECT_EQ(analyserModel, generator->model()); + EXPECT_EQ(fileContents("coverage/generator/model.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("coverage/generator/model.c"), generator->implementationCode()); + + auto profile = generator->profile(); + + profile->setInterfaceCreateStatesArrayMethodString("double * createStatesVector();\n"); + profile->setImplementationCreateStatesArrayMethodString("double * createStatesVector()\n" + "{\n" + " double *res = (double *) malloc(STATE_COUNT*sizeof(double));\n" + "\n" + " for (size_t i = 0; i < STATE_COUNT; ++i) {\n" + " res[i] = NAN;\n" + " }\n" + "\n" + " return res;\n" + "}\n"); + + EXPECT_EQ(fileContents("coverage/generator/model.modified.profile.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("coverage/generator/model.modified.profile.c"), generator->implementationCode()); + + profile = libcellml::GeneratorProfile::create(); + + generator->setProfile(profile); + + profile->setHasInterface(false); + + profile->setXorString("^"); + profile->setHasXorOperator(true); + + profile->setPowerString("^^"); + profile->setSquareString("sqr"); + profile->setHasPowerOperator(true); + + profile->setPiecewiseIfString("piecewise([CONDITION], [IF_STATEMENT]"); + profile->setPiecewiseElseString(", [ELSE_STATEMENT])"); + profile->setHasConditionalOperator(false); + + profile->setInterfaceFileNameString("customheaderfile.h"); + + profile->setImplementationHeaderString("#include \"[INTERFACE_FILE_NAME]\"\n"); + + profile->setImplementationVersionString(""); + + profile->setImplementationLibcellmlVersionString(""); + + profile->setImplementationStateCountString(""); + + profile->setImplementationVariableCountString(""); + + profile->setVariableTypeObjectString(false, false, ""); + profile->setVariableTypeObjectString(false, true, ""); + profile->setVariableTypeObjectString(true, false, ""); + profile->setVariableTypeObjectString(true, true, ""); + + profile->setVariableOfIntegrationVariableTypeString(""); + profile->setStateVariableTypeString(""); + profile->setConstantVariableTypeString(""); + profile->setComputedConstantVariableTypeString(""); + profile->setAlgebraicVariableTypeString(""); + profile->setExternalVariableTypeString(""); + + profile->setVariableInfoObjectString(""); + + profile->setImplementationVoiInfoString(""); + + profile->setImplementationStateInfoString(""); + + profile->setImplementationVariableInfoString(""); + + profile->setVariableInfoEntryString(""); + + profile->setImplementationCreateStatesArrayMethodString(""); + + profile->setImplementationCreateVariablesArrayMethodString(""); + + profile->setImplementationDeleteArrayMethodString(""); + + profile->setImplementationComputeVariablesMethodString(false, false, ""); + profile->setImplementationComputeVariablesMethodString(false, true, ""); + profile->setImplementationComputeVariablesMethodString(true, false, ""); + profile->setImplementationComputeVariablesMethodString(true, true, ""); + + EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); + EXPECT_EQ(fileContents("coverage/generator/model.out"), generator->implementationCode()); + + profile = libcellml::GeneratorProfile::create(); + + generator->setProfile(profile); + + profile->setHasInterface(true); + + profile->setEqString("eq"); + profile->setNeqString("neq"); + profile->setLtString("lt"); + profile->setLeqString("leq"); + profile->setGtString("gt"); + profile->setGeqString("geq"); + profile->setAndString("and"); + profile->setOrString("or"); + profile->setNotString("not"); + + profile->setHasEqOperator(false); + profile->setHasNeqOperator(false); + profile->setHasLtOperator(false); + profile->setHasLeqOperator(false); + profile->setHasGtOperator(false); + profile->setHasGeqOperator(false); + profile->setHasAndOperator(false); + profile->setHasOrOperator(false); + profile->setHasNotOperator(false); + + profile->setImplementationHeaderString(""); + + profile->setInterfaceVersionString(""); + profile->setImplementationVersionString(""); + + profile->setInterfaceLibcellmlVersionString(""); + profile->setImplementationLibcellmlVersionString(""); + + profile->setInterfaceStateCountString(""); + profile->setImplementationStateCountString(""); + + profile->setInterfaceVariableCountString(""); + profile->setImplementationVariableCountString(""); + + profile->setVariableTypeObjectString(false, false, ""); + profile->setVariableTypeObjectString(false, true, ""); + profile->setVariableTypeObjectString(true, false, ""); + profile->setVariableTypeObjectString(true, true, ""); + + profile->setVariableOfIntegrationVariableTypeString(""); + profile->setStateVariableTypeString(""); + profile->setConstantVariableTypeString(""); + profile->setComputedConstantVariableTypeString(""); + profile->setAlgebraicVariableTypeString(""); + profile->setExternalVariableTypeString(""); + + profile->setVariableInfoObjectString(""); + + profile->setInterfaceVoiInfoString(""); + profile->setImplementationVoiInfoString(""); + + profile->setInterfaceStateInfoString(""); + profile->setImplementationStateInfoString(""); + + profile->setInterfaceVariableInfoString(""); + profile->setImplementationVariableInfoString(""); + + profile->setVariableInfoEntryString(""); + + EXPECT_EQ(fileContents("coverage/generator/model.interface.out"), generator->interfaceCode()); + EXPECT_EQ(fileContents("coverage/generator/model.implementation.out"), generator->implementationCode()); + + profile->setProfile(libcellml::GeneratorProfile::Profile::PYTHON); + + EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); + EXPECT_EQ(fileContents("coverage/generator/model.py"), generator->implementationCode()); + + profile->setImplementationCreateStatesArrayMethodString("\n" + "def create_states_vector():\n" + " return [nan]*STATE_COUNT\n"); + + EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); + EXPECT_EQ(fileContents("coverage/generator/model.modified.profile.py"), generator->implementationCode()); + + // Coverage for the case where mProfile is equal to nullptr in Generator. + + generator->setProfile(nullptr); + + generator->interfaceCode(); + generator->implementationCode(); + + // Coverage for various profile settings. + + analyser->addExternalVariable(libcellml::AnalyserExternalVariable::create(model->component("my_component")->variable("eqnEq"))); + + analyser->analyseModel(model); + + generator->setModel(analyser->model()); + generator->setProfile(profile); + + profile->setAcotFunctionString(""); + profile->setAcothFunctionString(""); + profile->setAcscFunctionString(""); + profile->setAcschFunctionString(""); + profile->setAsecFunctionString(""); + profile->setAsechFunctionString(""); + profile->setCommentString(""); + profile->setCotFunctionString(""); + profile->setCothFunctionString(""); + profile->setCscFunctionString(""); + profile->setCschFunctionString(""); + profile->setExternalVariableMethodTypeDefinitionString(true, ""); + profile->setHasConditionalOperator(true); + profile->setHasInterface(true); + profile->setHasPowerOperator(true); + profile->setHasXorOperator(true); + profile->setImplementationComputeComputedConstantsMethodString(""); + profile->setImplementationComputeRatesMethodString(true, ""); + profile->setImplementationHeaderString("[INTERFACE_FILE_NAME]"); + profile->setImplementationInitialiseVariablesMethodString(true, true, ""); + profile->setInterfaceFileNameString(""); + profile->setInterfaceHeaderString(""); + profile->setMaxFunctionString(""); + profile->setMinFunctionString(""); + profile->setObjectiveFunctionMethodString(false, ""); + profile->setObjectiveFunctionMethodString(true, ""); + profile->setSecFunctionString(""); + profile->setSechFunctionString(""); + profile->setVariableInfoEntryString(""); + + generator->interfaceCode(); + generator->implementationCode(); + + profile->setArrayElementSeparatorString(""); + profile->setCommentString("xxx"); + profile->setFindRootMethodString(false, ""); + profile->setFindRootMethodString(true, ""); + profile->setObjectiveFunctionMethodString(false, "xxx"); + profile->setObjectiveFunctionMethodString(true, "xxx"); + profile->setOriginCommentString(""); + profile->setVariableInfoEntryString("xxx"); + + generator->implementationCode(); + + profile->setArrayElementSeparatorString("xxx"); + profile->setExternNlaSolveMethodString(""); + profile->setFindRootMethodString(false, "xxx"); + profile->setFindRootMethodString(true, "xxx"); + profile->setFindRootCallString(false, ""); + profile->setFindRootCallString(true, ""); + profile->setNlaSolveCallString(false, ""); + profile->setNlaSolveCallString(true, ""); + profile->setVariableOfIntegrationVariableTypeString(""); + + generator->implementationCode(); + + profile->setStateVariableTypeString(""); + profile->setVariableOfIntegrationVariableTypeString("xxx"); + + generator->implementationCode(); + + profile->setConstantVariableTypeString(""); + profile->setStateVariableTypeString("xxx"); + + generator->implementationCode(); + + profile->setComputedConstantVariableTypeString(""); + profile->setConstantVariableTypeString("xxx"); + + generator->implementationCode(); + + profile->setComputedConstantVariableTypeString("xxx"); + profile->setAlgebraicVariableTypeString(""); + + generator->implementationCode(); + + profile->setAlgebraicVariableTypeString("xxx"); + profile->setExternalVariableTypeString(""); + + generator->implementationCode(); + + profile->setHasXorOperator(false); + profile->setXorFunctionString(""); + + generator->implementationCode(); + + libcellml::Generator::equationCode(analyser->model()->equation(0)->ast()); +} + +TEST(CoverageValidator, degreeElementWithOneSibling) +{ + const std::string math = + "\n" + " \n" + " \n" + " n\n" + " \n" + "\n"; + + auto parser = libcellml::Parser::create(); + auto model = libcellml::Model::create("degree"); + + auto component = libcellml::Component::create("c"); + auto variable = libcellml::Variable::create("n"); + variable->setUnits("second"); + component->addVariable(variable); + component->appendMath(math); + + model->addComponent(component); + + auto validator = libcellml::Validator::create(); + + validator->validateModel(model); + EXPECT_EQ(size_t(0), validator->errorCount()); +} + +TEST(CoverageValidator, invalidXmlIds) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("coverage/invalidxmlids.cellml")); + + auto validator = libcellml::Validator::create(); + + validator->validateModel(model); + EXPECT_EQ(size_t(1), validator->errorCount()); + EXPECT_EQ("Units 'bob8' does not have a valid 'id' attribute, '\xF3\xBF\xBF\xBFid'.", validator->error(0)->description()); +} + +TEST(CoverageValidator, componentMathWithRepeatedVariableNames) +{ + const std::vector expectedIssues = { + "Component 'componentName' contains multiple variables with the name 'A'. Valid variable names must be unique to their component.", + "MathML ci element has the child text 'C' which does not correspond with any variable names present in component 'componentName'.", + "Math has a 'ci' element with no identifier as a child.", + }; + + const std::string math = + "\n" + " \n" + " \n" + " C\n" + "\n" + " \n" + " \n" + " A\n" + " \n" + " \n" + " \n" + "\n"; + + libcellml::ValidatorPtr v = libcellml::Validator::create(); + libcellml::ModelPtr m = libcellml::Model::create(); + libcellml::ComponentPtr c = libcellml::Component::create(); + libcellml::VariablePtr v1 = libcellml::Variable::create(); + libcellml::VariablePtr v2 = libcellml::Variable::create(); + libcellml::VariablePtr v3 = libcellml::Variable::create(); + + m->setName("modelName"); + c->setName("componentName"); + v1->setName("A"); + v2->setName("B"); + v3->setName("A"); + v1->setInitialValue("1.0"); + v2->setInitialValue("-1.0"); + v1->setUnits("dimensionless"); + v2->setUnits("dimensionless"); + v3->setUnits("dimensionless"); + + c->addVariable(v1); + c->addVariable(v2); + c->addVariable(v3); + c->setMath(math); + m->addComponent(c); + + v->validateModel(m); + EXPECT_EQ(size_t(3), v->issueCount()); + EXPECT_EQ_ISSUES(expectedIssues, v); +} + +TEST(CoverageAnnotator, crossComponentConnectionAndMappingIds) +{ + auto model = libcellml::Model::create("model"); + + auto component1 = libcellml::Component::create("component1"); + auto component2 = libcellml::Component::create("component2"); + auto component3 = libcellml::Component::create("component3"); + + auto variable1 = libcellml::Variable::create("variable1"); + auto variable2 = libcellml::Variable::create("variable2"); + auto variable3 = libcellml::Variable::create("variable3"); + + model->addComponent(component1); + model->addComponent(component2); + model->addComponent(component3); + + component1->addVariable(variable1); + component2->addVariable(variable2); + component3->addVariable(variable3); + + libcellml::Variable::addEquivalence(variable1, variable2); + libcellml::Variable::addEquivalence(variable1, variable3); + + libcellml::Variable::setEquivalenceMappingId(variable1, variable2, "mapping_id"); + libcellml::Variable::setEquivalenceMappingId(variable1, variable3, "mapping_id"); + + libcellml::Variable::setEquivalenceConnectionId(variable1, variable2, "connection_id"); + libcellml::Variable::setEquivalenceConnectionId(variable1, variable3, "connection_id"); + + auto annotator = libcellml::Annotator::create(); + + annotator->setModel(model); + + EXPECT_EQ(size_t(2), annotator->itemCount("mapping_id")); + EXPECT_EQ(size_t(2), annotator->itemCount("connection_id")); +} + +TEST(CoverageModelFlattening, componentWithMathThatIsNotMathML) +{ + const std::string notMathMl = ""; + + const std::string importModelString = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + const std::string modelString = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + + auto importer = libcellml::Importer::create(); + auto parser = libcellml::Parser::create(); + auto validator = libcellml::Validator::create(); + + auto model = parser->parseModel(modelString); + auto importModel = parser->parseModel(importModelString); + + importModel->component(0)->appendMath(notMathMl); + + importer->addModel(importModel, "change_model.cellml"); + + importer->resolveImports(model, "."); + auto flattenedModel = importer->flattenModel(model); + EXPECT_EQ(size_t(1), flattenedModel->unitsCount()); +} diff --git a/tests/equality/equality.cpp b/tests/equality/equality.cpp index 17a05f1a3..985af4963 100644 --- a/tests/equality/equality.cpp +++ b/tests/equality/equality.cpp @@ -138,6 +138,28 @@ TEST(Equality, variableNotEqualByUnits) EXPECT_FALSE(v2->equals(v1)); } +TEST(Equality, variableNotEqualByInitialCondition) +{ + libcellml::VariablePtr v1 = libcellml::Variable::create("variable"); + libcellml::VariablePtr v2 = libcellml::Variable::create("variable"); + + v1->setInitialValue(3.2); + + EXPECT_FALSE(v1->equals(v2)); + EXPECT_FALSE(v2->equals(v1)); +} + +TEST(Equality, variableNotEqualByInterfaceType) +{ + libcellml::VariablePtr v1 = libcellml::Variable::create("variable"); + libcellml::VariablePtr v2 = libcellml::Variable::create("variable"); + + v1->setInterfaceType("public"); + + EXPECT_FALSE(v1->equals(v2)); + EXPECT_FALSE(v2->equals(v1)); +} + TEST(Equality, unitsEqualByNameOnly) { libcellml::UnitsPtr u1 = libcellml::Units::create("units"); @@ -160,6 +182,49 @@ TEST(Equality, unitsNotEqualByNameOnly) EXPECT_FALSE(libcellml::Units::equivalent(u1, u2)); } +TEST(Equality, unitsNotEqualByUnitPrefixOnly) +{ + libcellml::UnitsPtr u1 = libcellml::Units::create("unitsA"); + libcellml::UnitsPtr u2 = libcellml::Units::create("unitsA"); + + u1->addUnit("second", 3, 2.0, 5.0); + u2->addUnit("second", 4, 2.0, 5.0); + + EXPECT_FALSE(u1->equals(u2)); + EXPECT_FALSE(u2->equals(u1)); + EXPECT_FALSE(libcellml::Units::equivalent(u1, u2)); +} + +TEST(Equality, unitsNotEqualByUnitIdOnly) +{ + libcellml::UnitsPtr u1 = libcellml::Units::create("unitsA"); + libcellml::UnitsPtr u2 = libcellml::Units::create("unitsA"); + + u1->addUnit("second"); + u2->addUnit("second"); + + u1->setUnitId(0, "UnitsASecond"); + + EXPECT_NE(u1, u2); + EXPECT_FALSE(u1->equals(u2)); + EXPECT_FALSE(u2->equals(u1)); + EXPECT_TRUE(libcellml::Units::equivalent(u1, u2)); +} + +TEST(Equality, unitsNotEqualByUnitMultiplierOnly) +{ + libcellml::UnitsPtr u1 = libcellml::Units::create("unitsA"); + libcellml::UnitsPtr u2 = libcellml::Units::create("unitsA"); + + u1->addUnit("second", 3, 2.0, 5.0); + u2->addUnit("second", 3, 2.0, 3.0); + + EXPECT_NE(u1, u2); + EXPECT_FALSE(u1->equals(u2)); + EXPECT_FALSE(u2->equals(u1)); + EXPECT_FALSE(libcellml::Units::equivalent(u1, u2)); +} + TEST(Equality, unitsEqualAllTestedConditionsVariant1) { libcellml::UnitsPtr u1 = libcellml::Units::create("unitsA"); @@ -398,6 +463,17 @@ TEST(Equality, resetEqual) EXPECT_TRUE(r2->equals(r1)); } +TEST(Equality, resetNotEqualById) +{ + libcellml::ResetPtr r1 = createInitialisedReset(); + libcellml::ResetPtr r2 = createInitialisedReset(); + + r2->setId("id"); + + EXPECT_FALSE(r1->equals(r2)); + EXPECT_FALSE(r2->equals(r1)); +} + TEST(Equality, resetNotEqualByOrder) { libcellml::ResetPtr r1 = createInitialisedReset(); @@ -662,6 +738,19 @@ TEST(Equality, componentNotEqualByComponent) EXPECT_FALSE(c2->equals(c1)); } +TEST(Equality, componentNotEqualByNumberOfComponents) +{ + libcellml::ComponentPtr c1 = libcellml::Component::create("c"); + libcellml::ComponentPtr c2 = libcellml::Component::create("c"); + + libcellml::ComponentPtr cChild1 = libcellml::Component::create("child1"); + + c1->addComponent(cChild1); + + EXPECT_FALSE(c1->equals(c2)); + EXPECT_FALSE(c2->equals(c1)); +} + TEST(Equality, componentNotEqualByVariable) { libcellml::ComponentPtr c1 = libcellml::Component::create("c"); @@ -677,6 +766,28 @@ TEST(Equality, componentNotEqualByVariable) EXPECT_FALSE(c2->equals(c1)); } +TEST(Equality, componentNotEqualByMath) +{ + libcellml::ComponentPtr c1 = libcellml::Component::create("child1"); + libcellml::ComponentPtr c1Alt = libcellml::Component::create("child1"); + + c1Alt->setMath("math"); + + EXPECT_FALSE(c1->equals(c1Alt)); + EXPECT_FALSE(c1Alt->equals(c1)); +} + +TEST(Equality, componentNotEqualByEncapsulationId) +{ + libcellml::ComponentPtr c1 = libcellml::Component::create("child1"); + libcellml::ComponentPtr c1Alt = libcellml::Component::create("child1"); + + c1Alt->setEncapsulationId("id1"); + + EXPECT_FALSE(c1->equals(c1Alt)); + EXPECT_FALSE(c1Alt->equals(c1)); +} + TEST(Equality, importSourceEqual) { libcellml::ImportSourcePtr is1 = libcellml::ImportSource::create(); @@ -889,6 +1000,42 @@ TEST(Equality, namedEntityNotEqualNonNamedEntity) { libcellml::VariablePtr v1 = libcellml::Variable::create("variableA"); libcellml::ImportSourcePtr is1 = libcellml::ImportSource::create(); + libcellml::ResetPtr r1 = libcellml::Reset::create(); EXPECT_FALSE(v1->equals(is1)); + EXPECT_FALSE(is1->equals(v1)); + + EXPECT_FALSE(v1->equals(r1)); + EXPECT_FALSE(r1->equals(v1)); +} + +TEST(Equality, modelNotEqualComponent) +{ + libcellml::ModelPtr m = libcellml::Model::create("name"); + libcellml::ComponentPtr c = libcellml::Component::create("name"); + + EXPECT_FALSE(m->equals(c)); + EXPECT_FALSE(c->equals(m)); +} + +TEST(Equality, componentNotEqualVariable) +{ + libcellml::ComponentPtr c = libcellml::Component::create("name"); + libcellml::VariablePtr v = libcellml::Variable::create("name"); + + EXPECT_FALSE(c->equals(v)); + EXPECT_FALSE(v->equals(c)); +} + +TEST(Equality, unitsNotEqualImportedUnits) +{ + libcellml::UnitsPtr u1 = libcellml::Units::create("name"); + libcellml::UnitsPtr u2 = libcellml::Units::create("name"); + + libcellml::ImportSourcePtr iS = libcellml::ImportSource::create(); + + u1->setImportSource(iS); + + EXPECT_FALSE(u1->equals(u2)); + EXPECT_FALSE(u2->equals(u1)); } diff --git a/tests/generator/generator.cpp b/tests/generator/generator.cpp index cfb450314..36e03f3da 100644 --- a/tests/generator/generator.cpp +++ b/tests/generator/generator.cpp @@ -54,20 +54,6 @@ TEST(Generator, algebraicEqnComputedVarOnRhs) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ALGEBRAIC, analyserModel->type()); - - EXPECT_EQ(size_t(0), analyserModel->stateCount()); - EXPECT_EQ(size_t(2), analyserModel->variableCount()); - EXPECT_EQ(size_t(2), analyserModel->equationCount()); - - EXPECT_EQ(nullptr, analyserModel->voi()); - EXPECT_EQ(nullptr, analyserModel->state(0)); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -79,11 +65,10 @@ TEST(Generator, algebraicEqnComputedVarOnRhs) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/algebraic_eqn_computed_var_on_rhs/model.py"), generator->implementationCode()); } -TEST(Generator, algebraicEqnComputedVarOnRhsWithExternalVariables) +TEST(Generator, algebraicEqnComputedVarOnRhsWithComputedConstantAsExternalVariable) { auto parser = libcellml::Parser::create(); auto model = parser->parseModel(fileContents("generator/algebraic_eqn_computed_var_on_rhs/model.cellml")); @@ -99,20 +84,6 @@ TEST(Generator, algebraicEqnComputedVarOnRhsWithExternalVariables) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ALGEBRAIC, analyserModel->type()); - - EXPECT_EQ(size_t(0), analyserModel->stateCount()); - EXPECT_EQ(size_t(2), analyserModel->variableCount()); - EXPECT_EQ(size_t(2), analyserModel->equationCount()); - - EXPECT_EQ(nullptr, analyserModel->voi()); - EXPECT_EQ(nullptr, analyserModel->state(0)); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -128,7 +99,6 @@ TEST(Generator, algebraicEqnComputedVarOnRhsWithExternalVariables) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/algebraic_eqn_computed_var_on_rhs/model.external.py"), generator->implementationCode()); } @@ -146,20 +116,6 @@ TEST(Generator, algebraicEqnConstVarOnRhs) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ALGEBRAIC, analyserModel->type()); - - EXPECT_EQ(size_t(0), analyserModel->stateCount()); - EXPECT_EQ(size_t(2), analyserModel->variableCount()); - EXPECT_EQ(size_t(1), analyserModel->equationCount()); - - EXPECT_EQ(nullptr, analyserModel->voi()); - EXPECT_EQ(nullptr, analyserModel->state(0)); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -171,7 +127,6 @@ TEST(Generator, algebraicEqnConstVarOnRhs) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/algebraic_eqn_const_var_on_rhs/model.py"), generator->implementationCode()); } @@ -189,20 +144,6 @@ TEST(Generator, algebraicEqnConstantOnRhs) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ALGEBRAIC, analyserModel->type()); - - EXPECT_EQ(size_t(0), analyserModel->stateCount()); - EXPECT_EQ(size_t(1), analyserModel->variableCount()); - EXPECT_EQ(size_t(1), analyserModel->equationCount()); - - EXPECT_EQ(nullptr, analyserModel->voi()); - EXPECT_EQ(nullptr, analyserModel->state(0)); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -214,7 +155,6 @@ TEST(Generator, algebraicEqnConstantOnRhs) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/algebraic_eqn_constant_on_rhs/model.py"), generator->implementationCode()); } @@ -232,21 +172,6 @@ TEST(Generator, algebraicEqnDerivativeOnRhs) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(2), analyserModel->variableCount()); - EXPECT_EQ(size_t(3), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -258,7 +183,6 @@ TEST(Generator, algebraicEqnDerivativeOnRhs) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/algebraic_eqn_derivative_on_rhs/model.py"), generator->implementationCode()); } @@ -276,21 +200,6 @@ TEST(Generator, algebraicEqnDerivativeOnRhsOneComponent) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(2), analyserModel->variableCount()); - EXPECT_EQ(size_t(3), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -302,7 +211,6 @@ TEST(Generator, algebraicEqnDerivativeOnRhsOneComponent) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/algebraic_eqn_derivative_on_rhs_one_component/model.py"), generator->implementationCode()); } @@ -320,21 +228,6 @@ TEST(Generator, algebraicEqnStateVarOnRhs) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(2), analyserModel->variableCount()); - EXPECT_EQ(size_t(3), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -346,7 +239,6 @@ TEST(Generator, algebraicEqnStateVarOnRhs) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/algebraic_eqn_state_var_on_rhs/model.py"), generator->implementationCode()); } @@ -364,40 +256,52 @@ TEST(Generator, algebraicEqnStateVarOnRhsOneComponent) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); + + generator->setModel(analyserModel); + + EXPECT_EQ(fileContents("generator/algebraic_eqn_state_var_on_rhs_one_component/model.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/algebraic_eqn_state_var_on_rhs_one_component/model.c"), generator->implementationCode()); + + auto profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); + + generator->setProfile(profile); + + EXPECT_EQ(fileContents("generator/algebraic_eqn_state_var_on_rhs_one_component/model.py"), generator->implementationCode()); +} + +TEST(Generator, algebraicUnknownVarOnRhs) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/algebraic_unknown_var_on_rhs/model.cellml")); - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); + EXPECT_EQ(size_t(0), parser->issueCount()); - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(2), analyserModel->variableCount()); - EXPECT_EQ(size_t(3), analyserModel->equationCount()); + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(model); - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); + EXPECT_EQ(size_t(0), analyser->errorCount()); + auto analyserModel = analyser->model(); auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); - EXPECT_EQ(fileContents("generator/algebraic_eqn_state_var_on_rhs_one_component/model.h"), generator->interfaceCode()); - EXPECT_EQ(fileContents("generator/algebraic_eqn_state_var_on_rhs_one_component/model.c"), generator->implementationCode()); + EXPECT_EQ(fileContents("generator/algebraic_unknown_var_on_rhs/model.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/algebraic_unknown_var_on_rhs/model.c"), generator->implementationCode()); auto profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); - EXPECT_EQ(fileContents("generator/algebraic_eqn_state_var_on_rhs_one_component/model.py"), generator->implementationCode()); + EXPECT_EQ(fileContents("generator/algebraic_unknown_var_on_rhs/model.py"), generator->implementationCode()); } -TEST(Generator, odeComputedVarOnRhs) +TEST(Generator, algebraicEqnWithOneNonIsolatedUnknown) { auto parser = libcellml::Parser::create(); - auto model = parser->parseModel(fileContents("generator/ode_computed_var_on_rhs/model.cellml")); + auto model = parser->parseModel(fileContents("generator/algebraic_eqn_with_one_non_isolated_unknown/model.cellml")); EXPECT_EQ(size_t(0), parser->issueCount()); @@ -408,21 +312,196 @@ TEST(Generator, odeComputedVarOnRhs) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); + + generator->setModel(analyserModel); + + EXPECT_EQ(fileContents("generator/algebraic_eqn_with_one_non_isolated_unknown/model.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/algebraic_eqn_with_one_non_isolated_unknown/model.c"), generator->implementationCode()); + + auto profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); + + generator->setProfile(profile); + + EXPECT_EQ(fileContents("generator/algebraic_eqn_with_one_non_isolated_unknown/model.py"), generator->implementationCode()); +} + +TEST(Generator, algebraicEqnWithOneNonIsolatedUnknownWithExternalVariable) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/algebraic_eqn_with_one_non_isolated_unknown/model.cellml")); - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); + EXPECT_EQ(size_t(0), parser->issueCount()); - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(1), analyserModel->variableCount()); - EXPECT_EQ(size_t(2), analyserModel->equationCount()); + auto analyser = libcellml::Analyser::create(); - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); + analyser->addExternalVariable(libcellml::AnalyserExternalVariable::create(model->component("my_algebraic_eqn")->variable("a"))); + analyser->analyseModel(model); + + EXPECT_EQ(size_t(0), analyser->errorCount()); + + auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); + + generator->setModel(analyserModel); + + auto profile = generator->profile(); + + profile->setInterfaceFileNameString("model.external.h"); + + EXPECT_EQ(fileContents("generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.c"), generator->implementationCode()); + + profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); + + generator->setProfile(profile); + + EXPECT_EQ(fileContents("generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.py"), generator->implementationCode()); +} + +TEST(Generator, algebraicSystemWithThreeLinkedUnknowns) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/algebraic_system_with_three_linked_unknowns/model.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); + + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(model); + + EXPECT_EQ(size_t(0), analyser->errorCount()); + + auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); + + generator->setModel(analyserModel); + + EXPECT_EQ(fileContents("generator/algebraic_system_with_three_linked_unknowns/model.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/algebraic_system_with_three_linked_unknowns/model.c"), generator->implementationCode()); + + auto profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); + + generator->setProfile(profile); + + EXPECT_EQ(fileContents("generator/algebraic_system_with_three_linked_unknowns/model.py"), generator->implementationCode()); +} + +TEST(Generator, algebraicSystemWithThreeLinkedUnknownsWithThreeExternalVariables) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/algebraic_system_with_three_linked_unknowns/model.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); + + auto analyser = libcellml::Analyser::create(); + + analyser->addExternalVariable(libcellml::AnalyserExternalVariable::create(model->component("my_algebraic_system")->variable("x"))); + analyser->addExternalVariable(libcellml::AnalyserExternalVariable::create(model->component("my_algebraic_system")->variable("y"))); + analyser->addExternalVariable(libcellml::AnalyserExternalVariable::create(model->component("my_algebraic_system")->variable("z"))); + + analyser->analyseModel(model); + + EXPECT_EQ(size_t(0), analyser->errorCount()); + + auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); + + generator->setModel(analyserModel); + + auto profile = generator->profile(); + + profile->setInterfaceFileNameString("model.three.externals.h"); + + EXPECT_EQ(fileContents("generator/algebraic_system_with_three_linked_unknowns/model.three.externals.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/algebraic_system_with_three_linked_unknowns/model.three.externals.c"), generator->implementationCode()); + + profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); + + generator->setProfile(profile); + + EXPECT_EQ(fileContents("generator/algebraic_system_with_three_linked_unknowns/model.three.externals.py"), generator->implementationCode()); +} + +TEST(Generator, algebraicSystemWithVariousDependenciesOrdered) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/algebraic_system_with_various_dependencies/model.ordered.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); + + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(model); + + EXPECT_EQ(size_t(0), analyser->errorCount()); + + auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); + + generator->setModel(analyserModel); + + auto profile = generator->profile(); + + profile->setInterfaceFileNameString("model.ordered.h"); + + EXPECT_EQ(fileContents("generator/algebraic_system_with_various_dependencies/model.ordered.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/algebraic_system_with_various_dependencies/model.ordered.c"), generator->implementationCode()); + + profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); + + generator->setProfile(profile); + + EXPECT_EQ(fileContents("generator/algebraic_system_with_various_dependencies/model.ordered.py"), generator->implementationCode()); +} + +TEST(Generator, algebraicSystemWithVariousDependenciesNotOrdered) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/algebraic_system_with_various_dependencies/model.not.ordered.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); + + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(model); + + EXPECT_EQ(size_t(0), analyser->errorCount()); + + auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); + + generator->setModel(analyserModel); + + auto profile = generator->profile(); + + profile->setInterfaceFileNameString("model.not.ordered.h"); + + EXPECT_EQ(fileContents("generator/algebraic_system_with_various_dependencies/model.not.ordered.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/algebraic_system_with_various_dependencies/model.not.ordered.c"), generator->implementationCode()); + + profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); + + generator->setProfile(profile); + + EXPECT_EQ(fileContents("generator/algebraic_system_with_various_dependencies/model.not.ordered.py"), generator->implementationCode()); +} + +TEST(Generator, odeComputedVarOnRhs) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/ode_computed_var_on_rhs/model.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); + + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(model); + + EXPECT_EQ(size_t(0), analyser->errorCount()); + + auto analyserModel = analyser->model(); auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -434,7 +513,6 @@ TEST(Generator, odeComputedVarOnRhs) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/ode_computed_var_on_rhs/model.py"), generator->implementationCode()); } @@ -452,21 +530,6 @@ TEST(Generator, odeComputedVarOnRhsOneComponent) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(1), analyserModel->variableCount()); - EXPECT_EQ(size_t(2), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -478,7 +541,6 @@ TEST(Generator, odeComputedVarOnRhsOneComponent) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/ode_computed_var_on_rhs_one_component/model.py"), generator->implementationCode()); } @@ -496,21 +558,6 @@ TEST(Generator, odeConstVarOnRhs) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(1), analyserModel->variableCount()); - EXPECT_EQ(size_t(1), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -522,7 +569,6 @@ TEST(Generator, odeConstVarOnRhs) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/ode_const_var_on_rhs/model.py"), generator->implementationCode()); } @@ -540,21 +586,6 @@ TEST(Generator, odeConstVarOnRhsOneComponent) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(1), analyserModel->variableCount()); - EXPECT_EQ(size_t(1), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -566,7 +597,6 @@ TEST(Generator, odeConstVarOnRhsOneComponent) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/ode_const_var_on_rhs_one_component/model.py"), generator->implementationCode()); } @@ -584,20 +614,6 @@ TEST(Generator, odeConstantOnRhs) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(0), analyserModel->variableCount()); - EXPECT_EQ(size_t(1), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_EQ(nullptr, analyserModel->variable(0)); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -609,7 +625,6 @@ TEST(Generator, odeConstantOnRhs) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/ode_constant_on_rhs/model.py"), generator->implementationCode()); } @@ -627,20 +642,6 @@ TEST(Generator, odeConstantOnRhsOneComponent) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(0), analyserModel->variableCount()); - EXPECT_EQ(size_t(1), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_EQ(nullptr, analyserModel->variable(0)); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -652,7 +653,6 @@ TEST(Generator, odeConstantOnRhsOneComponent) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/ode_constant_on_rhs_one_component/model.py"), generator->implementationCode()); } @@ -670,21 +670,6 @@ TEST(Generator, odeMultipleDependentOdes) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(2), analyserModel->stateCount()); - EXPECT_EQ(size_t(1), analyserModel->variableCount()); - EXPECT_EQ(size_t(2), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -696,7 +681,6 @@ TEST(Generator, odeMultipleDependentOdes) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/ode_multiple_dependent_odes/model.py"), generator->implementationCode()); } @@ -714,21 +698,6 @@ TEST(Generator, odeMultipleDependentOdesOneComponent) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(2), analyserModel->stateCount()); - EXPECT_EQ(size_t(1), analyserModel->variableCount()); - EXPECT_EQ(size_t(2), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -740,7 +709,6 @@ TEST(Generator, odeMultipleDependentOdesOneComponent) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/ode_multiple_dependent_odes_one_component/model.py"), generator->implementationCode()); } @@ -758,21 +726,6 @@ TEST(Generator, odeMultipleOdesWithSameName) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(2), analyserModel->stateCount()); - EXPECT_EQ(size_t(1), analyserModel->variableCount()); - EXPECT_EQ(size_t(2), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -784,14 +737,13 @@ TEST(Generator, odeMultipleOdesWithSameName) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/ode_multiple_odes_with_same_name/model.py"), generator->implementationCode()); } -TEST(Generator, cellmlMappingsAndEncapsulations) +TEST(Generator, odeUnknownVarOnRhs) { auto parser = libcellml::Parser::create(); - auto model = parser->parseModel(fileContents("generator/cellml_mappings_and_encapsulations/model.cellml")); + auto model = parser->parseModel(fileContents("generator/ode_unknown_var_on_rhs/model.cellml")); EXPECT_EQ(size_t(0), parser->issueCount()); @@ -802,21 +754,34 @@ TEST(Generator, cellmlMappingsAndEncapsulations) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); + + generator->setModel(analyserModel); + + EXPECT_EQ(fileContents("generator/ode_unknown_var_on_rhs/model.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/ode_unknown_var_on_rhs/model.c"), generator->implementationCode()); + + auto profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); + + generator->setProfile(profile); + + EXPECT_EQ(fileContents("generator/ode_unknown_var_on_rhs/model.py"), generator->implementationCode()); +} - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); +TEST(Generator, cellmlMappingsAndEncapsulations) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/cellml_mappings_and_encapsulations/model.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); - EXPECT_EQ(size_t(2), analyserModel->stateCount()); - EXPECT_EQ(size_t(2), analyserModel->variableCount()); - EXPECT_EQ(size_t(4), analyserModel->equationCount()); + auto analyser = libcellml::Analyser::create(); - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); + analyser->analyseModel(model); + + EXPECT_EQ(size_t(0), analyser->errorCount()); + auto analyserModel = analyser->model(); auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -828,7 +793,6 @@ TEST(Generator, cellmlMappingsAndEncapsulations) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/cellml_mappings_and_encapsulations/model.py"), generator->implementationCode()); } @@ -846,21 +810,6 @@ TEST(Generator, cellmlStateInitialisedUsingVariable) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(1), analyserModel->variableCount()); - EXPECT_EQ(size_t(1), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -872,7 +821,6 @@ TEST(Generator, cellmlStateInitialisedUsingVariable) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/cellml_state_initialised_using_variable/model.py"), generator->implementationCode()); } @@ -890,21 +838,6 @@ TEST(Generator, cellmlUnitScalingVoiIndirect) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(2), analyserModel->stateCount()); - EXPECT_EQ(size_t(0), analyserModel->variableCount()); - EXPECT_EQ(size_t(2), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_EQ(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -916,7 +849,6 @@ TEST(Generator, cellmlUnitScalingVoiIndirect) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/cellml_unit_scaling_voi_indirect/model.py"), generator->implementationCode()); } @@ -934,21 +866,6 @@ TEST(Generator, cellmlUnitScalingVoiDirect) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(2), analyserModel->stateCount()); - EXPECT_EQ(size_t(0), analyserModel->variableCount()); - EXPECT_EQ(size_t(2), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_EQ(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -960,7 +877,6 @@ TEST(Generator, cellmlUnitScalingVoiDirect) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/cellml_unit_scaling_voi_direct/model.py"), generator->implementationCode()); } @@ -978,20 +894,6 @@ TEST(Generator, cellmlUnitScalingConstant) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ALGEBRAIC, analyserModel->type()); - - EXPECT_EQ(size_t(0), analyserModel->stateCount()); - EXPECT_EQ(size_t(3), analyserModel->variableCount()); - EXPECT_EQ(size_t(2), analyserModel->equationCount()); - - EXPECT_EQ(nullptr, analyserModel->voi()); - EXPECT_EQ(nullptr, analyserModel->state(0)); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1003,7 +905,6 @@ TEST(Generator, cellmlUnitScalingConstant) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/cellml_unit_scaling_constant/model.py"), generator->implementationCode()); } @@ -1021,21 +922,6 @@ TEST(Generator, cellmlUnitScalingState) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(2), analyserModel->variableCount()); - EXPECT_EQ(size_t(3), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1047,7 +933,6 @@ TEST(Generator, cellmlUnitScalingState) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/cellml_unit_scaling_state/model.py"), generator->implementationCode()); } @@ -1065,21 +950,6 @@ TEST(Generator, cellmlUnitScalingStateInitialisedUsingConstant) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(2), analyserModel->stateCount()); - EXPECT_EQ(size_t(0), analyserModel->variableCount()); - EXPECT_EQ(size_t(2), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_EQ(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1091,7 +961,6 @@ TEST(Generator, cellmlUnitScalingStateInitialisedUsingConstant) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/cellml_unit_scaling_state_initialised_using_constant/model.py"), generator->implementationCode()); } @@ -1104,26 +973,11 @@ TEST(Generator, cellmlUnitScalingStateInitialisedUsingVariable) auto analyser = libcellml::Analyser::create(); - analyser->analyseModel(model); - - EXPECT_EQ(size_t(0), analyser->errorCount()); - - auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(2), analyserModel->stateCount()); - EXPECT_EQ(size_t(2), analyserModel->variableCount()); - EXPECT_EQ(size_t(2), analyserModel->equationCount()); + analyser->analyseModel(model); - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); + EXPECT_EQ(size_t(0), analyser->errorCount()); + auto analyserModel = analyser->model(); auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1135,7 +989,6 @@ TEST(Generator, cellmlUnitScalingStateInitialisedUsingVariable) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/cellml_unit_scaling_state_initialised_using_variable/model.py"), generator->implementationCode()); } @@ -1153,21 +1006,6 @@ TEST(Generator, cellmlUnitScalingRate) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(2), analyserModel->variableCount()); - EXPECT_EQ(size_t(3), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1179,7 +1017,6 @@ TEST(Generator, cellmlUnitScalingRate) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/cellml_unit_scaling_rate/model.py"), generator->implementationCode()); } @@ -1197,21 +1034,6 @@ TEST(Generator, dependentEqns) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(2), analyserModel->variableCount()); - EXPECT_EQ(size_t(3), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1223,7 +1045,6 @@ TEST(Generator, dependentEqns) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/dependent_eqns/model.py"), generator->implementationCode()); } @@ -1241,20 +1062,6 @@ TEST(Generator, cellGeometryModel) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ALGEBRAIC, analyserModel->type()); - - EXPECT_EQ(size_t(0), analyserModel->stateCount()); - EXPECT_EQ(size_t(4), analyserModel->variableCount()); - EXPECT_EQ(size_t(2), analyserModel->equationCount()); - - EXPECT_EQ(nullptr, analyserModel->voi()); - EXPECT_EQ(nullptr, analyserModel->state(0)); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1266,11 +1073,10 @@ TEST(Generator, cellGeometryModel) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/cell_geometry_model/model.py"), generator->implementationCode()); } -TEST(Generator, cellGeometryModelWithExternalVariables) +TEST(Generator, cellGeometryModelWithSomeConstantsAsExternalVariables) { auto parser = libcellml::Parser::create(); auto model = parser->parseModel(fileContents("generator/cell_geometry_model/model.cellml")); @@ -1287,20 +1093,6 @@ TEST(Generator, cellGeometryModelWithExternalVariables) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ALGEBRAIC, analyserModel->type()); - - EXPECT_EQ(size_t(0), analyserModel->stateCount()); - EXPECT_EQ(size_t(4), analyserModel->variableCount()); - EXPECT_EQ(size_t(4), analyserModel->equationCount()); - - EXPECT_EQ(nullptr, analyserModel->voi()); - EXPECT_EQ(nullptr, analyserModel->state(0)); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1316,7 +1108,6 @@ TEST(Generator, cellGeometryModelWithExternalVariables) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/cell_geometry_model/model.external.py"), generator->implementationCode()); } @@ -1334,21 +1125,6 @@ TEST(Generator, fabbriFantiniWildersSeveriHumanSanModel2017) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(33), analyserModel->stateCount()); - EXPECT_EQ(size_t(217), analyserModel->variableCount()); - EXPECT_EQ(size_t(159), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1360,7 +1136,6 @@ TEST(Generator, fabbriFantiniWildersSeveriHumanSanModel2017) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/fabbri_fantini_wilders_severi_human_san_model_2017/model.py"), generator->implementationCode()); } @@ -1378,21 +1153,6 @@ TEST(Generator, garnyKohlHunterBoyettNobleRabbitSanModel2003) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(15), analyserModel->stateCount()); - EXPECT_EQ(size_t(185), analyserModel->variableCount()); - EXPECT_EQ(size_t(90), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1404,7 +1164,6 @@ TEST(Generator, garnyKohlHunterBoyettNobleRabbitSanModel2003) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/garny_kohl_hunter_boyett_noble_rabbit_san_model_2003/model.py"), generator->implementationCode()); } @@ -1422,21 +1181,34 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); + + generator->setModel(analyserModel); + + EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.c"), generator->implementationCode()); + + auto profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); + + generator->setProfile(profile); + + EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.py"), generator->implementationCode()); +} + +TEST(Generator, hodgkinHuxleySquidAxonModel1952UnknownVarsOnRhs) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model_unknown_vars_on_rhs.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); + auto analyser = libcellml::Analyser::create(); - EXPECT_EQ(size_t(4), analyserModel->stateCount()); - EXPECT_EQ(size_t(18), analyserModel->variableCount()); - EXPECT_EQ(size_t(17), analyserModel->equationCount()); + analyser->analyseModel(model); - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); + EXPECT_EQ(size_t(0), analyser->errorCount()); + auto analyserModel = analyser->model(); auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1448,11 +1220,10 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.py"), generator->implementationCode()); } -TEST(Generator, hodgkinHuxleySquidAxonModel1952WithStateAsExternalVariable) +TEST(Generator, hodgkinHuxleySquidAxonModel1952WithStateVariableAsExternalVariable) { // Generate some code for the HH52 model with sodium_channel.m (i.e. not a // primary variable) as an external variable. @@ -1471,21 +1242,6 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithStateAsExternalVariable) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(3), analyserModel->stateCount()); - EXPECT_EQ(size_t(19), analyserModel->variableCount()); - EXPECT_EQ(size_t(17), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1501,11 +1257,10 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithStateAsExternalVariable) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.state.py"), generator->implementationCode()); } -TEST(Generator, hodgkinHuxleySquidAxonModel1952WithDependentStateExternalVariable) +TEST(Generator, hodgkinHuxleySquidAxonModel1952WithStateVariablesAsExternalVariablesIncludingOneDependingOnTheOther) { // Generate some code for the HH52 model with sodium_channel.m (i.e. not a // primary variable) as an external variable which has a dependency on @@ -1531,21 +1286,6 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithDependentStateExternalVariabl EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(2), analyserModel->stateCount()); - EXPECT_EQ(size_t(20), analyserModel->variableCount()); - EXPECT_EQ(size_t(17), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1561,7 +1301,6 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithDependentStateExternalVariabl generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.py"), generator->implementationCode()); } @@ -1584,21 +1323,6 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithConstantAsExternalVariable) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(4), analyserModel->stateCount()); - EXPECT_EQ(size_t(18), analyserModel->variableCount()); - EXPECT_EQ(size_t(18), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1614,11 +1338,10 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithConstantAsExternalVariable) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.constant.py"), generator->implementationCode()); } -TEST(Generator, hodgkinHuxleySquidAxonModel1952WithDependentConstantAsExternalVariable) +TEST(Generator, hodgkinHuxleySquidAxonModel1952WithConstantsAsExternalVariablesIncludingOneDependingOnTheOther) { // Generate some code for the HH52 model with membrane.Cm as an external // variable which has a dependency on sodium_channel.g_Na, another constant @@ -1643,21 +1366,6 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithDependentConstantAsExternalVa EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(4), analyserModel->stateCount()); - EXPECT_EQ(size_t(18), analyserModel->variableCount()); - EXPECT_EQ(size_t(19), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1673,7 +1381,6 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithDependentConstantAsExternalVa generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.py"), generator->implementationCode()); } @@ -1696,21 +1403,6 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithComputedConstantAsExternalVar EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(4), analyserModel->stateCount()); - EXPECT_EQ(size_t(18), analyserModel->variableCount()); - EXPECT_EQ(size_t(17), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1726,11 +1418,10 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithComputedConstantAsExternalVar generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.py"), generator->implementationCode()); } -TEST(Generator, hodgkinHuxleySquidAxonModel1952WithDependentComputedConstantAsExternalVariable) +TEST(Generator, hodgkinHuxleySquidAxonModel1952WithComputedConstantsAsExternalVariablesIncludingOneDependingOnTheOther) { // Generate some code for the HH52 model with leakage_current.E_R as an // external variable which has a dependency on potassium_channel.E_K, @@ -1755,21 +1446,6 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithDependentComputedConstantAsEx EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(4), analyserModel->stateCount()); - EXPECT_EQ(size_t(18), analyserModel->variableCount()); - EXPECT_EQ(size_t(18), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1785,7 +1461,6 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithDependentComputedConstantAsEx generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.py"), generator->implementationCode()); } @@ -1808,21 +1483,6 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithAlgebraicVariableAsExternalVa EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(4), analyserModel->stateCount()); - EXPECT_EQ(size_t(18), analyserModel->variableCount()); - EXPECT_EQ(size_t(17), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1838,11 +1498,10 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithAlgebraicVariableAsExternalVa generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.py"), generator->implementationCode()); } -TEST(Generator, hodgkinHuxleySquidAxonModel1952WithDependentAlgebraicVariableAsExternalVariable) +TEST(Generator, hodgkinHuxleySquidAxonModel1952WithAlgebraicVariablesAsExternalVariablesIncludingOneDependingOnTheOther) { // Generate some code for the HH52 model with membrane.i_Stim as an external // variable which has a dependency on potassium_channel_n_gate.beta_n, @@ -1867,21 +1526,6 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithDependentAlgebraicVariableAsE EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(4), analyserModel->stateCount()); - EXPECT_EQ(size_t(18), analyserModel->variableCount()); - EXPECT_EQ(size_t(17), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1897,11 +1541,10 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithDependentAlgebraicVariableAsE generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.py"), generator->implementationCode()); } -TEST(Generator, hodgkinHuxleySquidAxonModel1952WithExternalVariables) +TEST(Generator, hodgkinHuxleySquidAxonModel1952WithVariousExternalVariables) { // Generate some code for the HH52 model with sodium_channel.i_Na as an // external variable which has a dependency on @@ -1933,21 +1576,6 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithExternalVariables) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(3), analyserModel->stateCount()); - EXPECT_EQ(size_t(19), analyserModel->variableCount()); - EXPECT_EQ(size_t(17), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -1963,14 +1591,16 @@ TEST(Generator, hodgkinHuxleySquidAxonModel1952WithExternalVariables) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.external.py"), generator->implementationCode()); } -TEST(Generator, nobleModel1962) +TEST(Generator, hodgkinHuxleySquidAxonModel1952Nla) { + // Same as the hodgkinHuxleySquidAxonModel1952 test, except that all the + // algebraic equations are to be computed using NLA systems of one equation. + auto parser = libcellml::Parser::create(); - auto model = parser->parseModel(fileContents("generator/noble_model_1962/model.cellml")); + auto model = parser->parseModel(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.dae.cellml")); EXPECT_EQ(size_t(0), parser->issueCount()); @@ -1981,21 +1611,38 @@ TEST(Generator, nobleModel1962) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); + + generator->setModel(analyserModel); + + auto profile = generator->profile(); + + profile->setInterfaceFileNameString("model.dae.h"); + + EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.dae.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.dae.c"), generator->implementationCode()); - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); + profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); + + generator->setProfile(profile); + + EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.dae.py"), generator->implementationCode()); +} + +TEST(Generator, nobleModel1962) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/noble_model_1962/model.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); - EXPECT_EQ(size_t(4), analyserModel->stateCount()); - EXPECT_EQ(size_t(17), analyserModel->variableCount()); - EXPECT_EQ(size_t(16), analyserModel->equationCount()); + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(model); - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); + EXPECT_EQ(size_t(0), analyser->errorCount()); + auto analyserModel = analyser->model(); auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); @@ -2007,24 +1654,15 @@ TEST(Generator, nobleModel1962) generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); EXPECT_EQ(fileContents("generator/noble_model_1962/model.py"), generator->implementationCode()); } -TEST(Generator, sineImports) +TEST(Generator, robertsonOdeModel1966) { auto parser = libcellml::Parser::create(); - auto model = parser->parseModel(fileContents("sine_approximations_import.xml")); - auto importer = libcellml::Importer::create(); + auto model = parser->parseModel(fileContents("generator/robertson_model_1966/model.ode.cellml")); EXPECT_EQ(size_t(0), parser->issueCount()); - EXPECT_TRUE(model->hasUnresolvedImports()); - - importer->resolveImports(model, resourcePath()); - - EXPECT_FALSE(model->hasUnresolvedImports()); - - model = importer->flattenModel(model); auto analyser = libcellml::Analyser::create(); @@ -2033,40 +1671,28 @@ TEST(Generator, sineImports) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); - - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); - - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(10), analyserModel->variableCount()); - EXPECT_EQ(size_t(9), analyserModel->equationCount()); - - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); - auto generator = libcellml::Generator::create(); generator->setModel(analyserModel); - EXPECT_EQ(fileContents("generator/sine_model_imports/model.h"), generator->interfaceCode()); - EXPECT_EQ(fileContents("generator/sine_model_imports/model.c"), generator->implementationCode()); + auto profile = generator->profile(); - auto profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); + profile->setInterfaceFileNameString("model.ode.h"); + + EXPECT_EQ(fileContents("generator/robertson_model_1966/model.ode.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/robertson_model_1966/model.ode.c"), generator->implementationCode()); + + profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); - EXPECT_EQ(fileContents("generator/sine_model_imports/model.py"), generator->implementationCode()); + EXPECT_EQ(fileContents("generator/robertson_model_1966/model.ode.py"), generator->implementationCode()); } -TEST(Generator, coverage) +TEST(Generator, robertsonDaeModel1966) { auto parser = libcellml::Parser::create(); - auto model = parser->parseModel(fileContents("generator/coverage/model.cellml")); + auto model = parser->parseModel(fileContents("generator/robertson_model_1966/model.dae.cellml")); EXPECT_EQ(size_t(0), parser->issueCount()); @@ -2077,199 +1703,193 @@ TEST(Generator, coverage) EXPECT_EQ(size_t(0), analyser->errorCount()); auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); - EXPECT_EQ(libcellml::AnalyserModel::Type::ODE, analyserModel->type()); + generator->setModel(analyserModel); - EXPECT_EQ(size_t(1), analyserModel->stateCount()); - EXPECT_EQ(size_t(186), analyserModel->variableCount()); - EXPECT_EQ(size_t(180), analyserModel->equationCount()); + auto profile = generator->profile(); - EXPECT_NE(nullptr, analyserModel->voi()); - EXPECT_EQ(nullptr, analyserModel->voi()->equation()); - EXPECT_NE(nullptr, analyserModel->state(0)); - EXPECT_NE(nullptr, analyserModel->state(0)->equation()); - EXPECT_EQ(nullptr, analyserModel->state(analyserModel->stateCount())); - EXPECT_NE(nullptr, analyserModel->variable(0)); - EXPECT_EQ(nullptr, analyserModel->variable(analyserModel->variableCount())); - EXPECT_NE(nullptr, analyserModel->equation(0)); - EXPECT_NE(nullptr, analyserModel->equation(0)->variable()); - EXPECT_EQ(nullptr, analyserModel->equation(analyserModel->equationCount())); + profile->setInterfaceFileNameString("model.dae.h"); - auto generator = libcellml::Generator::create(); + EXPECT_EQ(fileContents("generator/robertson_model_1966/model.dae.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/robertson_model_1966/model.dae.c"), generator->implementationCode()); - EXPECT_EQ(nullptr, analyserModel->voi()->initialisingVariable()); + profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); - for (size_t i = 0; i < analyserModel->stateCount(); ++i) { - EXPECT_NE(nullptr, analyserModel->state(i)->initialisingVariable()); - } + generator->setProfile(profile); - for (size_t i = 0; i < analyserModel->variableCount(); ++i) { - EXPECT_EQ(i < 7, analyserModel->variable(i)->initialisingVariable() != nullptr); - } + EXPECT_EQ(fileContents("generator/robertson_model_1966/model.dae.py"), generator->implementationCode()); +} - EXPECT_EQ(nullptr, generator->model()); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); - EXPECT_EQ(EMPTY_STRING, generator->implementationCode()); +TEST(Generator, sineImports) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("sine_approximations_import.xml")); + auto importer = libcellml::Importer::create(); - generator->setModel(analyserModel); + EXPECT_EQ(size_t(0), parser->issueCount()); + EXPECT_TRUE(model->hasUnresolvedImports()); - EXPECT_EQ(analyserModel, generator->model()); - EXPECT_EQ(fileContents("generator/coverage/model.h"), generator->interfaceCode()); - EXPECT_EQ(fileContents("generator/coverage/model.c"), generator->implementationCode()); + importer->resolveImports(model, resourcePath()); - auto profile = generator->profile(); + EXPECT_FALSE(model->hasUnresolvedImports()); + + model = importer->flattenModel(model); + + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(model); + + EXPECT_EQ(size_t(0), analyser->errorCount()); + + auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); - profile->setInterfaceCreateStatesArrayMethodString("double * createStatesVector();\n"); - profile->setImplementationCreateStatesArrayMethodString("double * createStatesVector()\n" - "{\n" - " return malloc(STATE_COUNT*sizeof(double));\n" - "}\n"); + generator->setModel(analyserModel); - EXPECT_EQ(fileContents("generator/coverage/model.modified.profile.h"), generator->interfaceCode()); - EXPECT_EQ(fileContents("generator/coverage/model.modified.profile.c"), generator->implementationCode()); + EXPECT_EQ(fileContents("generator/sine_model_imports/model.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/sine_model_imports/model.c"), generator->implementationCode()); - profile = libcellml::GeneratorProfile::create(); + auto profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); generator->setProfile(profile); - profile->setHasInterface(false); + EXPECT_EQ(fileContents("generator/sine_model_imports/model.py"), generator->implementationCode()); +} + +TEST(Generator, analyserModelScopeTest) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.cellml")); + + libcellml::AnalyserModelPtr analyserModel = nullptr; + + { + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(model); + + EXPECT_EQ(size_t(0), analyser->errorCount()); - profile->setXorString("^"); - profile->setHasXorOperator(true); + analyserModel = analyser->model(); + } - profile->setPowerString("^^"); - profile->setSquareString("sqr"); - profile->setHasPowerOperator(true); + auto generator = libcellml::Generator::create(); - profile->setPiecewiseIfString("piecewise([CONDITION], [IF_STATEMENT]"); - profile->setPiecewiseElseString(", [ELSE_STATEMENT])"); - profile->setHasConditionalOperator(false); + generator->setModel(analyserModel); - profile->setInterfaceFileNameString("customheaderfile.h"); + EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/hodgkin_huxley_squid_axon_model_1952/model.c"), generator->implementationCode()); +} - profile->setImplementationHeaderString("#include \"[INTERFACE_FILE_NAME]\"\n"); +TEST(Generator, daeModel) +{ + auto parser = libcellml::Parser::create(false); + auto model = parser->parseModel(fileContents("generator/dae_cellml_1_1_model/model.cellml")); - profile->setImplementationVersionString(""); + EXPECT_EQ(size_t(0), parser->errorCount()); - profile->setImplementationLibcellmlVersionString(""); + auto analyser = libcellml::Analyser::create(); - profile->setImplementationStateCountString(""); + analyser->analyseModel(model); - profile->setImplementationVariableCountString(""); + EXPECT_EQ(size_t(0), analyser->errorCount()); - profile->setVariableTypeObjectString(false, false, ""); - profile->setVariableTypeObjectString(false, true, ""); - profile->setVariableTypeObjectString(true, false, ""); - profile->setVariableTypeObjectString(true, true, ""); + auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); - profile->setVariableOfIntegrationVariableTypeString(""); - profile->setStateVariableTypeString(""); - profile->setConstantVariableTypeString(""); - profile->setComputedConstantVariableTypeString(""); - profile->setAlgebraicVariableTypeString(""); - profile->setExternalVariableTypeString(""); + generator->setModel(analyserModel); - profile->setVariableInfoObjectString(""); + EXPECT_EQ(fileContents("generator/dae_cellml_1_1_model/model.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/dae_cellml_1_1_model/model.c"), generator->implementationCode()); - profile->setImplementationVoiInfoString(""); + auto profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); - profile->setImplementationStateInfoString(""); + generator->setProfile(profile); - profile->setImplementationVariableInfoString(""); + EXPECT_EQ(fileContents("generator/dae_cellml_1_1_model/model.py"), generator->implementationCode()); +} - profile->setVariableInfoEntryString(""); +TEST(Generator, variableInitialisedUsingAConstant) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/variable_initialised_using_a_constant/model.cellml")); - profile->setImplementationCreateStatesArrayMethodString(""); + EXPECT_EQ(size_t(0), parser->issueCount()); - profile->setImplementationCreateVariablesArrayMethodString(""); + auto analyser = libcellml::Analyser::create(); - profile->setImplementationDeleteArrayMethodString(""); + analyser->analyseModel(model); - profile->setImplementationComputeVariablesMethodString(false, false, ""); - profile->setImplementationComputeVariablesMethodString(false, true, ""); - profile->setImplementationComputeVariablesMethodString(true, false, ""); - profile->setImplementationComputeVariablesMethodString(true, true, ""); + EXPECT_EQ(size_t(0), analyser->errorCount()); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); - EXPECT_EQ(fileContents("generator/coverage/model.out"), generator->implementationCode()); + auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); + + generator->setModel(analyserModel); + + EXPECT_EQ(fileContents("generator/variable_initialised_using_a_constant/model.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/variable_initialised_using_a_constant/model.c"), generator->implementationCode()); - profile = libcellml::GeneratorProfile::create(); + auto profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); generator->setProfile(profile); - profile->setHasInterface(true); + EXPECT_EQ(fileContents("generator/variable_initialised_using_a_constant/model.py"), generator->implementationCode()); +} + +TEST(Generator, modelOutOfScope) +{ + auto analyser = libcellml::Analyser::create(); + { + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/ode_multiple_dependent_odes/model.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); - profile->setEqString("eq"); - profile->setNeqString("neq"); - profile->setLtString("lt"); - profile->setLeqString("leq"); - profile->setGtString("gt"); - profile->setGeqString("geq"); - profile->setAndString("and"); - profile->setOrString("or"); - profile->setNotString("not"); + analyser->analyseModel(model); + } - profile->setHasEqOperator(false); - profile->setHasNeqOperator(false); - profile->setHasLtOperator(false); - profile->setHasLeqOperator(false); - profile->setHasGtOperator(false); - profile->setHasGeqOperator(false); - profile->setHasAndOperator(false); - profile->setHasOrOperator(false); - profile->setHasNotOperator(false); + EXPECT_EQ(size_t(0), analyser->errorCount()); - profile->setImplementationHeaderString(""); + auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); - profile->setInterfaceVersionString(""); - profile->setImplementationVersionString(""); + generator->setModel(analyserModel); - profile->setInterfaceLibcellmlVersionString(""); - profile->setImplementationLibcellmlVersionString(""); + auto profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); - profile->setInterfaceStateCountString(""); - profile->setImplementationStateCountString(""); + generator->setProfile(profile); - profile->setInterfaceVariableCountString(""); - profile->setImplementationVariableCountString(""); + EXPECT_EQ(fileContents("generator/ode_multiple_dependent_odes/model.py"), generator->implementationCode()); +} - profile->setVariableTypeObjectString(false, false, ""); - profile->setVariableTypeObjectString(false, true, ""); - profile->setVariableTypeObjectString(true, false, ""); - profile->setVariableTypeObjectString(true, true, ""); +TEST(Generator, unknownVariableMarkedAsExternalVariable) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("generator/unknown_variable_as_external_variable/model.cellml")); - profile->setVariableOfIntegrationVariableTypeString(""); - profile->setStateVariableTypeString(""); - profile->setConstantVariableTypeString(""); - profile->setComputedConstantVariableTypeString(""); - profile->setAlgebraicVariableTypeString(""); - profile->setExternalVariableTypeString(""); + EXPECT_EQ(size_t(0), parser->issueCount()); - profile->setVariableInfoObjectString(""); + auto analyser = libcellml::Analyser::create(); - profile->setInterfaceVoiInfoString(""); - profile->setImplementationVoiInfoString(""); + analyser->addExternalVariable(libcellml::AnalyserExternalVariable::create(model->component("SLC_template3_ss")->variable("P_3"))); - profile->setInterfaceStateInfoString(""); - profile->setImplementationStateInfoString(""); + analyser->analyseModel(model); - profile->setInterfaceVariableInfoString(""); - profile->setImplementationVariableInfoString(""); + EXPECT_EQ(size_t(0), analyser->errorCount()); - profile->setVariableInfoEntryString(""); + auto analyserModel = analyser->model(); + auto generator = libcellml::Generator::create(); - EXPECT_EQ(fileContents("generator/coverage/model.interface.out"), generator->interfaceCode()); - EXPECT_EQ(fileContents("generator/coverage/model.implementation.out"), generator->implementationCode()); + generator->setModel(analyserModel); - profile->setProfile(libcellml::GeneratorProfile::Profile::PYTHON); + EXPECT_EQ(fileContents("generator/unknown_variable_as_external_variable/model.h"), generator->interfaceCode()); + EXPECT_EQ(fileContents("generator/unknown_variable_as_external_variable/model.c"), generator->implementationCode()); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); - EXPECT_EQ(fileContents("generator/coverage/model.py"), generator->implementationCode()); + auto profile = libcellml::GeneratorProfile::create(libcellml::GeneratorProfile::Profile::PYTHON); - profile->setImplementationCreateStatesArrayMethodString("\n" - "def create_states_vector():\n" - " return [nan]*STATE_COUNT\n"); + generator->setProfile(profile); - EXPECT_EQ(EMPTY_STRING, generator->interfaceCode()); - EXPECT_EQ(fileContents("generator/coverage/model.modified.profile.py"), generator->implementationCode()); + EXPECT_EQ(fileContents("generator/unknown_variable_as_external_variable/model.py"), generator->implementationCode()); } diff --git a/tests/generator/generatorprofile.cpp b/tests/generator/generatorprofile.cpp index 076ce8e3a..29f02fcf1 100644 --- a/tests/generator/generatorprofile.cpp +++ b/tests/generator/generatorprofile.cpp @@ -38,6 +38,7 @@ TEST(GeneratorProfile, defaultGeneralValues) libcellml::GeneratorProfilePtr generatorProfile = libcellml::GeneratorProfile::create(); EXPECT_EQ(libcellml::GeneratorProfile::Profile::C, generatorProfile->profile()); + EXPECT_EQ("c", libcellml::GeneratorProfile::profileAsString(generatorProfile->profile())); EXPECT_EQ(true, generatorProfile->hasInterface()); } @@ -46,7 +47,7 @@ TEST(GeneratorProfile, defaultRelationalAndLogicalOperatorValues) { libcellml::GeneratorProfilePtr generatorProfile = libcellml::GeneratorProfile::create(); - EXPECT_EQ(" = ", generatorProfile->assignmentString()); + EXPECT_EQ(" = ", generatorProfile->equalityString()); EXPECT_EQ(" == ", generatorProfile->eqString()); EXPECT_EQ(" != ", generatorProfile->neqString()); EXPECT_EQ(" < ", generatorProfile->ltString()); @@ -270,7 +271,7 @@ TEST(GeneratorProfile, defaultMiscellaneousValues) generatorProfile->implementationHeaderString()); EXPECT_EQ("extern const char VERSION[];\n", generatorProfile->interfaceVersionString()); - EXPECT_EQ("const char VERSION[] = \"0.3.0\";\n", generatorProfile->implementationVersionString()); + EXPECT_EQ("const char VERSION[] = \"0.4.0\";\n", generatorProfile->implementationVersionString()); EXPECT_EQ("extern const char LIBCELLML_VERSION[];\n", generatorProfile->interfaceLibcellmlVersionString()); EXPECT_EQ("const char LIBCELLML_VERSION[] = \"[LIBCELLML_VERSION]\";\n", generatorProfile->implementationLibcellmlVersionString()); @@ -351,24 +352,96 @@ TEST(GeneratorProfile, defaultMiscellaneousValues) EXPECT_EQ("variables", generatorProfile->variablesArrayString()); EXPECT_EQ("typedef double (* ExternalVariable)(double *variables, size_t index);\n", generatorProfile->externalVariableMethodTypeDefinitionString(false)); - EXPECT_EQ("typedef double (* ExternalVariable)(double voi, double *states, double *variables, size_t index);\n", generatorProfile->externalVariableMethodTypeDefinitionString(true)); + EXPECT_EQ("typedef double (* ExternalVariable)(double voi, double *states, double *rates, double *variables, size_t index);\n", generatorProfile->externalVariableMethodTypeDefinitionString(true)); EXPECT_EQ("externalVariable(variables, [INDEX])", generatorProfile->externalVariableMethodCallString(false)); - EXPECT_EQ("externalVariable(voi, states, variables, [INDEX])", generatorProfile->externalVariableMethodCallString(true)); + EXPECT_EQ("externalVariable(voi, states, rates, variables, [INDEX])", generatorProfile->externalVariableMethodCallString(true)); EXPECT_EQ("double * createStatesArray();\n", generatorProfile->interfaceCreateStatesArrayMethodString()); EXPECT_EQ("double * createStatesArray()\n" "{\n" - " return malloc(STATE_COUNT*sizeof(double));\n" + " double *res = (double *) malloc(STATE_COUNT*sizeof(double));\n" + "\n" + " for (size_t i = 0; i < STATE_COUNT; ++i) {\n" + " res[i] = NAN;\n" + " }\n" + "\n" + " return res;\n" "}\n", generatorProfile->implementationCreateStatesArrayMethodString()); + EXPECT_EQ("typedef struct {\n" + " double *variables;\n" + "} RootFindingInfo;\n", + generatorProfile->rootFindingInfoObjectString(false)); + EXPECT_EQ("typedef struct {\n" + " double voi;\n" + " double *states;\n" + " double *rates;\n" + " double *variables;\n" + "} RootFindingInfo;\n", + generatorProfile->rootFindingInfoObjectString(true)); + EXPECT_EQ("extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *),\n" + " double *u, int n, void *data);\n", + generatorProfile->externNlaSolveMethodString()); + EXPECT_EQ("findRoot[INDEX](variables);\n", + generatorProfile->findRootCallString(false)); + EXPECT_EQ("findRoot[INDEX](voi, states, rates, variables);\n", + generatorProfile->findRootCallString(true)); + EXPECT_EQ("void findRoot[INDEX](double *variables)\n" + "{\n" + " RootFindingInfo rfi = { variables };\n" + " double u[[SIZE]];\n" + "\n" + "[CODE]" + "}\n", + generatorProfile->findRootMethodString(false)); + EXPECT_EQ("void findRoot[INDEX](double voi, double *states, double *rates, double *variables)\n" + "{\n" + " RootFindingInfo rfi = { voi, states, rates, variables };\n" + " double u[[SIZE]];\n" + "\n" + "[CODE]" + "}\n", + generatorProfile->findRootMethodString(true)); + EXPECT_EQ("nlaSolve(objectiveFunction[INDEX], u, [SIZE], &rfi);\n", + generatorProfile->nlaSolveCallString(false)); + EXPECT_EQ("nlaSolve(objectiveFunction[INDEX], u, [SIZE], &rfi);\n", + generatorProfile->nlaSolveCallString(true)); + EXPECT_EQ("void objectiveFunction[INDEX](double *u, double *f, void *data)\n" + "{\n" + " double *variables = ((RootFindingInfo *) data)->variables;\n" + "\n" + "[CODE]" + "}\n", + generatorProfile->objectiveFunctionMethodString(false)); + EXPECT_EQ("void objectiveFunction[INDEX](double *u, double *f, void *data)\n" + "{\n" + " double voi = ((RootFindingInfo *) data)->voi;\n" + " double *states = ((RootFindingInfo *) data)->states;\n" + " double *rates = ((RootFindingInfo *) data)->rates;\n" + " double *variables = ((RootFindingInfo *) data)->variables;\n" + "\n" + "[CODE]" + "}\n", + generatorProfile->objectiveFunctionMethodString(true)); + EXPECT_EQ("u", + generatorProfile->uArrayString()); + EXPECT_EQ("f", + generatorProfile->fArrayString()); + EXPECT_EQ("double * createVariablesArray();\n", generatorProfile->interfaceCreateVariablesArrayMethodString()); EXPECT_EQ("double * createVariablesArray()\n" "{\n" - " return malloc(VARIABLE_COUNT*sizeof(double));\n" + " double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double));\n" + "\n" + " for (size_t i = 0; i < VARIABLE_COUNT; ++i) {\n" + " res[i] = NAN;\n" + " }\n" + "\n" + " return res;\n" "}\n", generatorProfile->implementationCreateVariablesArrayMethodString()); @@ -396,17 +469,17 @@ TEST(GeneratorProfile, defaultMiscellaneousValues) "}\n", generatorProfile->implementationInitialiseVariablesMethodString(false, true)); - EXPECT_EQ("void initialiseVariables(double *states, double *variables);\n", + EXPECT_EQ("void initialiseVariables(double *states, double *rates, double *variables);\n", generatorProfile->interfaceInitialiseVariablesMethodString(true, false)); - EXPECT_EQ("void initialiseVariables(double *states, double *variables)\n" + EXPECT_EQ("void initialiseVariables(double *states, double *rates, double *variables)\n" "{\n" "[CODE]" "}\n", generatorProfile->implementationInitialiseVariablesMethodString(true, false)); - EXPECT_EQ("void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable);\n", + EXPECT_EQ("void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable);\n", generatorProfile->interfaceInitialiseVariablesMethodString(true, true)); - EXPECT_EQ("void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable)\n" + EXPECT_EQ("void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable)\n" "{\n" "[CODE]" "}\n", @@ -497,6 +570,7 @@ TEST(GeneratorProfile, generalSettings) generatorProfile->setHasInterface(falseValue); EXPECT_EQ(profile, generatorProfile->profile()); + EXPECT_EQ("python", libcellml::GeneratorProfile::profileAsString(generatorProfile->profile())); EXPECT_EQ(falseValue, generatorProfile->hasInterface()); } @@ -509,7 +583,7 @@ TEST(GeneratorProfile, relationalAndLogicalOperators) const bool trueValue = true; const bool falseValue = false; - generatorProfile->setAssignmentString(value); + generatorProfile->setEqualityString(value); generatorProfile->setEqString(value); generatorProfile->setNeqString(value); generatorProfile->setLtString(value); @@ -532,7 +606,7 @@ TEST(GeneratorProfile, relationalAndLogicalOperators) generatorProfile->setHasXorOperator(trueValue); generatorProfile->setHasNotOperator(falseValue); - EXPECT_EQ(value, generatorProfile->assignmentString()); + EXPECT_EQ(value, generatorProfile->equalityString()); EXPECT_EQ(value, generatorProfile->eqString()); EXPECT_EQ(value, generatorProfile->neqString()); EXPECT_EQ(value, generatorProfile->ltString()); @@ -834,6 +908,20 @@ TEST(GeneratorProfile, miscellaneous) generatorProfile->setInterfaceCreateStatesArrayMethodString(value); generatorProfile->setImplementationCreateStatesArrayMethodString(value); + generatorProfile->setRootFindingInfoObjectString(false, value); + generatorProfile->setRootFindingInfoObjectString(true, value); + generatorProfile->setExternNlaSolveMethodString(value); + generatorProfile->setFindRootCallString(false, value); + generatorProfile->setFindRootCallString(true, value); + generatorProfile->setFindRootMethodString(false, value); + generatorProfile->setFindRootMethodString(true, value); + generatorProfile->setNlaSolveCallString(false, value); + generatorProfile->setNlaSolveCallString(true, value); + generatorProfile->setObjectiveFunctionMethodString(false, value); + generatorProfile->setObjectiveFunctionMethodString(true, value); + generatorProfile->setUArrayString(value); + generatorProfile->setFArrayString(value); + generatorProfile->setInterfaceCreateVariablesArrayMethodString(value); generatorProfile->setImplementationCreateVariablesArrayMethodString(value); @@ -949,6 +1037,20 @@ TEST(GeneratorProfile, miscellaneous) EXPECT_EQ(value, generatorProfile->interfaceCreateStatesArrayMethodString()); EXPECT_EQ(value, generatorProfile->implementationCreateStatesArrayMethodString()); + EXPECT_EQ(value, generatorProfile->rootFindingInfoObjectString(false)); + EXPECT_EQ(value, generatorProfile->rootFindingInfoObjectString(true)); + EXPECT_EQ(value, generatorProfile->externNlaSolveMethodString()); + EXPECT_EQ(value, generatorProfile->findRootCallString(false)); + EXPECT_EQ(value, generatorProfile->findRootCallString(true)); + EXPECT_EQ(value, generatorProfile->findRootMethodString(false)); + EXPECT_EQ(value, generatorProfile->findRootMethodString(true)); + EXPECT_EQ(value, generatorProfile->nlaSolveCallString(false)); + EXPECT_EQ(value, generatorProfile->nlaSolveCallString(true)); + EXPECT_EQ(value, generatorProfile->objectiveFunctionMethodString(false)); + EXPECT_EQ(value, generatorProfile->objectiveFunctionMethodString(true)); + EXPECT_EQ(value, generatorProfile->uArrayString()); + EXPECT_EQ(value, generatorProfile->fArrayString()); + EXPECT_EQ(value, generatorProfile->interfaceCreateVariablesArrayMethodString()); EXPECT_EQ(value, generatorProfile->implementationCreateVariablesArrayMethodString()); diff --git a/tests/gtest/src/gtest-all.cc b/tests/gtest/src/gtest-all.cc index 9f2b3d565..b19c9f2a8 100644 --- a/tests/gtest/src/gtest-all.cc +++ b/tests/gtest/src/gtest-all.cc @@ -8676,7 +8676,7 @@ static void StackLowerThanAddress(const void* ptr, bool* result) { // Make sure AddressSanitizer does not tamper with the stack here. GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ static bool StackGrowsDown() { - int dummy; + int dummy = 0; bool result; StackLowerThanAddress(&dummy, &result); return result; diff --git a/tests/importer/importer.cpp b/tests/importer/importer.cpp index 1092cccea..3f959e71a 100644 --- a/tests/importer/importer.cpp +++ b/tests/importer/importer.cpp @@ -879,6 +879,95 @@ TEST(Importer, clearModelImportsBeforeResolving) EXPECT_EQ(size_t(0), importer->issueCount()); } +TEST(Importer, isResolvedUnitsNoModel) +{ + auto units = libcellml::Units::create("units"); + + EXPECT_FALSE(units->requiresImports()); +} + +TEST(Importer, isResolvedUnitsWithModel) +{ + auto model = libcellml::Model::create("model"); + auto units = libcellml::Units::create("units"); + + model->addUnits(units); + + EXPECT_FALSE(units->requiresImports()); +} + +TEST(Importer, isResolvedUnitsWithChild) +{ + auto model = libcellml::Model::create("model"); + auto units = libcellml::Units::create("units"); + units->addUnit("second"); + + model->addUnits(units); + + EXPECT_FALSE(units->requiresImports()); +} + +TEST(Importer, isResolvedUnitsWithNonExistentChild) +{ + auto model = libcellml::Model::create("model"); + auto units = libcellml::Units::create("units"); + units->addUnit("bumble"); + + model->addUnits(units); + + EXPECT_FALSE(units->requiresImports()); +} + +TEST(Importer, isResolvedUnitsWithNonStandardChild) +{ + auto model = libcellml::Model::create("model"); + auto units = libcellml::Units::create("units"); + auto unitsBumble = libcellml::Units::create("bumble"); + units->addUnit("bumble"); + + model->addUnits(units); + model->addUnits(unitsBumble); + + EXPECT_FALSE(units->requiresImports()); +} + +TEST(Importer, isResolvedUnitsWithReferenceToSelf) +{ + auto model = libcellml::Model::create("model"); + auto units = libcellml::Units::create("units"); + units->addUnit("units"); + + model->addUnits(units); + + EXPECT_FALSE(units->requiresImports()); +} + +TEST(Importer, isResolvedUnitsNotImportFullyDefined) +{ + auto model = libcellml::Model::create("standard_model"); + auto units = libcellml::Units::create("my_units"); + units->addUnit("second", -1.0); + + model->addUnits(units); + + EXPECT_FALSE(model->hasUnresolvedImports()); + EXPECT_TRUE(units->isResolved()); + EXPECT_TRUE(units->isDefined()); +} + +TEST(Importer, isResolvedUnitsNotImportPartiallyDefined) +{ + auto model = libcellml::Model::create("standard_model"); + auto units = libcellml::Units::create("my_units"); + units->addUnit("seconds", -1.0); + + model->addUnits(units); + + EXPECT_FALSE(model->hasUnresolvedImports()); + EXPECT_TRUE(units->isResolved()); + EXPECT_FALSE(units->isDefined()); +} + TEST(Importer, isResolvedUnitsOverOneLevel) { auto parser = libcellml::Parser::create(); @@ -1001,9 +1090,11 @@ TEST(Importer, isResolvedReferencedUnitsMissing) auto units = model->units(0); - EXPECT_FALSE(units->isResolved()); + EXPECT_TRUE(units->isResolved()); + EXPECT_FALSE(units->isDefined()); - EXPECT_TRUE(model->hasUnresolvedImports()); + EXPECT_FALSE(model->hasUnresolvedImports()); + EXPECT_FALSE(model->isDefined()); } TEST(Importer, isResolvedCircularImportUnits) @@ -1025,6 +1116,7 @@ TEST(Importer, isResolvedCircularImportUnits) importModel->units("u2")->importSource()->model()->units("u3")->importSource()->model()->units("i_am_cyclic")->importSource()->setModel(importModel); EXPECT_FALSE(u->isResolved()); + EXPECT_TRUE(model->hasUnresolvedImports()); } TEST(Importer, isResolvedCircularImportComponent) @@ -1046,6 +1138,7 @@ TEST(Importer, isResolvedCircularImportComponent) importModel->component("c2")->importSource()->model()->component("c3")->importSource()->model()->component("i_am_cyclic")->importSource()->setModel(importModel); EXPECT_FALSE(c->isResolved()); + EXPECT_TRUE(model->hasUnresolvedImports()); } TEST(Importer, removeAllModels) @@ -1136,6 +1229,21 @@ TEST(Importer, importInvalidUnitsFromCellmlModel) EXPECT_EQ(e, importer->error(0)->description()); } +TEST(Importer, importUnitsThatEncounterARelatedImportError) +{ + const std::string e = "Encountered an error when resolving units 'unitsB_imported' from '" + resourcePath("importer/simple_model.cellml") + "'."; + auto importer = libcellml::Importer::create(); + auto parser = libcellml::Parser::create(); + + auto model = parser->parseModel(fileContents("importer/import_invalid_component.cellml")); + model->component(0)->setImportReference("component4"); + model->component(0)->setName("component4_imported"); + + importer->resolveImports(model, resourcePath("importer")); + EXPECT_EQ(size_t(1), importer->errorCount()); + EXPECT_EQ(e, importer->error(0)->description()); +} + TEST(Importer, importInvalidComponentFromCellmlModelComponentError) { auto e = "Encountered an error when resolving component 'component1_imported' from '" + resourcePath("importer/invalid_model.cellml") + "'."; @@ -1183,3 +1291,27 @@ TEST(Importer, importInvalidComponentFromCellmlModelResetError) EXPECT_EQ(size_t(1), importer->errorCount()); EXPECT_EQ(e, importer->error(0)->description()); } + +void testImporterWithInvalidImportedModels(bool strict) +{ + const std::string e = "The attempt to import the model at '" + resourcePath("importer/triangle_units_opposite.cellml") + "' failed: the file is not valid XML."; + + auto importer = libcellml::Importer::create(strict); + auto parser = libcellml::Parser::create(strict); + + auto model = parser->parseModel(fileContents("importer/triangle_units_point.cellml")); + + importer->resolveImports(model, resourcePath("importer")); + EXPECT_EQ(size_t(1), importer->errorCount()); + EXPECT_EQ(e, importer->error(0)->description()); +} + +TEST(Importer, importingCommonUnitsFromTriangleImportStructurePermissive) +{ + testImporterWithInvalidImportedModels(false); +} + +TEST(Importer, importingCommonUnitsFromTriangleImportStructureStrict) +{ + testImporterWithInvalidImportedModels(true); +} diff --git a/tests/importer/model_flattening.cpp b/tests/importer/model_flattening.cpp index 9d8a07df3..181d59f3d 100644 --- a/tests/importer/model_flattening.cpp +++ b/tests/importer/model_flattening.cpp @@ -782,6 +782,9 @@ TEST(ModelFlattening, importedComponentsWithConnectionsToChildren) " \n" " \n" " \n" + " \n" + " \n" + " \n" " \n" " \n" " \n" @@ -795,6 +798,9 @@ TEST(ModelFlattening, importedComponentsWithConnectionsToChildren) const std::string e = "\n" "\n" + " \n" + " \n" + " \n" " \n" " \n" " \n" @@ -871,6 +877,42 @@ TEST(ModelFlattening, resolveFlattenCircularImportsComponents) EXPECT_EQ(nullptr, flatModel); } +TEST(ModelFlattening, resolveFlattenNonCircularImportsUnits) +{ + auto importer = libcellml::Importer::create(); + auto model = libcellml::Model::create("model"); + auto importModel = libcellml::Model::create("importModel"); + + auto unitsWithImportedUnit = libcellml::Units::create("one_imported_unit"); + unitsWithImportedUnit->addUnit("metre"); + unitsWithImportedUnit->addUnit("importedUnit"); + + auto fancyUnits = libcellml::Units::create("fancyUnits"); + fancyUnits->addUnit("per_becquerel"); + + auto perBecquerel = libcellml::Units::create("per_becquerel"); + perBecquerel->addUnit(libcellml::Units::StandardUnit::BECQUEREL, -1.0); + + importModel->addUnits(fancyUnits); + importModel->addUnits(perBecquerel); + + auto importSource = libcellml::ImportSource::create(); + importSource->setUrl("here.cellml"); + importSource->setModel(importModel); + + auto importedUnit = libcellml::Units::create("importedUnit"); + importedUnit->setImportReference("fancyUnits"); + importedUnit->setImportSource(importSource); + + model->addUnits(unitsWithImportedUnit); + model->addUnits(importedUnit); + + EXPECT_FALSE(model->hasUnresolvedImports()); + + auto flatModel = importer->flattenModel(model); + EXPECT_EQ(size_t(0), importer->issueCount()); +} + TEST(ModelFlattening, resolveFlattenCircularImportsUnits) { const std::string resolveError = @@ -949,6 +991,7 @@ TEST(ModelFlattening, resolveFlattenMissingUnits) { const std::string e = "Units 'units1_imported' imports units named 'units1' from the model imported from '" + resourcePath("importer/") + "units_source.cellml'. The units could not be found."; + auto parser = libcellml::Parser::create(); auto originalModel = parser->parseModel(fileContents("importer/units_imported.cellml")); auto importer = libcellml::Importer::create(); @@ -966,3 +1009,857 @@ TEST(ModelFlattening, resolveFlattenMissingUnits) EXPECT_EQ(size_t(1), importer->issueCount()); EXPECT_EQ(e, importer->issue(0)->description()); } + +TEST(ModelFlattening, importSimilarEntitiesMultipleTimes) +{ + const std::string e = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + auto importer = libcellml::Importer::create(); + + auto model = libcellml::Model::create("model"); + auto importModel1 = libcellml::Model::create("importModel1"); + auto importModel2 = libcellml::Model::create("importModel2"); + + auto similarUnits = libcellml::Units::create("similar_units"); + similarUnits->addUnit("second", -1.0); + + auto similarUnits1 = libcellml::Units::create("similar_units"); + similarUnits1->addUnit("second", -2.0); + + auto similarUnits2 = libcellml::Units::create("similar_units"); + similarUnits2->addUnit("second", -0.5); + + auto component = libcellml::Component::create("base_component"); + auto variable = libcellml::Variable::create("variable_similar"); + variable->setUnits("similar_units"); + component->addVariable(variable); + + model->addUnits(similarUnits); + model->addComponent(component); + + auto component1 = libcellml::Component::create("component_1"); + component1->addComponent(component->clone()); + importModel1->addUnits(similarUnits1); + importModel1->addComponent(component1); + importModel1->linkUnits(); + + auto component2 = libcellml::Component::create("component_2"); + component2->addComponent(component->clone()); + importModel2->addUnits(similarUnits2); + importModel2->addComponent(component2); + importModel2->linkUnits(); + + auto importedComponent1 = libcellml::Component::create("component1"); + auto importedComponent2 = libcellml::Component::create("component2"); + + model->addComponent(importedComponent1); + model->addComponent(importedComponent2); + + auto printer = libcellml::Printer::create(); + + auto importSource1 = libcellml::ImportSource::create(); + importSource1->setUrl("model1.cellml"); + importSource1->setModel(importModel1); + + auto importSource2 = libcellml::ImportSource::create(); + importSource2->setUrl("model2.cellml"); + importSource2->setModel(importModel2); + + importedComponent1->setImportSource(importSource1); + importedComponent1->setImportReference("component_1"); + + importedComponent2->setImportSource(importSource2); + importedComponent2->setImportReference("component_2"); + + EXPECT_FALSE(model->hasUnresolvedImports()); + + auto flatModel = importer->flattenModel(model); + EXPECT_EQ(size_t(0), importer->issueCount()); + + const std::string a = printer->printModel(flatModel); + EXPECT_EQ(e, a); +} + +TEST(ModelFlattening, proposedImportedUnitsAlreadyDefinedInModel) +{ + const std::string e = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("modelflattening/importedunitswithnameclashes.xml")); + auto importer = libcellml::Importer::create(); + + auto u = libcellml::Units::create("common_units_1"); + u->addUnit(libcellml::Units::StandardUnit::SECOND, libcellml::Units::Prefix::HECTO); + model->addUnits(u); + + EXPECT_TRUE(model->hasUnresolvedImports()); + importer->resolveImports(model, resourcePath("modelflattening/")); + EXPECT_FALSE(model->hasUnresolvedImports()); + + model = importer->flattenModel(model); + + auto printer = libcellml::Printer::create(); + + auto a = printer->printModel(model); + EXPECT_EQ(e, a); +} + +TEST(ModelFlattening, cascadedUnitsManuallyImported) +{ + const std::string e = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + auto importer = libcellml::Importer::create(); + + auto model = libcellml::Model::create("model"); + auto importModel1 = libcellml::Model::create("importModel1"); + auto importModel2 = libcellml::Model::create("importModel2"); + + auto firstUnits = libcellml::Units::create("first_units"); + firstUnits->addUnit("second", -1.0); + firstUnits->addUnit("units1_import"); + + auto secondUnits = libcellml::Units::create("second_units"); + secondUnits->addUnit("second", -2.0); + secondUnits->addUnit("units2_import"); + + auto thirdUnits = libcellml::Units::create("third_units"); + thirdUnits->addUnit("second", -0.5); + + auto component1 = libcellml::Component::create("base_component"); + auto variable = libcellml::Variable::create("variable"); + variable->setUnits(firstUnits); + component1->addVariable(variable); + + model->addUnits(firstUnits); + model->addComponent(component1); + + auto importedUnits1 = libcellml::Units::create("units1_import"); + auto importedUnits2 = libcellml::Units::create("units2_import"); + + model->addUnits(importedUnits1); + importModel1->addUnits(secondUnits); + importModel1->addUnits(importedUnits2); + importModel2->addUnits(thirdUnits); + + auto printer = libcellml::Printer::create(); + + auto importSource1 = libcellml::ImportSource::create(); + importSource1->setUrl("model1.cellml"); + importSource1->setModel(importModel1); + + auto importSource2 = libcellml::ImportSource::create(); + importSource2->setUrl("model2.cellml"); + importSource2->setModel(importModel2); + + importedUnits1->setImportSource(importSource1); + importedUnits1->setImportReference("second_units"); + + importedUnits2->setImportSource(importSource2); + importedUnits2->setImportReference("third_units"); + + EXPECT_FALSE(model->hasUnresolvedImports()); + + importer->addModel(importModel1, "model1.cellml"); + importer->addModel(importModel2, "model2.cellml"); + + auto flatModel = importer->flattenModel(model); + EXPECT_EQ(size_t(0), importer->issueCount()); + + const std::string a = printer->printModel(flatModel); + EXPECT_EQ(e, a); +} + +TEST(ModelFlattening, cascadedUnitsManuallyImportedWithoutImportSourcesAddedToImporter) +{ + const std::string e = + "Cyclic dependencies were found when attempting to flatten units in the model 'model'. The dependency loop is:\n" + " - units 'units1_import' specifies an import from ':this:' to ':this:'; and\n" + " - units 'units2_import' specifies an import from ':this:' to ':this:'."; + + auto importer = libcellml::Importer::create(); + + auto model = libcellml::Model::create("model"); + auto importModel1 = libcellml::Model::create("importModel1"); + auto importModel2 = libcellml::Model::create("importModel2"); + + auto firstUnits = libcellml::Units::create("first_units"); + firstUnits->addUnit("second", -1.0); + firstUnits->addUnit("units1_import"); + + auto secondUnits = libcellml::Units::create("second_units"); + secondUnits->addUnit("second", -2.0); + secondUnits->addUnit("units2_import"); + + auto thirdUnits = libcellml::Units::create("third_units"); + thirdUnits->addUnit("second", -0.5); + + auto component1 = libcellml::Component::create("base_component"); + auto variable = libcellml::Variable::create("variable"); + variable->setUnits(firstUnits); + component1->addVariable(variable); + + model->addUnits(firstUnits); + model->addComponent(component1); + + auto importedUnits1 = libcellml::Units::create("units1_import"); + auto importedUnits2 = libcellml::Units::create("units2_import"); + + model->addUnits(importedUnits1); + importModel1->addUnits(secondUnits); + importModel1->addUnits(importedUnits2); + importModel2->addUnits(thirdUnits); + + auto printer = libcellml::Printer::create(); + + auto importSource1 = libcellml::ImportSource::create(); + importSource1->setUrl("model1.cellml"); + importSource1->setModel(importModel1); + + auto importSource2 = libcellml::ImportSource::create(); + importSource2->setUrl("model2.cellml"); + importSource2->setModel(importModel2); + + importedUnits1->setImportSource(importSource1); + importedUnits1->setImportReference("second_units"); + + importedUnits2->setImportSource(importSource2); + importedUnits2->setImportReference("third_units"); + + EXPECT_FALSE(model->hasUnresolvedImports()); + + auto flatModel = importer->flattenModel(model); + EXPECT_EQ(size_t(1), importer->issueCount()); + EXPECT_EQ(e, importer->issue(0)->description()); +} + +TEST(ModelFlattening, cascadedUnitsManuallyImportedMissingUnitReferences) +{ + const std::string e = "The model is not fully defined."; + + auto importer = libcellml::Importer::create(); + + auto model = libcellml::Model::create("model"); + auto importModel1 = libcellml::Model::create("importModel1"); + auto importModel2 = libcellml::Model::create("importModel2"); + + auto firstUnits = libcellml::Units::create("first_units"); + firstUnits->addUnit("second", -1.0); + firstUnits->addUnit("units1_import"); + + auto secondUnits = libcellml::Units::create("second_units"); + secondUnits->addUnit("second", -2.0); + secondUnits->addUnit("units2_import"); + + auto thirdUnits = libcellml::Units::create("third_units"); + thirdUnits->addUnit("second", -0.5); + thirdUnits->addUnit(""); + thirdUnits->addUnit("missing_units"); + + auto component1 = libcellml::Component::create("base_component"); + auto variable = libcellml::Variable::create("variable"); + variable->setUnits(firstUnits); + component1->addVariable(variable); + + model->addUnits(firstUnits); + model->addComponent(component1); + + auto importedUnits1 = libcellml::Units::create("units1_import"); + auto importedUnits2 = libcellml::Units::create("units2_import"); + + model->addUnits(importedUnits1); + importModel1->addUnits(secondUnits); + importModel1->addUnits(importedUnits2); + importModel2->addUnits(thirdUnits); + + auto printer = libcellml::Printer::create(); + + auto importSource1 = libcellml::ImportSource::create(); + importSource1->setUrl("model1.cellml"); + importSource1->setModel(importModel1); + + auto importSource2 = libcellml::ImportSource::create(); + importSource2->setUrl("model2.cellml"); + importSource2->setModel(importModel2); + + importedUnits1->setImportSource(importSource1); + importedUnits1->setImportReference("second_units"); + + importedUnits2->setImportSource(importSource2); + importedUnits2->setImportReference("third_units"); + + EXPECT_FALSE(model->hasUnresolvedImports()); + EXPECT_FALSE(model->isDefined()); + + importer->addModel(importModel1, "model1.cellml"); + importer->addModel(importModel2, "model2.cellml"); + + auto flatModel = importer->flattenModel(model); + EXPECT_EQ(size_t(1), importer->issueCount()); + EXPECT_EQ(e, importer->issue(0)->description()); +} + +TEST(ModelFlattening, importCascadingUnitsImports) +{ + const std::string e = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + auto importer = libcellml::Importer::create(); + auto parser = libcellml::Parser::create(); + + auto model = parser->parseModel(fileContents("importer/model_cascaded_units.cellml")); + + importer->resolveImports(model, resourcePath("importer")); + EXPECT_EQ(size_t(0), importer->errorCount()); + + auto flatModel = importer->flattenModel(model); + EXPECT_EQ(size_t(0), importer->issueCount()); + + auto printer = libcellml::Printer::create(); + const std::string a = printer->printModel(flatModel); + EXPECT_EQ(e, a); +} + +TEST(ModelFlattening, importingUnitsWithSameNameDoesntResultInRepeatedUnits) +{ + auto importer = libcellml::Importer::create(); + auto parser = libcellml::Parser::create(); + auto validator = libcellml::Validator::create(); + + auto model = parser->parseModel(fileContents("importer/triangle_units_point_I.cellml")); + + EXPECT_EQ(size_t(0), importer->errorCount()); + + importer->resolveImports(model, resourcePath("importer")); + + for (size_t i = 0; i < importer->libraryCount(); ++i) { + validator->validateModel(importer->library(i)); + EXPECT_EQ(size_t(0), validator->errorCount()); + } + + auto flattenedModel = importer->flattenModel(model); + + EXPECT_EQ(size_t(1), flattenedModel->unitsCount()); + EXPECT_EQ("mm", flattenedModel->units(0)->name()); +} + +TEST(ModelFlattening, importingAliasedUnits) +{ + const std::string importModelString = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + const std::string modelString = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + const std::string e = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + auto importer = libcellml::Importer::create(); + auto parser = libcellml::Parser::create(); + auto validator = libcellml::Validator::create(); + + auto model = parser->parseModel(modelString); + auto importModel = parser->parseModel(importModelString); + + EXPECT_TRUE(model->hasUnresolvedImports()); + + importer->addModel(importModel, "change_model.cellml"); + + importer->resolveImports(model, "."); + auto flattenedModel = importer->flattenModel(model); + EXPECT_EQ(size_t(4), flattenedModel->unitsCount()); + + libcellml::PrinterPtr printer = libcellml::Printer::create(); + const std::string a = printer->printModel(flattenedModel); + EXPECT_EQ(e, a); +} + +TEST(ModelFlattening, importingAliasedUnitsWithoutReplacing) +{ + const std::string importModelString = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + const std::string modelString = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + const std::string e = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + auto importer = libcellml::Importer::create(); + auto parser = libcellml::Parser::create(); + auto validator = libcellml::Validator::create(); + + auto model = parser->parseModel(modelString); + auto importModel = parser->parseModel(importModelString); + + EXPECT_TRUE(model->hasUnresolvedImports()); + + importer->addModel(importModel, "change_model.cellml"); + + importer->resolveImports(model, "."); + auto flattenedModel = importer->flattenModel(model); + EXPECT_EQ(size_t(1), flattenedModel->unitsCount()); + + libcellml::PrinterPtr printer = libcellml::Printer::create(); + const std::string a = printer->printModel(flattenedModel); + EXPECT_EQ(e, a); +} + +TEST(ModelFlattening, importingComponentUsingEmptyUnitReference) +{ + const std::string unitsDefinitionModelString = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + const std::string importModelString = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + const std::string modelString = + "\n" + "\n" + " \n" + " \n" + " \n" + ""; + const std::string e = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + auto importer = libcellml::Importer::create(); + auto parser = libcellml::Parser::create(); + auto validator = libcellml::Validator::create(); + + auto model = parser->parseModel(modelString); + auto importModel = parser->parseModel(importModelString); + auto unitsDefinitionModel = parser->parseModel(unitsDefinitionModelString); + + EXPECT_TRUE(model->hasUnresolvedImports()); + + importer->addModel(importModel, "change_model.cellml"); + importer->addModel(unitsDefinitionModel, "units_definitions.cellml"); + + importer->resolveImports(model, "."); + auto flattenedModel = importer->flattenModel(model); + EXPECT_EQ(size_t(1), flattenedModel->unitsCount()); + + libcellml::PrinterPtr printer = libcellml::Printer::create(); + const std::string a = printer->printModel(flattenedModel); + EXPECT_EQ(e, a); +} + +TEST(ModelFlattening, importedComponentWithUnresolvedUnitsImport) +{ + const std::string unitsDefinitionsModelString = + "\n" + "\n" + " \n" + " \n" + " \n" + ""; + const std::string importModelString = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + const std::string modelString = + "\n" + "\n" + " \n" + " \n" + " \n" + ""; + + auto importer = libcellml::Importer::create(); + auto parser = libcellml::Parser::create(); + auto validator = libcellml::Validator::create(); + + auto model = parser->parseModel(modelString); + auto importModel = parser->parseModel(importModelString); + auto unitsDefinitionsModel = parser->parseModel(unitsDefinitionsModelString); + + importer->addModel(importModel, "base.cellml"); + importer->addModel(unitsDefinitionsModel, "units_definitions.cellml"); + + importer->resolveImports(model, "."); + EXPECT_TRUE(model->hasUnresolvedImports()); + + auto flattenedModel = importer->flattenModel(model); + EXPECT_EQ(nullptr, flattenedModel); +} + +TEST(ModelFlattening, importedUnitsUsingUnitWhichIsAnImportedUnits) +{ + const std::string unitsDefinitionsModelString = + "\n" + "\n" + " \n" + " \n" + " \n" + ""; + const std::string importModelString = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + const std::string modelString = + "\n" + "\n" + " \n" + " \n" + " \n" + ""; + const std::string e = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + auto importer = libcellml::Importer::create(); + auto parser = libcellml::Parser::create(); + auto validator = libcellml::Validator::create(); + + auto model = parser->parseModel(modelString); + auto importModel = parser->parseModel(importModelString); + auto unitsDefinitionsModel = parser->parseModel(unitsDefinitionsModelString); + + importer->addModel(importModel, "base.cellml"); + importer->addModel(unitsDefinitionsModel, "units_definitions.cellml"); + + importer->resolveImports(model, "."); + EXPECT_TRUE(model->hasUnresolvedImports()); + + auto flattenedModel = importer->flattenModel(model); + EXPECT_EQ(nullptr, flattenedModel); +} + +TEST(ModelFlattening, flatteningSimpleBondGraph) +{ + auto importer = libcellml::Importer::create(false); + auto parser = libcellml::Parser::create(false); + + auto model = parser->parseModel(fileContents("importer/simplebondgraph/cpp_coupling.cellml")); + importer->resolveImports(model, resourcePath("importer/simplebondgraph")); + + auto flatModel = importer->flattenModel(model); + EXPECT_EQ("C_main_vessel", flatModel->component(0)->variable(0)->name()); + EXPECT_EQ(size_t(1), flatModel->component(0)->variable(0)->equivalentVariableCount()); + EXPECT_EQ("C", flatModel->component(1)->variable(0)->name()); + EXPECT_EQ(size_t(1), flatModel->component(1)->variable(0)->equivalentVariableCount()); +} + +TEST(ModelFlattening, flatteningMediumBondGraph) +{ + auto importer = libcellml::Importer::create(false); + auto parser = libcellml::Parser::create(false); + + auto model = parser->parseModel(fileContents("importer/mediumbondgraph/cpp_coupling.cellml")); + importer->resolveImports(model, resourcePath("importer/mediumbondgraph")); + + auto flatModel = importer->flattenModel(model); + EXPECT_EQ("C_main_vessel", flatModel->component(0)->variable(0)->name()); + EXPECT_EQ(size_t(1), flatModel->component(0)->variable(0)->equivalentVariableCount()); + EXPECT_EQ("C", flatModel->component(2)->variable(1)->name()); + EXPECT_EQ(size_t(2), flatModel->component(2)->variable(1)->equivalentVariableCount()); +} + +TEST(ModelFlattening, flatteningComplexBondGraph) +{ + auto importer = libcellml::Importer::create(false); + auto parser = libcellml::Parser::create(false); + + auto model = parser->parseModel(fileContents("importer/complexbondgraph/cpp_coupling.cellml")); + importer->resolveImports(model, resourcePath("importer/complexbondgraph")); + + auto flatModel = importer->flattenModel(model); + EXPECT_EQ("C_main_vessel", flatModel->component(0)->variable(1)->name()); + EXPECT_EQ(size_t(1), flatModel->component(0)->variable(0)->equivalentVariableCount()); + EXPECT_EQ("C", flatModel->component(2)->variable(2)->name()); + EXPECT_EQ(size_t(2), flatModel->component(2)->variable(2)->equivalentVariableCount()); + EXPECT_EQ("C", flatModel->component(3)->variable(4)->name()); + EXPECT_EQ(size_t(1), flatModel->component(3)->variable(4)->equivalentVariableCount()); +} + +TEST(ModelFlattening, flatteningCheckImportModelsForChanges) +{ + const std::string eParent = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + const std::string eChild = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + auto importer = libcellml::Importer::create(false); + auto parser = libcellml::Parser::create(false); + auto printer = libcellml::Printer::create(); + + auto model = parser->parseModel(fileContents("modelflattening/user_ex_01/parent.cellml")); + importer->resolveImports(model, resourcePath("modelflattening/user_ex_01")); + + auto importedModel = importer->library(0); + + EXPECT_EQ(eChild, printer->printModel(importedModel)); + EXPECT_EQ(eParent, printer->printModel(model)); + + auto flatModel = importer->flattenModel(model); + + EXPECT_EQ(eChild, printer->printModel(importedModel)); + EXPECT_EQ(eParent, printer->printModel(model)); +} + +TEST(ModelFlattening, flatteningModelsRequiringUnitsNameChangesInvolvingImportedComponents) +{ + auto importer = libcellml::Importer::create(false); + auto parser = libcellml::Parser::create(false); + + auto model = parser->parseModel(fileContents("importer/HHComplete/MembraneModel.cellml")); + importer->resolveImports(model, resourcePath("importer/HHComplete")); + + EXPECT_FALSE(model->hasUnresolvedImports()); + + auto flatModel = importer->flattenModel(model); + EXPECT_NE(nullptr, flatModel); +} + +TEST(ModelFlattening, resolveImportsInvalidInput) +{ + auto importer = libcellml::Importer::create(); + + libcellml::ModelPtr model = nullptr; + + EXPECT_FALSE(importer->resolveImports(model, "not/used")); + EXPECT_EQ(size_t(1), importer->issueCount()); + EXPECT_EQ("Cannot resolve imports for null model.", importer->issue(0)->description()); +} diff --git a/tests/libxml2issues.2.9.10.h b/tests/libxml2issues.2.9.10.h new file mode 100644 index 000000000..9c7f9081e --- /dev/null +++ b/tests/libxml2issues.2.9.10.h @@ -0,0 +1,13 @@ +#pragma once + +#include "string" +#include "vector" + +// Version 2.9.10 of LibXml2 reports the following errors, +// used on Windows CI machines. +const std::vector expectedLibXml2Issues = { + "LibXml2 error: Opening and ending tag mismatch: ci line 6 and apply.", + "LibXml2 error: Opening and ending tag mismatch: ci line 6 and math.", + "LibXml2 error: Opening and ending tag mismatch: apply line 6 and math_wrap_as_single_root_element.", + "LibXml2 error: EndTag: ' expectedLibXml2Issues = { + "LibXml2 error: Opening and ending tag mismatch: ci line 6 and apply.", + "LibXml2 error: Opening and ending tag mismatch: ci line 6 and math.", + "LibXml2 error: Opening and ending tag mismatch: apply line 3 and math_wrap_as_single_root_element.", + "LibXml2 error: Premature end of data in tag math line 2.", + "LibXml2 error: Premature end of data in tag math_wrap_as_single_root_element line 1.", +}; diff --git a/tests/libxml2issues.2.9.13.h b/tests/libxml2issues.2.9.13.h new file mode 100644 index 000000000..c8c4096eb --- /dev/null +++ b/tests/libxml2issues.2.9.13.h @@ -0,0 +1,12 @@ +#pragma once + +#include "string" +#include "vector" + +// Version 2.9.13 of LibXml2 reports the following errors. +const std::vector expectedLibXml2Issues = { + "LibXml2 error: Opening and ending tag mismatch: ci line 6 and apply.", + "LibXml2 error: Opening and ending tag mismatch: ci line 6 and math.", + "LibXml2 error: Opening and ending tag mismatch: apply line 3 and math_wrap_as_single_root_element.", + "LibXml2 error: Premature end of data in tag math line 2.", +}; diff --git a/tests/libxml2issues.2.9.4.h b/tests/libxml2issues.2.9.4.h new file mode 100644 index 000000000..6f63dc074 --- /dev/null +++ b/tests/libxml2issues.2.9.4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "string" +#include "vector" + +// Version 2.9.4 of LibXml2 reports the following errors, +// used on Windows CI machines. +const std::vector expectedLibXml2Issues = { + "LibXml2 error: Opening and ending tag mismatch: ci line 6 and apply.", + "LibXml2 error: Opening and ending tag mismatch: ci line 6 and math.", + "LibXml2 error: Opening and ending tag mismatch: apply line 3 and math_wrap_as_single_root_element.", + "LibXml2 error: Premature end of data in tag math line 2.", + "LibXml2 error: Premature end of data in tag math_wrap_as_single_root_element line 1.", +}; diff --git a/tests/math/math.cpp b/tests/math/math.cpp index 71c450837..84a21cced 100644 --- a/tests/math/math.cpp +++ b/tests/math/math.cpp @@ -20,22 +20,7 @@ limitations under the License. #include -// Version 2.9.4 of LibXml2 reports the following errors, -// used on macOS and Linux CI machines. -const std::vector expectedIssues_2_9_4 = { - "LibXml2 error: Opening and ending tag mismatch: ci line 6 and apply.", - "LibXml2 error: Opening and ending tag mismatch: ci line 6 and math.", - "LibXml2 error: Premature end of data in tag apply line 3.", - "LibXml2 error: Premature end of data in tag math line 2.", -}; - -// Version 2.9.10 of LibXml2 reports the following errors, -// used on Windows CI machines. -const std::vector expectedIssues_2_9_10 = { - "LibXml2 error: Opening and ending tag mismatch: ci line 6 and apply.", - "LibXml2 error: Opening and ending tag mismatch: ci line 6 and math.", - "LibXml2 error: EndTag: '\n" - "\n" - " \n" - " \n" - " \n" - " \n" - "\n"; - - libcellml::ModelPtr m = libcellml::Model::create(); - libcellml::ComponentPtr c = libcellml::Component::create(); - libcellml::VariablePtr v1 = libcellml::Variable::create(); - libcellml::VariablePtr v2 = libcellml::Variable::create(); - c->setName("component"); - v1->setName("variable1"); - v2->setName("variable2"); - c->addVariable(v1); - c->addVariable(v2); - c->appendMath(EMPTY_MATH); - c->appendMath(EMPTY_MATH); - m->addComponent(c); - - libcellml::PrinterPtr printer = libcellml::Printer::create(); - const std::string a = printer->printModel(m); - EXPECT_EQ(e, a); -} - TEST(Maths, modelWithTwoVariablesWithInitialValuesAndInvalidMath) { const std::string e = @@ -374,6 +330,13 @@ TEST(Printer, addMathMLAsCompleteXMLDoc) EXPECT_EQ(e, printer->printModel(model)); } +void compareLibXml2Issues(const libcellml::PrinterPtr &printer) +{ + EXPECT_EQ(expectedLibXml2Issues.size(), printer->issueCount()); + for (size_t i = 0; i < printer->issueCount(); ++i) { + EXPECT_EQ(expectedLibXml2Issues.at(i), printer->issue(i)->description()); + } +} TEST(Printer, mathMLWithSyntaxError) { const std::string e = @@ -401,15 +364,7 @@ TEST(Printer, mathMLWithSyntaxError) EXPECT_EQ(e, printer->printModel(model)); - if (expectedIssues_2_9_4.size() == printer->issueCount()) { - for (size_t i = 0; i < printer->issueCount(); ++i) { - EXPECT_EQ(expectedIssues_2_9_4.at(i), printer->issue(i)->description()); - } - } else { - for (size_t i = 0; i < printer->issueCount(); ++i) { - EXPECT_EQ(expectedIssues_2_9_10.at(i), printer->issue(i)->description()); - } - } + compareLibXml2Issues(printer); auto itemComponent = printer->issue(printer->issueCount() - 1)->item()->component(); EXPECT_NE(nullptr, itemComponent); @@ -449,15 +404,8 @@ TEST(Printer, mathMLInResetWithSyntaxError) component->addReset(reset); EXPECT_EQ(e, printer->printModel(model)); - if (expectedIssues_2_9_4.size() == printer->issueCount()) { - for (size_t i = 0; i < printer->issueCount(); ++i) { - EXPECT_EQ(expectedIssues_2_9_4.at(i), printer->issue(i)->description()); - } - } else { - for (size_t i = 0; i < printer->issueCount(); ++i) { - EXPECT_EQ(expectedIssues_2_9_10.at(i), printer->issue(i)->description()); - } - } + + compareLibXml2Issues(printer); auto itemReset = printer->issue(printer->issueCount() - 1)->item()->reset(); EXPECT_NE(nullptr, itemReset); diff --git a/tests/model/import_requirement.cpp b/tests/model/import_requirement.cpp index 57aa9d392..3ac4a6c65 100644 --- a/tests/model/import_requirement.cpp +++ b/tests/model/import_requirement.cpp @@ -57,3 +57,17 @@ TEST(ImportRequirement, requirementsEncapsulationUnitsWithChildren) auto requirements = model->importRequirements(); EXPECT_EQ(e, requirements); } + +TEST(ImportRequirement, requirementsRepeatedImports) +{ + const std::vector e = { + "importExample2components.cellml", + "importExample2units.cellml", + }; + + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("import-requirements/importExample2.cellml")); + + auto requirements = model->importRequirements(); + EXPECT_EQ(e, requirements); +} diff --git a/tests/model/model.cpp b/tests/model/model.cpp index 924388048..adf74f815 100644 --- a/tests/model/model.cpp +++ b/tests/model/model.cpp @@ -644,7 +644,7 @@ TEST(Model, cleanEmptyComponents) " \n" " \n" " \n" - " \n" + " abc\n" "\n"; auto model = libcellml::Model::create(); auto c1 = libcellml::Component::create("c1"); diff --git a/tests/parser/cellml_1_0.cpp b/tests/parser/cellml_1_0.cpp index 8bd3fbf7c..545852783 100644 --- a/tests/parser/cellml_1_0.cpp +++ b/tests/parser/cellml_1_0.cpp @@ -143,3 +143,27 @@ TEST(ParserTransform, renameNonSiUnits) EXPECT_EQ("metre", v1->units()->name()); EXPECT_EQ("litre", v2->units()->name()); } + +TEST(ParserTransform, multipleMathInComponent) +{ + libcellml::ParserPtr parser = libcellml::Parser::create(false); + auto model = parser->parseModel(fileContents("cellml1X/cardiac_constant_simplified.cellml")); + + auto validator = libcellml::Validator::create(); + + validator->validateModel(model); + + EXPECT_EQ(size_t(0), validator->errorCount()); +} + +TEST(ParserTransform, multipleMathInComponentAlternativeFormulation) +{ + libcellml::ParserPtr parser = libcellml::Parser::create(false); + auto model = parser->parseModel(fileContents("cellml1X/cardiac_constant_simplified_alternative.cellml")); + + auto validator = libcellml::Validator::create(); + + validator->validateModel(model); + + EXPECT_EQ(size_t(0), validator->errorCount()); +} diff --git a/tests/parser/parser.cpp b/tests/parser/parser.cpp index 975916b2b..218dd4552 100644 --- a/tests/parser/parser.cpp +++ b/tests/parser/parser.cpp @@ -2038,6 +2038,7 @@ TEST(Parser, unitsWithCellMLRealVariations) " \n" " \n" " \n" + " \n" " \n" "\n"; @@ -2054,6 +2055,7 @@ TEST(Parser, unitsWithCellMLRealVariations) " \n" " \n" " \n" + " \n" " \n" "\n"; diff --git a/tests/printer/printer.cpp b/tests/printer/printer.cpp index bd62111b2..a55cf81ce 100644 --- a/tests/printer/printer.cpp +++ b/tests/printer/printer.cpp @@ -978,3 +978,63 @@ TEST(Printer, prettyPrintSpacesWrongPlaceNewlines) component6->appendMath(MATH_FOOTER); EXPECT_EQ(PRETTY_MODEL_STRING, printer->printModel(model)); } + +TEST(Printer, printComponentWithMultipleMathDocuments) +{ + auto printer = libcellml::Printer::create(); + auto parser = libcellml::Parser::create(); + + const std::string e = fileContents("printer/component_with_multiple_math.cellml"); + auto model = parser->parseModel(e); + + EXPECT_EQ(e, printer->printModel(model)); +} + +TEST(Printer, printComponentWithMultipleFullyQualifiedMathDocuments) +{ + const std::string in = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + const std::string math1 = + "\n" + "\n" + " \n" + " \n" + " nK_stim\n" + " 0.3\n" + " \n" + "\n"; + + const std::string math2 = + "\n" + "\n" + " \n" + " \n" + " stimPeriod\n" + " 42.6\n" + " \n" + "\n"; + + auto printer = libcellml::Printer::create(); + auto parser = libcellml::Parser::create(); + + auto model = parser->parseModel(in); + + model->component(0)->appendMath(math1); + model->component(0)->appendMath(math2); + + const std::string e = fileContents("printer/component_with_multiple_math.cellml"); + EXPECT_EQ(e, printer->printModel(model)); +} diff --git a/tests/resources/analyser/not_equality_statement.cellml b/tests/resources/analyser/not_equality_statement.cellml new file mode 100644 index 000000000..d1a1fb291 --- /dev/null +++ b/tests/resources/analyser/not_equality_statement.cellml @@ -0,0 +1,18 @@ + + + + + + + + + + + x + y + z + + + + diff --git a/tests/resources/analyser/overconstrained_one_variable.cellml b/tests/resources/analyser/overconstrained.cellml similarity index 89% rename from tests/resources/analyser/overconstrained_one_variable.cellml rename to tests/resources/analyser/overconstrained.cellml index 7ec8908c4..87c5ad1e2 100644 --- a/tests/resources/analyser/overconstrained_one_variable.cellml +++ b/tests/resources/analyser/overconstrained.cellml @@ -1,5 +1,8 @@ + diff --git a/tests/resources/analyser/overconstrained_nla_system.cellml b/tests/resources/analyser/overconstrained_nla_system.cellml new file mode 100644 index 000000000..2e2f03058 --- /dev/null +++ b/tests/resources/analyser/overconstrained_nla_system.cellml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + 2 + x + + y + + 15 + + + + + + + + 3 + x + + y + + 5 + + + + + + x + y + + 11 + + + + diff --git a/tests/resources/analyser/overconstrained_three_variables.cellml b/tests/resources/analyser/overconstrained_three_variables.cellml deleted file mode 100644 index 71e4a6a15..000000000 --- a/tests/resources/analyser/overconstrained_three_variables.cellml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - z - - - x - y - 1 - - - - - z - - - x - y - 3 - - - - - diff --git a/tests/resources/annotator/lots_of_duplicate_ids.cellml b/tests/resources/annotator/lots_of_duplicate_ids.cellml index d1cd7a7c7..0b0b503e3 100644 --- a/tests/resources/annotator/lots_of_duplicate_ids.cellml +++ b/tests/resources/annotator/lots_of_duplicate_ids.cellml @@ -1,16 +1,27 @@ - + - - + + + + + + + + + variable4 + 9.0 + + + @@ -36,19 +47,8 @@ - - - - - - variable4 - 9.0 - - - - - - + + @@ -57,14 +57,14 @@ + + + + - - - - diff --git a/tests/resources/cellml1X/cardiac_constant_simplified.cellml b/tests/resources/cellml1X/cardiac_constant_simplified.cellml new file mode 100644 index 000000000..4295bebfe --- /dev/null +++ b/tests/resources/cellml1X/cardiac_constant_simplified.cellml @@ -0,0 +1,25 @@ + + + + + + + + nK_stim + 0.3 + + + + + + + stimPeriod + 42.6 + + + + diff --git a/tests/resources/cellml1X/cardiac_constant_simplified_alternative.cellml b/tests/resources/cellml1X/cardiac_constant_simplified_alternative.cellml new file mode 100644 index 000000000..6b3210bbe --- /dev/null +++ b/tests/resources/cellml1X/cardiac_constant_simplified_alternative.cellml @@ -0,0 +1,25 @@ + + + + + + + + nK_stim + 0.3 + + + + + + + stimPeriod + 42.6 + + + + diff --git a/tests/resources/coverage/analyser.cellml b/tests/resources/coverage/analyser.cellml new file mode 100644 index 000000000..4a2a0d64c --- /dev/null +++ b/tests/resources/coverage/analyser.cellml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + t + + x + + 1.7977308 + + + + + + + u + + 2 + + + y + + 1.7977308 + + + + + + + v + + 1 + + + z + + 3 + + + + diff --git a/tests/resources/coverage/converttodouble.cellml b/tests/resources/coverage/converttodouble.cellml new file mode 100644 index 000000000..d87dfd403 --- /dev/null +++ b/tests/resources/coverage/converttodouble.cellml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + t + + x + + 1.7977308 + + + + + + + u + + 1.7977308 + + + y + + 1.7977308 + + + + + + + v + + XXYY + + + z + + 3 + + + + diff --git a/tests/resources/coverage/converttoint.cellml b/tests/resources/coverage/converttoint.cellml new file mode 100644 index 000000000..c1004e46e --- /dev/null +++ b/tests/resources/coverage/converttoint.cellml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/coverage/generator/model.c b/tests/resources/coverage/generator/model.c new file mode 100644 index 000000000..e7d346247 --- /dev/null +++ b/tests/resources/coverage/generator/model.c @@ -0,0 +1,604 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t STATE_COUNT = 1; +const size_t VARIABLE_COUNT = 209; + +const VariableInfo VOI_INFO = {"t", "second", "my_component", VARIABLE_OF_INTEGRATION}; + +const VariableInfo STATE_INFO[] = { + {"x", "dimensionless", "my_component", STATE} +}; + +const VariableInfo VARIABLE_INFO[] = { + {"eqnEq", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"m", "dimensionless", "my_component", CONSTANT}, + {"n", "dimensionless", "my_component", CONSTANT}, + {"eqnEqCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnNeq", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnNeqCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"o", "dimensionless", "my_component", CONSTANT}, + {"eqnLt", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLtCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLeq", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLeqCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnGt", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnGtCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnGeq", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnGeqCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAnd", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"p", "dimensionless", "my_component", CONSTANT}, + {"eqnAndParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesLeftPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesLeftRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOr", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesLeftPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesLeftRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXor", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesLeftPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesLeftRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnNot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPlus", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPlusMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPlusParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPlusUnary", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinus", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusParenthesesPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusParenthesesPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusParenthesesDirectUnaryMinus", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusParenthesesIndirectUnaryMinus", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusUnary", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusUnaryParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesRightTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesRightDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerSqrt", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerSqr", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerCube", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesLeftTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesLeftDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootSqrt", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootSqrtOther", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootCube", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesLeftTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesLeftDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAbs", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnExp", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLn", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLog", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLog2", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLog10", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLogCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCeiling", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnFloor", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMin", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMax", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMaxMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRem", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnSin", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCos", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTan", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnSec", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCsc", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnSinh", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCosh", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTanh", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnSech", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCsch", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoth", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArcsin", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArccos", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArctan", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArcsec", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArccsc", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArccot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArcsinh", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArccosh", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArctanh", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArcsech", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArccsch", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArccoth", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPiecewisePiece", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPiecewisePieceOtherwise", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPiecewisePiecePiecePiece", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"q", "dimensionless", "my_component", CONSTANT}, + {"r", "dimensionless", "my_component", CONSTANT}, + {"eqnPiecewisePiecePiecePieceOtherwise", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"s", "dimensionless", "my_component", CONSTANT}, + {"eqnWithPiecewise", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCnInteger", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCnDouble", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCnIntegerWithExponent", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCnDoubleWithExponent", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTrue", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnFalse", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnExponentiale", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPi", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnInfinity", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnNotanumber", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForPlusOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForMinusOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForTimesOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForDivideOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForAndOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForOrOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForXorOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForPowerOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForRootOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForMinusUnary", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnNlaVariable1", "dimensionless", "my_component", ALGEBRAIC}, + {"eqnNlaVariable2", "dimensionless", "my_component", ALGEBRAIC}, + {"eqnComputedConstant1", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnComputedConstant2", "dimensionless", "my_component", COMPUTED_CONSTANT} +}; + +double xor(double x, double y) +{ + return (x != 0.0) ^ (y != 0.0); +} + +double min(double x, double y) +{ + return (x < y)?x:y; +} + +double max(double x, double y) +{ + return (x > y)?x:y; +} + +double sec(double x) +{ + return 1.0/cos(x); +} + +double csc(double x) +{ + return 1.0/sin(x); +} + +double cot(double x) +{ + return 1.0/tan(x); +} + +double sech(double x) +{ + return 1.0/cosh(x); +} + +double csch(double x) +{ + return 1.0/sinh(x); +} + +double coth(double x) +{ + return 1.0/tanh(x); +} + +double asec(double x) +{ + return acos(1.0/x); +} + +double acsc(double x) +{ + return asin(1.0/x); +} + +double acot(double x) +{ + return atan(1.0/x); +} + +double asech(double x) +{ + double oneOverX = 1.0/x; + + return log(oneOverX+sqrt(oneOverX*oneOverX-1.0)); +} + +double acsch(double x) +{ + double oneOverX = 1.0/x; + + return log(oneOverX+sqrt(oneOverX*oneOverX+1.0)); +} + +double acoth(double x) +{ + double oneOverX = 1.0/x; + + return 0.5*log((1.0+oneOverX)/(1.0-oneOverX)); +} + +double * createStatesArray() +{ + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +typedef struct { + double voi; + double *states; + double *rates; + double *variables; +} RootFindingInfo; + +extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *), + double *u, int n, void *data); + +void objectiveFunction0(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[205] = u[0]; + variables[206] = u[1]; + + f[0] = variables[205]+variables[206]+states[0]-0.0; + f[1] = variables[205]-variables[206]-(variables[207]+variables[208]); +} + +void findRoot0(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[2]; + + u[0] = variables[205]; + u[1] = variables[206]; + + nlaSolve(objectiveFunction0, u, 2, &rfi); + + variables[205] = u[0]; + variables[206] = u[1]; +} + +void initialiseVariables(double *states, double *rates, double *variables) +{ + variables[1] = 1.0; + variables[2] = 2.0; + variables[6] = 3.0; + variables[18] = 4.0; + variables[179] = 5.0; + variables[180] = 6.0; + variables[182] = 7.0; + variables[205] = 1.0; + variables[206] = 2.0; + variables[184] = 123.0; + variables[185] = 123.456789; + variables[186] = 123.0e99; + variables[187] = 123.456789e99; + variables[189] = 1.0; + variables[190] = 0.0; + variables[191] = 2.71828182845905; + variables[192] = 3.14159265358979; + variables[193] = INFINITY; + variables[194] = NAN; + variables[207] = 1.0; + variables[208] = 3.0; + states[0] = 0.0; +} + +void computeComputedConstants(double *variables) +{ + variables[0] = variables[1] == variables[2]; + variables[3] = variables[1]/(variables[2] == variables[2]); + variables[4] = variables[1] != variables[2]; + variables[5] = variables[1]/(variables[2] != variables[6]); + variables[7] = variables[1] < variables[2]; + variables[8] = variables[1]/(variables[2] < variables[6]); + variables[9] = variables[1] <= variables[2]; + variables[10] = variables[1]/(variables[2] <= variables[6]); + variables[11] = variables[1] > variables[2]; + variables[12] = variables[1]/(variables[2] > variables[6]); + variables[13] = variables[1] >= variables[2]; + variables[14] = variables[1]/(variables[2] >= variables[6]); + variables[15] = variables[1] && variables[2]; + variables[16] = variables[1] && variables[2] && variables[6]; + variables[17] = (variables[1] < variables[2]) && (variables[6] > variables[18]); + variables[19] = (variables[1]+variables[2]) && (variables[6] > variables[18]); + variables[20] = variables[1] && (variables[2] > variables[6]); + variables[21] = (variables[1]-variables[2]) && (variables[6] > variables[18]); + variables[22] = -variables[1] && (variables[2] > variables[6]); + variables[23] = pow(variables[1], variables[2]) && (variables[6] > variables[18]); + variables[24] = pow(variables[1], 1.0/variables[2]) && (variables[6] > variables[18]); + variables[25] = (variables[1] < variables[2]) && (variables[6]+variables[18]); + variables[26] = (variables[1] < variables[2]) && variables[6]; + variables[27] = (variables[1] < variables[2]) && (variables[6]-variables[18]); + variables[28] = (variables[1] < variables[2]) && -variables[6]; + variables[29] = (variables[1] < variables[2]) && pow(variables[6], variables[18]); + variables[30] = (variables[1] < variables[2]) && pow(variables[6], 1.0/variables[18]); + variables[31] = variables[1]/(variables[2] && variables[6]); + variables[32] = variables[1] || variables[2]; + variables[33] = variables[1] || variables[2] || variables[6]; + variables[34] = (variables[1] < variables[2]) || (variables[6] > variables[18]); + variables[35] = (variables[1]+variables[2]) || (variables[6] > variables[18]); + variables[36] = variables[1] || (variables[2] > variables[6]); + variables[37] = (variables[1]-variables[2]) || (variables[6] > variables[18]); + variables[38] = -variables[1] || (variables[2] > variables[6]); + variables[39] = pow(variables[1], variables[2]) || (variables[6] > variables[18]); + variables[40] = pow(variables[1], 1.0/variables[2]) || (variables[6] > variables[18]); + variables[41] = (variables[1] < variables[2]) || (variables[6]+variables[18]); + variables[42] = (variables[1] < variables[2]) || variables[6]; + variables[43] = (variables[1] < variables[2]) || (variables[6]-variables[18]); + variables[44] = (variables[1] < variables[2]) || -variables[6]; + variables[45] = (variables[1] < variables[2]) || pow(variables[6], variables[18]); + variables[46] = (variables[1] < variables[2]) || pow(variables[6], 1.0/variables[18]); + variables[47] = variables[1]/(variables[2] || variables[6]); + variables[48] = xor(variables[1], variables[2]); + variables[49] = xor(variables[1], xor(variables[2], variables[6])); + variables[50] = xor(variables[1] < variables[2], variables[6] > variables[18]); + variables[51] = xor(variables[1]+variables[2], variables[6] > variables[18]); + variables[52] = xor(variables[1], variables[2] > variables[6]); + variables[53] = xor(variables[1]-variables[2], variables[6] > variables[18]); + variables[54] = xor(-variables[1], variables[2] > variables[6]); + variables[55] = xor(pow(variables[1], variables[2]), variables[6] > variables[18]); + variables[56] = xor(pow(variables[1], 1.0/variables[2]), variables[6] > variables[18]); + variables[57] = xor(variables[1] < variables[2], variables[6]+variables[18]); + variables[58] = xor(variables[1] < variables[2], variables[6]); + variables[59] = xor(variables[1] < variables[2], variables[6]-variables[18]); + variables[60] = xor(variables[1] < variables[2], -variables[6]); + variables[61] = xor(variables[1] < variables[2], pow(variables[6], variables[18])); + variables[62] = xor(variables[1] < variables[2], pow(variables[6], 1.0/variables[18])); + variables[63] = variables[1]/xor(variables[2], variables[6]); + variables[64] = !variables[1]; + variables[65] = variables[1]+variables[2]; + variables[66] = variables[1]+variables[2]+variables[6]; + variables[67] = (variables[1] < variables[2])+(variables[6] > variables[18]); + variables[68] = variables[1]; + variables[69] = variables[1]-variables[2]; + variables[70] = (variables[1] < variables[2])-(variables[6] > variables[18]); + variables[71] = (variables[1] < variables[2])-(variables[6]+variables[18]); + variables[72] = (variables[1] < variables[2])-variables[6]; + variables[73] = variables[1]-(-variables[2]); + variables[74] = variables[1]-(-variables[2]*variables[6]); + variables[75] = -variables[1]; + variables[76] = -(variables[1] < variables[2]); + variables[77] = variables[1]*variables[2]; + variables[78] = variables[1]*variables[2]*variables[6]; + variables[79] = (variables[1] < variables[2])*(variables[6] > variables[18]); + variables[80] = (variables[1]+variables[2])*(variables[6] > variables[18]); + variables[81] = variables[1]*(variables[2] > variables[6]); + variables[82] = (variables[1]-variables[2])*(variables[6] > variables[18]); + variables[83] = -variables[1]*(variables[2] > variables[6]); + variables[84] = (variables[1] < variables[2])*(variables[6]+variables[18]); + variables[85] = (variables[1] < variables[2])*variables[6]; + variables[86] = (variables[1] < variables[2])*(variables[6]-variables[18]); + variables[87] = (variables[1] < variables[2])*-variables[6]; + variables[88] = variables[1]/variables[2]; + variables[89] = (variables[1] < variables[2])/(variables[18] > variables[6]); + variables[90] = (variables[1]+variables[2])/(variables[18] > variables[6]); + variables[91] = variables[1]/(variables[6] > variables[2]); + variables[92] = (variables[1]-variables[2])/(variables[18] > variables[6]); + variables[93] = -variables[1]/(variables[6] > variables[2]); + variables[94] = (variables[1] < variables[2])/(variables[6]+variables[18]); + variables[95] = (variables[1] < variables[2])/variables[6]; + variables[96] = (variables[1] < variables[2])/(variables[6]-variables[18]); + variables[97] = (variables[1] < variables[2])/-variables[6]; + variables[98] = (variables[1] < variables[2])/(variables[6]*variables[18]); + variables[99] = (variables[1] < variables[2])/(variables[6]/variables[18]); + variables[100] = sqrt(variables[1]); + variables[101] = pow(variables[1], 2.0); + variables[102] = pow(variables[1], 3.0); + variables[103] = pow(variables[1], variables[2]); + variables[104] = pow(variables[1] <= variables[2], variables[6] >= variables[18]); + variables[105] = pow(variables[1]+variables[2], variables[6] >= variables[18]); + variables[106] = pow(variables[1], variables[2] >= variables[6]); + variables[107] = pow(variables[1]-variables[2], variables[6] >= variables[18]); + variables[108] = pow(-variables[1], variables[2] >= variables[6]); + variables[109] = pow(variables[1]*variables[2], variables[6] >= variables[18]); + variables[110] = pow(variables[1]/variables[2], variables[6] >= variables[18]); + variables[111] = pow(variables[1] <= variables[2], variables[6]+variables[18]); + variables[112] = pow(variables[1] <= variables[2], variables[6]); + variables[113] = pow(variables[1] <= variables[2], variables[6]-variables[18]); + variables[114] = pow(variables[1] <= variables[2], -variables[6]); + variables[115] = pow(variables[1] <= variables[2], variables[6]*variables[18]); + variables[116] = pow(variables[1] <= variables[2], variables[6]/variables[18]); + variables[117] = pow(variables[1] <= variables[2], pow(variables[6], variables[18])); + variables[118] = pow(variables[1] <= variables[2], pow(variables[6], 1.0/variables[18])); + variables[119] = sqrt(variables[1]); + variables[120] = sqrt(variables[1]); + variables[121] = pow(variables[1], 1.0/3.0); + variables[122] = pow(variables[1], 1.0/variables[2]); + variables[123] = pow(variables[1] < variables[2], 1.0/(variables[18] > variables[6])); + variables[124] = pow(variables[1]+variables[2], 1.0/(variables[18] > variables[6])); + variables[125] = pow(variables[1], 1.0/(variables[6] > variables[2])); + variables[126] = pow(variables[1]-variables[2], 1.0/(variables[18] > variables[6])); + variables[127] = pow(-variables[1], 1.0/(variables[6] > variables[2])); + variables[128] = pow(variables[1]*variables[2], 1.0/(variables[18] > variables[6])); + variables[129] = pow(variables[1]/variables[2], 1.0/(variables[18] > variables[6])); + variables[130] = pow(variables[1] < variables[2], 1.0/(variables[6]+variables[18])); + variables[131] = pow(variables[1] < variables[2], 1.0/variables[6]); + variables[132] = pow(variables[1] < variables[2], 1.0/(variables[6]-variables[18])); + variables[133] = pow(variables[1] < variables[2], 1.0/-variables[6]); + variables[134] = pow(variables[1] < variables[2], 1.0/(variables[6]*variables[18])); + variables[135] = pow(variables[1] < variables[2], 1.0/(variables[6]/variables[18])); + variables[136] = pow(variables[1] < variables[2], 1.0/pow(variables[6], variables[18])); + variables[137] = pow(variables[1] < variables[2], 1.0/pow(variables[6], 1.0/variables[18])); + variables[138] = fabs(variables[1]); + variables[139] = exp(variables[1]); + variables[140] = log(variables[1]); + variables[141] = log10(variables[1]); + variables[142] = log(variables[1])/log(2.0); + variables[143] = log10(variables[1]); + variables[144] = log(variables[1])/log(variables[2]); + variables[145] = ceil(variables[1]); + variables[146] = floor(variables[1]); + variables[147] = min(variables[1], variables[2]); + variables[148] = min(variables[1], min(variables[2], variables[6])); + variables[149] = max(variables[1], variables[2]); + variables[150] = max(variables[1], max(variables[2], variables[6])); + variables[151] = fmod(variables[1], variables[2]); + variables[152] = sin(variables[1]); + variables[153] = cos(variables[1]); + variables[154] = tan(variables[1]); + variables[155] = sec(variables[1]); + variables[156] = csc(variables[1]); + variables[157] = cot(variables[1]); + variables[158] = sinh(variables[1]); + variables[159] = cosh(variables[1]); + variables[160] = tanh(variables[1]); + variables[161] = sech(variables[1]); + variables[162] = csch(variables[1]); + variables[163] = coth(variables[1]); + variables[164] = asin(variables[1]); + variables[165] = acos(variables[1]); + variables[166] = atan(variables[1]); + variables[167] = asec(variables[1]); + variables[168] = acsc(variables[1]); + variables[169] = acot(variables[1]); + variables[170] = asinh(variables[1]); + variables[171] = acosh(variables[1]); + variables[172] = atanh(variables[1]/2.0); + variables[173] = asech(variables[1]); + variables[174] = acsch(variables[1]); + variables[175] = acoth(2.0*variables[1]); + variables[176] = (variables[1] > variables[2])?variables[1]:NAN; + variables[177] = (variables[1] > variables[2])?variables[1]:variables[6]; + variables[178] = (variables[1] > variables[2])?variables[1]:(variables[6] > variables[18])?variables[6]:(variables[179] > variables[180])?variables[179]:NAN; + variables[181] = (variables[1] > variables[2])?variables[1]:(variables[6] > variables[18])?variables[6]:(variables[179] > variables[180])?variables[179]:variables[182]; + variables[183] = 123.0+((variables[1] > variables[2])?variables[1]:NAN); + variables[188] = variables[1]; + variables[195] = (variables[1] && variables[2])+((variables[6] > variables[18])?variables[2]:NAN)+variables[179]+(variables[180] && variables[182]); + variables[196] = (variables[1] && variables[2])-(((variables[6] > variables[18])?variables[2]:NAN)-(variables[179]-((variables[6] > variables[18])?variables[2]:NAN)))-(variables[180] && variables[182]); + variables[197] = (variables[1] && variables[2])*((variables[6] > variables[18])?variables[2]:NAN)*variables[179]*((variables[6] > variables[18])?variables[2]:NAN)*(variables[180] && variables[182]); + variables[198] = (variables[1] && variables[2])/(((variables[6] > variables[18])?variables[2]:NAN)/(variables[179]/((variables[6] > variables[18])?variables[2]:NAN))); + variables[199] = (variables[1] || variables[2]) && xor(variables[1], variables[2]) && ((variables[6] > variables[18])?variables[2]:NAN) && variables[179] && ((variables[6] > variables[18])?variables[2]:NAN) && xor(variables[1], variables[2]) && (variables[1] || variables[2]); + variables[200] = (variables[1] && variables[2]) || xor(variables[1], variables[2]) || ((variables[6] > variables[18])?variables[2]:NAN) || variables[179] || ((variables[6] > variables[18])?variables[2]:NAN) || xor(variables[1], variables[2]) || (variables[1] && variables[2]); + variables[201] = xor(variables[1] && variables[2], xor(variables[1] || variables[2], xor((variables[6] > variables[18])?variables[2]:NAN, xor(xor(xor(variables[179], (variables[6] > variables[18])?variables[2]:NAN), variables[1] || variables[2]), variables[1] && variables[2])))); + variables[202] = pow(variables[1] && variables[2], pow((variables[6] > variables[18])?variables[2]:NAN, pow(pow(variables[179], (variables[6] > variables[18])?variables[2]:NAN), variables[1] && variables[2]))); + variables[203] = pow(pow(pow(variables[1] && variables[2], 1.0/pow((variables[6] > variables[18])?variables[2]:NAN, 1.0/variables[179])), 1.0/((variables[6] > variables[18])?variables[2]:NAN)), 1.0/(variables[1] && variables[2])); + variables[204] = -(variables[1] && variables[2])+-((variables[6] > variables[18])?variables[2]:NAN); +} + +void computeRates(double voi, double *states, double *rates, double *variables) +{ + rates[0] = 1.0; +} + +void computeVariables(double voi, double *states, double *rates, double *variables) +{ + findRoot0(voi, states, rates, variables); +} diff --git a/tests/resources/generator/coverage/model.cellml b/tests/resources/coverage/generator/model.cellml similarity index 77% rename from tests/resources/generator/coverage/model.cellml rename to tests/resources/coverage/generator/model.cellml index 9a8763074..6a2574eed 100644 --- a/tests/resources/generator/coverage/model.cellml +++ b/tests/resources/coverage/generator/model.cellml @@ -17,9 +17,13 @@ + + + + @@ -35,6 +39,7 @@ + @@ -50,6 +55,7 @@ + @@ -65,6 +71,7 @@ + @@ -74,6 +81,8 @@ + + @@ -191,6 +200,20 @@ + + + + + + + + + + + + + + @@ -270,6 +293,19 @@ n + + + eqnLtCoverageParentheses + + + m + + + n + o + + + @@ -281,6 +317,19 @@ n + + + eqnLeqCoverageParentheses + + + m + + + n + o + + + @@ -292,6 +341,19 @@ n + + + eqnGtCoverageParentheses + + + m + + + n + o + + + @@ -303,6 +365,19 @@ n + + + eqnGeqCoverageParentheses + + + m + + + n + o + + + @@ -545,6 +620,19 @@ + + + eqnAndCoverageParentheses + + + m + + + n + o + + + @@ -787,6 +875,19 @@ + + + eqnOrCoverageParentheses + + + m + + + n + o + + + @@ -1029,6 +1130,19 @@ + + + eqnXorCoverageParentheses + + + m + + + n + o + + + @@ -1146,6 +1260,34 @@ + + + eqnMinusParenthesesDirectUnaryMinus + + + m + + + n + + + + + + eqnMinusParenthesesIndirectUnaryMinus + + + m + + + + + n + + o + + + eqnMinusUnary @@ -1574,12 +1716,12 @@ - + m n - + o p @@ -1596,7 +1738,7 @@ n - + o p @@ -1612,7 +1754,7 @@ m - + n o @@ -1629,7 +1771,7 @@ n - + o p @@ -1645,7 +1787,7 @@ m - + n o @@ -1662,7 +1804,7 @@ n - + o p @@ -1679,7 +1821,7 @@ n - + o p @@ -1691,7 +1833,7 @@ - + m n @@ -1708,7 +1850,7 @@ - + m n @@ -1724,7 +1866,7 @@ - + m n @@ -1741,7 +1883,7 @@ - + m n @@ -1757,7 +1899,7 @@ - + m n @@ -1774,7 +1916,7 @@ - + m n @@ -1791,7 +1933,7 @@ - + m n @@ -1808,7 +1950,7 @@ - + m n @@ -2743,6 +2885,531 @@ + + + + eqnCoverageForPlusOperator + + + + + + + m + n + + + + + + n + + + o + p + + + + q + + + + + r + s + + + + + + eqnCoverageForMinusOperator + + + + + + + m + n + + + + + + n + + + o + p + + + + + + q + + + n + + + o + p + + + + + + + + + r + s + + + + + + eqnCoverageForTimesOperator + + + + + + + m + n + + + + + + n + + + o + p + + + + + + q + + + n + + + o + p + + + + + + + + + r + s + + + + + + eqnCoverageForDivideOperator + + + + + m + n + + + + + + n + + + o + p + + + + + + q + + + n + + + o + p + + + + + + + + + + eqnCoverageForAndOperator + + + + + m + n + + + + + + m + n + + + + + + n + + + o + p + + + + + + + + + + q + + + n + + + o + p + + + + + + + m + n + + + + + m + n + + + + + + + + + eqnCoverageForOrOperator + + + + + m + n + + + + + + m + n + + + + + + n + + + o + p + + + + + + + + + + q + + + n + + + o + p + + + + + + + m + n + + + + + m + n + + + + + + + + + eqnCoverageForXorOperator + + + + + m + n + + + + + + m + n + + + + + + n + + + o + p + + + + + + + + + + q + + + n + + + o + p + + + + + + + m + n + + + + + m + n + + + + + + + + + eqnCoverageForPowerOperator + + + + + m + n + + + + + + n + + + o + p + + + + + + + + q + + + n + + + o + p + + + + + + + m + n + + + + + + + + eqnCoverageForRootOperator + + + + + + m + n + + + + + + + + n + + + o + p + + + + + + + + + + + q + + + + n + + + o + p + + + + + + + + m + n + + + + + + + + eqnCoverageForMinusUnary + + + + + + + m + n + + + + + + + n + + + o + p + + + + + + + + + + + + + eqnNlaVariable1 + eqnNlaVariable2 + x + + 0 + + + + + + eqnNlaVariable1 + eqnNlaVariable2 + + + + eqnComputedConstant1 + eqnComputedConstant2 + + + + + + + eqnComputedConstant1 + 1 + + + + eqnComputedConstant2 + 3 + + diff --git a/tests/resources/generator/coverage/model.h b/tests/resources/coverage/generator/model.h similarity index 90% rename from tests/resources/generator/coverage/model.h rename to tests/resources/coverage/generator/model.h index 155fe76cd..3ff486183 100644 --- a/tests/resources/generator/coverage/model.h +++ b/tests/resources/coverage/generator/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/coverage/generator/model.implementation.out b/tests/resources/coverage/generator/model.implementation.out new file mode 100644 index 000000000..44aabf58f --- /dev/null +++ b/tests/resources/coverage/generator/model.implementation.out @@ -0,0 +1,375 @@ +/* The content of this file was generated using a modified C profile of libCellML 0.5.0. */ + +double xor(double x, double y) +{ + return (x != 0.0) ^ (y != 0.0); +} + +double min(double x, double y) +{ + return (x < y)?x:y; +} + +double max(double x, double y) +{ + return (x > y)?x:y; +} + +double sec(double x) +{ + return 1.0/cos(x); +} + +double csc(double x) +{ + return 1.0/sin(x); +} + +double cot(double x) +{ + return 1.0/tan(x); +} + +double sech(double x) +{ + return 1.0/cosh(x); +} + +double csch(double x) +{ + return 1.0/sinh(x); +} + +double coth(double x) +{ + return 1.0/tanh(x); +} + +double asec(double x) +{ + return acos(1.0/x); +} + +double acsc(double x) +{ + return asin(1.0/x); +} + +double acot(double x) +{ + return atan(1.0/x); +} + +double asech(double x) +{ + double oneOverX = 1.0/x; + + return log(oneOverX+sqrt(oneOverX*oneOverX-1.0)); +} + +double acsch(double x) +{ + double oneOverX = 1.0/x; + + return log(oneOverX+sqrt(oneOverX*oneOverX+1.0)); +} + +double acoth(double x) +{ + double oneOverX = 1.0/x; + + return 0.5*log((1.0+oneOverX)/(1.0-oneOverX)); +} + +double * createStatesArray() +{ + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +typedef struct { + double voi; + double *states; + double *rates; + double *variables; +} RootFindingInfo; + +extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *), + double *u, int n, void *data); + +void objectiveFunction0(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[205] = u[0]; + variables[206] = u[1]; + + f[0] = variables[205]+variables[206]+states[0]-0.0; + f[1] = variables[205]-variables[206]-(variables[207]+variables[208]); +} + +void findRoot0(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[2]; + + u[0] = variables[205]; + u[1] = variables[206]; + + nlaSolve(objectiveFunction0, u, 2, &rfi); + + variables[205] = u[0]; + variables[206] = u[1]; +} + +void initialiseVariables(double *states, double *rates, double *variables) +{ + variables[1] = 1.0; + variables[2] = 2.0; + variables[6] = 3.0; + variables[18] = 4.0; + variables[179] = 5.0; + variables[180] = 6.0; + variables[182] = 7.0; + variables[205] = 1.0; + variables[206] = 2.0; + variables[184] = 123.0; + variables[185] = 123.456789; + variables[186] = 123.0e99; + variables[187] = 123.456789e99; + variables[189] = 1.0; + variables[190] = 0.0; + variables[191] = 2.71828182845905; + variables[192] = 3.14159265358979; + variables[193] = INFINITY; + variables[194] = NAN; + variables[207] = 1.0; + variables[208] = 3.0; + states[0] = 0.0; +} + +void computeComputedConstants(double *variables) +{ + variables[0] = eq(variables[1], variables[2]); + variables[3] = variables[1]/eq(variables[2], variables[2]); + variables[4] = neq(variables[1], variables[2]); + variables[5] = variables[1]/neq(variables[2], variables[6]); + variables[7] = lt(variables[1], variables[2]); + variables[8] = variables[1]/lt(variables[2], variables[6]); + variables[9] = leq(variables[1], variables[2]); + variables[10] = variables[1]/leq(variables[2], variables[6]); + variables[11] = gt(variables[1], variables[2]); + variables[12] = variables[1]/gt(variables[2], variables[6]); + variables[13] = geq(variables[1], variables[2]); + variables[14] = variables[1]/geq(variables[2], variables[6]); + variables[15] = and(variables[1], variables[2]); + variables[16] = and(variables[1], and(variables[2], variables[6])); + variables[17] = and(lt(variables[1], variables[2]), gt(variables[6], variables[18])); + variables[19] = and(variables[1]+variables[2], gt(variables[6], variables[18])); + variables[20] = and(variables[1], gt(variables[2], variables[6])); + variables[21] = and(variables[1]-variables[2], gt(variables[6], variables[18])); + variables[22] = and(-variables[1], gt(variables[2], variables[6])); + variables[23] = and(pow(variables[1], variables[2]), gt(variables[6], variables[18])); + variables[24] = and(pow(variables[1], 1.0/variables[2]), gt(variables[6], variables[18])); + variables[25] = and(lt(variables[1], variables[2]), variables[6]+variables[18]); + variables[26] = and(lt(variables[1], variables[2]), variables[6]); + variables[27] = and(lt(variables[1], variables[2]), variables[6]-variables[18]); + variables[28] = and(lt(variables[1], variables[2]), -variables[6]); + variables[29] = and(lt(variables[1], variables[2]), pow(variables[6], variables[18])); + variables[30] = and(lt(variables[1], variables[2]), pow(variables[6], 1.0/variables[18])); + variables[31] = variables[1]/and(variables[2], variables[6]); + variables[32] = or(variables[1], variables[2]); + variables[33] = or(variables[1], or(variables[2], variables[6])); + variables[34] = or(lt(variables[1], variables[2]), gt(variables[6], variables[18])); + variables[35] = or(variables[1]+variables[2], gt(variables[6], variables[18])); + variables[36] = or(variables[1], gt(variables[2], variables[6])); + variables[37] = or(variables[1]-variables[2], gt(variables[6], variables[18])); + variables[38] = or(-variables[1], gt(variables[2], variables[6])); + variables[39] = or(pow(variables[1], variables[2]), gt(variables[6], variables[18])); + variables[40] = or(pow(variables[1], 1.0/variables[2]), gt(variables[6], variables[18])); + variables[41] = or(lt(variables[1], variables[2]), variables[6]+variables[18]); + variables[42] = or(lt(variables[1], variables[2]), variables[6]); + variables[43] = or(lt(variables[1], variables[2]), variables[6]-variables[18]); + variables[44] = or(lt(variables[1], variables[2]), -variables[6]); + variables[45] = or(lt(variables[1], variables[2]), pow(variables[6], variables[18])); + variables[46] = or(lt(variables[1], variables[2]), pow(variables[6], 1.0/variables[18])); + variables[47] = variables[1]/or(variables[2], variables[6]); + variables[48] = xor(variables[1], variables[2]); + variables[49] = xor(variables[1], xor(variables[2], variables[6])); + variables[50] = xor(lt(variables[1], variables[2]), gt(variables[6], variables[18])); + variables[51] = xor(variables[1]+variables[2], gt(variables[6], variables[18])); + variables[52] = xor(variables[1], gt(variables[2], variables[6])); + variables[53] = xor(variables[1]-variables[2], gt(variables[6], variables[18])); + variables[54] = xor(-variables[1], gt(variables[2], variables[6])); + variables[55] = xor(pow(variables[1], variables[2]), gt(variables[6], variables[18])); + variables[56] = xor(pow(variables[1], 1.0/variables[2]), gt(variables[6], variables[18])); + variables[57] = xor(lt(variables[1], variables[2]), variables[6]+variables[18]); + variables[58] = xor(lt(variables[1], variables[2]), variables[6]); + variables[59] = xor(lt(variables[1], variables[2]), variables[6]-variables[18]); + variables[60] = xor(lt(variables[1], variables[2]), -variables[6]); + variables[61] = xor(lt(variables[1], variables[2]), pow(variables[6], variables[18])); + variables[62] = xor(lt(variables[1], variables[2]), pow(variables[6], 1.0/variables[18])); + variables[63] = variables[1]/xor(variables[2], variables[6]); + variables[64] = not(variables[1]); + variables[65] = variables[1]+variables[2]; + variables[66] = variables[1]+variables[2]+variables[6]; + variables[67] = lt(variables[1], variables[2])+gt(variables[6], variables[18]); + variables[68] = variables[1]; + variables[69] = variables[1]-variables[2]; + variables[70] = lt(variables[1], variables[2])-gt(variables[6], variables[18]); + variables[71] = lt(variables[1], variables[2])-(variables[6]+variables[18]); + variables[72] = lt(variables[1], variables[2])-variables[6]; + variables[73] = variables[1]-(-variables[2]); + variables[74] = variables[1]-(-variables[2]*variables[6]); + variables[75] = -variables[1]; + variables[76] = -lt(variables[1], variables[2]); + variables[77] = variables[1]*variables[2]; + variables[78] = variables[1]*variables[2]*variables[6]; + variables[79] = lt(variables[1], variables[2])*gt(variables[6], variables[18]); + variables[80] = (variables[1]+variables[2])*gt(variables[6], variables[18]); + variables[81] = variables[1]*gt(variables[2], variables[6]); + variables[82] = (variables[1]-variables[2])*gt(variables[6], variables[18]); + variables[83] = -variables[1]*gt(variables[2], variables[6]); + variables[84] = lt(variables[1], variables[2])*(variables[6]+variables[18]); + variables[85] = lt(variables[1], variables[2])*variables[6]; + variables[86] = lt(variables[1], variables[2])*(variables[6]-variables[18]); + variables[87] = lt(variables[1], variables[2])*-variables[6]; + variables[88] = variables[1]/variables[2]; + variables[89] = lt(variables[1], variables[2])/gt(variables[18], variables[6]); + variables[90] = (variables[1]+variables[2])/gt(variables[18], variables[6]); + variables[91] = variables[1]/gt(variables[6], variables[2]); + variables[92] = (variables[1]-variables[2])/gt(variables[18], variables[6]); + variables[93] = -variables[1]/gt(variables[6], variables[2]); + variables[94] = lt(variables[1], variables[2])/(variables[6]+variables[18]); + variables[95] = lt(variables[1], variables[2])/variables[6]; + variables[96] = lt(variables[1], variables[2])/(variables[6]-variables[18]); + variables[97] = lt(variables[1], variables[2])/-variables[6]; + variables[98] = lt(variables[1], variables[2])/(variables[6]*variables[18]); + variables[99] = lt(variables[1], variables[2])/(variables[6]/variables[18]); + variables[100] = sqrt(variables[1]); + variables[101] = pow(variables[1], 2.0); + variables[102] = pow(variables[1], 3.0); + variables[103] = pow(variables[1], variables[2]); + variables[104] = pow(leq(variables[1], variables[2]), geq(variables[6], variables[18])); + variables[105] = pow(variables[1]+variables[2], geq(variables[6], variables[18])); + variables[106] = pow(variables[1], geq(variables[2], variables[6])); + variables[107] = pow(variables[1]-variables[2], geq(variables[6], variables[18])); + variables[108] = pow(-variables[1], geq(variables[2], variables[6])); + variables[109] = pow(variables[1]*variables[2], geq(variables[6], variables[18])); + variables[110] = pow(variables[1]/variables[2], geq(variables[6], variables[18])); + variables[111] = pow(leq(variables[1], variables[2]), variables[6]+variables[18]); + variables[112] = pow(leq(variables[1], variables[2]), variables[6]); + variables[113] = pow(leq(variables[1], variables[2]), variables[6]-variables[18]); + variables[114] = pow(leq(variables[1], variables[2]), -variables[6]); + variables[115] = pow(leq(variables[1], variables[2]), variables[6]*variables[18]); + variables[116] = pow(leq(variables[1], variables[2]), variables[6]/variables[18]); + variables[117] = pow(leq(variables[1], variables[2]), pow(variables[6], variables[18])); + variables[118] = pow(leq(variables[1], variables[2]), pow(variables[6], 1.0/variables[18])); + variables[119] = sqrt(variables[1]); + variables[120] = sqrt(variables[1]); + variables[121] = pow(variables[1], 1.0/3.0); + variables[122] = pow(variables[1], 1.0/variables[2]); + variables[123] = pow(lt(variables[1], variables[2]), 1.0/gt(variables[18], variables[6])); + variables[124] = pow(variables[1]+variables[2], 1.0/gt(variables[18], variables[6])); + variables[125] = pow(variables[1], 1.0/gt(variables[6], variables[2])); + variables[126] = pow(variables[1]-variables[2], 1.0/gt(variables[18], variables[6])); + variables[127] = pow(-variables[1], 1.0/gt(variables[6], variables[2])); + variables[128] = pow(variables[1]*variables[2], 1.0/gt(variables[18], variables[6])); + variables[129] = pow(variables[1]/variables[2], 1.0/gt(variables[18], variables[6])); + variables[130] = pow(lt(variables[1], variables[2]), 1.0/(variables[6]+variables[18])); + variables[131] = pow(lt(variables[1], variables[2]), 1.0/variables[6]); + variables[132] = pow(lt(variables[1], variables[2]), 1.0/(variables[6]-variables[18])); + variables[133] = pow(lt(variables[1], variables[2]), 1.0/-variables[6]); + variables[134] = pow(lt(variables[1], variables[2]), 1.0/(variables[6]*variables[18])); + variables[135] = pow(lt(variables[1], variables[2]), 1.0/(variables[6]/variables[18])); + variables[136] = pow(lt(variables[1], variables[2]), 1.0/pow(variables[6], variables[18])); + variables[137] = pow(lt(variables[1], variables[2]), 1.0/pow(variables[6], 1.0/variables[18])); + variables[138] = fabs(variables[1]); + variables[139] = exp(variables[1]); + variables[140] = log(variables[1]); + variables[141] = log10(variables[1]); + variables[142] = log(variables[1])/log(2.0); + variables[143] = log10(variables[1]); + variables[144] = log(variables[1])/log(variables[2]); + variables[145] = ceil(variables[1]); + variables[146] = floor(variables[1]); + variables[147] = min(variables[1], variables[2]); + variables[148] = min(variables[1], min(variables[2], variables[6])); + variables[149] = max(variables[1], variables[2]); + variables[150] = max(variables[1], max(variables[2], variables[6])); + variables[151] = fmod(variables[1], variables[2]); + variables[152] = sin(variables[1]); + variables[153] = cos(variables[1]); + variables[154] = tan(variables[1]); + variables[155] = sec(variables[1]); + variables[156] = csc(variables[1]); + variables[157] = cot(variables[1]); + variables[158] = sinh(variables[1]); + variables[159] = cosh(variables[1]); + variables[160] = tanh(variables[1]); + variables[161] = sech(variables[1]); + variables[162] = csch(variables[1]); + variables[163] = coth(variables[1]); + variables[164] = asin(variables[1]); + variables[165] = acos(variables[1]); + variables[166] = atan(variables[1]); + variables[167] = asec(variables[1]); + variables[168] = acsc(variables[1]); + variables[169] = acot(variables[1]); + variables[170] = asinh(variables[1]); + variables[171] = acosh(variables[1]); + variables[172] = atanh(variables[1]/2.0); + variables[173] = asech(variables[1]); + variables[174] = acsch(variables[1]); + variables[175] = acoth(2.0*variables[1]); + variables[176] = (gt(variables[1], variables[2]))?variables[1]:NAN; + variables[177] = (gt(variables[1], variables[2]))?variables[1]:variables[6]; + variables[178] = (gt(variables[1], variables[2]))?variables[1]:(gt(variables[6], variables[18]))?variables[6]:(gt(variables[179], variables[180]))?variables[179]:NAN; + variables[181] = (gt(variables[1], variables[2]))?variables[1]:(gt(variables[6], variables[18]))?variables[6]:(gt(variables[179], variables[180]))?variables[179]:variables[182]; + variables[183] = 123.0+((gt(variables[1], variables[2]))?variables[1]:NAN); + variables[188] = variables[1]; + variables[195] = and(variables[1], variables[2])+((gt(variables[6], variables[18]))?variables[2]:NAN)+variables[179]+and(variables[180], variables[182]); + variables[196] = and(variables[1], variables[2])-(((gt(variables[6], variables[18]))?variables[2]:NAN)-(variables[179]-((gt(variables[6], variables[18]))?variables[2]:NAN)))-and(variables[180], variables[182]); + variables[197] = and(variables[1], variables[2])*((gt(variables[6], variables[18]))?variables[2]:NAN)*variables[179]*((gt(variables[6], variables[18]))?variables[2]:NAN)*and(variables[180], variables[182]); + variables[198] = and(variables[1], variables[2])/(((gt(variables[6], variables[18]))?variables[2]:NAN)/(variables[179]/((gt(variables[6], variables[18]))?variables[2]:NAN))); + variables[199] = and(or(variables[1], variables[2]), and(xor(variables[1], variables[2]), and((gt(variables[6], variables[18]))?variables[2]:NAN, and(and(and(variables[179], (gt(variables[6], variables[18]))?variables[2]:NAN), xor(variables[1], variables[2])), or(variables[1], variables[2]))))); + variables[200] = or(and(variables[1], variables[2]), or(xor(variables[1], variables[2]), or((gt(variables[6], variables[18]))?variables[2]:NAN, or(or(or(variables[179], (gt(variables[6], variables[18]))?variables[2]:NAN), xor(variables[1], variables[2])), and(variables[1], variables[2]))))); + variables[201] = xor(and(variables[1], variables[2]), xor(or(variables[1], variables[2]), xor((gt(variables[6], variables[18]))?variables[2]:NAN, xor(xor(xor(variables[179], (gt(variables[6], variables[18]))?variables[2]:NAN), or(variables[1], variables[2])), and(variables[1], variables[2]))))); + variables[202] = pow(and(variables[1], variables[2]), pow((gt(variables[6], variables[18]))?variables[2]:NAN, pow(pow(variables[179], (gt(variables[6], variables[18]))?variables[2]:NAN), and(variables[1], variables[2])))); + variables[203] = pow(pow(pow(and(variables[1], variables[2]), 1.0/pow((gt(variables[6], variables[18]))?variables[2]:NAN, 1.0/variables[179])), 1.0/((gt(variables[6], variables[18]))?variables[2]:NAN)), 1.0/and(variables[1], variables[2])); + variables[204] = -and(variables[1], variables[2])+-((gt(variables[6], variables[18]))?variables[2]:NAN); +} + +void computeRates(double voi, double *states, double *rates, double *variables) +{ + rates[0] = 1.0; +} + +void computeVariables(double voi, double *states, double *rates, double *variables) +{ + findRoot0(voi, states, rates, variables); +} diff --git a/tests/resources/generator/coverage/model.interface.out b/tests/resources/coverage/generator/model.interface.out similarity index 79% rename from tests/resources/generator/coverage/model.interface.out rename to tests/resources/coverage/generator/model.interface.out index f7b5f1eee..e50441a8b 100644 --- a/tests/resources/generator/coverage/model.interface.out +++ b/tests/resources/coverage/generator/model.interface.out @@ -1,4 +1,4 @@ -/* The content of this file was generated using a modified C profile of libCellML 0.4.0. */ +/* The content of this file was generated using a modified C profile of libCellML 0.5.0. */ #pragma once @@ -8,7 +8,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/coverage/generator/model.modified.profile.c b/tests/resources/coverage/generator/model.modified.profile.c new file mode 100644 index 000000000..487c40138 --- /dev/null +++ b/tests/resources/coverage/generator/model.modified.profile.c @@ -0,0 +1,604 @@ +/* The content of this file was generated using a modified C profile of libCellML 0.5.0. */ + +#include "model.h" + +#include +#include + +const char VERSION[] = "0.4.0.post0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t STATE_COUNT = 1; +const size_t VARIABLE_COUNT = 209; + +const VariableInfo VOI_INFO = {"t", "second", "my_component", VARIABLE_OF_INTEGRATION}; + +const VariableInfo STATE_INFO[] = { + {"x", "dimensionless", "my_component", STATE} +}; + +const VariableInfo VARIABLE_INFO[] = { + {"eqnEq", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"m", "dimensionless", "my_component", CONSTANT}, + {"n", "dimensionless", "my_component", CONSTANT}, + {"eqnEqCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnNeq", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnNeqCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"o", "dimensionless", "my_component", CONSTANT}, + {"eqnLt", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLtCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLeq", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLeqCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnGt", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnGtCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnGeq", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnGeqCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAnd", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"p", "dimensionless", "my_component", CONSTANT}, + {"eqnAndParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesLeftPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesLeftRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAndCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOr", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesLeftPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesLeftRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnOrCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXor", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesLeftPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesLeftRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnXorCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnNot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPlus", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPlusMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPlusParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPlusUnary", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinus", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusParenthesesPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusParenthesesPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusParenthesesDirectUnaryMinus", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusParenthesesIndirectUnaryMinus", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusUnary", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinusUnaryParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTimesParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesRightTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnDivideParenthesesRightDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerSqrt", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerSqr", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerCube", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesLeftTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesLeftDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPowerParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootSqrt", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootSqrtOther", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootCube", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesLeftTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesLeftDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRootParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnAbs", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnExp", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLn", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLog", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLog2", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLog10", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnLogCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCeiling", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnFloor", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMin", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMinMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMax", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnMaxMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnRem", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnSin", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCos", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTan", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnSec", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCsc", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnSinh", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCosh", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTanh", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnSech", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCsch", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoth", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArcsin", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArccos", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArctan", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArcsec", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArccsc", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArccot", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArcsinh", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArccosh", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArctanh", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArcsech", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArccsch", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnArccoth", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPiecewisePiece", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPiecewisePieceOtherwise", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPiecewisePiecePiecePiece", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"q", "dimensionless", "my_component", CONSTANT}, + {"r", "dimensionless", "my_component", CONSTANT}, + {"eqnPiecewisePiecePiecePieceOtherwise", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"s", "dimensionless", "my_component", CONSTANT}, + {"eqnWithPiecewise", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCnInteger", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCnDouble", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCnIntegerWithExponent", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCnDoubleWithExponent", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnTrue", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnFalse", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnExponentiale", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnPi", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnInfinity", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnNotanumber", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForPlusOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForMinusOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForTimesOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForDivideOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForAndOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForOrOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForXorOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForPowerOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForRootOperator", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnCoverageForMinusUnary", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnNlaVariable1", "dimensionless", "my_component", ALGEBRAIC}, + {"eqnNlaVariable2", "dimensionless", "my_component", ALGEBRAIC}, + {"eqnComputedConstant1", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"eqnComputedConstant2", "dimensionless", "my_component", COMPUTED_CONSTANT} +}; + +double xor(double x, double y) +{ + return (x != 0.0) ^ (y != 0.0); +} + +double min(double x, double y) +{ + return (x < y)?x:y; +} + +double max(double x, double y) +{ + return (x > y)?x:y; +} + +double sec(double x) +{ + return 1.0/cos(x); +} + +double csc(double x) +{ + return 1.0/sin(x); +} + +double cot(double x) +{ + return 1.0/tan(x); +} + +double sech(double x) +{ + return 1.0/cosh(x); +} + +double csch(double x) +{ + return 1.0/sinh(x); +} + +double coth(double x) +{ + return 1.0/tanh(x); +} + +double asec(double x) +{ + return acos(1.0/x); +} + +double acsc(double x) +{ + return asin(1.0/x); +} + +double acot(double x) +{ + return atan(1.0/x); +} + +double asech(double x) +{ + double oneOverX = 1.0/x; + + return log(oneOverX+sqrt(oneOverX*oneOverX-1.0)); +} + +double acsch(double x) +{ + double oneOverX = 1.0/x; + + return log(oneOverX+sqrt(oneOverX*oneOverX+1.0)); +} + +double acoth(double x) +{ + double oneOverX = 1.0/x; + + return 0.5*log((1.0+oneOverX)/(1.0-oneOverX)); +} + +double * createStatesVector() +{ + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +typedef struct { + double voi; + double *states; + double *rates; + double *variables; +} RootFindingInfo; + +extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *), + double *u, int n, void *data); + +void objectiveFunction0(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[205] = u[0]; + variables[206] = u[1]; + + f[0] = variables[205]+variables[206]+states[0]-0.0; + f[1] = variables[205]-variables[206]-(variables[207]+variables[208]); +} + +void findRoot0(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[2]; + + u[0] = variables[205]; + u[1] = variables[206]; + + nlaSolve(objectiveFunction0, u, 2, &rfi); + + variables[205] = u[0]; + variables[206] = u[1]; +} + +void initialiseVariables(double *states, double *rates, double *variables) +{ + variables[1] = 1.0; + variables[2] = 2.0; + variables[6] = 3.0; + variables[18] = 4.0; + variables[179] = 5.0; + variables[180] = 6.0; + variables[182] = 7.0; + variables[205] = 1.0; + variables[206] = 2.0; + variables[184] = 123.0; + variables[185] = 123.456789; + variables[186] = 123.0e99; + variables[187] = 123.456789e99; + variables[189] = 1.0; + variables[190] = 0.0; + variables[191] = 2.71828182845905; + variables[192] = 3.14159265358979; + variables[193] = INFINITY; + variables[194] = NAN; + variables[207] = 1.0; + variables[208] = 3.0; + states[0] = 0.0; +} + +void computeComputedConstants(double *variables) +{ + variables[0] = variables[1] == variables[2]; + variables[3] = variables[1]/(variables[2] == variables[2]); + variables[4] = variables[1] != variables[2]; + variables[5] = variables[1]/(variables[2] != variables[6]); + variables[7] = variables[1] < variables[2]; + variables[8] = variables[1]/(variables[2] < variables[6]); + variables[9] = variables[1] <= variables[2]; + variables[10] = variables[1]/(variables[2] <= variables[6]); + variables[11] = variables[1] > variables[2]; + variables[12] = variables[1]/(variables[2] > variables[6]); + variables[13] = variables[1] >= variables[2]; + variables[14] = variables[1]/(variables[2] >= variables[6]); + variables[15] = variables[1] && variables[2]; + variables[16] = variables[1] && variables[2] && variables[6]; + variables[17] = (variables[1] < variables[2]) && (variables[6] > variables[18]); + variables[19] = (variables[1]+variables[2]) && (variables[6] > variables[18]); + variables[20] = variables[1] && (variables[2] > variables[6]); + variables[21] = (variables[1]-variables[2]) && (variables[6] > variables[18]); + variables[22] = -variables[1] && (variables[2] > variables[6]); + variables[23] = pow(variables[1], variables[2]) && (variables[6] > variables[18]); + variables[24] = pow(variables[1], 1.0/variables[2]) && (variables[6] > variables[18]); + variables[25] = (variables[1] < variables[2]) && (variables[6]+variables[18]); + variables[26] = (variables[1] < variables[2]) && variables[6]; + variables[27] = (variables[1] < variables[2]) && (variables[6]-variables[18]); + variables[28] = (variables[1] < variables[2]) && -variables[6]; + variables[29] = (variables[1] < variables[2]) && pow(variables[6], variables[18]); + variables[30] = (variables[1] < variables[2]) && pow(variables[6], 1.0/variables[18]); + variables[31] = variables[1]/(variables[2] && variables[6]); + variables[32] = variables[1] || variables[2]; + variables[33] = variables[1] || variables[2] || variables[6]; + variables[34] = (variables[1] < variables[2]) || (variables[6] > variables[18]); + variables[35] = (variables[1]+variables[2]) || (variables[6] > variables[18]); + variables[36] = variables[1] || (variables[2] > variables[6]); + variables[37] = (variables[1]-variables[2]) || (variables[6] > variables[18]); + variables[38] = -variables[1] || (variables[2] > variables[6]); + variables[39] = pow(variables[1], variables[2]) || (variables[6] > variables[18]); + variables[40] = pow(variables[1], 1.0/variables[2]) || (variables[6] > variables[18]); + variables[41] = (variables[1] < variables[2]) || (variables[6]+variables[18]); + variables[42] = (variables[1] < variables[2]) || variables[6]; + variables[43] = (variables[1] < variables[2]) || (variables[6]-variables[18]); + variables[44] = (variables[1] < variables[2]) || -variables[6]; + variables[45] = (variables[1] < variables[2]) || pow(variables[6], variables[18]); + variables[46] = (variables[1] < variables[2]) || pow(variables[6], 1.0/variables[18]); + variables[47] = variables[1]/(variables[2] || variables[6]); + variables[48] = xor(variables[1], variables[2]); + variables[49] = xor(variables[1], xor(variables[2], variables[6])); + variables[50] = xor(variables[1] < variables[2], variables[6] > variables[18]); + variables[51] = xor(variables[1]+variables[2], variables[6] > variables[18]); + variables[52] = xor(variables[1], variables[2] > variables[6]); + variables[53] = xor(variables[1]-variables[2], variables[6] > variables[18]); + variables[54] = xor(-variables[1], variables[2] > variables[6]); + variables[55] = xor(pow(variables[1], variables[2]), variables[6] > variables[18]); + variables[56] = xor(pow(variables[1], 1.0/variables[2]), variables[6] > variables[18]); + variables[57] = xor(variables[1] < variables[2], variables[6]+variables[18]); + variables[58] = xor(variables[1] < variables[2], variables[6]); + variables[59] = xor(variables[1] < variables[2], variables[6]-variables[18]); + variables[60] = xor(variables[1] < variables[2], -variables[6]); + variables[61] = xor(variables[1] < variables[2], pow(variables[6], variables[18])); + variables[62] = xor(variables[1] < variables[2], pow(variables[6], 1.0/variables[18])); + variables[63] = variables[1]/xor(variables[2], variables[6]); + variables[64] = !variables[1]; + variables[65] = variables[1]+variables[2]; + variables[66] = variables[1]+variables[2]+variables[6]; + variables[67] = (variables[1] < variables[2])+(variables[6] > variables[18]); + variables[68] = variables[1]; + variables[69] = variables[1]-variables[2]; + variables[70] = (variables[1] < variables[2])-(variables[6] > variables[18]); + variables[71] = (variables[1] < variables[2])-(variables[6]+variables[18]); + variables[72] = (variables[1] < variables[2])-variables[6]; + variables[73] = variables[1]-(-variables[2]); + variables[74] = variables[1]-(-variables[2]*variables[6]); + variables[75] = -variables[1]; + variables[76] = -(variables[1] < variables[2]); + variables[77] = variables[1]*variables[2]; + variables[78] = variables[1]*variables[2]*variables[6]; + variables[79] = (variables[1] < variables[2])*(variables[6] > variables[18]); + variables[80] = (variables[1]+variables[2])*(variables[6] > variables[18]); + variables[81] = variables[1]*(variables[2] > variables[6]); + variables[82] = (variables[1]-variables[2])*(variables[6] > variables[18]); + variables[83] = -variables[1]*(variables[2] > variables[6]); + variables[84] = (variables[1] < variables[2])*(variables[6]+variables[18]); + variables[85] = (variables[1] < variables[2])*variables[6]; + variables[86] = (variables[1] < variables[2])*(variables[6]-variables[18]); + variables[87] = (variables[1] < variables[2])*-variables[6]; + variables[88] = variables[1]/variables[2]; + variables[89] = (variables[1] < variables[2])/(variables[18] > variables[6]); + variables[90] = (variables[1]+variables[2])/(variables[18] > variables[6]); + variables[91] = variables[1]/(variables[6] > variables[2]); + variables[92] = (variables[1]-variables[2])/(variables[18] > variables[6]); + variables[93] = -variables[1]/(variables[6] > variables[2]); + variables[94] = (variables[1] < variables[2])/(variables[6]+variables[18]); + variables[95] = (variables[1] < variables[2])/variables[6]; + variables[96] = (variables[1] < variables[2])/(variables[6]-variables[18]); + variables[97] = (variables[1] < variables[2])/-variables[6]; + variables[98] = (variables[1] < variables[2])/(variables[6]*variables[18]); + variables[99] = (variables[1] < variables[2])/(variables[6]/variables[18]); + variables[100] = sqrt(variables[1]); + variables[101] = pow(variables[1], 2.0); + variables[102] = pow(variables[1], 3.0); + variables[103] = pow(variables[1], variables[2]); + variables[104] = pow(variables[1] <= variables[2], variables[6] >= variables[18]); + variables[105] = pow(variables[1]+variables[2], variables[6] >= variables[18]); + variables[106] = pow(variables[1], variables[2] >= variables[6]); + variables[107] = pow(variables[1]-variables[2], variables[6] >= variables[18]); + variables[108] = pow(-variables[1], variables[2] >= variables[6]); + variables[109] = pow(variables[1]*variables[2], variables[6] >= variables[18]); + variables[110] = pow(variables[1]/variables[2], variables[6] >= variables[18]); + variables[111] = pow(variables[1] <= variables[2], variables[6]+variables[18]); + variables[112] = pow(variables[1] <= variables[2], variables[6]); + variables[113] = pow(variables[1] <= variables[2], variables[6]-variables[18]); + variables[114] = pow(variables[1] <= variables[2], -variables[6]); + variables[115] = pow(variables[1] <= variables[2], variables[6]*variables[18]); + variables[116] = pow(variables[1] <= variables[2], variables[6]/variables[18]); + variables[117] = pow(variables[1] <= variables[2], pow(variables[6], variables[18])); + variables[118] = pow(variables[1] <= variables[2], pow(variables[6], 1.0/variables[18])); + variables[119] = sqrt(variables[1]); + variables[120] = sqrt(variables[1]); + variables[121] = pow(variables[1], 1.0/3.0); + variables[122] = pow(variables[1], 1.0/variables[2]); + variables[123] = pow(variables[1] < variables[2], 1.0/(variables[18] > variables[6])); + variables[124] = pow(variables[1]+variables[2], 1.0/(variables[18] > variables[6])); + variables[125] = pow(variables[1], 1.0/(variables[6] > variables[2])); + variables[126] = pow(variables[1]-variables[2], 1.0/(variables[18] > variables[6])); + variables[127] = pow(-variables[1], 1.0/(variables[6] > variables[2])); + variables[128] = pow(variables[1]*variables[2], 1.0/(variables[18] > variables[6])); + variables[129] = pow(variables[1]/variables[2], 1.0/(variables[18] > variables[6])); + variables[130] = pow(variables[1] < variables[2], 1.0/(variables[6]+variables[18])); + variables[131] = pow(variables[1] < variables[2], 1.0/variables[6]); + variables[132] = pow(variables[1] < variables[2], 1.0/(variables[6]-variables[18])); + variables[133] = pow(variables[1] < variables[2], 1.0/-variables[6]); + variables[134] = pow(variables[1] < variables[2], 1.0/(variables[6]*variables[18])); + variables[135] = pow(variables[1] < variables[2], 1.0/(variables[6]/variables[18])); + variables[136] = pow(variables[1] < variables[2], 1.0/pow(variables[6], variables[18])); + variables[137] = pow(variables[1] < variables[2], 1.0/pow(variables[6], 1.0/variables[18])); + variables[138] = fabs(variables[1]); + variables[139] = exp(variables[1]); + variables[140] = log(variables[1]); + variables[141] = log10(variables[1]); + variables[142] = log(variables[1])/log(2.0); + variables[143] = log10(variables[1]); + variables[144] = log(variables[1])/log(variables[2]); + variables[145] = ceil(variables[1]); + variables[146] = floor(variables[1]); + variables[147] = min(variables[1], variables[2]); + variables[148] = min(variables[1], min(variables[2], variables[6])); + variables[149] = max(variables[1], variables[2]); + variables[150] = max(variables[1], max(variables[2], variables[6])); + variables[151] = fmod(variables[1], variables[2]); + variables[152] = sin(variables[1]); + variables[153] = cos(variables[1]); + variables[154] = tan(variables[1]); + variables[155] = sec(variables[1]); + variables[156] = csc(variables[1]); + variables[157] = cot(variables[1]); + variables[158] = sinh(variables[1]); + variables[159] = cosh(variables[1]); + variables[160] = tanh(variables[1]); + variables[161] = sech(variables[1]); + variables[162] = csch(variables[1]); + variables[163] = coth(variables[1]); + variables[164] = asin(variables[1]); + variables[165] = acos(variables[1]); + variables[166] = atan(variables[1]); + variables[167] = asec(variables[1]); + variables[168] = acsc(variables[1]); + variables[169] = acot(variables[1]); + variables[170] = asinh(variables[1]); + variables[171] = acosh(variables[1]); + variables[172] = atanh(variables[1]/2.0); + variables[173] = asech(variables[1]); + variables[174] = acsch(variables[1]); + variables[175] = acoth(2.0*variables[1]); + variables[176] = (variables[1] > variables[2])?variables[1]:NAN; + variables[177] = (variables[1] > variables[2])?variables[1]:variables[6]; + variables[178] = (variables[1] > variables[2])?variables[1]:(variables[6] > variables[18])?variables[6]:(variables[179] > variables[180])?variables[179]:NAN; + variables[181] = (variables[1] > variables[2])?variables[1]:(variables[6] > variables[18])?variables[6]:(variables[179] > variables[180])?variables[179]:variables[182]; + variables[183] = 123.0+((variables[1] > variables[2])?variables[1]:NAN); + variables[188] = variables[1]; + variables[195] = (variables[1] && variables[2])+((variables[6] > variables[18])?variables[2]:NAN)+variables[179]+(variables[180] && variables[182]); + variables[196] = (variables[1] && variables[2])-(((variables[6] > variables[18])?variables[2]:NAN)-(variables[179]-((variables[6] > variables[18])?variables[2]:NAN)))-(variables[180] && variables[182]); + variables[197] = (variables[1] && variables[2])*((variables[6] > variables[18])?variables[2]:NAN)*variables[179]*((variables[6] > variables[18])?variables[2]:NAN)*(variables[180] && variables[182]); + variables[198] = (variables[1] && variables[2])/(((variables[6] > variables[18])?variables[2]:NAN)/(variables[179]/((variables[6] > variables[18])?variables[2]:NAN))); + variables[199] = (variables[1] || variables[2]) && xor(variables[1], variables[2]) && ((variables[6] > variables[18])?variables[2]:NAN) && variables[179] && ((variables[6] > variables[18])?variables[2]:NAN) && xor(variables[1], variables[2]) && (variables[1] || variables[2]); + variables[200] = (variables[1] && variables[2]) || xor(variables[1], variables[2]) || ((variables[6] > variables[18])?variables[2]:NAN) || variables[179] || ((variables[6] > variables[18])?variables[2]:NAN) || xor(variables[1], variables[2]) || (variables[1] && variables[2]); + variables[201] = xor(variables[1] && variables[2], xor(variables[1] || variables[2], xor((variables[6] > variables[18])?variables[2]:NAN, xor(xor(xor(variables[179], (variables[6] > variables[18])?variables[2]:NAN), variables[1] || variables[2]), variables[1] && variables[2])))); + variables[202] = pow(variables[1] && variables[2], pow((variables[6] > variables[18])?variables[2]:NAN, pow(pow(variables[179], (variables[6] > variables[18])?variables[2]:NAN), variables[1] && variables[2]))); + variables[203] = pow(pow(pow(variables[1] && variables[2], 1.0/pow((variables[6] > variables[18])?variables[2]:NAN, 1.0/variables[179])), 1.0/((variables[6] > variables[18])?variables[2]:NAN)), 1.0/(variables[1] && variables[2])); + variables[204] = -(variables[1] && variables[2])+-((variables[6] > variables[18])?variables[2]:NAN); +} + +void computeRates(double voi, double *states, double *rates, double *variables) +{ + rates[0] = 1.0; +} + +void computeVariables(double voi, double *states, double *rates, double *variables) +{ + findRoot0(voi, states, rates, variables); +} diff --git a/tests/resources/generator/coverage/model.modified.profile.h b/tests/resources/coverage/generator/model.modified.profile.h similarity index 89% rename from tests/resources/generator/coverage/model.modified.profile.h rename to tests/resources/coverage/generator/model.modified.profile.h index ffe95bb8b..dc602c289 100644 --- a/tests/resources/generator/coverage/model.modified.profile.h +++ b/tests/resources/coverage/generator/model.modified.profile.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using a modified C profile of libCellML 0.4.0. */ +/* The content of this file was generated using a modified C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesVector(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/coverage/model.modified.profile.py b/tests/resources/coverage/generator/model.modified.profile.py similarity index 57% rename from tests/resources/generator/coverage/model.modified.profile.py rename to tests/resources/coverage/generator/model.modified.profile.py index ec7902991..e99214ce3 100644 --- a/tests/resources/generator/coverage/model.modified.profile.py +++ b/tests/resources/coverage/generator/model.modified.profile.py @@ -1,14 +1,14 @@ -# The content of this file was generated using a modified Python profile of libCellML 0.4.0. +# The content of this file was generated using a modified Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1.post0" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0.post0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 -VARIABLE_COUNT = 186 +VARIABLE_COUNT = 209 class VariableType(Enum): @@ -26,24 +26,25 @@ class VariableType(Enum): ] VARIABLE_INFO = [ + {"name": "eqnEq", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "m", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, {"name": "n", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, - {"name": "o", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, - {"name": "p", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, - {"name": "q", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, - {"name": "r", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, - {"name": "s", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, - {"name": "eqnEq", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnEqCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnNeq", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnNeqCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "o", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, {"name": "eqnLt", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnLtCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnLeq", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnLeqCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnGt", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnGtCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnGeq", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnGeqCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAnd", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAndMultiple", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAndParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "p", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, {"name": "eqnAndParenthesesLeftPlusWith", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAndParenthesesLeftPlusWithout", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAndParenthesesLeftMinusWith", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, @@ -56,6 +57,7 @@ class VariableType(Enum): {"name": "eqnAndParenthesesRightMinusWithout", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAndParenthesesRightPower", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAndParenthesesRightRoot", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnAndCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnOr", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnOrMultiple", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnOrParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, @@ -71,6 +73,7 @@ class VariableType(Enum): {"name": "eqnOrParenthesesRightMinusWithout", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnOrParenthesesRightPower", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnOrParenthesesRightRoot", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnOrCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnXor", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnXorMultiple", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnXorParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, @@ -86,6 +89,7 @@ class VariableType(Enum): {"name": "eqnXorParenthesesRightMinusWithout", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnXorParenthesesRightPower", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnXorParenthesesRightRoot", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnXorCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnNot", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnPlus", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnPlusMultiple", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, @@ -95,6 +99,8 @@ class VariableType(Enum): {"name": "eqnMinusParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnMinusParenthesesPlusWith", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnMinusParenthesesPlusWithout", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnMinusParenthesesDirectUnaryMinus", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnMinusParenthesesIndirectUnaryMinus", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnMinusUnary", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnMinusUnaryParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnTimes", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, @@ -199,7 +205,10 @@ class VariableType(Enum): {"name": "eqnPiecewisePiece", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnPiecewisePieceOtherwise", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnPiecewisePiecePiecePiece", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "q", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, + {"name": "r", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, {"name": "eqnPiecewisePiecePiecePieceOtherwise", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "s", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, {"name": "eqnWithPiecewise", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnCnInteger", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnCnDouble", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, @@ -211,7 +220,21 @@ class VariableType(Enum): {"name": "eqnExponentiale", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnPi", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnInfinity", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "eqnNotanumber", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT} + {"name": "eqnNotanumber", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForPlusOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForMinusOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForTimesOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForDivideOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForAndOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForOrOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForXorOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForPowerOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForRootOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForMinusUnary", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnNlaVariable1", "units": "dimensionless", "component": "my_component", "type": VariableType.ALGEBRAIC}, + {"name": "eqnNlaVariable2", "units": "dimensionless", "component": "my_component", "type": VariableType.ALGEBRAIC}, + {"name": "eqnComputedConstant1", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnComputedConstant2", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT} ] @@ -325,197 +348,248 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): - variables[0] = 1.0 - variables[1] = 2.0 - variables[2] = 3.0 - variables[3] = 4.0 - variables[4] = 5.0 - variables[5] = 6.0 - variables[6] = 7.0 - variables[175] = 123.0 - variables[176] = 123.456789 - variables[177] = 123.0e99 - variables[178] = 123.456789e99 - variables[180] = 1.0 - variables[181] = 0.0 - variables[182] = 2.71828182845905 - variables[183] = 3.14159265358979 - variables[184] = inf - variables[185] = nan +from nlasolver import nla_solve + + +def objective_function_0(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[205] = u[0] + variables[206] = u[1] + + f[0] = variables[205]+variables[206]+states[0]-0.0 + f[1] = variables[205]-variables[206]-(variables[207]+variables[208]) + + +def find_root_0(voi, states, rates, variables): + u = [nan]*2 + + u[0] = variables[205] + u[1] = variables[206] + + u = nla_solve(objective_function_0, u, 2, [voi, states, rates, variables]) + + variables[205] = u[0] + variables[206] = u[1] + + +def initialise_variables(states, rates, variables): + variables[1] = 1.0 + variables[2] = 2.0 + variables[6] = 3.0 + variables[18] = 4.0 + variables[179] = 5.0 + variables[180] = 6.0 + variables[182] = 7.0 + variables[205] = 1.0 + variables[206] = 2.0 + variables[184] = 123.0 + variables[185] = 123.456789 + variables[186] = 123.0e99 + variables[187] = 123.456789e99 + variables[189] = 1.0 + variables[190] = 0.0 + variables[191] = 2.71828182845905 + variables[192] = 3.14159265358979 + variables[193] = inf + variables[194] = nan + variables[207] = 1.0 + variables[208] = 3.0 states[0] = 0.0 def compute_computed_constants(variables): - variables[7] = eq_func(variables[0], variables[1]) - variables[8] = variables[0]/eq_func(variables[1], variables[1]) - variables[9] = neq_func(variables[0], variables[1]) - variables[10] = variables[0]/neq_func(variables[1], variables[2]) - variables[11] = lt_func(variables[0], variables[1]) - variables[12] = leq_func(variables[0], variables[1]) - variables[13] = gt_func(variables[0], variables[1]) - variables[14] = geq_func(variables[0], variables[1]) - variables[15] = and_func(variables[0], variables[1]) - variables[16] = and_func(variables[0], and_func(variables[1], variables[2])) - variables[17] = and_func(lt_func(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[18] = and_func(variables[0]+variables[1], gt_func(variables[2], variables[3])) - variables[19] = and_func(variables[0], gt_func(variables[1], variables[2])) - variables[20] = and_func(variables[0]-variables[1], gt_func(variables[2], variables[3])) - variables[21] = and_func(-variables[0], gt_func(variables[1], variables[2])) - variables[22] = and_func(pow(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[23] = and_func(pow(variables[0], 1.0/variables[1]), gt_func(variables[2], variables[3])) - variables[24] = and_func(lt_func(variables[0], variables[1]), variables[2]+variables[3]) - variables[25] = and_func(lt_func(variables[0], variables[1]), variables[2]) - variables[26] = and_func(lt_func(variables[0], variables[1]), variables[2]-variables[3]) - variables[27] = and_func(lt_func(variables[0], variables[1]), -variables[2]) - variables[28] = and_func(lt_func(variables[0], variables[1]), pow(variables[2], variables[3])) - variables[29] = and_func(lt_func(variables[0], variables[1]), pow(variables[2], 1.0/variables[3])) - variables[30] = or_func(variables[0], variables[1]) - variables[31] = or_func(variables[0], or_func(variables[1], variables[2])) - variables[32] = or_func(lt_func(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[33] = or_func(variables[0]+variables[1], gt_func(variables[2], variables[3])) - variables[34] = or_func(variables[0], gt_func(variables[1], variables[2])) - variables[35] = or_func(variables[0]-variables[1], gt_func(variables[2], variables[3])) - variables[36] = or_func(-variables[0], gt_func(variables[1], variables[2])) - variables[37] = or_func(pow(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[38] = or_func(pow(variables[0], 1.0/variables[1]), gt_func(variables[2], variables[3])) - variables[39] = or_func(lt_func(variables[0], variables[1]), variables[2]+variables[3]) - variables[40] = or_func(lt_func(variables[0], variables[1]), variables[2]) - variables[41] = or_func(lt_func(variables[0], variables[1]), variables[2]-variables[3]) - variables[42] = or_func(lt_func(variables[0], variables[1]), -variables[2]) - variables[43] = or_func(lt_func(variables[0], variables[1]), pow(variables[2], variables[3])) - variables[44] = or_func(lt_func(variables[0], variables[1]), pow(variables[2], 1.0/variables[3])) - variables[45] = xor_func(variables[0], variables[1]) - variables[46] = xor_func(variables[0], xor_func(variables[1], variables[2])) - variables[47] = xor_func(lt_func(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[48] = xor_func(variables[0]+variables[1], gt_func(variables[2], variables[3])) - variables[49] = xor_func(variables[0], gt_func(variables[1], variables[2])) - variables[50] = xor_func(variables[0]-variables[1], gt_func(variables[2], variables[3])) - variables[51] = xor_func(-variables[0], gt_func(variables[1], variables[2])) - variables[52] = xor_func(pow(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[53] = xor_func(pow(variables[0], 1.0/variables[1]), gt_func(variables[2], variables[3])) - variables[54] = xor_func(lt_func(variables[0], variables[1]), variables[2]+variables[3]) - variables[55] = xor_func(lt_func(variables[0], variables[1]), variables[2]) - variables[56] = xor_func(lt_func(variables[0], variables[1]), variables[2]-variables[3]) - variables[57] = xor_func(lt_func(variables[0], variables[1]), -variables[2]) - variables[58] = xor_func(lt_func(variables[0], variables[1]), pow(variables[2], variables[3])) - variables[59] = xor_func(lt_func(variables[0], variables[1]), pow(variables[2], 1.0/variables[3])) - variables[60] = not_func(variables[0]) - variables[61] = variables[0]+variables[1] - variables[62] = variables[0]+variables[1]+variables[2] - variables[63] = lt_func(variables[0], variables[1])+gt_func(variables[2], variables[3]) - variables[64] = variables[0] - variables[65] = variables[0]-variables[1] - variables[66] = lt_func(variables[0], variables[1])-gt_func(variables[2], variables[3]) - variables[67] = lt_func(variables[0], variables[1])-(variables[2]+variables[3]) - variables[68] = lt_func(variables[0], variables[1])-variables[2] - variables[69] = -variables[0] - variables[70] = -lt_func(variables[0], variables[1]) - variables[71] = variables[0]*variables[1] - variables[72] = variables[0]*variables[1]*variables[2] - variables[73] = lt_func(variables[0], variables[1])*gt_func(variables[2], variables[3]) - variables[74] = (variables[0]+variables[1])*gt_func(variables[2], variables[3]) - variables[75] = variables[0]*gt_func(variables[1], variables[2]) - variables[76] = (variables[0]-variables[1])*gt_func(variables[2], variables[3]) - variables[77] = -variables[0]*gt_func(variables[1], variables[2]) - variables[78] = lt_func(variables[0], variables[1])*(variables[2]+variables[3]) - variables[79] = lt_func(variables[0], variables[1])*variables[2] - variables[80] = lt_func(variables[0], variables[1])*(variables[2]-variables[3]) - variables[81] = lt_func(variables[0], variables[1])*-variables[2] - variables[82] = variables[0]/variables[1] - variables[83] = lt_func(variables[0], variables[1])/gt_func(variables[3], variables[2]) - variables[84] = (variables[0]+variables[1])/gt_func(variables[3], variables[2]) - variables[85] = variables[0]/gt_func(variables[2], variables[1]) - variables[86] = (variables[0]-variables[1])/gt_func(variables[3], variables[2]) - variables[87] = -variables[0]/gt_func(variables[2], variables[1]) - variables[88] = lt_func(variables[0], variables[1])/(variables[2]+variables[3]) - variables[89] = lt_func(variables[0], variables[1])/variables[2] - variables[90] = lt_func(variables[0], variables[1])/(variables[2]-variables[3]) - variables[91] = lt_func(variables[0], variables[1])/-variables[2] - variables[92] = lt_func(variables[0], variables[1])/(variables[2]*variables[3]) - variables[93] = lt_func(variables[0], variables[1])/(variables[2]/variables[3]) - variables[94] = sqrt(variables[0]) - variables[95] = pow(variables[0], 2.0) - variables[96] = pow(variables[0], 3.0) - variables[97] = pow(variables[0], variables[1]) - variables[98] = pow(lt_func(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[99] = pow(variables[0]+variables[1], gt_func(variables[2], variables[3])) - variables[100] = pow(variables[0], gt_func(variables[1], variables[2])) - variables[101] = pow(variables[0]-variables[1], gt_func(variables[2], variables[3])) - variables[102] = pow(-variables[0], gt_func(variables[1], variables[2])) - variables[103] = pow(variables[0]*variables[1], gt_func(variables[2], variables[3])) - variables[104] = pow(variables[0]/variables[1], gt_func(variables[2], variables[3])) - variables[105] = pow(lt_func(variables[0], variables[1]), variables[2]+variables[3]) - variables[106] = pow(lt_func(variables[0], variables[1]), variables[2]) - variables[107] = pow(lt_func(variables[0], variables[1]), variables[2]-variables[3]) - variables[108] = pow(lt_func(variables[0], variables[1]), -variables[2]) - variables[109] = pow(lt_func(variables[0], variables[1]), variables[2]*variables[3]) - variables[110] = pow(lt_func(variables[0], variables[1]), variables[2]/variables[3]) - variables[111] = pow(lt_func(variables[0], variables[1]), pow(variables[2], variables[3])) - variables[112] = pow(lt_func(variables[0], variables[1]), pow(variables[2], 1.0/variables[3])) - variables[113] = sqrt(variables[0]) - variables[114] = sqrt(variables[0]) - variables[115] = pow(variables[0], 1.0/3.0) - variables[116] = pow(variables[0], 1.0/variables[1]) - variables[117] = pow(lt_func(variables[0], variables[1]), 1.0/gt_func(variables[3], variables[2])) - variables[118] = pow(variables[0]+variables[1], 1.0/gt_func(variables[3], variables[2])) - variables[119] = pow(variables[0], 1.0/gt_func(variables[2], variables[1])) - variables[120] = pow(variables[0]-variables[1], 1.0/gt_func(variables[3], variables[2])) - variables[121] = pow(-variables[0], 1.0/gt_func(variables[2], variables[1])) - variables[122] = pow(variables[0]*variables[1], 1.0/gt_func(variables[3], variables[2])) - variables[123] = pow(variables[0]/variables[1], 1.0/gt_func(variables[3], variables[2])) - variables[124] = pow(lt_func(variables[0], variables[1]), 1.0/(variables[2]+variables[3])) - variables[125] = pow(lt_func(variables[0], variables[1]), 1.0/variables[2]) - variables[126] = pow(lt_func(variables[0], variables[1]), 1.0/(variables[2]-variables[3])) - variables[127] = pow(lt_func(variables[0], variables[1]), 1.0/-variables[2]) - variables[128] = pow(lt_func(variables[0], variables[1]), 1.0/(variables[2]*variables[3])) - variables[129] = pow(lt_func(variables[0], variables[1]), 1.0/(variables[2]/variables[3])) - variables[130] = pow(lt_func(variables[0], variables[1]), 1.0/pow(variables[2], variables[3])) - variables[131] = pow(lt_func(variables[0], variables[1]), 1.0/pow(variables[2], 1.0/variables[3])) - variables[132] = fabs(variables[0]) - variables[133] = exp(variables[0]) - variables[134] = log(variables[0]) - variables[135] = log10(variables[0]) - variables[136] = log(variables[0])/log(2.0) - variables[137] = log10(variables[0]) - variables[138] = log(variables[0])/log(variables[1]) - variables[139] = ceil(variables[0]) - variables[140] = floor(variables[0]) - variables[141] = min(variables[0], variables[1]) - variables[142] = min(variables[0], min(variables[1], variables[2])) - variables[143] = max(variables[0], variables[1]) - variables[144] = max(variables[0], max(variables[1], variables[2])) - variables[145] = fmod(variables[0], variables[1]) - variables[146] = sin(variables[0]) - variables[147] = cos(variables[0]) - variables[148] = tan(variables[0]) - variables[149] = sec(variables[0]) - variables[150] = csc(variables[0]) - variables[151] = cot(variables[0]) - variables[152] = sinh(variables[0]) - variables[153] = cosh(variables[0]) - variables[154] = tanh(variables[0]) - variables[155] = sech(variables[0]) - variables[156] = csch(variables[0]) - variables[157] = coth(variables[0]) - variables[158] = asin(variables[0]) - variables[159] = acos(variables[0]) - variables[160] = atan(variables[0]) - variables[161] = asec(variables[0]) - variables[162] = acsc(variables[0]) - variables[163] = acot(variables[0]) - variables[164] = asinh(variables[0]) - variables[165] = acosh(variables[0]) - variables[166] = atanh(variables[0]/2.0) - variables[167] = asech(variables[0]) - variables[168] = acsch(variables[0]) - variables[169] = acoth(2.0*variables[0]) - variables[170] = variables[0] if gt_func(variables[0], variables[1]) else nan - variables[171] = variables[0] if gt_func(variables[0], variables[1]) else variables[2] - variables[172] = variables[0] if gt_func(variables[0], variables[1]) else variables[2] if gt_func(variables[2], variables[3]) else variables[4] if gt_func(variables[4], variables[5]) else nan - variables[173] = variables[0] if gt_func(variables[0], variables[1]) else variables[2] if gt_func(variables[2], variables[3]) else variables[4] if gt_func(variables[4], variables[5]) else variables[6] - variables[174] = 123.0+(variables[0] if gt_func(variables[0], variables[1]) else nan) - variables[179] = variables[0] + variables[0] = eq_func(variables[1], variables[2]) + variables[3] = variables[1]/eq_func(variables[2], variables[2]) + variables[4] = neq_func(variables[1], variables[2]) + variables[5] = variables[1]/neq_func(variables[2], variables[6]) + variables[7] = lt_func(variables[1], variables[2]) + variables[8] = variables[1]/lt_func(variables[2], variables[6]) + variables[9] = leq_func(variables[1], variables[2]) + variables[10] = variables[1]/leq_func(variables[2], variables[6]) + variables[11] = gt_func(variables[1], variables[2]) + variables[12] = variables[1]/gt_func(variables[2], variables[6]) + variables[13] = geq_func(variables[1], variables[2]) + variables[14] = variables[1]/geq_func(variables[2], variables[6]) + variables[15] = and_func(variables[1], variables[2]) + variables[16] = and_func(variables[1], and_func(variables[2], variables[6])) + variables[17] = and_func(lt_func(variables[1], variables[2]), gt_func(variables[6], variables[18])) + variables[19] = and_func(variables[1]+variables[2], gt_func(variables[6], variables[18])) + variables[20] = and_func(variables[1], gt_func(variables[2], variables[6])) + variables[21] = and_func(variables[1]-variables[2], gt_func(variables[6], variables[18])) + variables[22] = and_func(-variables[1], gt_func(variables[2], variables[6])) + variables[23] = and_func(pow(variables[1], variables[2]), gt_func(variables[6], variables[18])) + variables[24] = and_func(pow(variables[1], 1.0/variables[2]), gt_func(variables[6], variables[18])) + variables[25] = and_func(lt_func(variables[1], variables[2]), variables[6]+variables[18]) + variables[26] = and_func(lt_func(variables[1], variables[2]), variables[6]) + variables[27] = and_func(lt_func(variables[1], variables[2]), variables[6]-variables[18]) + variables[28] = and_func(lt_func(variables[1], variables[2]), -variables[6]) + variables[29] = and_func(lt_func(variables[1], variables[2]), pow(variables[6], variables[18])) + variables[30] = and_func(lt_func(variables[1], variables[2]), pow(variables[6], 1.0/variables[18])) + variables[31] = variables[1]/and_func(variables[2], variables[6]) + variables[32] = or_func(variables[1], variables[2]) + variables[33] = or_func(variables[1], or_func(variables[2], variables[6])) + variables[34] = or_func(lt_func(variables[1], variables[2]), gt_func(variables[6], variables[18])) + variables[35] = or_func(variables[1]+variables[2], gt_func(variables[6], variables[18])) + variables[36] = or_func(variables[1], gt_func(variables[2], variables[6])) + variables[37] = or_func(variables[1]-variables[2], gt_func(variables[6], variables[18])) + variables[38] = or_func(-variables[1], gt_func(variables[2], variables[6])) + variables[39] = or_func(pow(variables[1], variables[2]), gt_func(variables[6], variables[18])) + variables[40] = or_func(pow(variables[1], 1.0/variables[2]), gt_func(variables[6], variables[18])) + variables[41] = or_func(lt_func(variables[1], variables[2]), variables[6]+variables[18]) + variables[42] = or_func(lt_func(variables[1], variables[2]), variables[6]) + variables[43] = or_func(lt_func(variables[1], variables[2]), variables[6]-variables[18]) + variables[44] = or_func(lt_func(variables[1], variables[2]), -variables[6]) + variables[45] = or_func(lt_func(variables[1], variables[2]), pow(variables[6], variables[18])) + variables[46] = or_func(lt_func(variables[1], variables[2]), pow(variables[6], 1.0/variables[18])) + variables[47] = variables[1]/or_func(variables[2], variables[6]) + variables[48] = xor_func(variables[1], variables[2]) + variables[49] = xor_func(variables[1], xor_func(variables[2], variables[6])) + variables[50] = xor_func(lt_func(variables[1], variables[2]), gt_func(variables[6], variables[18])) + variables[51] = xor_func(variables[1]+variables[2], gt_func(variables[6], variables[18])) + variables[52] = xor_func(variables[1], gt_func(variables[2], variables[6])) + variables[53] = xor_func(variables[1]-variables[2], gt_func(variables[6], variables[18])) + variables[54] = xor_func(-variables[1], gt_func(variables[2], variables[6])) + variables[55] = xor_func(pow(variables[1], variables[2]), gt_func(variables[6], variables[18])) + variables[56] = xor_func(pow(variables[1], 1.0/variables[2]), gt_func(variables[6], variables[18])) + variables[57] = xor_func(lt_func(variables[1], variables[2]), variables[6]+variables[18]) + variables[58] = xor_func(lt_func(variables[1], variables[2]), variables[6]) + variables[59] = xor_func(lt_func(variables[1], variables[2]), variables[6]-variables[18]) + variables[60] = xor_func(lt_func(variables[1], variables[2]), -variables[6]) + variables[61] = xor_func(lt_func(variables[1], variables[2]), pow(variables[6], variables[18])) + variables[62] = xor_func(lt_func(variables[1], variables[2]), pow(variables[6], 1.0/variables[18])) + variables[63] = variables[1]/xor_func(variables[2], variables[6]) + variables[64] = not_func(variables[1]) + variables[65] = variables[1]+variables[2] + variables[66] = variables[1]+variables[2]+variables[6] + variables[67] = lt_func(variables[1], variables[2])+gt_func(variables[6], variables[18]) + variables[68] = variables[1] + variables[69] = variables[1]-variables[2] + variables[70] = lt_func(variables[1], variables[2])-gt_func(variables[6], variables[18]) + variables[71] = lt_func(variables[1], variables[2])-(variables[6]+variables[18]) + variables[72] = lt_func(variables[1], variables[2])-variables[6] + variables[73] = variables[1]-(-variables[2]) + variables[74] = variables[1]-(-variables[2]*variables[6]) + variables[75] = -variables[1] + variables[76] = -lt_func(variables[1], variables[2]) + variables[77] = variables[1]*variables[2] + variables[78] = variables[1]*variables[2]*variables[6] + variables[79] = lt_func(variables[1], variables[2])*gt_func(variables[6], variables[18]) + variables[80] = (variables[1]+variables[2])*gt_func(variables[6], variables[18]) + variables[81] = variables[1]*gt_func(variables[2], variables[6]) + variables[82] = (variables[1]-variables[2])*gt_func(variables[6], variables[18]) + variables[83] = -variables[1]*gt_func(variables[2], variables[6]) + variables[84] = lt_func(variables[1], variables[2])*(variables[6]+variables[18]) + variables[85] = lt_func(variables[1], variables[2])*variables[6] + variables[86] = lt_func(variables[1], variables[2])*(variables[6]-variables[18]) + variables[87] = lt_func(variables[1], variables[2])*-variables[6] + variables[88] = variables[1]/variables[2] + variables[89] = lt_func(variables[1], variables[2])/gt_func(variables[18], variables[6]) + variables[90] = (variables[1]+variables[2])/gt_func(variables[18], variables[6]) + variables[91] = variables[1]/gt_func(variables[6], variables[2]) + variables[92] = (variables[1]-variables[2])/gt_func(variables[18], variables[6]) + variables[93] = -variables[1]/gt_func(variables[6], variables[2]) + variables[94] = lt_func(variables[1], variables[2])/(variables[6]+variables[18]) + variables[95] = lt_func(variables[1], variables[2])/variables[6] + variables[96] = lt_func(variables[1], variables[2])/(variables[6]-variables[18]) + variables[97] = lt_func(variables[1], variables[2])/-variables[6] + variables[98] = lt_func(variables[1], variables[2])/(variables[6]*variables[18]) + variables[99] = lt_func(variables[1], variables[2])/(variables[6]/variables[18]) + variables[100] = sqrt(variables[1]) + variables[101] = pow(variables[1], 2.0) + variables[102] = pow(variables[1], 3.0) + variables[103] = pow(variables[1], variables[2]) + variables[104] = pow(leq_func(variables[1], variables[2]), geq_func(variables[6], variables[18])) + variables[105] = pow(variables[1]+variables[2], geq_func(variables[6], variables[18])) + variables[106] = pow(variables[1], geq_func(variables[2], variables[6])) + variables[107] = pow(variables[1]-variables[2], geq_func(variables[6], variables[18])) + variables[108] = pow(-variables[1], geq_func(variables[2], variables[6])) + variables[109] = pow(variables[1]*variables[2], geq_func(variables[6], variables[18])) + variables[110] = pow(variables[1]/variables[2], geq_func(variables[6], variables[18])) + variables[111] = pow(leq_func(variables[1], variables[2]), variables[6]+variables[18]) + variables[112] = pow(leq_func(variables[1], variables[2]), variables[6]) + variables[113] = pow(leq_func(variables[1], variables[2]), variables[6]-variables[18]) + variables[114] = pow(leq_func(variables[1], variables[2]), -variables[6]) + variables[115] = pow(leq_func(variables[1], variables[2]), variables[6]*variables[18]) + variables[116] = pow(leq_func(variables[1], variables[2]), variables[6]/variables[18]) + variables[117] = pow(leq_func(variables[1], variables[2]), pow(variables[6], variables[18])) + variables[118] = pow(leq_func(variables[1], variables[2]), pow(variables[6], 1.0/variables[18])) + variables[119] = sqrt(variables[1]) + variables[120] = sqrt(variables[1]) + variables[121] = pow(variables[1], 1.0/3.0) + variables[122] = pow(variables[1], 1.0/variables[2]) + variables[123] = pow(lt_func(variables[1], variables[2]), 1.0/gt_func(variables[18], variables[6])) + variables[124] = pow(variables[1]+variables[2], 1.0/gt_func(variables[18], variables[6])) + variables[125] = pow(variables[1], 1.0/gt_func(variables[6], variables[2])) + variables[126] = pow(variables[1]-variables[2], 1.0/gt_func(variables[18], variables[6])) + variables[127] = pow(-variables[1], 1.0/gt_func(variables[6], variables[2])) + variables[128] = pow(variables[1]*variables[2], 1.0/gt_func(variables[18], variables[6])) + variables[129] = pow(variables[1]/variables[2], 1.0/gt_func(variables[18], variables[6])) + variables[130] = pow(lt_func(variables[1], variables[2]), 1.0/(variables[6]+variables[18])) + variables[131] = pow(lt_func(variables[1], variables[2]), 1.0/variables[6]) + variables[132] = pow(lt_func(variables[1], variables[2]), 1.0/(variables[6]-variables[18])) + variables[133] = pow(lt_func(variables[1], variables[2]), 1.0/-variables[6]) + variables[134] = pow(lt_func(variables[1], variables[2]), 1.0/(variables[6]*variables[18])) + variables[135] = pow(lt_func(variables[1], variables[2]), 1.0/(variables[6]/variables[18])) + variables[136] = pow(lt_func(variables[1], variables[2]), 1.0/pow(variables[6], variables[18])) + variables[137] = pow(lt_func(variables[1], variables[2]), 1.0/pow(variables[6], 1.0/variables[18])) + variables[138] = fabs(variables[1]) + variables[139] = exp(variables[1]) + variables[140] = log(variables[1]) + variables[141] = log10(variables[1]) + variables[142] = log(variables[1])/log(2.0) + variables[143] = log10(variables[1]) + variables[144] = log(variables[1])/log(variables[2]) + variables[145] = ceil(variables[1]) + variables[146] = floor(variables[1]) + variables[147] = min(variables[1], variables[2]) + variables[148] = min(variables[1], min(variables[2], variables[6])) + variables[149] = max(variables[1], variables[2]) + variables[150] = max(variables[1], max(variables[2], variables[6])) + variables[151] = fmod(variables[1], variables[2]) + variables[152] = sin(variables[1]) + variables[153] = cos(variables[1]) + variables[154] = tan(variables[1]) + variables[155] = sec(variables[1]) + variables[156] = csc(variables[1]) + variables[157] = cot(variables[1]) + variables[158] = sinh(variables[1]) + variables[159] = cosh(variables[1]) + variables[160] = tanh(variables[1]) + variables[161] = sech(variables[1]) + variables[162] = csch(variables[1]) + variables[163] = coth(variables[1]) + variables[164] = asin(variables[1]) + variables[165] = acos(variables[1]) + variables[166] = atan(variables[1]) + variables[167] = asec(variables[1]) + variables[168] = acsc(variables[1]) + variables[169] = acot(variables[1]) + variables[170] = asinh(variables[1]) + variables[171] = acosh(variables[1]) + variables[172] = atanh(variables[1]/2.0) + variables[173] = asech(variables[1]) + variables[174] = acsch(variables[1]) + variables[175] = acoth(2.0*variables[1]) + variables[176] = variables[1] if gt_func(variables[1], variables[2]) else nan + variables[177] = variables[1] if gt_func(variables[1], variables[2]) else variables[6] + variables[178] = variables[1] if gt_func(variables[1], variables[2]) else variables[6] if gt_func(variables[6], variables[18]) else variables[179] if gt_func(variables[179], variables[180]) else nan + variables[181] = variables[1] if gt_func(variables[1], variables[2]) else variables[6] if gt_func(variables[6], variables[18]) else variables[179] if gt_func(variables[179], variables[180]) else variables[182] + variables[183] = 123.0+(variables[1] if gt_func(variables[1], variables[2]) else nan) + variables[188] = variables[1] + variables[195] = and_func(variables[1], variables[2])+(variables[2] if gt_func(variables[6], variables[18]) else nan)+variables[179]+and_func(variables[180], variables[182]) + variables[196] = and_func(variables[1], variables[2])-((variables[2] if gt_func(variables[6], variables[18]) else nan)-(variables[179]-(variables[2] if gt_func(variables[6], variables[18]) else nan)))-and_func(variables[180], variables[182]) + variables[197] = and_func(variables[1], variables[2])*(variables[2] if gt_func(variables[6], variables[18]) else nan)*variables[179]*(variables[2] if gt_func(variables[6], variables[18]) else nan)*and_func(variables[180], variables[182]) + variables[198] = and_func(variables[1], variables[2])/((variables[2] if gt_func(variables[6], variables[18]) else nan)/(variables[179]/(variables[2] if gt_func(variables[6], variables[18]) else nan))) + variables[199] = and_func(or_func(variables[1], variables[2]), and_func(xor_func(variables[1], variables[2]), and_func(variables[2] if gt_func(variables[6], variables[18]) else nan, and_func(and_func(and_func(variables[179], variables[2] if gt_func(variables[6], variables[18]) else nan), xor_func(variables[1], variables[2])), or_func(variables[1], variables[2]))))) + variables[200] = or_func(and_func(variables[1], variables[2]), or_func(xor_func(variables[1], variables[2]), or_func(variables[2] if gt_func(variables[6], variables[18]) else nan, or_func(or_func(or_func(variables[179], variables[2] if gt_func(variables[6], variables[18]) else nan), xor_func(variables[1], variables[2])), and_func(variables[1], variables[2]))))) + variables[201] = xor_func(and_func(variables[1], variables[2]), xor_func(or_func(variables[1], variables[2]), xor_func(variables[2] if gt_func(variables[6], variables[18]) else nan, xor_func(xor_func(xor_func(variables[179], variables[2] if gt_func(variables[6], variables[18]) else nan), or_func(variables[1], variables[2])), and_func(variables[1], variables[2]))))) + variables[202] = pow(and_func(variables[1], variables[2]), pow(variables[2] if gt_func(variables[6], variables[18]) else nan, pow(pow(variables[179], variables[2] if gt_func(variables[6], variables[18]) else nan), and_func(variables[1], variables[2])))) + variables[203] = pow(pow(pow(and_func(variables[1], variables[2]), 1.0/pow(variables[2] if gt_func(variables[6], variables[18]) else nan, 1.0/variables[179])), 1.0/(variables[2] if gt_func(variables[6], variables[18]) else nan)), 1.0/and_func(variables[1], variables[2])) + variables[204] = -and_func(variables[1], variables[2])+-(variables[2] if gt_func(variables[6], variables[18]) else nan) def compute_rates(voi, states, rates, variables): @@ -523,4 +597,4 @@ def compute_rates(voi, states, rates, variables): def compute_variables(voi, states, rates, variables): - pass + find_root_0(voi, states, rates, variables) diff --git a/tests/resources/coverage/generator/model.out b/tests/resources/coverage/generator/model.out new file mode 100644 index 000000000..2791e4470 --- /dev/null +++ b/tests/resources/coverage/generator/model.out @@ -0,0 +1,340 @@ +/* The content of this file was generated using a modified C profile of libCellML 0.5.0. */ + +#include "customheaderfile.h" + +double min(double x, double y) +{ + return (x < y)?x:y; +} + +double max(double x, double y) +{ + return (x > y)?x:y; +} + +double sec(double x) +{ + return 1.0/cos(x); +} + +double csc(double x) +{ + return 1.0/sin(x); +} + +double cot(double x) +{ + return 1.0/tan(x); +} + +double sech(double x) +{ + return 1.0/cosh(x); +} + +double csch(double x) +{ + return 1.0/sinh(x); +} + +double coth(double x) +{ + return 1.0/tanh(x); +} + +double asec(double x) +{ + return acos(1.0/x); +} + +double acsc(double x) +{ + return asin(1.0/x); +} + +double acot(double x) +{ + return atan(1.0/x); +} + +double asech(double x) +{ + double oneOverX = 1.0/x; + + return log(oneOverX+sqrt(oneOverX*oneOverX-1.0)); +} + +double acsch(double x) +{ + double oneOverX = 1.0/x; + + return log(oneOverX+sqrt(oneOverX*oneOverX+1.0)); +} + +double acoth(double x) +{ + double oneOverX = 1.0/x; + + return 0.5*log((1.0+oneOverX)/(1.0-oneOverX)); +} + +typedef struct { + double voi; + double *states; + double *rates; + double *variables; +} RootFindingInfo; + +extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *), + double *u, int n, void *data); + +void objectiveFunction0(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[205] = u[0]; + variables[206] = u[1]; + + f[0] = variables[205]+variables[206]+states[0]-0.0; + f[1] = variables[205]-variables[206]-(variables[207]+variables[208]); +} + +void findRoot0(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[2]; + + u[0] = variables[205]; + u[1] = variables[206]; + + nlaSolve(objectiveFunction0, u, 2, &rfi); + + variables[205] = u[0]; + variables[206] = u[1]; +} + +void initialiseVariables(double *states, double *rates, double *variables) +{ + variables[1] = 1.0; + variables[2] = 2.0; + variables[6] = 3.0; + variables[18] = 4.0; + variables[179] = 5.0; + variables[180] = 6.0; + variables[182] = 7.0; + variables[205] = 1.0; + variables[206] = 2.0; + variables[184] = 123.0; + variables[185] = 123.456789; + variables[186] = 123.0e99; + variables[187] = 123.456789e99; + variables[189] = 1.0; + variables[190] = 0.0; + variables[191] = 2.71828182845905; + variables[192] = 3.14159265358979; + variables[193] = INFINITY; + variables[194] = NAN; + variables[207] = 1.0; + variables[208] = 3.0; + states[0] = 0.0; +} + +void computeComputedConstants(double *variables) +{ + variables[0] = variables[1] == variables[2]; + variables[3] = variables[1]/(variables[2] == variables[2]); + variables[4] = variables[1] != variables[2]; + variables[5] = variables[1]/(variables[2] != variables[6]); + variables[7] = variables[1] < variables[2]; + variables[8] = variables[1]/(variables[2] < variables[6]); + variables[9] = variables[1] <= variables[2]; + variables[10] = variables[1]/(variables[2] <= variables[6]); + variables[11] = variables[1] > variables[2]; + variables[12] = variables[1]/(variables[2] > variables[6]); + variables[13] = variables[1] >= variables[2]; + variables[14] = variables[1]/(variables[2] >= variables[6]); + variables[15] = variables[1] && variables[2]; + variables[16] = variables[1] && variables[2] && variables[6]; + variables[17] = (variables[1] < variables[2]) && (variables[6] > variables[18]); + variables[19] = (variables[1]+variables[2]) && (variables[6] > variables[18]); + variables[20] = variables[1] && (variables[2] > variables[6]); + variables[21] = (variables[1]-variables[2]) && (variables[6] > variables[18]); + variables[22] = -variables[1] && (variables[2] > variables[6]); + variables[23] = (variables[1]^^variables[2]) && (variables[6] > variables[18]); + variables[24] = (variables[1]^^(1.0/variables[2])) && (variables[6] > variables[18]); + variables[25] = (variables[1] < variables[2]) && (variables[6]+variables[18]); + variables[26] = (variables[1] < variables[2]) && variables[6]; + variables[27] = (variables[1] < variables[2]) && (variables[6]-variables[18]); + variables[28] = (variables[1] < variables[2]) && -variables[6]; + variables[29] = (variables[1] < variables[2]) && (variables[6]^^variables[18]); + variables[30] = (variables[1] < variables[2]) && (variables[6]^^(1.0/variables[18])); + variables[31] = variables[1]/(variables[2] && variables[6]); + variables[32] = variables[1] || variables[2]; + variables[33] = variables[1] || variables[2] || variables[6]; + variables[34] = (variables[1] < variables[2]) || (variables[6] > variables[18]); + variables[35] = (variables[1]+variables[2]) || (variables[6] > variables[18]); + variables[36] = variables[1] || (variables[2] > variables[6]); + variables[37] = (variables[1]-variables[2]) || (variables[6] > variables[18]); + variables[38] = -variables[1] || (variables[2] > variables[6]); + variables[39] = (variables[1]^^variables[2]) || (variables[6] > variables[18]); + variables[40] = (variables[1]^^(1.0/variables[2])) || (variables[6] > variables[18]); + variables[41] = (variables[1] < variables[2]) || (variables[6]+variables[18]); + variables[42] = (variables[1] < variables[2]) || variables[6]; + variables[43] = (variables[1] < variables[2]) || (variables[6]-variables[18]); + variables[44] = (variables[1] < variables[2]) || -variables[6]; + variables[45] = (variables[1] < variables[2]) || (variables[6]^^variables[18]); + variables[46] = (variables[1] < variables[2]) || (variables[6]^^(1.0/variables[18])); + variables[47] = variables[1]/(variables[2] || variables[6]); + variables[48] = variables[1]^variables[2]; + variables[49] = variables[1]^variables[2]^variables[6]; + variables[50] = (variables[1] < variables[2])^(variables[6] > variables[18]); + variables[51] = (variables[1]+variables[2])^(variables[6] > variables[18]); + variables[52] = variables[1]^(variables[2] > variables[6]); + variables[53] = (variables[1]-variables[2])^(variables[6] > variables[18]); + variables[54] = -variables[1]^(variables[2] > variables[6]); + variables[55] = (variables[1]^^variables[2])^(variables[6] > variables[18]); + variables[56] = (variables[1]^^(1.0/variables[2]))^(variables[6] > variables[18]); + variables[57] = (variables[1] < variables[2])^(variables[6]+variables[18]); + variables[58] = (variables[1] < variables[2])^variables[6]; + variables[59] = (variables[1] < variables[2])^(variables[6]-variables[18]); + variables[60] = (variables[1] < variables[2])^-variables[6]; + variables[61] = (variables[1] < variables[2])^(variables[6]^^variables[18]); + variables[62] = (variables[1] < variables[2])^(variables[6]^^(1.0/variables[18])); + variables[63] = variables[1]/(variables[2]^variables[6]); + variables[64] = !variables[1]; + variables[65] = variables[1]+variables[2]; + variables[66] = variables[1]+variables[2]+variables[6]; + variables[67] = (variables[1] < variables[2])+(variables[6] > variables[18]); + variables[68] = variables[1]; + variables[69] = variables[1]-variables[2]; + variables[70] = (variables[1] < variables[2])-(variables[6] > variables[18]); + variables[71] = (variables[1] < variables[2])-(variables[6]+variables[18]); + variables[72] = (variables[1] < variables[2])-variables[6]; + variables[73] = variables[1]-(-variables[2]); + variables[74] = variables[1]-(-variables[2]*variables[6]); + variables[75] = -variables[1]; + variables[76] = -(variables[1] < variables[2]); + variables[77] = variables[1]*variables[2]; + variables[78] = variables[1]*variables[2]*variables[6]; + variables[79] = (variables[1] < variables[2])*(variables[6] > variables[18]); + variables[80] = (variables[1]+variables[2])*(variables[6] > variables[18]); + variables[81] = variables[1]*(variables[2] > variables[6]); + variables[82] = (variables[1]-variables[2])*(variables[6] > variables[18]); + variables[83] = -variables[1]*(variables[2] > variables[6]); + variables[84] = (variables[1] < variables[2])*(variables[6]+variables[18]); + variables[85] = (variables[1] < variables[2])*variables[6]; + variables[86] = (variables[1] < variables[2])*(variables[6]-variables[18]); + variables[87] = (variables[1] < variables[2])*-variables[6]; + variables[88] = variables[1]/variables[2]; + variables[89] = (variables[1] < variables[2])/(variables[18] > variables[6]); + variables[90] = (variables[1]+variables[2])/(variables[18] > variables[6]); + variables[91] = variables[1]/(variables[6] > variables[2]); + variables[92] = (variables[1]-variables[2])/(variables[18] > variables[6]); + variables[93] = -variables[1]/(variables[6] > variables[2]); + variables[94] = (variables[1] < variables[2])/(variables[6]+variables[18]); + variables[95] = (variables[1] < variables[2])/variables[6]; + variables[96] = (variables[1] < variables[2])/(variables[6]-variables[18]); + variables[97] = (variables[1] < variables[2])/-variables[6]; + variables[98] = (variables[1] < variables[2])/(variables[6]*variables[18]); + variables[99] = (variables[1] < variables[2])/(variables[6]/variables[18]); + variables[100] = sqrt(variables[1]); + variables[101] = sqr(variables[1]); + variables[102] = variables[1]^^3.0; + variables[103] = variables[1]^^variables[2]; + variables[104] = (variables[1] <= variables[2])^^(variables[6] >= variables[18]); + variables[105] = (variables[1]+variables[2])^^(variables[6] >= variables[18]); + variables[106] = variables[1]^^(variables[2] >= variables[6]); + variables[107] = (variables[1]-variables[2])^^(variables[6] >= variables[18]); + variables[108] = (-variables[1])^^(variables[2] >= variables[6]); + variables[109] = (variables[1]*variables[2])^^(variables[6] >= variables[18]); + variables[110] = (variables[1]/variables[2])^^(variables[6] >= variables[18]); + variables[111] = (variables[1] <= variables[2])^^(variables[6]+variables[18]); + variables[112] = (variables[1] <= variables[2])^^variables[6]; + variables[113] = (variables[1] <= variables[2])^^variables[6]-variables[18]; + variables[114] = (variables[1] <= variables[2])^^-variables[6]; + variables[115] = (variables[1] <= variables[2])^^(variables[6]*variables[18]); + variables[116] = (variables[1] <= variables[2])^^(variables[6]/variables[18]); + variables[117] = (variables[1] <= variables[2])^^(variables[6]^^variables[18]); + variables[118] = (variables[1] <= variables[2])^^(variables[6]^^(1.0/variables[18])); + variables[119] = sqrt(variables[1]); + variables[120] = sqrt(variables[1]); + variables[121] = variables[1]^^(1.0/3.0); + variables[122] = variables[1]^^(1.0/variables[2]); + variables[123] = (variables[1] < variables[2])^^(1.0/(variables[18] > variables[6])); + variables[124] = (variables[1]+variables[2])^^(1.0/(variables[18] > variables[6])); + variables[125] = variables[1]^^(1.0/(variables[6] > variables[2])); + variables[126] = (variables[1]-variables[2])^^(1.0/(variables[18] > variables[6])); + variables[127] = (-variables[1])^^(1.0/(variables[6] > variables[2])); + variables[128] = (variables[1]*variables[2])^^(1.0/(variables[18] > variables[6])); + variables[129] = (variables[1]/variables[2])^^(1.0/(variables[18] > variables[6])); + variables[130] = (variables[1] < variables[2])^^(1.0/(variables[6]+variables[18])); + variables[131] = (variables[1] < variables[2])^^(1.0/variables[6]); + variables[132] = (variables[1] < variables[2])^^(1.0/(variables[6]-variables[18])); + variables[133] = (variables[1] < variables[2])^^(1.0/(-variables[6])); + variables[134] = (variables[1] < variables[2])^^(1.0/(variables[6]*variables[18])); + variables[135] = (variables[1] < variables[2])^^(1.0/(variables[6]/variables[18])); + variables[136] = (variables[1] < variables[2])^^(1.0/(variables[6]^^variables[18])); + variables[137] = (variables[1] < variables[2])^^(1.0/(variables[6]^^(1.0/variables[18]))); + variables[138] = fabs(variables[1]); + variables[139] = exp(variables[1]); + variables[140] = log(variables[1]); + variables[141] = log10(variables[1]); + variables[142] = log(variables[1])/log(2.0); + variables[143] = log10(variables[1]); + variables[144] = log(variables[1])/log(variables[2]); + variables[145] = ceil(variables[1]); + variables[146] = floor(variables[1]); + variables[147] = min(variables[1], variables[2]); + variables[148] = min(variables[1], min(variables[2], variables[6])); + variables[149] = max(variables[1], variables[2]); + variables[150] = max(variables[1], max(variables[2], variables[6])); + variables[151] = fmod(variables[1], variables[2]); + variables[152] = sin(variables[1]); + variables[153] = cos(variables[1]); + variables[154] = tan(variables[1]); + variables[155] = sec(variables[1]); + variables[156] = csc(variables[1]); + variables[157] = cot(variables[1]); + variables[158] = sinh(variables[1]); + variables[159] = cosh(variables[1]); + variables[160] = tanh(variables[1]); + variables[161] = sech(variables[1]); + variables[162] = csch(variables[1]); + variables[163] = coth(variables[1]); + variables[164] = asin(variables[1]); + variables[165] = acos(variables[1]); + variables[166] = atan(variables[1]); + variables[167] = asec(variables[1]); + variables[168] = acsc(variables[1]); + variables[169] = acot(variables[1]); + variables[170] = asinh(variables[1]); + variables[171] = acosh(variables[1]); + variables[172] = atanh(variables[1]/2.0); + variables[173] = asech(variables[1]); + variables[174] = acsch(variables[1]); + variables[175] = acoth(2.0*variables[1]); + variables[176] = piecewise(variables[1] > variables[2], variables[1], NAN); + variables[177] = piecewise(variables[1] > variables[2], variables[1], variables[6]); + variables[178] = piecewise(variables[1] > variables[2], variables[1], piecewise(variables[6] > variables[18], variables[6], piecewise(variables[179] > variables[180], variables[179], NAN))); + variables[181] = piecewise(variables[1] > variables[2], variables[1], piecewise(variables[6] > variables[18], variables[6], piecewise(variables[179] > variables[180], variables[179], variables[182]))); + variables[183] = 123.0+piecewise(variables[1] > variables[2], variables[1], NAN); + variables[188] = variables[1]; + variables[195] = (variables[1] && variables[2])+piecewise(variables[6] > variables[18], variables[2], NAN)+variables[179]+(variables[180] && variables[182]); + variables[196] = (variables[1] && variables[2])-(piecewise(variables[6] > variables[18], variables[2], NAN)-(variables[179]-piecewise(variables[6] > variables[18], variables[2], NAN)))-(variables[180] && variables[182]); + variables[197] = (variables[1] && variables[2])*piecewise(variables[6] > variables[18], variables[2], NAN)*variables[179]*piecewise(variables[6] > variables[18], variables[2], NAN)*(variables[180] && variables[182]); + variables[198] = (variables[1] && variables[2])/(piecewise(variables[6] > variables[18], variables[2], NAN)/(variables[179]/piecewise(variables[6] > variables[18], variables[2], NAN))); + variables[199] = (variables[1] || variables[2]) && (variables[1]^variables[2]) && piecewise(variables[6] > variables[18], variables[2], NAN) && variables[179] && piecewise(variables[6] > variables[18], variables[2], NAN) && (variables[1]^variables[2]) && (variables[1] || variables[2]); + variables[200] = (variables[1] && variables[2]) || (variables[1]^variables[2]) || piecewise(variables[6] > variables[18], variables[2], NAN) || variables[179] || piecewise(variables[6] > variables[18], variables[2], NAN) || (variables[1]^variables[2]) || (variables[1] && variables[2]); + variables[201] = (variables[1] && variables[2])^(variables[1] || variables[2])^piecewise(variables[6] > variables[18], variables[2], NAN)^variables[179]^piecewise(variables[6] > variables[18], variables[2], NAN)^(variables[1] || variables[2])^(variables[1] && variables[2]); + variables[202] = (variables[1] && variables[2])^^(piecewise(variables[6] > variables[18], variables[2], NAN)^^(variables[179]^^piecewise(variables[6] > variables[18], variables[2], NAN)^^(variables[1] && variables[2]))); + variables[203] = (variables[1] && variables[2])^^(1.0/(piecewise(variables[6] > variables[18], variables[2], NAN)^^(1.0/variables[179])))^^(1.0/piecewise(variables[6] > variables[18], variables[2], NAN))^^(1.0/(variables[1] && variables[2])); + variables[204] = -(variables[1] && variables[2])+-piecewise(variables[6] > variables[18], variables[2], NAN); +} + +void computeRates(double voi, double *states, double *rates, double *variables) +{ + rates[0] = 1.0; +} diff --git a/tests/resources/generator/coverage/model.py b/tests/resources/coverage/generator/model.py similarity index 57% rename from tests/resources/generator/coverage/model.py rename to tests/resources/coverage/generator/model.py index 28d089f6c..9e75327d1 100644 --- a/tests/resources/generator/coverage/model.py +++ b/tests/resources/coverage/generator/model.py @@ -1,14 +1,14 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 -VARIABLE_COUNT = 186 +VARIABLE_COUNT = 209 class VariableType(Enum): @@ -26,24 +26,25 @@ class VariableType(Enum): ] VARIABLE_INFO = [ + {"name": "eqnEq", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "m", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, {"name": "n", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, - {"name": "o", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, - {"name": "p", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, - {"name": "q", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, - {"name": "r", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, - {"name": "s", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, - {"name": "eqnEq", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnEqCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnNeq", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnNeqCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "o", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, {"name": "eqnLt", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnLtCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnLeq", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnLeqCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnGt", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnGtCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnGeq", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnGeqCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAnd", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAndMultiple", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAndParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "p", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, {"name": "eqnAndParenthesesLeftPlusWith", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAndParenthesesLeftPlusWithout", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAndParenthesesLeftMinusWith", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, @@ -56,6 +57,7 @@ class VariableType(Enum): {"name": "eqnAndParenthesesRightMinusWithout", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAndParenthesesRightPower", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnAndParenthesesRightRoot", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnAndCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnOr", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnOrMultiple", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnOrParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, @@ -71,6 +73,7 @@ class VariableType(Enum): {"name": "eqnOrParenthesesRightMinusWithout", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnOrParenthesesRightPower", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnOrParenthesesRightRoot", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnOrCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnXor", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnXorMultiple", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnXorParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, @@ -86,6 +89,7 @@ class VariableType(Enum): {"name": "eqnXorParenthesesRightMinusWithout", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnXorParenthesesRightPower", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnXorParenthesesRightRoot", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnXorCoverageParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnNot", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnPlus", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnPlusMultiple", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, @@ -95,6 +99,8 @@ class VariableType(Enum): {"name": "eqnMinusParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnMinusParenthesesPlusWith", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnMinusParenthesesPlusWithout", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnMinusParenthesesDirectUnaryMinus", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnMinusParenthesesIndirectUnaryMinus", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnMinusUnary", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnMinusUnaryParentheses", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnTimes", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, @@ -199,7 +205,10 @@ class VariableType(Enum): {"name": "eqnPiecewisePiece", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnPiecewisePieceOtherwise", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnPiecewisePiecePiecePiece", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "q", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, + {"name": "r", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, {"name": "eqnPiecewisePiecePiecePieceOtherwise", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "s", "units": "dimensionless", "component": "my_component", "type": VariableType.CONSTANT}, {"name": "eqnWithPiecewise", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnCnInteger", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnCnDouble", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, @@ -211,7 +220,21 @@ class VariableType(Enum): {"name": "eqnExponentiale", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnPi", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, {"name": "eqnInfinity", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "eqnNotanumber", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT} + {"name": "eqnNotanumber", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForPlusOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForMinusOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForTimesOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForDivideOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForAndOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForOrOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForXorOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForPowerOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForRootOperator", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnCoverageForMinusUnary", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnNlaVariable1", "units": "dimensionless", "component": "my_component", "type": VariableType.ALGEBRAIC}, + {"name": "eqnNlaVariable2", "units": "dimensionless", "component": "my_component", "type": VariableType.ALGEBRAIC}, + {"name": "eqnComputedConstant1", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "eqnComputedConstant2", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT} ] @@ -325,197 +348,248 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): - variables[0] = 1.0 - variables[1] = 2.0 - variables[2] = 3.0 - variables[3] = 4.0 - variables[4] = 5.0 - variables[5] = 6.0 - variables[6] = 7.0 - variables[175] = 123.0 - variables[176] = 123.456789 - variables[177] = 123.0e99 - variables[178] = 123.456789e99 - variables[180] = 1.0 - variables[181] = 0.0 - variables[182] = 2.71828182845905 - variables[183] = 3.14159265358979 - variables[184] = inf - variables[185] = nan +from nlasolver import nla_solve + + +def objective_function_0(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[205] = u[0] + variables[206] = u[1] + + f[0] = variables[205]+variables[206]+states[0]-0.0 + f[1] = variables[205]-variables[206]-(variables[207]+variables[208]) + + +def find_root_0(voi, states, rates, variables): + u = [nan]*2 + + u[0] = variables[205] + u[1] = variables[206] + + u = nla_solve(objective_function_0, u, 2, [voi, states, rates, variables]) + + variables[205] = u[0] + variables[206] = u[1] + + +def initialise_variables(states, rates, variables): + variables[1] = 1.0 + variables[2] = 2.0 + variables[6] = 3.0 + variables[18] = 4.0 + variables[179] = 5.0 + variables[180] = 6.0 + variables[182] = 7.0 + variables[205] = 1.0 + variables[206] = 2.0 + variables[184] = 123.0 + variables[185] = 123.456789 + variables[186] = 123.0e99 + variables[187] = 123.456789e99 + variables[189] = 1.0 + variables[190] = 0.0 + variables[191] = 2.71828182845905 + variables[192] = 3.14159265358979 + variables[193] = inf + variables[194] = nan + variables[207] = 1.0 + variables[208] = 3.0 states[0] = 0.0 def compute_computed_constants(variables): - variables[7] = eq_func(variables[0], variables[1]) - variables[8] = variables[0]/eq_func(variables[1], variables[1]) - variables[9] = neq_func(variables[0], variables[1]) - variables[10] = variables[0]/neq_func(variables[1], variables[2]) - variables[11] = lt_func(variables[0], variables[1]) - variables[12] = leq_func(variables[0], variables[1]) - variables[13] = gt_func(variables[0], variables[1]) - variables[14] = geq_func(variables[0], variables[1]) - variables[15] = and_func(variables[0], variables[1]) - variables[16] = and_func(variables[0], and_func(variables[1], variables[2])) - variables[17] = and_func(lt_func(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[18] = and_func(variables[0]+variables[1], gt_func(variables[2], variables[3])) - variables[19] = and_func(variables[0], gt_func(variables[1], variables[2])) - variables[20] = and_func(variables[0]-variables[1], gt_func(variables[2], variables[3])) - variables[21] = and_func(-variables[0], gt_func(variables[1], variables[2])) - variables[22] = and_func(pow(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[23] = and_func(pow(variables[0], 1.0/variables[1]), gt_func(variables[2], variables[3])) - variables[24] = and_func(lt_func(variables[0], variables[1]), variables[2]+variables[3]) - variables[25] = and_func(lt_func(variables[0], variables[1]), variables[2]) - variables[26] = and_func(lt_func(variables[0], variables[1]), variables[2]-variables[3]) - variables[27] = and_func(lt_func(variables[0], variables[1]), -variables[2]) - variables[28] = and_func(lt_func(variables[0], variables[1]), pow(variables[2], variables[3])) - variables[29] = and_func(lt_func(variables[0], variables[1]), pow(variables[2], 1.0/variables[3])) - variables[30] = or_func(variables[0], variables[1]) - variables[31] = or_func(variables[0], or_func(variables[1], variables[2])) - variables[32] = or_func(lt_func(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[33] = or_func(variables[0]+variables[1], gt_func(variables[2], variables[3])) - variables[34] = or_func(variables[0], gt_func(variables[1], variables[2])) - variables[35] = or_func(variables[0]-variables[1], gt_func(variables[2], variables[3])) - variables[36] = or_func(-variables[0], gt_func(variables[1], variables[2])) - variables[37] = or_func(pow(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[38] = or_func(pow(variables[0], 1.0/variables[1]), gt_func(variables[2], variables[3])) - variables[39] = or_func(lt_func(variables[0], variables[1]), variables[2]+variables[3]) - variables[40] = or_func(lt_func(variables[0], variables[1]), variables[2]) - variables[41] = or_func(lt_func(variables[0], variables[1]), variables[2]-variables[3]) - variables[42] = or_func(lt_func(variables[0], variables[1]), -variables[2]) - variables[43] = or_func(lt_func(variables[0], variables[1]), pow(variables[2], variables[3])) - variables[44] = or_func(lt_func(variables[0], variables[1]), pow(variables[2], 1.0/variables[3])) - variables[45] = xor_func(variables[0], variables[1]) - variables[46] = xor_func(variables[0], xor_func(variables[1], variables[2])) - variables[47] = xor_func(lt_func(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[48] = xor_func(variables[0]+variables[1], gt_func(variables[2], variables[3])) - variables[49] = xor_func(variables[0], gt_func(variables[1], variables[2])) - variables[50] = xor_func(variables[0]-variables[1], gt_func(variables[2], variables[3])) - variables[51] = xor_func(-variables[0], gt_func(variables[1], variables[2])) - variables[52] = xor_func(pow(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[53] = xor_func(pow(variables[0], 1.0/variables[1]), gt_func(variables[2], variables[3])) - variables[54] = xor_func(lt_func(variables[0], variables[1]), variables[2]+variables[3]) - variables[55] = xor_func(lt_func(variables[0], variables[1]), variables[2]) - variables[56] = xor_func(lt_func(variables[0], variables[1]), variables[2]-variables[3]) - variables[57] = xor_func(lt_func(variables[0], variables[1]), -variables[2]) - variables[58] = xor_func(lt_func(variables[0], variables[1]), pow(variables[2], variables[3])) - variables[59] = xor_func(lt_func(variables[0], variables[1]), pow(variables[2], 1.0/variables[3])) - variables[60] = not_func(variables[0]) - variables[61] = variables[0]+variables[1] - variables[62] = variables[0]+variables[1]+variables[2] - variables[63] = lt_func(variables[0], variables[1])+gt_func(variables[2], variables[3]) - variables[64] = variables[0] - variables[65] = variables[0]-variables[1] - variables[66] = lt_func(variables[0], variables[1])-gt_func(variables[2], variables[3]) - variables[67] = lt_func(variables[0], variables[1])-(variables[2]+variables[3]) - variables[68] = lt_func(variables[0], variables[1])-variables[2] - variables[69] = -variables[0] - variables[70] = -lt_func(variables[0], variables[1]) - variables[71] = variables[0]*variables[1] - variables[72] = variables[0]*variables[1]*variables[2] - variables[73] = lt_func(variables[0], variables[1])*gt_func(variables[2], variables[3]) - variables[74] = (variables[0]+variables[1])*gt_func(variables[2], variables[3]) - variables[75] = variables[0]*gt_func(variables[1], variables[2]) - variables[76] = (variables[0]-variables[1])*gt_func(variables[2], variables[3]) - variables[77] = -variables[0]*gt_func(variables[1], variables[2]) - variables[78] = lt_func(variables[0], variables[1])*(variables[2]+variables[3]) - variables[79] = lt_func(variables[0], variables[1])*variables[2] - variables[80] = lt_func(variables[0], variables[1])*(variables[2]-variables[3]) - variables[81] = lt_func(variables[0], variables[1])*-variables[2] - variables[82] = variables[0]/variables[1] - variables[83] = lt_func(variables[0], variables[1])/gt_func(variables[3], variables[2]) - variables[84] = (variables[0]+variables[1])/gt_func(variables[3], variables[2]) - variables[85] = variables[0]/gt_func(variables[2], variables[1]) - variables[86] = (variables[0]-variables[1])/gt_func(variables[3], variables[2]) - variables[87] = -variables[0]/gt_func(variables[2], variables[1]) - variables[88] = lt_func(variables[0], variables[1])/(variables[2]+variables[3]) - variables[89] = lt_func(variables[0], variables[1])/variables[2] - variables[90] = lt_func(variables[0], variables[1])/(variables[2]-variables[3]) - variables[91] = lt_func(variables[0], variables[1])/-variables[2] - variables[92] = lt_func(variables[0], variables[1])/(variables[2]*variables[3]) - variables[93] = lt_func(variables[0], variables[1])/(variables[2]/variables[3]) - variables[94] = sqrt(variables[0]) - variables[95] = pow(variables[0], 2.0) - variables[96] = pow(variables[0], 3.0) - variables[97] = pow(variables[0], variables[1]) - variables[98] = pow(lt_func(variables[0], variables[1]), gt_func(variables[2], variables[3])) - variables[99] = pow(variables[0]+variables[1], gt_func(variables[2], variables[3])) - variables[100] = pow(variables[0], gt_func(variables[1], variables[2])) - variables[101] = pow(variables[0]-variables[1], gt_func(variables[2], variables[3])) - variables[102] = pow(-variables[0], gt_func(variables[1], variables[2])) - variables[103] = pow(variables[0]*variables[1], gt_func(variables[2], variables[3])) - variables[104] = pow(variables[0]/variables[1], gt_func(variables[2], variables[3])) - variables[105] = pow(lt_func(variables[0], variables[1]), variables[2]+variables[3]) - variables[106] = pow(lt_func(variables[0], variables[1]), variables[2]) - variables[107] = pow(lt_func(variables[0], variables[1]), variables[2]-variables[3]) - variables[108] = pow(lt_func(variables[0], variables[1]), -variables[2]) - variables[109] = pow(lt_func(variables[0], variables[1]), variables[2]*variables[3]) - variables[110] = pow(lt_func(variables[0], variables[1]), variables[2]/variables[3]) - variables[111] = pow(lt_func(variables[0], variables[1]), pow(variables[2], variables[3])) - variables[112] = pow(lt_func(variables[0], variables[1]), pow(variables[2], 1.0/variables[3])) - variables[113] = sqrt(variables[0]) - variables[114] = sqrt(variables[0]) - variables[115] = pow(variables[0], 1.0/3.0) - variables[116] = pow(variables[0], 1.0/variables[1]) - variables[117] = pow(lt_func(variables[0], variables[1]), 1.0/gt_func(variables[3], variables[2])) - variables[118] = pow(variables[0]+variables[1], 1.0/gt_func(variables[3], variables[2])) - variables[119] = pow(variables[0], 1.0/gt_func(variables[2], variables[1])) - variables[120] = pow(variables[0]-variables[1], 1.0/gt_func(variables[3], variables[2])) - variables[121] = pow(-variables[0], 1.0/gt_func(variables[2], variables[1])) - variables[122] = pow(variables[0]*variables[1], 1.0/gt_func(variables[3], variables[2])) - variables[123] = pow(variables[0]/variables[1], 1.0/gt_func(variables[3], variables[2])) - variables[124] = pow(lt_func(variables[0], variables[1]), 1.0/(variables[2]+variables[3])) - variables[125] = pow(lt_func(variables[0], variables[1]), 1.0/variables[2]) - variables[126] = pow(lt_func(variables[0], variables[1]), 1.0/(variables[2]-variables[3])) - variables[127] = pow(lt_func(variables[0], variables[1]), 1.0/-variables[2]) - variables[128] = pow(lt_func(variables[0], variables[1]), 1.0/(variables[2]*variables[3])) - variables[129] = pow(lt_func(variables[0], variables[1]), 1.0/(variables[2]/variables[3])) - variables[130] = pow(lt_func(variables[0], variables[1]), 1.0/pow(variables[2], variables[3])) - variables[131] = pow(lt_func(variables[0], variables[1]), 1.0/pow(variables[2], 1.0/variables[3])) - variables[132] = fabs(variables[0]) - variables[133] = exp(variables[0]) - variables[134] = log(variables[0]) - variables[135] = log10(variables[0]) - variables[136] = log(variables[0])/log(2.0) - variables[137] = log10(variables[0]) - variables[138] = log(variables[0])/log(variables[1]) - variables[139] = ceil(variables[0]) - variables[140] = floor(variables[0]) - variables[141] = min(variables[0], variables[1]) - variables[142] = min(variables[0], min(variables[1], variables[2])) - variables[143] = max(variables[0], variables[1]) - variables[144] = max(variables[0], max(variables[1], variables[2])) - variables[145] = fmod(variables[0], variables[1]) - variables[146] = sin(variables[0]) - variables[147] = cos(variables[0]) - variables[148] = tan(variables[0]) - variables[149] = sec(variables[0]) - variables[150] = csc(variables[0]) - variables[151] = cot(variables[0]) - variables[152] = sinh(variables[0]) - variables[153] = cosh(variables[0]) - variables[154] = tanh(variables[0]) - variables[155] = sech(variables[0]) - variables[156] = csch(variables[0]) - variables[157] = coth(variables[0]) - variables[158] = asin(variables[0]) - variables[159] = acos(variables[0]) - variables[160] = atan(variables[0]) - variables[161] = asec(variables[0]) - variables[162] = acsc(variables[0]) - variables[163] = acot(variables[0]) - variables[164] = asinh(variables[0]) - variables[165] = acosh(variables[0]) - variables[166] = atanh(variables[0]/2.0) - variables[167] = asech(variables[0]) - variables[168] = acsch(variables[0]) - variables[169] = acoth(2.0*variables[0]) - variables[170] = variables[0] if gt_func(variables[0], variables[1]) else nan - variables[171] = variables[0] if gt_func(variables[0], variables[1]) else variables[2] - variables[172] = variables[0] if gt_func(variables[0], variables[1]) else variables[2] if gt_func(variables[2], variables[3]) else variables[4] if gt_func(variables[4], variables[5]) else nan - variables[173] = variables[0] if gt_func(variables[0], variables[1]) else variables[2] if gt_func(variables[2], variables[3]) else variables[4] if gt_func(variables[4], variables[5]) else variables[6] - variables[174] = 123.0+(variables[0] if gt_func(variables[0], variables[1]) else nan) - variables[179] = variables[0] + variables[0] = eq_func(variables[1], variables[2]) + variables[3] = variables[1]/eq_func(variables[2], variables[2]) + variables[4] = neq_func(variables[1], variables[2]) + variables[5] = variables[1]/neq_func(variables[2], variables[6]) + variables[7] = lt_func(variables[1], variables[2]) + variables[8] = variables[1]/lt_func(variables[2], variables[6]) + variables[9] = leq_func(variables[1], variables[2]) + variables[10] = variables[1]/leq_func(variables[2], variables[6]) + variables[11] = gt_func(variables[1], variables[2]) + variables[12] = variables[1]/gt_func(variables[2], variables[6]) + variables[13] = geq_func(variables[1], variables[2]) + variables[14] = variables[1]/geq_func(variables[2], variables[6]) + variables[15] = and_func(variables[1], variables[2]) + variables[16] = and_func(variables[1], and_func(variables[2], variables[6])) + variables[17] = and_func(lt_func(variables[1], variables[2]), gt_func(variables[6], variables[18])) + variables[19] = and_func(variables[1]+variables[2], gt_func(variables[6], variables[18])) + variables[20] = and_func(variables[1], gt_func(variables[2], variables[6])) + variables[21] = and_func(variables[1]-variables[2], gt_func(variables[6], variables[18])) + variables[22] = and_func(-variables[1], gt_func(variables[2], variables[6])) + variables[23] = and_func(pow(variables[1], variables[2]), gt_func(variables[6], variables[18])) + variables[24] = and_func(pow(variables[1], 1.0/variables[2]), gt_func(variables[6], variables[18])) + variables[25] = and_func(lt_func(variables[1], variables[2]), variables[6]+variables[18]) + variables[26] = and_func(lt_func(variables[1], variables[2]), variables[6]) + variables[27] = and_func(lt_func(variables[1], variables[2]), variables[6]-variables[18]) + variables[28] = and_func(lt_func(variables[1], variables[2]), -variables[6]) + variables[29] = and_func(lt_func(variables[1], variables[2]), pow(variables[6], variables[18])) + variables[30] = and_func(lt_func(variables[1], variables[2]), pow(variables[6], 1.0/variables[18])) + variables[31] = variables[1]/and_func(variables[2], variables[6]) + variables[32] = or_func(variables[1], variables[2]) + variables[33] = or_func(variables[1], or_func(variables[2], variables[6])) + variables[34] = or_func(lt_func(variables[1], variables[2]), gt_func(variables[6], variables[18])) + variables[35] = or_func(variables[1]+variables[2], gt_func(variables[6], variables[18])) + variables[36] = or_func(variables[1], gt_func(variables[2], variables[6])) + variables[37] = or_func(variables[1]-variables[2], gt_func(variables[6], variables[18])) + variables[38] = or_func(-variables[1], gt_func(variables[2], variables[6])) + variables[39] = or_func(pow(variables[1], variables[2]), gt_func(variables[6], variables[18])) + variables[40] = or_func(pow(variables[1], 1.0/variables[2]), gt_func(variables[6], variables[18])) + variables[41] = or_func(lt_func(variables[1], variables[2]), variables[6]+variables[18]) + variables[42] = or_func(lt_func(variables[1], variables[2]), variables[6]) + variables[43] = or_func(lt_func(variables[1], variables[2]), variables[6]-variables[18]) + variables[44] = or_func(lt_func(variables[1], variables[2]), -variables[6]) + variables[45] = or_func(lt_func(variables[1], variables[2]), pow(variables[6], variables[18])) + variables[46] = or_func(lt_func(variables[1], variables[2]), pow(variables[6], 1.0/variables[18])) + variables[47] = variables[1]/or_func(variables[2], variables[6]) + variables[48] = xor_func(variables[1], variables[2]) + variables[49] = xor_func(variables[1], xor_func(variables[2], variables[6])) + variables[50] = xor_func(lt_func(variables[1], variables[2]), gt_func(variables[6], variables[18])) + variables[51] = xor_func(variables[1]+variables[2], gt_func(variables[6], variables[18])) + variables[52] = xor_func(variables[1], gt_func(variables[2], variables[6])) + variables[53] = xor_func(variables[1]-variables[2], gt_func(variables[6], variables[18])) + variables[54] = xor_func(-variables[1], gt_func(variables[2], variables[6])) + variables[55] = xor_func(pow(variables[1], variables[2]), gt_func(variables[6], variables[18])) + variables[56] = xor_func(pow(variables[1], 1.0/variables[2]), gt_func(variables[6], variables[18])) + variables[57] = xor_func(lt_func(variables[1], variables[2]), variables[6]+variables[18]) + variables[58] = xor_func(lt_func(variables[1], variables[2]), variables[6]) + variables[59] = xor_func(lt_func(variables[1], variables[2]), variables[6]-variables[18]) + variables[60] = xor_func(lt_func(variables[1], variables[2]), -variables[6]) + variables[61] = xor_func(lt_func(variables[1], variables[2]), pow(variables[6], variables[18])) + variables[62] = xor_func(lt_func(variables[1], variables[2]), pow(variables[6], 1.0/variables[18])) + variables[63] = variables[1]/xor_func(variables[2], variables[6]) + variables[64] = not_func(variables[1]) + variables[65] = variables[1]+variables[2] + variables[66] = variables[1]+variables[2]+variables[6] + variables[67] = lt_func(variables[1], variables[2])+gt_func(variables[6], variables[18]) + variables[68] = variables[1] + variables[69] = variables[1]-variables[2] + variables[70] = lt_func(variables[1], variables[2])-gt_func(variables[6], variables[18]) + variables[71] = lt_func(variables[1], variables[2])-(variables[6]+variables[18]) + variables[72] = lt_func(variables[1], variables[2])-variables[6] + variables[73] = variables[1]-(-variables[2]) + variables[74] = variables[1]-(-variables[2]*variables[6]) + variables[75] = -variables[1] + variables[76] = -lt_func(variables[1], variables[2]) + variables[77] = variables[1]*variables[2] + variables[78] = variables[1]*variables[2]*variables[6] + variables[79] = lt_func(variables[1], variables[2])*gt_func(variables[6], variables[18]) + variables[80] = (variables[1]+variables[2])*gt_func(variables[6], variables[18]) + variables[81] = variables[1]*gt_func(variables[2], variables[6]) + variables[82] = (variables[1]-variables[2])*gt_func(variables[6], variables[18]) + variables[83] = -variables[1]*gt_func(variables[2], variables[6]) + variables[84] = lt_func(variables[1], variables[2])*(variables[6]+variables[18]) + variables[85] = lt_func(variables[1], variables[2])*variables[6] + variables[86] = lt_func(variables[1], variables[2])*(variables[6]-variables[18]) + variables[87] = lt_func(variables[1], variables[2])*-variables[6] + variables[88] = variables[1]/variables[2] + variables[89] = lt_func(variables[1], variables[2])/gt_func(variables[18], variables[6]) + variables[90] = (variables[1]+variables[2])/gt_func(variables[18], variables[6]) + variables[91] = variables[1]/gt_func(variables[6], variables[2]) + variables[92] = (variables[1]-variables[2])/gt_func(variables[18], variables[6]) + variables[93] = -variables[1]/gt_func(variables[6], variables[2]) + variables[94] = lt_func(variables[1], variables[2])/(variables[6]+variables[18]) + variables[95] = lt_func(variables[1], variables[2])/variables[6] + variables[96] = lt_func(variables[1], variables[2])/(variables[6]-variables[18]) + variables[97] = lt_func(variables[1], variables[2])/-variables[6] + variables[98] = lt_func(variables[1], variables[2])/(variables[6]*variables[18]) + variables[99] = lt_func(variables[1], variables[2])/(variables[6]/variables[18]) + variables[100] = sqrt(variables[1]) + variables[101] = pow(variables[1], 2.0) + variables[102] = pow(variables[1], 3.0) + variables[103] = pow(variables[1], variables[2]) + variables[104] = pow(leq_func(variables[1], variables[2]), geq_func(variables[6], variables[18])) + variables[105] = pow(variables[1]+variables[2], geq_func(variables[6], variables[18])) + variables[106] = pow(variables[1], geq_func(variables[2], variables[6])) + variables[107] = pow(variables[1]-variables[2], geq_func(variables[6], variables[18])) + variables[108] = pow(-variables[1], geq_func(variables[2], variables[6])) + variables[109] = pow(variables[1]*variables[2], geq_func(variables[6], variables[18])) + variables[110] = pow(variables[1]/variables[2], geq_func(variables[6], variables[18])) + variables[111] = pow(leq_func(variables[1], variables[2]), variables[6]+variables[18]) + variables[112] = pow(leq_func(variables[1], variables[2]), variables[6]) + variables[113] = pow(leq_func(variables[1], variables[2]), variables[6]-variables[18]) + variables[114] = pow(leq_func(variables[1], variables[2]), -variables[6]) + variables[115] = pow(leq_func(variables[1], variables[2]), variables[6]*variables[18]) + variables[116] = pow(leq_func(variables[1], variables[2]), variables[6]/variables[18]) + variables[117] = pow(leq_func(variables[1], variables[2]), pow(variables[6], variables[18])) + variables[118] = pow(leq_func(variables[1], variables[2]), pow(variables[6], 1.0/variables[18])) + variables[119] = sqrt(variables[1]) + variables[120] = sqrt(variables[1]) + variables[121] = pow(variables[1], 1.0/3.0) + variables[122] = pow(variables[1], 1.0/variables[2]) + variables[123] = pow(lt_func(variables[1], variables[2]), 1.0/gt_func(variables[18], variables[6])) + variables[124] = pow(variables[1]+variables[2], 1.0/gt_func(variables[18], variables[6])) + variables[125] = pow(variables[1], 1.0/gt_func(variables[6], variables[2])) + variables[126] = pow(variables[1]-variables[2], 1.0/gt_func(variables[18], variables[6])) + variables[127] = pow(-variables[1], 1.0/gt_func(variables[6], variables[2])) + variables[128] = pow(variables[1]*variables[2], 1.0/gt_func(variables[18], variables[6])) + variables[129] = pow(variables[1]/variables[2], 1.0/gt_func(variables[18], variables[6])) + variables[130] = pow(lt_func(variables[1], variables[2]), 1.0/(variables[6]+variables[18])) + variables[131] = pow(lt_func(variables[1], variables[2]), 1.0/variables[6]) + variables[132] = pow(lt_func(variables[1], variables[2]), 1.0/(variables[6]-variables[18])) + variables[133] = pow(lt_func(variables[1], variables[2]), 1.0/-variables[6]) + variables[134] = pow(lt_func(variables[1], variables[2]), 1.0/(variables[6]*variables[18])) + variables[135] = pow(lt_func(variables[1], variables[2]), 1.0/(variables[6]/variables[18])) + variables[136] = pow(lt_func(variables[1], variables[2]), 1.0/pow(variables[6], variables[18])) + variables[137] = pow(lt_func(variables[1], variables[2]), 1.0/pow(variables[6], 1.0/variables[18])) + variables[138] = fabs(variables[1]) + variables[139] = exp(variables[1]) + variables[140] = log(variables[1]) + variables[141] = log10(variables[1]) + variables[142] = log(variables[1])/log(2.0) + variables[143] = log10(variables[1]) + variables[144] = log(variables[1])/log(variables[2]) + variables[145] = ceil(variables[1]) + variables[146] = floor(variables[1]) + variables[147] = min(variables[1], variables[2]) + variables[148] = min(variables[1], min(variables[2], variables[6])) + variables[149] = max(variables[1], variables[2]) + variables[150] = max(variables[1], max(variables[2], variables[6])) + variables[151] = fmod(variables[1], variables[2]) + variables[152] = sin(variables[1]) + variables[153] = cos(variables[1]) + variables[154] = tan(variables[1]) + variables[155] = sec(variables[1]) + variables[156] = csc(variables[1]) + variables[157] = cot(variables[1]) + variables[158] = sinh(variables[1]) + variables[159] = cosh(variables[1]) + variables[160] = tanh(variables[1]) + variables[161] = sech(variables[1]) + variables[162] = csch(variables[1]) + variables[163] = coth(variables[1]) + variables[164] = asin(variables[1]) + variables[165] = acos(variables[1]) + variables[166] = atan(variables[1]) + variables[167] = asec(variables[1]) + variables[168] = acsc(variables[1]) + variables[169] = acot(variables[1]) + variables[170] = asinh(variables[1]) + variables[171] = acosh(variables[1]) + variables[172] = atanh(variables[1]/2.0) + variables[173] = asech(variables[1]) + variables[174] = acsch(variables[1]) + variables[175] = acoth(2.0*variables[1]) + variables[176] = variables[1] if gt_func(variables[1], variables[2]) else nan + variables[177] = variables[1] if gt_func(variables[1], variables[2]) else variables[6] + variables[178] = variables[1] if gt_func(variables[1], variables[2]) else variables[6] if gt_func(variables[6], variables[18]) else variables[179] if gt_func(variables[179], variables[180]) else nan + variables[181] = variables[1] if gt_func(variables[1], variables[2]) else variables[6] if gt_func(variables[6], variables[18]) else variables[179] if gt_func(variables[179], variables[180]) else variables[182] + variables[183] = 123.0+(variables[1] if gt_func(variables[1], variables[2]) else nan) + variables[188] = variables[1] + variables[195] = and_func(variables[1], variables[2])+(variables[2] if gt_func(variables[6], variables[18]) else nan)+variables[179]+and_func(variables[180], variables[182]) + variables[196] = and_func(variables[1], variables[2])-((variables[2] if gt_func(variables[6], variables[18]) else nan)-(variables[179]-(variables[2] if gt_func(variables[6], variables[18]) else nan)))-and_func(variables[180], variables[182]) + variables[197] = and_func(variables[1], variables[2])*(variables[2] if gt_func(variables[6], variables[18]) else nan)*variables[179]*(variables[2] if gt_func(variables[6], variables[18]) else nan)*and_func(variables[180], variables[182]) + variables[198] = and_func(variables[1], variables[2])/((variables[2] if gt_func(variables[6], variables[18]) else nan)/(variables[179]/(variables[2] if gt_func(variables[6], variables[18]) else nan))) + variables[199] = and_func(or_func(variables[1], variables[2]), and_func(xor_func(variables[1], variables[2]), and_func(variables[2] if gt_func(variables[6], variables[18]) else nan, and_func(and_func(and_func(variables[179], variables[2] if gt_func(variables[6], variables[18]) else nan), xor_func(variables[1], variables[2])), or_func(variables[1], variables[2]))))) + variables[200] = or_func(and_func(variables[1], variables[2]), or_func(xor_func(variables[1], variables[2]), or_func(variables[2] if gt_func(variables[6], variables[18]) else nan, or_func(or_func(or_func(variables[179], variables[2] if gt_func(variables[6], variables[18]) else nan), xor_func(variables[1], variables[2])), and_func(variables[1], variables[2]))))) + variables[201] = xor_func(and_func(variables[1], variables[2]), xor_func(or_func(variables[1], variables[2]), xor_func(variables[2] if gt_func(variables[6], variables[18]) else nan, xor_func(xor_func(xor_func(variables[179], variables[2] if gt_func(variables[6], variables[18]) else nan), or_func(variables[1], variables[2])), and_func(variables[1], variables[2]))))) + variables[202] = pow(and_func(variables[1], variables[2]), pow(variables[2] if gt_func(variables[6], variables[18]) else nan, pow(pow(variables[179], variables[2] if gt_func(variables[6], variables[18]) else nan), and_func(variables[1], variables[2])))) + variables[203] = pow(pow(pow(and_func(variables[1], variables[2]), 1.0/pow(variables[2] if gt_func(variables[6], variables[18]) else nan, 1.0/variables[179])), 1.0/(variables[2] if gt_func(variables[6], variables[18]) else nan)), 1.0/and_func(variables[1], variables[2])) + variables[204] = -and_func(variables[1], variables[2])+-(variables[2] if gt_func(variables[6], variables[18]) else nan) def compute_rates(voi, states, rates, variables): @@ -523,4 +597,4 @@ def compute_rates(voi, states, rates, variables): def compute_variables(voi, states, rates, variables): - pass + find_root_0(voi, states, rates, variables) diff --git a/tests/resources/coverage/invalidxmlids.cellml b/tests/resources/coverage/invalidxmlids.cellml new file mode 100644 index 000000000..58e722f95 --- /dev/null +++ b/tests/resources/coverage/invalidxmlids.cellml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.c b/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.c index 3691152f0..2c89ae526 100644 --- a/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.c +++ b/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.c @@ -1,23 +1,29 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t VARIABLE_COUNT = 2; const VariableInfo VARIABLE_INFO[] = { - {"a", "dimensionless", "my_algebraic_eqn", COMPUTED_CONSTANT}, - {"x", "dimensionless", "my_algebraic_eqn", COMPUTED_CONSTANT} + {"x", "dimensionless", "my_algebraic_eqn", COMPUTED_CONSTANT}, + {"a", "dimensionless", "my_algebraic_eqn", COMPUTED_CONSTANT} }; double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -27,12 +33,12 @@ void deleteArray(double *array) void initialiseVariables(double *variables) { - variables[0] = 1.0; + variables[1] = 1.0; } void computeComputedConstants(double *variables) { - variables[1] = variables[0]; + variables[0] = variables[1]; } void computeVariables(double *variables) diff --git a/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.external.c b/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.external.c index e65c3f80b..3602a7e71 100644 --- a/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.external.c +++ b/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.external.c @@ -1,23 +1,29 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.external.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t VARIABLE_COUNT = 2; const VariableInfo VARIABLE_INFO[] = { - {"a", "dimensionless", "my_algebraic_eqn", EXTERNAL}, - {"x", "dimensionless", "my_algebraic_eqn", ALGEBRAIC} + {"x", "dimensionless", "my_algebraic_eqn", ALGEBRAIC}, + {"a", "dimensionless", "my_algebraic_eqn", EXTERNAL} }; double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -27,7 +33,7 @@ void deleteArray(double *array) void initialiseVariables(double *variables, ExternalVariable externalVariable) { - variables[0] = externalVariable(variables, 0); + variables[1] = externalVariable(variables, 1); } void computeComputedConstants(double *variables) @@ -36,6 +42,6 @@ void computeComputedConstants(double *variables) void computeVariables(double *variables, ExternalVariable externalVariable) { - variables[0] = externalVariable(variables, 0); - variables[1] = variables[0]; + variables[1] = externalVariable(variables, 1); + variables[0] = variables[1]; } diff --git a/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.external.h b/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.external.h index 884e07e51..9c1fc0d54 100644 --- a/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.external.h +++ b/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.external.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once diff --git a/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.external.py b/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.external.py index 9279d73c0..e162bd368 100644 --- a/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.external.py +++ b/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.external.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" VARIABLE_COUNT = 2 @@ -18,8 +18,8 @@ class VariableType(Enum): VARIABLE_INFO = [ - {"name": "a", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.EXTERNAL}, - {"name": "x", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.ALGEBRAIC} + {"name": "x", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.ALGEBRAIC}, + {"name": "a", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.EXTERNAL} ] @@ -28,7 +28,7 @@ def create_variables_array(): def initialise_variables(variables, external_variable): - variables[0] = external_variable(variables, 0) + variables[1] = external_variable(variables, 1) def compute_computed_constants(variables): @@ -36,5 +36,5 @@ def compute_computed_constants(variables): def compute_variables(variables, external_variable): - variables[0] = external_variable(variables, 0) - variables[1] = variables[0] + variables[1] = external_variable(variables, 1) + variables[0] = variables[1] diff --git a/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.h b/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.h index 67707f103..599f17050 100644 --- a/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.h +++ b/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once diff --git a/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.py b/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.py index 34fe05592..ace02c542 100644 --- a/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.py +++ b/tests/resources/generator/algebraic_eqn_computed_var_on_rhs/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" VARIABLE_COUNT = 2 @@ -17,8 +17,8 @@ class VariableType(Enum): VARIABLE_INFO = [ - {"name": "a", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "x", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.COMPUTED_CONSTANT} + {"name": "x", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "a", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.COMPUTED_CONSTANT} ] @@ -27,11 +27,11 @@ def create_variables_array(): def initialise_variables(variables): - variables[0] = 1.0 + variables[1] = 1.0 def compute_computed_constants(variables): - variables[1] = variables[0] + variables[0] = variables[1] def compute_variables(variables): diff --git a/tests/resources/generator/algebraic_eqn_const_var_on_rhs/model.c b/tests/resources/generator/algebraic_eqn_const_var_on_rhs/model.c index 2aafd2cb1..93906ea7c 100644 --- a/tests/resources/generator/algebraic_eqn_const_var_on_rhs/model.c +++ b/tests/resources/generator/algebraic_eqn_const_var_on_rhs/model.c @@ -1,23 +1,29 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t VARIABLE_COUNT = 2; const VariableInfo VARIABLE_INFO[] = { - {"a", "dimensionless", "my_algebraic_eqn", CONSTANT}, - {"x", "dimensionless", "my_algebraic_eqn", COMPUTED_CONSTANT} + {"x", "dimensionless", "my_algebraic_eqn", COMPUTED_CONSTANT}, + {"a", "dimensionless", "my_algebraic_eqn", CONSTANT} }; double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -27,12 +33,12 @@ void deleteArray(double *array) void initialiseVariables(double *variables) { - variables[0] = 1.0; + variables[1] = 1.0; } void computeComputedConstants(double *variables) { - variables[1] = variables[0]; + variables[0] = variables[1]; } void computeVariables(double *variables) diff --git a/tests/resources/generator/algebraic_eqn_const_var_on_rhs/model.h b/tests/resources/generator/algebraic_eqn_const_var_on_rhs/model.h index 67707f103..599f17050 100644 --- a/tests/resources/generator/algebraic_eqn_const_var_on_rhs/model.h +++ b/tests/resources/generator/algebraic_eqn_const_var_on_rhs/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once diff --git a/tests/resources/generator/algebraic_eqn_const_var_on_rhs/model.py b/tests/resources/generator/algebraic_eqn_const_var_on_rhs/model.py index b2f6402e4..93b0b8698 100644 --- a/tests/resources/generator/algebraic_eqn_const_var_on_rhs/model.py +++ b/tests/resources/generator/algebraic_eqn_const_var_on_rhs/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" VARIABLE_COUNT = 2 @@ -17,8 +17,8 @@ class VariableType(Enum): VARIABLE_INFO = [ - {"name": "a", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.CONSTANT}, - {"name": "x", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.COMPUTED_CONSTANT} + {"name": "x", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "a", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.CONSTANT} ] @@ -27,11 +27,11 @@ def create_variables_array(): def initialise_variables(variables): - variables[0] = 1.0 + variables[1] = 1.0 def compute_computed_constants(variables): - variables[1] = variables[0] + variables[0] = variables[1] def compute_variables(variables): diff --git a/tests/resources/generator/algebraic_eqn_constant_on_rhs/model.c b/tests/resources/generator/algebraic_eqn_constant_on_rhs/model.c index d8681081a..0a3a37f7c 100644 --- a/tests/resources/generator/algebraic_eqn_constant_on_rhs/model.c +++ b/tests/resources/generator/algebraic_eqn_constant_on_rhs/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t VARIABLE_COUNT = 1; @@ -16,7 +16,13 @@ const VariableInfo VARIABLE_INFO[] = { double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) diff --git a/tests/resources/generator/algebraic_eqn_constant_on_rhs/model.h b/tests/resources/generator/algebraic_eqn_constant_on_rhs/model.h index d195fd29c..32566495b 100644 --- a/tests/resources/generator/algebraic_eqn_constant_on_rhs/model.h +++ b/tests/resources/generator/algebraic_eqn_constant_on_rhs/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once diff --git a/tests/resources/generator/algebraic_eqn_constant_on_rhs/model.py b/tests/resources/generator/algebraic_eqn_constant_on_rhs/model.py index a4661e850..76067ecc6 100644 --- a/tests/resources/generator/algebraic_eqn_constant_on_rhs/model.py +++ b/tests/resources/generator/algebraic_eqn_constant_on_rhs/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" VARIABLE_COUNT = 1 diff --git a/tests/resources/generator/algebraic_eqn_derivative_on_rhs/model.c b/tests/resources/generator/algebraic_eqn_derivative_on_rhs/model.c index cf9456323..2161d6754 100644 --- a/tests/resources/generator/algebraic_eqn_derivative_on_rhs/model.c +++ b/tests/resources/generator/algebraic_eqn_derivative_on_rhs/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 2; @@ -24,12 +24,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -37,7 +49,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { variables[0] = 1.0; states[0] = 1.0; diff --git a/tests/resources/generator/algebraic_eqn_derivative_on_rhs/model.h b/tests/resources/generator/algebraic_eqn_derivative_on_rhs/model.h index 446a5c415..9cbab2d88 100644 --- a/tests/resources/generator/algebraic_eqn_derivative_on_rhs/model.h +++ b/tests/resources/generator/algebraic_eqn_derivative_on_rhs/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/algebraic_eqn_derivative_on_rhs/model.py b/tests/resources/generator/algebraic_eqn_derivative_on_rhs/model.py index c71c392f7..ea246e37b 100644 --- a/tests/resources/generator/algebraic_eqn_derivative_on_rhs/model.py +++ b/tests/resources/generator/algebraic_eqn_derivative_on_rhs/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 2 @@ -39,7 +39,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): variables[0] = 1.0 states[0] = 1.0 diff --git a/tests/resources/generator/algebraic_eqn_derivative_on_rhs_one_component/model.c b/tests/resources/generator/algebraic_eqn_derivative_on_rhs_one_component/model.c index d9dbbe43d..2f3e72de9 100644 --- a/tests/resources/generator/algebraic_eqn_derivative_on_rhs_one_component/model.c +++ b/tests/resources/generator/algebraic_eqn_derivative_on_rhs_one_component/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 2; @@ -24,12 +24,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -37,7 +49,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { variables[0] = 1.0; states[0] = 1.0; diff --git a/tests/resources/generator/algebraic_eqn_derivative_on_rhs_one_component/model.h b/tests/resources/generator/algebraic_eqn_derivative_on_rhs_one_component/model.h index 2235c5e07..9aad67f7a 100644 --- a/tests/resources/generator/algebraic_eqn_derivative_on_rhs_one_component/model.h +++ b/tests/resources/generator/algebraic_eqn_derivative_on_rhs_one_component/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/algebraic_eqn_derivative_on_rhs_one_component/model.py b/tests/resources/generator/algebraic_eqn_derivative_on_rhs_one_component/model.py index 8d6705bb6..93e624191 100644 --- a/tests/resources/generator/algebraic_eqn_derivative_on_rhs_one_component/model.py +++ b/tests/resources/generator/algebraic_eqn_derivative_on_rhs_one_component/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 2 @@ -39,7 +39,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): variables[0] = 1.0 states[0] = 1.0 diff --git a/tests/resources/generator/algebraic_eqn_state_var_on_rhs/model.c b/tests/resources/generator/algebraic_eqn_state_var_on_rhs/model.c index 207585161..4a7e9a123 100644 --- a/tests/resources/generator/algebraic_eqn_state_var_on_rhs/model.c +++ b/tests/resources/generator/algebraic_eqn_state_var_on_rhs/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 2; @@ -24,12 +24,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -37,7 +49,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { variables[0] = 1.0; states[0] = 1.0; diff --git a/tests/resources/generator/algebraic_eqn_state_var_on_rhs/model.h b/tests/resources/generator/algebraic_eqn_state_var_on_rhs/model.h index 075bdb760..5a4e26be3 100644 --- a/tests/resources/generator/algebraic_eqn_state_var_on_rhs/model.h +++ b/tests/resources/generator/algebraic_eqn_state_var_on_rhs/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/algebraic_eqn_state_var_on_rhs/model.py b/tests/resources/generator/algebraic_eqn_state_var_on_rhs/model.py index c437f4ef4..819c48815 100644 --- a/tests/resources/generator/algebraic_eqn_state_var_on_rhs/model.py +++ b/tests/resources/generator/algebraic_eqn_state_var_on_rhs/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 2 @@ -39,7 +39,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): variables[0] = 1.0 states[0] = 1.0 diff --git a/tests/resources/generator/algebraic_eqn_state_var_on_rhs_one_component/model.c b/tests/resources/generator/algebraic_eqn_state_var_on_rhs_one_component/model.c index d75df61ca..e2b07d92b 100644 --- a/tests/resources/generator/algebraic_eqn_state_var_on_rhs_one_component/model.c +++ b/tests/resources/generator/algebraic_eqn_state_var_on_rhs_one_component/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 2; @@ -24,12 +24,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -37,7 +49,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { variables[0] = 1.0; states[0] = 1.0; diff --git a/tests/resources/generator/algebraic_eqn_state_var_on_rhs_one_component/model.h b/tests/resources/generator/algebraic_eqn_state_var_on_rhs_one_component/model.h index 551054efb..6801dd9c0 100644 --- a/tests/resources/generator/algebraic_eqn_state_var_on_rhs_one_component/model.h +++ b/tests/resources/generator/algebraic_eqn_state_var_on_rhs_one_component/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/algebraic_eqn_state_var_on_rhs_one_component/model.py b/tests/resources/generator/algebraic_eqn_state_var_on_rhs_one_component/model.py index f496768ef..186d408c8 100644 --- a/tests/resources/generator/algebraic_eqn_state_var_on_rhs_one_component/model.py +++ b/tests/resources/generator/algebraic_eqn_state_var_on_rhs_one_component/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 2 @@ -39,7 +39,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): variables[0] = 1.0 states[0] = 1.0 diff --git a/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.c b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.c new file mode 100644 index 000000000..0993f56f9 --- /dev/null +++ b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.c @@ -0,0 +1,79 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t VARIABLE_COUNT = 4; + +const VariableInfo VARIABLE_INFO[] = { + {"b", "dimensionless", "my_algebraic_eqn", COMPUTED_CONSTANT}, + {"c", "dimensionless", "my_algebraic_eqn", COMPUTED_CONSTANT}, + {"d", "dimensionless", "my_algebraic_eqn", COMPUTED_CONSTANT}, + {"a", "dimensionless", "my_algebraic_eqn", ALGEBRAIC} +}; + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +typedef struct { + double *variables; +} RootFindingInfo; + +extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *), + double *u, int n, void *data); + +void objectiveFunction0(double *u, double *f, void *data) +{ + double *variables = ((RootFindingInfo *) data)->variables; + + variables[3] = u[0]; + + f[0] = variables[3]+variables[0]-(variables[1]+variables[2]); +} + +void findRoot0(double *variables) +{ + RootFindingInfo rfi = { variables }; + double u[1]; + + u[0] = variables[3]; + + nlaSolve(objectiveFunction0, u, 1, &rfi); + + variables[3] = u[0]; +} + +void initialiseVariables(double *variables) +{ + variables[3] = 1.0; + variables[0] = 3.0; + variables[1] = 5.0; + variables[2] = 7.0; +} + +void computeComputedConstants(double *variables) +{ +} + +void computeVariables(double *variables) +{ + findRoot0(variables); +} diff --git a/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.cellml b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.cellml new file mode 100644 index 000000000..ac8e6388a --- /dev/null +++ b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.cellml @@ -0,0 +1,48 @@ + + + + + + + + + + + + b + 3 + + + + c + 5 + + + + d + 7 + + + + + + a + b + + + + c + d + + + + + diff --git a/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.c b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.c new file mode 100644 index 000000000..eb2c563f7 --- /dev/null +++ b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.c @@ -0,0 +1,51 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.external.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t VARIABLE_COUNT = 4; + +const VariableInfo VARIABLE_INFO[] = { + {"b", "dimensionless", "my_algebraic_eqn", COMPUTED_CONSTANT}, + {"c", "dimensionless", "my_algebraic_eqn", COMPUTED_CONSTANT}, + {"d", "dimensionless", "my_algebraic_eqn", COMPUTED_CONSTANT}, + {"a", "dimensionless", "my_algebraic_eqn", EXTERNAL} +}; + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +void initialiseVariables(double *variables, ExternalVariable externalVariable) +{ + variables[0] = 3.0; + variables[1] = 5.0; + variables[2] = 7.0; + variables[3] = externalVariable(variables, 3); +} + +void computeComputedConstants(double *variables) +{ +} + +void computeVariables(double *variables, ExternalVariable externalVariable) +{ + variables[3] = externalVariable(variables, 3); +} diff --git a/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.h b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.h new file mode 100644 index 000000000..9c1fc0d54 --- /dev/null +++ b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.h @@ -0,0 +1,35 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t VARIABLE_COUNT; + +typedef enum { + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC, + EXTERNAL +} VariableType; + +typedef struct { + char name[2]; + char units[14]; + char component[17]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VARIABLE_INFO[]; + +double * createVariablesArray(); +void deleteArray(double *array); + +typedef double (* ExternalVariable)(double *variables, size_t index); + +void initialiseVariables(double *variables, ExternalVariable externalVariable); +void computeComputedConstants(double *variables); +void computeVariables(double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.py b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.py new file mode 100644 index 000000000..6122ce629 --- /dev/null +++ b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.external.py @@ -0,0 +1,44 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +VARIABLE_COUNT = 4 + + +class VariableType(Enum): + CONSTANT = 0 + COMPUTED_CONSTANT = 1 + ALGEBRAIC = 2 + EXTERNAL = 3 + + +VARIABLE_INFO = [ + {"name": "b", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "c", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "d", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "a", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.EXTERNAL} +] + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +def initialise_variables(variables, external_variable): + variables[0] = 3.0 + variables[1] = 5.0 + variables[2] = 7.0 + variables[3] = external_variable(variables, 3) + + +def compute_computed_constants(variables): + pass + + +def compute_variables(variables, external_variable): + variables[3] = external_variable(variables, 3) diff --git a/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.h b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.h new file mode 100644 index 000000000..599f17050 --- /dev/null +++ b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.h @@ -0,0 +1,32 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t VARIABLE_COUNT; + +typedef enum { + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC +} VariableType; + +typedef struct { + char name[2]; + char units[14]; + char component[17]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VARIABLE_INFO[]; + +double * createVariablesArray(); +void deleteArray(double *array); + +void initialiseVariables(double *variables); +void computeComputedConstants(double *variables); +void computeVariables(double *variables); diff --git a/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.py b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.py new file mode 100644 index 000000000..64e6fded5 --- /dev/null +++ b/tests/resources/generator/algebraic_eqn_with_one_non_isolated_unknown/model.py @@ -0,0 +1,64 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +VARIABLE_COUNT = 4 + + +class VariableType(Enum): + CONSTANT = 0 + COMPUTED_CONSTANT = 1 + ALGEBRAIC = 2 + + +VARIABLE_INFO = [ + {"name": "b", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "c", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "d", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "a", "units": "dimensionless", "component": "my_algebraic_eqn", "type": VariableType.ALGEBRAIC} +] + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +from nlasolver import nla_solve + + +def objective_function_0(u, f, data): + variables = data[0] + + variables[3] = u[0] + + f[0] = variables[3]+variables[0]-(variables[1]+variables[2]) + + +def find_root_0(variables): + u = [nan]*1 + + u[0] = variables[3] + + u = nla_solve(objective_function_0, u, 1, [variables]) + + variables[3] = u[0] + + +def initialise_variables(variables): + variables[3] = 1.0 + variables[0] = 3.0 + variables[1] = 5.0 + variables[2] = 7.0 + + +def compute_computed_constants(variables): + pass + + +def compute_variables(variables): + find_root_0(variables) diff --git a/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.c b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.c new file mode 100644 index 000000000..63be9dafd --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.c @@ -0,0 +1,85 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t VARIABLE_COUNT = 3; + +const VariableInfo VARIABLE_INFO[] = { + {"x", "dimensionless", "my_algebraic_system", ALGEBRAIC}, + {"y", "dimensionless", "my_algebraic_system", ALGEBRAIC}, + {"z", "dimensionless", "my_algebraic_system", ALGEBRAIC} +}; + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +typedef struct { + double *variables; +} RootFindingInfo; + +extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *), + double *u, int n, void *data); + +void objectiveFunction0(double *u, double *f, void *data) +{ + double *variables = ((RootFindingInfo *) data)->variables; + + variables[0] = u[0]; + variables[1] = u[1]; + variables[2] = u[2]; + + f[0] = 2.0*variables[0]+variables[1]-2.0*variables[2]-(-1.0); + f[1] = 3.0*variables[0]-3.0*variables[1]-variables[2]-5.0; + f[2] = variables[0]-2.0*variables[1]+3.0*variables[2]-6.0; +} + +void findRoot0(double *variables) +{ + RootFindingInfo rfi = { variables }; + double u[3]; + + u[0] = variables[0]; + u[1] = variables[1]; + u[2] = variables[2]; + + nlaSolve(objectiveFunction0, u, 3, &rfi); + + variables[0] = u[0]; + variables[1] = u[1]; + variables[2] = u[2]; +} + +void initialiseVariables(double *variables) +{ + variables[0] = 1.0; + variables[1] = 1.0; + variables[2] = 1.0; +} + +void computeComputedConstants(double *variables) +{ +} + +void computeVariables(double *variables) +{ + findRoot0(variables); +} diff --git a/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.cellml b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.cellml new file mode 100644 index 000000000..19f830870 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.cellml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + 2 + x + + y + + + + 2 + z + + + -1 + + + + + + + + + + 3 + x + + + + 3 + y + + + z + + 5 + + + + + + + + x + + + 2 + y + + + + + 3 + z + + + 6 + + + + diff --git a/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.h b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.h new file mode 100644 index 000000000..5c5224a4c --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.h @@ -0,0 +1,32 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t VARIABLE_COUNT; + +typedef enum { + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC +} VariableType; + +typedef struct { + char name[2]; + char units[14]; + char component[20]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VARIABLE_INFO[]; + +double * createVariablesArray(); +void deleteArray(double *array); + +void initialiseVariables(double *variables); +void computeComputedConstants(double *variables); +void computeVariables(double *variables); diff --git a/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.one.external.c b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.one.external.c new file mode 100644 index 000000000..532ffe474 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.one.external.c @@ -0,0 +1,83 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.one.external.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t VARIABLE_COUNT = 3; + +const VariableInfo VARIABLE_INFO[] = { + {"x", "dimensionless", "my_algebraic_system", EXTERNAL}, + {"y", "dimensionless", "my_algebraic_system", ALGEBRAIC}, + {"z", "dimensionless", "my_algebraic_system", ALGEBRAIC} +}; + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +typedef struct { + double *variables; +} RootFindingInfo; + +extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *), + double *u, int n, void *data); + +void objectiveFunction0(double *u, double *f, void *data) +{ + double *variables = ((RootFindingInfo *) data)->variables; + + variables[1] = u[0]; + variables[2] = u[1]; + + f[0] = 2.0*variables[0]+variables[1]-2.0*variables[2]-(-1.0); + f[1] = 3.0*variables[0]-3.0*variables[1]-variables[2]-5.0; + f[2] = variables[0]-2.0*variables[1]+3.0*variables[2]-6.0; +} + +void findRoot0(double *variables) +{ + RootFindingInfo rfi = { variables }; + double u[2]; + + u[0] = variables[1]; + u[1] = variables[2]; + + nlaSolve(objectiveFunction0, u, 2, &rfi); + + variables[1] = u[0]; + variables[2] = u[1]; +} + +void initialiseVariables(double *variables, ExternalVariable externalVariable) +{ + variables[1] = 1.0; + variables[2] = 1.0; + variables[0] = externalVariable(variables, 0); +} + +void computeComputedConstants(double *variables) +{ +} + +void computeVariables(double *variables, ExternalVariable externalVariable) +{ + variables[0] = externalVariable(variables, 0); + findRoot0(variables); +} diff --git a/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.one.external.h b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.one.external.h new file mode 100644 index 000000000..1313c3687 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.one.external.h @@ -0,0 +1,35 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t VARIABLE_COUNT; + +typedef enum { + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC, + EXTERNAL +} VariableType; + +typedef struct { + char name[2]; + char units[14]; + char component[20]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VARIABLE_INFO[]; + +double * createVariablesArray(); +void deleteArray(double *array); + +typedef double (* ExternalVariable)(double *variables, size_t index); + +void initialiseVariables(double *variables, ExternalVariable externalVariable); +void computeComputedConstants(double *variables); +void computeVariables(double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.one.external.py b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.one.external.py new file mode 100644 index 000000000..43e635b6d --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.one.external.py @@ -0,0 +1,69 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +VARIABLE_COUNT = 3 + + +class VariableType(Enum): + CONSTANT = 0 + COMPUTED_CONSTANT = 1 + ALGEBRAIC = 2 + EXTERNAL = 3 + + +VARIABLE_INFO = [ + {"name": "x", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.EXTERNAL}, + {"name": "y", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.ALGEBRAIC}, + {"name": "z", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.ALGEBRAIC} +] + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +from nlasolver import nla_solve + + +def objective_function_0(u, f, data): + variables = data[0] + + variables[1] = u[0] + variables[2] = u[1] + + f[0] = 2.0*variables[0]+variables[1]-2.0*variables[2]-(-1.0) + f[1] = 3.0*variables[0]-3.0*variables[1]-variables[2]-5.0 + f[2] = variables[0]-2.0*variables[1]+3.0*variables[2]-6.0 + + +def find_root_0(variables): + u = [nan]*2 + + u[0] = variables[1] + u[1] = variables[2] + + u = nla_solve(objective_function_0, u, 2, [variables]) + + variables[1] = u[0] + variables[2] = u[1] + + +def initialise_variables(variables, external_variable): + variables[1] = 1.0 + variables[2] = 1.0 + variables[0] = external_variable(variables, 0) + + +def compute_computed_constants(variables): + pass + + +def compute_variables(variables, external_variable): + variables[0] = external_variable(variables, 0) + find_root_0(variables) diff --git a/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.py b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.py new file mode 100644 index 000000000..2f54c8121 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.py @@ -0,0 +1,70 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +VARIABLE_COUNT = 3 + + +class VariableType(Enum): + CONSTANT = 0 + COMPUTED_CONSTANT = 1 + ALGEBRAIC = 2 + + +VARIABLE_INFO = [ + {"name": "x", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.ALGEBRAIC}, + {"name": "y", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.ALGEBRAIC}, + {"name": "z", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.ALGEBRAIC} +] + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +from nlasolver import nla_solve + + +def objective_function_0(u, f, data): + variables = data[0] + + variables[0] = u[0] + variables[1] = u[1] + variables[2] = u[2] + + f[0] = 2.0*variables[0]+variables[1]-2.0*variables[2]-(-1.0) + f[1] = 3.0*variables[0]-3.0*variables[1]-variables[2]-5.0 + f[2] = variables[0]-2.0*variables[1]+3.0*variables[2]-6.0 + + +def find_root_0(variables): + u = [nan]*3 + + u[0] = variables[0] + u[1] = variables[1] + u[2] = variables[2] + + u = nla_solve(objective_function_0, u, 3, [variables]) + + variables[0] = u[0] + variables[1] = u[1] + variables[2] = u[2] + + +def initialise_variables(variables): + variables[0] = 1.0 + variables[1] = 1.0 + variables[2] = 1.0 + + +def compute_computed_constants(variables): + pass + + +def compute_variables(variables): + find_root_0(variables) diff --git a/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.three.externals.c b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.three.externals.c new file mode 100644 index 000000000..654a8aa75 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.three.externals.c @@ -0,0 +1,51 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.three.externals.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t VARIABLE_COUNT = 3; + +const VariableInfo VARIABLE_INFO[] = { + {"x", "dimensionless", "my_algebraic_system", EXTERNAL}, + {"y", "dimensionless", "my_algebraic_system", EXTERNAL}, + {"z", "dimensionless", "my_algebraic_system", EXTERNAL} +}; + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +void initialiseVariables(double *variables, ExternalVariable externalVariable) +{ + variables[0] = externalVariable(variables, 0); + variables[1] = externalVariable(variables, 1); + variables[2] = externalVariable(variables, 2); +} + +void computeComputedConstants(double *variables) +{ +} + +void computeVariables(double *variables, ExternalVariable externalVariable) +{ + variables[0] = externalVariable(variables, 0); + variables[1] = externalVariable(variables, 1); + variables[2] = externalVariable(variables, 2); +} diff --git a/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.three.externals.h b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.three.externals.h new file mode 100644 index 000000000..1313c3687 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.three.externals.h @@ -0,0 +1,35 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t VARIABLE_COUNT; + +typedef enum { + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC, + EXTERNAL +} VariableType; + +typedef struct { + char name[2]; + char units[14]; + char component[20]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VARIABLE_INFO[]; + +double * createVariablesArray(); +void deleteArray(double *array); + +typedef double (* ExternalVariable)(double *variables, size_t index); + +void initialiseVariables(double *variables, ExternalVariable externalVariable); +void computeComputedConstants(double *variables); +void computeVariables(double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.three.externals.py b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.three.externals.py new file mode 100644 index 000000000..5816ca029 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.three.externals.py @@ -0,0 +1,44 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +VARIABLE_COUNT = 3 + + +class VariableType(Enum): + CONSTANT = 0 + COMPUTED_CONSTANT = 1 + ALGEBRAIC = 2 + EXTERNAL = 3 + + +VARIABLE_INFO = [ + {"name": "x", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.EXTERNAL}, + {"name": "y", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.EXTERNAL}, + {"name": "z", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.EXTERNAL} +] + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +def initialise_variables(variables, external_variable): + variables[0] = external_variable(variables, 0) + variables[1] = external_variable(variables, 1) + variables[2] = external_variable(variables, 2) + + +def compute_computed_constants(variables): + pass + + +def compute_variables(variables, external_variable): + variables[0] = external_variable(variables, 0) + variables[1] = external_variable(variables, 1) + variables[2] = external_variable(variables, 2) diff --git a/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.two.externals.c b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.two.externals.c new file mode 100644 index 000000000..eab3f0eb7 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.two.externals.c @@ -0,0 +1,123 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.two.externals.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t VARIABLE_COUNT = 3; + +const VariableInfo VARIABLE_INFO[] = { + {"x", "dimensionless", "my_algebraic_system", EXTERNAL}, + {"y", "dimensionless", "my_algebraic_system", ALGEBRAIC}, + {"z", "dimensionless", "my_algebraic_system", EXTERNAL} +}; + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +typedef struct { + double *variables; +} RootFindingInfo; + +extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *), + double *u, int n, void *data); + +void objectiveFunction0(double *u, double *f, void *data) +{ + double *variables = ((RootFindingInfo *) data)->variables; + + variables[1] = u[0]; + + f[0] = 2.0*variables[0]+variables[1]-2.0*variables[2]-(-1.0); +} + +void findRoot0(double *variables) +{ + RootFindingInfo rfi = { variables }; + double u[1]; + + u[0] = variables[1]; + + nlaSolve(objectiveFunction0, u, 1, &rfi); + + variables[1] = u[0]; +} + +void objectiveFunction1(double *u, double *f, void *data) +{ + double *variables = ((RootFindingInfo *) data)->variables; + + variables[1] = u[0]; + + f[0] = 3.0*variables[0]-3.0*variables[1]-variables[2]-5.0; +} + +void findRoot1(double *variables) +{ + RootFindingInfo rfi = { variables }; + double u[1]; + + u[0] = variables[1]; + + nlaSolve(objectiveFunction1, u, 1, &rfi); + + variables[1] = u[0]; +} + +void objectiveFunction2(double *u, double *f, void *data) +{ + double *variables = ((RootFindingInfo *) data)->variables; + + variables[1] = u[0]; + + f[0] = variables[0]-2.0*variables[1]+3.0*variables[2]-6.0; +} + +void findRoot2(double *variables) +{ + RootFindingInfo rfi = { variables }; + double u[1]; + + u[0] = variables[1]; + + nlaSolve(objectiveFunction2, u, 1, &rfi); + + variables[1] = u[0]; +} + +void initialiseVariables(double *variables, ExternalVariable externalVariable) +{ + variables[1] = 1.0; + variables[0] = externalVariable(variables, 0); + variables[2] = externalVariable(variables, 2); +} + +void computeComputedConstants(double *variables) +{ +} + +void computeVariables(double *variables, ExternalVariable externalVariable) +{ + variables[0] = externalVariable(variables, 0); + variables[2] = externalVariable(variables, 2); + findRoot0(variables); + findRoot1(variables); + findRoot2(variables); +} diff --git a/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.two.externals.h b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.two.externals.h new file mode 100644 index 000000000..1313c3687 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.two.externals.h @@ -0,0 +1,35 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t VARIABLE_COUNT; + +typedef enum { + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC, + EXTERNAL +} VariableType; + +typedef struct { + char name[2]; + char units[14]; + char component[20]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VARIABLE_INFO[]; + +double * createVariablesArray(); +void deleteArray(double *array); + +typedef double (* ExternalVariable)(double *variables, size_t index); + +void initialiseVariables(double *variables, ExternalVariable externalVariable); +void computeComputedConstants(double *variables); +void computeVariables(double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.two.externals.py b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.two.externals.py new file mode 100644 index 000000000..34b77ef86 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_three_linked_unknowns/model.two.externals.py @@ -0,0 +1,103 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +VARIABLE_COUNT = 3 + + +class VariableType(Enum): + CONSTANT = 0 + COMPUTED_CONSTANT = 1 + ALGEBRAIC = 2 + EXTERNAL = 3 + + +VARIABLE_INFO = [ + {"name": "x", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.EXTERNAL}, + {"name": "y", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.ALGEBRAIC}, + {"name": "z", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.EXTERNAL} +] + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +from nlasolver import nla_solve + + +def objective_function_0(u, f, data): + variables = data[0] + + variables[1] = u[0] + + f[0] = 2.0*variables[0]+variables[1]-2.0*variables[2]-(-1.0) + + +def find_root_0(variables): + u = [nan]*1 + + u[0] = variables[1] + + u = nla_solve(objective_function_0, u, 1, [variables]) + + variables[1] = u[0] + + +def objective_function_1(u, f, data): + variables = data[0] + + variables[1] = u[0] + + f[0] = 3.0*variables[0]-3.0*variables[1]-variables[2]-5.0 + + +def find_root_1(variables): + u = [nan]*1 + + u[0] = variables[1] + + u = nla_solve(objective_function_1, u, 1, [variables]) + + variables[1] = u[0] + + +def objective_function_2(u, f, data): + variables = data[0] + + variables[1] = u[0] + + f[0] = variables[0]-2.0*variables[1]+3.0*variables[2]-6.0 + + +def find_root_2(variables): + u = [nan]*1 + + u[0] = variables[1] + + u = nla_solve(objective_function_2, u, 1, [variables]) + + variables[1] = u[0] + + +def initialise_variables(variables, external_variable): + variables[1] = 1.0 + variables[0] = external_variable(variables, 0) + variables[2] = external_variable(variables, 2) + + +def compute_computed_constants(variables): + pass + + +def compute_variables(variables, external_variable): + variables[0] = external_variable(variables, 0) + variables[2] = external_variable(variables, 2) + find_root_0(variables) + find_root_1(variables) + find_root_2(variables) diff --git a/tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.c b/tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.c new file mode 100644 index 000000000..a3d23d553 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.c @@ -0,0 +1,87 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.not.ordered.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t VARIABLE_COUNT = 6; + +const VariableInfo VARIABLE_INFO[] = { + {"d", "dimensionless", "my_algebraic_system", ALGEBRAIC}, + {"b", "dimensionless", "my_algebraic_system", ALGEBRAIC}, + {"c", "dimensionless", "my_algebraic_system", ALGEBRAIC}, + {"a", "dimensionless", "my_algebraic_system", COMPUTED_CONSTANT}, + {"x", "dimensionless", "my_algebraic_system", CONSTANT}, + {"y", "dimensionless", "my_algebraic_system", CONSTANT} +}; + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +typedef struct { + double *variables; +} RootFindingInfo; + +extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *), + double *u, int n, void *data); + +void objectiveFunction0(double *u, double *f, void *data) +{ + double *variables = ((RootFindingInfo *) data)->variables; + + variables[2] = u[0]; + variables[1] = u[1]; + + f[0] = 3.0*variables[3]+2.0*variables[1]+variables[2]-57.0; + f[1] = variables[3]+3.0*variables[1]-variables[2]-19.0; +} + +void findRoot0(double *variables) +{ + RootFindingInfo rfi = { variables }; + double u[2]; + + u[0] = variables[2]; + u[1] = variables[1]; + + nlaSolve(objectiveFunction0, u, 2, &rfi); + + variables[2] = u[0]; + variables[1] = u[1]; +} + +void initialiseVariables(double *variables) +{ + variables[1] = 1.0; + variables[2] = 1.0; + variables[4] = 3.0; + variables[5] = 5.0; +} + +void computeComputedConstants(double *variables) +{ + variables[3] = 3.0*variables[4]+variables[5]; +} + +void computeVariables(double *variables) +{ + findRoot0(variables); + variables[0] = variables[1]+variables[2]; +} diff --git a/tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.cellml b/tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.cellml new file mode 100644 index 000000000..9a82849c6 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.cellml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + d + + + b + c + + + + + + + + + 3 + a + + + + 2 + b + + c + + 57 + + + + + + + + a + + + 3 + b + + + c + + 19 + + + + a + + + + + 3 + x + + y + + + + + diff --git a/tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.h b/tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.h new file mode 100644 index 000000000..5c5224a4c --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.h @@ -0,0 +1,32 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t VARIABLE_COUNT; + +typedef enum { + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC +} VariableType; + +typedef struct { + char name[2]; + char units[14]; + char component[20]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VARIABLE_INFO[]; + +double * createVariablesArray(); +void deleteArray(double *array); + +void initialiseVariables(double *variables); +void computeComputedConstants(double *variables); +void computeVariables(double *variables); diff --git a/tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.py b/tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.py new file mode 100644 index 000000000..0fbf42a74 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_various_dependencies/model.not.ordered.py @@ -0,0 +1,71 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +VARIABLE_COUNT = 6 + + +class VariableType(Enum): + CONSTANT = 0 + COMPUTED_CONSTANT = 1 + ALGEBRAIC = 2 + + +VARIABLE_INFO = [ + {"name": "d", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.ALGEBRAIC}, + {"name": "b", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.ALGEBRAIC}, + {"name": "c", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.ALGEBRAIC}, + {"name": "a", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "x", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.CONSTANT}, + {"name": "y", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.CONSTANT} +] + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +from nlasolver import nla_solve + + +def objective_function_0(u, f, data): + variables = data[0] + + variables[2] = u[0] + variables[1] = u[1] + + f[0] = 3.0*variables[3]+2.0*variables[1]+variables[2]-57.0 + f[1] = variables[3]+3.0*variables[1]-variables[2]-19.0 + + +def find_root_0(variables): + u = [nan]*2 + + u[0] = variables[2] + u[1] = variables[1] + + u = nla_solve(objective_function_0, u, 2, [variables]) + + variables[2] = u[0] + variables[1] = u[1] + + +def initialise_variables(variables): + variables[1] = 1.0 + variables[2] = 1.0 + variables[4] = 3.0 + variables[5] = 5.0 + + +def compute_computed_constants(variables): + variables[3] = 3.0*variables[4]+variables[5] + + +def compute_variables(variables): + find_root_0(variables) + variables[0] = variables[1]+variables[2] diff --git a/tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.c b/tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.c new file mode 100644 index 000000000..07f2620ee --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.c @@ -0,0 +1,87 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.ordered.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t VARIABLE_COUNT = 6; + +const VariableInfo VARIABLE_INFO[] = { + {"a", "dimensionless", "my_algebraic_system", COMPUTED_CONSTANT}, + {"x", "dimensionless", "my_algebraic_system", CONSTANT}, + {"y", "dimensionless", "my_algebraic_system", CONSTANT}, + {"c", "dimensionless", "my_algebraic_system", ALGEBRAIC}, + {"b", "dimensionless", "my_algebraic_system", ALGEBRAIC}, + {"d", "dimensionless", "my_algebraic_system", ALGEBRAIC} +}; + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +typedef struct { + double *variables; +} RootFindingInfo; + +extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *), + double *u, int n, void *data); + +void objectiveFunction0(double *u, double *f, void *data) +{ + double *variables = ((RootFindingInfo *) data)->variables; + + variables[3] = u[0]; + variables[4] = u[1]; + + f[0] = 3.0*variables[0]+2.0*variables[4]+variables[3]-57.0; + f[1] = variables[0]+3.0*variables[4]-variables[3]-19.0; +} + +void findRoot0(double *variables) +{ + RootFindingInfo rfi = { variables }; + double u[2]; + + u[0] = variables[3]; + u[1] = variables[4]; + + nlaSolve(objectiveFunction0, u, 2, &rfi); + + variables[3] = u[0]; + variables[4] = u[1]; +} + +void initialiseVariables(double *variables) +{ + variables[1] = 3.0; + variables[2] = 5.0; + variables[3] = 1.0; + variables[4] = 1.0; +} + +void computeComputedConstants(double *variables) +{ + variables[0] = 3.0*variables[1]+variables[2]; +} + +void computeVariables(double *variables) +{ + findRoot0(variables); + variables[5] = variables[4]+variables[3]; +} diff --git a/tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.cellml b/tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.cellml new file mode 100644 index 000000000..6851b8557 --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.cellml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + a + + + + + 3 + x + + y + + + + + + + + + 3 + a + + + + 2 + b + + c + + 57 + + + + + + + + a + + + 3 + b + + + c + + 19 + + + + d + + + b + c + + + + + diff --git a/tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.h b/tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.h new file mode 100644 index 000000000..5c5224a4c --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.h @@ -0,0 +1,32 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t VARIABLE_COUNT; + +typedef enum { + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC +} VariableType; + +typedef struct { + char name[2]; + char units[14]; + char component[20]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VARIABLE_INFO[]; + +double * createVariablesArray(); +void deleteArray(double *array); + +void initialiseVariables(double *variables); +void computeComputedConstants(double *variables); +void computeVariables(double *variables); diff --git a/tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.py b/tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.py new file mode 100644 index 000000000..3295b1d2c --- /dev/null +++ b/tests/resources/generator/algebraic_system_with_various_dependencies/model.ordered.py @@ -0,0 +1,71 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +VARIABLE_COUNT = 6 + + +class VariableType(Enum): + CONSTANT = 0 + COMPUTED_CONSTANT = 1 + ALGEBRAIC = 2 + + +VARIABLE_INFO = [ + {"name": "a", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "x", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.CONSTANT}, + {"name": "y", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.CONSTANT}, + {"name": "c", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.ALGEBRAIC}, + {"name": "b", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.ALGEBRAIC}, + {"name": "d", "units": "dimensionless", "component": "my_algebraic_system", "type": VariableType.ALGEBRAIC} +] + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +from nlasolver import nla_solve + + +def objective_function_0(u, f, data): + variables = data[0] + + variables[3] = u[0] + variables[4] = u[1] + + f[0] = 3.0*variables[0]+2.0*variables[4]+variables[3]-57.0 + f[1] = variables[0]+3.0*variables[4]-variables[3]-19.0 + + +def find_root_0(variables): + u = [nan]*2 + + u[0] = variables[3] + u[1] = variables[4] + + u = nla_solve(objective_function_0, u, 2, [variables]) + + variables[3] = u[0] + variables[4] = u[1] + + +def initialise_variables(variables): + variables[1] = 3.0 + variables[2] = 5.0 + variables[3] = 1.0 + variables[4] = 1.0 + + +def compute_computed_constants(variables): + variables[0] = 3.0*variables[1]+variables[2] + + +def compute_variables(variables): + find_root_0(variables) + variables[5] = variables[4]+variables[3] diff --git a/tests/resources/generator/algebraic_unknown_var_on_rhs/model.c b/tests/resources/generator/algebraic_unknown_var_on_rhs/model.c new file mode 100644 index 000000000..c6eacd196 --- /dev/null +++ b/tests/resources/generator/algebraic_unknown_var_on_rhs/model.c @@ -0,0 +1,46 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t VARIABLE_COUNT = 2; + +const VariableInfo VARIABLE_INFO[] = { + {"x", "dimensionless", "my_component", COMPUTED_CONSTANT}, + {"y", "dimensionless", "my_component", COMPUTED_CONSTANT} +}; + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +void initialiseVariables(double *variables) +{ + variables[0] = 1.0; +} + +void computeComputedConstants(double *variables) +{ + variables[1] = variables[0]; +} + +void computeVariables(double *variables) +{ +} diff --git a/tests/resources/analyser/overconstrained_two_variables.cellml b/tests/resources/generator/algebraic_unknown_var_on_rhs/model.cellml similarity index 53% rename from tests/resources/analyser/overconstrained_two_variables.cellml rename to tests/resources/generator/algebraic_unknown_var_on_rhs/model.cellml index 9d179c458..44a7582a2 100644 --- a/tests/resources/analyser/overconstrained_two_variables.cellml +++ b/tests/resources/generator/algebraic_unknown_var_on_rhs/model.cellml @@ -1,26 +1,21 @@ + - + - y - - - x - 1 - + 1 + x + x y - - - x - 3 - diff --git a/tests/resources/generator/algebraic_unknown_var_on_rhs/model.h b/tests/resources/generator/algebraic_unknown_var_on_rhs/model.h new file mode 100644 index 000000000..32566495b --- /dev/null +++ b/tests/resources/generator/algebraic_unknown_var_on_rhs/model.h @@ -0,0 +1,32 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t VARIABLE_COUNT; + +typedef enum { + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC +} VariableType; + +typedef struct { + char name[2]; + char units[14]; + char component[13]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VARIABLE_INFO[]; + +double * createVariablesArray(); +void deleteArray(double *array); + +void initialiseVariables(double *variables); +void computeComputedConstants(double *variables); +void computeVariables(double *variables); diff --git a/tests/resources/generator/algebraic_unknown_var_on_rhs/model.py b/tests/resources/generator/algebraic_unknown_var_on_rhs/model.py new file mode 100644 index 000000000..b2ae5ff20 --- /dev/null +++ b/tests/resources/generator/algebraic_unknown_var_on_rhs/model.py @@ -0,0 +1,38 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +VARIABLE_COUNT = 2 + + +class VariableType(Enum): + CONSTANT = 0 + COMPUTED_CONSTANT = 1 + ALGEBRAIC = 2 + + +VARIABLE_INFO = [ + {"name": "x", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "y", "units": "dimensionless", "component": "my_component", "type": VariableType.COMPUTED_CONSTANT} +] + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +def initialise_variables(variables): + variables[0] = 1.0 + + +def compute_computed_constants(variables): + variables[1] = variables[0] + + +def compute_variables(variables): + pass diff --git a/tests/resources/generator/cell_geometry_model/model.c b/tests/resources/generator/cell_geometry_model/model.c index 000b77619..c29bf9ab5 100644 --- a/tests/resources/generator/cell_geometry_model/model.c +++ b/tests/resources/generator/cell_geometry_model/model.c @@ -1,25 +1,31 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t VARIABLE_COUNT = 4; const VariableInfo VARIABLE_INFO[] = { + {"vcell", "microlitre", "cell_geometry", COMPUTED_CONSTANT}, {"L", "centimeter", "cell_geometry", CONSTANT}, {"rad", "centimeter", "cell_geometry", CONSTANT}, - {"vcell", "microlitre", "cell_geometry", COMPUTED_CONSTANT}, {"vss", "microlitre", "cell_geometry", COMPUTED_CONSTANT} }; double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -29,14 +35,14 @@ void deleteArray(double *array) void initialiseVariables(double *variables) { - variables[0] = 0.01; - variables[1] = 0.0011; + variables[1] = 0.01; + variables[2] = 0.0011; } void computeComputedConstants(double *variables) { - variables[2] = 1000.0*3.14*variables[1]*variables[1]*variables[0]; - variables[3] = 0.02*variables[2]; + variables[0] = 1000.0*3.14*variables[2]*variables[2]*variables[1]; + variables[3] = 0.02*variables[0]; } void computeVariables(double *variables) diff --git a/tests/resources/generator/cell_geometry_model/model.external.c b/tests/resources/generator/cell_geometry_model/model.external.c index 4bc766877..9018f1e02 100644 --- a/tests/resources/generator/cell_geometry_model/model.external.c +++ b/tests/resources/generator/cell_geometry_model/model.external.c @@ -1,25 +1,31 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.external.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t VARIABLE_COUNT = 4; const VariableInfo VARIABLE_INFO[] = { + {"vcell", "microlitre", "cell_geometry", ALGEBRAIC}, {"L", "centimeter", "cell_geometry", EXTERNAL}, {"rad", "centimeter", "cell_geometry", EXTERNAL}, - {"vcell", "microlitre", "cell_geometry", ALGEBRAIC}, {"vss", "microlitre", "cell_geometry", ALGEBRAIC} }; double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -29,8 +35,8 @@ void deleteArray(double *array) void initialiseVariables(double *variables, ExternalVariable externalVariable) { - variables[0] = externalVariable(variables, 0); variables[1] = externalVariable(variables, 1); + variables[2] = externalVariable(variables, 2); } void computeComputedConstants(double *variables) @@ -39,8 +45,8 @@ void computeComputedConstants(double *variables) void computeVariables(double *variables, ExternalVariable externalVariable) { - variables[0] = externalVariable(variables, 0); variables[1] = externalVariable(variables, 1); - variables[2] = 1000.0*3.14*variables[1]*variables[1]*variables[0]; - variables[3] = 0.02*variables[2]; + variables[2] = externalVariable(variables, 2); + variables[0] = 1000.0*3.14*variables[2]*variables[2]*variables[1]; + variables[3] = 0.02*variables[0]; } diff --git a/tests/resources/generator/cell_geometry_model/model.external.h b/tests/resources/generator/cell_geometry_model/model.external.h index 273796e38..3664a6d38 100644 --- a/tests/resources/generator/cell_geometry_model/model.external.h +++ b/tests/resources/generator/cell_geometry_model/model.external.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once diff --git a/tests/resources/generator/cell_geometry_model/model.external.py b/tests/resources/generator/cell_geometry_model/model.external.py index 3f3ccc131..5dda92b0a 100644 --- a/tests/resources/generator/cell_geometry_model/model.external.py +++ b/tests/resources/generator/cell_geometry_model/model.external.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" VARIABLE_COUNT = 4 @@ -18,9 +18,9 @@ class VariableType(Enum): VARIABLE_INFO = [ + {"name": "vcell", "units": "microlitre", "component": "cell_geometry", "type": VariableType.ALGEBRAIC}, {"name": "L", "units": "centimeter", "component": "cell_geometry", "type": VariableType.EXTERNAL}, {"name": "rad", "units": "centimeter", "component": "cell_geometry", "type": VariableType.EXTERNAL}, - {"name": "vcell", "units": "microlitre", "component": "cell_geometry", "type": VariableType.ALGEBRAIC}, {"name": "vss", "units": "microlitre", "component": "cell_geometry", "type": VariableType.ALGEBRAIC} ] @@ -30,8 +30,8 @@ def create_variables_array(): def initialise_variables(variables, external_variable): - variables[0] = external_variable(variables, 0) variables[1] = external_variable(variables, 1) + variables[2] = external_variable(variables, 2) def compute_computed_constants(variables): @@ -39,7 +39,7 @@ def compute_computed_constants(variables): def compute_variables(variables, external_variable): - variables[0] = external_variable(variables, 0) variables[1] = external_variable(variables, 1) - variables[2] = 1000.0*3.14*variables[1]*variables[1]*variables[0] - variables[3] = 0.02*variables[2] + variables[2] = external_variable(variables, 2) + variables[0] = 1000.0*3.14*variables[2]*variables[2]*variables[1] + variables[3] = 0.02*variables[0] diff --git a/tests/resources/generator/cell_geometry_model/model.h b/tests/resources/generator/cell_geometry_model/model.h index 5d4085292..aecf1d812 100644 --- a/tests/resources/generator/cell_geometry_model/model.h +++ b/tests/resources/generator/cell_geometry_model/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once diff --git a/tests/resources/generator/cell_geometry_model/model.py b/tests/resources/generator/cell_geometry_model/model.py index 1e31b9acd..09f2093d3 100644 --- a/tests/resources/generator/cell_geometry_model/model.py +++ b/tests/resources/generator/cell_geometry_model/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" VARIABLE_COUNT = 4 @@ -17,9 +17,9 @@ class VariableType(Enum): VARIABLE_INFO = [ + {"name": "vcell", "units": "microlitre", "component": "cell_geometry", "type": VariableType.COMPUTED_CONSTANT}, {"name": "L", "units": "centimeter", "component": "cell_geometry", "type": VariableType.CONSTANT}, {"name": "rad", "units": "centimeter", "component": "cell_geometry", "type": VariableType.CONSTANT}, - {"name": "vcell", "units": "microlitre", "component": "cell_geometry", "type": VariableType.COMPUTED_CONSTANT}, {"name": "vss", "units": "microlitre", "component": "cell_geometry", "type": VariableType.COMPUTED_CONSTANT} ] @@ -29,13 +29,13 @@ def create_variables_array(): def initialise_variables(variables): - variables[0] = 0.01 - variables[1] = 0.0011 + variables[1] = 0.01 + variables[2] = 0.0011 def compute_computed_constants(variables): - variables[2] = 1000.0*3.14*variables[1]*variables[1]*variables[0] - variables[3] = 0.02*variables[2] + variables[0] = 1000.0*3.14*variables[2]*variables[2]*variables[1] + variables[3] = 0.02*variables[0] def compute_variables(variables): diff --git a/tests/resources/generator/cellml_mappings_and_encapsulations/model.c b/tests/resources/generator/cellml_mappings_and_encapsulations/model.c index 391694702..e2fc41b49 100644 --- a/tests/resources/generator/cellml_mappings_and_encapsulations/model.c +++ b/tests/resources/generator/cellml_mappings_and_encapsulations/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 2; const size_t VARIABLE_COUNT = 2; @@ -14,8 +14,8 @@ const size_t VARIABLE_COUNT = 2; const VariableInfo VOI_INFO = {"t", "ms", "environment", VARIABLE_OF_INTEGRATION}; const VariableInfo STATE_INFO[] = { - {"x", "mM", "circle_x", STATE}, - {"y", "mM", "circle_y_implementation", STATE} + {"y", "mM", "circle_y_implementation", STATE}, + {"x", "mM", "circle_x", STATE} }; const VariableInfo VARIABLE_INFO[] = { @@ -25,12 +25,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -38,10 +50,10 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { - states[0] = 0.0; - states[1] = 1.0; + states[0] = 1.0; + states[1] = 0.0; } void computeComputedConstants(double *variables) @@ -50,12 +62,12 @@ void computeComputedConstants(double *variables) void computeRates(double voi, double *states, double *rates, double *variables) { - rates[0] = -states[1]*1.0; - rates[1] = states[0]*1.0; + rates[1] = -states[0]*1.0; + rates[0] = states[1]*1.0; } void computeVariables(double voi, double *states, double *rates, double *variables) { - variables[0] = states[1]+5.0*states[1]/3.0+1.0*exp(states[1]/2.0); - variables[1] = 2.0*states[0]; + variables[0] = states[0]+5.0*states[0]/3.0+1.0*exp(states[0]/2.0); + variables[1] = 2.0*states[1]; } diff --git a/tests/resources/generator/cellml_mappings_and_encapsulations/model.h b/tests/resources/generator/cellml_mappings_and_encapsulations/model.h index 2c1f896c4..acc99f2a4 100644 --- a/tests/resources/generator/cellml_mappings_and_encapsulations/model.h +++ b/tests/resources/generator/cellml_mappings_and_encapsulations/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/cellml_mappings_and_encapsulations/model.py b/tests/resources/generator/cellml_mappings_and_encapsulations/model.py index c9e0855de..414b539eb 100644 --- a/tests/resources/generator/cellml_mappings_and_encapsulations/model.py +++ b/tests/resources/generator/cellml_mappings_and_encapsulations/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 2 VARIABLE_COUNT = 2 @@ -22,8 +22,8 @@ class VariableType(Enum): VOI_INFO = {"name": "t", "units": "ms", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} STATE_INFO = [ - {"name": "x", "units": "mM", "component": "circle_x", "type": VariableType.STATE}, - {"name": "y", "units": "mM", "component": "circle_y_implementation", "type": VariableType.STATE} + {"name": "y", "units": "mM", "component": "circle_y_implementation", "type": VariableType.STATE}, + {"name": "x", "units": "mM", "component": "circle_x", "type": VariableType.STATE} ] VARIABLE_INFO = [ @@ -40,9 +40,9 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): - states[0] = 0.0 - states[1] = 1.0 +def initialise_variables(states, rates, variables): + states[0] = 1.0 + states[1] = 0.0 def compute_computed_constants(variables): @@ -50,10 +50,10 @@ def compute_computed_constants(variables): def compute_rates(voi, states, rates, variables): - rates[0] = -states[1]*1.0 - rates[1] = states[0]*1.0 + rates[1] = -states[0]*1.0 + rates[0] = states[1]*1.0 def compute_variables(voi, states, rates, variables): - variables[0] = states[1]+5.0*states[1]/3.0+1.0*exp(states[1]/2.0) - variables[1] = 2.0*states[0] + variables[0] = states[0]+5.0*states[0]/3.0+1.0*exp(states[0]/2.0) + variables[1] = 2.0*states[1] diff --git a/tests/resources/generator/cellml_state_initialised_using_variable/model.c b/tests/resources/generator/cellml_state_initialised_using_variable/model.c index dcc3e1205..d3092bcf5 100644 --- a/tests/resources/generator/cellml_state_initialised_using_variable/model.c +++ b/tests/resources/generator/cellml_state_initialised_using_variable/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 1; @@ -23,12 +23,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -36,7 +48,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { variables[0] = 123.0; states[0] = variables[0]; diff --git a/tests/resources/generator/cellml_state_initialised_using_variable/model.h b/tests/resources/generator/cellml_state_initialised_using_variable/model.h index 9e2806859..d683c7fb0 100644 --- a/tests/resources/generator/cellml_state_initialised_using_variable/model.h +++ b/tests/resources/generator/cellml_state_initialised_using_variable/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/cellml_state_initialised_using_variable/model.py b/tests/resources/generator/cellml_state_initialised_using_variable/model.py index 5dda71007..6e0d3a8da 100644 --- a/tests/resources/generator/cellml_state_initialised_using_variable/model.py +++ b/tests/resources/generator/cellml_state_initialised_using_variable/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 1 @@ -38,7 +38,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): variables[0] = 123.0 states[0] = variables[0] diff --git a/tests/resources/generator/cellml_unit_scaling_constant/model.c b/tests/resources/generator/cellml_unit_scaling_constant/model.c index 11b88e44d..271426414 100644 --- a/tests/resources/generator/cellml_unit_scaling_constant/model.c +++ b/tests/resources/generator/cellml_unit_scaling_constant/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t VARIABLE_COUNT = 3; @@ -18,7 +18,13 @@ const VariableInfo VARIABLE_INFO[] = { double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) diff --git a/tests/resources/generator/cellml_unit_scaling_constant/model.h b/tests/resources/generator/cellml_unit_scaling_constant/model.h index b3d428e0a..d43c10c5a 100644 --- a/tests/resources/generator/cellml_unit_scaling_constant/model.h +++ b/tests/resources/generator/cellml_unit_scaling_constant/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once diff --git a/tests/resources/generator/cellml_unit_scaling_constant/model.py b/tests/resources/generator/cellml_unit_scaling_constant/model.py index 821bef855..ce3805d20 100644 --- a/tests/resources/generator/cellml_unit_scaling_constant/model.py +++ b/tests/resources/generator/cellml_unit_scaling_constant/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" VARIABLE_COUNT = 3 diff --git a/tests/resources/generator/cellml_unit_scaling_rate/model.c b/tests/resources/generator/cellml_unit_scaling_rate/model.c index e38ccadc7..8de1ea245 100644 --- a/tests/resources/generator/cellml_unit_scaling_rate/model.c +++ b/tests/resources/generator/cellml_unit_scaling_rate/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 2; @@ -24,12 +24,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -37,7 +49,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { states[0] = 123.0; } diff --git a/tests/resources/generator/cellml_unit_scaling_rate/model.h b/tests/resources/generator/cellml_unit_scaling_rate/model.h index 9e2806859..d683c7fb0 100644 --- a/tests/resources/generator/cellml_unit_scaling_rate/model.h +++ b/tests/resources/generator/cellml_unit_scaling_rate/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/cellml_unit_scaling_rate/model.py b/tests/resources/generator/cellml_unit_scaling_rate/model.py index 1492491d8..74bcb203f 100644 --- a/tests/resources/generator/cellml_unit_scaling_rate/model.py +++ b/tests/resources/generator/cellml_unit_scaling_rate/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 2 @@ -39,7 +39,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): states[0] = 123.0 diff --git a/tests/resources/generator/cellml_unit_scaling_state/model.c b/tests/resources/generator/cellml_unit_scaling_state/model.c index 57e644085..f1275daa2 100644 --- a/tests/resources/generator/cellml_unit_scaling_state/model.c +++ b/tests/resources/generator/cellml_unit_scaling_state/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 2; @@ -24,12 +24,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -37,7 +49,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { states[0] = 123.0; } diff --git a/tests/resources/generator/cellml_unit_scaling_state/model.h b/tests/resources/generator/cellml_unit_scaling_state/model.h index 9e2806859..d683c7fb0 100644 --- a/tests/resources/generator/cellml_unit_scaling_state/model.h +++ b/tests/resources/generator/cellml_unit_scaling_state/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/cellml_unit_scaling_state/model.py b/tests/resources/generator/cellml_unit_scaling_state/model.py index e8449b6d8..bcf2cc6cc 100644 --- a/tests/resources/generator/cellml_unit_scaling_state/model.py +++ b/tests/resources/generator/cellml_unit_scaling_state/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 2 @@ -39,7 +39,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): states[0] = 123.0 diff --git a/tests/resources/generator/cellml_unit_scaling_state_initialised_using_constant/model.c b/tests/resources/generator/cellml_unit_scaling_state_initialised_using_constant/model.c index 5503c36e7..72c727061 100644 --- a/tests/resources/generator/cellml_unit_scaling_state_initialised_using_constant/model.c +++ b/tests/resources/generator/cellml_unit_scaling_state_initialised_using_constant/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 2; const size_t VARIABLE_COUNT = 0; @@ -23,12 +23,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -36,7 +48,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { states[0] = 123.0; states[1] = 0.001*789.0; diff --git a/tests/resources/generator/cellml_unit_scaling_state_initialised_using_constant/model.h b/tests/resources/generator/cellml_unit_scaling_state_initialised_using_constant/model.h index a52bb97e2..3137b91f1 100644 --- a/tests/resources/generator/cellml_unit_scaling_state_initialised_using_constant/model.h +++ b/tests/resources/generator/cellml_unit_scaling_state_initialised_using_constant/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/cellml_unit_scaling_state_initialised_using_constant/model.py b/tests/resources/generator/cellml_unit_scaling_state_initialised_using_constant/model.py index b50eba090..f07685af6 100644 --- a/tests/resources/generator/cellml_unit_scaling_state_initialised_using_constant/model.py +++ b/tests/resources/generator/cellml_unit_scaling_state_initialised_using_constant/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 2 VARIABLE_COUNT = 0 @@ -38,7 +38,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): states[0] = 123.0 states[1] = 0.001*789.0 diff --git a/tests/resources/generator/cellml_unit_scaling_state_initialised_using_variable/model.c b/tests/resources/generator/cellml_unit_scaling_state_initialised_using_variable/model.c index 29af10b6f..37a2a556b 100644 --- a/tests/resources/generator/cellml_unit_scaling_state_initialised_using_variable/model.c +++ b/tests/resources/generator/cellml_unit_scaling_state_initialised_using_variable/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 2; const size_t VARIABLE_COUNT = 2; @@ -25,12 +25,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -38,7 +50,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { variables[0] = 123.0; variables[1] = 789.0; diff --git a/tests/resources/generator/cellml_unit_scaling_state_initialised_using_variable/model.h b/tests/resources/generator/cellml_unit_scaling_state_initialised_using_variable/model.h index 31244ce9e..05eed874d 100644 --- a/tests/resources/generator/cellml_unit_scaling_state_initialised_using_variable/model.h +++ b/tests/resources/generator/cellml_unit_scaling_state_initialised_using_variable/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/cellml_unit_scaling_state_initialised_using_variable/model.py b/tests/resources/generator/cellml_unit_scaling_state_initialised_using_variable/model.py index 5e61bb46a..bc6233809 100644 --- a/tests/resources/generator/cellml_unit_scaling_state_initialised_using_variable/model.py +++ b/tests/resources/generator/cellml_unit_scaling_state_initialised_using_variable/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 2 VARIABLE_COUNT = 2 @@ -40,7 +40,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): variables[0] = 123.0 variables[1] = 789.0 states[0] = variables[0] diff --git a/tests/resources/generator/cellml_unit_scaling_voi_direct/model.c b/tests/resources/generator/cellml_unit_scaling_voi_direct/model.c index 99840ce0e..1c8884b0f 100644 --- a/tests/resources/generator/cellml_unit_scaling_voi_direct/model.c +++ b/tests/resources/generator/cellml_unit_scaling_voi_direct/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 2; const size_t VARIABLE_COUNT = 0; @@ -23,12 +23,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -36,7 +48,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { states[0] = 3.0; states[1] = 5.0; diff --git a/tests/resources/generator/cellml_unit_scaling_voi_direct/model.h b/tests/resources/generator/cellml_unit_scaling_voi_direct/model.h index 9d284a1ed..caeb40bab 100644 --- a/tests/resources/generator/cellml_unit_scaling_voi_direct/model.h +++ b/tests/resources/generator/cellml_unit_scaling_voi_direct/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/cellml_unit_scaling_voi_direct/model.py b/tests/resources/generator/cellml_unit_scaling_voi_direct/model.py index 4795e6a01..25a75e71f 100644 --- a/tests/resources/generator/cellml_unit_scaling_voi_direct/model.py +++ b/tests/resources/generator/cellml_unit_scaling_voi_direct/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 2 VARIABLE_COUNT = 0 @@ -38,7 +38,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): states[0] = 3.0 states[1] = 5.0 diff --git a/tests/resources/generator/cellml_unit_scaling_voi_indirect/model.c b/tests/resources/generator/cellml_unit_scaling_voi_indirect/model.c index 37696b367..db2d1653e 100644 --- a/tests/resources/generator/cellml_unit_scaling_voi_indirect/model.c +++ b/tests/resources/generator/cellml_unit_scaling_voi_indirect/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 2; const size_t VARIABLE_COUNT = 0; @@ -23,12 +23,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -36,7 +48,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { states[0] = 3.0; states[1] = 7.0; diff --git a/tests/resources/generator/cellml_unit_scaling_voi_indirect/model.h b/tests/resources/generator/cellml_unit_scaling_voi_indirect/model.h index 9e2806859..d683c7fb0 100644 --- a/tests/resources/generator/cellml_unit_scaling_voi_indirect/model.h +++ b/tests/resources/generator/cellml_unit_scaling_voi_indirect/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/cellml_unit_scaling_voi_indirect/model.py b/tests/resources/generator/cellml_unit_scaling_voi_indirect/model.py index ea6dd01fa..91d0a5bb9 100644 --- a/tests/resources/generator/cellml_unit_scaling_voi_indirect/model.py +++ b/tests/resources/generator/cellml_unit_scaling_voi_indirect/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 2 VARIABLE_COUNT = 0 @@ -38,7 +38,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): states[0] = 3.0 states[1] = 7.0 diff --git a/tests/resources/generator/coverage/model.c b/tests/resources/generator/coverage/model.c deleted file mode 100644 index 0cb0623dc..000000000 --- a/tests/resources/generator/coverage/model.c +++ /dev/null @@ -1,507 +0,0 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ - -#include "model.h" - -#include -#include - -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; - -const size_t STATE_COUNT = 1; -const size_t VARIABLE_COUNT = 186; - -const VariableInfo VOI_INFO = {"t", "second", "my_component", VARIABLE_OF_INTEGRATION}; - -const VariableInfo STATE_INFO[] = { - {"x", "dimensionless", "my_component", STATE} -}; - -const VariableInfo VARIABLE_INFO[] = { - {"m", "dimensionless", "my_component", CONSTANT}, - {"n", "dimensionless", "my_component", CONSTANT}, - {"o", "dimensionless", "my_component", CONSTANT}, - {"p", "dimensionless", "my_component", CONSTANT}, - {"q", "dimensionless", "my_component", CONSTANT}, - {"r", "dimensionless", "my_component", CONSTANT}, - {"s", "dimensionless", "my_component", CONSTANT}, - {"eqnEq", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnEqCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnNeq", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnNeqCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLt", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLeq", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnGt", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnGeq", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAnd", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesLeftPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesLeftRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOr", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesLeftPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesLeftRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXor", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesLeftPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesLeftRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnNot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPlus", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPlusMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPlusParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPlusUnary", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinus", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinusParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinusParenthesesPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinusParenthesesPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinusUnary", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinusUnaryParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesRightTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesRightDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerSqrt", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerSqr", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerCube", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesLeftTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesLeftDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootSqrt", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootSqrtOther", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootCube", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesLeftTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesLeftDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAbs", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnExp", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLn", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLog", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLog2", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLog10", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLogCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCeiling", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnFloor", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMin", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMax", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMaxMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRem", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnSin", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCos", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTan", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnSec", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCsc", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnSinh", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCosh", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTanh", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnSech", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCsch", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCoth", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArcsin", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArccos", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArctan", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArcsec", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArccsc", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArccot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArcsinh", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArccosh", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArctanh", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArcsech", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArccsch", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArccoth", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPiecewisePiece", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPiecewisePieceOtherwise", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPiecewisePiecePiecePiece", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPiecewisePiecePiecePieceOtherwise", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnWithPiecewise", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCnInteger", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCnDouble", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCnIntegerWithExponent", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCnDoubleWithExponent", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTrue", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnFalse", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnExponentiale", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPi", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnInfinity", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnNotanumber", "dimensionless", "my_component", COMPUTED_CONSTANT} -}; - -double xor(double x, double y) -{ - return (x != 0.0) ^ (y != 0.0); -} - -double min(double x, double y) -{ - return (x < y)?x:y; -} - -double max(double x, double y) -{ - return (x > y)?x:y; -} - -double sec(double x) -{ - return 1.0/cos(x); -} - -double csc(double x) -{ - return 1.0/sin(x); -} - -double cot(double x) -{ - return 1.0/tan(x); -} - -double sech(double x) -{ - return 1.0/cosh(x); -} - -double csch(double x) -{ - return 1.0/sinh(x); -} - -double coth(double x) -{ - return 1.0/tanh(x); -} - -double asec(double x) -{ - return acos(1.0/x); -} - -double acsc(double x) -{ - return asin(1.0/x); -} - -double acot(double x) -{ - return atan(1.0/x); -} - -double asech(double x) -{ - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX-1.0)); -} - -double acsch(double x) -{ - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX+1.0)); -} - -double acoth(double x) -{ - double oneOverX = 1.0/x; - - return 0.5*log((1.0+oneOverX)/(1.0-oneOverX)); -} - -double * createStatesArray() -{ - return malloc(STATE_COUNT*sizeof(double)); -} - -double * createVariablesArray() -{ - return malloc(VARIABLE_COUNT*sizeof(double)); -} - -void deleteArray(double *array) -{ - free(array); -} - -void initialiseVariables(double *states, double *variables) -{ - variables[0] = 1.0; - variables[1] = 2.0; - variables[2] = 3.0; - variables[3] = 4.0; - variables[4] = 5.0; - variables[5] = 6.0; - variables[6] = 7.0; - variables[175] = 123.0; - variables[176] = 123.456789; - variables[177] = 123.0e99; - variables[178] = 123.456789e99; - variables[180] = 1.0; - variables[181] = 0.0; - variables[182] = 2.71828182845905; - variables[183] = 3.14159265358979; - variables[184] = INFINITY; - variables[185] = NAN; - states[0] = 0.0; -} - -void computeComputedConstants(double *variables) -{ - variables[7] = variables[0] == variables[1]; - variables[8] = variables[0]/(variables[1] == variables[1]); - variables[9] = variables[0] != variables[1]; - variables[10] = variables[0]/(variables[1] != variables[2]); - variables[11] = variables[0] < variables[1]; - variables[12] = variables[0] <= variables[1]; - variables[13] = variables[0] > variables[1]; - variables[14] = variables[0] >= variables[1]; - variables[15] = variables[0] && variables[1]; - variables[16] = variables[0] && variables[1] && variables[2]; - variables[17] = (variables[0] < variables[1]) && (variables[2] > variables[3]); - variables[18] = (variables[0]+variables[1]) && (variables[2] > variables[3]); - variables[19] = variables[0] && (variables[1] > variables[2]); - variables[20] = (variables[0]-variables[1]) && (variables[2] > variables[3]); - variables[21] = -variables[0] && (variables[1] > variables[2]); - variables[22] = pow(variables[0], variables[1]) && (variables[2] > variables[3]); - variables[23] = pow(variables[0], 1.0/variables[1]) && (variables[2] > variables[3]); - variables[24] = (variables[0] < variables[1]) && (variables[2]+variables[3]); - variables[25] = (variables[0] < variables[1]) && variables[2]; - variables[26] = (variables[0] < variables[1]) && (variables[2]-variables[3]); - variables[27] = (variables[0] < variables[1]) && -variables[2]; - variables[28] = (variables[0] < variables[1]) && pow(variables[2], variables[3]); - variables[29] = (variables[0] < variables[1]) && pow(variables[2], 1.0/variables[3]); - variables[30] = variables[0] || variables[1]; - variables[31] = variables[0] || variables[1] || variables[2]; - variables[32] = (variables[0] < variables[1]) || (variables[2] > variables[3]); - variables[33] = (variables[0]+variables[1]) || (variables[2] > variables[3]); - variables[34] = variables[0] || (variables[1] > variables[2]); - variables[35] = (variables[0]-variables[1]) || (variables[2] > variables[3]); - variables[36] = -variables[0] || (variables[1] > variables[2]); - variables[37] = pow(variables[0], variables[1]) || (variables[2] > variables[3]); - variables[38] = pow(variables[0], 1.0/variables[1]) || (variables[2] > variables[3]); - variables[39] = (variables[0] < variables[1]) || (variables[2]+variables[3]); - variables[40] = (variables[0] < variables[1]) || variables[2]; - variables[41] = (variables[0] < variables[1]) || (variables[2]-variables[3]); - variables[42] = (variables[0] < variables[1]) || -variables[2]; - variables[43] = (variables[0] < variables[1]) || pow(variables[2], variables[3]); - variables[44] = (variables[0] < variables[1]) || pow(variables[2], 1.0/variables[3]); - variables[45] = xor(variables[0], variables[1]); - variables[46] = xor(variables[0], xor(variables[1], variables[2])); - variables[47] = xor(variables[0] < variables[1], variables[2] > variables[3]); - variables[48] = xor(variables[0]+variables[1], variables[2] > variables[3]); - variables[49] = xor(variables[0], variables[1] > variables[2]); - variables[50] = xor(variables[0]-variables[1], variables[2] > variables[3]); - variables[51] = xor(-variables[0], variables[1] > variables[2]); - variables[52] = xor(pow(variables[0], variables[1]), variables[2] > variables[3]); - variables[53] = xor(pow(variables[0], 1.0/variables[1]), variables[2] > variables[3]); - variables[54] = xor(variables[0] < variables[1], variables[2]+variables[3]); - variables[55] = xor(variables[0] < variables[1], variables[2]); - variables[56] = xor(variables[0] < variables[1], variables[2]-variables[3]); - variables[57] = xor(variables[0] < variables[1], -variables[2]); - variables[58] = xor(variables[0] < variables[1], pow(variables[2], variables[3])); - variables[59] = xor(variables[0] < variables[1], pow(variables[2], 1.0/variables[3])); - variables[60] = !variables[0]; - variables[61] = variables[0]+variables[1]; - variables[62] = variables[0]+variables[1]+variables[2]; - variables[63] = (variables[0] < variables[1])+(variables[2] > variables[3]); - variables[64] = variables[0]; - variables[65] = variables[0]-variables[1]; - variables[66] = (variables[0] < variables[1])-(variables[2] > variables[3]); - variables[67] = (variables[0] < variables[1])-(variables[2]+variables[3]); - variables[68] = (variables[0] < variables[1])-variables[2]; - variables[69] = -variables[0]; - variables[70] = -(variables[0] < variables[1]); - variables[71] = variables[0]*variables[1]; - variables[72] = variables[0]*variables[1]*variables[2]; - variables[73] = (variables[0] < variables[1])*(variables[2] > variables[3]); - variables[74] = (variables[0]+variables[1])*(variables[2] > variables[3]); - variables[75] = variables[0]*(variables[1] > variables[2]); - variables[76] = (variables[0]-variables[1])*(variables[2] > variables[3]); - variables[77] = -variables[0]*(variables[1] > variables[2]); - variables[78] = (variables[0] < variables[1])*(variables[2]+variables[3]); - variables[79] = (variables[0] < variables[1])*variables[2]; - variables[80] = (variables[0] < variables[1])*(variables[2]-variables[3]); - variables[81] = (variables[0] < variables[1])*-variables[2]; - variables[82] = variables[0]/variables[1]; - variables[83] = (variables[0] < variables[1])/(variables[3] > variables[2]); - variables[84] = (variables[0]+variables[1])/(variables[3] > variables[2]); - variables[85] = variables[0]/(variables[2] > variables[1]); - variables[86] = (variables[0]-variables[1])/(variables[3] > variables[2]); - variables[87] = -variables[0]/(variables[2] > variables[1]); - variables[88] = (variables[0] < variables[1])/(variables[2]+variables[3]); - variables[89] = (variables[0] < variables[1])/variables[2]; - variables[90] = (variables[0] < variables[1])/(variables[2]-variables[3]); - variables[91] = (variables[0] < variables[1])/-variables[2]; - variables[92] = (variables[0] < variables[1])/(variables[2]*variables[3]); - variables[93] = (variables[0] < variables[1])/(variables[2]/variables[3]); - variables[94] = sqrt(variables[0]); - variables[95] = pow(variables[0], 2.0); - variables[96] = pow(variables[0], 3.0); - variables[97] = pow(variables[0], variables[1]); - variables[98] = pow(variables[0] < variables[1], variables[2] > variables[3]); - variables[99] = pow(variables[0]+variables[1], variables[2] > variables[3]); - variables[100] = pow(variables[0], variables[1] > variables[2]); - variables[101] = pow(variables[0]-variables[1], variables[2] > variables[3]); - variables[102] = pow(-variables[0], variables[1] > variables[2]); - variables[103] = pow(variables[0]*variables[1], variables[2] > variables[3]); - variables[104] = pow(variables[0]/variables[1], variables[2] > variables[3]); - variables[105] = pow(variables[0] < variables[1], variables[2]+variables[3]); - variables[106] = pow(variables[0] < variables[1], variables[2]); - variables[107] = pow(variables[0] < variables[1], variables[2]-variables[3]); - variables[108] = pow(variables[0] < variables[1], -variables[2]); - variables[109] = pow(variables[0] < variables[1], variables[2]*variables[3]); - variables[110] = pow(variables[0] < variables[1], variables[2]/variables[3]); - variables[111] = pow(variables[0] < variables[1], pow(variables[2], variables[3])); - variables[112] = pow(variables[0] < variables[1], pow(variables[2], 1.0/variables[3])); - variables[113] = sqrt(variables[0]); - variables[114] = sqrt(variables[0]); - variables[115] = pow(variables[0], 1.0/3.0); - variables[116] = pow(variables[0], 1.0/variables[1]); - variables[117] = pow(variables[0] < variables[1], 1.0/(variables[3] > variables[2])); - variables[118] = pow(variables[0]+variables[1], 1.0/(variables[3] > variables[2])); - variables[119] = pow(variables[0], 1.0/(variables[2] > variables[1])); - variables[120] = pow(variables[0]-variables[1], 1.0/(variables[3] > variables[2])); - variables[121] = pow(-variables[0], 1.0/(variables[2] > variables[1])); - variables[122] = pow(variables[0]*variables[1], 1.0/(variables[3] > variables[2])); - variables[123] = pow(variables[0]/variables[1], 1.0/(variables[3] > variables[2])); - variables[124] = pow(variables[0] < variables[1], 1.0/(variables[2]+variables[3])); - variables[125] = pow(variables[0] < variables[1], 1.0/variables[2]); - variables[126] = pow(variables[0] < variables[1], 1.0/(variables[2]-variables[3])); - variables[127] = pow(variables[0] < variables[1], 1.0/-variables[2]); - variables[128] = pow(variables[0] < variables[1], 1.0/(variables[2]*variables[3])); - variables[129] = pow(variables[0] < variables[1], 1.0/(variables[2]/variables[3])); - variables[130] = pow(variables[0] < variables[1], 1.0/pow(variables[2], variables[3])); - variables[131] = pow(variables[0] < variables[1], 1.0/pow(variables[2], 1.0/variables[3])); - variables[132] = fabs(variables[0]); - variables[133] = exp(variables[0]); - variables[134] = log(variables[0]); - variables[135] = log10(variables[0]); - variables[136] = log(variables[0])/log(2.0); - variables[137] = log10(variables[0]); - variables[138] = log(variables[0])/log(variables[1]); - variables[139] = ceil(variables[0]); - variables[140] = floor(variables[0]); - variables[141] = min(variables[0], variables[1]); - variables[142] = min(variables[0], min(variables[1], variables[2])); - variables[143] = max(variables[0], variables[1]); - variables[144] = max(variables[0], max(variables[1], variables[2])); - variables[145] = fmod(variables[0], variables[1]); - variables[146] = sin(variables[0]); - variables[147] = cos(variables[0]); - variables[148] = tan(variables[0]); - variables[149] = sec(variables[0]); - variables[150] = csc(variables[0]); - variables[151] = cot(variables[0]); - variables[152] = sinh(variables[0]); - variables[153] = cosh(variables[0]); - variables[154] = tanh(variables[0]); - variables[155] = sech(variables[0]); - variables[156] = csch(variables[0]); - variables[157] = coth(variables[0]); - variables[158] = asin(variables[0]); - variables[159] = acos(variables[0]); - variables[160] = atan(variables[0]); - variables[161] = asec(variables[0]); - variables[162] = acsc(variables[0]); - variables[163] = acot(variables[0]); - variables[164] = asinh(variables[0]); - variables[165] = acosh(variables[0]); - variables[166] = atanh(variables[0]/2.0); - variables[167] = asech(variables[0]); - variables[168] = acsch(variables[0]); - variables[169] = acoth(2.0*variables[0]); - variables[170] = (variables[0] > variables[1])?variables[0]:NAN; - variables[171] = (variables[0] > variables[1])?variables[0]:variables[2]; - variables[172] = (variables[0] > variables[1])?variables[0]:(variables[2] > variables[3])?variables[2]:(variables[4] > variables[5])?variables[4]:NAN; - variables[173] = (variables[0] > variables[1])?variables[0]:(variables[2] > variables[3])?variables[2]:(variables[4] > variables[5])?variables[4]:variables[6]; - variables[174] = 123.0+((variables[0] > variables[1])?variables[0]:NAN); - variables[179] = variables[0]; -} - -void computeRates(double voi, double *states, double *rates, double *variables) -{ - rates[0] = 1.0; -} - -void computeVariables(double voi, double *states, double *rates, double *variables) -{ -} diff --git a/tests/resources/generator/coverage/model.implementation.out b/tests/resources/generator/coverage/model.implementation.out deleted file mode 100644 index ea1c63267..000000000 --- a/tests/resources/generator/coverage/model.implementation.out +++ /dev/null @@ -1,301 +0,0 @@ -/* The content of this file was generated using a modified C profile of libCellML 0.4.0. */ - -double xor(double x, double y) -{ - return (x != 0.0) ^ (y != 0.0); -} - -double min(double x, double y) -{ - return (x < y)?x:y; -} - -double max(double x, double y) -{ - return (x > y)?x:y; -} - -double sec(double x) -{ - return 1.0/cos(x); -} - -double csc(double x) -{ - return 1.0/sin(x); -} - -double cot(double x) -{ - return 1.0/tan(x); -} - -double sech(double x) -{ - return 1.0/cosh(x); -} - -double csch(double x) -{ - return 1.0/sinh(x); -} - -double coth(double x) -{ - return 1.0/tanh(x); -} - -double asec(double x) -{ - return acos(1.0/x); -} - -double acsc(double x) -{ - return asin(1.0/x); -} - -double acot(double x) -{ - return atan(1.0/x); -} - -double asech(double x) -{ - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX-1.0)); -} - -double acsch(double x) -{ - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX+1.0)); -} - -double acoth(double x) -{ - double oneOverX = 1.0/x; - - return 0.5*log((1.0+oneOverX)/(1.0-oneOverX)); -} - -double * createStatesArray() -{ - return malloc(STATE_COUNT*sizeof(double)); -} - -double * createVariablesArray() -{ - return malloc(VARIABLE_COUNT*sizeof(double)); -} - -void deleteArray(double *array) -{ - free(array); -} - -void initialiseVariables(double *states, double *variables) -{ - variables[0] = 1.0; - variables[1] = 2.0; - variables[2] = 3.0; - variables[3] = 4.0; - variables[4] = 5.0; - variables[5] = 6.0; - variables[6] = 7.0; - variables[175] = 123.0; - variables[176] = 123.456789; - variables[177] = 123.0e99; - variables[178] = 123.456789e99; - variables[180] = 1.0; - variables[181] = 0.0; - variables[182] = 2.71828182845905; - variables[183] = 3.14159265358979; - variables[184] = INFINITY; - variables[185] = NAN; - states[0] = 0.0; -} - -void computeComputedConstants(double *variables) -{ - variables[7] = eq(variables[0], variables[1]); - variables[8] = variables[0]/eq(variables[1], variables[1]); - variables[9] = neq(variables[0], variables[1]); - variables[10] = variables[0]/neq(variables[1], variables[2]); - variables[11] = lt(variables[0], variables[1]); - variables[12] = leq(variables[0], variables[1]); - variables[13] = gt(variables[0], variables[1]); - variables[14] = geq(variables[0], variables[1]); - variables[15] = and(variables[0], variables[1]); - variables[16] = and(variables[0], and(variables[1], variables[2])); - variables[17] = and(lt(variables[0], variables[1]), gt(variables[2], variables[3])); - variables[18] = and(variables[0]+variables[1], gt(variables[2], variables[3])); - variables[19] = and(variables[0], gt(variables[1], variables[2])); - variables[20] = and(variables[0]-variables[1], gt(variables[2], variables[3])); - variables[21] = and(-variables[0], gt(variables[1], variables[2])); - variables[22] = and(pow(variables[0], variables[1]), gt(variables[2], variables[3])); - variables[23] = and(pow(variables[0], 1.0/variables[1]), gt(variables[2], variables[3])); - variables[24] = and(lt(variables[0], variables[1]), variables[2]+variables[3]); - variables[25] = and(lt(variables[0], variables[1]), variables[2]); - variables[26] = and(lt(variables[0], variables[1]), variables[2]-variables[3]); - variables[27] = and(lt(variables[0], variables[1]), -variables[2]); - variables[28] = and(lt(variables[0], variables[1]), pow(variables[2], variables[3])); - variables[29] = and(lt(variables[0], variables[1]), pow(variables[2], 1.0/variables[3])); - variables[30] = or(variables[0], variables[1]); - variables[31] = or(variables[0], or(variables[1], variables[2])); - variables[32] = or(lt(variables[0], variables[1]), gt(variables[2], variables[3])); - variables[33] = or(variables[0]+variables[1], gt(variables[2], variables[3])); - variables[34] = or(variables[0], gt(variables[1], variables[2])); - variables[35] = or(variables[0]-variables[1], gt(variables[2], variables[3])); - variables[36] = or(-variables[0], gt(variables[1], variables[2])); - variables[37] = or(pow(variables[0], variables[1]), gt(variables[2], variables[3])); - variables[38] = or(pow(variables[0], 1.0/variables[1]), gt(variables[2], variables[3])); - variables[39] = or(lt(variables[0], variables[1]), variables[2]+variables[3]); - variables[40] = or(lt(variables[0], variables[1]), variables[2]); - variables[41] = or(lt(variables[0], variables[1]), variables[2]-variables[3]); - variables[42] = or(lt(variables[0], variables[1]), -variables[2]); - variables[43] = or(lt(variables[0], variables[1]), pow(variables[2], variables[3])); - variables[44] = or(lt(variables[0], variables[1]), pow(variables[2], 1.0/variables[3])); - variables[45] = xor(variables[0], variables[1]); - variables[46] = xor(variables[0], xor(variables[1], variables[2])); - variables[47] = xor(lt(variables[0], variables[1]), gt(variables[2], variables[3])); - variables[48] = xor(variables[0]+variables[1], gt(variables[2], variables[3])); - variables[49] = xor(variables[0], gt(variables[1], variables[2])); - variables[50] = xor(variables[0]-variables[1], gt(variables[2], variables[3])); - variables[51] = xor(-variables[0], gt(variables[1], variables[2])); - variables[52] = xor(pow(variables[0], variables[1]), gt(variables[2], variables[3])); - variables[53] = xor(pow(variables[0], 1.0/variables[1]), gt(variables[2], variables[3])); - variables[54] = xor(lt(variables[0], variables[1]), variables[2]+variables[3]); - variables[55] = xor(lt(variables[0], variables[1]), variables[2]); - variables[56] = xor(lt(variables[0], variables[1]), variables[2]-variables[3]); - variables[57] = xor(lt(variables[0], variables[1]), -variables[2]); - variables[58] = xor(lt(variables[0], variables[1]), pow(variables[2], variables[3])); - variables[59] = xor(lt(variables[0], variables[1]), pow(variables[2], 1.0/variables[3])); - variables[60] = not(variables[0]); - variables[61] = variables[0]+variables[1]; - variables[62] = variables[0]+variables[1]+variables[2]; - variables[63] = lt(variables[0], variables[1])+gt(variables[2], variables[3]); - variables[64] = variables[0]; - variables[65] = variables[0]-variables[1]; - variables[66] = lt(variables[0], variables[1])-gt(variables[2], variables[3]); - variables[67] = lt(variables[0], variables[1])-(variables[2]+variables[3]); - variables[68] = lt(variables[0], variables[1])-variables[2]; - variables[69] = -variables[0]; - variables[70] = -lt(variables[0], variables[1]); - variables[71] = variables[0]*variables[1]; - variables[72] = variables[0]*variables[1]*variables[2]; - variables[73] = lt(variables[0], variables[1])*gt(variables[2], variables[3]); - variables[74] = (variables[0]+variables[1])*gt(variables[2], variables[3]); - variables[75] = variables[0]*gt(variables[1], variables[2]); - variables[76] = (variables[0]-variables[1])*gt(variables[2], variables[3]); - variables[77] = -variables[0]*gt(variables[1], variables[2]); - variables[78] = lt(variables[0], variables[1])*(variables[2]+variables[3]); - variables[79] = lt(variables[0], variables[1])*variables[2]; - variables[80] = lt(variables[0], variables[1])*(variables[2]-variables[3]); - variables[81] = lt(variables[0], variables[1])*-variables[2]; - variables[82] = variables[0]/variables[1]; - variables[83] = lt(variables[0], variables[1])/gt(variables[3], variables[2]); - variables[84] = (variables[0]+variables[1])/gt(variables[3], variables[2]); - variables[85] = variables[0]/gt(variables[2], variables[1]); - variables[86] = (variables[0]-variables[1])/gt(variables[3], variables[2]); - variables[87] = -variables[0]/gt(variables[2], variables[1]); - variables[88] = lt(variables[0], variables[1])/(variables[2]+variables[3]); - variables[89] = lt(variables[0], variables[1])/variables[2]; - variables[90] = lt(variables[0], variables[1])/(variables[2]-variables[3]); - variables[91] = lt(variables[0], variables[1])/-variables[2]; - variables[92] = lt(variables[0], variables[1])/(variables[2]*variables[3]); - variables[93] = lt(variables[0], variables[1])/(variables[2]/variables[3]); - variables[94] = sqrt(variables[0]); - variables[95] = pow(variables[0], 2.0); - variables[96] = pow(variables[0], 3.0); - variables[97] = pow(variables[0], variables[1]); - variables[98] = pow(lt(variables[0], variables[1]), gt(variables[2], variables[3])); - variables[99] = pow(variables[0]+variables[1], gt(variables[2], variables[3])); - variables[100] = pow(variables[0], gt(variables[1], variables[2])); - variables[101] = pow(variables[0]-variables[1], gt(variables[2], variables[3])); - variables[102] = pow(-variables[0], gt(variables[1], variables[2])); - variables[103] = pow(variables[0]*variables[1], gt(variables[2], variables[3])); - variables[104] = pow(variables[0]/variables[1], gt(variables[2], variables[3])); - variables[105] = pow(lt(variables[0], variables[1]), variables[2]+variables[3]); - variables[106] = pow(lt(variables[0], variables[1]), variables[2]); - variables[107] = pow(lt(variables[0], variables[1]), variables[2]-variables[3]); - variables[108] = pow(lt(variables[0], variables[1]), -variables[2]); - variables[109] = pow(lt(variables[0], variables[1]), variables[2]*variables[3]); - variables[110] = pow(lt(variables[0], variables[1]), variables[2]/variables[3]); - variables[111] = pow(lt(variables[0], variables[1]), pow(variables[2], variables[3])); - variables[112] = pow(lt(variables[0], variables[1]), pow(variables[2], 1.0/variables[3])); - variables[113] = sqrt(variables[0]); - variables[114] = sqrt(variables[0]); - variables[115] = pow(variables[0], 1.0/3.0); - variables[116] = pow(variables[0], 1.0/variables[1]); - variables[117] = pow(lt(variables[0], variables[1]), 1.0/gt(variables[3], variables[2])); - variables[118] = pow(variables[0]+variables[1], 1.0/gt(variables[3], variables[2])); - variables[119] = pow(variables[0], 1.0/gt(variables[2], variables[1])); - variables[120] = pow(variables[0]-variables[1], 1.0/gt(variables[3], variables[2])); - variables[121] = pow(-variables[0], 1.0/gt(variables[2], variables[1])); - variables[122] = pow(variables[0]*variables[1], 1.0/gt(variables[3], variables[2])); - variables[123] = pow(variables[0]/variables[1], 1.0/gt(variables[3], variables[2])); - variables[124] = pow(lt(variables[0], variables[1]), 1.0/(variables[2]+variables[3])); - variables[125] = pow(lt(variables[0], variables[1]), 1.0/variables[2]); - variables[126] = pow(lt(variables[0], variables[1]), 1.0/(variables[2]-variables[3])); - variables[127] = pow(lt(variables[0], variables[1]), 1.0/-variables[2]); - variables[128] = pow(lt(variables[0], variables[1]), 1.0/(variables[2]*variables[3])); - variables[129] = pow(lt(variables[0], variables[1]), 1.0/(variables[2]/variables[3])); - variables[130] = pow(lt(variables[0], variables[1]), 1.0/pow(variables[2], variables[3])); - variables[131] = pow(lt(variables[0], variables[1]), 1.0/pow(variables[2], 1.0/variables[3])); - variables[132] = fabs(variables[0]); - variables[133] = exp(variables[0]); - variables[134] = log(variables[0]); - variables[135] = log10(variables[0]); - variables[136] = log(variables[0])/log(2.0); - variables[137] = log10(variables[0]); - variables[138] = log(variables[0])/log(variables[1]); - variables[139] = ceil(variables[0]); - variables[140] = floor(variables[0]); - variables[141] = min(variables[0], variables[1]); - variables[142] = min(variables[0], min(variables[1], variables[2])); - variables[143] = max(variables[0], variables[1]); - variables[144] = max(variables[0], max(variables[1], variables[2])); - variables[145] = fmod(variables[0], variables[1]); - variables[146] = sin(variables[0]); - variables[147] = cos(variables[0]); - variables[148] = tan(variables[0]); - variables[149] = sec(variables[0]); - variables[150] = csc(variables[0]); - variables[151] = cot(variables[0]); - variables[152] = sinh(variables[0]); - variables[153] = cosh(variables[0]); - variables[154] = tanh(variables[0]); - variables[155] = sech(variables[0]); - variables[156] = csch(variables[0]); - variables[157] = coth(variables[0]); - variables[158] = asin(variables[0]); - variables[159] = acos(variables[0]); - variables[160] = atan(variables[0]); - variables[161] = asec(variables[0]); - variables[162] = acsc(variables[0]); - variables[163] = acot(variables[0]); - variables[164] = asinh(variables[0]); - variables[165] = acosh(variables[0]); - variables[166] = atanh(variables[0]/2.0); - variables[167] = asech(variables[0]); - variables[168] = acsch(variables[0]); - variables[169] = acoth(2.0*variables[0]); - variables[170] = (gt(variables[0], variables[1]))?variables[0]:NAN; - variables[171] = (gt(variables[0], variables[1]))?variables[0]:variables[2]; - variables[172] = (gt(variables[0], variables[1]))?variables[0]:(gt(variables[2], variables[3]))?variables[2]:(gt(variables[4], variables[5]))?variables[4]:NAN; - variables[173] = (gt(variables[0], variables[1]))?variables[0]:(gt(variables[2], variables[3]))?variables[2]:(gt(variables[4], variables[5]))?variables[4]:variables[6]; - variables[174] = 123.0+((gt(variables[0], variables[1]))?variables[0]:NAN); - variables[179] = variables[0]; -} - -void computeRates(double voi, double *states, double *rates, double *variables) -{ - rates[0] = 1.0; -} - -void computeVariables(double voi, double *states, double *rates, double *variables) -{ -} diff --git a/tests/resources/generator/coverage/model.modified.profile.c b/tests/resources/generator/coverage/model.modified.profile.c deleted file mode 100644 index eb0a42e86..000000000 --- a/tests/resources/generator/coverage/model.modified.profile.c +++ /dev/null @@ -1,507 +0,0 @@ -/* The content of this file was generated using a modified C profile of libCellML 0.4.0. */ - -#include "model.h" - -#include -#include - -const char VERSION[] = "0.3.0.post0"; -const char LIBCELLML_VERSION[] = "0.4.0"; - -const size_t STATE_COUNT = 1; -const size_t VARIABLE_COUNT = 186; - -const VariableInfo VOI_INFO = {"t", "second", "my_component", VARIABLE_OF_INTEGRATION}; - -const VariableInfo STATE_INFO[] = { - {"x", "dimensionless", "my_component", STATE} -}; - -const VariableInfo VARIABLE_INFO[] = { - {"m", "dimensionless", "my_component", CONSTANT}, - {"n", "dimensionless", "my_component", CONSTANT}, - {"o", "dimensionless", "my_component", CONSTANT}, - {"p", "dimensionless", "my_component", CONSTANT}, - {"q", "dimensionless", "my_component", CONSTANT}, - {"r", "dimensionless", "my_component", CONSTANT}, - {"s", "dimensionless", "my_component", CONSTANT}, - {"eqnEq", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnEqCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnNeq", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnNeqCoverageParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLt", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLeq", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnGt", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnGeq", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAnd", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesLeftPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesLeftRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAndParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOr", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesLeftPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesLeftRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnOrParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXor", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesLeftPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesLeftRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnXorParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnNot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPlus", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPlusMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPlusParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPlusUnary", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinus", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinusParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinusParenthesesPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinusParenthesesPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinusUnary", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinusUnaryParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTimesParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesRightTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnDivideParenthesesRightDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerSqrt", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerSqr", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerCube", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesLeftTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesLeftDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPowerParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootSqrt", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootSqrtOther", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootCube", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParentheses", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesLeftPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesLeftPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesLeftMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesLeftMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesLeftTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesLeftDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightPlusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightPlusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightMinusWith", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightMinusWithout", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightTimes", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightDivide", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightPower", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRootParenthesesRightRoot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnAbs", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnExp", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLn", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLog", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLog2", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLog10", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnLogCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCeiling", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnFloor", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMin", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMinMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMax", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnMaxMultiple", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnRem", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnSin", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCos", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTan", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnSec", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCsc", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnSinh", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCosh", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTanh", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnSech", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCsch", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCoth", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArcsin", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArccos", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArctan", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArcsec", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArccsc", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArccot", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArcsinh", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArccosh", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArctanh", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArcsech", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArccsch", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnArccoth", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPiecewisePiece", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPiecewisePieceOtherwise", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPiecewisePiecePiecePiece", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPiecewisePiecePiecePieceOtherwise", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnWithPiecewise", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCnInteger", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCnDouble", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCnIntegerWithExponent", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCnDoubleWithExponent", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnCi", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnTrue", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnFalse", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnExponentiale", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnPi", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnInfinity", "dimensionless", "my_component", COMPUTED_CONSTANT}, - {"eqnNotanumber", "dimensionless", "my_component", COMPUTED_CONSTANT} -}; - -double xor(double x, double y) -{ - return (x != 0.0) ^ (y != 0.0); -} - -double min(double x, double y) -{ - return (x < y)?x:y; -} - -double max(double x, double y) -{ - return (x > y)?x:y; -} - -double sec(double x) -{ - return 1.0/cos(x); -} - -double csc(double x) -{ - return 1.0/sin(x); -} - -double cot(double x) -{ - return 1.0/tan(x); -} - -double sech(double x) -{ - return 1.0/cosh(x); -} - -double csch(double x) -{ - return 1.0/sinh(x); -} - -double coth(double x) -{ - return 1.0/tanh(x); -} - -double asec(double x) -{ - return acos(1.0/x); -} - -double acsc(double x) -{ - return asin(1.0/x); -} - -double acot(double x) -{ - return atan(1.0/x); -} - -double asech(double x) -{ - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX-1.0)); -} - -double acsch(double x) -{ - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX+1.0)); -} - -double acoth(double x) -{ - double oneOverX = 1.0/x; - - return 0.5*log((1.0+oneOverX)/(1.0-oneOverX)); -} - -double * createStatesVector() -{ - return malloc(STATE_COUNT*sizeof(double)); -} - -double * createVariablesArray() -{ - return malloc(VARIABLE_COUNT*sizeof(double)); -} - -void deleteArray(double *array) -{ - free(array); -} - -void initialiseVariables(double *states, double *variables) -{ - variables[0] = 1.0; - variables[1] = 2.0; - variables[2] = 3.0; - variables[3] = 4.0; - variables[4] = 5.0; - variables[5] = 6.0; - variables[6] = 7.0; - variables[175] = 123.0; - variables[176] = 123.456789; - variables[177] = 123.0e99; - variables[178] = 123.456789e99; - variables[180] = 1.0; - variables[181] = 0.0; - variables[182] = 2.71828182845905; - variables[183] = 3.14159265358979; - variables[184] = INFINITY; - variables[185] = NAN; - states[0] = 0.0; -} - -void computeComputedConstants(double *variables) -{ - variables[7] = variables[0] == variables[1]; - variables[8] = variables[0]/(variables[1] == variables[1]); - variables[9] = variables[0] != variables[1]; - variables[10] = variables[0]/(variables[1] != variables[2]); - variables[11] = variables[0] < variables[1]; - variables[12] = variables[0] <= variables[1]; - variables[13] = variables[0] > variables[1]; - variables[14] = variables[0] >= variables[1]; - variables[15] = variables[0] && variables[1]; - variables[16] = variables[0] && variables[1] && variables[2]; - variables[17] = (variables[0] < variables[1]) && (variables[2] > variables[3]); - variables[18] = (variables[0]+variables[1]) && (variables[2] > variables[3]); - variables[19] = variables[0] && (variables[1] > variables[2]); - variables[20] = (variables[0]-variables[1]) && (variables[2] > variables[3]); - variables[21] = -variables[0] && (variables[1] > variables[2]); - variables[22] = pow(variables[0], variables[1]) && (variables[2] > variables[3]); - variables[23] = pow(variables[0], 1.0/variables[1]) && (variables[2] > variables[3]); - variables[24] = (variables[0] < variables[1]) && (variables[2]+variables[3]); - variables[25] = (variables[0] < variables[1]) && variables[2]; - variables[26] = (variables[0] < variables[1]) && (variables[2]-variables[3]); - variables[27] = (variables[0] < variables[1]) && -variables[2]; - variables[28] = (variables[0] < variables[1]) && pow(variables[2], variables[3]); - variables[29] = (variables[0] < variables[1]) && pow(variables[2], 1.0/variables[3]); - variables[30] = variables[0] || variables[1]; - variables[31] = variables[0] || variables[1] || variables[2]; - variables[32] = (variables[0] < variables[1]) || (variables[2] > variables[3]); - variables[33] = (variables[0]+variables[1]) || (variables[2] > variables[3]); - variables[34] = variables[0] || (variables[1] > variables[2]); - variables[35] = (variables[0]-variables[1]) || (variables[2] > variables[3]); - variables[36] = -variables[0] || (variables[1] > variables[2]); - variables[37] = pow(variables[0], variables[1]) || (variables[2] > variables[3]); - variables[38] = pow(variables[0], 1.0/variables[1]) || (variables[2] > variables[3]); - variables[39] = (variables[0] < variables[1]) || (variables[2]+variables[3]); - variables[40] = (variables[0] < variables[1]) || variables[2]; - variables[41] = (variables[0] < variables[1]) || (variables[2]-variables[3]); - variables[42] = (variables[0] < variables[1]) || -variables[2]; - variables[43] = (variables[0] < variables[1]) || pow(variables[2], variables[3]); - variables[44] = (variables[0] < variables[1]) || pow(variables[2], 1.0/variables[3]); - variables[45] = xor(variables[0], variables[1]); - variables[46] = xor(variables[0], xor(variables[1], variables[2])); - variables[47] = xor(variables[0] < variables[1], variables[2] > variables[3]); - variables[48] = xor(variables[0]+variables[1], variables[2] > variables[3]); - variables[49] = xor(variables[0], variables[1] > variables[2]); - variables[50] = xor(variables[0]-variables[1], variables[2] > variables[3]); - variables[51] = xor(-variables[0], variables[1] > variables[2]); - variables[52] = xor(pow(variables[0], variables[1]), variables[2] > variables[3]); - variables[53] = xor(pow(variables[0], 1.0/variables[1]), variables[2] > variables[3]); - variables[54] = xor(variables[0] < variables[1], variables[2]+variables[3]); - variables[55] = xor(variables[0] < variables[1], variables[2]); - variables[56] = xor(variables[0] < variables[1], variables[2]-variables[3]); - variables[57] = xor(variables[0] < variables[1], -variables[2]); - variables[58] = xor(variables[0] < variables[1], pow(variables[2], variables[3])); - variables[59] = xor(variables[0] < variables[1], pow(variables[2], 1.0/variables[3])); - variables[60] = !variables[0]; - variables[61] = variables[0]+variables[1]; - variables[62] = variables[0]+variables[1]+variables[2]; - variables[63] = (variables[0] < variables[1])+(variables[2] > variables[3]); - variables[64] = variables[0]; - variables[65] = variables[0]-variables[1]; - variables[66] = (variables[0] < variables[1])-(variables[2] > variables[3]); - variables[67] = (variables[0] < variables[1])-(variables[2]+variables[3]); - variables[68] = (variables[0] < variables[1])-variables[2]; - variables[69] = -variables[0]; - variables[70] = -(variables[0] < variables[1]); - variables[71] = variables[0]*variables[1]; - variables[72] = variables[0]*variables[1]*variables[2]; - variables[73] = (variables[0] < variables[1])*(variables[2] > variables[3]); - variables[74] = (variables[0]+variables[1])*(variables[2] > variables[3]); - variables[75] = variables[0]*(variables[1] > variables[2]); - variables[76] = (variables[0]-variables[1])*(variables[2] > variables[3]); - variables[77] = -variables[0]*(variables[1] > variables[2]); - variables[78] = (variables[0] < variables[1])*(variables[2]+variables[3]); - variables[79] = (variables[0] < variables[1])*variables[2]; - variables[80] = (variables[0] < variables[1])*(variables[2]-variables[3]); - variables[81] = (variables[0] < variables[1])*-variables[2]; - variables[82] = variables[0]/variables[1]; - variables[83] = (variables[0] < variables[1])/(variables[3] > variables[2]); - variables[84] = (variables[0]+variables[1])/(variables[3] > variables[2]); - variables[85] = variables[0]/(variables[2] > variables[1]); - variables[86] = (variables[0]-variables[1])/(variables[3] > variables[2]); - variables[87] = -variables[0]/(variables[2] > variables[1]); - variables[88] = (variables[0] < variables[1])/(variables[2]+variables[3]); - variables[89] = (variables[0] < variables[1])/variables[2]; - variables[90] = (variables[0] < variables[1])/(variables[2]-variables[3]); - variables[91] = (variables[0] < variables[1])/-variables[2]; - variables[92] = (variables[0] < variables[1])/(variables[2]*variables[3]); - variables[93] = (variables[0] < variables[1])/(variables[2]/variables[3]); - variables[94] = sqrt(variables[0]); - variables[95] = pow(variables[0], 2.0); - variables[96] = pow(variables[0], 3.0); - variables[97] = pow(variables[0], variables[1]); - variables[98] = pow(variables[0] < variables[1], variables[2] > variables[3]); - variables[99] = pow(variables[0]+variables[1], variables[2] > variables[3]); - variables[100] = pow(variables[0], variables[1] > variables[2]); - variables[101] = pow(variables[0]-variables[1], variables[2] > variables[3]); - variables[102] = pow(-variables[0], variables[1] > variables[2]); - variables[103] = pow(variables[0]*variables[1], variables[2] > variables[3]); - variables[104] = pow(variables[0]/variables[1], variables[2] > variables[3]); - variables[105] = pow(variables[0] < variables[1], variables[2]+variables[3]); - variables[106] = pow(variables[0] < variables[1], variables[2]); - variables[107] = pow(variables[0] < variables[1], variables[2]-variables[3]); - variables[108] = pow(variables[0] < variables[1], -variables[2]); - variables[109] = pow(variables[0] < variables[1], variables[2]*variables[3]); - variables[110] = pow(variables[0] < variables[1], variables[2]/variables[3]); - variables[111] = pow(variables[0] < variables[1], pow(variables[2], variables[3])); - variables[112] = pow(variables[0] < variables[1], pow(variables[2], 1.0/variables[3])); - variables[113] = sqrt(variables[0]); - variables[114] = sqrt(variables[0]); - variables[115] = pow(variables[0], 1.0/3.0); - variables[116] = pow(variables[0], 1.0/variables[1]); - variables[117] = pow(variables[0] < variables[1], 1.0/(variables[3] > variables[2])); - variables[118] = pow(variables[0]+variables[1], 1.0/(variables[3] > variables[2])); - variables[119] = pow(variables[0], 1.0/(variables[2] > variables[1])); - variables[120] = pow(variables[0]-variables[1], 1.0/(variables[3] > variables[2])); - variables[121] = pow(-variables[0], 1.0/(variables[2] > variables[1])); - variables[122] = pow(variables[0]*variables[1], 1.0/(variables[3] > variables[2])); - variables[123] = pow(variables[0]/variables[1], 1.0/(variables[3] > variables[2])); - variables[124] = pow(variables[0] < variables[1], 1.0/(variables[2]+variables[3])); - variables[125] = pow(variables[0] < variables[1], 1.0/variables[2]); - variables[126] = pow(variables[0] < variables[1], 1.0/(variables[2]-variables[3])); - variables[127] = pow(variables[0] < variables[1], 1.0/-variables[2]); - variables[128] = pow(variables[0] < variables[1], 1.0/(variables[2]*variables[3])); - variables[129] = pow(variables[0] < variables[1], 1.0/(variables[2]/variables[3])); - variables[130] = pow(variables[0] < variables[1], 1.0/pow(variables[2], variables[3])); - variables[131] = pow(variables[0] < variables[1], 1.0/pow(variables[2], 1.0/variables[3])); - variables[132] = fabs(variables[0]); - variables[133] = exp(variables[0]); - variables[134] = log(variables[0]); - variables[135] = log10(variables[0]); - variables[136] = log(variables[0])/log(2.0); - variables[137] = log10(variables[0]); - variables[138] = log(variables[0])/log(variables[1]); - variables[139] = ceil(variables[0]); - variables[140] = floor(variables[0]); - variables[141] = min(variables[0], variables[1]); - variables[142] = min(variables[0], min(variables[1], variables[2])); - variables[143] = max(variables[0], variables[1]); - variables[144] = max(variables[0], max(variables[1], variables[2])); - variables[145] = fmod(variables[0], variables[1]); - variables[146] = sin(variables[0]); - variables[147] = cos(variables[0]); - variables[148] = tan(variables[0]); - variables[149] = sec(variables[0]); - variables[150] = csc(variables[0]); - variables[151] = cot(variables[0]); - variables[152] = sinh(variables[0]); - variables[153] = cosh(variables[0]); - variables[154] = tanh(variables[0]); - variables[155] = sech(variables[0]); - variables[156] = csch(variables[0]); - variables[157] = coth(variables[0]); - variables[158] = asin(variables[0]); - variables[159] = acos(variables[0]); - variables[160] = atan(variables[0]); - variables[161] = asec(variables[0]); - variables[162] = acsc(variables[0]); - variables[163] = acot(variables[0]); - variables[164] = asinh(variables[0]); - variables[165] = acosh(variables[0]); - variables[166] = atanh(variables[0]/2.0); - variables[167] = asech(variables[0]); - variables[168] = acsch(variables[0]); - variables[169] = acoth(2.0*variables[0]); - variables[170] = (variables[0] > variables[1])?variables[0]:NAN; - variables[171] = (variables[0] > variables[1])?variables[0]:variables[2]; - variables[172] = (variables[0] > variables[1])?variables[0]:(variables[2] > variables[3])?variables[2]:(variables[4] > variables[5])?variables[4]:NAN; - variables[173] = (variables[0] > variables[1])?variables[0]:(variables[2] > variables[3])?variables[2]:(variables[4] > variables[5])?variables[4]:variables[6]; - variables[174] = 123.0+((variables[0] > variables[1])?variables[0]:NAN); - variables[179] = variables[0]; -} - -void computeRates(double voi, double *states, double *rates, double *variables) -{ - rates[0] = 1.0; -} - -void computeVariables(double voi, double *states, double *rates, double *variables) -{ -} diff --git a/tests/resources/generator/coverage/model.out b/tests/resources/generator/coverage/model.out deleted file mode 100644 index 337b75a3c..000000000 --- a/tests/resources/generator/coverage/model.out +++ /dev/null @@ -1,279 +0,0 @@ -/* The content of this file was generated using a modified C profile of libCellML 0.4.0. */ - -#include "customheaderfile.h" - -double min(double x, double y) -{ - return (x < y)?x:y; -} - -double max(double x, double y) -{ - return (x > y)?x:y; -} - -double sec(double x) -{ - return 1.0/cos(x); -} - -double csc(double x) -{ - return 1.0/sin(x); -} - -double cot(double x) -{ - return 1.0/tan(x); -} - -double sech(double x) -{ - return 1.0/cosh(x); -} - -double csch(double x) -{ - return 1.0/sinh(x); -} - -double coth(double x) -{ - return 1.0/tanh(x); -} - -double asec(double x) -{ - return acos(1.0/x); -} - -double acsc(double x) -{ - return asin(1.0/x); -} - -double acot(double x) -{ - return atan(1.0/x); -} - -double asech(double x) -{ - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX-1.0)); -} - -double acsch(double x) -{ - double oneOverX = 1.0/x; - - return log(oneOverX+sqrt(oneOverX*oneOverX+1.0)); -} - -double acoth(double x) -{ - double oneOverX = 1.0/x; - - return 0.5*log((1.0+oneOverX)/(1.0-oneOverX)); -} - -void initialiseVariables(double *states, double *variables) -{ - variables[0] = 1.0; - variables[1] = 2.0; - variables[2] = 3.0; - variables[3] = 4.0; - variables[4] = 5.0; - variables[5] = 6.0; - variables[6] = 7.0; - variables[175] = 123.0; - variables[176] = 123.456789; - variables[177] = 123.0e99; - variables[178] = 123.456789e99; - variables[180] = 1.0; - variables[181] = 0.0; - variables[182] = 2.71828182845905; - variables[183] = 3.14159265358979; - variables[184] = INFINITY; - variables[185] = NAN; - states[0] = 0.0; -} - -void computeComputedConstants(double *variables) -{ - variables[7] = variables[0] == variables[1]; - variables[8] = variables[0]/(variables[1] == variables[1]); - variables[9] = variables[0] != variables[1]; - variables[10] = variables[0]/(variables[1] != variables[2]); - variables[11] = variables[0] < variables[1]; - variables[12] = variables[0] <= variables[1]; - variables[13] = variables[0] > variables[1]; - variables[14] = variables[0] >= variables[1]; - variables[15] = variables[0] && variables[1]; - variables[16] = variables[0] && variables[1] && variables[2]; - variables[17] = (variables[0] < variables[1]) && (variables[2] > variables[3]); - variables[18] = (variables[0]+variables[1]) && (variables[2] > variables[3]); - variables[19] = variables[0] && (variables[1] > variables[2]); - variables[20] = (variables[0]-variables[1]) && (variables[2] > variables[3]); - variables[21] = -variables[0] && (variables[1] > variables[2]); - variables[22] = (variables[0]^^variables[1]) && (variables[2] > variables[3]); - variables[23] = (variables[0]^^(1.0/variables[1])) && (variables[2] > variables[3]); - variables[24] = (variables[0] < variables[1]) && (variables[2]+variables[3]); - variables[25] = (variables[0] < variables[1]) && variables[2]; - variables[26] = (variables[0] < variables[1]) && (variables[2]-variables[3]); - variables[27] = (variables[0] < variables[1]) && -variables[2]; - variables[28] = (variables[0] < variables[1]) && (variables[2]^^variables[3]); - variables[29] = (variables[0] < variables[1]) && (variables[2]^^(1.0/variables[3])); - variables[30] = variables[0] || variables[1]; - variables[31] = variables[0] || variables[1] || variables[2]; - variables[32] = (variables[0] < variables[1]) || (variables[2] > variables[3]); - variables[33] = (variables[0]+variables[1]) || (variables[2] > variables[3]); - variables[34] = variables[0] || (variables[1] > variables[2]); - variables[35] = (variables[0]-variables[1]) || (variables[2] > variables[3]); - variables[36] = -variables[0] || (variables[1] > variables[2]); - variables[37] = (variables[0]^^variables[1]) || (variables[2] > variables[3]); - variables[38] = (variables[0]^^(1.0/variables[1])) || (variables[2] > variables[3]); - variables[39] = (variables[0] < variables[1]) || (variables[2]+variables[3]); - variables[40] = (variables[0] < variables[1]) || variables[2]; - variables[41] = (variables[0] < variables[1]) || (variables[2]-variables[3]); - variables[42] = (variables[0] < variables[1]) || -variables[2]; - variables[43] = (variables[0] < variables[1]) || (variables[2]^^variables[3]); - variables[44] = (variables[0] < variables[1]) || (variables[2]^^(1.0/variables[3])); - variables[45] = variables[0]^variables[1]; - variables[46] = variables[0]^variables[1]^variables[2]; - variables[47] = (variables[0] < variables[1])^(variables[2] > variables[3]); - variables[48] = (variables[0]+variables[1])^(variables[2] > variables[3]); - variables[49] = variables[0]^(variables[1] > variables[2]); - variables[50] = (variables[0]-variables[1])^(variables[2] > variables[3]); - variables[51] = -variables[0]^(variables[1] > variables[2]); - variables[52] = (variables[0]^^variables[1])^(variables[2] > variables[3]); - variables[53] = (variables[0]^^(1.0/variables[1]))^(variables[2] > variables[3]); - variables[54] = (variables[0] < variables[1])^(variables[2]+variables[3]); - variables[55] = (variables[0] < variables[1])^variables[2]; - variables[56] = (variables[0] < variables[1])^(variables[2]-variables[3]); - variables[57] = (variables[0] < variables[1])^-variables[2]; - variables[58] = (variables[0] < variables[1])^(variables[2]^^variables[3]); - variables[59] = (variables[0] < variables[1])^(variables[2]^^(1.0/variables[3])); - variables[60] = !variables[0]; - variables[61] = variables[0]+variables[1]; - variables[62] = variables[0]+variables[1]+variables[2]; - variables[63] = (variables[0] < variables[1])+(variables[2] > variables[3]); - variables[64] = variables[0]; - variables[65] = variables[0]-variables[1]; - variables[66] = (variables[0] < variables[1])-(variables[2] > variables[3]); - variables[67] = (variables[0] < variables[1])-(variables[2]+variables[3]); - variables[68] = (variables[0] < variables[1])-variables[2]; - variables[69] = -variables[0]; - variables[70] = -(variables[0] < variables[1]); - variables[71] = variables[0]*variables[1]; - variables[72] = variables[0]*variables[1]*variables[2]; - variables[73] = (variables[0] < variables[1])*(variables[2] > variables[3]); - variables[74] = (variables[0]+variables[1])*(variables[2] > variables[3]); - variables[75] = variables[0]*(variables[1] > variables[2]); - variables[76] = (variables[0]-variables[1])*(variables[2] > variables[3]); - variables[77] = -variables[0]*(variables[1] > variables[2]); - variables[78] = (variables[0] < variables[1])*(variables[2]+variables[3]); - variables[79] = (variables[0] < variables[1])*variables[2]; - variables[80] = (variables[0] < variables[1])*(variables[2]-variables[3]); - variables[81] = (variables[0] < variables[1])*-variables[2]; - variables[82] = variables[0]/variables[1]; - variables[83] = (variables[0] < variables[1])/(variables[3] > variables[2]); - variables[84] = (variables[0]+variables[1])/(variables[3] > variables[2]); - variables[85] = variables[0]/(variables[2] > variables[1]); - variables[86] = (variables[0]-variables[1])/(variables[3] > variables[2]); - variables[87] = -variables[0]/(variables[2] > variables[1]); - variables[88] = (variables[0] < variables[1])/(variables[2]+variables[3]); - variables[89] = (variables[0] < variables[1])/variables[2]; - variables[90] = (variables[0] < variables[1])/(variables[2]-variables[3]); - variables[91] = (variables[0] < variables[1])/-variables[2]; - variables[92] = (variables[0] < variables[1])/(variables[2]*variables[3]); - variables[93] = (variables[0] < variables[1])/(variables[2]/variables[3]); - variables[94] = sqrt(variables[0]); - variables[95] = sqr(variables[0]); - variables[96] = variables[0]^^3.0; - variables[97] = variables[0]^^variables[1]; - variables[98] = (variables[0] < variables[1])^^(variables[2] > variables[3]); - variables[99] = (variables[0]+variables[1])^^(variables[2] > variables[3]); - variables[100] = variables[0]^^(variables[1] > variables[2]); - variables[101] = (variables[0]-variables[1])^^(variables[2] > variables[3]); - variables[102] = (-variables[0])^^(variables[1] > variables[2]); - variables[103] = (variables[0]*variables[1])^^(variables[2] > variables[3]); - variables[104] = (variables[0]/variables[1])^^(variables[2] > variables[3]); - variables[105] = (variables[0] < variables[1])^^(variables[2]+variables[3]); - variables[106] = (variables[0] < variables[1])^^variables[2]; - variables[107] = (variables[0] < variables[1])^^variables[2]-variables[3]; - variables[108] = (variables[0] < variables[1])^^-variables[2]; - variables[109] = (variables[0] < variables[1])^^(variables[2]*variables[3]); - variables[110] = (variables[0] < variables[1])^^(variables[2]/variables[3]); - variables[111] = (variables[0] < variables[1])^^(variables[2]^^variables[3]); - variables[112] = (variables[0] < variables[1])^^(variables[2]^^(1.0/variables[3])); - variables[113] = sqrt(variables[0]); - variables[114] = sqrt(variables[0]); - variables[115] = variables[0]^^(1.0/3.0); - variables[116] = variables[0]^^(1.0/variables[1]); - variables[117] = (variables[0] < variables[1])^^(1.0/(variables[3] > variables[2])); - variables[118] = (variables[0]+variables[1])^^(1.0/(variables[3] > variables[2])); - variables[119] = variables[0]^^(1.0/(variables[2] > variables[1])); - variables[120] = (variables[0]-variables[1])^^(1.0/(variables[3] > variables[2])); - variables[121] = (-variables[0])^^(1.0/(variables[2] > variables[1])); - variables[122] = (variables[0]*variables[1])^^(1.0/(variables[3] > variables[2])); - variables[123] = (variables[0]/variables[1])^^(1.0/(variables[3] > variables[2])); - variables[124] = (variables[0] < variables[1])^^(1.0/(variables[2]+variables[3])); - variables[125] = (variables[0] < variables[1])^^(1.0/variables[2]); - variables[126] = (variables[0] < variables[1])^^(1.0/(variables[2]-variables[3])); - variables[127] = (variables[0] < variables[1])^^(1.0/(-variables[2])); - variables[128] = (variables[0] < variables[1])^^(1.0/(variables[2]*variables[3])); - variables[129] = (variables[0] < variables[1])^^(1.0/(variables[2]/variables[3])); - variables[130] = (variables[0] < variables[1])^^(1.0/(variables[2]^^variables[3])); - variables[131] = (variables[0] < variables[1])^^(1.0/(variables[2]^^(1.0/variables[3]))); - variables[132] = fabs(variables[0]); - variables[133] = exp(variables[0]); - variables[134] = log(variables[0]); - variables[135] = log10(variables[0]); - variables[136] = log(variables[0])/log(2.0); - variables[137] = log10(variables[0]); - variables[138] = log(variables[0])/log(variables[1]); - variables[139] = ceil(variables[0]); - variables[140] = floor(variables[0]); - variables[141] = min(variables[0], variables[1]); - variables[142] = min(variables[0], min(variables[1], variables[2])); - variables[143] = max(variables[0], variables[1]); - variables[144] = max(variables[0], max(variables[1], variables[2])); - variables[145] = fmod(variables[0], variables[1]); - variables[146] = sin(variables[0]); - variables[147] = cos(variables[0]); - variables[148] = tan(variables[0]); - variables[149] = sec(variables[0]); - variables[150] = csc(variables[0]); - variables[151] = cot(variables[0]); - variables[152] = sinh(variables[0]); - variables[153] = cosh(variables[0]); - variables[154] = tanh(variables[0]); - variables[155] = sech(variables[0]); - variables[156] = csch(variables[0]); - variables[157] = coth(variables[0]); - variables[158] = asin(variables[0]); - variables[159] = acos(variables[0]); - variables[160] = atan(variables[0]); - variables[161] = asec(variables[0]); - variables[162] = acsc(variables[0]); - variables[163] = acot(variables[0]); - variables[164] = asinh(variables[0]); - variables[165] = acosh(variables[0]); - variables[166] = atanh(variables[0]/2.0); - variables[167] = asech(variables[0]); - variables[168] = acsch(variables[0]); - variables[169] = acoth(2.0*variables[0]); - variables[170] = piecewise(variables[0] > variables[1], variables[0], NAN); - variables[171] = piecewise(variables[0] > variables[1], variables[0], variables[2]); - variables[172] = piecewise(variables[0] > variables[1], variables[0], piecewise(variables[2] > variables[3], variables[2], piecewise(variables[4] > variables[5], variables[4], NAN))); - variables[173] = piecewise(variables[0] > variables[1], variables[0], piecewise(variables[2] > variables[3], variables[2], piecewise(variables[4] > variables[5], variables[4], variables[6]))); - variables[174] = 123.0+piecewise(variables[0] > variables[1], variables[0], NAN); - variables[179] = variables[0]; -} - -void computeRates(double voi, double *states, double *rates, double *variables) -{ - rates[0] = 1.0; -} diff --git a/tests/resources/generator/dae_cellml_1_1_model/model.c b/tests/resources/generator/dae_cellml_1_1_model/model.c new file mode 100644 index 000000000..766739ee2 --- /dev/null +++ b/tests/resources/generator/dae_cellml_1_1_model/model.c @@ -0,0 +1,154 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t STATE_COUNT = 2; +const size_t VARIABLE_COUNT = 10; + +const VariableInfo VOI_INFO = {"t", "second", "main", VARIABLE_OF_INTEGRATION}; + +const VariableInfo STATE_INFO[] = { + {"q_1", "coulomb", "main", STATE}, + {"v_3", "C_per_s", "main", STATE} +}; + +const VariableInfo VARIABLE_INFO[] = { + {"v_1", "C_per_s", "main", ALGEBRAIC}, + {"v_in", "C_per_s", "main", CONSTANT}, + {"v_2", "C_per_s", "main", ALGEBRAIC}, + {"v_out", "C_per_s", "main", CONSTANT}, + {"u_1", "J_per_C", "main", ALGEBRAIC}, + {"u_2", "J_per_C", "main", ALGEBRAIC}, + {"u_3", "J_per_C", "main", ALGEBRAIC}, + {"C", "C2_per_J", "main", CONSTANT}, + {"R", "Js_per_C2", "main", CONSTANT}, + {"L", "Js2_per_C2", "main", CONSTANT} +}; + +double * createStatesArray() +{ + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +typedef struct { + double voi; + double *states; + double *rates; + double *variables; +} RootFindingInfo; + +extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *), + double *u, int n, void *data); + +void objectiveFunction0(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[0] = u[0]; + + f[0] = variables[1]-(variables[0]+variables[2]); +} + +void findRoot0(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[0]; + + nlaSolve(objectiveFunction0, u, 1, &rfi); + + variables[0] = u[0]; +} + +void objectiveFunction1(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[6] = u[0]; + + f[0] = variables[4]-(variables[5]+variables[6]); +} + +void findRoot1(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[6]; + + nlaSolve(objectiveFunction1, u, 1, &rfi); + + variables[6] = u[0]; +} + +void initialiseVariables(double *states, double *rates, double *variables) +{ + variables[0] = 0.0; + variables[1] = 1.0; + variables[3] = 1.0; + variables[6] = 0.0; + variables[7] = 20.0; + variables[8] = 2.0; + variables[9] = 10.0; + states[0] = 1.0; + states[1] = 0.0; +} + +void computeComputedConstants(double *variables) +{ +} + +void computeRates(double voi, double *states, double *rates, double *variables) +{ + variables[2] = states[1]+variables[3]; + findRoot0(voi, states, rates, variables); + rates[0] = variables[0]; + variables[4] = states[0]/variables[7]; + variables[5] = variables[8]*variables[2]; + findRoot1(voi, states, rates, variables); + rates[1] = variables[6]/variables[9]; +} + +void computeVariables(double voi, double *states, double *rates, double *variables) +{ + variables[2] = states[1]+variables[3]; + findRoot0(voi, states, rates, variables); + variables[4] = states[0]/variables[7]; + variables[5] = variables[8]*variables[2]; + findRoot1(voi, states, rates, variables); +} diff --git a/tests/resources/generator/dae_cellml_1_1_model/model.cellml b/tests/resources/generator/dae_cellml_1_1_model/model.cellml new file mode 100644 index 000000000..3cf399427 --- /dev/null +++ b/tests/resources/generator/dae_cellml_1_1_model/model.cellml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + t + + q_1 + + v_1 + + + + v_in + + + v_1 + v_2 + + + + + v_2 + + + v_3 + v_out + + + + + u_1 + + + u_2 + u_3 + + + + + + u_1 + + + q_1 + C + + + + + u_2 + + + R + v_2 + + + + + + + + t + + v_3 + + + + u_3 + L + + + + + diff --git a/tests/resources/generator/dae_cellml_1_1_model/model.h b/tests/resources/generator/dae_cellml_1_1_model/model.h new file mode 100644 index 000000000..0a6670a37 --- /dev/null +++ b/tests/resources/generator/dae_cellml_1_1_model/model.h @@ -0,0 +1,39 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t STATE_COUNT; +extern const size_t VARIABLE_COUNT; + +typedef enum { + VARIABLE_OF_INTEGRATION, + STATE, + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC +} VariableType; + +typedef struct { + char name[6]; + char units[11]; + char component[5]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VOI_INFO; +extern const VariableInfo STATE_INFO[]; +extern const VariableInfo VARIABLE_INFO[]; + +double * createStatesArray(); +double * createVariablesArray(); +void deleteArray(double *array); + +void initialiseVariables(double *states, double *rates, double *variables); +void computeComputedConstants(double *variables); +void computeRates(double voi, double *states, double *rates, double *variables); +void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/dae_cellml_1_1_model/model.py b/tests/resources/generator/dae_cellml_1_1_model/model.py new file mode 100644 index 000000000..3dc413e02 --- /dev/null +++ b/tests/resources/generator/dae_cellml_1_1_model/model.py @@ -0,0 +1,127 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +STATE_COUNT = 2 +VARIABLE_COUNT = 10 + + +class VariableType(Enum): + VARIABLE_OF_INTEGRATION = 0 + STATE = 1 + CONSTANT = 2 + COMPUTED_CONSTANT = 3 + ALGEBRAIC = 4 + + +VOI_INFO = {"name": "t", "units": "second", "component": "main", "type": VariableType.VARIABLE_OF_INTEGRATION} + +STATE_INFO = [ + {"name": "q_1", "units": "coulomb", "component": "main", "type": VariableType.STATE}, + {"name": "v_3", "units": "C_per_s", "component": "main", "type": VariableType.STATE} +] + +VARIABLE_INFO = [ + {"name": "v_1", "units": "C_per_s", "component": "main", "type": VariableType.ALGEBRAIC}, + {"name": "v_in", "units": "C_per_s", "component": "main", "type": VariableType.CONSTANT}, + {"name": "v_2", "units": "C_per_s", "component": "main", "type": VariableType.ALGEBRAIC}, + {"name": "v_out", "units": "C_per_s", "component": "main", "type": VariableType.CONSTANT}, + {"name": "u_1", "units": "J_per_C", "component": "main", "type": VariableType.ALGEBRAIC}, + {"name": "u_2", "units": "J_per_C", "component": "main", "type": VariableType.ALGEBRAIC}, + {"name": "u_3", "units": "J_per_C", "component": "main", "type": VariableType.ALGEBRAIC}, + {"name": "C", "units": "C2_per_J", "component": "main", "type": VariableType.CONSTANT}, + {"name": "R", "units": "Js_per_C2", "component": "main", "type": VariableType.CONSTANT}, + {"name": "L", "units": "Js2_per_C2", "component": "main", "type": VariableType.CONSTANT} +] + + +def create_states_array(): + return [nan]*STATE_COUNT + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +from nlasolver import nla_solve + + +def objective_function_0(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[0] = u[0] + + f[0] = variables[1]-(variables[0]+variables[2]) + + +def find_root_0(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[0] + + u = nla_solve(objective_function_0, u, 1, [voi, states, rates, variables]) + + variables[0] = u[0] + + +def objective_function_1(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[6] = u[0] + + f[0] = variables[4]-(variables[5]+variables[6]) + + +def find_root_1(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[6] + + u = nla_solve(objective_function_1, u, 1, [voi, states, rates, variables]) + + variables[6] = u[0] + + +def initialise_variables(states, rates, variables): + variables[0] = 0.0 + variables[1] = 1.0 + variables[3] = 1.0 + variables[6] = 0.0 + variables[7] = 20.0 + variables[8] = 2.0 + variables[9] = 10.0 + states[0] = 1.0 + states[1] = 0.0 + + +def compute_computed_constants(variables): + pass + + +def compute_rates(voi, states, rates, variables): + variables[2] = states[1]+variables[3] + find_root_0(voi, states, rates, variables) + rates[0] = variables[0] + variables[4] = states[0]/variables[7] + variables[5] = variables[8]*variables[2] + find_root_1(voi, states, rates, variables) + rates[1] = variables[6]/variables[9] + + +def compute_variables(voi, states, rates, variables): + variables[2] = states[1]+variables[3] + find_root_0(voi, states, rates, variables) + variables[4] = states[0]/variables[7] + variables[5] = variables[8]*variables[2] + find_root_1(voi, states, rates, variables) diff --git a/tests/resources/generator/dependent_eqns/model.c b/tests/resources/generator/dependent_eqns/model.c index 2520dcb0a..099a54928 100644 --- a/tests/resources/generator/dependent_eqns/model.c +++ b/tests/resources/generator/dependent_eqns/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 2; @@ -18,18 +18,30 @@ const VariableInfo STATE_INFO[] = { }; const VariableInfo VARIABLE_INFO[] = { - {"b", "second", "my_component", ALGEBRAIC}, - {"a", "second", "my_component", ALGEBRAIC} + {"a", "second", "my_component", ALGEBRAIC}, + {"b", "second", "my_component", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -37,7 +49,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { states[0] = 0.0; } @@ -53,6 +65,6 @@ void computeRates(double voi, double *states, double *rates, double *variables) void computeVariables(double voi, double *states, double *rates, double *variables) { - variables[0] = 2.0*voi; - variables[1] = 3.0*variables[0]; + variables[1] = 2.0*voi; + variables[0] = 3.0*variables[1]; } diff --git a/tests/resources/generator/dependent_eqns/model.h b/tests/resources/generator/dependent_eqns/model.h index f80915c4c..762e2e457 100644 --- a/tests/resources/generator/dependent_eqns/model.h +++ b/tests/resources/generator/dependent_eqns/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/dependent_eqns/model.py b/tests/resources/generator/dependent_eqns/model.py index cb59f2fd6..21f76ea6b 100644 --- a/tests/resources/generator/dependent_eqns/model.py +++ b/tests/resources/generator/dependent_eqns/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 2 @@ -26,8 +26,8 @@ class VariableType(Enum): ] VARIABLE_INFO = [ - {"name": "b", "units": "second", "component": "my_component", "type": VariableType.ALGEBRAIC}, - {"name": "a", "units": "second", "component": "my_component", "type": VariableType.ALGEBRAIC} + {"name": "a", "units": "second", "component": "my_component", "type": VariableType.ALGEBRAIC}, + {"name": "b", "units": "second", "component": "my_component", "type": VariableType.ALGEBRAIC} ] @@ -39,7 +39,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): states[0] = 0.0 @@ -52,5 +52,5 @@ def compute_rates(voi, states, rates, variables): def compute_variables(voi, states, rates, variables): - variables[0] = 2.0*voi - variables[1] = 3.0*variables[0] + variables[1] = 2.0*voi + variables[0] = 3.0*variables[1] diff --git a/tests/resources/generator/fabbri_fantini_wilders_severi_human_san_model_2017/model.c b/tests/resources/generator/fabbri_fantini_wilders_severi_human_san_model_2017/model.c index 97c29015b..03a7ac6a3 100644 --- a/tests/resources/generator/fabbri_fantini_wilders_severi_human_san_model_2017/model.c +++ b/tests/resources/generator/fabbri_fantini_wilders_severi_human_san_model_2017/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 33; const size_t VARIABLE_COUNT = 217; @@ -14,225 +14,238 @@ const size_t VARIABLE_COUNT = 217; const VariableInfo VOI_INFO = {"time", "second", "environment", VARIABLE_OF_INTEGRATION}; const VariableInfo STATE_INFO[] = { - {"R", "dimensionless", "Ca_SR_release", STATE}, + {"Ca_sub", "millimolar", "Ca_dynamics", STATE}, + {"Nai_", "millimolar", "Nai_concentration", STATE}, + {"Ca_jsr", "millimolar", "Ca_dynamics", STATE}, {"O", "dimensionless", "Ca_SR_release", STATE}, - {"I", "dimensionless", "Ca_SR_release", STATE}, + {"R", "dimensionless", "Ca_SR_release", STATE}, {"RI", "dimensionless", "Ca_SR_release", STATE}, - {"Ca_jsr", "millimolar", "Ca_dynamics", STATE}, - {"fCa", "dimensionless", "i_CaL_fCa_gate", STATE}, + {"I", "dimensionless", "Ca_SR_release", STATE}, + {"Cai", "millimolar", "Ca_dynamics", STATE}, + {"Ca_nsr", "millimolar", "Ca_dynamics", STATE}, {"fTC", "dimensionless", "Ca_buffering", STATE}, {"fTMC", "dimensionless", "Ca_buffering", STATE}, {"fTMM", "dimensionless", "Ca_buffering", STATE}, {"fCMi", "dimensionless", "Ca_buffering", STATE}, {"fCMs", "dimensionless", "Ca_buffering", STATE}, {"fCQ", "dimensionless", "Ca_buffering", STATE}, - {"Cai", "millimolar", "Ca_dynamics", STATE}, - {"Ca_nsr", "millimolar", "Ca_dynamics", STATE}, + {"V_ode", "millivolt", "Membrane", STATE}, {"y", "dimensionless", "i_f_y_gate", STATE}, - {"m", "dimensionless", "i_Na_m_gate", STATE}, {"h", "dimensionless", "i_Na_h_gate", STATE}, + {"m", "dimensionless", "i_Na_m_gate", STATE}, + {"s_Kur", "dimensionless", "i_Kur_sKur_gate", STATE}, + {"r_Kur", "dimensionless", "i_Kur_rKur_gate", STATE}, + {"fCa", "dimensionless", "i_CaL_fCa_gate", STATE}, {"fL", "dimensionless", "i_CaL_fL_gate", STATE}, - {"dT", "dimensionless", "i_CaT_dT_gate", STATE}, + {"dL", "dimensionless", "i_CaL_dL_gate", STATE}, {"fT", "dimensionless", "i_CaT_fT_gate", STATE}, - {"q", "dimensionless", "i_to_q_gate", STATE}, + {"dT", "dimensionless", "i_CaT_dT_gate", STATE}, {"r", "dimensionless", "i_to_r_gate", STATE}, - {"paS", "dimensionless", "i_Kr_pa_gate", STATE}, - {"paF", "dimensionless", "i_Kr_pa_gate", STATE}, + {"q", "dimensionless", "i_to_q_gate", STATE}, {"piy", "dimensionless", "i_Kr_pi_gate", STATE}, - {"a", "dimensionless", "i_KACh_a_gate", STATE}, - {"r_Kur", "dimensionless", "i_Kur_rKur_gate", STATE}, - {"s_Kur", "dimensionless", "i_Kur_sKur_gate", STATE}, + {"paF", "dimensionless", "i_Kr_pa_gate", STATE}, + {"paS", "dimensionless", "i_Kr_pa_gate", STATE}, {"n", "dimensionless", "i_Ks_n_gate", STATE}, - {"dL", "dimensionless", "i_CaL_dL_gate", STATE}, - {"Ca_sub", "millimolar", "Ca_dynamics", STATE}, - {"V_ode", "millivolt", "Membrane", STATE}, - {"Nai_", "millimolar", "Nai_concentration", STATE} + {"a", "dimensionless", "i_KACh_a_gate", STATE} }; const VariableInfo VARIABLE_INFO[] = { - {"EC50_SR", "millimolar", "Ca_SR_release", CONSTANT}, - {"HSR", "dimensionless", "Ca_SR_release", CONSTANT}, - {"MaxSR", "dimensionless", "Ca_SR_release", CONSTANT}, - {"MinSR", "dimensionless", "Ca_SR_release", CONSTANT}, - {"kiCa", "per_millimolar_second", "Ca_SR_release", CONSTANT}, - {"kim", "per_second", "Ca_SR_release", CONSTANT}, - {"koCa", "per_millimolar2_second", "Ca_SR_release", CONSTANT}, - {"kom", "per_second", "Ca_SR_release", CONSTANT}, - {"ks", "per_second", "Ca_SR_release", CONSTANT}, - {"CM_tot", "millimolar", "Ca_buffering", CONSTANT}, - {"CQ_tot", "millimolar", "Ca_buffering", CONSTANT}, - {"Mgi", "millimolar", "Ca_buffering", CONSTANT}, - {"TC_tot", "millimolar", "Ca_buffering", CONSTANT}, - {"TMC_tot", "millimolar", "Ca_buffering", CONSTANT}, - {"kb_CM", "per_second", "Ca_buffering", CONSTANT}, - {"kb_CQ", "per_second", "Ca_buffering", CONSTANT}, - {"kb_TC", "per_second", "Ca_buffering", CONSTANT}, - {"kb_TMC", "per_second", "Ca_buffering", CONSTANT}, - {"kb_TMM", "per_second", "Ca_buffering", CONSTANT}, - {"kf_CM", "per_millimolar_second", "Ca_buffering", CONSTANT}, - {"kf_CQ", "per_millimolar_second", "Ca_buffering", CONSTANT}, - {"kf_TC", "per_millimolar_second", "Ca_buffering", CONSTANT}, - {"kf_TMC", "per_millimolar_second", "Ca_buffering", CONSTANT}, - {"kf_TMM", "per_millimolar_second", "Ca_buffering", CONSTANT}, - {"K_up", "millimolar", "Ca_intracellular_fluxes", CONSTANT}, - {"P_up_basal", "millimolar_per_second", "Ca_intracellular_fluxes", CONSTANT}, - {"slope_up", "millimolar", "Ca_intracellular_fluxes", CONSTANT}, - {"tau_dif_Ca", "second", "Ca_intracellular_fluxes", CONSTANT}, - {"tau_tr", "second", "Ca_intracellular_fluxes", CONSTANT}, - {"L_cell", "micrometre", "Cell_parameters", CONSTANT}, - {"L_sub", "micrometre", "Cell_parameters", CONSTANT}, - {"R_cell", "micrometre", "Cell_parameters", CONSTANT}, - {"V_i_part", "dimensionless", "Cell_parameters", CONSTANT}, - {"V_jsr_part", "dimensionless", "Cell_parameters", CONSTANT}, - {"V_nsr_part", "dimensionless", "Cell_parameters", CONSTANT}, - {"Cao", "millimolar", "Ionic_values", CONSTANT}, - {"Ki", "millimolar", "Ionic_values", CONSTANT}, - {"Ko", "millimolar", "Ionic_values", CONSTANT}, - {"Nao", "millimolar", "Ionic_values", CONSTANT}, - {"C", "microF", "Membrane", CONSTANT}, - {"F", "coulomb_per_mole", "Membrane", CONSTANT}, - {"R", "joule_per_kilomole_kelvin", "Membrane", CONSTANT}, - {"T", "kelvin", "Membrane", CONSTANT}, - {"clamp_mode", "dimensionless", "Membrane", CONSTANT}, - {"Nai_clamp", "dimensionless", "Nai_concentration", CONSTANT}, {"ACh", "millimolar", "Rate_modulation_experiments", CONSTANT}, {"Iso_1_uM", "dimensionless", "Rate_modulation_experiments", CONSTANT}, - {"V_holding", "millivolt", "Voltage_clamp", CONSTANT}, - {"V_test", "millivolt", "Voltage_clamp", CONSTANT}, - {"t_holding", "second", "Voltage_clamp", CONSTANT}, - {"t_test", "second", "Voltage_clamp", CONSTANT}, - {"P_CaL", "nanoA_per_millimolar", "i_CaL", CONSTANT}, - {"V_dL", "millivolt", "i_CaL_dL_gate", CONSTANT}, - {"k_dL", "millivolt", "i_CaL_dL_gate", CONSTANT}, - {"Km_fCa", "millimolar", "i_CaL_fCa_gate", CONSTANT}, - {"alpha_fCa", "per_second", "i_CaL_fCa_gate", CONSTANT}, - {"k_fL", "millivolt", "i_CaL_fL_gate", CONSTANT}, - {"shift_fL", "millivolt", "i_CaL_fL_gate", CONSTANT}, - {"P_CaT", "nanoA_per_millimolar", "i_CaT", CONSTANT}, - {"offset_fT", "second", "i_CaT_fT_gate", CONSTANT}, - {"ACh_on", "dimensionless", "i_KACh", CONSTANT}, - {"g_KACh", "microS", "i_KACh", CONSTANT}, - {"g_Kr", "microS", "i_Kr", CONSTANT}, - {"g_Ks_", "microS", "i_Ks", CONSTANT}, - {"g_Kur", "microS", "i_Kur", CONSTANT}, - {"g_Na", "microS", "i_Na", CONSTANT}, - {"g_Na_L", "microS", "i_Na", CONSTANT}, - {"K1ni", "millimolar", "i_NaCa", CONSTANT}, - {"K1no", "millimolar", "i_NaCa", CONSTANT}, - {"K2ni", "millimolar", "i_NaCa", CONSTANT}, - {"K2no", "millimolar", "i_NaCa", CONSTANT}, - {"K3ni", "millimolar", "i_NaCa", CONSTANT}, - {"K3no", "millimolar", "i_NaCa", CONSTANT}, + {"E_Na", "millivolt", "Ionic_values", ALGEBRAIC}, + {"RTONF", "millivolt", "Membrane", COMPUTED_CONSTANT}, + {"Nao", "millimolar", "Ionic_values", CONSTANT}, + {"Nai", "millimolar", "Nai_concentration", ALGEBRAIC}, + {"E_K", "millivolt", "Ionic_values", COMPUTED_CONSTANT}, + {"Ko", "millimolar", "Ionic_values", CONSTANT}, + {"Ki", "millimolar", "Ionic_values", CONSTANT}, + {"E_Ca", "millivolt", "Ionic_values", ALGEBRAIC}, + {"Cao", "millimolar", "Ionic_values", CONSTANT}, + {"Nai_clamp", "dimensionless", "Nai_concentration", CONSTANT}, + {"i_Na", "nanoA", "i_Na", ALGEBRAIC}, + {"i_NaCa", "nanoA", "i_NaCa", ALGEBRAIC}, + {"i_NaK", "nanoA", "i_NaK", ALGEBRAIC}, + {"i_siNa", "nanoA", "i_CaL", ALGEBRAIC}, + {"i_fNa", "nanoA", "i_f", ALGEBRAIC}, + {"F", "coulomb_per_mole", "Membrane", CONSTANT}, + {"V_i", "millimetre3", "Cell_parameters", COMPUTED_CONSTANT}, + {"V_sub", "millimetre3", "Cell_parameters", COMPUTED_CONSTANT}, + {"Iso_increase", "dimensionless", "i_NaK", COMPUTED_CONSTANT}, + {"V", "millivolt", "Membrane", ALGEBRAIC}, + {"Km_Nap", "millimolar", "i_NaK", CONSTANT}, + {"Km_Kp", "millimolar", "i_NaK", CONSTANT}, + {"i_NaK_max", "nanoA", "i_NaK", CONSTANT}, + {"blockade_NaCa", "dimensionless", "i_NaCa", CONSTANT}, + {"x2", "dimensionless", "i_NaCa", ALGEBRAIC}, + {"k21", "dimensionless", "i_NaCa", ALGEBRAIC}, + {"x1", "dimensionless", "i_NaCa", ALGEBRAIC}, + {"k12", "dimensionless", "i_NaCa", ALGEBRAIC}, {"K_NaCa", "nanoA", "i_NaCa", CONSTANT}, + {"x4", "dimensionless", "i_NaCa", ALGEBRAIC}, + {"x3", "dimensionless", "i_NaCa", ALGEBRAIC}, + {"k41", "dimensionless", "i_NaCa", ALGEBRAIC}, + {"k23", "dimensionless", "i_NaCa", ALGEBRAIC}, + {"k34", "dimensionless", "i_NaCa", COMPUTED_CONSTANT}, + {"k43", "dimensionless", "i_NaCa", ALGEBRAIC}, + {"k32", "dimensionless", "i_NaCa", ALGEBRAIC}, + {"k14", "dimensionless", "i_NaCa", ALGEBRAIC}, + {"K3ni", "millimolar", "i_NaCa", CONSTANT}, {"Kci", "millimolar", "i_NaCa", CONSTANT}, + {"Qci", "dimensionless", "i_NaCa", CONSTANT}, + {"di", "dimensionless", "i_NaCa", ALGEBRAIC}, + {"K1ni", "millimolar", "i_NaCa", CONSTANT}, + {"K2ni", "millimolar", "i_NaCa", CONSTANT}, + {"Qn", "dimensionless", "i_NaCa", CONSTANT}, {"Kcni", "millimolar", "i_NaCa", CONSTANT}, + {"K3no", "millimolar", "i_NaCa", CONSTANT}, {"Kco", "millimolar", "i_NaCa", CONSTANT}, - {"Qci", "dimensionless", "i_NaCa", CONSTANT}, {"Qco", "dimensionless", "i_NaCa", CONSTANT}, - {"Qn", "dimensionless", "i_NaCa", CONSTANT}, - {"blockade_NaCa", "dimensionless", "i_NaCa", CONSTANT}, - {"Km_Kp", "millimolar", "i_NaK", CONSTANT}, - {"Km_Nap", "millimolar", "i_NaK", CONSTANT}, - {"i_NaK_max", "nanoA", "i_NaK", CONSTANT}, - {"delta_m", "millivolt", "i_Na_m_gate", CONSTANT}, - {"Km_f", "millimolar", "i_f", CONSTANT}, - {"alpha", "dimensionless", "i_f", CONSTANT}, - {"blockade", "dimensionless", "i_f", CONSTANT}, - {"g_f", "microS", "i_f", CONSTANT}, - {"y_shift", "millivolt", "i_f_y_gate", CONSTANT}, - {"g_to", "microS", "i_to", CONSTANT}, - {"Nai", "millimolar", "Nai_concentration", ALGEBRAIC}, - {"Iso_increase", "dimensionless", "i_NaK", COMPUTED_CONSTANT}, - {"k43", "dimensionless", "i_NaCa", ALGEBRAIC}, - {"k34", "dimensionless", "i_NaCa", COMPUTED_CONSTANT}, + {"do", "dimensionless", "i_NaCa", ALGEBRAIC}, + {"K1no", "millimolar", "i_NaCa", CONSTANT}, + {"K2no", "millimolar", "i_NaCa", CONSTANT}, {"j_SRCarel", "millimolar_per_second", "Ca_SR_release", ALGEBRAIC}, + {"ks", "per_second", "Ca_SR_release", CONSTANT}, {"diff", "millimolar", "Ca_SR_release", ALGEBRAIC}, {"kCaSR", "dimensionless", "Ca_SR_release", ALGEBRAIC}, + {"MaxSR", "dimensionless", "Ca_SR_release", CONSTANT}, + {"MinSR", "dimensionless", "Ca_SR_release", CONSTANT}, + {"EC50_SR", "millimolar", "Ca_SR_release", CONSTANT}, + {"HSR", "dimensionless", "Ca_SR_release", CONSTANT}, {"koSRCa", "per_millimolar2_second", "Ca_SR_release", ALGEBRAIC}, + {"koCa", "per_millimolar2_second", "Ca_SR_release", CONSTANT}, {"kiSRCa", "per_millimolar_second", "Ca_SR_release", ALGEBRAIC}, + {"kiCa", "per_millimolar_second", "Ca_SR_release", CONSTANT}, + {"kim", "per_second", "Ca_SR_release", CONSTANT}, + {"kom", "per_second", "Ca_SR_release", CONSTANT}, {"P_tot", "dimensionless", "Ca_SR_release", ALGEBRAIC}, {"b_up", "dimensionless", "Ca_intracellular_fluxes", COMPUTED_CONSTANT}, {"P_up", "millimolar_per_second", "Ca_intracellular_fluxes", COMPUTED_CONSTANT}, + {"P_up_basal", "millimolar_per_second", "Ca_intracellular_fluxes", CONSTANT}, {"j_Ca_dif", "millimolar_per_second", "Ca_intracellular_fluxes", ALGEBRAIC}, + {"tau_dif_Ca", "second", "Ca_intracellular_fluxes", CONSTANT}, {"j_up", "millimolar_per_second", "Ca_intracellular_fluxes", ALGEBRAIC}, + {"K_up", "millimolar", "Ca_intracellular_fluxes", CONSTANT}, + {"slope_up", "millimolar", "Ca_intracellular_fluxes", CONSTANT}, {"j_tr", "millimolar_per_second", "Ca_intracellular_fluxes", ALGEBRAIC}, + {"tau_tr", "second", "Ca_intracellular_fluxes", CONSTANT}, {"delta_fTC", "per_second", "Ca_buffering", ALGEBRAIC}, + {"kf_TC", "per_millimolar_second", "Ca_buffering", CONSTANT}, + {"kb_TC", "per_second", "Ca_buffering", CONSTANT}, {"delta_fTMC", "per_second", "Ca_buffering", ALGEBRAIC}, + {"kf_TMC", "per_millimolar_second", "Ca_buffering", CONSTANT}, + {"kb_TMC", "per_second", "Ca_buffering", CONSTANT}, {"delta_fTMM", "per_second", "Ca_buffering", ALGEBRAIC}, + {"kf_TMM", "per_millimolar_second", "Ca_buffering", CONSTANT}, + {"Mgi", "millimolar", "Ca_buffering", CONSTANT}, + {"kb_TMM", "per_second", "Ca_buffering", CONSTANT}, {"delta_fCMi", "per_second", "Ca_buffering", ALGEBRAIC}, + {"kf_CM", "per_millimolar_second", "Ca_buffering", CONSTANT}, + {"kb_CM", "per_second", "Ca_buffering", CONSTANT}, {"delta_fCMs", "per_second", "Ca_buffering", ALGEBRAIC}, {"delta_fCQ", "per_second", "Ca_buffering", ALGEBRAIC}, - {"V_cell", "millimetre3", "Cell_parameters", COMPUTED_CONSTANT}, - {"V_sub", "millimetre3", "Cell_parameters", COMPUTED_CONSTANT}, - {"V_jsr", "millimetre3", "Cell_parameters", COMPUTED_CONSTANT}, - {"V_i", "millimetre3", "Cell_parameters", COMPUTED_CONSTANT}, + {"kf_CQ", "per_millimolar_second", "Ca_buffering", CONSTANT}, + {"kb_CQ", "per_second", "Ca_buffering", CONSTANT}, + {"TC_tot", "millimolar", "Ca_buffering", CONSTANT}, + {"TMC_tot", "millimolar", "Ca_buffering", CONSTANT}, + {"CM_tot", "millimolar", "Ca_buffering", CONSTANT}, + {"CQ_tot", "millimolar", "Ca_buffering", CONSTANT}, {"V_nsr", "millimetre3", "Cell_parameters", COMPUTED_CONSTANT}, - {"RTONF", "millivolt", "Membrane", COMPUTED_CONSTANT}, + {"V_jsr", "millimetre3", "Cell_parameters", COMPUTED_CONSTANT}, + {"i_siCa", "nanoA", "i_CaL", ALGEBRAIC}, + {"i_CaT", "nanoA", "i_CaT", ALGEBRAIC}, + {"V_cell", "millimetre3", "Cell_parameters", COMPUTED_CONSTANT}, + {"L_cell", "micrometre", "Cell_parameters", CONSTANT}, + {"R_cell", "micrometre", "Cell_parameters", CONSTANT}, + {"L_sub", "micrometre", "Cell_parameters", CONSTANT}, + {"V_jsr_part", "dimensionless", "Cell_parameters", CONSTANT}, + {"V_i_part", "dimensionless", "Cell_parameters", CONSTANT}, + {"V_nsr_part", "dimensionless", "Cell_parameters", CONSTANT}, + {"i_tot", "nanoA", "Membrane", ALGEBRAIC}, + {"i_f", "nanoA", "i_f", ALGEBRAIC}, + {"i_Kur", "nanoA", "i_Kur", ALGEBRAIC}, + {"i_KACh", "nanoA", "i_KACh", ALGEBRAIC}, + {"i_CaL", "nanoA", "i_CaL", ALGEBRAIC}, + {"i_to", "nanoA", "i_to", ALGEBRAIC}, + {"i_Ks", "nanoA", "i_Ks", ALGEBRAIC}, + {"i_Kr", "nanoA", "i_Kr", ALGEBRAIC}, + {"C", "microF", "Membrane", CONSTANT}, + {"R", "joule_per_kilomole_kelvin", "Membrane", CONSTANT}, + {"T", "kelvin", "Membrane", CONSTANT}, {"V_clamp", "millivolt", "Voltage_clamp", ALGEBRAIC}, + {"clamp_mode", "dimensionless", "Membrane", CONSTANT}, + {"V_test", "millivolt", "Voltage_clamp", CONSTANT}, + {"t_holding", "second", "Voltage_clamp", CONSTANT}, + {"t_test", "second", "Voltage_clamp", CONSTANT}, + {"V_holding", "millivolt", "Voltage_clamp", CONSTANT}, {"G_f", "microS", "i_f", COMPUTED_CONSTANT}, + {"g_f", "microS", "i_f", CONSTANT}, + {"Km_f", "millimolar", "i_f", CONSTANT}, {"G_f_K", "microS", "i_f", COMPUTED_CONSTANT}, + {"alpha", "dimensionless", "i_f", CONSTANT}, {"G_f_Na", "microS", "i_f", COMPUTED_CONSTANT}, {"g_f_Na", "microS", "i_f", COMPUTED_CONSTANT}, {"g_f_K", "microS", "i_f", COMPUTED_CONSTANT}, + {"blockade", "dimensionless", "i_f", CONSTANT}, + {"i_fK", "nanoA", "i_f", ALGEBRAIC}, {"ACh_shift", "millivolt", "i_f_y_gate", COMPUTED_CONSTANT}, {"Iso_shift", "millivolt", "i_f_y_gate", COMPUTED_CONSTANT}, - {"E_mh", "millivolt", "i_Na", ALGEBRAIC}, - {"Iso_increase", "dimensionless", "i_CaL", COMPUTED_CONSTANT}, - {"ACh_block", "dimensionless", "i_CaL", COMPUTED_CONSTANT}, - {"Iso_shift_dL", "millivolt", "i_CaL_dL_gate", COMPUTED_CONSTANT}, - {"Iso_slope_dL", "dimensionless", "i_CaL_dL_gate", COMPUTED_CONSTANT}, - {"fCa_infinity", "dimensionless", "i_CaL_fCa_gate", ALGEBRAIC}, - {"tau_fCa", "second", "i_CaL_fCa_gate", ALGEBRAIC}, - {"g_Ks", "microS", "i_Ks", COMPUTED_CONSTANT}, - {"E_Ks", "millivolt", "i_Ks", ALGEBRAIC}, - {"Iso_shift", "millivolt", "i_Ks_n_gate", COMPUTED_CONSTANT}, - {"alpha_a", "per_second", "i_KACh_a_gate", COMPUTED_CONSTANT}, - {"E_Na", "millivolt", "Ionic_values", ALGEBRAIC}, - {"E_K", "millivolt", "Ionic_values", COMPUTED_CONSTANT}, - {"E_Ca", "millivolt", "Ionic_values", ALGEBRAIC}, - {"V", "millivolt", "Membrane", ALGEBRAIC}, - {"i_fNa", "nanoA", "i_f", ALGEBRAIC}, - {"i_fK", "nanoA", "i_f", ALGEBRAIC}, - {"i_f", "nanoA", "i_f", ALGEBRAIC}, {"tau_y", "second", "i_f_y_gate", ALGEBRAIC}, {"y_infinity", "dimensionless", "i_f_y_gate", ALGEBRAIC}, + {"y_shift", "millivolt", "i_f_y_gate", CONSTANT}, + {"E_mh", "millivolt", "i_Na", ALGEBRAIC}, {"i_Na_", "nanoA", "i_Na", ALGEBRAIC}, + {"g_Na", "microS", "i_Na", CONSTANT}, {"i_Na_L", "nanoA", "i_Na", ALGEBRAIC}, - {"i_Na", "nanoA", "i_Na", ALGEBRAIC}, + {"g_Na_L", "microS", "i_Na", CONSTANT}, {"m_infinity", "dimensionless", "i_Na_m_gate", ALGEBRAIC}, {"E0_m", "millivolt", "i_Na_m_gate", ALGEBRAIC}, {"alpha_m", "per_second", "i_Na_m_gate", ALGEBRAIC}, + {"delta_m", "millivolt", "i_Na_m_gate", CONSTANT}, {"beta_m", "per_second", "i_Na_m_gate", ALGEBRAIC}, {"tau_m", "second", "i_Na_m_gate", ALGEBRAIC}, {"h_infinity", "dimensionless", "i_Na_h_gate", ALGEBRAIC}, {"alpha_h", "per_second", "i_Na_h_gate", ALGEBRAIC}, {"beta_h", "per_second", "i_Na_h_gate", ALGEBRAIC}, {"tau_h", "second", "i_Na_h_gate", ALGEBRAIC}, - {"i_Kur", "nanoA", "i_Kur", ALGEBRAIC}, + {"g_Kur", "microS", "i_Kur", CONSTANT}, {"r_Kur_infinity", "dimensionless", "i_Kur_rKur_gate", ALGEBRAIC}, {"tau_r_Kur", "second", "i_Kur_rKur_gate", ALGEBRAIC}, {"s_Kur_infinity", "dimensionless", "i_Kur_sKur_gate", ALGEBRAIC}, {"tau_s_Kur", "second", "i_Kur_sKur_gate", ALGEBRAIC}, - {"i_siCa", "nanoA", "i_CaL", ALGEBRAIC}, + {"Iso_increase", "dimensionless", "i_CaL", COMPUTED_CONSTANT}, + {"P_CaL", "nanoA_per_millimolar", "i_CaL", CONSTANT}, {"i_siK", "nanoA", "i_CaL", ALGEBRAIC}, - {"i_siNa", "nanoA", "i_CaL", ALGEBRAIC}, - {"i_CaL", "nanoA", "i_CaL", ALGEBRAIC}, + {"ACh_block", "dimensionless", "i_CaL", COMPUTED_CONSTANT}, + {"Iso_shift_dL", "millivolt", "i_CaL_dL_gate", COMPUTED_CONSTANT}, + {"Iso_slope_dL", "dimensionless", "i_CaL_dL_gate", COMPUTED_CONSTANT}, {"dL_infinity", "dimensionless", "i_CaL_dL_gate", ALGEBRAIC}, + {"V_dL", "millivolt", "i_CaL_dL_gate", CONSTANT}, + {"k_dL", "millivolt", "i_CaL_dL_gate", CONSTANT}, + {"tau_dL", "second", "i_CaL_dL_gate", ALGEBRAIC}, + {"alpha_dL", "per_second", "i_CaL_dL_gate", ALGEBRAIC}, + {"beta_dL", "per_second", "i_CaL_dL_gate", ALGEBRAIC}, {"adVm", "millivolt", "i_CaL_dL_gate", ALGEBRAIC}, {"bdVm", "millivolt", "i_CaL_dL_gate", ALGEBRAIC}, {"fL_infinity", "dimensionless", "i_CaL_fL_gate", ALGEBRAIC}, + {"shift_fL", "millivolt", "i_CaL_fL_gate", CONSTANT}, + {"k_fL", "millivolt", "i_CaL_fL_gate", CONSTANT}, {"tau_fL", "second", "i_CaL_fL_gate", ALGEBRAIC}, - {"i_CaT", "nanoA", "i_CaT", ALGEBRAIC}, + {"fCa_infinity", "dimensionless", "i_CaL_fCa_gate", ALGEBRAIC}, + {"Km_fCa", "millimolar", "i_CaL_fCa_gate", CONSTANT}, + {"tau_fCa", "second", "i_CaL_fCa_gate", ALGEBRAIC}, + {"alpha_fCa", "per_second", "i_CaL_fCa_gate", CONSTANT}, + {"P_CaT", "nanoA_per_millimolar", "i_CaT", CONSTANT}, {"dT_infinity", "dimensionless", "i_CaT_dT_gate", ALGEBRAIC}, {"tau_dT", "second", "i_CaT_dT_gate", ALGEBRAIC}, {"fT_infinity", "dimensionless", "i_CaT_fT_gate", ALGEBRAIC}, {"tau_fT", "second", "i_CaT_fT_gate", ALGEBRAIC}, - {"i_to", "nanoA", "i_to", ALGEBRAIC}, + {"offset_fT", "second", "i_CaT_fT_gate", CONSTANT}, + {"g_to", "microS", "i_to", CONSTANT}, {"q_infinity", "dimensionless", "i_to_q_gate", ALGEBRAIC}, {"tau_q", "second", "i_to_q_gate", ALGEBRAIC}, {"r_infinity", "dimensionless", "i_to_r_gate", ALGEBRAIC}, {"tau_r", "second", "i_to_r_gate", ALGEBRAIC}, - {"i_Kr", "nanoA", "i_Kr", ALGEBRAIC}, + {"g_Kr", "microS", "i_Kr", CONSTANT}, {"alfapaF", "per_second", "i_Kr_pa_gate", ALGEBRAIC}, {"betapaF", "per_second", "i_Kr_pa_gate", ALGEBRAIC}, {"pa_infinity", "dimensionless", "i_Kr_pa_gate", ALGEBRAIC}, @@ -240,43 +253,42 @@ const VariableInfo VARIABLE_INFO[] = { {"tau_paF", "second", "i_Kr_pa_gate", ALGEBRAIC}, {"tau_pi", "second", "i_Kr_pi_gate", ALGEBRAIC}, {"pi_infinity", "dimensionless", "i_Kr_pi_gate", ALGEBRAIC}, - {"i_Ks", "nanoA", "i_Ks", ALGEBRAIC}, + {"g_Ks", "microS", "i_Ks", COMPUTED_CONSTANT}, + {"g_Ks_", "microS", "i_Ks", CONSTANT}, + {"E_Ks", "millivolt", "i_Ks", ALGEBRAIC}, + {"Iso_shift", "millivolt", "i_Ks_n_gate", COMPUTED_CONSTANT}, {"n_infinity", "dimensionless", "i_Ks_n_gate", ALGEBRAIC}, + {"tau_n", "second", "i_Ks_n_gate", ALGEBRAIC}, {"alpha_n", "per_second", "i_Ks_n_gate", ALGEBRAIC}, {"beta_n", "per_second", "i_Ks_n_gate", ALGEBRAIC}, - {"i_KACh", "nanoA", "i_KACh", ALGEBRAIC}, + {"ACh_on", "dimensionless", "i_KACh", CONSTANT}, + {"g_KACh", "microS", "i_KACh", CONSTANT}, + {"alpha_a", "per_second", "i_KACh_a_gate", COMPUTED_CONSTANT}, {"beta_a", "per_second", "i_KACh_a_gate", ALGEBRAIC}, {"a_infinity", "dimensionless", "i_KACh_a_gate", ALGEBRAIC}, - {"tau_a", "second", "i_KACh_a_gate", ALGEBRAIC}, - {"i_NaK", "nanoA", "i_NaK", ALGEBRAIC}, - {"k41", "dimensionless", "i_NaCa", ALGEBRAIC}, - {"di", "dimensionless", "i_NaCa", ALGEBRAIC}, - {"k32", "dimensionless", "i_NaCa", ALGEBRAIC}, - {"do", "dimensionless", "i_NaCa", ALGEBRAIC}, - {"alpha_dL", "per_second", "i_CaL_dL_gate", ALGEBRAIC}, - {"beta_dL", "per_second", "i_CaL_dL_gate", ALGEBRAIC}, - {"tau_n", "second", "i_Ks_n_gate", ALGEBRAIC}, - {"k12", "dimensionless", "i_NaCa", ALGEBRAIC}, - {"k14", "dimensionless", "i_NaCa", ALGEBRAIC}, - {"k21", "dimensionless", "i_NaCa", ALGEBRAIC}, - {"k23", "dimensionless", "i_NaCa", ALGEBRAIC}, - {"tau_dL", "second", "i_CaL_dL_gate", ALGEBRAIC}, - {"x1", "dimensionless", "i_NaCa", ALGEBRAIC}, - {"x2", "dimensionless", "i_NaCa", ALGEBRAIC}, - {"x3", "dimensionless", "i_NaCa", ALGEBRAIC}, - {"x4", "dimensionless", "i_NaCa", ALGEBRAIC}, - {"i_NaCa", "nanoA", "i_NaCa", ALGEBRAIC}, - {"i_tot", "nanoA", "Membrane", ALGEBRAIC} + {"tau_a", "second", "i_KACh_a_gate", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -284,396 +296,396 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { - variables[0] = 0.45; - variables[1] = 2.5; - variables[2] = 15.0; - variables[3] = 1.0; - variables[4] = 500.0; - variables[5] = 5.0; - variables[6] = 10000.0; - variables[7] = 660.0; - variables[8] = 148041085.1; - variables[9] = 0.045; - variables[10] = 10.0; - variables[11] = 2.5; - variables[12] = 0.031; - variables[13] = 0.062; - variables[14] = 542.0; - variables[15] = 445.0; - variables[16] = 446.0; - variables[17] = 7.51; - variables[18] = 751.0; - variables[19] = 1.642e6; - variables[20] = 175.4; - variables[21] = 88800.0; - variables[22] = 227700.0; - variables[23] = 2277.0; - variables[24] = 0.000286113; - variables[25] = 5.0; - variables[26] = 5.0e-5; - variables[27] = 5.469e-5; - variables[28] = 0.04; - variables[29] = 67.0; - variables[30] = 0.02; - variables[31] = 3.9; - variables[32] = 0.46; - variables[33] = 0.0012; - variables[34] = 0.0116; - variables[35] = 1.8; - variables[36] = 140.0; - variables[37] = 5.4; - variables[38] = 140.0; - variables[39] = 5.7e-5; - variables[40] = 96485.3415; - variables[41] = 8314.472; - variables[42] = 310.0; - variables[43] = 0.0; - variables[44] = 1.0; - variables[45] = 0.0; - variables[46] = 0.0; - variables[47] = -45.0; - variables[48] = -35.0; - variables[49] = 0.5; - variables[50] = 0.5; - variables[51] = 0.4578; - variables[52] = -16.4508; - variables[53] = 4.3371; - variables[54] = 0.000338; - variables[55] = 0.0075; - variables[56] = 0.0; - variables[57] = 0.0; - variables[58] = 0.04132; - variables[59] = 0.0; - variables[60] = 1.0; - variables[61] = 0.00345; - variables[62] = 0.00424; - variables[63] = 0.00065; - variables[64] = 0.1539e-3; - variables[65] = 0.0223; - variables[66] = 0.0; - variables[67] = 395.3; - variables[68] = 1628.0; - variables[69] = 2.289; - variables[70] = 561.4; - variables[71] = 26.44; - variables[72] = 4.663; - variables[73] = 3.343; - variables[74] = 0.0207; - variables[75] = 26.44; - variables[76] = 3.663; - variables[77] = 0.1369; - variables[78] = 0.0; - variables[79] = 0.4315; - variables[80] = 0.0; - variables[81] = 1.4; - variables[82] = 14.0; - variables[83] = 0.08105; - variables[84] = 1.0e-5; - variables[85] = 45.0; - variables[86] = 0.5927; - variables[87] = 0.0; - variables[88] = 0.00427; - variables[89] = 0.0; - variables[90] = 3.5e-3; - states[0] = 0.9308; - states[1] = 6.181512e-9; - states[2] = 4.595622e-10; - states[3] = 0.069199; - states[4] = 0.409551; - states[5] = 0.844449; - states[6] = 0.017929; - states[7] = 0.259947; - states[8] = 0.653777; - states[9] = 0.217311; - states[10] = 0.158521; - states[11] = 0.138975; - states[12] = 9.15641e-6; - states[13] = 0.435148; - states[14] = 0.009508; - states[15] = 0.447724; - states[16] = 0.003058; - states[17] = 0.846702; - states[18] = 0.268909; - states[19] = 0.020484; - states[20] = 0.430836; - states[21] = 0.014523; - states[22] = 0.283185; - states[23] = 0.011068; - states[24] = 0.709051; - states[25] = 0.00277; - states[26] = 0.011845; - states[27] = 0.845304; - states[28] = 0.1162; - states[29] = 0.001921; - states[30] = 6.226104e-5; - states[31] = -47.787168; - states[32] = 5.0; + variables[0] = 0.0; + variables[1] = 0.0; + variables[4] = 140.0; + variables[7] = 5.4; + variables[8] = 140.0; + variables[10] = 1.8; + variables[11] = 1.0; + variables[17] = 96485.3415; + variables[22] = 14.0; + variables[23] = 1.4; + variables[24] = 0.08105; + variables[25] = 0.0; + variables[30] = 3.343; + variables[39] = 26.44; + variables[40] = 0.0207; + variables[41] = 0.1369; + variables[43] = 395.3; + variables[44] = 2.289; + variables[45] = 0.4315; + variables[46] = 26.44; + variables[47] = 4.663; + variables[48] = 3.663; + variables[49] = 0.0; + variables[51] = 1628.0; + variables[52] = 561.4; + variables[54] = 148041085.1; + variables[57] = 15.0; + variables[58] = 1.0; + variables[59] = 0.45; + variables[60] = 2.5; + variables[62] = 10000.0; + variables[64] = 500.0; + variables[65] = 5.0; + variables[66] = 660.0; + variables[70] = 5.0; + variables[72] = 5.469e-5; + variables[74] = 0.000286113; + variables[75] = 5.0e-5; + variables[77] = 0.04; + variables[79] = 88800.0; + variables[80] = 446.0; + variables[82] = 227700.0; + variables[83] = 7.51; + variables[85] = 2277.0; + variables[86] = 2.5; + variables[87] = 751.0; + variables[89] = 1.642e6; + variables[90] = 542.0; + variables[93] = 175.4; + variables[94] = 445.0; + variables[95] = 0.031; + variables[96] = 0.062; + variables[97] = 0.045; + variables[98] = 10.0; + variables[104] = 67.0; + variables[105] = 3.9; + variables[106] = 0.02; + variables[107] = 0.0012; + variables[108] = 0.46; + variables[109] = 0.0116; + variables[118] = 5.7e-5; + variables[119] = 8314.472; + variables[120] = 310.0; + variables[122] = 0.0; + variables[123] = -35.0; + variables[124] = 0.5; + variables[125] = 0.5; + variables[126] = -45.0; + variables[128] = 0.00427; + variables[129] = 45.0; + variables[131] = 0.5927; + variables[135] = 0.0; + variables[141] = 0.0; + variables[144] = 0.0223; + variables[146] = 0.0; + variables[150] = 1.0e-5; + variables[157] = 0.1539e-3; + variables[163] = 0.4578; + variables[169] = -16.4508; + variables[170] = 4.3371; + variables[177] = 0.0; + variables[178] = 0.0; + variables[181] = 0.000338; + variables[183] = 0.0075; + variables[184] = 0.04132; + variables[189] = 0.0; + variables[190] = 3.5e-3; + variables[195] = 0.00424; + variables[204] = 0.00065; + variables[211] = 1.0; + variables[212] = 0.00345; + states[0] = 6.226104e-5; + states[1] = 5.0; + states[2] = 0.409551; + states[3] = 6.181512e-9; + states[4] = 0.9308; + states[5] = 0.069199; + states[6] = 4.595622e-10; + states[7] = 9.15641e-6; + states[8] = 0.435148; + states[9] = 0.017929; + states[10] = 0.259947; + states[11] = 0.653777; + states[12] = 0.217311; + states[13] = 0.158521; + states[14] = 0.138975; + states[15] = -47.787168; + states[16] = 0.009508; + states[17] = 0.003058; + states[18] = 0.447724; + states[19] = 0.845304; + states[20] = 0.011845; + states[21] = 0.844449; + states[22] = 0.846702; + states[23] = 0.001921; + states[24] = 0.020484; + states[25] = 0.268909; + states[26] = 0.014523; + states[27] = 0.430836; + states[28] = 0.709051; + states[29] = 0.011068; + states[30] = 0.283185; + states[31] = 0.1162; + states[32] = 0.00277; } void computeComputedConstants(double *variables) { - variables[92] = (variables[46] > 0.0)?1.2:1.0; - variables[94] = variables[38]/(variables[72]+variables[38]); - variables[101] = (variables[46] > 0.0)?-0.25:(variables[45] > 0.0)?0.7*variables[45]/(0.00009+variables[45]):0.0; - variables[102] = variables[25]*(1.0-variables[101]); - variables[112] = 0.000000001*3.14159265358979*pow(variables[31], 2.0)*variables[29]; - variables[113] = 0.000000001*2.0*3.14159265358979*variables[30]*(variables[31]-variables[30]/2.0)*variables[29]; - variables[114] = variables[33]*variables[112]; - variables[115] = variables[32]*variables[112]-variables[113]; - variables[116] = variables[34]*variables[112]; - variables[117] = variables[41]*variables[42]/variables[40]; - variables[119] = variables[88]/(variables[37]/(variables[37]+variables[85])); - variables[120] = variables[119]/(variables[86]+1.0); - variables[121] = variables[86]*variables[120]; - variables[122] = variables[121]*variables[37]/(variables[37]+variables[85]); - variables[123] = variables[120]*variables[37]/(variables[37]+variables[85]); - variables[124] = (variables[45] > 0.0)?-1.0-9.898*pow(1.0*variables[45], 0.618)/(pow(1.0*variables[45], 0.618)+0.00122423):0.0; - variables[125] = (variables[46] > 0.0)?7.5:0.0; - variables[127] = (variables[46] > 0.0)?1.23:1.0; - variables[128] = 0.31*variables[45]/(variables[45]+0.00009); - variables[129] = (variables[46] > 0.0)?-8.0:0.0; - variables[130] = (variables[46] > 0.0)?-27.0:0.0; - variables[133] = (variables[46] > 0.0)?1.2*variables[63]:variables[63]; - variables[135] = (variables[46] > 0.0)?-14.0:0.0; - variables[136] = (3.5988-0.025641)/(1.0+0.0000012155/pow(1.0*variables[45], 1.6951))+0.025641; - variables[138] = variables[117]*log(variables[37]/variables[36]); + variables[6] = variables[3]*log(variables[7]/variables[8]); + variables[20] = (variables[1] > 0.0)?1.2:1.0; + variables[35] = variables[4]/(variables[47]+variables[4]); + variables[68] = (variables[1] > 0.0)?-0.25:(variables[0] > 0.0)?0.7*variables[0]/(0.00009+variables[0]):0.0; + variables[69] = variables[70]*(1.0-variables[68]); + variables[103] = 0.000000001*3.14159265358979*pow(variables[105], 2.0)*variables[104]; + variables[19] = 0.000000001*2.0*3.14159265358979*variables[106]*(variables[105]-variables[106]/2.0)*variables[104]; + variables[100] = variables[107]*variables[103]; + variables[18] = variables[108]*variables[103]-variables[19]; + variables[99] = variables[109]*variables[103]; + variables[3] = variables[119]*variables[120]/variables[17]; + variables[127] = variables[128]/(variables[7]/(variables[7]+variables[129])); + variables[130] = variables[127]/(variables[131]+1.0); + variables[132] = variables[131]*variables[130]; + variables[133] = variables[132]*variables[7]/(variables[7]+variables[129]); + variables[134] = variables[130]*variables[7]/(variables[7]+variables[129]); + variables[137] = (variables[0] > 0.0)?-1.0-9.898*pow(1.0*variables[0], 0.618)/(pow(1.0*variables[0], 0.618)+0.00122423):0.0; + variables[138] = (variables[1] > 0.0)?7.5:0.0; + variables[162] = (variables[1] > 0.0)?1.23:1.0; + variables[165] = 0.31*variables[0]/(variables[0]+0.00009); + variables[166] = (variables[1] > 0.0)?-8.0:0.0; + variables[167] = (variables[1] > 0.0)?-27.0:0.0; + variables[203] = (variables[1] > 0.0)?1.2*variables[204]:variables[204]; + variables[206] = (variables[1] > 0.0)?-14.0:0.0; + variables[213] = (3.5988-0.025641)/(1.0+0.0000012155/pow(1.0*variables[0], 1.6951))+0.025641; } void computeRates(double voi, double *states, double *rates, double *variables) { - variables[97] = variables[2]-(variables[2]-variables[3])/(1.0+pow(variables[0]/states[4], variables[1])); - variables[99] = variables[4]*variables[97]; - variables[98] = variables[6]/variables[97]; - rates[0] = variables[5]*states[3]-variables[99]*states[30]*states[0]-(variables[98]*pow(states[30], 2.0)*states[0]-variables[7]*states[1]); - rates[1] = variables[98]*pow(states[30], 2.0)*states[0]-variables[7]*states[1]-(variables[99]*states[30]*states[1]-variables[5]*states[2]); - rates[2] = variables[99]*states[30]*states[1]-variables[5]*states[2]-(variables[7]*states[2]-variables[98]*pow(states[30], 2.0)*states[3]); - rates[3] = variables[7]*states[2]-variables[98]*pow(states[30], 2.0)*states[3]-(variables[5]*states[3]-variables[99]*states[30]*states[0]); - variables[105] = (states[13]-states[4])/variables[28]; - variables[95] = variables[8]*states[1]*(states[4]-states[30]); - variables[111] = variables[20]*states[4]*(1.0-states[11])-variables[15]*states[11]; - rates[4] = variables[105]-(variables[95]+variables[10]*variables[111]); - variables[131] = variables[54]/(variables[54]+states[30]); - variables[132] = 0.001*variables[131]/variables[55]; - rates[5] = (variables[131]-states[5])/variables[132]; - variables[106] = variables[21]*states[12]*(1.0-states[6])-variables[16]*states[6]; - rates[6] = variables[106]; - variables[107] = variables[22]*states[12]*(1.0-(states[7]+states[8]))-variables[17]*states[7]; - rates[7] = variables[107]; - variables[108] = variables[23]*variables[11]*(1.0-(states[7]+states[8]))-variables[18]*states[8]; - rates[8] = variables[108]; - variables[109] = variables[19]*states[12]*(1.0-states[9])-variables[14]*states[9]; - rates[9] = variables[109]; - variables[110] = variables[19]*states[30]*(1.0-states[10])-variables[14]*states[10]; - rates[10] = variables[110]; - rates[11] = variables[111]; - variables[103] = (states[30]-states[12])/variables[27]; - variables[104] = variables[102]/(1.0+exp((-states[12]+variables[24])/variables[26])); - rates[12] = 1.0*(variables[103]*variables[113]-variables[104]*variables[116])/variables[115]-(variables[9]*variables[109]+variables[12]*variables[106]+variables[13]*variables[107]); - rates[13] = variables[104]-variables[105]*variables[114]/variables[116]; - variables[118] = ((voi > variables[49]) && (voi < variables[49]+variables[50]))?variables[48]:variables[47]; - variables[140] = (variables[43] >= 1.0)?variables[118]:states[31]; - variables[145] = (variables[140] < -(80.0-variables[124]-variables[125]-variables[89]))?0.01329+0.99921/(1.0+exp((variables[140]+97.134-variables[124]-variables[125]-variables[89])/8.1752)):0.0002501*exp(-(variables[140]-variables[124]-variables[125]-variables[89])/12.861); - variables[144] = 1.0/(0.36*(variables[140]+148.8-variables[124]-variables[125])/(exp(0.066*(variables[140]+148.8-variables[124]-variables[125]))-1.0)+0.1*(variables[140]+87.3-variables[124]-variables[125])/(1.0-exp(-0.2*(variables[140]+87.3-variables[124]-variables[125]))))-0.054; - rates[14] = (variables[145]-states[14])/variables[144]; - variables[149] = 1.0/(1.0+exp(-(variables[140]+42.0504)/8.3106)); - variables[150] = variables[140]+41.0; - variables[151] = (fabs(variables[150]) < variables[84])?2000.0:200.0*variables[150]/(1.0-exp(-0.1*variables[150])); - variables[152] = 8000.0*exp(-0.056*(variables[140]+66.0)); - variables[153] = 1.0/(variables[151]+variables[152]); - rates[15] = (variables[149]-states[15])/variables[153]; - variables[154] = 1.0/(1.0+exp((variables[140]+69.804)/4.4565)); - variables[155] = 20.0*exp(-0.125*(variables[140]+75.0)); - variables[156] = 2000.0/(320.0*exp(-0.1*(variables[140]+75.0))+1.0); - variables[157] = 1.0/(variables[155]+variables[156]); - rates[16] = (variables[154]-states[16])/variables[157]; - variables[170] = 1.0/(1.0+exp((variables[140]+37.4+variables[57])/(5.3+variables[56]))); - variables[171] = 0.001*(44.3+230.0*exp(-pow((variables[140]+36.0)/10.0, 2.0))); - rates[17] = (variables[170]-states[17])/variables[171]; - variables[173] = 1.0/(1.0+exp(-(variables[140]+38.3)/5.5)); - variables[174] = 0.001/(1.068*exp((variables[140]+38.3)/30.0)+1.068*exp(-(variables[140]+38.3)/30.0)); - rates[18] = (variables[173]-states[18])/variables[174]; - variables[175] = 1.0/(1.0+exp((variables[140]+58.7)/3.8)); - variables[176] = 1.0/(16.67*exp(-(variables[140]+75.0)/83.3)+16.67*exp((variables[140]+75.0)/15.38))+variables[59]; - rates[19] = (variables[175]-states[19])/variables[176]; - variables[178] = 1.0/(1.0+exp((variables[140]+49.0)/13.0)); - variables[179] = 0.001*0.6*(65.17/(0.57*exp(-0.08*(variables[140]+44.0))+0.065*exp(0.1*(variables[140]+45.93)))+10.1); - rates[20] = (variables[178]-states[20])/variables[179]; - variables[180] = 1.0/(1.0+exp(-(variables[140]-19.3)/15.0)); - variables[181] = 0.001*0.66*1.4*(15.59/(1.037*exp(0.09*(variables[140]+30.61))+0.369*exp(-0.12*(variables[140]+23.84)))+2.98); - rates[21] = (variables[180]-states[21])/variables[181]; - variables[185] = 1.0/(1.0+exp(-(variables[140]+10.0144)/7.6607)); - variables[186] = 0.84655354/(4.2*exp(variables[140]/17.0)+0.15*exp(-variables[140]/21.6)); - rates[22] = (variables[185]-states[22])/variables[186]; - variables[187] = 1.0/(30.0*exp(variables[140]/10.0)+exp(-variables[140]/12.0)); - rates[23] = (variables[185]-states[23])/variables[187]; - variables[189] = 1.0/(1.0+exp((variables[140]+28.6)/17.1)); - variables[188] = 1.0/(100.0*exp(-variables[140]/54.645)+656.0*exp(variables[140]/106.157)); - rates[24] = (variables[189]-states[24])/variables[188]; - variables[195] = 10.0*exp(0.0133*(variables[140]+40.0)); - variables[196] = variables[136]/(variables[136]+variables[195]); - variables[197] = 1.0/(variables[136]+variables[195]); - rates[25] = (variables[196]-states[25])/variables[197]; - variables[159] = 1.0/(1.0+exp((variables[140]+6.0)/-8.6)); - variables[160] = 0.009/(1.0+exp((variables[140]+5.0)/12.0))+0.0005; - rates[26] = (variables[159]-states[26])/variables[160]; - variables[161] = 1.0/(1.0+exp((variables[140]+7.5)/10.0)); - variables[162] = 0.59/(1.0+exp((variables[140]+60.0)/10.0))+3.05; - rates[27] = (variables[161]-states[27])/variables[162]; - variables[191] = sqrt(1.0/(1.0+exp(-(variables[140]+0.6383-variables[135])/10.7071))); - variables[192] = 28.0/(1.0+exp(-(variables[140]-40.0-variables[135])/3.0)); - variables[193] = 1.0*exp(-(variables[140]-variables[135]-5.0)/25.0); - variables[205] = 1.0/(variables[192]+variables[193]); - rates[28] = (variables[191]-states[28])/variables[205]; - variables[167] = 1.0/(1.0+exp(-(variables[140]-variables[52]-variables[129])/(variables[53]*(1.0+variables[130]/100.0)))); - variables[168] = (variables[140] == -41.8)?-41.80001:(variables[140] == 0.0)?0.0:(variables[140] == -6.8)?-6.80001:variables[140]; - variables[203] = -0.02839*(variables[168]+41.8)/(exp(-(variables[168]+41.8)/2.5)-1.0)-0.0849*(variables[168]+6.8)/(exp(-(variables[168]+6.8)/4.8)-1.0); - variables[169] = (variables[140] == -1.8)?-1.80001:variables[140]; - variables[204] = 0.01143*(variables[169]+1.8)/(exp((variables[169]+1.8)/2.5)-1.0); - variables[210] = 0.001/(variables[203]+variables[204]); - rates[29] = (variables[167]-states[29])/variables[210]; - variables[163] = 2.0*variables[51]*(variables[140]-0.0)/(variables[117]*(1.0-exp(-1.0*(variables[140]-0.0)*2.0/variables[117])))*(states[30]-variables[35]*exp(-2.0*(variables[140]-0.0)/variables[117]))*states[29]*states[17]*states[5]; - variables[172] = 2.0*variables[58]*variables[140]/(variables[117]*(1.0-exp(-1.0*variables[140]*2.0/variables[117])))*(states[30]-variables[35]*exp(-2.0*variables[140]/variables[117]))*states[18]*states[19]; - variables[202] = 1.0+variables[35]/variables[76]*(1.0+exp(variables[78]*variables[140]/variables[117]))+variables[38]/variables[68]*(1.0+variables[38]/variables[70]*(1.0+variables[38]/variables[72])); - variables[208] = variables[35]/variables[76]*exp(variables[78]*variables[140]/variables[117])/variables[202]; - variables[91] = states[32]; - variables[200] = 1.0+states[30]/variables[74]*(1.0+exp(-variables[77]*variables[140]/variables[117])+variables[91]/variables[75])+variables[91]/variables[67]*(1.0+variables[91]/variables[69]*(1.0+variables[91]/variables[71])); - variables[206] = states[30]/variables[74]*exp(-variables[77]*variables[140]/variables[117])/variables[200]; - variables[93] = variables[91]/(variables[71]+variables[91]); - variables[201] = exp(variables[79]*variables[140]/(2.0*variables[117])); - variables[199] = exp(-variables[79]*variables[140]/(2.0*variables[117])); - variables[207] = variables[91]/variables[67]*variables[91]/variables[69]*(1.0+variables[91]/variables[71])*exp(variables[79]*variables[140]/(2.0*variables[117]))/variables[200]; - variables[212] = variables[201]*variables[93]*(variables[207]+variables[206])+variables[199]*variables[206]*(variables[94]+variables[201]); - variables[209] = variables[38]/variables[68]*variables[38]/variables[70]*(1.0+variables[38]/variables[72])*exp(-variables[79]*variables[140]/(2.0*variables[117]))/variables[202]; - variables[211] = variables[199]*variables[94]*(variables[209]+variables[208])+variables[208]*variables[201]*(variables[93]+variables[199]); - variables[214] = variables[209]*variables[94]*(variables[207]+variables[206])+variables[207]*variables[208]*(variables[94]+variables[201]); - variables[213] = variables[207]*variables[93]*(variables[209]+variables[208])+variables[206]*variables[209]*(variables[93]+variables[199]); - variables[215] = (1.0-variables[80])*variables[73]*(variables[212]*variables[208]-variables[211]*variables[206])/(variables[211]+variables[212]+variables[213]+variables[214]); - rates[30] = variables[95]*variables[114]/variables[113]-((variables[163]+variables[172]-2.0*variables[215])/(2.0*variables[40]*variables[113])+variables[103]+variables[9]*variables[110]); - variables[137] = variables[117]*log(variables[38]/variables[91]); - variables[141] = states[14]*variables[122]*(variables[140]-variables[137])*(1.0-variables[87]); - variables[142] = states[14]*variables[123]*(variables[140]-variables[138])*(1.0-variables[87]); - variables[143] = variables[141]+variables[142]; - variables[158] = variables[64]*states[26]*states[27]*(variables[140]-variables[138]); - variables[194] = (variables[45] > 0.0)?variables[60]*variables[61]*(variables[140]-variables[138])*(1.0+exp((variables[140]+20.0)/20.0))*states[25]:0.0; - variables[165] = 0.0000185*variables[51]*(variables[140]-0.0)/(variables[117]*(1.0-exp(-1.0*(variables[140]-0.0)/variables[117])))*(variables[91]-variables[38]*exp(-1.0*(variables[140]-0.0)/variables[117]))*states[29]*states[17]*states[5]; - variables[164] = 0.000365*variables[51]*(variables[140]-0.0)/(variables[117]*(1.0-exp(-1.0*(variables[140]-0.0)/variables[117])))*(variables[36]-variables[37]*exp(-1.0*(variables[140]-0.0)/variables[117]))*states[29]*states[17]*states[5]; - variables[166] = (variables[163]+variables[164]+variables[165])*(1.0-variables[128])*1.0*variables[127]; - variables[126] = variables[117]*log((variables[38]+0.12*variables[37])/(variables[91]+0.12*variables[36])); - variables[146] = variables[65]*pow(states[15], 3.0)*states[16]*(variables[140]-variables[126]); - variables[147] = variables[66]*pow(states[15], 3.0)*(variables[140]-variables[126]); - variables[148] = variables[146]+variables[147]; - variables[198] = variables[92]*variables[83]*pow(1.0+pow(variables[81]/variables[37], 1.2), -1.0)*pow(1.0+pow(variables[82]/variables[91], 1.3), -1.0)*pow(1.0+exp(-(variables[140]-variables[137]+110.0)/20.0), -1.0); - variables[177] = variables[90]*(variables[140]-variables[138])*states[20]*states[21]; - variables[134] = variables[117]*log((variables[37]+0.12*variables[38])/(variables[36]+0.12*variables[91])); - variables[190] = variables[133]*(variables[140]-variables[134])*pow(states[28], 2.0); - variables[182] = variables[62]*(variables[140]-variables[138])*(0.9*states[23]+0.1*states[22])*states[24]; - variables[216] = variables[143]+variables[182]+variables[190]+variables[177]+variables[198]+variables[215]+variables[148]+variables[166]+variables[172]+variables[194]+variables[158]; - rates[31] = -variables[216]/variables[39]; - rates[32] = (1.0-variables[44])*-1.0*(variables[148]+variables[141]+variables[165]+3.0*variables[198]+3.0*variables[215])/(1.0*(variables[115]+variables[113])*variables[40]); + variables[5] = states[1]; + variables[142] = variables[3]*log((variables[4]+0.12*variables[7])/(variables[5]+0.12*variables[8])); + variables[121] = ((voi > variables[124]) && (voi < variables[124]+variables[125]))?variables[123]:variables[126]; + variables[21] = (variables[122] >= 1.0)?variables[121]:states[15]; + variables[143] = variables[144]*pow(states[18], 3.0)*states[17]*(variables[21]-variables[142]); + variables[145] = variables[146]*pow(states[18], 3.0)*(variables[21]-variables[142]); + variables[12] = variables[143]+variables[145]; + variables[15] = 0.0000185*variables[163]*(variables[21]-0.0)/(variables[3]*(1.0-exp(-1.0*(variables[21]-0.0)/variables[3])))*(variables[5]-variables[4]*exp(-1.0*(variables[21]-0.0)/variables[3]))*states[23]*states[22]*states[21]; + variables[2] = variables[3]*log(variables[4]/variables[5]); + variables[16] = states[16]*variables[133]*(variables[21]-variables[2])*(1.0-variables[135]); + variables[14] = variables[20]*variables[24]*pow(1.0+pow(variables[23]/variables[7], 1.2), -1.0)*pow(1.0+pow(variables[22]/variables[5], 1.3), -1.0)*pow(1.0+exp(-(variables[21]-variables[2]+110.0)/20.0), -1.0); + variables[50] = 1.0+variables[10]/variables[48]*(1.0+exp(variables[49]*variables[21]/variables[3]))+variables[4]/variables[51]*(1.0+variables[4]/variables[52]*(1.0+variables[4]/variables[47])); + variables[27] = variables[10]/variables[48]*exp(variables[49]*variables[21]/variables[3])/variables[50]; + variables[42] = 1.0+states[0]/variables[40]*(1.0+exp(-variables[41]*variables[21]/variables[3])+variables[5]/variables[46])+variables[5]/variables[43]*(1.0+variables[5]/variables[44]*(1.0+variables[5]/variables[39])); + variables[29] = states[0]/variables[40]*exp(-variables[41]*variables[21]/variables[3])/variables[42]; + variables[36] = variables[5]/(variables[39]+variables[5]); + variables[37] = exp(variables[45]*variables[21]/(2.0*variables[3])); + variables[33] = exp(-variables[45]*variables[21]/(2.0*variables[3])); + variables[38] = variables[5]/variables[43]*variables[5]/variables[44]*(1.0+variables[5]/variables[39])*exp(variables[45]*variables[21]/(2.0*variables[3]))/variables[42]; + variables[26] = variables[37]*variables[36]*(variables[38]+variables[29])+variables[33]*variables[29]*(variables[35]+variables[37]); + variables[34] = variables[4]/variables[51]*variables[4]/variables[52]*(1.0+variables[4]/variables[47])*exp(-variables[45]*variables[21]/(2.0*variables[3]))/variables[50]; + variables[28] = variables[33]*variables[35]*(variables[34]+variables[27])+variables[27]*variables[37]*(variables[36]+variables[33]); + variables[31] = variables[34]*variables[35]*(variables[38]+variables[29])+variables[38]*variables[27]*(variables[35]+variables[37]); + variables[32] = variables[38]*variables[36]*(variables[34]+variables[27])+variables[29]*variables[34]*(variables[36]+variables[33]); + variables[13] = (1.0-variables[25])*variables[30]*(variables[26]*variables[27]-variables[28]*variables[29])/(variables[28]+variables[26]+variables[32]+variables[31]); + rates[1] = (1.0-variables[11])*-1.0*(variables[12]+variables[16]+variables[15]+3.0*variables[14]+3.0*variables[13])/(1.0*(variables[18]+variables[19])*variables[17]); + variables[56] = variables[57]-(variables[57]-variables[58])/(1.0+pow(variables[59]/states[2], variables[60])); + variables[63] = variables[64]*variables[56]; + variables[61] = variables[62]/variables[56]; + rates[4] = variables[65]*states[5]-variables[63]*states[0]*states[4]-(variables[61]*pow(states[0], 2.0)*states[4]-variables[66]*states[3]); + rates[3] = variables[61]*pow(states[0], 2.0)*states[4]-variables[66]*states[3]-(variables[63]*states[0]*states[3]-variables[65]*states[6]); + rates[6] = variables[63]*states[0]*states[3]-variables[65]*states[6]-(variables[66]*states[6]-variables[61]*pow(states[0], 2.0)*states[5]); + rates[5] = variables[66]*states[6]-variables[61]*pow(states[0], 2.0)*states[5]-(variables[65]*states[5]-variables[63]*states[0]*states[4]); + variables[78] = variables[79]*states[7]*(1.0-states[9])-variables[80]*states[9]; + rates[9] = variables[78]; + variables[81] = variables[82]*states[7]*(1.0-(states[10]+states[11]))-variables[83]*states[10]; + rates[10] = variables[81]; + variables[84] = variables[85]*variables[86]*(1.0-(states[10]+states[11]))-variables[87]*states[11]; + rates[11] = variables[84]; + variables[88] = variables[89]*states[7]*(1.0-states[12])-variables[90]*states[12]; + rates[12] = variables[88]; + variables[91] = variables[89]*states[0]*(1.0-states[13])-variables[90]*states[13]; + rates[13] = variables[91]; + variables[92] = variables[93]*states[2]*(1.0-states[14])-variables[94]*states[14]; + rates[14] = variables[92]; + variables[71] = (states[0]-states[7])/variables[72]; + variables[73] = variables[69]/(1.0+exp((-states[7]+variables[74])/variables[75])); + rates[7] = 1.0*(variables[71]*variables[19]-variables[73]*variables[99])/variables[18]-(variables[97]*variables[88]+variables[95]*variables[78]+variables[96]*variables[81]); + variables[53] = variables[54]*states[3]*(states[2]-states[0]); + variables[101] = 2.0*variables[163]*(variables[21]-0.0)/(variables[3]*(1.0-exp(-1.0*(variables[21]-0.0)*2.0/variables[3])))*(states[0]-variables[10]*exp(-2.0*(variables[21]-0.0)/variables[3]))*states[23]*states[22]*states[21]; + variables[102] = 2.0*variables[184]*variables[21]/(variables[3]*(1.0-exp(-1.0*variables[21]*2.0/variables[3])))*(states[0]-variables[10]*exp(-2.0*variables[21]/variables[3]))*states[25]*states[24]; + rates[0] = variables[53]*variables[100]/variables[19]-((variables[101]+variables[102]-2.0*variables[13])/(2.0*variables[17]*variables[19])+variables[71]+variables[97]*variables[91]); + variables[76] = (states[8]-states[2])/variables[77]; + rates[8] = variables[73]-variables[76]*variables[100]/variables[99]; + rates[2] = variables[76]-(variables[53]+variables[98]*variables[92]); + variables[136] = states[16]*variables[134]*(variables[21]-variables[6])*(1.0-variables[135]); + variables[111] = variables[16]+variables[136]; + variables[112] = variables[157]*states[20]*states[19]*(variables[21]-variables[6]); + variables[113] = (variables[0] > 0.0)?variables[211]*variables[212]*(variables[21]-variables[6])*(1.0+exp((variables[21]+20.0)/20.0))*states[32]:0.0; + variables[164] = 0.000365*variables[163]*(variables[21]-0.0)/(variables[3]*(1.0-exp(-1.0*(variables[21]-0.0)/variables[3])))*(variables[8]-variables[7]*exp(-1.0*(variables[21]-0.0)/variables[3]))*states[23]*states[22]*states[21]; + variables[114] = (variables[101]+variables[164]+variables[15])*(1.0-variables[165])*1.0*variables[162]; + variables[115] = variables[190]*(variables[21]-variables[6])*states[27]*states[26]; + variables[205] = variables[3]*log((variables[7]+0.12*variables[4])/(variables[8]+0.12*variables[5])); + variables[116] = variables[203]*(variables[21]-variables[205])*pow(states[31], 2.0); + variables[117] = variables[195]*(variables[21]-variables[6])*(0.9*states[29]+0.1*states[30])*states[28]; + variables[110] = variables[111]+variables[117]+variables[116]+variables[115]+variables[14]+variables[13]+variables[12]+variables[114]+variables[102]+variables[113]+variables[112]; + rates[15] = -variables[110]/variables[118]; + variables[140] = (variables[21] < -(80.0-variables[137]-variables[138]-variables[141]))?0.01329+0.99921/(1.0+exp((variables[21]+97.134-variables[137]-variables[138]-variables[141])/8.1752)):0.0002501*exp(-(variables[21]-variables[137]-variables[138]-variables[141])/12.861); + variables[139] = 1.0/(0.36*(variables[21]+148.8-variables[137]-variables[138])/(exp(0.066*(variables[21]+148.8-variables[137]-variables[138]))-1.0)+0.1*(variables[21]+87.3-variables[137]-variables[138])/(1.0-exp(-0.2*(variables[21]+87.3-variables[137]-variables[138]))))-0.054; + rates[16] = (variables[140]-states[16])/variables[139]; + variables[147] = 1.0/(1.0+exp(-(variables[21]+42.0504)/8.3106)); + variables[148] = variables[21]+41.0; + variables[149] = (fabs(variables[148]) < variables[150])?2000.0:200.0*variables[148]/(1.0-exp(-0.1*variables[148])); + variables[151] = 8000.0*exp(-0.056*(variables[21]+66.0)); + variables[152] = 1.0/(variables[149]+variables[151]); + rates[18] = (variables[147]-states[18])/variables[152]; + variables[153] = 1.0/(1.0+exp((variables[21]+69.804)/4.4565)); + variables[154] = 20.0*exp(-0.125*(variables[21]+75.0)); + variables[155] = 2000.0/(320.0*exp(-0.1*(variables[21]+75.0))+1.0); + variables[156] = 1.0/(variables[154]+variables[155]); + rates[17] = (variables[153]-states[17])/variables[156]; + variables[158] = 1.0/(1.0+exp((variables[21]+6.0)/-8.6)); + variables[159] = 0.009/(1.0+exp((variables[21]+5.0)/12.0))+0.0005; + rates[20] = (variables[158]-states[20])/variables[159]; + variables[160] = 1.0/(1.0+exp((variables[21]+7.5)/10.0)); + variables[161] = 0.59/(1.0+exp((variables[21]+60.0)/10.0))+3.05; + rates[19] = (variables[160]-states[19])/variables[161]; + variables[168] = 1.0/(1.0+exp(-(variables[21]-variables[169]-variables[166])/(variables[170]*(1.0+variables[167]/100.0)))); + variables[174] = (variables[21] == -41.8)?-41.80001:(variables[21] == 0.0)?0.0:(variables[21] == -6.8)?-6.80001:variables[21]; + variables[172] = -0.02839*(variables[174]+41.8)/(exp(-(variables[174]+41.8)/2.5)-1.0)-0.0849*(variables[174]+6.8)/(exp(-(variables[174]+6.8)/4.8)-1.0); + variables[175] = (variables[21] == -1.8)?-1.80001:variables[21]; + variables[173] = 0.01143*(variables[175]+1.8)/(exp((variables[175]+1.8)/2.5)-1.0); + variables[171] = 0.001/(variables[172]+variables[173]); + rates[23] = (variables[168]-states[23])/variables[171]; + variables[176] = 1.0/(1.0+exp((variables[21]+37.4+variables[177])/(5.3+variables[178]))); + variables[179] = 0.001*(44.3+230.0*exp(-pow((variables[21]+36.0)/10.0, 2.0))); + rates[22] = (variables[176]-states[22])/variables[179]; + variables[180] = variables[181]/(variables[181]+states[0]); + variables[182] = 0.001*variables[180]/variables[183]; + rates[21] = (variables[180]-states[21])/variables[182]; + variables[185] = 1.0/(1.0+exp(-(variables[21]+38.3)/5.5)); + variables[186] = 0.001/(1.068*exp((variables[21]+38.3)/30.0)+1.068*exp(-(variables[21]+38.3)/30.0)); + rates[25] = (variables[185]-states[25])/variables[186]; + variables[187] = 1.0/(1.0+exp((variables[21]+58.7)/3.8)); + variables[188] = 1.0/(16.67*exp(-(variables[21]+75.0)/83.3)+16.67*exp((variables[21]+75.0)/15.38))+variables[189]; + rates[24] = (variables[187]-states[24])/variables[188]; + variables[191] = 1.0/(1.0+exp((variables[21]+49.0)/13.0)); + variables[192] = 0.001*0.6*(65.17/(0.57*exp(-0.08*(variables[21]+44.0))+0.065*exp(0.1*(variables[21]+45.93)))+10.1); + rates[27] = (variables[191]-states[27])/variables[192]; + variables[193] = 1.0/(1.0+exp(-(variables[21]-19.3)/15.0)); + variables[194] = 0.001*0.66*1.4*(15.59/(1.037*exp(0.09*(variables[21]+30.61))+0.369*exp(-0.12*(variables[21]+23.84)))+2.98); + rates[26] = (variables[193]-states[26])/variables[194]; + variables[198] = 1.0/(1.0+exp(-(variables[21]+10.0144)/7.6607)); + variables[199] = 0.84655354/(4.2*exp(variables[21]/17.0)+0.15*exp(-variables[21]/21.6)); + rates[30] = (variables[198]-states[30])/variables[199]; + variables[200] = 1.0/(30.0*exp(variables[21]/10.0)+exp(-variables[21]/12.0)); + rates[29] = (variables[198]-states[29])/variables[200]; + variables[202] = 1.0/(1.0+exp((variables[21]+28.6)/17.1)); + variables[201] = 1.0/(100.0*exp(-variables[21]/54.645)+656.0*exp(variables[21]/106.157)); + rates[28] = (variables[202]-states[28])/variables[201]; + variables[207] = sqrt(1.0/(1.0+exp(-(variables[21]+0.6383-variables[206])/10.7071))); + variables[209] = 28.0/(1.0+exp(-(variables[21]-40.0-variables[206])/3.0)); + variables[210] = 1.0*exp(-(variables[21]-variables[206]-5.0)/25.0); + variables[208] = 1.0/(variables[209]+variables[210]); + rates[31] = (variables[207]-states[31])/variables[208]; + variables[214] = 10.0*exp(0.0133*(variables[21]+40.0)); + variables[215] = variables[213]/(variables[213]+variables[214]); + variables[216] = 1.0/(variables[213]+variables[214]); + rates[32] = (variables[215]-states[32])/variables[216]; } void computeVariables(double voi, double *states, double *rates, double *variables) { - variables[91] = states[32]; - variables[93] = variables[91]/(variables[71]+variables[91]); - variables[95] = variables[8]*states[1]*(states[4]-states[30]); - variables[96] = states[4]-states[30]; - variables[97] = variables[2]-(variables[2]-variables[3])/(1.0+pow(variables[0]/states[4], variables[1])); - variables[98] = variables[6]/variables[97]; - variables[99] = variables[4]*variables[97]; - variables[100] = states[0]+states[1]+states[2]+states[3]; - variables[103] = (states[30]-states[12])/variables[27]; - variables[104] = variables[102]/(1.0+exp((-states[12]+variables[24])/variables[26])); - variables[105] = (states[13]-states[4])/variables[28]; - variables[106] = variables[21]*states[12]*(1.0-states[6])-variables[16]*states[6]; - variables[107] = variables[22]*states[12]*(1.0-(states[7]+states[8]))-variables[17]*states[7]; - variables[108] = variables[23]*variables[11]*(1.0-(states[7]+states[8]))-variables[18]*states[8]; - variables[109] = variables[19]*states[12]*(1.0-states[9])-variables[14]*states[9]; - variables[110] = variables[19]*states[30]*(1.0-states[10])-variables[14]*states[10]; - variables[111] = variables[20]*states[4]*(1.0-states[11])-variables[15]*states[11]; - variables[126] = variables[117]*log((variables[38]+0.12*variables[37])/(variables[91]+0.12*variables[36])); - variables[131] = variables[54]/(variables[54]+states[30]); - variables[132] = 0.001*variables[131]/variables[55]; - variables[134] = variables[117]*log((variables[37]+0.12*variables[38])/(variables[36]+0.12*variables[91])); - variables[137] = variables[117]*log(variables[38]/variables[91]); - variables[139] = 0.5*variables[117]*log(variables[35]/states[30]); - variables[140] = (variables[43] >= 1.0)?variables[118]:states[31]; - variables[141] = states[14]*variables[122]*(variables[140]-variables[137])*(1.0-variables[87]); - variables[142] = states[14]*variables[123]*(variables[140]-variables[138])*(1.0-variables[87]); - variables[143] = variables[141]+variables[142]; - variables[144] = 1.0/(0.36*(variables[140]+148.8-variables[124]-variables[125])/(exp(0.066*(variables[140]+148.8-variables[124]-variables[125]))-1.0)+0.1*(variables[140]+87.3-variables[124]-variables[125])/(1.0-exp(-0.2*(variables[140]+87.3-variables[124]-variables[125]))))-0.054; - variables[145] = (variables[140] < -(80.0-variables[124]-variables[125]-variables[89]))?0.01329+0.99921/(1.0+exp((variables[140]+97.134-variables[124]-variables[125]-variables[89])/8.1752)):0.0002501*exp(-(variables[140]-variables[124]-variables[125]-variables[89])/12.861); - variables[146] = variables[65]*pow(states[15], 3.0)*states[16]*(variables[140]-variables[126]); - variables[147] = variables[66]*pow(states[15], 3.0)*(variables[140]-variables[126]); - variables[148] = variables[146]+variables[147]; - variables[149] = 1.0/(1.0+exp(-(variables[140]+42.0504)/8.3106)); - variables[150] = variables[140]+41.0; - variables[151] = (fabs(variables[150]) < variables[84])?2000.0:200.0*variables[150]/(1.0-exp(-0.1*variables[150])); - variables[152] = 8000.0*exp(-0.056*(variables[140]+66.0)); - variables[153] = 1.0/(variables[151]+variables[152]); - variables[154] = 1.0/(1.0+exp((variables[140]+69.804)/4.4565)); - variables[155] = 20.0*exp(-0.125*(variables[140]+75.0)); - variables[156] = 2000.0/(320.0*exp(-0.1*(variables[140]+75.0))+1.0); - variables[157] = 1.0/(variables[155]+variables[156]); - variables[158] = variables[64]*states[26]*states[27]*(variables[140]-variables[138]); - variables[159] = 1.0/(1.0+exp((variables[140]+6.0)/-8.6)); - variables[160] = 0.009/(1.0+exp((variables[140]+5.0)/12.0))+0.0005; - variables[161] = 1.0/(1.0+exp((variables[140]+7.5)/10.0)); - variables[162] = 0.59/(1.0+exp((variables[140]+60.0)/10.0))+3.05; - variables[163] = 2.0*variables[51]*(variables[140]-0.0)/(variables[117]*(1.0-exp(-1.0*(variables[140]-0.0)*2.0/variables[117])))*(states[30]-variables[35]*exp(-2.0*(variables[140]-0.0)/variables[117]))*states[29]*states[17]*states[5]; - variables[164] = 0.000365*variables[51]*(variables[140]-0.0)/(variables[117]*(1.0-exp(-1.0*(variables[140]-0.0)/variables[117])))*(variables[36]-variables[37]*exp(-1.0*(variables[140]-0.0)/variables[117]))*states[29]*states[17]*states[5]; - variables[165] = 0.0000185*variables[51]*(variables[140]-0.0)/(variables[117]*(1.0-exp(-1.0*(variables[140]-0.0)/variables[117])))*(variables[91]-variables[38]*exp(-1.0*(variables[140]-0.0)/variables[117]))*states[29]*states[17]*states[5]; - variables[166] = (variables[163]+variables[164]+variables[165])*(1.0-variables[128])*1.0*variables[127]; - variables[167] = 1.0/(1.0+exp(-(variables[140]-variables[52]-variables[129])/(variables[53]*(1.0+variables[130]/100.0)))); - variables[168] = (variables[140] == -41.8)?-41.80001:(variables[140] == 0.0)?0.0:(variables[140] == -6.8)?-6.80001:variables[140]; - variables[169] = (variables[140] == -1.8)?-1.80001:variables[140]; - variables[170] = 1.0/(1.0+exp((variables[140]+37.4+variables[57])/(5.3+variables[56]))); - variables[171] = 0.001*(44.3+230.0*exp(-pow((variables[140]+36.0)/10.0, 2.0))); - variables[172] = 2.0*variables[58]*variables[140]/(variables[117]*(1.0-exp(-1.0*variables[140]*2.0/variables[117])))*(states[30]-variables[35]*exp(-2.0*variables[140]/variables[117]))*states[18]*states[19]; - variables[173] = 1.0/(1.0+exp(-(variables[140]+38.3)/5.5)); - variables[174] = 0.001/(1.068*exp((variables[140]+38.3)/30.0)+1.068*exp(-(variables[140]+38.3)/30.0)); - variables[175] = 1.0/(1.0+exp((variables[140]+58.7)/3.8)); - variables[176] = 1.0/(16.67*exp(-(variables[140]+75.0)/83.3)+16.67*exp((variables[140]+75.0)/15.38))+variables[59]; - variables[177] = variables[90]*(variables[140]-variables[138])*states[20]*states[21]; - variables[178] = 1.0/(1.0+exp((variables[140]+49.0)/13.0)); - variables[179] = 0.001*0.6*(65.17/(0.57*exp(-0.08*(variables[140]+44.0))+0.065*exp(0.1*(variables[140]+45.93)))+10.1); - variables[180] = 1.0/(1.0+exp(-(variables[140]-19.3)/15.0)); - variables[181] = 0.001*0.66*1.4*(15.59/(1.037*exp(0.09*(variables[140]+30.61))+0.369*exp(-0.12*(variables[140]+23.84)))+2.98); - variables[182] = variables[62]*(variables[140]-variables[138])*(0.9*states[23]+0.1*states[22])*states[24]; - variables[183] = 1.0/(1.0+exp(-(variables[140]+23.2)/6.6))/(0.84655354/(37.2*exp(variables[140]/11.9)+0.96*exp(-variables[140]/18.5))); - variables[184] = 4.0*((37.2*exp(variables[140]/15.9)+0.96*exp(-variables[140]/22.5))/0.84655354-1.0/(1.0+exp(-(variables[140]+23.2)/10.6))/(0.84655354/(37.2*exp(variables[140]/15.9)+0.96*exp(-variables[140]/22.5)))); - variables[185] = 1.0/(1.0+exp(-(variables[140]+10.0144)/7.6607)); - variables[186] = 0.84655354/(4.2*exp(variables[140]/17.0)+0.15*exp(-variables[140]/21.6)); - variables[187] = 1.0/(30.0*exp(variables[140]/10.0)+exp(-variables[140]/12.0)); - variables[188] = 1.0/(100.0*exp(-variables[140]/54.645)+656.0*exp(variables[140]/106.157)); - variables[189] = 1.0/(1.0+exp((variables[140]+28.6)/17.1)); - variables[190] = variables[133]*(variables[140]-variables[134])*pow(states[28], 2.0); - variables[191] = sqrt(1.0/(1.0+exp(-(variables[140]+0.6383-variables[135])/10.7071))); - variables[192] = 28.0/(1.0+exp(-(variables[140]-40.0-variables[135])/3.0)); - variables[193] = 1.0*exp(-(variables[140]-variables[135]-5.0)/25.0); - variables[194] = (variables[45] > 0.0)?variables[60]*variables[61]*(variables[140]-variables[138])*(1.0+exp((variables[140]+20.0)/20.0))*states[25]:0.0; - variables[195] = 10.0*exp(0.0133*(variables[140]+40.0)); - variables[196] = variables[136]/(variables[136]+variables[195]); - variables[197] = 1.0/(variables[136]+variables[195]); - variables[198] = variables[92]*variables[83]*pow(1.0+pow(variables[81]/variables[37], 1.2), -1.0)*pow(1.0+pow(variables[82]/variables[91], 1.3), -1.0)*pow(1.0+exp(-(variables[140]-variables[137]+110.0)/20.0), -1.0); - variables[199] = exp(-variables[79]*variables[140]/(2.0*variables[117])); - variables[200] = 1.0+states[30]/variables[74]*(1.0+exp(-variables[77]*variables[140]/variables[117])+variables[91]/variables[75])+variables[91]/variables[67]*(1.0+variables[91]/variables[69]*(1.0+variables[91]/variables[71])); - variables[201] = exp(variables[79]*variables[140]/(2.0*variables[117])); - variables[202] = 1.0+variables[35]/variables[76]*(1.0+exp(variables[78]*variables[140]/variables[117]))+variables[38]/variables[68]*(1.0+variables[38]/variables[70]*(1.0+variables[38]/variables[72])); - variables[203] = -0.02839*(variables[168]+41.8)/(exp(-(variables[168]+41.8)/2.5)-1.0)-0.0849*(variables[168]+6.8)/(exp(-(variables[168]+6.8)/4.8)-1.0); - variables[204] = 0.01143*(variables[169]+1.8)/(exp((variables[169]+1.8)/2.5)-1.0); - variables[205] = 1.0/(variables[192]+variables[193]); - variables[206] = states[30]/variables[74]*exp(-variables[77]*variables[140]/variables[117])/variables[200]; - variables[207] = variables[91]/variables[67]*variables[91]/variables[69]*(1.0+variables[91]/variables[71])*exp(variables[79]*variables[140]/(2.0*variables[117]))/variables[200]; - variables[208] = variables[35]/variables[76]*exp(variables[78]*variables[140]/variables[117])/variables[202]; - variables[209] = variables[38]/variables[68]*variables[38]/variables[70]*(1.0+variables[38]/variables[72])*exp(-variables[79]*variables[140]/(2.0*variables[117]))/variables[202]; - variables[210] = 0.001/(variables[203]+variables[204]); - variables[211] = variables[199]*variables[94]*(variables[209]+variables[208])+variables[208]*variables[201]*(variables[93]+variables[199]); - variables[212] = variables[201]*variables[93]*(variables[207]+variables[206])+variables[199]*variables[206]*(variables[94]+variables[201]); - variables[213] = variables[207]*variables[93]*(variables[209]+variables[208])+variables[206]*variables[209]*(variables[93]+variables[199]); - variables[214] = variables[209]*variables[94]*(variables[207]+variables[206])+variables[207]*variables[208]*(variables[94]+variables[201]); - variables[215] = (1.0-variables[80])*variables[73]*(variables[212]*variables[208]-variables[211]*variables[206])/(variables[211]+variables[212]+variables[213]+variables[214]); - variables[216] = variables[143]+variables[182]+variables[190]+variables[177]+variables[198]+variables[215]+variables[148]+variables[166]+variables[172]+variables[194]+variables[158]; + variables[5] = states[1]; + variables[2] = variables[3]*log(variables[4]/variables[5]); + variables[9] = 0.5*variables[3]*log(variables[10]/states[0]); + variables[21] = (variables[122] >= 1.0)?variables[121]:states[15]; + variables[14] = variables[20]*variables[24]*pow(1.0+pow(variables[23]/variables[7], 1.2), -1.0)*pow(1.0+pow(variables[22]/variables[5], 1.3), -1.0)*pow(1.0+exp(-(variables[21]-variables[2]+110.0)/20.0), -1.0); + variables[50] = 1.0+variables[10]/variables[48]*(1.0+exp(variables[49]*variables[21]/variables[3]))+variables[4]/variables[51]*(1.0+variables[4]/variables[52]*(1.0+variables[4]/variables[47])); + variables[27] = variables[10]/variables[48]*exp(variables[49]*variables[21]/variables[3])/variables[50]; + variables[42] = 1.0+states[0]/variables[40]*(1.0+exp(-variables[41]*variables[21]/variables[3])+variables[5]/variables[46])+variables[5]/variables[43]*(1.0+variables[5]/variables[44]*(1.0+variables[5]/variables[39])); + variables[29] = states[0]/variables[40]*exp(-variables[41]*variables[21]/variables[3])/variables[42]; + variables[36] = variables[5]/(variables[39]+variables[5]); + variables[37] = exp(variables[45]*variables[21]/(2.0*variables[3])); + variables[33] = exp(-variables[45]*variables[21]/(2.0*variables[3])); + variables[38] = variables[5]/variables[43]*variables[5]/variables[44]*(1.0+variables[5]/variables[39])*exp(variables[45]*variables[21]/(2.0*variables[3]))/variables[42]; + variables[26] = variables[37]*variables[36]*(variables[38]+variables[29])+variables[33]*variables[29]*(variables[35]+variables[37]); + variables[34] = variables[4]/variables[51]*variables[4]/variables[52]*(1.0+variables[4]/variables[47])*exp(-variables[45]*variables[21]/(2.0*variables[3]))/variables[50]; + variables[28] = variables[33]*variables[35]*(variables[34]+variables[27])+variables[27]*variables[37]*(variables[36]+variables[33]); + variables[31] = variables[34]*variables[35]*(variables[38]+variables[29])+variables[38]*variables[27]*(variables[35]+variables[37]); + variables[32] = variables[38]*variables[36]*(variables[34]+variables[27])+variables[29]*variables[34]*(variables[36]+variables[33]); + variables[13] = (1.0-variables[25])*variables[30]*(variables[26]*variables[27]-variables[28]*variables[29])/(variables[28]+variables[26]+variables[32]+variables[31]); + variables[53] = variables[54]*states[3]*(states[2]-states[0]); + variables[55] = states[2]-states[0]; + variables[56] = variables[57]-(variables[57]-variables[58])/(1.0+pow(variables[59]/states[2], variables[60])); + variables[61] = variables[62]/variables[56]; + variables[63] = variables[64]*variables[56]; + variables[67] = states[4]+states[3]+states[6]+states[5]; + variables[71] = (states[0]-states[7])/variables[72]; + variables[73] = variables[69]/(1.0+exp((-states[7]+variables[74])/variables[75])); + variables[76] = (states[8]-states[2])/variables[77]; + variables[78] = variables[79]*states[7]*(1.0-states[9])-variables[80]*states[9]; + variables[81] = variables[82]*states[7]*(1.0-(states[10]+states[11]))-variables[83]*states[10]; + variables[84] = variables[85]*variables[86]*(1.0-(states[10]+states[11]))-variables[87]*states[11]; + variables[88] = variables[89]*states[7]*(1.0-states[12])-variables[90]*states[12]; + variables[91] = variables[89]*states[0]*(1.0-states[13])-variables[90]*states[13]; + variables[92] = variables[93]*states[2]*(1.0-states[14])-variables[94]*states[14]; + variables[16] = states[16]*variables[133]*(variables[21]-variables[2])*(1.0-variables[135]); + variables[136] = states[16]*variables[134]*(variables[21]-variables[6])*(1.0-variables[135]); + variables[111] = variables[16]+variables[136]; + variables[112] = variables[157]*states[20]*states[19]*(variables[21]-variables[6]); + variables[113] = (variables[0] > 0.0)?variables[211]*variables[212]*(variables[21]-variables[6])*(1.0+exp((variables[21]+20.0)/20.0))*states[32]:0.0; + variables[102] = 2.0*variables[184]*variables[21]/(variables[3]*(1.0-exp(-1.0*variables[21]*2.0/variables[3])))*(states[0]-variables[10]*exp(-2.0*variables[21]/variables[3]))*states[25]*states[24]; + variables[101] = 2.0*variables[163]*(variables[21]-0.0)/(variables[3]*(1.0-exp(-1.0*(variables[21]-0.0)*2.0/variables[3])))*(states[0]-variables[10]*exp(-2.0*(variables[21]-0.0)/variables[3]))*states[23]*states[22]*states[21]; + variables[15] = 0.0000185*variables[163]*(variables[21]-0.0)/(variables[3]*(1.0-exp(-1.0*(variables[21]-0.0)/variables[3])))*(variables[5]-variables[4]*exp(-1.0*(variables[21]-0.0)/variables[3]))*states[23]*states[22]*states[21]; + variables[164] = 0.000365*variables[163]*(variables[21]-0.0)/(variables[3]*(1.0-exp(-1.0*(variables[21]-0.0)/variables[3])))*(variables[8]-variables[7]*exp(-1.0*(variables[21]-0.0)/variables[3]))*states[23]*states[22]*states[21]; + variables[114] = (variables[101]+variables[164]+variables[15])*(1.0-variables[165])*1.0*variables[162]; + variables[142] = variables[3]*log((variables[4]+0.12*variables[7])/(variables[5]+0.12*variables[8])); + variables[143] = variables[144]*pow(states[18], 3.0)*states[17]*(variables[21]-variables[142]); + variables[145] = variables[146]*pow(states[18], 3.0)*(variables[21]-variables[142]); + variables[12] = variables[143]+variables[145]; + variables[115] = variables[190]*(variables[21]-variables[6])*states[27]*states[26]; + variables[205] = variables[3]*log((variables[7]+0.12*variables[4])/(variables[8]+0.12*variables[5])); + variables[116] = variables[203]*(variables[21]-variables[205])*pow(states[31], 2.0); + variables[117] = variables[195]*(variables[21]-variables[6])*(0.9*states[29]+0.1*states[30])*states[28]; + variables[110] = variables[111]+variables[117]+variables[116]+variables[115]+variables[14]+variables[13]+variables[12]+variables[114]+variables[102]+variables[113]+variables[112]; + variables[139] = 1.0/(0.36*(variables[21]+148.8-variables[137]-variables[138])/(exp(0.066*(variables[21]+148.8-variables[137]-variables[138]))-1.0)+0.1*(variables[21]+87.3-variables[137]-variables[138])/(1.0-exp(-0.2*(variables[21]+87.3-variables[137]-variables[138]))))-0.054; + variables[140] = (variables[21] < -(80.0-variables[137]-variables[138]-variables[141]))?0.01329+0.99921/(1.0+exp((variables[21]+97.134-variables[137]-variables[138]-variables[141])/8.1752)):0.0002501*exp(-(variables[21]-variables[137]-variables[138]-variables[141])/12.861); + variables[147] = 1.0/(1.0+exp(-(variables[21]+42.0504)/8.3106)); + variables[148] = variables[21]+41.0; + variables[149] = (fabs(variables[148]) < variables[150])?2000.0:200.0*variables[148]/(1.0-exp(-0.1*variables[148])); + variables[151] = 8000.0*exp(-0.056*(variables[21]+66.0)); + variables[152] = 1.0/(variables[149]+variables[151]); + variables[153] = 1.0/(1.0+exp((variables[21]+69.804)/4.4565)); + variables[154] = 20.0*exp(-0.125*(variables[21]+75.0)); + variables[155] = 2000.0/(320.0*exp(-0.1*(variables[21]+75.0))+1.0); + variables[156] = 1.0/(variables[154]+variables[155]); + variables[158] = 1.0/(1.0+exp((variables[21]+6.0)/-8.6)); + variables[159] = 0.009/(1.0+exp((variables[21]+5.0)/12.0))+0.0005; + variables[160] = 1.0/(1.0+exp((variables[21]+7.5)/10.0)); + variables[161] = 0.59/(1.0+exp((variables[21]+60.0)/10.0))+3.05; + variables[168] = 1.0/(1.0+exp(-(variables[21]-variables[169]-variables[166])/(variables[170]*(1.0+variables[167]/100.0)))); + variables[174] = (variables[21] == -41.8)?-41.80001:(variables[21] == 0.0)?0.0:(variables[21] == -6.8)?-6.80001:variables[21]; + variables[172] = -0.02839*(variables[174]+41.8)/(exp(-(variables[174]+41.8)/2.5)-1.0)-0.0849*(variables[174]+6.8)/(exp(-(variables[174]+6.8)/4.8)-1.0); + variables[175] = (variables[21] == -1.8)?-1.80001:variables[21]; + variables[173] = 0.01143*(variables[175]+1.8)/(exp((variables[175]+1.8)/2.5)-1.0); + variables[171] = 0.001/(variables[172]+variables[173]); + variables[176] = 1.0/(1.0+exp((variables[21]+37.4+variables[177])/(5.3+variables[178]))); + variables[179] = 0.001*(44.3+230.0*exp(-pow((variables[21]+36.0)/10.0, 2.0))); + variables[180] = variables[181]/(variables[181]+states[0]); + variables[182] = 0.001*variables[180]/variables[183]; + variables[185] = 1.0/(1.0+exp(-(variables[21]+38.3)/5.5)); + variables[186] = 0.001/(1.068*exp((variables[21]+38.3)/30.0)+1.068*exp(-(variables[21]+38.3)/30.0)); + variables[187] = 1.0/(1.0+exp((variables[21]+58.7)/3.8)); + variables[188] = 1.0/(16.67*exp(-(variables[21]+75.0)/83.3)+16.67*exp((variables[21]+75.0)/15.38))+variables[189]; + variables[191] = 1.0/(1.0+exp((variables[21]+49.0)/13.0)); + variables[192] = 0.001*0.6*(65.17/(0.57*exp(-0.08*(variables[21]+44.0))+0.065*exp(0.1*(variables[21]+45.93)))+10.1); + variables[193] = 1.0/(1.0+exp(-(variables[21]-19.3)/15.0)); + variables[194] = 0.001*0.66*1.4*(15.59/(1.037*exp(0.09*(variables[21]+30.61))+0.369*exp(-0.12*(variables[21]+23.84)))+2.98); + variables[196] = 1.0/(1.0+exp(-(variables[21]+23.2)/6.6))/(0.84655354/(37.2*exp(variables[21]/11.9)+0.96*exp(-variables[21]/18.5))); + variables[197] = 4.0*((37.2*exp(variables[21]/15.9)+0.96*exp(-variables[21]/22.5))/0.84655354-1.0/(1.0+exp(-(variables[21]+23.2)/10.6))/(0.84655354/(37.2*exp(variables[21]/15.9)+0.96*exp(-variables[21]/22.5)))); + variables[198] = 1.0/(1.0+exp(-(variables[21]+10.0144)/7.6607)); + variables[199] = 0.84655354/(4.2*exp(variables[21]/17.0)+0.15*exp(-variables[21]/21.6)); + variables[200] = 1.0/(30.0*exp(variables[21]/10.0)+exp(-variables[21]/12.0)); + variables[201] = 1.0/(100.0*exp(-variables[21]/54.645)+656.0*exp(variables[21]/106.157)); + variables[202] = 1.0/(1.0+exp((variables[21]+28.6)/17.1)); + variables[207] = sqrt(1.0/(1.0+exp(-(variables[21]+0.6383-variables[206])/10.7071))); + variables[209] = 28.0/(1.0+exp(-(variables[21]-40.0-variables[206])/3.0)); + variables[210] = 1.0*exp(-(variables[21]-variables[206]-5.0)/25.0); + variables[208] = 1.0/(variables[209]+variables[210]); + variables[214] = 10.0*exp(0.0133*(variables[21]+40.0)); + variables[215] = variables[213]/(variables[213]+variables[214]); + variables[216] = 1.0/(variables[213]+variables[214]); } diff --git a/tests/resources/generator/fabbri_fantini_wilders_severi_human_san_model_2017/model.h b/tests/resources/generator/fabbri_fantini_wilders_severi_human_san_model_2017/model.h index 9406d1e79..b76a0a63a 100644 --- a/tests/resources/generator/fabbri_fantini_wilders_severi_human_san_model_2017/model.h +++ b/tests/resources/generator/fabbri_fantini_wilders_severi_human_san_model_2017/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/fabbri_fantini_wilders_severi_human_san_model_2017/model.py b/tests/resources/generator/fabbri_fantini_wilders_severi_human_san_model_2017/model.py index cac4eb67a..023c5f72e 100644 --- a/tests/resources/generator/fabbri_fantini_wilders_severi_human_san_model_2017/model.py +++ b/tests/resources/generator/fabbri_fantini_wilders_severi_human_san_model_2017/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 33 VARIABLE_COUNT = 217 @@ -22,225 +22,238 @@ class VariableType(Enum): VOI_INFO = {"name": "time", "units": "second", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} STATE_INFO = [ - {"name": "R", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.STATE}, + {"name": "Ca_sub", "units": "millimolar", "component": "Ca_dynamics", "type": VariableType.STATE}, + {"name": "Nai_", "units": "millimolar", "component": "Nai_concentration", "type": VariableType.STATE}, + {"name": "Ca_jsr", "units": "millimolar", "component": "Ca_dynamics", "type": VariableType.STATE}, {"name": "O", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.STATE}, - {"name": "I", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.STATE}, + {"name": "R", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.STATE}, {"name": "RI", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.STATE}, - {"name": "Ca_jsr", "units": "millimolar", "component": "Ca_dynamics", "type": VariableType.STATE}, - {"name": "fCa", "units": "dimensionless", "component": "i_CaL_fCa_gate", "type": VariableType.STATE}, + {"name": "I", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.STATE}, + {"name": "Cai", "units": "millimolar", "component": "Ca_dynamics", "type": VariableType.STATE}, + {"name": "Ca_nsr", "units": "millimolar", "component": "Ca_dynamics", "type": VariableType.STATE}, {"name": "fTC", "units": "dimensionless", "component": "Ca_buffering", "type": VariableType.STATE}, {"name": "fTMC", "units": "dimensionless", "component": "Ca_buffering", "type": VariableType.STATE}, {"name": "fTMM", "units": "dimensionless", "component": "Ca_buffering", "type": VariableType.STATE}, {"name": "fCMi", "units": "dimensionless", "component": "Ca_buffering", "type": VariableType.STATE}, {"name": "fCMs", "units": "dimensionless", "component": "Ca_buffering", "type": VariableType.STATE}, {"name": "fCQ", "units": "dimensionless", "component": "Ca_buffering", "type": VariableType.STATE}, - {"name": "Cai", "units": "millimolar", "component": "Ca_dynamics", "type": VariableType.STATE}, - {"name": "Ca_nsr", "units": "millimolar", "component": "Ca_dynamics", "type": VariableType.STATE}, + {"name": "V_ode", "units": "millivolt", "component": "Membrane", "type": VariableType.STATE}, {"name": "y", "units": "dimensionless", "component": "i_f_y_gate", "type": VariableType.STATE}, - {"name": "m", "units": "dimensionless", "component": "i_Na_m_gate", "type": VariableType.STATE}, {"name": "h", "units": "dimensionless", "component": "i_Na_h_gate", "type": VariableType.STATE}, + {"name": "m", "units": "dimensionless", "component": "i_Na_m_gate", "type": VariableType.STATE}, + {"name": "s_Kur", "units": "dimensionless", "component": "i_Kur_sKur_gate", "type": VariableType.STATE}, + {"name": "r_Kur", "units": "dimensionless", "component": "i_Kur_rKur_gate", "type": VariableType.STATE}, + {"name": "fCa", "units": "dimensionless", "component": "i_CaL_fCa_gate", "type": VariableType.STATE}, {"name": "fL", "units": "dimensionless", "component": "i_CaL_fL_gate", "type": VariableType.STATE}, - {"name": "dT", "units": "dimensionless", "component": "i_CaT_dT_gate", "type": VariableType.STATE}, + {"name": "dL", "units": "dimensionless", "component": "i_CaL_dL_gate", "type": VariableType.STATE}, {"name": "fT", "units": "dimensionless", "component": "i_CaT_fT_gate", "type": VariableType.STATE}, - {"name": "q", "units": "dimensionless", "component": "i_to_q_gate", "type": VariableType.STATE}, + {"name": "dT", "units": "dimensionless", "component": "i_CaT_dT_gate", "type": VariableType.STATE}, {"name": "r", "units": "dimensionless", "component": "i_to_r_gate", "type": VariableType.STATE}, - {"name": "paS", "units": "dimensionless", "component": "i_Kr_pa_gate", "type": VariableType.STATE}, - {"name": "paF", "units": "dimensionless", "component": "i_Kr_pa_gate", "type": VariableType.STATE}, + {"name": "q", "units": "dimensionless", "component": "i_to_q_gate", "type": VariableType.STATE}, {"name": "piy", "units": "dimensionless", "component": "i_Kr_pi_gate", "type": VariableType.STATE}, - {"name": "a", "units": "dimensionless", "component": "i_KACh_a_gate", "type": VariableType.STATE}, - {"name": "r_Kur", "units": "dimensionless", "component": "i_Kur_rKur_gate", "type": VariableType.STATE}, - {"name": "s_Kur", "units": "dimensionless", "component": "i_Kur_sKur_gate", "type": VariableType.STATE}, + {"name": "paF", "units": "dimensionless", "component": "i_Kr_pa_gate", "type": VariableType.STATE}, + {"name": "paS", "units": "dimensionless", "component": "i_Kr_pa_gate", "type": VariableType.STATE}, {"name": "n", "units": "dimensionless", "component": "i_Ks_n_gate", "type": VariableType.STATE}, - {"name": "dL", "units": "dimensionless", "component": "i_CaL_dL_gate", "type": VariableType.STATE}, - {"name": "Ca_sub", "units": "millimolar", "component": "Ca_dynamics", "type": VariableType.STATE}, - {"name": "V_ode", "units": "millivolt", "component": "Membrane", "type": VariableType.STATE}, - {"name": "Nai_", "units": "millimolar", "component": "Nai_concentration", "type": VariableType.STATE} + {"name": "a", "units": "dimensionless", "component": "i_KACh_a_gate", "type": VariableType.STATE} ] VARIABLE_INFO = [ - {"name": "EC50_SR", "units": "millimolar", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, - {"name": "HSR", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, - {"name": "MaxSR", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, - {"name": "MinSR", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, - {"name": "kiCa", "units": "per_millimolar_second", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, - {"name": "kim", "units": "per_second", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, - {"name": "koCa", "units": "per_millimolar2_second", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, - {"name": "kom", "units": "per_second", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, - {"name": "ks", "units": "per_second", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, - {"name": "CM_tot", "units": "millimolar", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "CQ_tot", "units": "millimolar", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "Mgi", "units": "millimolar", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "TC_tot", "units": "millimolar", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "TMC_tot", "units": "millimolar", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "kb_CM", "units": "per_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "kb_CQ", "units": "per_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "kb_TC", "units": "per_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "kb_TMC", "units": "per_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "kb_TMM", "units": "per_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "kf_CM", "units": "per_millimolar_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "kf_CQ", "units": "per_millimolar_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "kf_TC", "units": "per_millimolar_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "kf_TMC", "units": "per_millimolar_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "kf_TMM", "units": "per_millimolar_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, - {"name": "K_up", "units": "millimolar", "component": "Ca_intracellular_fluxes", "type": VariableType.CONSTANT}, - {"name": "P_up_basal", "units": "millimolar_per_second", "component": "Ca_intracellular_fluxes", "type": VariableType.CONSTANT}, - {"name": "slope_up", "units": "millimolar", "component": "Ca_intracellular_fluxes", "type": VariableType.CONSTANT}, - {"name": "tau_dif_Ca", "units": "second", "component": "Ca_intracellular_fluxes", "type": VariableType.CONSTANT}, - {"name": "tau_tr", "units": "second", "component": "Ca_intracellular_fluxes", "type": VariableType.CONSTANT}, - {"name": "L_cell", "units": "micrometre", "component": "Cell_parameters", "type": VariableType.CONSTANT}, - {"name": "L_sub", "units": "micrometre", "component": "Cell_parameters", "type": VariableType.CONSTANT}, - {"name": "R_cell", "units": "micrometre", "component": "Cell_parameters", "type": VariableType.CONSTANT}, - {"name": "V_i_part", "units": "dimensionless", "component": "Cell_parameters", "type": VariableType.CONSTANT}, - {"name": "V_jsr_part", "units": "dimensionless", "component": "Cell_parameters", "type": VariableType.CONSTANT}, - {"name": "V_nsr_part", "units": "dimensionless", "component": "Cell_parameters", "type": VariableType.CONSTANT}, - {"name": "Cao", "units": "millimolar", "component": "Ionic_values", "type": VariableType.CONSTANT}, - {"name": "Ki", "units": "millimolar", "component": "Ionic_values", "type": VariableType.CONSTANT}, - {"name": "Ko", "units": "millimolar", "component": "Ionic_values", "type": VariableType.CONSTANT}, - {"name": "Nao", "units": "millimolar", "component": "Ionic_values", "type": VariableType.CONSTANT}, - {"name": "C", "units": "microF", "component": "Membrane", "type": VariableType.CONSTANT}, - {"name": "F", "units": "coulomb_per_mole", "component": "Membrane", "type": VariableType.CONSTANT}, - {"name": "R", "units": "joule_per_kilomole_kelvin", "component": "Membrane", "type": VariableType.CONSTANT}, - {"name": "T", "units": "kelvin", "component": "Membrane", "type": VariableType.CONSTANT}, - {"name": "clamp_mode", "units": "dimensionless", "component": "Membrane", "type": VariableType.CONSTANT}, - {"name": "Nai_clamp", "units": "dimensionless", "component": "Nai_concentration", "type": VariableType.CONSTANT}, {"name": "ACh", "units": "millimolar", "component": "Rate_modulation_experiments", "type": VariableType.CONSTANT}, {"name": "Iso_1_uM", "units": "dimensionless", "component": "Rate_modulation_experiments", "type": VariableType.CONSTANT}, - {"name": "V_holding", "units": "millivolt", "component": "Voltage_clamp", "type": VariableType.CONSTANT}, - {"name": "V_test", "units": "millivolt", "component": "Voltage_clamp", "type": VariableType.CONSTANT}, - {"name": "t_holding", "units": "second", "component": "Voltage_clamp", "type": VariableType.CONSTANT}, - {"name": "t_test", "units": "second", "component": "Voltage_clamp", "type": VariableType.CONSTANT}, - {"name": "P_CaL", "units": "nanoA_per_millimolar", "component": "i_CaL", "type": VariableType.CONSTANT}, - {"name": "V_dL", "units": "millivolt", "component": "i_CaL_dL_gate", "type": VariableType.CONSTANT}, - {"name": "k_dL", "units": "millivolt", "component": "i_CaL_dL_gate", "type": VariableType.CONSTANT}, - {"name": "Km_fCa", "units": "millimolar", "component": "i_CaL_fCa_gate", "type": VariableType.CONSTANT}, - {"name": "alpha_fCa", "units": "per_second", "component": "i_CaL_fCa_gate", "type": VariableType.CONSTANT}, - {"name": "k_fL", "units": "millivolt", "component": "i_CaL_fL_gate", "type": VariableType.CONSTANT}, - {"name": "shift_fL", "units": "millivolt", "component": "i_CaL_fL_gate", "type": VariableType.CONSTANT}, - {"name": "P_CaT", "units": "nanoA_per_millimolar", "component": "i_CaT", "type": VariableType.CONSTANT}, - {"name": "offset_fT", "units": "second", "component": "i_CaT_fT_gate", "type": VariableType.CONSTANT}, - {"name": "ACh_on", "units": "dimensionless", "component": "i_KACh", "type": VariableType.CONSTANT}, - {"name": "g_KACh", "units": "microS", "component": "i_KACh", "type": VariableType.CONSTANT}, - {"name": "g_Kr", "units": "microS", "component": "i_Kr", "type": VariableType.CONSTANT}, - {"name": "g_Ks_", "units": "microS", "component": "i_Ks", "type": VariableType.CONSTANT}, - {"name": "g_Kur", "units": "microS", "component": "i_Kur", "type": VariableType.CONSTANT}, - {"name": "g_Na", "units": "microS", "component": "i_Na", "type": VariableType.CONSTANT}, - {"name": "g_Na_L", "units": "microS", "component": "i_Na", "type": VariableType.CONSTANT}, - {"name": "K1ni", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, - {"name": "K1no", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, - {"name": "K2ni", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, - {"name": "K2no", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, - {"name": "K3ni", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, - {"name": "K3no", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, + {"name": "E_Na", "units": "millivolt", "component": "Ionic_values", "type": VariableType.ALGEBRAIC}, + {"name": "RTONF", "units": "millivolt", "component": "Membrane", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "Nao", "units": "millimolar", "component": "Ionic_values", "type": VariableType.CONSTANT}, + {"name": "Nai", "units": "millimolar", "component": "Nai_concentration", "type": VariableType.ALGEBRAIC}, + {"name": "E_K", "units": "millivolt", "component": "Ionic_values", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "Ko", "units": "millimolar", "component": "Ionic_values", "type": VariableType.CONSTANT}, + {"name": "Ki", "units": "millimolar", "component": "Ionic_values", "type": VariableType.CONSTANT}, + {"name": "E_Ca", "units": "millivolt", "component": "Ionic_values", "type": VariableType.ALGEBRAIC}, + {"name": "Cao", "units": "millimolar", "component": "Ionic_values", "type": VariableType.CONSTANT}, + {"name": "Nai_clamp", "units": "dimensionless", "component": "Nai_concentration", "type": VariableType.CONSTANT}, + {"name": "i_Na", "units": "nanoA", "component": "i_Na", "type": VariableType.ALGEBRAIC}, + {"name": "i_NaCa", "units": "nanoA", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, + {"name": "i_NaK", "units": "nanoA", "component": "i_NaK", "type": VariableType.ALGEBRAIC}, + {"name": "i_siNa", "units": "nanoA", "component": "i_CaL", "type": VariableType.ALGEBRAIC}, + {"name": "i_fNa", "units": "nanoA", "component": "i_f", "type": VariableType.ALGEBRAIC}, + {"name": "F", "units": "coulomb_per_mole", "component": "Membrane", "type": VariableType.CONSTANT}, + {"name": "V_i", "units": "millimetre3", "component": "Cell_parameters", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "V_sub", "units": "millimetre3", "component": "Cell_parameters", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "Iso_increase", "units": "dimensionless", "component": "i_NaK", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "V", "units": "millivolt", "component": "Membrane", "type": VariableType.ALGEBRAIC}, + {"name": "Km_Nap", "units": "millimolar", "component": "i_NaK", "type": VariableType.CONSTANT}, + {"name": "Km_Kp", "units": "millimolar", "component": "i_NaK", "type": VariableType.CONSTANT}, + {"name": "i_NaK_max", "units": "nanoA", "component": "i_NaK", "type": VariableType.CONSTANT}, + {"name": "blockade_NaCa", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.CONSTANT}, + {"name": "x2", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, + {"name": "k21", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, + {"name": "x1", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, + {"name": "k12", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, {"name": "K_NaCa", "units": "nanoA", "component": "i_NaCa", "type": VariableType.CONSTANT}, + {"name": "x4", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, + {"name": "x3", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, + {"name": "k41", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, + {"name": "k23", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, + {"name": "k34", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "k43", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, + {"name": "k32", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, + {"name": "k14", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, + {"name": "K3ni", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, {"name": "Kci", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, + {"name": "Qci", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.CONSTANT}, + {"name": "di", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, + {"name": "K1ni", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, + {"name": "K2ni", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, + {"name": "Qn", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.CONSTANT}, {"name": "Kcni", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, + {"name": "K3no", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, {"name": "Kco", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, - {"name": "Qci", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.CONSTANT}, {"name": "Qco", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.CONSTANT}, - {"name": "Qn", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.CONSTANT}, - {"name": "blockade_NaCa", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.CONSTANT}, - {"name": "Km_Kp", "units": "millimolar", "component": "i_NaK", "type": VariableType.CONSTANT}, - {"name": "Km_Nap", "units": "millimolar", "component": "i_NaK", "type": VariableType.CONSTANT}, - {"name": "i_NaK_max", "units": "nanoA", "component": "i_NaK", "type": VariableType.CONSTANT}, - {"name": "delta_m", "units": "millivolt", "component": "i_Na_m_gate", "type": VariableType.CONSTANT}, - {"name": "Km_f", "units": "millimolar", "component": "i_f", "type": VariableType.CONSTANT}, - {"name": "alpha", "units": "dimensionless", "component": "i_f", "type": VariableType.CONSTANT}, - {"name": "blockade", "units": "dimensionless", "component": "i_f", "type": VariableType.CONSTANT}, - {"name": "g_f", "units": "microS", "component": "i_f", "type": VariableType.CONSTANT}, - {"name": "y_shift", "units": "millivolt", "component": "i_f_y_gate", "type": VariableType.CONSTANT}, - {"name": "g_to", "units": "microS", "component": "i_to", "type": VariableType.CONSTANT}, - {"name": "Nai", "units": "millimolar", "component": "Nai_concentration", "type": VariableType.ALGEBRAIC}, - {"name": "Iso_increase", "units": "dimensionless", "component": "i_NaK", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "k43", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "k34", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "do", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, + {"name": "K1no", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, + {"name": "K2no", "units": "millimolar", "component": "i_NaCa", "type": VariableType.CONSTANT}, {"name": "j_SRCarel", "units": "millimolar_per_second", "component": "Ca_SR_release", "type": VariableType.ALGEBRAIC}, + {"name": "ks", "units": "per_second", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, {"name": "diff", "units": "millimolar", "component": "Ca_SR_release", "type": VariableType.ALGEBRAIC}, {"name": "kCaSR", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.ALGEBRAIC}, + {"name": "MaxSR", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, + {"name": "MinSR", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, + {"name": "EC50_SR", "units": "millimolar", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, + {"name": "HSR", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, {"name": "koSRCa", "units": "per_millimolar2_second", "component": "Ca_SR_release", "type": VariableType.ALGEBRAIC}, + {"name": "koCa", "units": "per_millimolar2_second", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, {"name": "kiSRCa", "units": "per_millimolar_second", "component": "Ca_SR_release", "type": VariableType.ALGEBRAIC}, + {"name": "kiCa", "units": "per_millimolar_second", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, + {"name": "kim", "units": "per_second", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, + {"name": "kom", "units": "per_second", "component": "Ca_SR_release", "type": VariableType.CONSTANT}, {"name": "P_tot", "units": "dimensionless", "component": "Ca_SR_release", "type": VariableType.ALGEBRAIC}, {"name": "b_up", "units": "dimensionless", "component": "Ca_intracellular_fluxes", "type": VariableType.COMPUTED_CONSTANT}, {"name": "P_up", "units": "millimolar_per_second", "component": "Ca_intracellular_fluxes", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "P_up_basal", "units": "millimolar_per_second", "component": "Ca_intracellular_fluxes", "type": VariableType.CONSTANT}, {"name": "j_Ca_dif", "units": "millimolar_per_second", "component": "Ca_intracellular_fluxes", "type": VariableType.ALGEBRAIC}, + {"name": "tau_dif_Ca", "units": "second", "component": "Ca_intracellular_fluxes", "type": VariableType.CONSTANT}, {"name": "j_up", "units": "millimolar_per_second", "component": "Ca_intracellular_fluxes", "type": VariableType.ALGEBRAIC}, + {"name": "K_up", "units": "millimolar", "component": "Ca_intracellular_fluxes", "type": VariableType.CONSTANT}, + {"name": "slope_up", "units": "millimolar", "component": "Ca_intracellular_fluxes", "type": VariableType.CONSTANT}, {"name": "j_tr", "units": "millimolar_per_second", "component": "Ca_intracellular_fluxes", "type": VariableType.ALGEBRAIC}, + {"name": "tau_tr", "units": "second", "component": "Ca_intracellular_fluxes", "type": VariableType.CONSTANT}, {"name": "delta_fTC", "units": "per_second", "component": "Ca_buffering", "type": VariableType.ALGEBRAIC}, + {"name": "kf_TC", "units": "per_millimolar_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, + {"name": "kb_TC", "units": "per_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, {"name": "delta_fTMC", "units": "per_second", "component": "Ca_buffering", "type": VariableType.ALGEBRAIC}, + {"name": "kf_TMC", "units": "per_millimolar_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, + {"name": "kb_TMC", "units": "per_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, {"name": "delta_fTMM", "units": "per_second", "component": "Ca_buffering", "type": VariableType.ALGEBRAIC}, + {"name": "kf_TMM", "units": "per_millimolar_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, + {"name": "Mgi", "units": "millimolar", "component": "Ca_buffering", "type": VariableType.CONSTANT}, + {"name": "kb_TMM", "units": "per_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, {"name": "delta_fCMi", "units": "per_second", "component": "Ca_buffering", "type": VariableType.ALGEBRAIC}, + {"name": "kf_CM", "units": "per_millimolar_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, + {"name": "kb_CM", "units": "per_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, {"name": "delta_fCMs", "units": "per_second", "component": "Ca_buffering", "type": VariableType.ALGEBRAIC}, {"name": "delta_fCQ", "units": "per_second", "component": "Ca_buffering", "type": VariableType.ALGEBRAIC}, - {"name": "V_cell", "units": "millimetre3", "component": "Cell_parameters", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "V_sub", "units": "millimetre3", "component": "Cell_parameters", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "V_jsr", "units": "millimetre3", "component": "Cell_parameters", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "V_i", "units": "millimetre3", "component": "Cell_parameters", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "kf_CQ", "units": "per_millimolar_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, + {"name": "kb_CQ", "units": "per_second", "component": "Ca_buffering", "type": VariableType.CONSTANT}, + {"name": "TC_tot", "units": "millimolar", "component": "Ca_buffering", "type": VariableType.CONSTANT}, + {"name": "TMC_tot", "units": "millimolar", "component": "Ca_buffering", "type": VariableType.CONSTANT}, + {"name": "CM_tot", "units": "millimolar", "component": "Ca_buffering", "type": VariableType.CONSTANT}, + {"name": "CQ_tot", "units": "millimolar", "component": "Ca_buffering", "type": VariableType.CONSTANT}, {"name": "V_nsr", "units": "millimetre3", "component": "Cell_parameters", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "RTONF", "units": "millivolt", "component": "Membrane", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "V_jsr", "units": "millimetre3", "component": "Cell_parameters", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "i_siCa", "units": "nanoA", "component": "i_CaL", "type": VariableType.ALGEBRAIC}, + {"name": "i_CaT", "units": "nanoA", "component": "i_CaT", "type": VariableType.ALGEBRAIC}, + {"name": "V_cell", "units": "millimetre3", "component": "Cell_parameters", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "L_cell", "units": "micrometre", "component": "Cell_parameters", "type": VariableType.CONSTANT}, + {"name": "R_cell", "units": "micrometre", "component": "Cell_parameters", "type": VariableType.CONSTANT}, + {"name": "L_sub", "units": "micrometre", "component": "Cell_parameters", "type": VariableType.CONSTANT}, + {"name": "V_jsr_part", "units": "dimensionless", "component": "Cell_parameters", "type": VariableType.CONSTANT}, + {"name": "V_i_part", "units": "dimensionless", "component": "Cell_parameters", "type": VariableType.CONSTANT}, + {"name": "V_nsr_part", "units": "dimensionless", "component": "Cell_parameters", "type": VariableType.CONSTANT}, + {"name": "i_tot", "units": "nanoA", "component": "Membrane", "type": VariableType.ALGEBRAIC}, + {"name": "i_f", "units": "nanoA", "component": "i_f", "type": VariableType.ALGEBRAIC}, + {"name": "i_Kur", "units": "nanoA", "component": "i_Kur", "type": VariableType.ALGEBRAIC}, + {"name": "i_KACh", "units": "nanoA", "component": "i_KACh", "type": VariableType.ALGEBRAIC}, + {"name": "i_CaL", "units": "nanoA", "component": "i_CaL", "type": VariableType.ALGEBRAIC}, + {"name": "i_to", "units": "nanoA", "component": "i_to", "type": VariableType.ALGEBRAIC}, + {"name": "i_Ks", "units": "nanoA", "component": "i_Ks", "type": VariableType.ALGEBRAIC}, + {"name": "i_Kr", "units": "nanoA", "component": "i_Kr", "type": VariableType.ALGEBRAIC}, + {"name": "C", "units": "microF", "component": "Membrane", "type": VariableType.CONSTANT}, + {"name": "R", "units": "joule_per_kilomole_kelvin", "component": "Membrane", "type": VariableType.CONSTANT}, + {"name": "T", "units": "kelvin", "component": "Membrane", "type": VariableType.CONSTANT}, {"name": "V_clamp", "units": "millivolt", "component": "Voltage_clamp", "type": VariableType.ALGEBRAIC}, + {"name": "clamp_mode", "units": "dimensionless", "component": "Membrane", "type": VariableType.CONSTANT}, + {"name": "V_test", "units": "millivolt", "component": "Voltage_clamp", "type": VariableType.CONSTANT}, + {"name": "t_holding", "units": "second", "component": "Voltage_clamp", "type": VariableType.CONSTANT}, + {"name": "t_test", "units": "second", "component": "Voltage_clamp", "type": VariableType.CONSTANT}, + {"name": "V_holding", "units": "millivolt", "component": "Voltage_clamp", "type": VariableType.CONSTANT}, {"name": "G_f", "units": "microS", "component": "i_f", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "g_f", "units": "microS", "component": "i_f", "type": VariableType.CONSTANT}, + {"name": "Km_f", "units": "millimolar", "component": "i_f", "type": VariableType.CONSTANT}, {"name": "G_f_K", "units": "microS", "component": "i_f", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "alpha", "units": "dimensionless", "component": "i_f", "type": VariableType.CONSTANT}, {"name": "G_f_Na", "units": "microS", "component": "i_f", "type": VariableType.COMPUTED_CONSTANT}, {"name": "g_f_Na", "units": "microS", "component": "i_f", "type": VariableType.COMPUTED_CONSTANT}, {"name": "g_f_K", "units": "microS", "component": "i_f", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "blockade", "units": "dimensionless", "component": "i_f", "type": VariableType.CONSTANT}, + {"name": "i_fK", "units": "nanoA", "component": "i_f", "type": VariableType.ALGEBRAIC}, {"name": "ACh_shift", "units": "millivolt", "component": "i_f_y_gate", "type": VariableType.COMPUTED_CONSTANT}, {"name": "Iso_shift", "units": "millivolt", "component": "i_f_y_gate", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "E_mh", "units": "millivolt", "component": "i_Na", "type": VariableType.ALGEBRAIC}, - {"name": "Iso_increase", "units": "dimensionless", "component": "i_CaL", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "ACh_block", "units": "dimensionless", "component": "i_CaL", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "Iso_shift_dL", "units": "millivolt", "component": "i_CaL_dL_gate", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "Iso_slope_dL", "units": "dimensionless", "component": "i_CaL_dL_gate", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "fCa_infinity", "units": "dimensionless", "component": "i_CaL_fCa_gate", "type": VariableType.ALGEBRAIC}, - {"name": "tau_fCa", "units": "second", "component": "i_CaL_fCa_gate", "type": VariableType.ALGEBRAIC}, - {"name": "g_Ks", "units": "microS", "component": "i_Ks", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "E_Ks", "units": "millivolt", "component": "i_Ks", "type": VariableType.ALGEBRAIC}, - {"name": "Iso_shift", "units": "millivolt", "component": "i_Ks_n_gate", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "alpha_a", "units": "per_second", "component": "i_KACh_a_gate", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "E_Na", "units": "millivolt", "component": "Ionic_values", "type": VariableType.ALGEBRAIC}, - {"name": "E_K", "units": "millivolt", "component": "Ionic_values", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "E_Ca", "units": "millivolt", "component": "Ionic_values", "type": VariableType.ALGEBRAIC}, - {"name": "V", "units": "millivolt", "component": "Membrane", "type": VariableType.ALGEBRAIC}, - {"name": "i_fNa", "units": "nanoA", "component": "i_f", "type": VariableType.ALGEBRAIC}, - {"name": "i_fK", "units": "nanoA", "component": "i_f", "type": VariableType.ALGEBRAIC}, - {"name": "i_f", "units": "nanoA", "component": "i_f", "type": VariableType.ALGEBRAIC}, {"name": "tau_y", "units": "second", "component": "i_f_y_gate", "type": VariableType.ALGEBRAIC}, {"name": "y_infinity", "units": "dimensionless", "component": "i_f_y_gate", "type": VariableType.ALGEBRAIC}, + {"name": "y_shift", "units": "millivolt", "component": "i_f_y_gate", "type": VariableType.CONSTANT}, + {"name": "E_mh", "units": "millivolt", "component": "i_Na", "type": VariableType.ALGEBRAIC}, {"name": "i_Na_", "units": "nanoA", "component": "i_Na", "type": VariableType.ALGEBRAIC}, + {"name": "g_Na", "units": "microS", "component": "i_Na", "type": VariableType.CONSTANT}, {"name": "i_Na_L", "units": "nanoA", "component": "i_Na", "type": VariableType.ALGEBRAIC}, - {"name": "i_Na", "units": "nanoA", "component": "i_Na", "type": VariableType.ALGEBRAIC}, + {"name": "g_Na_L", "units": "microS", "component": "i_Na", "type": VariableType.CONSTANT}, {"name": "m_infinity", "units": "dimensionless", "component": "i_Na_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "E0_m", "units": "millivolt", "component": "i_Na_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_m", "units": "per_second", "component": "i_Na_m_gate", "type": VariableType.ALGEBRAIC}, + {"name": "delta_m", "units": "millivolt", "component": "i_Na_m_gate", "type": VariableType.CONSTANT}, {"name": "beta_m", "units": "per_second", "component": "i_Na_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_m", "units": "second", "component": "i_Na_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "h_infinity", "units": "dimensionless", "component": "i_Na_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_h", "units": "per_second", "component": "i_Na_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_h", "units": "per_second", "component": "i_Na_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_h", "units": "second", "component": "i_Na_h_gate", "type": VariableType.ALGEBRAIC}, - {"name": "i_Kur", "units": "nanoA", "component": "i_Kur", "type": VariableType.ALGEBRAIC}, + {"name": "g_Kur", "units": "microS", "component": "i_Kur", "type": VariableType.CONSTANT}, {"name": "r_Kur_infinity", "units": "dimensionless", "component": "i_Kur_rKur_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_r_Kur", "units": "second", "component": "i_Kur_rKur_gate", "type": VariableType.ALGEBRAIC}, {"name": "s_Kur_infinity", "units": "dimensionless", "component": "i_Kur_sKur_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_s_Kur", "units": "second", "component": "i_Kur_sKur_gate", "type": VariableType.ALGEBRAIC}, - {"name": "i_siCa", "units": "nanoA", "component": "i_CaL", "type": VariableType.ALGEBRAIC}, + {"name": "Iso_increase", "units": "dimensionless", "component": "i_CaL", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "P_CaL", "units": "nanoA_per_millimolar", "component": "i_CaL", "type": VariableType.CONSTANT}, {"name": "i_siK", "units": "nanoA", "component": "i_CaL", "type": VariableType.ALGEBRAIC}, - {"name": "i_siNa", "units": "nanoA", "component": "i_CaL", "type": VariableType.ALGEBRAIC}, - {"name": "i_CaL", "units": "nanoA", "component": "i_CaL", "type": VariableType.ALGEBRAIC}, + {"name": "ACh_block", "units": "dimensionless", "component": "i_CaL", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "Iso_shift_dL", "units": "millivolt", "component": "i_CaL_dL_gate", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "Iso_slope_dL", "units": "dimensionless", "component": "i_CaL_dL_gate", "type": VariableType.COMPUTED_CONSTANT}, {"name": "dL_infinity", "units": "dimensionless", "component": "i_CaL_dL_gate", "type": VariableType.ALGEBRAIC}, + {"name": "V_dL", "units": "millivolt", "component": "i_CaL_dL_gate", "type": VariableType.CONSTANT}, + {"name": "k_dL", "units": "millivolt", "component": "i_CaL_dL_gate", "type": VariableType.CONSTANT}, + {"name": "tau_dL", "units": "second", "component": "i_CaL_dL_gate", "type": VariableType.ALGEBRAIC}, + {"name": "alpha_dL", "units": "per_second", "component": "i_CaL_dL_gate", "type": VariableType.ALGEBRAIC}, + {"name": "beta_dL", "units": "per_second", "component": "i_CaL_dL_gate", "type": VariableType.ALGEBRAIC}, {"name": "adVm", "units": "millivolt", "component": "i_CaL_dL_gate", "type": VariableType.ALGEBRAIC}, {"name": "bdVm", "units": "millivolt", "component": "i_CaL_dL_gate", "type": VariableType.ALGEBRAIC}, {"name": "fL_infinity", "units": "dimensionless", "component": "i_CaL_fL_gate", "type": VariableType.ALGEBRAIC}, + {"name": "shift_fL", "units": "millivolt", "component": "i_CaL_fL_gate", "type": VariableType.CONSTANT}, + {"name": "k_fL", "units": "millivolt", "component": "i_CaL_fL_gate", "type": VariableType.CONSTANT}, {"name": "tau_fL", "units": "second", "component": "i_CaL_fL_gate", "type": VariableType.ALGEBRAIC}, - {"name": "i_CaT", "units": "nanoA", "component": "i_CaT", "type": VariableType.ALGEBRAIC}, + {"name": "fCa_infinity", "units": "dimensionless", "component": "i_CaL_fCa_gate", "type": VariableType.ALGEBRAIC}, + {"name": "Km_fCa", "units": "millimolar", "component": "i_CaL_fCa_gate", "type": VariableType.CONSTANT}, + {"name": "tau_fCa", "units": "second", "component": "i_CaL_fCa_gate", "type": VariableType.ALGEBRAIC}, + {"name": "alpha_fCa", "units": "per_second", "component": "i_CaL_fCa_gate", "type": VariableType.CONSTANT}, + {"name": "P_CaT", "units": "nanoA_per_millimolar", "component": "i_CaT", "type": VariableType.CONSTANT}, {"name": "dT_infinity", "units": "dimensionless", "component": "i_CaT_dT_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_dT", "units": "second", "component": "i_CaT_dT_gate", "type": VariableType.ALGEBRAIC}, {"name": "fT_infinity", "units": "dimensionless", "component": "i_CaT_fT_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_fT", "units": "second", "component": "i_CaT_fT_gate", "type": VariableType.ALGEBRAIC}, - {"name": "i_to", "units": "nanoA", "component": "i_to", "type": VariableType.ALGEBRAIC}, + {"name": "offset_fT", "units": "second", "component": "i_CaT_fT_gate", "type": VariableType.CONSTANT}, + {"name": "g_to", "units": "microS", "component": "i_to", "type": VariableType.CONSTANT}, {"name": "q_infinity", "units": "dimensionless", "component": "i_to_q_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_q", "units": "second", "component": "i_to_q_gate", "type": VariableType.ALGEBRAIC}, {"name": "r_infinity", "units": "dimensionless", "component": "i_to_r_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_r", "units": "second", "component": "i_to_r_gate", "type": VariableType.ALGEBRAIC}, - {"name": "i_Kr", "units": "nanoA", "component": "i_Kr", "type": VariableType.ALGEBRAIC}, + {"name": "g_Kr", "units": "microS", "component": "i_Kr", "type": VariableType.CONSTANT}, {"name": "alfapaF", "units": "per_second", "component": "i_Kr_pa_gate", "type": VariableType.ALGEBRAIC}, {"name": "betapaF", "units": "per_second", "component": "i_Kr_pa_gate", "type": VariableType.ALGEBRAIC}, {"name": "pa_infinity", "units": "dimensionless", "component": "i_Kr_pa_gate", "type": VariableType.ALGEBRAIC}, @@ -248,33 +261,20 @@ class VariableType(Enum): {"name": "tau_paF", "units": "second", "component": "i_Kr_pa_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_pi", "units": "second", "component": "i_Kr_pi_gate", "type": VariableType.ALGEBRAIC}, {"name": "pi_infinity", "units": "dimensionless", "component": "i_Kr_pi_gate", "type": VariableType.ALGEBRAIC}, - {"name": "i_Ks", "units": "nanoA", "component": "i_Ks", "type": VariableType.ALGEBRAIC}, + {"name": "g_Ks", "units": "microS", "component": "i_Ks", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "g_Ks_", "units": "microS", "component": "i_Ks", "type": VariableType.CONSTANT}, + {"name": "E_Ks", "units": "millivolt", "component": "i_Ks", "type": VariableType.ALGEBRAIC}, + {"name": "Iso_shift", "units": "millivolt", "component": "i_Ks_n_gate", "type": VariableType.COMPUTED_CONSTANT}, {"name": "n_infinity", "units": "dimensionless", "component": "i_Ks_n_gate", "type": VariableType.ALGEBRAIC}, + {"name": "tau_n", "units": "second", "component": "i_Ks_n_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_n", "units": "per_second", "component": "i_Ks_n_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_n", "units": "per_second", "component": "i_Ks_n_gate", "type": VariableType.ALGEBRAIC}, - {"name": "i_KACh", "units": "nanoA", "component": "i_KACh", "type": VariableType.ALGEBRAIC}, + {"name": "ACh_on", "units": "dimensionless", "component": "i_KACh", "type": VariableType.CONSTANT}, + {"name": "g_KACh", "units": "microS", "component": "i_KACh", "type": VariableType.CONSTANT}, + {"name": "alpha_a", "units": "per_second", "component": "i_KACh_a_gate", "type": VariableType.COMPUTED_CONSTANT}, {"name": "beta_a", "units": "per_second", "component": "i_KACh_a_gate", "type": VariableType.ALGEBRAIC}, {"name": "a_infinity", "units": "dimensionless", "component": "i_KACh_a_gate", "type": VariableType.ALGEBRAIC}, - {"name": "tau_a", "units": "second", "component": "i_KACh_a_gate", "type": VariableType.ALGEBRAIC}, - {"name": "i_NaK", "units": "nanoA", "component": "i_NaK", "type": VariableType.ALGEBRAIC}, - {"name": "k41", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "di", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "k32", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "do", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "alpha_dL", "units": "per_second", "component": "i_CaL_dL_gate", "type": VariableType.ALGEBRAIC}, - {"name": "beta_dL", "units": "per_second", "component": "i_CaL_dL_gate", "type": VariableType.ALGEBRAIC}, - {"name": "tau_n", "units": "second", "component": "i_Ks_n_gate", "type": VariableType.ALGEBRAIC}, - {"name": "k12", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "k14", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "k21", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "k23", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "tau_dL", "units": "second", "component": "i_CaL_dL_gate", "type": VariableType.ALGEBRAIC}, - {"name": "x1", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "x2", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "x3", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "x4", "units": "dimensionless", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "i_NaCa", "units": "nanoA", "component": "i_NaCa", "type": VariableType.ALGEBRAIC}, - {"name": "i_tot", "units": "nanoA", "component": "Membrane", "type": VariableType.ALGEBRAIC} + {"name": "tau_a", "units": "second", "component": "i_KACh_a_gate", "type": VariableType.ALGEBRAIC} ] @@ -306,391 +306,391 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): - variables[0] = 0.45 - variables[1] = 2.5 - variables[2] = 15.0 - variables[3] = 1.0 - variables[4] = 500.0 - variables[5] = 5.0 - variables[6] = 10000.0 - variables[7] = 660.0 - variables[8] = 148041085.1 - variables[9] = 0.045 - variables[10] = 10.0 - variables[11] = 2.5 - variables[12] = 0.031 - variables[13] = 0.062 - variables[14] = 542.0 - variables[15] = 445.0 - variables[16] = 446.0 - variables[17] = 7.51 - variables[18] = 751.0 - variables[19] = 1.642e6 - variables[20] = 175.4 - variables[21] = 88800.0 - variables[22] = 227700.0 - variables[23] = 2277.0 - variables[24] = 0.000286113 - variables[25] = 5.0 - variables[26] = 5.0e-5 - variables[27] = 5.469e-5 - variables[28] = 0.04 - variables[29] = 67.0 - variables[30] = 0.02 - variables[31] = 3.9 - variables[32] = 0.46 - variables[33] = 0.0012 - variables[34] = 0.0116 - variables[35] = 1.8 - variables[36] = 140.0 - variables[37] = 5.4 - variables[38] = 140.0 - variables[39] = 5.7e-5 - variables[40] = 96485.3415 - variables[41] = 8314.472 - variables[42] = 310.0 - variables[43] = 0.0 - variables[44] = 1.0 - variables[45] = 0.0 - variables[46] = 0.0 - variables[47] = -45.0 - variables[48] = -35.0 - variables[49] = 0.5 - variables[50] = 0.5 - variables[51] = 0.4578 - variables[52] = -16.4508 - variables[53] = 4.3371 - variables[54] = 0.000338 - variables[55] = 0.0075 - variables[56] = 0.0 - variables[57] = 0.0 - variables[58] = 0.04132 - variables[59] = 0.0 - variables[60] = 1.0 - variables[61] = 0.00345 - variables[62] = 0.00424 - variables[63] = 0.00065 - variables[64] = 0.1539e-3 - variables[65] = 0.0223 - variables[66] = 0.0 - variables[67] = 395.3 - variables[68] = 1628.0 - variables[69] = 2.289 - variables[70] = 561.4 - variables[71] = 26.44 - variables[72] = 4.663 - variables[73] = 3.343 - variables[74] = 0.0207 - variables[75] = 26.44 - variables[76] = 3.663 - variables[77] = 0.1369 - variables[78] = 0.0 - variables[79] = 0.4315 - variables[80] = 0.0 - variables[81] = 1.4 - variables[82] = 14.0 - variables[83] = 0.08105 - variables[84] = 1.0e-5 - variables[85] = 45.0 - variables[86] = 0.5927 - variables[87] = 0.0 - variables[88] = 0.00427 - variables[89] = 0.0 - variables[90] = 3.5e-3 - states[0] = 0.9308 - states[1] = 6.181512e-9 - states[2] = 4.595622e-10 - states[3] = 0.069199 - states[4] = 0.409551 - states[5] = 0.844449 - states[6] = 0.017929 - states[7] = 0.259947 - states[8] = 0.653777 - states[9] = 0.217311 - states[10] = 0.158521 - states[11] = 0.138975 - states[12] = 9.15641e-6 - states[13] = 0.435148 - states[14] = 0.009508 - states[15] = 0.447724 - states[16] = 0.003058 - states[17] = 0.846702 - states[18] = 0.268909 - states[19] = 0.020484 - states[20] = 0.430836 - states[21] = 0.014523 - states[22] = 0.283185 - states[23] = 0.011068 - states[24] = 0.709051 - states[25] = 0.00277 - states[26] = 0.011845 - states[27] = 0.845304 - states[28] = 0.1162 - states[29] = 0.001921 - states[30] = 6.226104e-5 - states[31] = -47.787168 - states[32] = 5.0 +def initialise_variables(states, rates, variables): + variables[0] = 0.0 + variables[1] = 0.0 + variables[4] = 140.0 + variables[7] = 5.4 + variables[8] = 140.0 + variables[10] = 1.8 + variables[11] = 1.0 + variables[17] = 96485.3415 + variables[22] = 14.0 + variables[23] = 1.4 + variables[24] = 0.08105 + variables[25] = 0.0 + variables[30] = 3.343 + variables[39] = 26.44 + variables[40] = 0.0207 + variables[41] = 0.1369 + variables[43] = 395.3 + variables[44] = 2.289 + variables[45] = 0.4315 + variables[46] = 26.44 + variables[47] = 4.663 + variables[48] = 3.663 + variables[49] = 0.0 + variables[51] = 1628.0 + variables[52] = 561.4 + variables[54] = 148041085.1 + variables[57] = 15.0 + variables[58] = 1.0 + variables[59] = 0.45 + variables[60] = 2.5 + variables[62] = 10000.0 + variables[64] = 500.0 + variables[65] = 5.0 + variables[66] = 660.0 + variables[70] = 5.0 + variables[72] = 5.469e-5 + variables[74] = 0.000286113 + variables[75] = 5.0e-5 + variables[77] = 0.04 + variables[79] = 88800.0 + variables[80] = 446.0 + variables[82] = 227700.0 + variables[83] = 7.51 + variables[85] = 2277.0 + variables[86] = 2.5 + variables[87] = 751.0 + variables[89] = 1.642e6 + variables[90] = 542.0 + variables[93] = 175.4 + variables[94] = 445.0 + variables[95] = 0.031 + variables[96] = 0.062 + variables[97] = 0.045 + variables[98] = 10.0 + variables[104] = 67.0 + variables[105] = 3.9 + variables[106] = 0.02 + variables[107] = 0.0012 + variables[108] = 0.46 + variables[109] = 0.0116 + variables[118] = 5.7e-5 + variables[119] = 8314.472 + variables[120] = 310.0 + variables[122] = 0.0 + variables[123] = -35.0 + variables[124] = 0.5 + variables[125] = 0.5 + variables[126] = -45.0 + variables[128] = 0.00427 + variables[129] = 45.0 + variables[131] = 0.5927 + variables[135] = 0.0 + variables[141] = 0.0 + variables[144] = 0.0223 + variables[146] = 0.0 + variables[150] = 1.0e-5 + variables[157] = 0.1539e-3 + variables[163] = 0.4578 + variables[169] = -16.4508 + variables[170] = 4.3371 + variables[177] = 0.0 + variables[178] = 0.0 + variables[181] = 0.000338 + variables[183] = 0.0075 + variables[184] = 0.04132 + variables[189] = 0.0 + variables[190] = 3.5e-3 + variables[195] = 0.00424 + variables[204] = 0.00065 + variables[211] = 1.0 + variables[212] = 0.00345 + states[0] = 6.226104e-5 + states[1] = 5.0 + states[2] = 0.409551 + states[3] = 6.181512e-9 + states[4] = 0.9308 + states[5] = 0.069199 + states[6] = 4.595622e-10 + states[7] = 9.15641e-6 + states[8] = 0.435148 + states[9] = 0.017929 + states[10] = 0.259947 + states[11] = 0.653777 + states[12] = 0.217311 + states[13] = 0.158521 + states[14] = 0.138975 + states[15] = -47.787168 + states[16] = 0.009508 + states[17] = 0.003058 + states[18] = 0.447724 + states[19] = 0.845304 + states[20] = 0.011845 + states[21] = 0.844449 + states[22] = 0.846702 + states[23] = 0.001921 + states[24] = 0.020484 + states[25] = 0.268909 + states[26] = 0.014523 + states[27] = 0.430836 + states[28] = 0.709051 + states[29] = 0.011068 + states[30] = 0.283185 + states[31] = 0.1162 + states[32] = 0.00277 def compute_computed_constants(variables): - variables[92] = 1.2 if gt_func(variables[46], 0.0) else 1.0 - variables[94] = variables[38]/(variables[72]+variables[38]) - variables[101] = -0.25 if gt_func(variables[46], 0.0) else 0.7*variables[45]/(0.00009+variables[45]) if gt_func(variables[45], 0.0) else 0.0 - variables[102] = variables[25]*(1.0-variables[101]) - variables[112] = 0.000000001*3.14159265358979*pow(variables[31], 2.0)*variables[29] - variables[113] = 0.000000001*2.0*3.14159265358979*variables[30]*(variables[31]-variables[30]/2.0)*variables[29] - variables[114] = variables[33]*variables[112] - variables[115] = variables[32]*variables[112]-variables[113] - variables[116] = variables[34]*variables[112] - variables[117] = variables[41]*variables[42]/variables[40] - variables[119] = variables[88]/(variables[37]/(variables[37]+variables[85])) - variables[120] = variables[119]/(variables[86]+1.0) - variables[121] = variables[86]*variables[120] - variables[122] = variables[121]*variables[37]/(variables[37]+variables[85]) - variables[123] = variables[120]*variables[37]/(variables[37]+variables[85]) - variables[124] = -1.0-9.898*pow(1.0*variables[45], 0.618)/(pow(1.0*variables[45], 0.618)+0.00122423) if gt_func(variables[45], 0.0) else 0.0 - variables[125] = 7.5 if gt_func(variables[46], 0.0) else 0.0 - variables[127] = 1.23 if gt_func(variables[46], 0.0) else 1.0 - variables[128] = 0.31*variables[45]/(variables[45]+0.00009) - variables[129] = -8.0 if gt_func(variables[46], 0.0) else 0.0 - variables[130] = -27.0 if gt_func(variables[46], 0.0) else 0.0 - variables[133] = 1.2*variables[63] if gt_func(variables[46], 0.0) else variables[63] - variables[135] = -14.0 if gt_func(variables[46], 0.0) else 0.0 - variables[136] = (3.5988-0.025641)/(1.0+0.0000012155/pow(1.0*variables[45], 1.6951))+0.025641 - variables[138] = variables[117]*log(variables[37]/variables[36]) + variables[6] = variables[3]*log(variables[7]/variables[8]) + variables[20] = 1.2 if gt_func(variables[1], 0.0) else 1.0 + variables[35] = variables[4]/(variables[47]+variables[4]) + variables[68] = -0.25 if gt_func(variables[1], 0.0) else 0.7*variables[0]/(0.00009+variables[0]) if gt_func(variables[0], 0.0) else 0.0 + variables[69] = variables[70]*(1.0-variables[68]) + variables[103] = 0.000000001*3.14159265358979*pow(variables[105], 2.0)*variables[104] + variables[19] = 0.000000001*2.0*3.14159265358979*variables[106]*(variables[105]-variables[106]/2.0)*variables[104] + variables[100] = variables[107]*variables[103] + variables[18] = variables[108]*variables[103]-variables[19] + variables[99] = variables[109]*variables[103] + variables[3] = variables[119]*variables[120]/variables[17] + variables[127] = variables[128]/(variables[7]/(variables[7]+variables[129])) + variables[130] = variables[127]/(variables[131]+1.0) + variables[132] = variables[131]*variables[130] + variables[133] = variables[132]*variables[7]/(variables[7]+variables[129]) + variables[134] = variables[130]*variables[7]/(variables[7]+variables[129]) + variables[137] = -1.0-9.898*pow(1.0*variables[0], 0.618)/(pow(1.0*variables[0], 0.618)+0.00122423) if gt_func(variables[0], 0.0) else 0.0 + variables[138] = 7.5 if gt_func(variables[1], 0.0) else 0.0 + variables[162] = 1.23 if gt_func(variables[1], 0.0) else 1.0 + variables[165] = 0.31*variables[0]/(variables[0]+0.00009) + variables[166] = -8.0 if gt_func(variables[1], 0.0) else 0.0 + variables[167] = -27.0 if gt_func(variables[1], 0.0) else 0.0 + variables[203] = 1.2*variables[204] if gt_func(variables[1], 0.0) else variables[204] + variables[206] = -14.0 if gt_func(variables[1], 0.0) else 0.0 + variables[213] = (3.5988-0.025641)/(1.0+0.0000012155/pow(1.0*variables[0], 1.6951))+0.025641 def compute_rates(voi, states, rates, variables): - variables[97] = variables[2]-(variables[2]-variables[3])/(1.0+pow(variables[0]/states[4], variables[1])) - variables[99] = variables[4]*variables[97] - variables[98] = variables[6]/variables[97] - rates[0] = variables[5]*states[3]-variables[99]*states[30]*states[0]-(variables[98]*pow(states[30], 2.0)*states[0]-variables[7]*states[1]) - rates[1] = variables[98]*pow(states[30], 2.0)*states[0]-variables[7]*states[1]-(variables[99]*states[30]*states[1]-variables[5]*states[2]) - rates[2] = variables[99]*states[30]*states[1]-variables[5]*states[2]-(variables[7]*states[2]-variables[98]*pow(states[30], 2.0)*states[3]) - rates[3] = variables[7]*states[2]-variables[98]*pow(states[30], 2.0)*states[3]-(variables[5]*states[3]-variables[99]*states[30]*states[0]) - variables[105] = (states[13]-states[4])/variables[28] - variables[95] = variables[8]*states[1]*(states[4]-states[30]) - variables[111] = variables[20]*states[4]*(1.0-states[11])-variables[15]*states[11] - rates[4] = variables[105]-(variables[95]+variables[10]*variables[111]) - variables[131] = variables[54]/(variables[54]+states[30]) - variables[132] = 0.001*variables[131]/variables[55] - rates[5] = (variables[131]-states[5])/variables[132] - variables[106] = variables[21]*states[12]*(1.0-states[6])-variables[16]*states[6] - rates[6] = variables[106] - variables[107] = variables[22]*states[12]*(1.0-(states[7]+states[8]))-variables[17]*states[7] - rates[7] = variables[107] - variables[108] = variables[23]*variables[11]*(1.0-(states[7]+states[8]))-variables[18]*states[8] - rates[8] = variables[108] - variables[109] = variables[19]*states[12]*(1.0-states[9])-variables[14]*states[9] - rates[9] = variables[109] - variables[110] = variables[19]*states[30]*(1.0-states[10])-variables[14]*states[10] - rates[10] = variables[110] - rates[11] = variables[111] - variables[103] = (states[30]-states[12])/variables[27] - variables[104] = variables[102]/(1.0+exp((-states[12]+variables[24])/variables[26])) - rates[12] = 1.0*(variables[103]*variables[113]-variables[104]*variables[116])/variables[115]-(variables[9]*variables[109]+variables[12]*variables[106]+variables[13]*variables[107]) - rates[13] = variables[104]-variables[105]*variables[114]/variables[116] - variables[118] = variables[48] if and_func(gt_func(voi, variables[49]), lt_func(voi, variables[49]+variables[50])) else variables[47] - variables[140] = variables[118] if geq_func(variables[43], 1.0) else states[31] - variables[145] = 0.01329+0.99921/(1.0+exp((variables[140]+97.134-variables[124]-variables[125]-variables[89])/8.1752)) if lt_func(variables[140], -(80.0-variables[124]-variables[125]-variables[89])) else 0.0002501*exp(-(variables[140]-variables[124]-variables[125]-variables[89])/12.861) - variables[144] = 1.0/(0.36*(variables[140]+148.8-variables[124]-variables[125])/(exp(0.066*(variables[140]+148.8-variables[124]-variables[125]))-1.0)+0.1*(variables[140]+87.3-variables[124]-variables[125])/(1.0-exp(-0.2*(variables[140]+87.3-variables[124]-variables[125]))))-0.054 - rates[14] = (variables[145]-states[14])/variables[144] - variables[149] = 1.0/(1.0+exp(-(variables[140]+42.0504)/8.3106)) - variables[150] = variables[140]+41.0 - variables[151] = 2000.0 if lt_func(fabs(variables[150]), variables[84]) else 200.0*variables[150]/(1.0-exp(-0.1*variables[150])) - variables[152] = 8000.0*exp(-0.056*(variables[140]+66.0)) - variables[153] = 1.0/(variables[151]+variables[152]) - rates[15] = (variables[149]-states[15])/variables[153] - variables[154] = 1.0/(1.0+exp((variables[140]+69.804)/4.4565)) - variables[155] = 20.0*exp(-0.125*(variables[140]+75.0)) - variables[156] = 2000.0/(320.0*exp(-0.1*(variables[140]+75.0))+1.0) - variables[157] = 1.0/(variables[155]+variables[156]) - rates[16] = (variables[154]-states[16])/variables[157] - variables[170] = 1.0/(1.0+exp((variables[140]+37.4+variables[57])/(5.3+variables[56]))) - variables[171] = 0.001*(44.3+230.0*exp(-pow((variables[140]+36.0)/10.0, 2.0))) - rates[17] = (variables[170]-states[17])/variables[171] - variables[173] = 1.0/(1.0+exp(-(variables[140]+38.3)/5.5)) - variables[174] = 0.001/(1.068*exp((variables[140]+38.3)/30.0)+1.068*exp(-(variables[140]+38.3)/30.0)) - rates[18] = (variables[173]-states[18])/variables[174] - variables[175] = 1.0/(1.0+exp((variables[140]+58.7)/3.8)) - variables[176] = 1.0/(16.67*exp(-(variables[140]+75.0)/83.3)+16.67*exp((variables[140]+75.0)/15.38))+variables[59] - rates[19] = (variables[175]-states[19])/variables[176] - variables[178] = 1.0/(1.0+exp((variables[140]+49.0)/13.0)) - variables[179] = 0.001*0.6*(65.17/(0.57*exp(-0.08*(variables[140]+44.0))+0.065*exp(0.1*(variables[140]+45.93)))+10.1) - rates[20] = (variables[178]-states[20])/variables[179] - variables[180] = 1.0/(1.0+exp(-(variables[140]-19.3)/15.0)) - variables[181] = 0.001*0.66*1.4*(15.59/(1.037*exp(0.09*(variables[140]+30.61))+0.369*exp(-0.12*(variables[140]+23.84)))+2.98) - rates[21] = (variables[180]-states[21])/variables[181] - variables[185] = 1.0/(1.0+exp(-(variables[140]+10.0144)/7.6607)) - variables[186] = 0.84655354/(4.2*exp(variables[140]/17.0)+0.15*exp(-variables[140]/21.6)) - rates[22] = (variables[185]-states[22])/variables[186] - variables[187] = 1.0/(30.0*exp(variables[140]/10.0)+exp(-variables[140]/12.0)) - rates[23] = (variables[185]-states[23])/variables[187] - variables[189] = 1.0/(1.0+exp((variables[140]+28.6)/17.1)) - variables[188] = 1.0/(100.0*exp(-variables[140]/54.645)+656.0*exp(variables[140]/106.157)) - rates[24] = (variables[189]-states[24])/variables[188] - variables[195] = 10.0*exp(0.0133*(variables[140]+40.0)) - variables[196] = variables[136]/(variables[136]+variables[195]) - variables[197] = 1.0/(variables[136]+variables[195]) - rates[25] = (variables[196]-states[25])/variables[197] - variables[159] = 1.0/(1.0+exp((variables[140]+6.0)/-8.6)) - variables[160] = 0.009/(1.0+exp((variables[140]+5.0)/12.0))+0.0005 - rates[26] = (variables[159]-states[26])/variables[160] - variables[161] = 1.0/(1.0+exp((variables[140]+7.5)/10.0)) - variables[162] = 0.59/(1.0+exp((variables[140]+60.0)/10.0))+3.05 - rates[27] = (variables[161]-states[27])/variables[162] - variables[191] = sqrt(1.0/(1.0+exp(-(variables[140]+0.6383-variables[135])/10.7071))) - variables[192] = 28.0/(1.0+exp(-(variables[140]-40.0-variables[135])/3.0)) - variables[193] = 1.0*exp(-(variables[140]-variables[135]-5.0)/25.0) - variables[205] = 1.0/(variables[192]+variables[193]) - rates[28] = (variables[191]-states[28])/variables[205] - variables[167] = 1.0/(1.0+exp(-(variables[140]-variables[52]-variables[129])/(variables[53]*(1.0+variables[130]/100.0)))) - variables[168] = -41.80001 if eq_func(variables[140], -41.8) else 0.0 if eq_func(variables[140], 0.0) else -6.80001 if eq_func(variables[140], -6.8) else variables[140] - variables[203] = -0.02839*(variables[168]+41.8)/(exp(-(variables[168]+41.8)/2.5)-1.0)-0.0849*(variables[168]+6.8)/(exp(-(variables[168]+6.8)/4.8)-1.0) - variables[169] = -1.80001 if eq_func(variables[140], -1.8) else variables[140] - variables[204] = 0.01143*(variables[169]+1.8)/(exp((variables[169]+1.8)/2.5)-1.0) - variables[210] = 0.001/(variables[203]+variables[204]) - rates[29] = (variables[167]-states[29])/variables[210] - variables[163] = 2.0*variables[51]*(variables[140]-0.0)/(variables[117]*(1.0-exp(-1.0*(variables[140]-0.0)*2.0/variables[117])))*(states[30]-variables[35]*exp(-2.0*(variables[140]-0.0)/variables[117]))*states[29]*states[17]*states[5] - variables[172] = 2.0*variables[58]*variables[140]/(variables[117]*(1.0-exp(-1.0*variables[140]*2.0/variables[117])))*(states[30]-variables[35]*exp(-2.0*variables[140]/variables[117]))*states[18]*states[19] - variables[202] = 1.0+variables[35]/variables[76]*(1.0+exp(variables[78]*variables[140]/variables[117]))+variables[38]/variables[68]*(1.0+variables[38]/variables[70]*(1.0+variables[38]/variables[72])) - variables[208] = variables[35]/variables[76]*exp(variables[78]*variables[140]/variables[117])/variables[202] - variables[91] = states[32] - variables[200] = 1.0+states[30]/variables[74]*(1.0+exp(-variables[77]*variables[140]/variables[117])+variables[91]/variables[75])+variables[91]/variables[67]*(1.0+variables[91]/variables[69]*(1.0+variables[91]/variables[71])) - variables[206] = states[30]/variables[74]*exp(-variables[77]*variables[140]/variables[117])/variables[200] - variables[93] = variables[91]/(variables[71]+variables[91]) - variables[201] = exp(variables[79]*variables[140]/(2.0*variables[117])) - variables[199] = exp(-variables[79]*variables[140]/(2.0*variables[117])) - variables[207] = variables[91]/variables[67]*variables[91]/variables[69]*(1.0+variables[91]/variables[71])*exp(variables[79]*variables[140]/(2.0*variables[117]))/variables[200] - variables[212] = variables[201]*variables[93]*(variables[207]+variables[206])+variables[199]*variables[206]*(variables[94]+variables[201]) - variables[209] = variables[38]/variables[68]*variables[38]/variables[70]*(1.0+variables[38]/variables[72])*exp(-variables[79]*variables[140]/(2.0*variables[117]))/variables[202] - variables[211] = variables[199]*variables[94]*(variables[209]+variables[208])+variables[208]*variables[201]*(variables[93]+variables[199]) - variables[214] = variables[209]*variables[94]*(variables[207]+variables[206])+variables[207]*variables[208]*(variables[94]+variables[201]) - variables[213] = variables[207]*variables[93]*(variables[209]+variables[208])+variables[206]*variables[209]*(variables[93]+variables[199]) - variables[215] = (1.0-variables[80])*variables[73]*(variables[212]*variables[208]-variables[211]*variables[206])/(variables[211]+variables[212]+variables[213]+variables[214]) - rates[30] = variables[95]*variables[114]/variables[113]-((variables[163]+variables[172]-2.0*variables[215])/(2.0*variables[40]*variables[113])+variables[103]+variables[9]*variables[110]) - variables[137] = variables[117]*log(variables[38]/variables[91]) - variables[141] = states[14]*variables[122]*(variables[140]-variables[137])*(1.0-variables[87]) - variables[142] = states[14]*variables[123]*(variables[140]-variables[138])*(1.0-variables[87]) - variables[143] = variables[141]+variables[142] - variables[158] = variables[64]*states[26]*states[27]*(variables[140]-variables[138]) - variables[194] = variables[60]*variables[61]*(variables[140]-variables[138])*(1.0+exp((variables[140]+20.0)/20.0))*states[25] if gt_func(variables[45], 0.0) else 0.0 - variables[165] = 0.0000185*variables[51]*(variables[140]-0.0)/(variables[117]*(1.0-exp(-1.0*(variables[140]-0.0)/variables[117])))*(variables[91]-variables[38]*exp(-1.0*(variables[140]-0.0)/variables[117]))*states[29]*states[17]*states[5] - variables[164] = 0.000365*variables[51]*(variables[140]-0.0)/(variables[117]*(1.0-exp(-1.0*(variables[140]-0.0)/variables[117])))*(variables[36]-variables[37]*exp(-1.0*(variables[140]-0.0)/variables[117]))*states[29]*states[17]*states[5] - variables[166] = (variables[163]+variables[164]+variables[165])*(1.0-variables[128])*1.0*variables[127] - variables[126] = variables[117]*log((variables[38]+0.12*variables[37])/(variables[91]+0.12*variables[36])) - variables[146] = variables[65]*pow(states[15], 3.0)*states[16]*(variables[140]-variables[126]) - variables[147] = variables[66]*pow(states[15], 3.0)*(variables[140]-variables[126]) - variables[148] = variables[146]+variables[147] - variables[198] = variables[92]*variables[83]*pow(1.0+pow(variables[81]/variables[37], 1.2), -1.0)*pow(1.0+pow(variables[82]/variables[91], 1.3), -1.0)*pow(1.0+exp(-(variables[140]-variables[137]+110.0)/20.0), -1.0) - variables[177] = variables[90]*(variables[140]-variables[138])*states[20]*states[21] - variables[134] = variables[117]*log((variables[37]+0.12*variables[38])/(variables[36]+0.12*variables[91])) - variables[190] = variables[133]*(variables[140]-variables[134])*pow(states[28], 2.0) - variables[182] = variables[62]*(variables[140]-variables[138])*(0.9*states[23]+0.1*states[22])*states[24] - variables[216] = variables[143]+variables[182]+variables[190]+variables[177]+variables[198]+variables[215]+variables[148]+variables[166]+variables[172]+variables[194]+variables[158] - rates[31] = -variables[216]/variables[39] - rates[32] = (1.0-variables[44])*-1.0*(variables[148]+variables[141]+variables[165]+3.0*variables[198]+3.0*variables[215])/(1.0*(variables[115]+variables[113])*variables[40]) + variables[5] = states[1] + variables[142] = variables[3]*log((variables[4]+0.12*variables[7])/(variables[5]+0.12*variables[8])) + variables[121] = variables[123] if and_func(gt_func(voi, variables[124]), lt_func(voi, variables[124]+variables[125])) else variables[126] + variables[21] = variables[121] if geq_func(variables[122], 1.0) else states[15] + variables[143] = variables[144]*pow(states[18], 3.0)*states[17]*(variables[21]-variables[142]) + variables[145] = variables[146]*pow(states[18], 3.0)*(variables[21]-variables[142]) + variables[12] = variables[143]+variables[145] + variables[15] = 0.0000185*variables[163]*(variables[21]-0.0)/(variables[3]*(1.0-exp(-1.0*(variables[21]-0.0)/variables[3])))*(variables[5]-variables[4]*exp(-1.0*(variables[21]-0.0)/variables[3]))*states[23]*states[22]*states[21] + variables[2] = variables[3]*log(variables[4]/variables[5]) + variables[16] = states[16]*variables[133]*(variables[21]-variables[2])*(1.0-variables[135]) + variables[14] = variables[20]*variables[24]*pow(1.0+pow(variables[23]/variables[7], 1.2), -1.0)*pow(1.0+pow(variables[22]/variables[5], 1.3), -1.0)*pow(1.0+exp(-(variables[21]-variables[2]+110.0)/20.0), -1.0) + variables[50] = 1.0+variables[10]/variables[48]*(1.0+exp(variables[49]*variables[21]/variables[3]))+variables[4]/variables[51]*(1.0+variables[4]/variables[52]*(1.0+variables[4]/variables[47])) + variables[27] = variables[10]/variables[48]*exp(variables[49]*variables[21]/variables[3])/variables[50] + variables[42] = 1.0+states[0]/variables[40]*(1.0+exp(-variables[41]*variables[21]/variables[3])+variables[5]/variables[46])+variables[5]/variables[43]*(1.0+variables[5]/variables[44]*(1.0+variables[5]/variables[39])) + variables[29] = states[0]/variables[40]*exp(-variables[41]*variables[21]/variables[3])/variables[42] + variables[36] = variables[5]/(variables[39]+variables[5]) + variables[37] = exp(variables[45]*variables[21]/(2.0*variables[3])) + variables[33] = exp(-variables[45]*variables[21]/(2.0*variables[3])) + variables[38] = variables[5]/variables[43]*variables[5]/variables[44]*(1.0+variables[5]/variables[39])*exp(variables[45]*variables[21]/(2.0*variables[3]))/variables[42] + variables[26] = variables[37]*variables[36]*(variables[38]+variables[29])+variables[33]*variables[29]*(variables[35]+variables[37]) + variables[34] = variables[4]/variables[51]*variables[4]/variables[52]*(1.0+variables[4]/variables[47])*exp(-variables[45]*variables[21]/(2.0*variables[3]))/variables[50] + variables[28] = variables[33]*variables[35]*(variables[34]+variables[27])+variables[27]*variables[37]*(variables[36]+variables[33]) + variables[31] = variables[34]*variables[35]*(variables[38]+variables[29])+variables[38]*variables[27]*(variables[35]+variables[37]) + variables[32] = variables[38]*variables[36]*(variables[34]+variables[27])+variables[29]*variables[34]*(variables[36]+variables[33]) + variables[13] = (1.0-variables[25])*variables[30]*(variables[26]*variables[27]-variables[28]*variables[29])/(variables[28]+variables[26]+variables[32]+variables[31]) + rates[1] = (1.0-variables[11])*-1.0*(variables[12]+variables[16]+variables[15]+3.0*variables[14]+3.0*variables[13])/(1.0*(variables[18]+variables[19])*variables[17]) + variables[56] = variables[57]-(variables[57]-variables[58])/(1.0+pow(variables[59]/states[2], variables[60])) + variables[63] = variables[64]*variables[56] + variables[61] = variables[62]/variables[56] + rates[4] = variables[65]*states[5]-variables[63]*states[0]*states[4]-(variables[61]*pow(states[0], 2.0)*states[4]-variables[66]*states[3]) + rates[3] = variables[61]*pow(states[0], 2.0)*states[4]-variables[66]*states[3]-(variables[63]*states[0]*states[3]-variables[65]*states[6]) + rates[6] = variables[63]*states[0]*states[3]-variables[65]*states[6]-(variables[66]*states[6]-variables[61]*pow(states[0], 2.0)*states[5]) + rates[5] = variables[66]*states[6]-variables[61]*pow(states[0], 2.0)*states[5]-(variables[65]*states[5]-variables[63]*states[0]*states[4]) + variables[78] = variables[79]*states[7]*(1.0-states[9])-variables[80]*states[9] + rates[9] = variables[78] + variables[81] = variables[82]*states[7]*(1.0-(states[10]+states[11]))-variables[83]*states[10] + rates[10] = variables[81] + variables[84] = variables[85]*variables[86]*(1.0-(states[10]+states[11]))-variables[87]*states[11] + rates[11] = variables[84] + variables[88] = variables[89]*states[7]*(1.0-states[12])-variables[90]*states[12] + rates[12] = variables[88] + variables[91] = variables[89]*states[0]*(1.0-states[13])-variables[90]*states[13] + rates[13] = variables[91] + variables[92] = variables[93]*states[2]*(1.0-states[14])-variables[94]*states[14] + rates[14] = variables[92] + variables[71] = (states[0]-states[7])/variables[72] + variables[73] = variables[69]/(1.0+exp((-states[7]+variables[74])/variables[75])) + rates[7] = 1.0*(variables[71]*variables[19]-variables[73]*variables[99])/variables[18]-(variables[97]*variables[88]+variables[95]*variables[78]+variables[96]*variables[81]) + variables[53] = variables[54]*states[3]*(states[2]-states[0]) + variables[101] = 2.0*variables[163]*(variables[21]-0.0)/(variables[3]*(1.0-exp(-1.0*(variables[21]-0.0)*2.0/variables[3])))*(states[0]-variables[10]*exp(-2.0*(variables[21]-0.0)/variables[3]))*states[23]*states[22]*states[21] + variables[102] = 2.0*variables[184]*variables[21]/(variables[3]*(1.0-exp(-1.0*variables[21]*2.0/variables[3])))*(states[0]-variables[10]*exp(-2.0*variables[21]/variables[3]))*states[25]*states[24] + rates[0] = variables[53]*variables[100]/variables[19]-((variables[101]+variables[102]-2.0*variables[13])/(2.0*variables[17]*variables[19])+variables[71]+variables[97]*variables[91]) + variables[76] = (states[8]-states[2])/variables[77] + rates[8] = variables[73]-variables[76]*variables[100]/variables[99] + rates[2] = variables[76]-(variables[53]+variables[98]*variables[92]) + variables[136] = states[16]*variables[134]*(variables[21]-variables[6])*(1.0-variables[135]) + variables[111] = variables[16]+variables[136] + variables[112] = variables[157]*states[20]*states[19]*(variables[21]-variables[6]) + variables[113] = variables[211]*variables[212]*(variables[21]-variables[6])*(1.0+exp((variables[21]+20.0)/20.0))*states[32] if gt_func(variables[0], 0.0) else 0.0 + variables[164] = 0.000365*variables[163]*(variables[21]-0.0)/(variables[3]*(1.0-exp(-1.0*(variables[21]-0.0)/variables[3])))*(variables[8]-variables[7]*exp(-1.0*(variables[21]-0.0)/variables[3]))*states[23]*states[22]*states[21] + variables[114] = (variables[101]+variables[164]+variables[15])*(1.0-variables[165])*1.0*variables[162] + variables[115] = variables[190]*(variables[21]-variables[6])*states[27]*states[26] + variables[205] = variables[3]*log((variables[7]+0.12*variables[4])/(variables[8]+0.12*variables[5])) + variables[116] = variables[203]*(variables[21]-variables[205])*pow(states[31], 2.0) + variables[117] = variables[195]*(variables[21]-variables[6])*(0.9*states[29]+0.1*states[30])*states[28] + variables[110] = variables[111]+variables[117]+variables[116]+variables[115]+variables[14]+variables[13]+variables[12]+variables[114]+variables[102]+variables[113]+variables[112] + rates[15] = -variables[110]/variables[118] + variables[140] = 0.01329+0.99921/(1.0+exp((variables[21]+97.134-variables[137]-variables[138]-variables[141])/8.1752)) if lt_func(variables[21], -(80.0-variables[137]-variables[138]-variables[141])) else 0.0002501*exp(-(variables[21]-variables[137]-variables[138]-variables[141])/12.861) + variables[139] = 1.0/(0.36*(variables[21]+148.8-variables[137]-variables[138])/(exp(0.066*(variables[21]+148.8-variables[137]-variables[138]))-1.0)+0.1*(variables[21]+87.3-variables[137]-variables[138])/(1.0-exp(-0.2*(variables[21]+87.3-variables[137]-variables[138]))))-0.054 + rates[16] = (variables[140]-states[16])/variables[139] + variables[147] = 1.0/(1.0+exp(-(variables[21]+42.0504)/8.3106)) + variables[148] = variables[21]+41.0 + variables[149] = 2000.0 if lt_func(fabs(variables[148]), variables[150]) else 200.0*variables[148]/(1.0-exp(-0.1*variables[148])) + variables[151] = 8000.0*exp(-0.056*(variables[21]+66.0)) + variables[152] = 1.0/(variables[149]+variables[151]) + rates[18] = (variables[147]-states[18])/variables[152] + variables[153] = 1.0/(1.0+exp((variables[21]+69.804)/4.4565)) + variables[154] = 20.0*exp(-0.125*(variables[21]+75.0)) + variables[155] = 2000.0/(320.0*exp(-0.1*(variables[21]+75.0))+1.0) + variables[156] = 1.0/(variables[154]+variables[155]) + rates[17] = (variables[153]-states[17])/variables[156] + variables[158] = 1.0/(1.0+exp((variables[21]+6.0)/-8.6)) + variables[159] = 0.009/(1.0+exp((variables[21]+5.0)/12.0))+0.0005 + rates[20] = (variables[158]-states[20])/variables[159] + variables[160] = 1.0/(1.0+exp((variables[21]+7.5)/10.0)) + variables[161] = 0.59/(1.0+exp((variables[21]+60.0)/10.0))+3.05 + rates[19] = (variables[160]-states[19])/variables[161] + variables[168] = 1.0/(1.0+exp(-(variables[21]-variables[169]-variables[166])/(variables[170]*(1.0+variables[167]/100.0)))) + variables[174] = -41.80001 if eq_func(variables[21], -41.8) else 0.0 if eq_func(variables[21], 0.0) else -6.80001 if eq_func(variables[21], -6.8) else variables[21] + variables[172] = -0.02839*(variables[174]+41.8)/(exp(-(variables[174]+41.8)/2.5)-1.0)-0.0849*(variables[174]+6.8)/(exp(-(variables[174]+6.8)/4.8)-1.0) + variables[175] = -1.80001 if eq_func(variables[21], -1.8) else variables[21] + variables[173] = 0.01143*(variables[175]+1.8)/(exp((variables[175]+1.8)/2.5)-1.0) + variables[171] = 0.001/(variables[172]+variables[173]) + rates[23] = (variables[168]-states[23])/variables[171] + variables[176] = 1.0/(1.0+exp((variables[21]+37.4+variables[177])/(5.3+variables[178]))) + variables[179] = 0.001*(44.3+230.0*exp(-pow((variables[21]+36.0)/10.0, 2.0))) + rates[22] = (variables[176]-states[22])/variables[179] + variables[180] = variables[181]/(variables[181]+states[0]) + variables[182] = 0.001*variables[180]/variables[183] + rates[21] = (variables[180]-states[21])/variables[182] + variables[185] = 1.0/(1.0+exp(-(variables[21]+38.3)/5.5)) + variables[186] = 0.001/(1.068*exp((variables[21]+38.3)/30.0)+1.068*exp(-(variables[21]+38.3)/30.0)) + rates[25] = (variables[185]-states[25])/variables[186] + variables[187] = 1.0/(1.0+exp((variables[21]+58.7)/3.8)) + variables[188] = 1.0/(16.67*exp(-(variables[21]+75.0)/83.3)+16.67*exp((variables[21]+75.0)/15.38))+variables[189] + rates[24] = (variables[187]-states[24])/variables[188] + variables[191] = 1.0/(1.0+exp((variables[21]+49.0)/13.0)) + variables[192] = 0.001*0.6*(65.17/(0.57*exp(-0.08*(variables[21]+44.0))+0.065*exp(0.1*(variables[21]+45.93)))+10.1) + rates[27] = (variables[191]-states[27])/variables[192] + variables[193] = 1.0/(1.0+exp(-(variables[21]-19.3)/15.0)) + variables[194] = 0.001*0.66*1.4*(15.59/(1.037*exp(0.09*(variables[21]+30.61))+0.369*exp(-0.12*(variables[21]+23.84)))+2.98) + rates[26] = (variables[193]-states[26])/variables[194] + variables[198] = 1.0/(1.0+exp(-(variables[21]+10.0144)/7.6607)) + variables[199] = 0.84655354/(4.2*exp(variables[21]/17.0)+0.15*exp(-variables[21]/21.6)) + rates[30] = (variables[198]-states[30])/variables[199] + variables[200] = 1.0/(30.0*exp(variables[21]/10.0)+exp(-variables[21]/12.0)) + rates[29] = (variables[198]-states[29])/variables[200] + variables[202] = 1.0/(1.0+exp((variables[21]+28.6)/17.1)) + variables[201] = 1.0/(100.0*exp(-variables[21]/54.645)+656.0*exp(variables[21]/106.157)) + rates[28] = (variables[202]-states[28])/variables[201] + variables[207] = sqrt(1.0/(1.0+exp(-(variables[21]+0.6383-variables[206])/10.7071))) + variables[209] = 28.0/(1.0+exp(-(variables[21]-40.0-variables[206])/3.0)) + variables[210] = 1.0*exp(-(variables[21]-variables[206]-5.0)/25.0) + variables[208] = 1.0/(variables[209]+variables[210]) + rates[31] = (variables[207]-states[31])/variables[208] + variables[214] = 10.0*exp(0.0133*(variables[21]+40.0)) + variables[215] = variables[213]/(variables[213]+variables[214]) + variables[216] = 1.0/(variables[213]+variables[214]) + rates[32] = (variables[215]-states[32])/variables[216] def compute_variables(voi, states, rates, variables): - variables[91] = states[32] - variables[93] = variables[91]/(variables[71]+variables[91]) - variables[95] = variables[8]*states[1]*(states[4]-states[30]) - variables[96] = states[4]-states[30] - variables[97] = variables[2]-(variables[2]-variables[3])/(1.0+pow(variables[0]/states[4], variables[1])) - variables[98] = variables[6]/variables[97] - variables[99] = variables[4]*variables[97] - variables[100] = states[0]+states[1]+states[2]+states[3] - variables[103] = (states[30]-states[12])/variables[27] - variables[104] = variables[102]/(1.0+exp((-states[12]+variables[24])/variables[26])) - variables[105] = (states[13]-states[4])/variables[28] - variables[106] = variables[21]*states[12]*(1.0-states[6])-variables[16]*states[6] - variables[107] = variables[22]*states[12]*(1.0-(states[7]+states[8]))-variables[17]*states[7] - variables[108] = variables[23]*variables[11]*(1.0-(states[7]+states[8]))-variables[18]*states[8] - variables[109] = variables[19]*states[12]*(1.0-states[9])-variables[14]*states[9] - variables[110] = variables[19]*states[30]*(1.0-states[10])-variables[14]*states[10] - variables[111] = variables[20]*states[4]*(1.0-states[11])-variables[15]*states[11] - variables[126] = variables[117]*log((variables[38]+0.12*variables[37])/(variables[91]+0.12*variables[36])) - variables[131] = variables[54]/(variables[54]+states[30]) - variables[132] = 0.001*variables[131]/variables[55] - variables[134] = variables[117]*log((variables[37]+0.12*variables[38])/(variables[36]+0.12*variables[91])) - variables[137] = variables[117]*log(variables[38]/variables[91]) - variables[139] = 0.5*variables[117]*log(variables[35]/states[30]) - variables[140] = variables[118] if geq_func(variables[43], 1.0) else states[31] - variables[141] = states[14]*variables[122]*(variables[140]-variables[137])*(1.0-variables[87]) - variables[142] = states[14]*variables[123]*(variables[140]-variables[138])*(1.0-variables[87]) - variables[143] = variables[141]+variables[142] - variables[144] = 1.0/(0.36*(variables[140]+148.8-variables[124]-variables[125])/(exp(0.066*(variables[140]+148.8-variables[124]-variables[125]))-1.0)+0.1*(variables[140]+87.3-variables[124]-variables[125])/(1.0-exp(-0.2*(variables[140]+87.3-variables[124]-variables[125]))))-0.054 - variables[145] = 0.01329+0.99921/(1.0+exp((variables[140]+97.134-variables[124]-variables[125]-variables[89])/8.1752)) if lt_func(variables[140], -(80.0-variables[124]-variables[125]-variables[89])) else 0.0002501*exp(-(variables[140]-variables[124]-variables[125]-variables[89])/12.861) - variables[146] = variables[65]*pow(states[15], 3.0)*states[16]*(variables[140]-variables[126]) - variables[147] = variables[66]*pow(states[15], 3.0)*(variables[140]-variables[126]) - variables[148] = variables[146]+variables[147] - variables[149] = 1.0/(1.0+exp(-(variables[140]+42.0504)/8.3106)) - variables[150] = variables[140]+41.0 - variables[151] = 2000.0 if lt_func(fabs(variables[150]), variables[84]) else 200.0*variables[150]/(1.0-exp(-0.1*variables[150])) - variables[152] = 8000.0*exp(-0.056*(variables[140]+66.0)) - variables[153] = 1.0/(variables[151]+variables[152]) - variables[154] = 1.0/(1.0+exp((variables[140]+69.804)/4.4565)) - variables[155] = 20.0*exp(-0.125*(variables[140]+75.0)) - variables[156] = 2000.0/(320.0*exp(-0.1*(variables[140]+75.0))+1.0) - variables[157] = 1.0/(variables[155]+variables[156]) - variables[158] = variables[64]*states[26]*states[27]*(variables[140]-variables[138]) - variables[159] = 1.0/(1.0+exp((variables[140]+6.0)/-8.6)) - variables[160] = 0.009/(1.0+exp((variables[140]+5.0)/12.0))+0.0005 - variables[161] = 1.0/(1.0+exp((variables[140]+7.5)/10.0)) - variables[162] = 0.59/(1.0+exp((variables[140]+60.0)/10.0))+3.05 - variables[163] = 2.0*variables[51]*(variables[140]-0.0)/(variables[117]*(1.0-exp(-1.0*(variables[140]-0.0)*2.0/variables[117])))*(states[30]-variables[35]*exp(-2.0*(variables[140]-0.0)/variables[117]))*states[29]*states[17]*states[5] - variables[164] = 0.000365*variables[51]*(variables[140]-0.0)/(variables[117]*(1.0-exp(-1.0*(variables[140]-0.0)/variables[117])))*(variables[36]-variables[37]*exp(-1.0*(variables[140]-0.0)/variables[117]))*states[29]*states[17]*states[5] - variables[165] = 0.0000185*variables[51]*(variables[140]-0.0)/(variables[117]*(1.0-exp(-1.0*(variables[140]-0.0)/variables[117])))*(variables[91]-variables[38]*exp(-1.0*(variables[140]-0.0)/variables[117]))*states[29]*states[17]*states[5] - variables[166] = (variables[163]+variables[164]+variables[165])*(1.0-variables[128])*1.0*variables[127] - variables[167] = 1.0/(1.0+exp(-(variables[140]-variables[52]-variables[129])/(variables[53]*(1.0+variables[130]/100.0)))) - variables[168] = -41.80001 if eq_func(variables[140], -41.8) else 0.0 if eq_func(variables[140], 0.0) else -6.80001 if eq_func(variables[140], -6.8) else variables[140] - variables[169] = -1.80001 if eq_func(variables[140], -1.8) else variables[140] - variables[170] = 1.0/(1.0+exp((variables[140]+37.4+variables[57])/(5.3+variables[56]))) - variables[171] = 0.001*(44.3+230.0*exp(-pow((variables[140]+36.0)/10.0, 2.0))) - variables[172] = 2.0*variables[58]*variables[140]/(variables[117]*(1.0-exp(-1.0*variables[140]*2.0/variables[117])))*(states[30]-variables[35]*exp(-2.0*variables[140]/variables[117]))*states[18]*states[19] - variables[173] = 1.0/(1.0+exp(-(variables[140]+38.3)/5.5)) - variables[174] = 0.001/(1.068*exp((variables[140]+38.3)/30.0)+1.068*exp(-(variables[140]+38.3)/30.0)) - variables[175] = 1.0/(1.0+exp((variables[140]+58.7)/3.8)) - variables[176] = 1.0/(16.67*exp(-(variables[140]+75.0)/83.3)+16.67*exp((variables[140]+75.0)/15.38))+variables[59] - variables[177] = variables[90]*(variables[140]-variables[138])*states[20]*states[21] - variables[178] = 1.0/(1.0+exp((variables[140]+49.0)/13.0)) - variables[179] = 0.001*0.6*(65.17/(0.57*exp(-0.08*(variables[140]+44.0))+0.065*exp(0.1*(variables[140]+45.93)))+10.1) - variables[180] = 1.0/(1.0+exp(-(variables[140]-19.3)/15.0)) - variables[181] = 0.001*0.66*1.4*(15.59/(1.037*exp(0.09*(variables[140]+30.61))+0.369*exp(-0.12*(variables[140]+23.84)))+2.98) - variables[182] = variables[62]*(variables[140]-variables[138])*(0.9*states[23]+0.1*states[22])*states[24] - variables[183] = 1.0/(1.0+exp(-(variables[140]+23.2)/6.6))/(0.84655354/(37.2*exp(variables[140]/11.9)+0.96*exp(-variables[140]/18.5))) - variables[184] = 4.0*((37.2*exp(variables[140]/15.9)+0.96*exp(-variables[140]/22.5))/0.84655354-1.0/(1.0+exp(-(variables[140]+23.2)/10.6))/(0.84655354/(37.2*exp(variables[140]/15.9)+0.96*exp(-variables[140]/22.5)))) - variables[185] = 1.0/(1.0+exp(-(variables[140]+10.0144)/7.6607)) - variables[186] = 0.84655354/(4.2*exp(variables[140]/17.0)+0.15*exp(-variables[140]/21.6)) - variables[187] = 1.0/(30.0*exp(variables[140]/10.0)+exp(-variables[140]/12.0)) - variables[188] = 1.0/(100.0*exp(-variables[140]/54.645)+656.0*exp(variables[140]/106.157)) - variables[189] = 1.0/(1.0+exp((variables[140]+28.6)/17.1)) - variables[190] = variables[133]*(variables[140]-variables[134])*pow(states[28], 2.0) - variables[191] = sqrt(1.0/(1.0+exp(-(variables[140]+0.6383-variables[135])/10.7071))) - variables[192] = 28.0/(1.0+exp(-(variables[140]-40.0-variables[135])/3.0)) - variables[193] = 1.0*exp(-(variables[140]-variables[135]-5.0)/25.0) - variables[194] = variables[60]*variables[61]*(variables[140]-variables[138])*(1.0+exp((variables[140]+20.0)/20.0))*states[25] if gt_func(variables[45], 0.0) else 0.0 - variables[195] = 10.0*exp(0.0133*(variables[140]+40.0)) - variables[196] = variables[136]/(variables[136]+variables[195]) - variables[197] = 1.0/(variables[136]+variables[195]) - variables[198] = variables[92]*variables[83]*pow(1.0+pow(variables[81]/variables[37], 1.2), -1.0)*pow(1.0+pow(variables[82]/variables[91], 1.3), -1.0)*pow(1.0+exp(-(variables[140]-variables[137]+110.0)/20.0), -1.0) - variables[199] = exp(-variables[79]*variables[140]/(2.0*variables[117])) - variables[200] = 1.0+states[30]/variables[74]*(1.0+exp(-variables[77]*variables[140]/variables[117])+variables[91]/variables[75])+variables[91]/variables[67]*(1.0+variables[91]/variables[69]*(1.0+variables[91]/variables[71])) - variables[201] = exp(variables[79]*variables[140]/(2.0*variables[117])) - variables[202] = 1.0+variables[35]/variables[76]*(1.0+exp(variables[78]*variables[140]/variables[117]))+variables[38]/variables[68]*(1.0+variables[38]/variables[70]*(1.0+variables[38]/variables[72])) - variables[203] = -0.02839*(variables[168]+41.8)/(exp(-(variables[168]+41.8)/2.5)-1.0)-0.0849*(variables[168]+6.8)/(exp(-(variables[168]+6.8)/4.8)-1.0) - variables[204] = 0.01143*(variables[169]+1.8)/(exp((variables[169]+1.8)/2.5)-1.0) - variables[205] = 1.0/(variables[192]+variables[193]) - variables[206] = states[30]/variables[74]*exp(-variables[77]*variables[140]/variables[117])/variables[200] - variables[207] = variables[91]/variables[67]*variables[91]/variables[69]*(1.0+variables[91]/variables[71])*exp(variables[79]*variables[140]/(2.0*variables[117]))/variables[200] - variables[208] = variables[35]/variables[76]*exp(variables[78]*variables[140]/variables[117])/variables[202] - variables[209] = variables[38]/variables[68]*variables[38]/variables[70]*(1.0+variables[38]/variables[72])*exp(-variables[79]*variables[140]/(2.0*variables[117]))/variables[202] - variables[210] = 0.001/(variables[203]+variables[204]) - variables[211] = variables[199]*variables[94]*(variables[209]+variables[208])+variables[208]*variables[201]*(variables[93]+variables[199]) - variables[212] = variables[201]*variables[93]*(variables[207]+variables[206])+variables[199]*variables[206]*(variables[94]+variables[201]) - variables[213] = variables[207]*variables[93]*(variables[209]+variables[208])+variables[206]*variables[209]*(variables[93]+variables[199]) - variables[214] = variables[209]*variables[94]*(variables[207]+variables[206])+variables[207]*variables[208]*(variables[94]+variables[201]) - variables[215] = (1.0-variables[80])*variables[73]*(variables[212]*variables[208]-variables[211]*variables[206])/(variables[211]+variables[212]+variables[213]+variables[214]) - variables[216] = variables[143]+variables[182]+variables[190]+variables[177]+variables[198]+variables[215]+variables[148]+variables[166]+variables[172]+variables[194]+variables[158] + variables[5] = states[1] + variables[2] = variables[3]*log(variables[4]/variables[5]) + variables[9] = 0.5*variables[3]*log(variables[10]/states[0]) + variables[21] = variables[121] if geq_func(variables[122], 1.0) else states[15] + variables[14] = variables[20]*variables[24]*pow(1.0+pow(variables[23]/variables[7], 1.2), -1.0)*pow(1.0+pow(variables[22]/variables[5], 1.3), -1.0)*pow(1.0+exp(-(variables[21]-variables[2]+110.0)/20.0), -1.0) + variables[50] = 1.0+variables[10]/variables[48]*(1.0+exp(variables[49]*variables[21]/variables[3]))+variables[4]/variables[51]*(1.0+variables[4]/variables[52]*(1.0+variables[4]/variables[47])) + variables[27] = variables[10]/variables[48]*exp(variables[49]*variables[21]/variables[3])/variables[50] + variables[42] = 1.0+states[0]/variables[40]*(1.0+exp(-variables[41]*variables[21]/variables[3])+variables[5]/variables[46])+variables[5]/variables[43]*(1.0+variables[5]/variables[44]*(1.0+variables[5]/variables[39])) + variables[29] = states[0]/variables[40]*exp(-variables[41]*variables[21]/variables[3])/variables[42] + variables[36] = variables[5]/(variables[39]+variables[5]) + variables[37] = exp(variables[45]*variables[21]/(2.0*variables[3])) + variables[33] = exp(-variables[45]*variables[21]/(2.0*variables[3])) + variables[38] = variables[5]/variables[43]*variables[5]/variables[44]*(1.0+variables[5]/variables[39])*exp(variables[45]*variables[21]/(2.0*variables[3]))/variables[42] + variables[26] = variables[37]*variables[36]*(variables[38]+variables[29])+variables[33]*variables[29]*(variables[35]+variables[37]) + variables[34] = variables[4]/variables[51]*variables[4]/variables[52]*(1.0+variables[4]/variables[47])*exp(-variables[45]*variables[21]/(2.0*variables[3]))/variables[50] + variables[28] = variables[33]*variables[35]*(variables[34]+variables[27])+variables[27]*variables[37]*(variables[36]+variables[33]) + variables[31] = variables[34]*variables[35]*(variables[38]+variables[29])+variables[38]*variables[27]*(variables[35]+variables[37]) + variables[32] = variables[38]*variables[36]*(variables[34]+variables[27])+variables[29]*variables[34]*(variables[36]+variables[33]) + variables[13] = (1.0-variables[25])*variables[30]*(variables[26]*variables[27]-variables[28]*variables[29])/(variables[28]+variables[26]+variables[32]+variables[31]) + variables[53] = variables[54]*states[3]*(states[2]-states[0]) + variables[55] = states[2]-states[0] + variables[56] = variables[57]-(variables[57]-variables[58])/(1.0+pow(variables[59]/states[2], variables[60])) + variables[61] = variables[62]/variables[56] + variables[63] = variables[64]*variables[56] + variables[67] = states[4]+states[3]+states[6]+states[5] + variables[71] = (states[0]-states[7])/variables[72] + variables[73] = variables[69]/(1.0+exp((-states[7]+variables[74])/variables[75])) + variables[76] = (states[8]-states[2])/variables[77] + variables[78] = variables[79]*states[7]*(1.0-states[9])-variables[80]*states[9] + variables[81] = variables[82]*states[7]*(1.0-(states[10]+states[11]))-variables[83]*states[10] + variables[84] = variables[85]*variables[86]*(1.0-(states[10]+states[11]))-variables[87]*states[11] + variables[88] = variables[89]*states[7]*(1.0-states[12])-variables[90]*states[12] + variables[91] = variables[89]*states[0]*(1.0-states[13])-variables[90]*states[13] + variables[92] = variables[93]*states[2]*(1.0-states[14])-variables[94]*states[14] + variables[16] = states[16]*variables[133]*(variables[21]-variables[2])*(1.0-variables[135]) + variables[136] = states[16]*variables[134]*(variables[21]-variables[6])*(1.0-variables[135]) + variables[111] = variables[16]+variables[136] + variables[112] = variables[157]*states[20]*states[19]*(variables[21]-variables[6]) + variables[113] = variables[211]*variables[212]*(variables[21]-variables[6])*(1.0+exp((variables[21]+20.0)/20.0))*states[32] if gt_func(variables[0], 0.0) else 0.0 + variables[102] = 2.0*variables[184]*variables[21]/(variables[3]*(1.0-exp(-1.0*variables[21]*2.0/variables[3])))*(states[0]-variables[10]*exp(-2.0*variables[21]/variables[3]))*states[25]*states[24] + variables[101] = 2.0*variables[163]*(variables[21]-0.0)/(variables[3]*(1.0-exp(-1.0*(variables[21]-0.0)*2.0/variables[3])))*(states[0]-variables[10]*exp(-2.0*(variables[21]-0.0)/variables[3]))*states[23]*states[22]*states[21] + variables[15] = 0.0000185*variables[163]*(variables[21]-0.0)/(variables[3]*(1.0-exp(-1.0*(variables[21]-0.0)/variables[3])))*(variables[5]-variables[4]*exp(-1.0*(variables[21]-0.0)/variables[3]))*states[23]*states[22]*states[21] + variables[164] = 0.000365*variables[163]*(variables[21]-0.0)/(variables[3]*(1.0-exp(-1.0*(variables[21]-0.0)/variables[3])))*(variables[8]-variables[7]*exp(-1.0*(variables[21]-0.0)/variables[3]))*states[23]*states[22]*states[21] + variables[114] = (variables[101]+variables[164]+variables[15])*(1.0-variables[165])*1.0*variables[162] + variables[142] = variables[3]*log((variables[4]+0.12*variables[7])/(variables[5]+0.12*variables[8])) + variables[143] = variables[144]*pow(states[18], 3.0)*states[17]*(variables[21]-variables[142]) + variables[145] = variables[146]*pow(states[18], 3.0)*(variables[21]-variables[142]) + variables[12] = variables[143]+variables[145] + variables[115] = variables[190]*(variables[21]-variables[6])*states[27]*states[26] + variables[205] = variables[3]*log((variables[7]+0.12*variables[4])/(variables[8]+0.12*variables[5])) + variables[116] = variables[203]*(variables[21]-variables[205])*pow(states[31], 2.0) + variables[117] = variables[195]*(variables[21]-variables[6])*(0.9*states[29]+0.1*states[30])*states[28] + variables[110] = variables[111]+variables[117]+variables[116]+variables[115]+variables[14]+variables[13]+variables[12]+variables[114]+variables[102]+variables[113]+variables[112] + variables[139] = 1.0/(0.36*(variables[21]+148.8-variables[137]-variables[138])/(exp(0.066*(variables[21]+148.8-variables[137]-variables[138]))-1.0)+0.1*(variables[21]+87.3-variables[137]-variables[138])/(1.0-exp(-0.2*(variables[21]+87.3-variables[137]-variables[138]))))-0.054 + variables[140] = 0.01329+0.99921/(1.0+exp((variables[21]+97.134-variables[137]-variables[138]-variables[141])/8.1752)) if lt_func(variables[21], -(80.0-variables[137]-variables[138]-variables[141])) else 0.0002501*exp(-(variables[21]-variables[137]-variables[138]-variables[141])/12.861) + variables[147] = 1.0/(1.0+exp(-(variables[21]+42.0504)/8.3106)) + variables[148] = variables[21]+41.0 + variables[149] = 2000.0 if lt_func(fabs(variables[148]), variables[150]) else 200.0*variables[148]/(1.0-exp(-0.1*variables[148])) + variables[151] = 8000.0*exp(-0.056*(variables[21]+66.0)) + variables[152] = 1.0/(variables[149]+variables[151]) + variables[153] = 1.0/(1.0+exp((variables[21]+69.804)/4.4565)) + variables[154] = 20.0*exp(-0.125*(variables[21]+75.0)) + variables[155] = 2000.0/(320.0*exp(-0.1*(variables[21]+75.0))+1.0) + variables[156] = 1.0/(variables[154]+variables[155]) + variables[158] = 1.0/(1.0+exp((variables[21]+6.0)/-8.6)) + variables[159] = 0.009/(1.0+exp((variables[21]+5.0)/12.0))+0.0005 + variables[160] = 1.0/(1.0+exp((variables[21]+7.5)/10.0)) + variables[161] = 0.59/(1.0+exp((variables[21]+60.0)/10.0))+3.05 + variables[168] = 1.0/(1.0+exp(-(variables[21]-variables[169]-variables[166])/(variables[170]*(1.0+variables[167]/100.0)))) + variables[174] = -41.80001 if eq_func(variables[21], -41.8) else 0.0 if eq_func(variables[21], 0.0) else -6.80001 if eq_func(variables[21], -6.8) else variables[21] + variables[172] = -0.02839*(variables[174]+41.8)/(exp(-(variables[174]+41.8)/2.5)-1.0)-0.0849*(variables[174]+6.8)/(exp(-(variables[174]+6.8)/4.8)-1.0) + variables[175] = -1.80001 if eq_func(variables[21], -1.8) else variables[21] + variables[173] = 0.01143*(variables[175]+1.8)/(exp((variables[175]+1.8)/2.5)-1.0) + variables[171] = 0.001/(variables[172]+variables[173]) + variables[176] = 1.0/(1.0+exp((variables[21]+37.4+variables[177])/(5.3+variables[178]))) + variables[179] = 0.001*(44.3+230.0*exp(-pow((variables[21]+36.0)/10.0, 2.0))) + variables[180] = variables[181]/(variables[181]+states[0]) + variables[182] = 0.001*variables[180]/variables[183] + variables[185] = 1.0/(1.0+exp(-(variables[21]+38.3)/5.5)) + variables[186] = 0.001/(1.068*exp((variables[21]+38.3)/30.0)+1.068*exp(-(variables[21]+38.3)/30.0)) + variables[187] = 1.0/(1.0+exp((variables[21]+58.7)/3.8)) + variables[188] = 1.0/(16.67*exp(-(variables[21]+75.0)/83.3)+16.67*exp((variables[21]+75.0)/15.38))+variables[189] + variables[191] = 1.0/(1.0+exp((variables[21]+49.0)/13.0)) + variables[192] = 0.001*0.6*(65.17/(0.57*exp(-0.08*(variables[21]+44.0))+0.065*exp(0.1*(variables[21]+45.93)))+10.1) + variables[193] = 1.0/(1.0+exp(-(variables[21]-19.3)/15.0)) + variables[194] = 0.001*0.66*1.4*(15.59/(1.037*exp(0.09*(variables[21]+30.61))+0.369*exp(-0.12*(variables[21]+23.84)))+2.98) + variables[196] = 1.0/(1.0+exp(-(variables[21]+23.2)/6.6))/(0.84655354/(37.2*exp(variables[21]/11.9)+0.96*exp(-variables[21]/18.5))) + variables[197] = 4.0*((37.2*exp(variables[21]/15.9)+0.96*exp(-variables[21]/22.5))/0.84655354-1.0/(1.0+exp(-(variables[21]+23.2)/10.6))/(0.84655354/(37.2*exp(variables[21]/15.9)+0.96*exp(-variables[21]/22.5)))) + variables[198] = 1.0/(1.0+exp(-(variables[21]+10.0144)/7.6607)) + variables[199] = 0.84655354/(4.2*exp(variables[21]/17.0)+0.15*exp(-variables[21]/21.6)) + variables[200] = 1.0/(30.0*exp(variables[21]/10.0)+exp(-variables[21]/12.0)) + variables[201] = 1.0/(100.0*exp(-variables[21]/54.645)+656.0*exp(variables[21]/106.157)) + variables[202] = 1.0/(1.0+exp((variables[21]+28.6)/17.1)) + variables[207] = sqrt(1.0/(1.0+exp(-(variables[21]+0.6383-variables[206])/10.7071))) + variables[209] = 28.0/(1.0+exp(-(variables[21]-40.0-variables[206])/3.0)) + variables[210] = 1.0*exp(-(variables[21]-variables[206]-5.0)/25.0) + variables[208] = 1.0/(variables[209]+variables[210]) + variables[214] = 10.0*exp(0.0133*(variables[21]+40.0)) + variables[215] = variables[213]/(variables[213]+variables[214]) + variables[216] = 1.0/(variables[213]+variables[214]) diff --git a/tests/resources/generator/garny_kohl_hunter_boyett_noble_rabbit_san_model_2003/model.c b/tests/resources/generator/garny_kohl_hunter_boyett_noble_rabbit_san_model_2003/model.c index 57a06a764..d6ff20df4 100644 --- a/tests/resources/generator/garny_kohl_hunter_boyett_noble_rabbit_san_model_2003/model.c +++ b/tests/resources/generator/garny_kohl_hunter_boyett_noble_rabbit_san_model_2003/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 15; const size_t VARIABLE_COUNT = 185; @@ -14,187 +14,177 @@ const size_t VARIABLE_COUNT = 185; const VariableInfo VOI_INFO = {"time", "second", "environment", VARIABLE_OF_INTEGRATION}; const VariableInfo STATE_INFO[] = { + {"V", "millivolt", "membrane", STATE}, {"m", "dimensionless", "sodium_current_m_gate", STATE}, {"h1", "dimensionless", "sodium_current_h_gate", STATE}, {"h2", "dimensionless", "sodium_current_h_gate", STATE}, - {"d_L", "dimensionless", "L_type_Ca_channel_d_gate", STATE}, {"f_L", "dimensionless", "L_type_Ca_channel_f_gate", STATE}, - {"d_T", "dimensionless", "T_type_Ca_channel_d_gate", STATE}, + {"d_L", "dimensionless", "L_type_Ca_channel_d_gate", STATE}, {"f_T", "dimensionless", "T_type_Ca_channel_f_gate", STATE}, - {"q", "dimensionless", "four_AP_sensitive_currents_q_gate", STATE}, + {"d_T", "dimensionless", "T_type_Ca_channel_d_gate", STATE}, {"r", "dimensionless", "four_AP_sensitive_currents_r_gate", STATE}, + {"q", "dimensionless", "four_AP_sensitive_currents_q_gate", STATE}, + {"P_i", "dimensionless", "rapid_delayed_rectifying_potassium_current_P_i_gate", STATE}, {"P_af", "dimensionless", "rapid_delayed_rectifying_potassium_current_P_af_gate", STATE}, {"P_as", "dimensionless", "rapid_delayed_rectifying_potassium_current_P_as_gate", STATE}, - {"P_i", "dimensionless", "rapid_delayed_rectifying_potassium_current_P_i_gate", STATE}, {"xs", "dimensionless", "slow_delayed_rectifying_potassium_current_xs_gate", STATE}, - {"y", "dimensionless", "hyperpolarisation_activated_current_y_gate", STATE}, - {"V", "millivolt", "membrane", STATE} + {"y", "dimensionless", "hyperpolarisation_activated_current_y_gate", STATE} }; const VariableInfo VARIABLE_INFO[] = { - {"E_Ca_L", "millivolt", "L_type_Ca_channel", CONSTANT}, - {"g_Ca_L_Centre_0DCapable", "microS", "L_type_Ca_channel", CONSTANT}, - {"g_Ca_L_Centre_1DCapable", "microS", "L_type_Ca_channel", CONSTANT}, - {"g_Ca_L_Centre_Published", "microS", "L_type_Ca_channel", CONSTANT}, - {"g_Ca_L_Periphery_0DCapable", "microS", "L_type_Ca_channel", CONSTANT}, - {"g_Ca_L_Periphery_1DCapable", "microS", "L_type_Ca_channel", CONSTANT}, - {"g_Ca_L_Periphery_Published", "microS", "L_type_Ca_channel", CONSTANT}, - {"E_Ca_T", "millivolt", "T_type_Ca_channel", CONSTANT}, - {"g_Ca_T_Centre_0DCapable", "microS", "T_type_Ca_channel", CONSTANT}, - {"g_Ca_T_Centre_1DCapable", "microS", "T_type_Ca_channel", CONSTANT}, - {"g_Ca_T_Centre_Published", "microS", "T_type_Ca_channel", CONSTANT}, - {"g_Ca_T_Periphery_0DCapable", "microS", "T_type_Ca_channel", CONSTANT}, - {"g_Ca_T_Periphery_1DCapable", "microS", "T_type_Ca_channel", CONSTANT}, - {"g_Ca_T_Periphery_Published", "microS", "T_type_Ca_channel", CONSTANT}, - {"g_b_Ca_Centre_0DCapable", "microS", "calcium_background_current", CONSTANT}, - {"g_b_Ca_Centre_1DCapable", "microS", "calcium_background_current", CONSTANT}, - {"g_b_Ca_Centre_Published", "microS", "calcium_background_current", CONSTANT}, - {"g_b_Ca_Periphery_0DCapable", "microS", "calcium_background_current", CONSTANT}, - {"g_b_Ca_Periphery_1DCapable", "microS", "calcium_background_current", CONSTANT}, - {"g_b_Ca_Periphery_Published", "microS", "calcium_background_current", CONSTANT}, - {"g_sus_Centre_0DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, - {"g_sus_Centre_1DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, - {"g_sus_Centre_Published", "microS", "four_AP_sensitive_currents", CONSTANT}, - {"g_sus_Periphery_0DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, - {"g_sus_Periphery_1DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, - {"g_sus_Periphery_Published", "microS", "four_AP_sensitive_currents", CONSTANT}, - {"g_to_Centre_0DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, - {"g_to_Centre_1DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, - {"g_to_Centre_Published", "microS", "four_AP_sensitive_currents", CONSTANT}, - {"g_to_Periphery_0DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, - {"g_to_Periphery_1DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, - {"g_to_Periphery_Published", "microS", "four_AP_sensitive_currents", CONSTANT}, - {"g_f_K_Centre_0DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, - {"g_f_K_Centre_1DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, - {"g_f_K_Centre_Published", "microS", "hyperpolarisation_activated_current", CONSTANT}, - {"g_f_K_Periphery_0DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, - {"g_f_K_Periphery_1DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, - {"g_f_K_Periphery_Published", "microS", "hyperpolarisation_activated_current", CONSTANT}, - {"g_f_Na_Centre_0DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, - {"g_f_Na_Centre_1DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, - {"g_f_Na_Centre_Published", "microS", "hyperpolarisation_activated_current", CONSTANT}, - {"g_f_Na_Periphery_0DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, - {"g_f_Na_Periphery_1DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, - {"g_f_Na_Periphery_Published", "microS", "hyperpolarisation_activated_current", CONSTANT}, - {"Ca_i", "millimolar", "ionic_concentrations", CONSTANT}, - {"Ca_o", "millimolar", "ionic_concentrations", CONSTANT}, - {"K_i", "millimolar", "ionic_concentrations", CONSTANT}, - {"K_o", "millimolar", "ionic_concentrations", CONSTANT}, - {"Na_i", "millimolar", "ionic_concentrations", CONSTANT}, - {"Na_o", "millimolar", "ionic_concentrations", CONSTANT}, + {"FCell", "dimensionless", "membrane", COMPUTED_CONSTANT}, + {"dCell", "dimensionless", "membrane", CONSTANT}, + {"Version", "dimensionless", "membrane", CONSTANT}, + {"FCellConstant", "dimensionless", "membrane", CONSTANT}, + {"Cm", "microF", "membrane", COMPUTED_CONSTANT}, {"CmCentre", "microF", "membrane", CONSTANT}, {"CmPeriphery", "microF", "membrane", CONSTANT}, - {"F", "coulomb_per_mole", "membrane", CONSTANT}, - {"FCellConstant", "dimensionless", "membrane", CONSTANT}, + {"i_Na", "nanoA", "sodium_current", ALGEBRAIC}, + {"i_Ca_p", "nanoA", "persistent_calcium_current", COMPUTED_CONSTANT}, + {"i_p", "nanoA", "sodium_potassium_pump", ALGEBRAIC}, + {"i_NaCa", "nanoA", "sodium_calcium_exchanger", ALGEBRAIC}, + {"i_b_K", "nanoA", "potassium_background_current", ALGEBRAIC}, + {"i_b_Ca", "nanoA", "calcium_background_current", ALGEBRAIC}, + {"i_b_Na", "nanoA", "sodium_background_current", ALGEBRAIC}, + {"i_f_K", "nanoA", "hyperpolarisation_activated_current", ALGEBRAIC}, + {"i_f_Na", "nanoA", "hyperpolarisation_activated_current", ALGEBRAIC}, + {"i_K_s", "nanoA", "slow_delayed_rectifying_potassium_current", ALGEBRAIC}, + {"i_K_r", "nanoA", "rapid_delayed_rectifying_potassium_current", ALGEBRAIC}, + {"i_sus", "nanoA", "four_AP_sensitive_currents", ALGEBRAIC}, + {"i_to", "nanoA", "four_AP_sensitive_currents", ALGEBRAIC}, + {"i_Ca_T", "nanoA", "T_type_Ca_channel", ALGEBRAIC}, + {"i_Ca_L", "nanoA", "L_type_Ca_channel", ALGEBRAIC}, {"R", "millijoule_per_mole_kelvin", "membrane", CONSTANT}, {"T", "kelvin", "membrane", CONSTANT}, - {"Version", "dimensionless", "membrane", CONSTANT}, - {"dCell", "dimensionless", "membrane", CONSTANT}, - {"i_Ca_p_max_Centre_0DCapable", "nanoA", "persistent_calcium_current", CONSTANT}, - {"i_Ca_p_max_Centre_1DCapable", "nanoA", "persistent_calcium_current", CONSTANT}, - {"i_Ca_p_max_Centre_Published", "nanoA", "persistent_calcium_current", CONSTANT}, - {"i_Ca_p_max_Periphery_0DCapable", "nanoA", "persistent_calcium_current", CONSTANT}, - {"i_Ca_p_max_Periphery_1DCapable", "nanoA", "persistent_calcium_current", CONSTANT}, - {"i_Ca_p_max_Periphery_Published", "nanoA", "persistent_calcium_current", CONSTANT}, - {"g_b_K_Centre_0DCapable", "microS", "potassium_background_current", CONSTANT}, - {"g_b_K_Centre_1DCapable", "microS", "potassium_background_current", CONSTANT}, - {"g_b_K_Centre_Published", "microS", "potassium_background_current", CONSTANT}, - {"g_b_K_Periphery_0DCapable", "microS", "potassium_background_current", CONSTANT}, - {"g_b_K_Periphery_1DCapable", "microS", "potassium_background_current", CONSTANT}, - {"g_b_K_Periphery_Published", "microS", "potassium_background_current", CONSTANT}, - {"g_K_r_Centre_0DCapable", "microS", "rapid_delayed_rectifying_potassium_current", CONSTANT}, - {"g_K_r_Centre_1DCapable", "microS", "rapid_delayed_rectifying_potassium_current", CONSTANT}, - {"g_K_r_Centre_Published", "microS", "rapid_delayed_rectifying_potassium_current", CONSTANT}, - {"g_K_r_Periphery_0DCapable", "microS", "rapid_delayed_rectifying_potassium_current", CONSTANT}, - {"g_K_r_Periphery_1DCapable", "microS", "rapid_delayed_rectifying_potassium_current", CONSTANT}, - {"g_K_r_Periphery_Published", "microS", "rapid_delayed_rectifying_potassium_current", CONSTANT}, - {"g_K_s_Centre_0DCapable", "microS", "slow_delayed_rectifying_potassium_current", CONSTANT}, - {"g_K_s_Centre_1DCapable", "microS", "slow_delayed_rectifying_potassium_current", CONSTANT}, - {"g_K_s_Centre_Published", "microS", "slow_delayed_rectifying_potassium_current", CONSTANT}, - {"g_K_s_Periphery_0DCapable", "microS", "slow_delayed_rectifying_potassium_current", CONSTANT}, - {"g_K_s_Periphery_1DCapable", "microS", "slow_delayed_rectifying_potassium_current", CONSTANT}, - {"g_K_s_Periphery_Published", "microS", "slow_delayed_rectifying_potassium_current", CONSTANT}, - {"g_b_Na_Centre_0DCapable", "microS", "sodium_background_current", CONSTANT}, - {"g_b_Na_Centre_1DCapable", "microS", "sodium_background_current", CONSTANT}, + {"F", "coulomb_per_mole", "membrane", CONSTANT}, + {"g_b_Na", "microS", "sodium_background_current", COMPUTED_CONSTANT}, {"g_b_Na_Centre_Published", "microS", "sodium_background_current", CONSTANT}, - {"g_b_Na_Periphery_0DCapable", "microS", "sodium_background_current", CONSTANT}, - {"g_b_Na_Periphery_1DCapable", "microS", "sodium_background_current", CONSTANT}, {"g_b_Na_Periphery_Published", "microS", "sodium_background_current", CONSTANT}, - {"d_NaCa", "dimensionless", "sodium_calcium_exchanger", CONSTANT}, - {"gamma_NaCa", "dimensionless", "sodium_calcium_exchanger", CONSTANT}, - {"k_NaCa_Centre_0DCapable", "nanoA", "sodium_calcium_exchanger", CONSTANT}, - {"k_NaCa_Centre_1DCapable", "nanoA", "sodium_calcium_exchanger", CONSTANT}, - {"k_NaCa_Centre_Published", "nanoA", "sodium_calcium_exchanger", CONSTANT}, - {"k_NaCa_Periphery_0DCapable", "nanoA", "sodium_calcium_exchanger", CONSTANT}, - {"k_NaCa_Periphery_1DCapable", "nanoA", "sodium_calcium_exchanger", CONSTANT}, - {"k_NaCa_Periphery_Published", "nanoA", "sodium_calcium_exchanger", CONSTANT}, - {"g_Na_Centre_0DCapable", "microlitre_per_second", "sodium_current", CONSTANT}, - {"g_Na_Centre_1DCapable", "microlitre_per_second", "sodium_current", CONSTANT}, - {"g_Na_Centre_Published", "microlitre_per_second", "sodium_current", CONSTANT}, - {"g_Na_Periphery_0DCapable", "microlitre_per_second", "sodium_current", CONSTANT}, - {"g_Na_Periphery_1DCapable", "microlitre_per_second", "sodium_current", CONSTANT}, - {"g_Na_Periphery_Published", "microlitre_per_second", "sodium_current", CONSTANT}, - {"K_m_K", "millimolar", "sodium_potassium_pump", CONSTANT}, - {"K_m_Na", "millimolar", "sodium_potassium_pump", CONSTANT}, - {"i_p_max_Centre_0DCapable", "nanoA", "sodium_potassium_pump", CONSTANT}, - {"i_p_max_Centre_1DCapable", "nanoA", "sodium_potassium_pump", CONSTANT}, - {"i_p_max_Centre_Published", "nanoA", "sodium_potassium_pump", CONSTANT}, - {"i_p_max_Periphery_0DCapable", "nanoA", "sodium_potassium_pump", CONSTANT}, - {"i_p_max_Periphery_1DCapable", "nanoA", "sodium_potassium_pump", CONSTANT}, - {"i_p_max_Periphery_Published", "nanoA", "sodium_potassium_pump", CONSTANT}, - {"FCell", "dimensionless", "membrane", COMPUTED_CONSTANT}, - {"Cm", "microF", "membrane", COMPUTED_CONSTANT}, - {"g_b_Na", "microS", "sodium_background_current", COMPUTED_CONSTANT}, + {"g_b_Na_Centre_1DCapable", "microS", "sodium_background_current", CONSTANT}, + {"g_b_Na_Periphery_1DCapable", "microS", "sodium_background_current", CONSTANT}, + {"g_b_Na_Centre_0DCapable", "microS", "sodium_background_current", CONSTANT}, + {"g_b_Na_Periphery_0DCapable", "microS", "sodium_background_current", CONSTANT}, + {"E_Na", "millivolt", "reversal_and_equilibrium_potentials", COMPUTED_CONSTANT}, {"g_b_K", "microS", "potassium_background_current", COMPUTED_CONSTANT}, + {"g_b_K_Centre_Published", "microS", "potassium_background_current", CONSTANT}, + {"g_b_K_Periphery_Published", "microS", "potassium_background_current", CONSTANT}, + {"g_b_K_Centre_1DCapable", "microS", "potassium_background_current", CONSTANT}, + {"g_b_K_Periphery_1DCapable", "microS", "potassium_background_current", CONSTANT}, + {"g_b_K_Centre_0DCapable", "microS", "potassium_background_current", CONSTANT}, + {"g_b_K_Periphery_0DCapable", "microS", "potassium_background_current", CONSTANT}, + {"E_K", "millivolt", "reversal_and_equilibrium_potentials", COMPUTED_CONSTANT}, {"g_b_Ca", "microS", "calcium_background_current", COMPUTED_CONSTANT}, + {"g_b_Ca_Centre_Published", "microS", "calcium_background_current", CONSTANT}, + {"g_b_Ca_Periphery_Published", "microS", "calcium_background_current", CONSTANT}, + {"g_b_Ca_Centre_1DCapable", "microS", "calcium_background_current", CONSTANT}, + {"g_b_Ca_Periphery_1DCapable", "microS", "calcium_background_current", CONSTANT}, + {"g_b_Ca_Centre_0DCapable", "microS", "calcium_background_current", CONSTANT}, + {"g_b_Ca_Periphery_0DCapable", "microS", "calcium_background_current", CONSTANT}, + {"E_Ca", "millivolt", "reversal_and_equilibrium_potentials", COMPUTED_CONSTANT}, {"k_NaCa", "nanoA", "sodium_calcium_exchanger", COMPUTED_CONSTANT}, - {"i_NaCa", "nanoA", "sodium_calcium_exchanger", ALGEBRAIC}, + {"k_NaCa_Centre_Published", "nanoA", "sodium_calcium_exchanger", CONSTANT}, + {"k_NaCa_Periphery_Published", "nanoA", "sodium_calcium_exchanger", CONSTANT}, + {"k_NaCa_Centre_1DCapable", "nanoA", "sodium_calcium_exchanger", CONSTANT}, + {"k_NaCa_Periphery_1DCapable", "nanoA", "sodium_calcium_exchanger", CONSTANT}, + {"k_NaCa_Centre_0DCapable", "nanoA", "sodium_calcium_exchanger", CONSTANT}, + {"k_NaCa_Periphery_0DCapable", "nanoA", "sodium_calcium_exchanger", CONSTANT}, + {"Na_i", "millimolar", "ionic_concentrations", CONSTANT}, + {"gamma_NaCa", "dimensionless", "sodium_calcium_exchanger", CONSTANT}, + {"Ca_o", "millimolar", "ionic_concentrations", CONSTANT}, + {"Na_o", "millimolar", "ionic_concentrations", CONSTANT}, + {"Ca_i", "millimolar", "ionic_concentrations", CONSTANT}, + {"d_NaCa", "dimensionless", "sodium_calcium_exchanger", CONSTANT}, {"i_p_max", "nanoA", "sodium_potassium_pump", COMPUTED_CONSTANT}, - {"i_p", "nanoA", "sodium_potassium_pump", ALGEBRAIC}, + {"i_p_max_Centre_Published", "nanoA", "sodium_potassium_pump", CONSTANT}, + {"i_p_max_Periphery_Published", "nanoA", "sodium_potassium_pump", CONSTANT}, + {"i_p_max_Centre_1DCapable", "nanoA", "sodium_potassium_pump", CONSTANT}, + {"i_p_max_Periphery_1DCapable", "nanoA", "sodium_potassium_pump", CONSTANT}, + {"i_p_max_Centre_0DCapable", "nanoA", "sodium_potassium_pump", CONSTANT}, + {"i_p_max_Periphery_0DCapable", "nanoA", "sodium_potassium_pump", CONSTANT}, + {"K_o", "millimolar", "ionic_concentrations", CONSTANT}, + {"K_m_K", "millimolar", "sodium_potassium_pump", CONSTANT}, + {"K_m_Na", "millimolar", "sodium_potassium_pump", CONSTANT}, {"i_Ca_p_max", "nanoA", "persistent_calcium_current", COMPUTED_CONSTANT}, - {"i_Ca_p", "nanoA", "persistent_calcium_current", COMPUTED_CONSTANT}, - {"E_Na", "millivolt", "reversal_and_equilibrium_potentials", COMPUTED_CONSTANT}, - {"E_K", "millivolt", "reversal_and_equilibrium_potentials", COMPUTED_CONSTANT}, - {"E_Ca", "millivolt", "reversal_and_equilibrium_potentials", COMPUTED_CONSTANT}, + {"i_Ca_p_max_Centre_Published", "nanoA", "persistent_calcium_current", CONSTANT}, + {"i_Ca_p_max_Periphery_Published", "nanoA", "persistent_calcium_current", CONSTANT}, + {"i_Ca_p_max_Centre_1DCapable", "nanoA", "persistent_calcium_current", CONSTANT}, + {"i_Ca_p_max_Periphery_1DCapable", "nanoA", "persistent_calcium_current", CONSTANT}, + {"i_Ca_p_max_Centre_0DCapable", "nanoA", "persistent_calcium_current", CONSTANT}, + {"i_Ca_p_max_Periphery_0DCapable", "nanoA", "persistent_calcium_current", CONSTANT}, + {"K_i", "millimolar", "ionic_concentrations", CONSTANT}, {"E_K_s", "millivolt", "reversal_and_equilibrium_potentials", COMPUTED_CONSTANT}, {"g_Na", "microlitre_per_second", "sodium_current", COMPUTED_CONSTANT}, + {"g_Na_Centre_Published", "microlitre_per_second", "sodium_current", CONSTANT}, + {"g_Na_Periphery_Published", "microlitre_per_second", "sodium_current", CONSTANT}, + {"g_Na_Centre_1DCapable", "microlitre_per_second", "sodium_current", CONSTANT}, + {"g_Na_Periphery_1DCapable", "microlitre_per_second", "sodium_current", CONSTANT}, + {"g_Na_Centre_0DCapable", "microlitre_per_second", "sodium_current", CONSTANT}, + {"g_Na_Periphery_0DCapable", "microlitre_per_second", "sodium_current", CONSTANT}, + {"h", "dimensionless", "sodium_current_h_gate", ALGEBRAIC}, {"m_infinity", "dimensionless", "sodium_current_m_gate", ALGEBRAIC}, {"tau_m", "second", "sodium_current_m_gate", ALGEBRAIC}, {"F_Na", "dimensionless", "sodium_current_h_gate", ALGEBRAIC}, - {"h", "dimensionless", "sodium_current_h_gate", ALGEBRAIC}, {"h1_infinity", "dimensionless", "sodium_current_h_gate", ALGEBRAIC}, - {"h2_infinity", "dimensionless", "sodium_current_h_gate", ALGEBRAIC}, {"tau_h1", "second", "sodium_current_h_gate", ALGEBRAIC}, + {"h2_infinity", "dimensionless", "sodium_current_h_gate", ALGEBRAIC}, {"tau_h2", "second", "sodium_current_h_gate", ALGEBRAIC}, {"g_Ca_L", "microS", "L_type_Ca_channel", COMPUTED_CONSTANT}, - {"i_Ca_L", "nanoA", "L_type_Ca_channel", ALGEBRAIC}, + {"g_Ca_L_Centre_Published", "microS", "L_type_Ca_channel", CONSTANT}, + {"g_Ca_L_Periphery_Published", "microS", "L_type_Ca_channel", CONSTANT}, + {"g_Ca_L_Centre_1DCapable", "microS", "L_type_Ca_channel", CONSTANT}, + {"g_Ca_L_Periphery_1DCapable", "microS", "L_type_Ca_channel", CONSTANT}, + {"g_Ca_L_Centre_0DCapable", "microS", "L_type_Ca_channel", CONSTANT}, + {"g_Ca_L_Periphery_0DCapable", "microS", "L_type_Ca_channel", CONSTANT}, + {"E_Ca_L", "millivolt", "L_type_Ca_channel", CONSTANT}, + {"d_L_infinity", "dimensionless", "L_type_Ca_channel_d_gate", ALGEBRAIC}, + {"tau_d_L", "second", "L_type_Ca_channel_d_gate", ALGEBRAIC}, {"alpha_d_L", "per_second", "L_type_Ca_channel_d_gate", ALGEBRAIC}, {"beta_d_L", "per_second", "L_type_Ca_channel_d_gate", ALGEBRAIC}, - {"tau_d_L", "second", "L_type_Ca_channel_d_gate", ALGEBRAIC}, - {"d_L_infinity", "dimensionless", "L_type_Ca_channel_d_gate", ALGEBRAIC}, + {"f_L_infinity", "dimensionless", "L_type_Ca_channel_f_gate", ALGEBRAIC}, + {"tau_f_L", "second", "L_type_Ca_channel_f_gate", ALGEBRAIC}, {"alpha_f_L", "per_second", "L_type_Ca_channel_f_gate", ALGEBRAIC}, {"beta_f_L", "per_second", "L_type_Ca_channel_f_gate", ALGEBRAIC}, - {"tau_f_L", "second", "L_type_Ca_channel_f_gate", ALGEBRAIC}, - {"f_L_infinity", "dimensionless", "L_type_Ca_channel_f_gate", ALGEBRAIC}, {"g_Ca_T", "microS", "T_type_Ca_channel", COMPUTED_CONSTANT}, - {"i_Ca_T", "nanoA", "T_type_Ca_channel", ALGEBRAIC}, + {"g_Ca_T_Centre_Published", "microS", "T_type_Ca_channel", CONSTANT}, + {"g_Ca_T_Periphery_Published", "microS", "T_type_Ca_channel", CONSTANT}, + {"g_Ca_T_Centre_1DCapable", "microS", "T_type_Ca_channel", CONSTANT}, + {"g_Ca_T_Periphery_1DCapable", "microS", "T_type_Ca_channel", CONSTANT}, + {"g_Ca_T_Centre_0DCapable", "microS", "T_type_Ca_channel", CONSTANT}, + {"g_Ca_T_Periphery_0DCapable", "microS", "T_type_Ca_channel", CONSTANT}, + {"E_Ca_T", "millivolt", "T_type_Ca_channel", CONSTANT}, + {"d_T_infinity", "dimensionless", "T_type_Ca_channel_d_gate", ALGEBRAIC}, + {"tau_d_T", "second", "T_type_Ca_channel_d_gate", ALGEBRAIC}, {"alpha_d_T", "per_second", "T_type_Ca_channel_d_gate", ALGEBRAIC}, {"beta_d_T", "per_second", "T_type_Ca_channel_d_gate", ALGEBRAIC}, - {"tau_d_T", "second", "T_type_Ca_channel_d_gate", ALGEBRAIC}, - {"d_T_infinity", "dimensionless", "T_type_Ca_channel_d_gate", ALGEBRAIC}, + {"f_T_infinity", "dimensionless", "T_type_Ca_channel_f_gate", ALGEBRAIC}, + {"tau_f_T", "second", "T_type_Ca_channel_f_gate", ALGEBRAIC}, {"alpha_f_T", "per_second", "T_type_Ca_channel_f_gate", ALGEBRAIC}, {"beta_f_T", "per_second", "T_type_Ca_channel_f_gate", ALGEBRAIC}, - {"tau_f_T", "second", "T_type_Ca_channel_f_gate", ALGEBRAIC}, - {"f_T_infinity", "dimensionless", "T_type_Ca_channel_f_gate", ALGEBRAIC}, {"g_to", "microS", "four_AP_sensitive_currents", COMPUTED_CONSTANT}, + {"g_to_Centre_Published", "microS", "four_AP_sensitive_currents", CONSTANT}, + {"g_to_Periphery_Published", "microS", "four_AP_sensitive_currents", CONSTANT}, + {"g_to_Centre_1DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, + {"g_to_Periphery_1DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, + {"g_to_Centre_0DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, + {"g_to_Periphery_0DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, {"g_sus", "microS", "four_AP_sensitive_currents", COMPUTED_CONSTANT}, - {"i_to", "nanoA", "four_AP_sensitive_currents", ALGEBRAIC}, - {"i_sus", "nanoA", "four_AP_sensitive_currents", ALGEBRAIC}, + {"g_sus_Centre_Published", "microS", "four_AP_sensitive_currents", CONSTANT}, + {"g_sus_Periphery_Published", "microS", "four_AP_sensitive_currents", CONSTANT}, + {"g_sus_Centre_1DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, + {"g_sus_Periphery_1DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, + {"g_sus_Centre_0DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, + {"g_sus_Periphery_0DCapable", "microS", "four_AP_sensitive_currents", CONSTANT}, {"q_infinity", "dimensionless", "four_AP_sensitive_currents_q_gate", ALGEBRAIC}, {"tau_q", "second", "four_AP_sensitive_currents_q_gate", ALGEBRAIC}, {"r_infinity", "dimensionless", "four_AP_sensitive_currents_r_gate", ALGEBRAIC}, {"tau_r", "second", "four_AP_sensitive_currents_r_gate", ALGEBRAIC}, {"g_K_r", "microS", "rapid_delayed_rectifying_potassium_current", COMPUTED_CONSTANT}, + {"g_K_r_Centre_Published", "microS", "rapid_delayed_rectifying_potassium_current", CONSTANT}, + {"g_K_r_Periphery_Published", "microS", "rapid_delayed_rectifying_potassium_current", CONSTANT}, + {"g_K_r_Centre_1DCapable", "microS", "rapid_delayed_rectifying_potassium_current", CONSTANT}, + {"g_K_r_Periphery_1DCapable", "microS", "rapid_delayed_rectifying_potassium_current", CONSTANT}, + {"g_K_r_Centre_0DCapable", "microS", "rapid_delayed_rectifying_potassium_current", CONSTANT}, + {"g_K_r_Periphery_0DCapable", "microS", "rapid_delayed_rectifying_potassium_current", CONSTANT}, {"P_a", "dimensionless", "rapid_delayed_rectifying_potassium_current", ALGEBRAIC}, {"P_af_infinity", "dimensionless", "rapid_delayed_rectifying_potassium_current_P_af_gate", ALGEBRAIC}, {"tau_P_af", "second", "rapid_delayed_rectifying_potassium_current_P_af_gate", ALGEBRAIC}, @@ -203,30 +193,52 @@ const VariableInfo VARIABLE_INFO[] = { {"tau_P_i", "second", "rapid_delayed_rectifying_potassium_current_P_i_gate", COMPUTED_CONSTANT}, {"P_i_infinity", "dimensionless", "rapid_delayed_rectifying_potassium_current_P_i_gate", ALGEBRAIC}, {"g_K_s", "microS", "slow_delayed_rectifying_potassium_current", COMPUTED_CONSTANT}, - {"i_K_s", "nanoA", "slow_delayed_rectifying_potassium_current", ALGEBRAIC}, + {"g_K_s_Centre_Published", "microS", "slow_delayed_rectifying_potassium_current", CONSTANT}, + {"g_K_s_Periphery_Published", "microS", "slow_delayed_rectifying_potassium_current", CONSTANT}, + {"g_K_s_Centre_1DCapable", "microS", "slow_delayed_rectifying_potassium_current", CONSTANT}, + {"g_K_s_Periphery_1DCapable", "microS", "slow_delayed_rectifying_potassium_current", CONSTANT}, + {"g_K_s_Centre_0DCapable", "microS", "slow_delayed_rectifying_potassium_current", CONSTANT}, + {"g_K_s_Periphery_0DCapable", "microS", "slow_delayed_rectifying_potassium_current", CONSTANT}, {"alpha_xs", "per_second", "slow_delayed_rectifying_potassium_current_xs_gate", ALGEBRAIC}, {"beta_xs", "per_second", "slow_delayed_rectifying_potassium_current_xs_gate", ALGEBRAIC}, {"g_f_Na", "microS", "hyperpolarisation_activated_current", COMPUTED_CONSTANT}, - {"i_f_Na", "nanoA", "hyperpolarisation_activated_current", ALGEBRAIC}, + {"g_f_Na_Centre_Published", "microS", "hyperpolarisation_activated_current", CONSTANT}, + {"g_f_Na_Periphery_Published", "microS", "hyperpolarisation_activated_current", CONSTANT}, + {"g_f_Na_Centre_1DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, + {"g_f_Na_Periphery_1DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, + {"g_f_Na_Centre_0DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, + {"g_f_Na_Periphery_0DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, {"g_f_K", "microS", "hyperpolarisation_activated_current", COMPUTED_CONSTANT}, - {"i_f_K", "nanoA", "hyperpolarisation_activated_current", ALGEBRAIC}, + {"g_f_K_Centre_Published", "microS", "hyperpolarisation_activated_current", CONSTANT}, + {"g_f_K_Periphery_Published", "microS", "hyperpolarisation_activated_current", CONSTANT}, + {"g_f_K_Centre_1DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, + {"g_f_K_Periphery_1DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, + {"g_f_K_Centre_0DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, + {"g_f_K_Periphery_0DCapable", "microS", "hyperpolarisation_activated_current", CONSTANT}, {"alpha_y", "per_second", "hyperpolarisation_activated_current_y_gate", ALGEBRAIC}, - {"beta_y", "per_second", "hyperpolarisation_activated_current_y_gate", ALGEBRAIC}, - {"i_b_Na", "nanoA", "sodium_background_current", ALGEBRAIC}, - {"i_b_K", "nanoA", "potassium_background_current", ALGEBRAIC}, - {"i_b_Ca", "nanoA", "calcium_background_current", ALGEBRAIC}, - {"i_Na", "nanoA", "sodium_current", ALGEBRAIC}, - {"i_K_r", "nanoA", "rapid_delayed_rectifying_potassium_current", ALGEBRAIC} + {"beta_y", "per_second", "hyperpolarisation_activated_current_y_gate", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -234,285 +246,285 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { - variables[0] = 46.4; - variables[1] = 0.0057938; - variables[2] = 0.0082; - variables[3] = 0.0058; - variables[4] = 0.06588648; - variables[5] = 0.0659; - variables[6] = 0.0659; - variables[7] = 45.0; - variables[8] = 0.00427806; - variables[9] = 0.0021; - variables[10] = 0.0043; - variables[11] = 0.0138823; - variables[12] = 0.00694; - variables[13] = 0.0139; - variables[14] = 1.3236e-5; - variables[15] = 1.323e-5; - variables[16] = 1.32e-5; - variables[17] = 4.2952e-5; - variables[18] = 4.29e-5; - variables[19] = 4.3e-5; - variables[20] = 6.645504e-5; - variables[21] = 0.000266; - variables[22] = 6.65e-5; - variables[23] = 0.01138376; - variables[24] = 0.0114; - variables[25] = 0.0114; - variables[26] = 0.004905; - variables[27] = 0.004905; - variables[28] = 0.00491; - variables[29] = 0.036495; - variables[30] = 0.0365; - variables[31] = 0.03649; - variables[32] = 0.0005465; - variables[33] = 0.000437; - variables[34] = 0.000548; - variables[35] = 0.006875; - variables[36] = 0.0055; - variables[37] = 0.0069; - variables[38] = 0.0005465; - variables[39] = 0.000437; - variables[40] = 0.000548; - variables[41] = 0.006875; - variables[42] = 0.0055; - variables[43] = 0.0069; - variables[44] = 0.0001; - variables[45] = 2.0; - variables[46] = 140.0; - variables[47] = 5.4; - variables[48] = 8.0; - variables[49] = 140.0; - variables[50] = 2.0e-5; - variables[51] = 6.5e-5; - variables[52] = 96845.0; - variables[53] = 1.0309347; - variables[54] = 8314.0; - variables[55] = 310.0; - variables[56] = 1.0; - variables[57] = 0.0; - variables[58] = 0.0; - variables[59] = 0.0042; - variables[60] = 0.0; - variables[61] = 0.0; - variables[62] = 0.03339; - variables[63] = 0.0; - variables[64] = 2.523636e-5; - variables[65] = 2.52e-5; - variables[66] = 2.52e-5; - variables[67] = 8.1892e-5; - variables[68] = 8.19e-5; - variables[69] = 8.19e-5; - variables[70] = 0.00079704; - variables[71] = 0.000738; - variables[72] = 0.000797; - variables[73] = 0.016; - variables[74] = 0.0208; - variables[75] = 0.016; - variables[76] = 0.0003445; - variables[77] = 0.000345; - variables[78] = 0.000518; - variables[79] = 0.0104; - variables[80] = 0.0104; - variables[81] = 0.0104; - variables[82] = 5.81818e-5; - variables[83] = 5.8e-5; - variables[84] = 5.8e-5; - variables[85] = 0.0001888; - variables[86] = 0.000189; - variables[87] = 0.000189; - variables[88] = 0.0001; - variables[89] = 0.5; - variables[90] = 2.7229e-6; - variables[91] = 2.8e-6; - variables[92] = 2.7e-6; - variables[93] = 8.83584e-6; - variables[94] = 8.8e-6; - variables[95] = 8.8e-6; - variables[96] = 0.0; - variables[97] = 0.0; - variables[98] = 0.0; - variables[99] = 1.204e-6; - variables[100] = 3.7e-7; - variables[101] = 1.2e-6; - variables[102] = 0.621; - variables[103] = 5.64; - variables[104] = 0.04782545; - variables[105] = 0.0478; - variables[106] = 0.0478; - variables[107] = 0.1551936; - variables[108] = 0.16; - variables[109] = 0.16; - states[0] = 0.092361701692; - states[1] = 0.015905380261; - states[2] = 0.01445216109; - states[3] = 0.04804900895; + variables[1] = 0.0; + variables[2] = 1.0; + variables[3] = 1.0309347; + variables[5] = 2.0e-5; + variables[6] = 6.5e-5; + variables[22] = 8314.0; + variables[23] = 310.0; + variables[24] = 96845.0; + variables[26] = 5.8e-5; + variables[27] = 0.000189; + variables[28] = 5.8e-5; + variables[29] = 0.000189; + variables[30] = 5.81818e-5; + variables[31] = 0.0001888; + variables[34] = 2.52e-5; + variables[35] = 8.19e-5; + variables[36] = 2.52e-5; + variables[37] = 8.19e-5; + variables[38] = 2.523636e-5; + variables[39] = 8.1892e-5; + variables[42] = 1.32e-5; + variables[43] = 4.3e-5; + variables[44] = 1.323e-5; + variables[45] = 4.29e-5; + variables[46] = 1.3236e-5; + variables[47] = 4.2952e-5; + variables[50] = 2.7e-6; + variables[51] = 8.8e-6; + variables[52] = 2.8e-6; + variables[53] = 8.8e-6; + variables[54] = 2.7229e-6; + variables[55] = 8.83584e-6; + variables[56] = 8.0; + variables[57] = 0.5; + variables[58] = 2.0; + variables[59] = 140.0; + variables[60] = 0.0001; + variables[61] = 0.0001; + variables[63] = 0.0478; + variables[64] = 0.16; + variables[65] = 0.0478; + variables[66] = 0.16; + variables[67] = 0.04782545; + variables[68] = 0.1551936; + variables[69] = 5.4; + variables[70] = 0.621; + variables[71] = 5.64; + variables[73] = 0.0; + variables[74] = 0.0; + variables[75] = 0.0042; + variables[76] = 0.03339; + variables[77] = 0.0; + variables[78] = 0.0; + variables[79] = 140.0; + variables[82] = 0.0; + variables[83] = 1.2e-6; + variables[84] = 0.0; + variables[85] = 3.7e-7; + variables[86] = 0.0; + variables[87] = 1.204e-6; + variables[97] = 0.0058; + variables[98] = 0.0659; + variables[99] = 0.0082; + variables[100] = 0.0659; + variables[101] = 0.0057938; + variables[102] = 0.06588648; + variables[103] = 46.4; + variables[113] = 0.0043; + variables[114] = 0.0139; + variables[115] = 0.0021; + variables[116] = 0.00694; + variables[117] = 0.00427806; + variables[118] = 0.0138823; + variables[119] = 45.0; + variables[129] = 0.00491; + variables[130] = 0.03649; + variables[131] = 0.004905; + variables[132] = 0.0365; + variables[133] = 0.004905; + variables[134] = 0.036495; + variables[136] = 6.65e-5; + variables[137] = 0.0114; + variables[138] = 0.000266; + variables[139] = 0.0114; + variables[140] = 6.645504e-5; + variables[141] = 0.01138376; + variables[147] = 0.000797; + variables[148] = 0.016; + variables[149] = 0.000738; + variables[150] = 0.0208; + variables[151] = 0.00079704; + variables[152] = 0.016; + variables[161] = 0.000518; + variables[162] = 0.0104; + variables[163] = 0.000345; + variables[164] = 0.0104; + variables[165] = 0.0003445; + variables[166] = 0.0104; + variables[170] = 0.000548; + variables[171] = 0.0069; + variables[172] = 0.000437; + variables[173] = 0.0055; + variables[174] = 0.0005465; + variables[175] = 0.006875; + variables[177] = 0.000548; + variables[178] = 0.0069; + variables[179] = 0.000437; + variables[180] = 0.0055; + variables[181] = 0.0005465; + variables[182] = 0.006875; + states[0] = -39.013558536; + states[1] = 0.092361701692; + states[2] = 0.015905380261; + states[3] = 0.01445216109; states[4] = 0.48779845203; - states[5] = 0.42074047435; + states[5] = 0.04804900895; states[6] = 0.038968420558; - states[7] = 0.29760539675; + states[7] = 0.42074047435; states[8] = 0.064402950262; - states[9] = 0.13034201158; - states[10] = 0.46960956028; - states[11] = 0.87993375273; - states[12] = 0.082293827208; - states[13] = 0.03889291759; - states[14] = -39.013558536; + states[9] = 0.29760539675; + states[10] = 0.87993375273; + states[11] = 0.13034201158; + states[12] = 0.46960956028; + states[13] = 0.082293827208; + states[14] = 0.03889291759; } void computeComputedConstants(double *variables) { - variables[110] = (variables[56] == 0.0)?1.07*(3.0*variables[57]-0.1)/(3.0*(1.0+0.7745*exp(-(3.0*variables[57]-2.05)/0.295))):(variables[56] == 1.0)?variables[53]*variables[57]/(1.0+0.7745*exp(-(3.0*variables[57]-2.05)/0.295)):1.07*29.0*variables[57]/(30.0*(1.0+0.7745*exp(-(29.0*variables[57]-24.5)/1.95))); - variables[111] = variables[50]+variables[110]*(variables[51]-variables[50]); - variables[112] = (variables[56] == 0.0)?variables[84]+variables[110]*(variables[87]-variables[84]):(variables[56] == 1.0)?variables[82]+variables[110]*(variables[85]-variables[82]):variables[83]+variables[110]*(variables[86]-variables[83]); - variables[113] = (variables[56] == 0.0)?variables[66]+variables[110]*(variables[69]-variables[66]):(variables[56] == 1.0)?variables[64]+variables[110]*(variables[67]-variables[64]):variables[65]+variables[110]*(variables[68]-variables[65]); - variables[114] = (variables[56] == 0.0)?variables[16]+variables[110]*(variables[19]-variables[16]):(variables[56] == 1.0)?variables[14]+variables[110]*(variables[17]-variables[14]):variables[15]+variables[110]*(variables[18]-variables[15]); - variables[115] = (variables[56] == 0.0)?variables[92]+variables[110]*(variables[95]-variables[92]):(variables[56] == 1.0)?variables[90]+variables[110]*(variables[93]-variables[90]):variables[91]+variables[110]*(variables[94]-variables[91]); - variables[117] = (variables[56] == 0.0)?variables[106]+variables[110]*(variables[109]-variables[106]):(variables[56] == 1.0)?variables[104]+variables[110]*(variables[107]-variables[104]):variables[105]+variables[110]*(variables[108]-variables[105]); - variables[119] = (variables[56] == 0.0)?variables[60]+variables[110]*(variables[63]-variables[60]):(variables[56] == 1.0)?variables[58]+variables[110]*(variables[61]-variables[58]):variables[59]+variables[110]*(variables[62]-variables[59]); - variables[120] = variables[119]*variables[44]/(variables[44]+0.0004); - variables[121] = variables[54]*variables[55]/variables[52]*log(variables[49]/variables[48]); - variables[122] = variables[54]*variables[55]/variables[52]*log(variables[47]/variables[46]); - variables[123] = variables[54]*variables[55]/(2.0*variables[52])*log(variables[45]/variables[44]); - variables[124] = (variables[56] == 0.0)?variables[54]*variables[55]/variables[52]*log((variables[47]+0.12*variables[49])/(variables[46]+0.12*variables[48])):variables[54]*variables[55]/variables[52]*log((variables[47]+0.03*variables[49])/(variables[46]+0.03*variables[48])); - variables[125] = (variables[56] == 0.0)?variables[98]+variables[110]*(variables[101]-variables[98]):(variables[56] == 1.0)?variables[96]+variables[110]*(variables[99]-variables[96]):variables[97]+variables[110]*(variables[100]-variables[97]); - variables[134] = (variables[56] == 0.0)?variables[3]+variables[110]*(variables[6]-variables[3]):(variables[56] == 1.0)?variables[1]+variables[110]*(variables[4]-variables[1]):variables[2]+variables[110]*(variables[5]-variables[2]); - variables[144] = (variables[56] == 0.0)?variables[10]+variables[110]*(variables[13]-variables[10]):(variables[56] == 1.0)?variables[8]+variables[110]*(variables[11]-variables[8]):variables[9]+variables[110]*(variables[12]-variables[9]); - variables[154] = (variables[56] == 0.0)?variables[28]+variables[110]*(variables[31]-variables[28]):(variables[56] == 1.0)?variables[26]+variables[110]*(variables[29]-variables[26]):variables[27]+variables[110]*(variables[30]-variables[27]); - variables[155] = (variables[56] == 0.0)?variables[22]+variables[110]*(variables[25]-variables[22]):(variables[56] == 1.0)?variables[20]+variables[110]*(variables[23]-variables[20]):variables[21]+variables[110]*(variables[24]-variables[21]); - variables[162] = (variables[56] == 0.0)?variables[72]+variables[110]*(variables[75]-variables[72]):(variables[56] == 1.0)?variables[70]+variables[110]*(variables[73]-variables[70]):variables[71]+variables[110]*(variables[74]-variables[71]); - variables[168] = (variables[56] == 0.0)?0.002:(variables[56] == 1.0)?0.002:0.006; - variables[170] = (variables[56] == 0.0)?variables[78]+variables[110]*(variables[81]-variables[78]):(variables[56] == 1.0)?variables[76]+variables[110]*(variables[79]-variables[76]):variables[77]+variables[110]*(variables[80]-variables[77]); - variables[174] = (variables[56] == 0.0)?variables[40]+variables[110]*(variables[43]-variables[40]):(variables[56] == 1.0)?variables[38]+variables[110]*(variables[41]-variables[38]):variables[39]+variables[110]*(variables[42]-variables[39]); - variables[176] = (variables[56] == 0.0)?variables[34]+variables[110]*(variables[37]-variables[34]):(variables[56] == 1.0)?variables[32]+variables[110]*(variables[35]-variables[32]):variables[33]+variables[110]*(variables[36]-variables[33]); + variables[0] = (variables[2] == 0.0)?1.07*(3.0*variables[1]-0.1)/(3.0*(1.0+0.7745*exp(-(3.0*variables[1]-2.05)/0.295))):(variables[2] == 1.0)?variables[3]*variables[1]/(1.0+0.7745*exp(-(3.0*variables[1]-2.05)/0.295)):1.07*29.0*variables[1]/(30.0*(1.0+0.7745*exp(-(29.0*variables[1]-24.5)/1.95))); + variables[4] = variables[5]+variables[0]*(variables[6]-variables[5]); + variables[25] = (variables[2] == 0.0)?variables[26]+variables[0]*(variables[27]-variables[26]):(variables[2] == 1.0)?variables[30]+variables[0]*(variables[31]-variables[30]):variables[28]+variables[0]*(variables[29]-variables[28]); + variables[33] = (variables[2] == 0.0)?variables[34]+variables[0]*(variables[35]-variables[34]):(variables[2] == 1.0)?variables[38]+variables[0]*(variables[39]-variables[38]):variables[36]+variables[0]*(variables[37]-variables[36]); + variables[41] = (variables[2] == 0.0)?variables[42]+variables[0]*(variables[43]-variables[42]):(variables[2] == 1.0)?variables[46]+variables[0]*(variables[47]-variables[46]):variables[44]+variables[0]*(variables[45]-variables[44]); + variables[49] = (variables[2] == 0.0)?variables[50]+variables[0]*(variables[51]-variables[50]):(variables[2] == 1.0)?variables[54]+variables[0]*(variables[55]-variables[54]):variables[52]+variables[0]*(variables[53]-variables[52]); + variables[62] = (variables[2] == 0.0)?variables[63]+variables[0]*(variables[64]-variables[63]):(variables[2] == 1.0)?variables[67]+variables[0]*(variables[68]-variables[67]):variables[65]+variables[0]*(variables[66]-variables[65]); + variables[72] = (variables[2] == 0.0)?variables[73]+variables[0]*(variables[74]-variables[73]):(variables[2] == 1.0)?variables[77]+variables[0]*(variables[78]-variables[77]):variables[75]+variables[0]*(variables[76]-variables[75]); + variables[8] = variables[72]*variables[60]/(variables[60]+0.0004); + variables[32] = variables[22]*variables[23]/variables[24]*log(variables[59]/variables[56]); + variables[40] = variables[22]*variables[23]/variables[24]*log(variables[69]/variables[79]); + variables[48] = variables[22]*variables[23]/(2.0*variables[24])*log(variables[58]/variables[60]); + variables[80] = (variables[2] == 0.0)?variables[22]*variables[23]/variables[24]*log((variables[69]+0.12*variables[59])/(variables[79]+0.12*variables[56])):variables[22]*variables[23]/variables[24]*log((variables[69]+0.03*variables[59])/(variables[79]+0.03*variables[56])); + variables[81] = (variables[2] == 0.0)?variables[82]+variables[0]*(variables[83]-variables[82]):(variables[2] == 1.0)?variables[86]+variables[0]*(variables[87]-variables[86]):variables[84]+variables[0]*(variables[85]-variables[84]); + variables[96] = (variables[2] == 0.0)?variables[97]+variables[0]*(variables[98]-variables[97]):(variables[2] == 1.0)?variables[101]+variables[0]*(variables[102]-variables[101]):variables[99]+variables[0]*(variables[100]-variables[99]); + variables[112] = (variables[2] == 0.0)?variables[113]+variables[0]*(variables[114]-variables[113]):(variables[2] == 1.0)?variables[117]+variables[0]*(variables[118]-variables[117]):variables[115]+variables[0]*(variables[116]-variables[115]); + variables[128] = (variables[2] == 0.0)?variables[129]+variables[0]*(variables[130]-variables[129]):(variables[2] == 1.0)?variables[133]+variables[0]*(variables[134]-variables[133]):variables[131]+variables[0]*(variables[132]-variables[131]); + variables[135] = (variables[2] == 0.0)?variables[136]+variables[0]*(variables[137]-variables[136]):(variables[2] == 1.0)?variables[140]+variables[0]*(variables[141]-variables[140]):variables[138]+variables[0]*(variables[139]-variables[138]); + variables[146] = (variables[2] == 0.0)?variables[147]+variables[0]*(variables[148]-variables[147]):(variables[2] == 1.0)?variables[151]+variables[0]*(variables[152]-variables[151]):variables[149]+variables[0]*(variables[150]-variables[149]); + variables[158] = (variables[2] == 0.0)?0.002:(variables[2] == 1.0)?0.002:0.006; + variables[160] = (variables[2] == 0.0)?variables[161]+variables[0]*(variables[162]-variables[161]):(variables[2] == 1.0)?variables[165]+variables[0]*(variables[166]-variables[165]):variables[163]+variables[0]*(variables[164]-variables[163]); + variables[169] = (variables[2] == 0.0)?variables[170]+variables[0]*(variables[171]-variables[170]):(variables[2] == 1.0)?variables[174]+variables[0]*(variables[175]-variables[174]):variables[172]+variables[0]*(variables[173]-variables[172]); + variables[176] = (variables[2] == 0.0)?variables[177]+variables[0]*(variables[178]-variables[177]):(variables[2] == 1.0)?variables[181]+variables[0]*(variables[182]-variables[181]):variables[179]+variables[0]*(variables[180]-variables[179]); } void computeRates(double voi, double *states, double *rates, double *variables) { - variables[126] = (variables[56] == 0.0)?pow(1.0/(1.0+exp(-states[14]/5.46)), 1.0/3.0):pow(1.0/(1.0+exp(-(states[14]+30.32)/5.46)), 1.0/3.0); - variables[127] = (variables[56] == 0.0)?0.0006247/(0.832*exp(-0.335*(states[14]+56.7))+0.627*exp(0.082*(states[14]+65.01)))+4.0e-5:0.0006247/(0.8322166*exp(-0.33566*(states[14]+56.7062))+0.6274*exp(0.0823*(states[14]+65.0131)))+4.569e-5; - rates[0] = (variables[126]-states[0])/variables[127]; - variables[130] = 1.0/(1.0+exp((states[14]+66.1)/6.4)); - variables[132] = 3.717e-6*exp(-0.2815*(states[14]+17.11))/(1.0+0.003732*exp(-0.3426*(states[14]+37.76)))+0.0005977; - rates[1] = (variables[130]-states[1])/variables[132]; - variables[131] = variables[130]; - variables[133] = 3.186e-8*exp(-0.6219*(states[14]+18.8))/(1.0+7.189e-5*exp(-0.6683*(states[14]+34.07)))+0.003556; - rates[2] = (variables[131]-states[2])/variables[133]; - variables[139] = (variables[56] == 0.0)?1.0/(1.0+exp(-(states[14]+23.1)/6.0)):(variables[56] == 1.0)?1.0/(1.0+exp(-(states[14]+22.3+0.8*variables[110])/6.0)):1.0/(1.0+exp(-(states[14]+22.2)/6.0)); - variables[136] = (variables[56] == 0.0)?-28.38*(states[14]+35.0)/(exp(-(states[14]+35.0)/2.5)-1.0)-84.9*states[14]/(exp(-0.208*states[14])-1.0):(variables[56] == 1.0)?-28.39*(states[14]+35.0)/(exp(-(states[14]+35.0)/2.5)-1.0)-84.9*states[14]/(exp(-0.208*states[14])-1.0):-28.4*(states[14]+35.0)/(exp(-(states[14]+35.0)/2.5)-1.0)-84.9*states[14]/(exp(-0.208*states[14])-1.0); - variables[137] = (variables[56] == 1.0)?11.43*(states[14]-5.0)/(exp(0.4*(states[14]-5.0))-1.0):11.42*(states[14]-5.0)/(exp(0.4*(states[14]-5.0))-1.0); - variables[138] = 2.0/(variables[136]+variables[137]); - rates[3] = (variables[139]-states[3])/variables[138]; - variables[143] = 1.0/(1.0+exp((states[14]+45.0)/5.0)); - variables[140] = (variables[56] == 1.0)?3.75*(states[14]+28.0)/(exp((states[14]+28.0)/4.0)-1.0):3.12*(states[14]+28.0)/(exp((states[14]+28.0)/4.0)-1.0); - variables[141] = (variables[56] == 1.0)?30.0/(1.0+exp(-(states[14]+28.0)/4.0)):25.0/(1.0+exp(-(states[14]+28.0)/4.0)); - variables[142] = (variables[56] == 1.0)?(1.2-0.2*variables[110])/(variables[140]+variables[141]):1.0/(variables[140]+variables[141]); - rates[4] = (variables[143]-states[4])/variables[142]; - variables[149] = 1.0/(1.0+exp(-(states[14]+37.0)/6.8)); - variables[146] = 1068.0*exp((states[14]+26.3)/30.0); - variables[147] = 1068.0*exp(-(states[14]+26.3)/30.0); - variables[148] = 1.0/(variables[146]+variables[147]); - rates[5] = (variables[149]-states[5])/variables[148]; - variables[153] = 1.0/(1.0+exp((states[14]+71.0)/9.0)); - variables[150] = (variables[56] == 1.0)?15.3*exp(-(states[14]+71.0+0.7*variables[110])/83.3):15.3*exp(-(states[14]+71.7)/83.3); - variables[151] = (variables[56] == 1.0)?15.0*exp((states[14]+71.0)/15.38):15.0*exp((states[14]+71.7)/15.38); - variables[152] = 1.0/(variables[150]+variables[151]); - rates[6] = (variables[153]-states[6])/variables[152]; - variables[158] = 1.0/(1.0+exp((states[14]+59.37)/13.1)); - variables[159] = (variables[56] == 0.0)?0.0101+0.06517/(0.57*exp(-0.08*(states[14]+49.0)))+2.4e-5*exp(0.1*(states[14]+50.93)):(variables[56] == 1.0)?0.001/3.0*(30.31+195.5/(0.5686*exp(-0.08161*(states[14]+39.0+10.0*variables[110]))+0.7174*exp((0.2719-0.1719*variables[110])*1.0*(states[14]+40.93+10.0*variables[110])))):0.0101+0.06517/(0.5686*exp(-0.08161*(states[14]+39.0))+0.7174*exp(0.2719*(states[14]+40.93))); - rates[7] = (variables[158]-states[7])/variables[159]; - variables[160] = 1.0/(1.0+exp(-(states[14]-10.93)/19.7)); - variables[161] = (variables[56] == 0.0)?0.001*(2.98+15.59/(1.037*exp(0.09*(states[14]+30.61))+0.369*exp(-0.12*(states[14]+23.84)))):(variables[56] == 1.0)?0.0025*(1.191+7.838/(1.037*exp(0.09012*(states[14]+30.61))+0.369*exp(-0.119*(states[14]+23.84)))):0.001*(2.98+19.59/(1.037*exp(0.09012*(states[14]+30.61))+0.369*exp(-0.119*(states[14]+23.84)))); - rates[8] = (variables[160]-states[8])/variables[161]; - variables[164] = (variables[56] != 2.0)?1.0/(1.0+exp(-(states[14]+14.2)/10.6)):1.0/(1.0+exp(-(states[14]+13.2)/10.6)); - variables[165] = (variables[56] != 2.0)?1.0/(37.2*exp((states[14]-9.0)/15.9)+0.96*exp(-(states[14]-9.0)/22.5)):1.0/(37.2*exp((states[14]-10.0)/15.9)+0.96*exp(-(states[14]-10.0)/22.5)); - rates[9] = (variables[164]-states[9])/variables[165]; - variables[166] = variables[164]; - variables[167] = (variables[56] != 2.0)?1.0/(4.2*exp((states[14]-9.0)/17.0)+0.15*exp(-(states[14]-9.0)/21.6)):1.0/(4.2*exp((states[14]-10.0)/17.0)+0.15*exp(-(states[14]-10.0)/21.6)); - rates[10] = (variables[166]-states[10])/variables[167]; - variables[169] = 1.0/(1.0+exp((states[14]+18.6)/10.1)); - rates[11] = (variables[169]-states[11])/variables[168]; - variables[172] = 14.0/(1.0+exp(-(states[14]-40.0)/9.0)); - variables[173] = 1.0*exp(-states[14]/45.0); - rates[12] = variables[172]*(1.0-states[12])-variables[173]*states[12]; - variables[178] = (variables[56] == 0.0)?1.0*exp(-(states[14]+78.91)/26.62):1.0*exp(-(states[14]+78.91)/26.63); - variables[179] = 1.0*exp((states[14]+75.13)/21.25); - rates[13] = variables[178]*(1.0-states[13])-variables[179]*states[13]; - variables[118] = variables[117]*pow(variables[48]/(variables[103]+variables[48]), 3.0)*pow(variables[47]/(variables[102]+variables[47]), 2.0)*1.6/(1.5+exp(-(states[14]+60.0)/40.0)); - variables[116] = (variables[56] == 0.0)?variables[115]*(pow(variables[48], 3.0)*variables[45]*exp(0.03743*states[14]*variables[89])-pow(variables[49], 3.0)*variables[44]*exp(0.0374*states[14]*(variables[89]-1.0)))/(1.0+variables[88]*(variables[44]*pow(variables[49], 3.0)+variables[45]*pow(variables[48], 3.0))):variables[115]*(pow(variables[48], 3.0)*variables[45]*exp(0.03743*states[14]*variables[89])-pow(variables[49], 3.0)*variables[44]*exp(0.03743*states[14]*(variables[89]-1.0)))/(1.0+variables[88]*(variables[44]*pow(variables[49], 3.0)+variables[45]*pow(variables[48], 3.0))); - variables[177] = (variables[56] != 2.0)?variables[176]*states[13]*(states[14]-variables[122]):variables[176]*states[13]*(states[14]+102.0); - variables[175] = (variables[56] != 2.0)?variables[174]*states[13]*(states[14]-variables[121]):variables[174]*states[13]*(states[14]-77.6); - variables[171] = variables[170]*pow(states[12], 2.0)*(states[14]-variables[124]); - variables[157] = variables[155]*states[8]*(states[14]-variables[122]); - variables[156] = variables[154]*states[7]*states[8]*(states[14]-variables[122]); - variables[145] = variables[144]*states[5]*states[6]*(states[14]-variables[7]); - variables[135] = variables[134]*(states[4]*states[3]+0.006/(1.0+exp(-(states[14]+14.1)/6.0)))*(states[14]-variables[0]); - variables[128] = (variables[56] == 0.0)?0.0952*exp(-0.063*(states[14]+34.4))/(1.0+1.66*exp(-0.225*(states[14]+63.7)))+0.0869:0.09518*exp(-0.06306*(states[14]+34.4))/(1.0+1.662*exp(-0.2251*(states[14]+63.7)))+0.08693; - variables[129] = (1.0-variables[128])*states[1]+variables[128]*states[2]; - variables[183] = variables[125]*pow(states[0], 3.0)*variables[129]*variables[49]*pow(variables[52], 2.0)/(variables[54]*variables[55])*(exp((states[14]-variables[121])*variables[52]/(variables[54]*variables[55]))-1.0)/(exp(states[14]*variables[52]/(variables[54]*variables[55]))-1.0)*states[14]; - variables[181] = variables[113]*(states[14]-variables[122]); - variables[182] = variables[114]*(states[14]-variables[123]); - variables[180] = variables[112]*(states[14]-variables[121]); - variables[163] = 0.6*states[9]+0.4*states[10]; - variables[184] = variables[162]*variables[163]*states[11]*(states[14]-variables[122]); - rates[14] = -1.0/variables[111]*(variables[183]+variables[135]+variables[145]+variables[156]+variables[157]+variables[184]+variables[171]+variables[175]+variables[177]+variables[180]+variables[182]+variables[181]+variables[116]+variables[118]+variables[120]); + variables[9] = variables[62]*pow(variables[56]/(variables[71]+variables[56]), 3.0)*pow(variables[69]/(variables[70]+variables[69]), 2.0)*1.6/(1.5+exp(-(states[0]+60.0)/40.0)); + variables[10] = (variables[2] == 0.0)?variables[49]*(pow(variables[56], 3.0)*variables[58]*exp(0.03743*states[0]*variables[57])-pow(variables[59], 3.0)*variables[60]*exp(0.0374*states[0]*(variables[57]-1.0)))/(1.0+variables[61]*(variables[60]*pow(variables[59], 3.0)+variables[58]*pow(variables[56], 3.0))):variables[49]*(pow(variables[56], 3.0)*variables[58]*exp(0.03743*states[0]*variables[57])-pow(variables[59], 3.0)*variables[60]*exp(0.03743*states[0]*(variables[57]-1.0)))/(1.0+variables[61]*(variables[60]*pow(variables[59], 3.0)+variables[58]*pow(variables[56], 3.0))); + variables[14] = (variables[2] != 2.0)?variables[176]*states[14]*(states[0]-variables[40]):variables[176]*states[14]*(states[0]+102.0); + variables[15] = (variables[2] != 2.0)?variables[169]*states[14]*(states[0]-variables[32]):variables[169]*states[14]*(states[0]-77.6); + variables[16] = variables[160]*pow(states[13], 2.0)*(states[0]-variables[80]); + variables[18] = variables[135]*states[8]*(states[0]-variables[40]); + variables[19] = variables[128]*states[9]*states[8]*(states[0]-variables[40]); + variables[20] = variables[112]*states[7]*states[6]*(states[0]-variables[119]); + variables[21] = variables[96]*(states[4]*states[5]+0.006/(1.0+exp(-(states[0]+14.1)/6.0)))*(states[0]-variables[103]); + variables[91] = (variables[2] == 0.0)?0.0952*exp(-0.063*(states[0]+34.4))/(1.0+1.66*exp(-0.225*(states[0]+63.7)))+0.0869:0.09518*exp(-0.06306*(states[0]+34.4))/(1.0+1.662*exp(-0.2251*(states[0]+63.7)))+0.08693; + variables[88] = (1.0-variables[91])*states[2]+variables[91]*states[3]; + variables[7] = variables[81]*pow(states[1], 3.0)*variables[88]*variables[59]*pow(variables[24], 2.0)/(variables[22]*variables[23])*(exp((states[0]-variables[32])*variables[24]/(variables[22]*variables[23]))-1.0)/(exp(states[0]*variables[24]/(variables[22]*variables[23]))-1.0)*states[0]; + variables[11] = variables[33]*(states[0]-variables[40]); + variables[12] = variables[41]*(states[0]-variables[48]); + variables[13] = variables[25]*(states[0]-variables[32]); + variables[153] = 0.6*states[11]+0.4*states[12]; + variables[17] = variables[146]*variables[153]*states[10]*(states[0]-variables[40]); + rates[0] = -1.0/variables[4]*(variables[7]+variables[21]+variables[20]+variables[19]+variables[18]+variables[17]+variables[16]+variables[15]+variables[14]+variables[13]+variables[12]+variables[11]+variables[10]+variables[9]+variables[8]); + variables[89] = (variables[2] == 0.0)?pow(1.0/(1.0+exp(-states[0]/5.46)), 1.0/3.0):pow(1.0/(1.0+exp(-(states[0]+30.32)/5.46)), 1.0/3.0); + variables[90] = (variables[2] == 0.0)?0.0006247/(0.832*exp(-0.335*(states[0]+56.7))+0.627*exp(0.082*(states[0]+65.01)))+4.0e-5:0.0006247/(0.8322166*exp(-0.33566*(states[0]+56.7062))+0.6274*exp(0.0823*(states[0]+65.0131)))+4.569e-5; + rates[1] = (variables[89]-states[1])/variables[90]; + variables[92] = 1.0/(1.0+exp((states[0]+66.1)/6.4)); + variables[93] = 3.717e-6*exp(-0.2815*(states[0]+17.11))/(1.0+0.003732*exp(-0.3426*(states[0]+37.76)))+0.0005977; + rates[2] = (variables[92]-states[2])/variables[93]; + variables[94] = variables[92]; + variables[95] = 3.186e-8*exp(-0.6219*(states[0]+18.8))/(1.0+7.189e-5*exp(-0.6683*(states[0]+34.07)))+0.003556; + rates[3] = (variables[94]-states[3])/variables[95]; + variables[104] = (variables[2] == 0.0)?1.0/(1.0+exp(-(states[0]+23.1)/6.0)):(variables[2] == 1.0)?1.0/(1.0+exp(-(states[0]+22.3+0.8*variables[0])/6.0)):1.0/(1.0+exp(-(states[0]+22.2)/6.0)); + variables[106] = (variables[2] == 0.0)?-28.38*(states[0]+35.0)/(exp(-(states[0]+35.0)/2.5)-1.0)-84.9*states[0]/(exp(-0.208*states[0])-1.0):(variables[2] == 1.0)?-28.39*(states[0]+35.0)/(exp(-(states[0]+35.0)/2.5)-1.0)-84.9*states[0]/(exp(-0.208*states[0])-1.0):-28.4*(states[0]+35.0)/(exp(-(states[0]+35.0)/2.5)-1.0)-84.9*states[0]/(exp(-0.208*states[0])-1.0); + variables[107] = (variables[2] == 1.0)?11.43*(states[0]-5.0)/(exp(0.4*(states[0]-5.0))-1.0):11.42*(states[0]-5.0)/(exp(0.4*(states[0]-5.0))-1.0); + variables[105] = 2.0/(variables[106]+variables[107]); + rates[5] = (variables[104]-states[5])/variables[105]; + variables[108] = 1.0/(1.0+exp((states[0]+45.0)/5.0)); + variables[110] = (variables[2] == 1.0)?3.75*(states[0]+28.0)/(exp((states[0]+28.0)/4.0)-1.0):3.12*(states[0]+28.0)/(exp((states[0]+28.0)/4.0)-1.0); + variables[111] = (variables[2] == 1.0)?30.0/(1.0+exp(-(states[0]+28.0)/4.0)):25.0/(1.0+exp(-(states[0]+28.0)/4.0)); + variables[109] = (variables[2] == 1.0)?(1.2-0.2*variables[0])/(variables[110]+variables[111]):1.0/(variables[110]+variables[111]); + rates[4] = (variables[108]-states[4])/variables[109]; + variables[120] = 1.0/(1.0+exp(-(states[0]+37.0)/6.8)); + variables[122] = 1068.0*exp((states[0]+26.3)/30.0); + variables[123] = 1068.0*exp(-(states[0]+26.3)/30.0); + variables[121] = 1.0/(variables[122]+variables[123]); + rates[7] = (variables[120]-states[7])/variables[121]; + variables[124] = 1.0/(1.0+exp((states[0]+71.0)/9.0)); + variables[126] = (variables[2] == 1.0)?15.3*exp(-(states[0]+71.0+0.7*variables[0])/83.3):15.3*exp(-(states[0]+71.7)/83.3); + variables[127] = (variables[2] == 1.0)?15.0*exp((states[0]+71.0)/15.38):15.0*exp((states[0]+71.7)/15.38); + variables[125] = 1.0/(variables[126]+variables[127]); + rates[6] = (variables[124]-states[6])/variables[125]; + variables[142] = 1.0/(1.0+exp((states[0]+59.37)/13.1)); + variables[143] = (variables[2] == 0.0)?0.0101+0.06517/(0.57*exp(-0.08*(states[0]+49.0)))+2.4e-5*exp(0.1*(states[0]+50.93)):(variables[2] == 1.0)?0.001/3.0*(30.31+195.5/(0.5686*exp(-0.08161*(states[0]+39.0+10.0*variables[0]))+0.7174*exp((0.2719-0.1719*variables[0])*1.0*(states[0]+40.93+10.0*variables[0])))):0.0101+0.06517/(0.5686*exp(-0.08161*(states[0]+39.0))+0.7174*exp(0.2719*(states[0]+40.93))); + rates[9] = (variables[142]-states[9])/variables[143]; + variables[144] = 1.0/(1.0+exp(-(states[0]-10.93)/19.7)); + variables[145] = (variables[2] == 0.0)?0.001*(2.98+15.59/(1.037*exp(0.09*(states[0]+30.61))+0.369*exp(-0.12*(states[0]+23.84)))):(variables[2] == 1.0)?0.0025*(1.191+7.838/(1.037*exp(0.09012*(states[0]+30.61))+0.369*exp(-0.119*(states[0]+23.84)))):0.001*(2.98+19.59/(1.037*exp(0.09012*(states[0]+30.61))+0.369*exp(-0.119*(states[0]+23.84)))); + rates[8] = (variables[144]-states[8])/variables[145]; + variables[154] = (variables[2] != 2.0)?1.0/(1.0+exp(-(states[0]+14.2)/10.6)):1.0/(1.0+exp(-(states[0]+13.2)/10.6)); + variables[155] = (variables[2] != 2.0)?1.0/(37.2*exp((states[0]-9.0)/15.9)+0.96*exp(-(states[0]-9.0)/22.5)):1.0/(37.2*exp((states[0]-10.0)/15.9)+0.96*exp(-(states[0]-10.0)/22.5)); + rates[11] = (variables[154]-states[11])/variables[155]; + variables[156] = variables[154]; + variables[157] = (variables[2] != 2.0)?1.0/(4.2*exp((states[0]-9.0)/17.0)+0.15*exp(-(states[0]-9.0)/21.6)):1.0/(4.2*exp((states[0]-10.0)/17.0)+0.15*exp(-(states[0]-10.0)/21.6)); + rates[12] = (variables[156]-states[12])/variables[157]; + variables[159] = 1.0/(1.0+exp((states[0]+18.6)/10.1)); + rates[10] = (variables[159]-states[10])/variables[158]; + variables[167] = 14.0/(1.0+exp(-(states[0]-40.0)/9.0)); + variables[168] = 1.0*exp(-states[0]/45.0); + rates[13] = variables[167]*(1.0-states[13])-variables[168]*states[13]; + variables[183] = (variables[2] == 0.0)?1.0*exp(-(states[0]+78.91)/26.62):1.0*exp(-(states[0]+78.91)/26.63); + variables[184] = 1.0*exp((states[0]+75.13)/21.25); + rates[14] = variables[183]*(1.0-states[14])-variables[184]*states[14]; } void computeVariables(double voi, double *states, double *rates, double *variables) { - variables[116] = (variables[56] == 0.0)?variables[115]*(pow(variables[48], 3.0)*variables[45]*exp(0.03743*states[14]*variables[89])-pow(variables[49], 3.0)*variables[44]*exp(0.0374*states[14]*(variables[89]-1.0)))/(1.0+variables[88]*(variables[44]*pow(variables[49], 3.0)+variables[45]*pow(variables[48], 3.0))):variables[115]*(pow(variables[48], 3.0)*variables[45]*exp(0.03743*states[14]*variables[89])-pow(variables[49], 3.0)*variables[44]*exp(0.03743*states[14]*(variables[89]-1.0)))/(1.0+variables[88]*(variables[44]*pow(variables[49], 3.0)+variables[45]*pow(variables[48], 3.0))); - variables[118] = variables[117]*pow(variables[48]/(variables[103]+variables[48]), 3.0)*pow(variables[47]/(variables[102]+variables[47]), 2.0)*1.6/(1.5+exp(-(states[14]+60.0)/40.0)); - variables[126] = (variables[56] == 0.0)?pow(1.0/(1.0+exp(-states[14]/5.46)), 1.0/3.0):pow(1.0/(1.0+exp(-(states[14]+30.32)/5.46)), 1.0/3.0); - variables[127] = (variables[56] == 0.0)?0.0006247/(0.832*exp(-0.335*(states[14]+56.7))+0.627*exp(0.082*(states[14]+65.01)))+4.0e-5:0.0006247/(0.8322166*exp(-0.33566*(states[14]+56.7062))+0.6274*exp(0.0823*(states[14]+65.0131)))+4.569e-5; - variables[128] = (variables[56] == 0.0)?0.0952*exp(-0.063*(states[14]+34.4))/(1.0+1.66*exp(-0.225*(states[14]+63.7)))+0.0869:0.09518*exp(-0.06306*(states[14]+34.4))/(1.0+1.662*exp(-0.2251*(states[14]+63.7)))+0.08693; - variables[129] = (1.0-variables[128])*states[1]+variables[128]*states[2]; - variables[130] = 1.0/(1.0+exp((states[14]+66.1)/6.4)); - variables[131] = variables[130]; - variables[132] = 3.717e-6*exp(-0.2815*(states[14]+17.11))/(1.0+0.003732*exp(-0.3426*(states[14]+37.76)))+0.0005977; - variables[133] = 3.186e-8*exp(-0.6219*(states[14]+18.8))/(1.0+7.189e-5*exp(-0.6683*(states[14]+34.07)))+0.003556; - variables[135] = variables[134]*(states[4]*states[3]+0.006/(1.0+exp(-(states[14]+14.1)/6.0)))*(states[14]-variables[0]); - variables[136] = (variables[56] == 0.0)?-28.38*(states[14]+35.0)/(exp(-(states[14]+35.0)/2.5)-1.0)-84.9*states[14]/(exp(-0.208*states[14])-1.0):(variables[56] == 1.0)?-28.39*(states[14]+35.0)/(exp(-(states[14]+35.0)/2.5)-1.0)-84.9*states[14]/(exp(-0.208*states[14])-1.0):-28.4*(states[14]+35.0)/(exp(-(states[14]+35.0)/2.5)-1.0)-84.9*states[14]/(exp(-0.208*states[14])-1.0); - variables[137] = (variables[56] == 1.0)?11.43*(states[14]-5.0)/(exp(0.4*(states[14]-5.0))-1.0):11.42*(states[14]-5.0)/(exp(0.4*(states[14]-5.0))-1.0); - variables[138] = 2.0/(variables[136]+variables[137]); - variables[139] = (variables[56] == 0.0)?1.0/(1.0+exp(-(states[14]+23.1)/6.0)):(variables[56] == 1.0)?1.0/(1.0+exp(-(states[14]+22.3+0.8*variables[110])/6.0)):1.0/(1.0+exp(-(states[14]+22.2)/6.0)); - variables[140] = (variables[56] == 1.0)?3.75*(states[14]+28.0)/(exp((states[14]+28.0)/4.0)-1.0):3.12*(states[14]+28.0)/(exp((states[14]+28.0)/4.0)-1.0); - variables[141] = (variables[56] == 1.0)?30.0/(1.0+exp(-(states[14]+28.0)/4.0)):25.0/(1.0+exp(-(states[14]+28.0)/4.0)); - variables[142] = (variables[56] == 1.0)?(1.2-0.2*variables[110])/(variables[140]+variables[141]):1.0/(variables[140]+variables[141]); - variables[143] = 1.0/(1.0+exp((states[14]+45.0)/5.0)); - variables[145] = variables[144]*states[5]*states[6]*(states[14]-variables[7]); - variables[146] = 1068.0*exp((states[14]+26.3)/30.0); - variables[147] = 1068.0*exp(-(states[14]+26.3)/30.0); - variables[148] = 1.0/(variables[146]+variables[147]); - variables[149] = 1.0/(1.0+exp(-(states[14]+37.0)/6.8)); - variables[150] = (variables[56] == 1.0)?15.3*exp(-(states[14]+71.0+0.7*variables[110])/83.3):15.3*exp(-(states[14]+71.7)/83.3); - variables[151] = (variables[56] == 1.0)?15.0*exp((states[14]+71.0)/15.38):15.0*exp((states[14]+71.7)/15.38); - variables[152] = 1.0/(variables[150]+variables[151]); - variables[153] = 1.0/(1.0+exp((states[14]+71.0)/9.0)); - variables[156] = variables[154]*states[7]*states[8]*(states[14]-variables[122]); - variables[157] = variables[155]*states[8]*(states[14]-variables[122]); - variables[158] = 1.0/(1.0+exp((states[14]+59.37)/13.1)); - variables[159] = (variables[56] == 0.0)?0.0101+0.06517/(0.57*exp(-0.08*(states[14]+49.0)))+2.4e-5*exp(0.1*(states[14]+50.93)):(variables[56] == 1.0)?0.001/3.0*(30.31+195.5/(0.5686*exp(-0.08161*(states[14]+39.0+10.0*variables[110]))+0.7174*exp((0.2719-0.1719*variables[110])*1.0*(states[14]+40.93+10.0*variables[110])))):0.0101+0.06517/(0.5686*exp(-0.08161*(states[14]+39.0))+0.7174*exp(0.2719*(states[14]+40.93))); - variables[160] = 1.0/(1.0+exp(-(states[14]-10.93)/19.7)); - variables[161] = (variables[56] == 0.0)?0.001*(2.98+15.59/(1.037*exp(0.09*(states[14]+30.61))+0.369*exp(-0.12*(states[14]+23.84)))):(variables[56] == 1.0)?0.0025*(1.191+7.838/(1.037*exp(0.09012*(states[14]+30.61))+0.369*exp(-0.119*(states[14]+23.84)))):0.001*(2.98+19.59/(1.037*exp(0.09012*(states[14]+30.61))+0.369*exp(-0.119*(states[14]+23.84)))); - variables[163] = 0.6*states[9]+0.4*states[10]; - variables[164] = (variables[56] != 2.0)?1.0/(1.0+exp(-(states[14]+14.2)/10.6)):1.0/(1.0+exp(-(states[14]+13.2)/10.6)); - variables[165] = (variables[56] != 2.0)?1.0/(37.2*exp((states[14]-9.0)/15.9)+0.96*exp(-(states[14]-9.0)/22.5)):1.0/(37.2*exp((states[14]-10.0)/15.9)+0.96*exp(-(states[14]-10.0)/22.5)); - variables[166] = variables[164]; - variables[167] = (variables[56] != 2.0)?1.0/(4.2*exp((states[14]-9.0)/17.0)+0.15*exp(-(states[14]-9.0)/21.6)):1.0/(4.2*exp((states[14]-10.0)/17.0)+0.15*exp(-(states[14]-10.0)/21.6)); - variables[169] = 1.0/(1.0+exp((states[14]+18.6)/10.1)); - variables[171] = variables[170]*pow(states[12], 2.0)*(states[14]-variables[124]); - variables[172] = 14.0/(1.0+exp(-(states[14]-40.0)/9.0)); - variables[173] = 1.0*exp(-states[14]/45.0); - variables[175] = (variables[56] != 2.0)?variables[174]*states[13]*(states[14]-variables[121]):variables[174]*states[13]*(states[14]-77.6); - variables[177] = (variables[56] != 2.0)?variables[176]*states[13]*(states[14]-variables[122]):variables[176]*states[13]*(states[14]+102.0); - variables[178] = (variables[56] == 0.0)?1.0*exp(-(states[14]+78.91)/26.62):1.0*exp(-(states[14]+78.91)/26.63); - variables[179] = 1.0*exp((states[14]+75.13)/21.25); - variables[180] = variables[112]*(states[14]-variables[121]); - variables[181] = variables[113]*(states[14]-variables[122]); - variables[182] = variables[114]*(states[14]-variables[123]); - variables[183] = variables[125]*pow(states[0], 3.0)*variables[129]*variables[49]*pow(variables[52], 2.0)/(variables[54]*variables[55])*(exp((states[14]-variables[121])*variables[52]/(variables[54]*variables[55]))-1.0)/(exp(states[14]*variables[52]/(variables[54]*variables[55]))-1.0)*states[14]; - variables[184] = variables[162]*variables[163]*states[11]*(states[14]-variables[122]); + variables[13] = variables[25]*(states[0]-variables[32]); + variables[11] = variables[33]*(states[0]-variables[40]); + variables[12] = variables[41]*(states[0]-variables[48]); + variables[10] = (variables[2] == 0.0)?variables[49]*(pow(variables[56], 3.0)*variables[58]*exp(0.03743*states[0]*variables[57])-pow(variables[59], 3.0)*variables[60]*exp(0.0374*states[0]*(variables[57]-1.0)))/(1.0+variables[61]*(variables[60]*pow(variables[59], 3.0)+variables[58]*pow(variables[56], 3.0))):variables[49]*(pow(variables[56], 3.0)*variables[58]*exp(0.03743*states[0]*variables[57])-pow(variables[59], 3.0)*variables[60]*exp(0.03743*states[0]*(variables[57]-1.0)))/(1.0+variables[61]*(variables[60]*pow(variables[59], 3.0)+variables[58]*pow(variables[56], 3.0))); + variables[9] = variables[62]*pow(variables[56]/(variables[71]+variables[56]), 3.0)*pow(variables[69]/(variables[70]+variables[69]), 2.0)*1.6/(1.5+exp(-(states[0]+60.0)/40.0)); + variables[91] = (variables[2] == 0.0)?0.0952*exp(-0.063*(states[0]+34.4))/(1.0+1.66*exp(-0.225*(states[0]+63.7)))+0.0869:0.09518*exp(-0.06306*(states[0]+34.4))/(1.0+1.662*exp(-0.2251*(states[0]+63.7)))+0.08693; + variables[88] = (1.0-variables[91])*states[2]+variables[91]*states[3]; + variables[7] = variables[81]*pow(states[1], 3.0)*variables[88]*variables[59]*pow(variables[24], 2.0)/(variables[22]*variables[23])*(exp((states[0]-variables[32])*variables[24]/(variables[22]*variables[23]))-1.0)/(exp(states[0]*variables[24]/(variables[22]*variables[23]))-1.0)*states[0]; + variables[89] = (variables[2] == 0.0)?pow(1.0/(1.0+exp(-states[0]/5.46)), 1.0/3.0):pow(1.0/(1.0+exp(-(states[0]+30.32)/5.46)), 1.0/3.0); + variables[90] = (variables[2] == 0.0)?0.0006247/(0.832*exp(-0.335*(states[0]+56.7))+0.627*exp(0.082*(states[0]+65.01)))+4.0e-5:0.0006247/(0.8322166*exp(-0.33566*(states[0]+56.7062))+0.6274*exp(0.0823*(states[0]+65.0131)))+4.569e-5; + variables[92] = 1.0/(1.0+exp((states[0]+66.1)/6.4)); + variables[94] = variables[92]; + variables[93] = 3.717e-6*exp(-0.2815*(states[0]+17.11))/(1.0+0.003732*exp(-0.3426*(states[0]+37.76)))+0.0005977; + variables[95] = 3.186e-8*exp(-0.6219*(states[0]+18.8))/(1.0+7.189e-5*exp(-0.6683*(states[0]+34.07)))+0.003556; + variables[21] = variables[96]*(states[4]*states[5]+0.006/(1.0+exp(-(states[0]+14.1)/6.0)))*(states[0]-variables[103]); + variables[106] = (variables[2] == 0.0)?-28.38*(states[0]+35.0)/(exp(-(states[0]+35.0)/2.5)-1.0)-84.9*states[0]/(exp(-0.208*states[0])-1.0):(variables[2] == 1.0)?-28.39*(states[0]+35.0)/(exp(-(states[0]+35.0)/2.5)-1.0)-84.9*states[0]/(exp(-0.208*states[0])-1.0):-28.4*(states[0]+35.0)/(exp(-(states[0]+35.0)/2.5)-1.0)-84.9*states[0]/(exp(-0.208*states[0])-1.0); + variables[107] = (variables[2] == 1.0)?11.43*(states[0]-5.0)/(exp(0.4*(states[0]-5.0))-1.0):11.42*(states[0]-5.0)/(exp(0.4*(states[0]-5.0))-1.0); + variables[105] = 2.0/(variables[106]+variables[107]); + variables[104] = (variables[2] == 0.0)?1.0/(1.0+exp(-(states[0]+23.1)/6.0)):(variables[2] == 1.0)?1.0/(1.0+exp(-(states[0]+22.3+0.8*variables[0])/6.0)):1.0/(1.0+exp(-(states[0]+22.2)/6.0)); + variables[110] = (variables[2] == 1.0)?3.75*(states[0]+28.0)/(exp((states[0]+28.0)/4.0)-1.0):3.12*(states[0]+28.0)/(exp((states[0]+28.0)/4.0)-1.0); + variables[111] = (variables[2] == 1.0)?30.0/(1.0+exp(-(states[0]+28.0)/4.0)):25.0/(1.0+exp(-(states[0]+28.0)/4.0)); + variables[109] = (variables[2] == 1.0)?(1.2-0.2*variables[0])/(variables[110]+variables[111]):1.0/(variables[110]+variables[111]); + variables[108] = 1.0/(1.0+exp((states[0]+45.0)/5.0)); + variables[20] = variables[112]*states[7]*states[6]*(states[0]-variables[119]); + variables[122] = 1068.0*exp((states[0]+26.3)/30.0); + variables[123] = 1068.0*exp(-(states[0]+26.3)/30.0); + variables[121] = 1.0/(variables[122]+variables[123]); + variables[120] = 1.0/(1.0+exp(-(states[0]+37.0)/6.8)); + variables[126] = (variables[2] == 1.0)?15.3*exp(-(states[0]+71.0+0.7*variables[0])/83.3):15.3*exp(-(states[0]+71.7)/83.3); + variables[127] = (variables[2] == 1.0)?15.0*exp((states[0]+71.0)/15.38):15.0*exp((states[0]+71.7)/15.38); + variables[125] = 1.0/(variables[126]+variables[127]); + variables[124] = 1.0/(1.0+exp((states[0]+71.0)/9.0)); + variables[19] = variables[128]*states[9]*states[8]*(states[0]-variables[40]); + variables[18] = variables[135]*states[8]*(states[0]-variables[40]); + variables[142] = 1.0/(1.0+exp((states[0]+59.37)/13.1)); + variables[143] = (variables[2] == 0.0)?0.0101+0.06517/(0.57*exp(-0.08*(states[0]+49.0)))+2.4e-5*exp(0.1*(states[0]+50.93)):(variables[2] == 1.0)?0.001/3.0*(30.31+195.5/(0.5686*exp(-0.08161*(states[0]+39.0+10.0*variables[0]))+0.7174*exp((0.2719-0.1719*variables[0])*1.0*(states[0]+40.93+10.0*variables[0])))):0.0101+0.06517/(0.5686*exp(-0.08161*(states[0]+39.0))+0.7174*exp(0.2719*(states[0]+40.93))); + variables[144] = 1.0/(1.0+exp(-(states[0]-10.93)/19.7)); + variables[145] = (variables[2] == 0.0)?0.001*(2.98+15.59/(1.037*exp(0.09*(states[0]+30.61))+0.369*exp(-0.12*(states[0]+23.84)))):(variables[2] == 1.0)?0.0025*(1.191+7.838/(1.037*exp(0.09012*(states[0]+30.61))+0.369*exp(-0.119*(states[0]+23.84)))):0.001*(2.98+19.59/(1.037*exp(0.09012*(states[0]+30.61))+0.369*exp(-0.119*(states[0]+23.84)))); + variables[153] = 0.6*states[11]+0.4*states[12]; + variables[17] = variables[146]*variables[153]*states[10]*(states[0]-variables[40]); + variables[154] = (variables[2] != 2.0)?1.0/(1.0+exp(-(states[0]+14.2)/10.6)):1.0/(1.0+exp(-(states[0]+13.2)/10.6)); + variables[155] = (variables[2] != 2.0)?1.0/(37.2*exp((states[0]-9.0)/15.9)+0.96*exp(-(states[0]-9.0)/22.5)):1.0/(37.2*exp((states[0]-10.0)/15.9)+0.96*exp(-(states[0]-10.0)/22.5)); + variables[156] = variables[154]; + variables[157] = (variables[2] != 2.0)?1.0/(4.2*exp((states[0]-9.0)/17.0)+0.15*exp(-(states[0]-9.0)/21.6)):1.0/(4.2*exp((states[0]-10.0)/17.0)+0.15*exp(-(states[0]-10.0)/21.6)); + variables[159] = 1.0/(1.0+exp((states[0]+18.6)/10.1)); + variables[16] = variables[160]*pow(states[13], 2.0)*(states[0]-variables[80]); + variables[167] = 14.0/(1.0+exp(-(states[0]-40.0)/9.0)); + variables[168] = 1.0*exp(-states[0]/45.0); + variables[15] = (variables[2] != 2.0)?variables[169]*states[14]*(states[0]-variables[32]):variables[169]*states[14]*(states[0]-77.6); + variables[14] = (variables[2] != 2.0)?variables[176]*states[14]*(states[0]-variables[40]):variables[176]*states[14]*(states[0]+102.0); + variables[183] = (variables[2] == 0.0)?1.0*exp(-(states[0]+78.91)/26.62):1.0*exp(-(states[0]+78.91)/26.63); + variables[184] = 1.0*exp((states[0]+75.13)/21.25); } diff --git a/tests/resources/generator/garny_kohl_hunter_boyett_noble_rabbit_san_model_2003/model.h b/tests/resources/generator/garny_kohl_hunter_boyett_noble_rabbit_san_model_2003/model.h index aef68921f..c5d5585fa 100644 --- a/tests/resources/generator/garny_kohl_hunter_boyett_noble_rabbit_san_model_2003/model.h +++ b/tests/resources/generator/garny_kohl_hunter_boyett_noble_rabbit_san_model_2003/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/garny_kohl_hunter_boyett_noble_rabbit_san_model_2003/model.py b/tests/resources/generator/garny_kohl_hunter_boyett_noble_rabbit_san_model_2003/model.py index 58a14a6a4..ae48f667d 100644 --- a/tests/resources/generator/garny_kohl_hunter_boyett_noble_rabbit_san_model_2003/model.py +++ b/tests/resources/generator/garny_kohl_hunter_boyett_noble_rabbit_san_model_2003/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 15 VARIABLE_COUNT = 185 @@ -22,187 +22,177 @@ class VariableType(Enum): VOI_INFO = {"name": "time", "units": "second", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} STATE_INFO = [ + {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE}, {"name": "m", "units": "dimensionless", "component": "sodium_current_m_gate", "type": VariableType.STATE}, {"name": "h1", "units": "dimensionless", "component": "sodium_current_h_gate", "type": VariableType.STATE}, {"name": "h2", "units": "dimensionless", "component": "sodium_current_h_gate", "type": VariableType.STATE}, - {"name": "d_L", "units": "dimensionless", "component": "L_type_Ca_channel_d_gate", "type": VariableType.STATE}, {"name": "f_L", "units": "dimensionless", "component": "L_type_Ca_channel_f_gate", "type": VariableType.STATE}, - {"name": "d_T", "units": "dimensionless", "component": "T_type_Ca_channel_d_gate", "type": VariableType.STATE}, + {"name": "d_L", "units": "dimensionless", "component": "L_type_Ca_channel_d_gate", "type": VariableType.STATE}, {"name": "f_T", "units": "dimensionless", "component": "T_type_Ca_channel_f_gate", "type": VariableType.STATE}, - {"name": "q", "units": "dimensionless", "component": "four_AP_sensitive_currents_q_gate", "type": VariableType.STATE}, + {"name": "d_T", "units": "dimensionless", "component": "T_type_Ca_channel_d_gate", "type": VariableType.STATE}, {"name": "r", "units": "dimensionless", "component": "four_AP_sensitive_currents_r_gate", "type": VariableType.STATE}, + {"name": "q", "units": "dimensionless", "component": "four_AP_sensitive_currents_q_gate", "type": VariableType.STATE}, + {"name": "P_i", "units": "dimensionless", "component": "rapid_delayed_rectifying_potassium_current_P_i_gate", "type": VariableType.STATE}, {"name": "P_af", "units": "dimensionless", "component": "rapid_delayed_rectifying_potassium_current_P_af_gate", "type": VariableType.STATE}, {"name": "P_as", "units": "dimensionless", "component": "rapid_delayed_rectifying_potassium_current_P_as_gate", "type": VariableType.STATE}, - {"name": "P_i", "units": "dimensionless", "component": "rapid_delayed_rectifying_potassium_current_P_i_gate", "type": VariableType.STATE}, {"name": "xs", "units": "dimensionless", "component": "slow_delayed_rectifying_potassium_current_xs_gate", "type": VariableType.STATE}, - {"name": "y", "units": "dimensionless", "component": "hyperpolarisation_activated_current_y_gate", "type": VariableType.STATE}, - {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE} + {"name": "y", "units": "dimensionless", "component": "hyperpolarisation_activated_current_y_gate", "type": VariableType.STATE} ] VARIABLE_INFO = [ - {"name": "E_Ca_L", "units": "millivolt", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "g_Ca_L_Centre_0DCapable", "units": "microS", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "g_Ca_L_Centre_1DCapable", "units": "microS", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "g_Ca_L_Centre_Published", "units": "microS", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "g_Ca_L_Periphery_0DCapable", "units": "microS", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "g_Ca_L_Periphery_1DCapable", "units": "microS", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "g_Ca_L_Periphery_Published", "units": "microS", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "E_Ca_T", "units": "millivolt", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "g_Ca_T_Centre_0DCapable", "units": "microS", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "g_Ca_T_Centre_1DCapable", "units": "microS", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "g_Ca_T_Centre_Published", "units": "microS", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "g_Ca_T_Periphery_0DCapable", "units": "microS", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "g_Ca_T_Periphery_1DCapable", "units": "microS", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "g_Ca_T_Periphery_Published", "units": "microS", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, - {"name": "g_b_Ca_Centre_0DCapable", "units": "microS", "component": "calcium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_b_Ca_Centre_1DCapable", "units": "microS", "component": "calcium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_b_Ca_Centre_Published", "units": "microS", "component": "calcium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_b_Ca_Periphery_0DCapable", "units": "microS", "component": "calcium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_b_Ca_Periphery_1DCapable", "units": "microS", "component": "calcium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_b_Ca_Periphery_Published", "units": "microS", "component": "calcium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_sus_Centre_0DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, - {"name": "g_sus_Centre_1DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, - {"name": "g_sus_Centre_Published", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, - {"name": "g_sus_Periphery_0DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, - {"name": "g_sus_Periphery_1DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, - {"name": "g_sus_Periphery_Published", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, - {"name": "g_to_Centre_0DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, - {"name": "g_to_Centre_1DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, - {"name": "g_to_Centre_Published", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, - {"name": "g_to_Periphery_0DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, - {"name": "g_to_Periphery_1DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, - {"name": "g_to_Periphery_Published", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, - {"name": "g_f_K_Centre_0DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, - {"name": "g_f_K_Centre_1DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, - {"name": "g_f_K_Centre_Published", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, - {"name": "g_f_K_Periphery_0DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, - {"name": "g_f_K_Periphery_1DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, - {"name": "g_f_K_Periphery_Published", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, - {"name": "g_f_Na_Centre_0DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, - {"name": "g_f_Na_Centre_1DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, - {"name": "g_f_Na_Centre_Published", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, - {"name": "g_f_Na_Periphery_0DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, - {"name": "g_f_Na_Periphery_1DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, - {"name": "g_f_Na_Periphery_Published", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, - {"name": "Ca_i", "units": "millimolar", "component": "ionic_concentrations", "type": VariableType.CONSTANT}, - {"name": "Ca_o", "units": "millimolar", "component": "ionic_concentrations", "type": VariableType.CONSTANT}, - {"name": "K_i", "units": "millimolar", "component": "ionic_concentrations", "type": VariableType.CONSTANT}, - {"name": "K_o", "units": "millimolar", "component": "ionic_concentrations", "type": VariableType.CONSTANT}, - {"name": "Na_i", "units": "millimolar", "component": "ionic_concentrations", "type": VariableType.CONSTANT}, - {"name": "Na_o", "units": "millimolar", "component": "ionic_concentrations", "type": VariableType.CONSTANT}, + {"name": "FCell", "units": "dimensionless", "component": "membrane", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "dCell", "units": "dimensionless", "component": "membrane", "type": VariableType.CONSTANT}, + {"name": "Version", "units": "dimensionless", "component": "membrane", "type": VariableType.CONSTANT}, + {"name": "FCellConstant", "units": "dimensionless", "component": "membrane", "type": VariableType.CONSTANT}, + {"name": "Cm", "units": "microF", "component": "membrane", "type": VariableType.COMPUTED_CONSTANT}, {"name": "CmCentre", "units": "microF", "component": "membrane", "type": VariableType.CONSTANT}, {"name": "CmPeriphery", "units": "microF", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "F", "units": "coulomb_per_mole", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "FCellConstant", "units": "dimensionless", "component": "membrane", "type": VariableType.CONSTANT}, + {"name": "i_Na", "units": "nanoA", "component": "sodium_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_Ca_p", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "i_p", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.ALGEBRAIC}, + {"name": "i_NaCa", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.ALGEBRAIC}, + {"name": "i_b_K", "units": "nanoA", "component": "potassium_background_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_b_Ca", "units": "nanoA", "component": "calcium_background_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_b_Na", "units": "nanoA", "component": "sodium_background_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_f_K", "units": "nanoA", "component": "hyperpolarisation_activated_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_f_Na", "units": "nanoA", "component": "hyperpolarisation_activated_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K_s", "units": "nanoA", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K_r", "units": "nanoA", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_sus", "units": "nanoA", "component": "four_AP_sensitive_currents", "type": VariableType.ALGEBRAIC}, + {"name": "i_to", "units": "nanoA", "component": "four_AP_sensitive_currents", "type": VariableType.ALGEBRAIC}, + {"name": "i_Ca_T", "units": "nanoA", "component": "T_type_Ca_channel", "type": VariableType.ALGEBRAIC}, + {"name": "i_Ca_L", "units": "nanoA", "component": "L_type_Ca_channel", "type": VariableType.ALGEBRAIC}, {"name": "R", "units": "millijoule_per_mole_kelvin", "component": "membrane", "type": VariableType.CONSTANT}, {"name": "T", "units": "kelvin", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "Version", "units": "dimensionless", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "dCell", "units": "dimensionless", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "i_Ca_p_max_Centre_0DCapable", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.CONSTANT}, - {"name": "i_Ca_p_max_Centre_1DCapable", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.CONSTANT}, - {"name": "i_Ca_p_max_Centre_Published", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.CONSTANT}, - {"name": "i_Ca_p_max_Periphery_0DCapable", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.CONSTANT}, - {"name": "i_Ca_p_max_Periphery_1DCapable", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.CONSTANT}, - {"name": "i_Ca_p_max_Periphery_Published", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.CONSTANT}, - {"name": "g_b_K_Centre_0DCapable", "units": "microS", "component": "potassium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_b_K_Centre_1DCapable", "units": "microS", "component": "potassium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_b_K_Centre_Published", "units": "microS", "component": "potassium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_b_K_Periphery_0DCapable", "units": "microS", "component": "potassium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_b_K_Periphery_1DCapable", "units": "microS", "component": "potassium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_b_K_Periphery_Published", "units": "microS", "component": "potassium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_K_r_Centre_0DCapable", "units": "microS", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, - {"name": "g_K_r_Centre_1DCapable", "units": "microS", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, - {"name": "g_K_r_Centre_Published", "units": "microS", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, - {"name": "g_K_r_Periphery_0DCapable", "units": "microS", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, - {"name": "g_K_r_Periphery_1DCapable", "units": "microS", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, - {"name": "g_K_r_Periphery_Published", "units": "microS", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, - {"name": "g_K_s_Centre_0DCapable", "units": "microS", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, - {"name": "g_K_s_Centre_1DCapable", "units": "microS", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, - {"name": "g_K_s_Centre_Published", "units": "microS", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, - {"name": "g_K_s_Periphery_0DCapable", "units": "microS", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, - {"name": "g_K_s_Periphery_1DCapable", "units": "microS", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, - {"name": "g_K_s_Periphery_Published", "units": "microS", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, - {"name": "g_b_Na_Centre_0DCapable", "units": "microS", "component": "sodium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_b_Na_Centre_1DCapable", "units": "microS", "component": "sodium_background_current", "type": VariableType.CONSTANT}, + {"name": "F", "units": "coulomb_per_mole", "component": "membrane", "type": VariableType.CONSTANT}, + {"name": "g_b_Na", "units": "microS", "component": "sodium_background_current", "type": VariableType.COMPUTED_CONSTANT}, {"name": "g_b_Na_Centre_Published", "units": "microS", "component": "sodium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_b_Na_Periphery_0DCapable", "units": "microS", "component": "sodium_background_current", "type": VariableType.CONSTANT}, - {"name": "g_b_Na_Periphery_1DCapable", "units": "microS", "component": "sodium_background_current", "type": VariableType.CONSTANT}, {"name": "g_b_Na_Periphery_Published", "units": "microS", "component": "sodium_background_current", "type": VariableType.CONSTANT}, - {"name": "d_NaCa", "units": "dimensionless", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, - {"name": "gamma_NaCa", "units": "dimensionless", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, - {"name": "k_NaCa_Centre_0DCapable", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, - {"name": "k_NaCa_Centre_1DCapable", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, - {"name": "k_NaCa_Centre_Published", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, - {"name": "k_NaCa_Periphery_0DCapable", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, - {"name": "k_NaCa_Periphery_1DCapable", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, - {"name": "k_NaCa_Periphery_Published", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, - {"name": "g_Na_Centre_0DCapable", "units": "microlitre_per_second", "component": "sodium_current", "type": VariableType.CONSTANT}, - {"name": "g_Na_Centre_1DCapable", "units": "microlitre_per_second", "component": "sodium_current", "type": VariableType.CONSTANT}, - {"name": "g_Na_Centre_Published", "units": "microlitre_per_second", "component": "sodium_current", "type": VariableType.CONSTANT}, - {"name": "g_Na_Periphery_0DCapable", "units": "microlitre_per_second", "component": "sodium_current", "type": VariableType.CONSTANT}, - {"name": "g_Na_Periphery_1DCapable", "units": "microlitre_per_second", "component": "sodium_current", "type": VariableType.CONSTANT}, - {"name": "g_Na_Periphery_Published", "units": "microlitre_per_second", "component": "sodium_current", "type": VariableType.CONSTANT}, - {"name": "K_m_K", "units": "millimolar", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, - {"name": "K_m_Na", "units": "millimolar", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, - {"name": "i_p_max_Centre_0DCapable", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, - {"name": "i_p_max_Centre_1DCapable", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, - {"name": "i_p_max_Centre_Published", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, - {"name": "i_p_max_Periphery_0DCapable", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, - {"name": "i_p_max_Periphery_1DCapable", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, - {"name": "i_p_max_Periphery_Published", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, - {"name": "FCell", "units": "dimensionless", "component": "membrane", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "Cm", "units": "microF", "component": "membrane", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "g_b_Na", "units": "microS", "component": "sodium_background_current", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "g_b_Na_Centre_1DCapable", "units": "microS", "component": "sodium_background_current", "type": VariableType.CONSTANT}, + {"name": "g_b_Na_Periphery_1DCapable", "units": "microS", "component": "sodium_background_current", "type": VariableType.CONSTANT}, + {"name": "g_b_Na_Centre_0DCapable", "units": "microS", "component": "sodium_background_current", "type": VariableType.CONSTANT}, + {"name": "g_b_Na_Periphery_0DCapable", "units": "microS", "component": "sodium_background_current", "type": VariableType.CONSTANT}, + {"name": "E_Na", "units": "millivolt", "component": "reversal_and_equilibrium_potentials", "type": VariableType.COMPUTED_CONSTANT}, {"name": "g_b_K", "units": "microS", "component": "potassium_background_current", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "g_b_K_Centre_Published", "units": "microS", "component": "potassium_background_current", "type": VariableType.CONSTANT}, + {"name": "g_b_K_Periphery_Published", "units": "microS", "component": "potassium_background_current", "type": VariableType.CONSTANT}, + {"name": "g_b_K_Centre_1DCapable", "units": "microS", "component": "potassium_background_current", "type": VariableType.CONSTANT}, + {"name": "g_b_K_Periphery_1DCapable", "units": "microS", "component": "potassium_background_current", "type": VariableType.CONSTANT}, + {"name": "g_b_K_Centre_0DCapable", "units": "microS", "component": "potassium_background_current", "type": VariableType.CONSTANT}, + {"name": "g_b_K_Periphery_0DCapable", "units": "microS", "component": "potassium_background_current", "type": VariableType.CONSTANT}, + {"name": "E_K", "units": "millivolt", "component": "reversal_and_equilibrium_potentials", "type": VariableType.COMPUTED_CONSTANT}, {"name": "g_b_Ca", "units": "microS", "component": "calcium_background_current", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "g_b_Ca_Centre_Published", "units": "microS", "component": "calcium_background_current", "type": VariableType.CONSTANT}, + {"name": "g_b_Ca_Periphery_Published", "units": "microS", "component": "calcium_background_current", "type": VariableType.CONSTANT}, + {"name": "g_b_Ca_Centre_1DCapable", "units": "microS", "component": "calcium_background_current", "type": VariableType.CONSTANT}, + {"name": "g_b_Ca_Periphery_1DCapable", "units": "microS", "component": "calcium_background_current", "type": VariableType.CONSTANT}, + {"name": "g_b_Ca_Centre_0DCapable", "units": "microS", "component": "calcium_background_current", "type": VariableType.CONSTANT}, + {"name": "g_b_Ca_Periphery_0DCapable", "units": "microS", "component": "calcium_background_current", "type": VariableType.CONSTANT}, + {"name": "E_Ca", "units": "millivolt", "component": "reversal_and_equilibrium_potentials", "type": VariableType.COMPUTED_CONSTANT}, {"name": "k_NaCa", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_NaCa", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.ALGEBRAIC}, + {"name": "k_NaCa_Centre_Published", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, + {"name": "k_NaCa_Periphery_Published", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, + {"name": "k_NaCa_Centre_1DCapable", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, + {"name": "k_NaCa_Periphery_1DCapable", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, + {"name": "k_NaCa_Centre_0DCapable", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, + {"name": "k_NaCa_Periphery_0DCapable", "units": "nanoA", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, + {"name": "Na_i", "units": "millimolar", "component": "ionic_concentrations", "type": VariableType.CONSTANT}, + {"name": "gamma_NaCa", "units": "dimensionless", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, + {"name": "Ca_o", "units": "millimolar", "component": "ionic_concentrations", "type": VariableType.CONSTANT}, + {"name": "Na_o", "units": "millimolar", "component": "ionic_concentrations", "type": VariableType.CONSTANT}, + {"name": "Ca_i", "units": "millimolar", "component": "ionic_concentrations", "type": VariableType.CONSTANT}, + {"name": "d_NaCa", "units": "dimensionless", "component": "sodium_calcium_exchanger", "type": VariableType.CONSTANT}, {"name": "i_p_max", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_p", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.ALGEBRAIC}, + {"name": "i_p_max_Centre_Published", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, + {"name": "i_p_max_Periphery_Published", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, + {"name": "i_p_max_Centre_1DCapable", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, + {"name": "i_p_max_Periphery_1DCapable", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, + {"name": "i_p_max_Centre_0DCapable", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, + {"name": "i_p_max_Periphery_0DCapable", "units": "nanoA", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, + {"name": "K_o", "units": "millimolar", "component": "ionic_concentrations", "type": VariableType.CONSTANT}, + {"name": "K_m_K", "units": "millimolar", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, + {"name": "K_m_Na", "units": "millimolar", "component": "sodium_potassium_pump", "type": VariableType.CONSTANT}, {"name": "i_Ca_p_max", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_Ca_p", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "E_Na", "units": "millivolt", "component": "reversal_and_equilibrium_potentials", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "E_K", "units": "millivolt", "component": "reversal_and_equilibrium_potentials", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "E_Ca", "units": "millivolt", "component": "reversal_and_equilibrium_potentials", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "i_Ca_p_max_Centre_Published", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.CONSTANT}, + {"name": "i_Ca_p_max_Periphery_Published", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.CONSTANT}, + {"name": "i_Ca_p_max_Centre_1DCapable", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.CONSTANT}, + {"name": "i_Ca_p_max_Periphery_1DCapable", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.CONSTANT}, + {"name": "i_Ca_p_max_Centre_0DCapable", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.CONSTANT}, + {"name": "i_Ca_p_max_Periphery_0DCapable", "units": "nanoA", "component": "persistent_calcium_current", "type": VariableType.CONSTANT}, + {"name": "K_i", "units": "millimolar", "component": "ionic_concentrations", "type": VariableType.CONSTANT}, {"name": "E_K_s", "units": "millivolt", "component": "reversal_and_equilibrium_potentials", "type": VariableType.COMPUTED_CONSTANT}, {"name": "g_Na", "units": "microlitre_per_second", "component": "sodium_current", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "g_Na_Centre_Published", "units": "microlitre_per_second", "component": "sodium_current", "type": VariableType.CONSTANT}, + {"name": "g_Na_Periphery_Published", "units": "microlitre_per_second", "component": "sodium_current", "type": VariableType.CONSTANT}, + {"name": "g_Na_Centre_1DCapable", "units": "microlitre_per_second", "component": "sodium_current", "type": VariableType.CONSTANT}, + {"name": "g_Na_Periphery_1DCapable", "units": "microlitre_per_second", "component": "sodium_current", "type": VariableType.CONSTANT}, + {"name": "g_Na_Centre_0DCapable", "units": "microlitre_per_second", "component": "sodium_current", "type": VariableType.CONSTANT}, + {"name": "g_Na_Periphery_0DCapable", "units": "microlitre_per_second", "component": "sodium_current", "type": VariableType.CONSTANT}, + {"name": "h", "units": "dimensionless", "component": "sodium_current_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "m_infinity", "units": "dimensionless", "component": "sodium_current_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_m", "units": "second", "component": "sodium_current_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "F_Na", "units": "dimensionless", "component": "sodium_current_h_gate", "type": VariableType.ALGEBRAIC}, - {"name": "h", "units": "dimensionless", "component": "sodium_current_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "h1_infinity", "units": "dimensionless", "component": "sodium_current_h_gate", "type": VariableType.ALGEBRAIC}, - {"name": "h2_infinity", "units": "dimensionless", "component": "sodium_current_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_h1", "units": "second", "component": "sodium_current_h_gate", "type": VariableType.ALGEBRAIC}, + {"name": "h2_infinity", "units": "dimensionless", "component": "sodium_current_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_h2", "units": "second", "component": "sodium_current_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "g_Ca_L", "units": "microS", "component": "L_type_Ca_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_Ca_L", "units": "nanoA", "component": "L_type_Ca_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_Ca_L_Centre_Published", "units": "microS", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "g_Ca_L_Periphery_Published", "units": "microS", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "g_Ca_L_Centre_1DCapable", "units": "microS", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "g_Ca_L_Periphery_1DCapable", "units": "microS", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "g_Ca_L_Centre_0DCapable", "units": "microS", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "g_Ca_L_Periphery_0DCapable", "units": "microS", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "E_Ca_L", "units": "millivolt", "component": "L_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "d_L_infinity", "units": "dimensionless", "component": "L_type_Ca_channel_d_gate", "type": VariableType.ALGEBRAIC}, + {"name": "tau_d_L", "units": "second", "component": "L_type_Ca_channel_d_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_d_L", "units": "per_second", "component": "L_type_Ca_channel_d_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_d_L", "units": "per_second", "component": "L_type_Ca_channel_d_gate", "type": VariableType.ALGEBRAIC}, - {"name": "tau_d_L", "units": "second", "component": "L_type_Ca_channel_d_gate", "type": VariableType.ALGEBRAIC}, - {"name": "d_L_infinity", "units": "dimensionless", "component": "L_type_Ca_channel_d_gate", "type": VariableType.ALGEBRAIC}, + {"name": "f_L_infinity", "units": "dimensionless", "component": "L_type_Ca_channel_f_gate", "type": VariableType.ALGEBRAIC}, + {"name": "tau_f_L", "units": "second", "component": "L_type_Ca_channel_f_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_f_L", "units": "per_second", "component": "L_type_Ca_channel_f_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_f_L", "units": "per_second", "component": "L_type_Ca_channel_f_gate", "type": VariableType.ALGEBRAIC}, - {"name": "tau_f_L", "units": "second", "component": "L_type_Ca_channel_f_gate", "type": VariableType.ALGEBRAIC}, - {"name": "f_L_infinity", "units": "dimensionless", "component": "L_type_Ca_channel_f_gate", "type": VariableType.ALGEBRAIC}, {"name": "g_Ca_T", "units": "microS", "component": "T_type_Ca_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_Ca_T", "units": "nanoA", "component": "T_type_Ca_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_Ca_T_Centre_Published", "units": "microS", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "g_Ca_T_Periphery_Published", "units": "microS", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "g_Ca_T_Centre_1DCapable", "units": "microS", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "g_Ca_T_Periphery_1DCapable", "units": "microS", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "g_Ca_T_Centre_0DCapable", "units": "microS", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "g_Ca_T_Periphery_0DCapable", "units": "microS", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "E_Ca_T", "units": "millivolt", "component": "T_type_Ca_channel", "type": VariableType.CONSTANT}, + {"name": "d_T_infinity", "units": "dimensionless", "component": "T_type_Ca_channel_d_gate", "type": VariableType.ALGEBRAIC}, + {"name": "tau_d_T", "units": "second", "component": "T_type_Ca_channel_d_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_d_T", "units": "per_second", "component": "T_type_Ca_channel_d_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_d_T", "units": "per_second", "component": "T_type_Ca_channel_d_gate", "type": VariableType.ALGEBRAIC}, - {"name": "tau_d_T", "units": "second", "component": "T_type_Ca_channel_d_gate", "type": VariableType.ALGEBRAIC}, - {"name": "d_T_infinity", "units": "dimensionless", "component": "T_type_Ca_channel_d_gate", "type": VariableType.ALGEBRAIC}, + {"name": "f_T_infinity", "units": "dimensionless", "component": "T_type_Ca_channel_f_gate", "type": VariableType.ALGEBRAIC}, + {"name": "tau_f_T", "units": "second", "component": "T_type_Ca_channel_f_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_f_T", "units": "per_second", "component": "T_type_Ca_channel_f_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_f_T", "units": "per_second", "component": "T_type_Ca_channel_f_gate", "type": VariableType.ALGEBRAIC}, - {"name": "tau_f_T", "units": "second", "component": "T_type_Ca_channel_f_gate", "type": VariableType.ALGEBRAIC}, - {"name": "f_T_infinity", "units": "dimensionless", "component": "T_type_Ca_channel_f_gate", "type": VariableType.ALGEBRAIC}, {"name": "g_to", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "g_to_Centre_Published", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, + {"name": "g_to_Periphery_Published", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, + {"name": "g_to_Centre_1DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, + {"name": "g_to_Periphery_1DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, + {"name": "g_to_Centre_0DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, + {"name": "g_to_Periphery_0DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, {"name": "g_sus", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_to", "units": "nanoA", "component": "four_AP_sensitive_currents", "type": VariableType.ALGEBRAIC}, - {"name": "i_sus", "units": "nanoA", "component": "four_AP_sensitive_currents", "type": VariableType.ALGEBRAIC}, + {"name": "g_sus_Centre_Published", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, + {"name": "g_sus_Periphery_Published", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, + {"name": "g_sus_Centre_1DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, + {"name": "g_sus_Periphery_1DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, + {"name": "g_sus_Centre_0DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, + {"name": "g_sus_Periphery_0DCapable", "units": "microS", "component": "four_AP_sensitive_currents", "type": VariableType.CONSTANT}, {"name": "q_infinity", "units": "dimensionless", "component": "four_AP_sensitive_currents_q_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_q", "units": "second", "component": "four_AP_sensitive_currents_q_gate", "type": VariableType.ALGEBRAIC}, {"name": "r_infinity", "units": "dimensionless", "component": "four_AP_sensitive_currents_r_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_r", "units": "second", "component": "four_AP_sensitive_currents_r_gate", "type": VariableType.ALGEBRAIC}, {"name": "g_K_r", "units": "microS", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "g_K_r_Centre_Published", "units": "microS", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, + {"name": "g_K_r_Periphery_Published", "units": "microS", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, + {"name": "g_K_r_Centre_1DCapable", "units": "microS", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, + {"name": "g_K_r_Periphery_1DCapable", "units": "microS", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, + {"name": "g_K_r_Centre_0DCapable", "units": "microS", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, + {"name": "g_K_r_Periphery_0DCapable", "units": "microS", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, {"name": "P_a", "units": "dimensionless", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.ALGEBRAIC}, {"name": "P_af_infinity", "units": "dimensionless", "component": "rapid_delayed_rectifying_potassium_current_P_af_gate", "type": VariableType.ALGEBRAIC}, {"name": "tau_P_af", "units": "second", "component": "rapid_delayed_rectifying_potassium_current_P_af_gate", "type": VariableType.ALGEBRAIC}, @@ -211,20 +201,30 @@ class VariableType(Enum): {"name": "tau_P_i", "units": "second", "component": "rapid_delayed_rectifying_potassium_current_P_i_gate", "type": VariableType.COMPUTED_CONSTANT}, {"name": "P_i_infinity", "units": "dimensionless", "component": "rapid_delayed_rectifying_potassium_current_P_i_gate", "type": VariableType.ALGEBRAIC}, {"name": "g_K_s", "units": "microS", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_K_s", "units": "nanoA", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.ALGEBRAIC}, + {"name": "g_K_s_Centre_Published", "units": "microS", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, + {"name": "g_K_s_Periphery_Published", "units": "microS", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, + {"name": "g_K_s_Centre_1DCapable", "units": "microS", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, + {"name": "g_K_s_Periphery_1DCapable", "units": "microS", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, + {"name": "g_K_s_Centre_0DCapable", "units": "microS", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, + {"name": "g_K_s_Periphery_0DCapable", "units": "microS", "component": "slow_delayed_rectifying_potassium_current", "type": VariableType.CONSTANT}, {"name": "alpha_xs", "units": "per_second", "component": "slow_delayed_rectifying_potassium_current_xs_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_xs", "units": "per_second", "component": "slow_delayed_rectifying_potassium_current_xs_gate", "type": VariableType.ALGEBRAIC}, {"name": "g_f_Na", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_f_Na", "units": "nanoA", "component": "hyperpolarisation_activated_current", "type": VariableType.ALGEBRAIC}, + {"name": "g_f_Na_Centre_Published", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, + {"name": "g_f_Na_Periphery_Published", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, + {"name": "g_f_Na_Centre_1DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, + {"name": "g_f_Na_Periphery_1DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, + {"name": "g_f_Na_Centre_0DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, + {"name": "g_f_Na_Periphery_0DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, {"name": "g_f_K", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_f_K", "units": "nanoA", "component": "hyperpolarisation_activated_current", "type": VariableType.ALGEBRAIC}, + {"name": "g_f_K_Centre_Published", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, + {"name": "g_f_K_Periphery_Published", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, + {"name": "g_f_K_Centre_1DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, + {"name": "g_f_K_Periphery_1DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, + {"name": "g_f_K_Centre_0DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, + {"name": "g_f_K_Periphery_0DCapable", "units": "microS", "component": "hyperpolarisation_activated_current", "type": VariableType.CONSTANT}, {"name": "alpha_y", "units": "per_second", "component": "hyperpolarisation_activated_current_y_gate", "type": VariableType.ALGEBRAIC}, - {"name": "beta_y", "units": "per_second", "component": "hyperpolarisation_activated_current_y_gate", "type": VariableType.ALGEBRAIC}, - {"name": "i_b_Na", "units": "nanoA", "component": "sodium_background_current", "type": VariableType.ALGEBRAIC}, - {"name": "i_b_K", "units": "nanoA", "component": "potassium_background_current", "type": VariableType.ALGEBRAIC}, - {"name": "i_b_Ca", "units": "nanoA", "component": "calcium_background_current", "type": VariableType.ALGEBRAIC}, - {"name": "i_Na", "units": "nanoA", "component": "sodium_current", "type": VariableType.ALGEBRAIC}, - {"name": "i_K_r", "units": "nanoA", "component": "rapid_delayed_rectifying_potassium_current", "type": VariableType.ALGEBRAIC} + {"name": "beta_y", "units": "per_second", "component": "hyperpolarisation_activated_current_y_gate", "type": VariableType.ALGEBRAIC} ] @@ -244,280 +244,280 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): - variables[0] = 46.4 - variables[1] = 0.0057938 - variables[2] = 0.0082 - variables[3] = 0.0058 - variables[4] = 0.06588648 - variables[5] = 0.0659 - variables[6] = 0.0659 - variables[7] = 45.0 - variables[8] = 0.00427806 - variables[9] = 0.0021 - variables[10] = 0.0043 - variables[11] = 0.0138823 - variables[12] = 0.00694 - variables[13] = 0.0139 - variables[14] = 1.3236e-5 - variables[15] = 1.323e-5 - variables[16] = 1.32e-5 - variables[17] = 4.2952e-5 - variables[18] = 4.29e-5 - variables[19] = 4.3e-5 - variables[20] = 6.645504e-5 - variables[21] = 0.000266 - variables[22] = 6.65e-5 - variables[23] = 0.01138376 - variables[24] = 0.0114 - variables[25] = 0.0114 - variables[26] = 0.004905 - variables[27] = 0.004905 - variables[28] = 0.00491 - variables[29] = 0.036495 - variables[30] = 0.0365 - variables[31] = 0.03649 - variables[32] = 0.0005465 - variables[33] = 0.000437 - variables[34] = 0.000548 - variables[35] = 0.006875 - variables[36] = 0.0055 - variables[37] = 0.0069 - variables[38] = 0.0005465 - variables[39] = 0.000437 - variables[40] = 0.000548 - variables[41] = 0.006875 - variables[42] = 0.0055 - variables[43] = 0.0069 - variables[44] = 0.0001 - variables[45] = 2.0 - variables[46] = 140.0 - variables[47] = 5.4 - variables[48] = 8.0 - variables[49] = 140.0 - variables[50] = 2.0e-5 - variables[51] = 6.5e-5 - variables[52] = 96845.0 - variables[53] = 1.0309347 - variables[54] = 8314.0 - variables[55] = 310.0 - variables[56] = 1.0 - variables[57] = 0.0 - variables[58] = 0.0 - variables[59] = 0.0042 - variables[60] = 0.0 - variables[61] = 0.0 - variables[62] = 0.03339 - variables[63] = 0.0 - variables[64] = 2.523636e-5 - variables[65] = 2.52e-5 - variables[66] = 2.52e-5 - variables[67] = 8.1892e-5 - variables[68] = 8.19e-5 - variables[69] = 8.19e-5 - variables[70] = 0.00079704 - variables[71] = 0.000738 - variables[72] = 0.000797 - variables[73] = 0.016 - variables[74] = 0.0208 - variables[75] = 0.016 - variables[76] = 0.0003445 - variables[77] = 0.000345 - variables[78] = 0.000518 - variables[79] = 0.0104 - variables[80] = 0.0104 - variables[81] = 0.0104 - variables[82] = 5.81818e-5 - variables[83] = 5.8e-5 - variables[84] = 5.8e-5 - variables[85] = 0.0001888 - variables[86] = 0.000189 - variables[87] = 0.000189 - variables[88] = 0.0001 - variables[89] = 0.5 - variables[90] = 2.7229e-6 - variables[91] = 2.8e-6 - variables[92] = 2.7e-6 - variables[93] = 8.83584e-6 - variables[94] = 8.8e-6 - variables[95] = 8.8e-6 - variables[96] = 0.0 - variables[97] = 0.0 - variables[98] = 0.0 - variables[99] = 1.204e-6 - variables[100] = 3.7e-7 - variables[101] = 1.2e-6 - variables[102] = 0.621 - variables[103] = 5.64 - variables[104] = 0.04782545 - variables[105] = 0.0478 - variables[106] = 0.0478 - variables[107] = 0.1551936 - variables[108] = 0.16 - variables[109] = 0.16 - states[0] = 0.092361701692 - states[1] = 0.015905380261 - states[2] = 0.01445216109 - states[3] = 0.04804900895 +def initialise_variables(states, rates, variables): + variables[1] = 0.0 + variables[2] = 1.0 + variables[3] = 1.0309347 + variables[5] = 2.0e-5 + variables[6] = 6.5e-5 + variables[22] = 8314.0 + variables[23] = 310.0 + variables[24] = 96845.0 + variables[26] = 5.8e-5 + variables[27] = 0.000189 + variables[28] = 5.8e-5 + variables[29] = 0.000189 + variables[30] = 5.81818e-5 + variables[31] = 0.0001888 + variables[34] = 2.52e-5 + variables[35] = 8.19e-5 + variables[36] = 2.52e-5 + variables[37] = 8.19e-5 + variables[38] = 2.523636e-5 + variables[39] = 8.1892e-5 + variables[42] = 1.32e-5 + variables[43] = 4.3e-5 + variables[44] = 1.323e-5 + variables[45] = 4.29e-5 + variables[46] = 1.3236e-5 + variables[47] = 4.2952e-5 + variables[50] = 2.7e-6 + variables[51] = 8.8e-6 + variables[52] = 2.8e-6 + variables[53] = 8.8e-6 + variables[54] = 2.7229e-6 + variables[55] = 8.83584e-6 + variables[56] = 8.0 + variables[57] = 0.5 + variables[58] = 2.0 + variables[59] = 140.0 + variables[60] = 0.0001 + variables[61] = 0.0001 + variables[63] = 0.0478 + variables[64] = 0.16 + variables[65] = 0.0478 + variables[66] = 0.16 + variables[67] = 0.04782545 + variables[68] = 0.1551936 + variables[69] = 5.4 + variables[70] = 0.621 + variables[71] = 5.64 + variables[73] = 0.0 + variables[74] = 0.0 + variables[75] = 0.0042 + variables[76] = 0.03339 + variables[77] = 0.0 + variables[78] = 0.0 + variables[79] = 140.0 + variables[82] = 0.0 + variables[83] = 1.2e-6 + variables[84] = 0.0 + variables[85] = 3.7e-7 + variables[86] = 0.0 + variables[87] = 1.204e-6 + variables[97] = 0.0058 + variables[98] = 0.0659 + variables[99] = 0.0082 + variables[100] = 0.0659 + variables[101] = 0.0057938 + variables[102] = 0.06588648 + variables[103] = 46.4 + variables[113] = 0.0043 + variables[114] = 0.0139 + variables[115] = 0.0021 + variables[116] = 0.00694 + variables[117] = 0.00427806 + variables[118] = 0.0138823 + variables[119] = 45.0 + variables[129] = 0.00491 + variables[130] = 0.03649 + variables[131] = 0.004905 + variables[132] = 0.0365 + variables[133] = 0.004905 + variables[134] = 0.036495 + variables[136] = 6.65e-5 + variables[137] = 0.0114 + variables[138] = 0.000266 + variables[139] = 0.0114 + variables[140] = 6.645504e-5 + variables[141] = 0.01138376 + variables[147] = 0.000797 + variables[148] = 0.016 + variables[149] = 0.000738 + variables[150] = 0.0208 + variables[151] = 0.00079704 + variables[152] = 0.016 + variables[161] = 0.000518 + variables[162] = 0.0104 + variables[163] = 0.000345 + variables[164] = 0.0104 + variables[165] = 0.0003445 + variables[166] = 0.0104 + variables[170] = 0.000548 + variables[171] = 0.0069 + variables[172] = 0.000437 + variables[173] = 0.0055 + variables[174] = 0.0005465 + variables[175] = 0.006875 + variables[177] = 0.000548 + variables[178] = 0.0069 + variables[179] = 0.000437 + variables[180] = 0.0055 + variables[181] = 0.0005465 + variables[182] = 0.006875 + states[0] = -39.013558536 + states[1] = 0.092361701692 + states[2] = 0.015905380261 + states[3] = 0.01445216109 states[4] = 0.48779845203 - states[5] = 0.42074047435 + states[5] = 0.04804900895 states[6] = 0.038968420558 - states[7] = 0.29760539675 + states[7] = 0.42074047435 states[8] = 0.064402950262 - states[9] = 0.13034201158 - states[10] = 0.46960956028 - states[11] = 0.87993375273 - states[12] = 0.082293827208 - states[13] = 0.03889291759 - states[14] = -39.013558536 + states[9] = 0.29760539675 + states[10] = 0.87993375273 + states[11] = 0.13034201158 + states[12] = 0.46960956028 + states[13] = 0.082293827208 + states[14] = 0.03889291759 def compute_computed_constants(variables): - variables[110] = 1.07*(3.0*variables[57]-0.1)/(3.0*(1.0+0.7745*exp(-(3.0*variables[57]-2.05)/0.295))) if eq_func(variables[56], 0.0) else variables[53]*variables[57]/(1.0+0.7745*exp(-(3.0*variables[57]-2.05)/0.295)) if eq_func(variables[56], 1.0) else 1.07*29.0*variables[57]/(30.0*(1.0+0.7745*exp(-(29.0*variables[57]-24.5)/1.95))) - variables[111] = variables[50]+variables[110]*(variables[51]-variables[50]) - variables[112] = variables[84]+variables[110]*(variables[87]-variables[84]) if eq_func(variables[56], 0.0) else variables[82]+variables[110]*(variables[85]-variables[82]) if eq_func(variables[56], 1.0) else variables[83]+variables[110]*(variables[86]-variables[83]) - variables[113] = variables[66]+variables[110]*(variables[69]-variables[66]) if eq_func(variables[56], 0.0) else variables[64]+variables[110]*(variables[67]-variables[64]) if eq_func(variables[56], 1.0) else variables[65]+variables[110]*(variables[68]-variables[65]) - variables[114] = variables[16]+variables[110]*(variables[19]-variables[16]) if eq_func(variables[56], 0.0) else variables[14]+variables[110]*(variables[17]-variables[14]) if eq_func(variables[56], 1.0) else variables[15]+variables[110]*(variables[18]-variables[15]) - variables[115] = variables[92]+variables[110]*(variables[95]-variables[92]) if eq_func(variables[56], 0.0) else variables[90]+variables[110]*(variables[93]-variables[90]) if eq_func(variables[56], 1.0) else variables[91]+variables[110]*(variables[94]-variables[91]) - variables[117] = variables[106]+variables[110]*(variables[109]-variables[106]) if eq_func(variables[56], 0.0) else variables[104]+variables[110]*(variables[107]-variables[104]) if eq_func(variables[56], 1.0) else variables[105]+variables[110]*(variables[108]-variables[105]) - variables[119] = variables[60]+variables[110]*(variables[63]-variables[60]) if eq_func(variables[56], 0.0) else variables[58]+variables[110]*(variables[61]-variables[58]) if eq_func(variables[56], 1.0) else variables[59]+variables[110]*(variables[62]-variables[59]) - variables[120] = variables[119]*variables[44]/(variables[44]+0.0004) - variables[121] = variables[54]*variables[55]/variables[52]*log(variables[49]/variables[48]) - variables[122] = variables[54]*variables[55]/variables[52]*log(variables[47]/variables[46]) - variables[123] = variables[54]*variables[55]/(2.0*variables[52])*log(variables[45]/variables[44]) - variables[124] = variables[54]*variables[55]/variables[52]*log((variables[47]+0.12*variables[49])/(variables[46]+0.12*variables[48])) if eq_func(variables[56], 0.0) else variables[54]*variables[55]/variables[52]*log((variables[47]+0.03*variables[49])/(variables[46]+0.03*variables[48])) - variables[125] = variables[98]+variables[110]*(variables[101]-variables[98]) if eq_func(variables[56], 0.0) else variables[96]+variables[110]*(variables[99]-variables[96]) if eq_func(variables[56], 1.0) else variables[97]+variables[110]*(variables[100]-variables[97]) - variables[134] = variables[3]+variables[110]*(variables[6]-variables[3]) if eq_func(variables[56], 0.0) else variables[1]+variables[110]*(variables[4]-variables[1]) if eq_func(variables[56], 1.0) else variables[2]+variables[110]*(variables[5]-variables[2]) - variables[144] = variables[10]+variables[110]*(variables[13]-variables[10]) if eq_func(variables[56], 0.0) else variables[8]+variables[110]*(variables[11]-variables[8]) if eq_func(variables[56], 1.0) else variables[9]+variables[110]*(variables[12]-variables[9]) - variables[154] = variables[28]+variables[110]*(variables[31]-variables[28]) if eq_func(variables[56], 0.0) else variables[26]+variables[110]*(variables[29]-variables[26]) if eq_func(variables[56], 1.0) else variables[27]+variables[110]*(variables[30]-variables[27]) - variables[155] = variables[22]+variables[110]*(variables[25]-variables[22]) if eq_func(variables[56], 0.0) else variables[20]+variables[110]*(variables[23]-variables[20]) if eq_func(variables[56], 1.0) else variables[21]+variables[110]*(variables[24]-variables[21]) - variables[162] = variables[72]+variables[110]*(variables[75]-variables[72]) if eq_func(variables[56], 0.0) else variables[70]+variables[110]*(variables[73]-variables[70]) if eq_func(variables[56], 1.0) else variables[71]+variables[110]*(variables[74]-variables[71]) - variables[168] = 0.002 if eq_func(variables[56], 0.0) else 0.002 if eq_func(variables[56], 1.0) else 0.006 - variables[170] = variables[78]+variables[110]*(variables[81]-variables[78]) if eq_func(variables[56], 0.0) else variables[76]+variables[110]*(variables[79]-variables[76]) if eq_func(variables[56], 1.0) else variables[77]+variables[110]*(variables[80]-variables[77]) - variables[174] = variables[40]+variables[110]*(variables[43]-variables[40]) if eq_func(variables[56], 0.0) else variables[38]+variables[110]*(variables[41]-variables[38]) if eq_func(variables[56], 1.0) else variables[39]+variables[110]*(variables[42]-variables[39]) - variables[176] = variables[34]+variables[110]*(variables[37]-variables[34]) if eq_func(variables[56], 0.0) else variables[32]+variables[110]*(variables[35]-variables[32]) if eq_func(variables[56], 1.0) else variables[33]+variables[110]*(variables[36]-variables[33]) + variables[0] = 1.07*(3.0*variables[1]-0.1)/(3.0*(1.0+0.7745*exp(-(3.0*variables[1]-2.05)/0.295))) if eq_func(variables[2], 0.0) else variables[3]*variables[1]/(1.0+0.7745*exp(-(3.0*variables[1]-2.05)/0.295)) if eq_func(variables[2], 1.0) else 1.07*29.0*variables[1]/(30.0*(1.0+0.7745*exp(-(29.0*variables[1]-24.5)/1.95))) + variables[4] = variables[5]+variables[0]*(variables[6]-variables[5]) + variables[25] = variables[26]+variables[0]*(variables[27]-variables[26]) if eq_func(variables[2], 0.0) else variables[30]+variables[0]*(variables[31]-variables[30]) if eq_func(variables[2], 1.0) else variables[28]+variables[0]*(variables[29]-variables[28]) + variables[33] = variables[34]+variables[0]*(variables[35]-variables[34]) if eq_func(variables[2], 0.0) else variables[38]+variables[0]*(variables[39]-variables[38]) if eq_func(variables[2], 1.0) else variables[36]+variables[0]*(variables[37]-variables[36]) + variables[41] = variables[42]+variables[0]*(variables[43]-variables[42]) if eq_func(variables[2], 0.0) else variables[46]+variables[0]*(variables[47]-variables[46]) if eq_func(variables[2], 1.0) else variables[44]+variables[0]*(variables[45]-variables[44]) + variables[49] = variables[50]+variables[0]*(variables[51]-variables[50]) if eq_func(variables[2], 0.0) else variables[54]+variables[0]*(variables[55]-variables[54]) if eq_func(variables[2], 1.0) else variables[52]+variables[0]*(variables[53]-variables[52]) + variables[62] = variables[63]+variables[0]*(variables[64]-variables[63]) if eq_func(variables[2], 0.0) else variables[67]+variables[0]*(variables[68]-variables[67]) if eq_func(variables[2], 1.0) else variables[65]+variables[0]*(variables[66]-variables[65]) + variables[72] = variables[73]+variables[0]*(variables[74]-variables[73]) if eq_func(variables[2], 0.0) else variables[77]+variables[0]*(variables[78]-variables[77]) if eq_func(variables[2], 1.0) else variables[75]+variables[0]*(variables[76]-variables[75]) + variables[8] = variables[72]*variables[60]/(variables[60]+0.0004) + variables[32] = variables[22]*variables[23]/variables[24]*log(variables[59]/variables[56]) + variables[40] = variables[22]*variables[23]/variables[24]*log(variables[69]/variables[79]) + variables[48] = variables[22]*variables[23]/(2.0*variables[24])*log(variables[58]/variables[60]) + variables[80] = variables[22]*variables[23]/variables[24]*log((variables[69]+0.12*variables[59])/(variables[79]+0.12*variables[56])) if eq_func(variables[2], 0.0) else variables[22]*variables[23]/variables[24]*log((variables[69]+0.03*variables[59])/(variables[79]+0.03*variables[56])) + variables[81] = variables[82]+variables[0]*(variables[83]-variables[82]) if eq_func(variables[2], 0.0) else variables[86]+variables[0]*(variables[87]-variables[86]) if eq_func(variables[2], 1.0) else variables[84]+variables[0]*(variables[85]-variables[84]) + variables[96] = variables[97]+variables[0]*(variables[98]-variables[97]) if eq_func(variables[2], 0.0) else variables[101]+variables[0]*(variables[102]-variables[101]) if eq_func(variables[2], 1.0) else variables[99]+variables[0]*(variables[100]-variables[99]) + variables[112] = variables[113]+variables[0]*(variables[114]-variables[113]) if eq_func(variables[2], 0.0) else variables[117]+variables[0]*(variables[118]-variables[117]) if eq_func(variables[2], 1.0) else variables[115]+variables[0]*(variables[116]-variables[115]) + variables[128] = variables[129]+variables[0]*(variables[130]-variables[129]) if eq_func(variables[2], 0.0) else variables[133]+variables[0]*(variables[134]-variables[133]) if eq_func(variables[2], 1.0) else variables[131]+variables[0]*(variables[132]-variables[131]) + variables[135] = variables[136]+variables[0]*(variables[137]-variables[136]) if eq_func(variables[2], 0.0) else variables[140]+variables[0]*(variables[141]-variables[140]) if eq_func(variables[2], 1.0) else variables[138]+variables[0]*(variables[139]-variables[138]) + variables[146] = variables[147]+variables[0]*(variables[148]-variables[147]) if eq_func(variables[2], 0.0) else variables[151]+variables[0]*(variables[152]-variables[151]) if eq_func(variables[2], 1.0) else variables[149]+variables[0]*(variables[150]-variables[149]) + variables[158] = 0.002 if eq_func(variables[2], 0.0) else 0.002 if eq_func(variables[2], 1.0) else 0.006 + variables[160] = variables[161]+variables[0]*(variables[162]-variables[161]) if eq_func(variables[2], 0.0) else variables[165]+variables[0]*(variables[166]-variables[165]) if eq_func(variables[2], 1.0) else variables[163]+variables[0]*(variables[164]-variables[163]) + variables[169] = variables[170]+variables[0]*(variables[171]-variables[170]) if eq_func(variables[2], 0.0) else variables[174]+variables[0]*(variables[175]-variables[174]) if eq_func(variables[2], 1.0) else variables[172]+variables[0]*(variables[173]-variables[172]) + variables[176] = variables[177]+variables[0]*(variables[178]-variables[177]) if eq_func(variables[2], 0.0) else variables[181]+variables[0]*(variables[182]-variables[181]) if eq_func(variables[2], 1.0) else variables[179]+variables[0]*(variables[180]-variables[179]) def compute_rates(voi, states, rates, variables): - variables[126] = pow(1.0/(1.0+exp(-states[14]/5.46)), 1.0/3.0) if eq_func(variables[56], 0.0) else pow(1.0/(1.0+exp(-(states[14]+30.32)/5.46)), 1.0/3.0) - variables[127] = 0.0006247/(0.832*exp(-0.335*(states[14]+56.7))+0.627*exp(0.082*(states[14]+65.01)))+4.0e-5 if eq_func(variables[56], 0.0) else 0.0006247/(0.8322166*exp(-0.33566*(states[14]+56.7062))+0.6274*exp(0.0823*(states[14]+65.0131)))+4.569e-5 - rates[0] = (variables[126]-states[0])/variables[127] - variables[130] = 1.0/(1.0+exp((states[14]+66.1)/6.4)) - variables[132] = 3.717e-6*exp(-0.2815*(states[14]+17.11))/(1.0+0.003732*exp(-0.3426*(states[14]+37.76)))+0.0005977 - rates[1] = (variables[130]-states[1])/variables[132] - variables[131] = variables[130] - variables[133] = 3.186e-8*exp(-0.6219*(states[14]+18.8))/(1.0+7.189e-5*exp(-0.6683*(states[14]+34.07)))+0.003556 - rates[2] = (variables[131]-states[2])/variables[133] - variables[139] = 1.0/(1.0+exp(-(states[14]+23.1)/6.0)) if eq_func(variables[56], 0.0) else 1.0/(1.0+exp(-(states[14]+22.3+0.8*variables[110])/6.0)) if eq_func(variables[56], 1.0) else 1.0/(1.0+exp(-(states[14]+22.2)/6.0)) - variables[136] = -28.38*(states[14]+35.0)/(exp(-(states[14]+35.0)/2.5)-1.0)-84.9*states[14]/(exp(-0.208*states[14])-1.0) if eq_func(variables[56], 0.0) else -28.39*(states[14]+35.0)/(exp(-(states[14]+35.0)/2.5)-1.0)-84.9*states[14]/(exp(-0.208*states[14])-1.0) if eq_func(variables[56], 1.0) else -28.4*(states[14]+35.0)/(exp(-(states[14]+35.0)/2.5)-1.0)-84.9*states[14]/(exp(-0.208*states[14])-1.0) - variables[137] = 11.43*(states[14]-5.0)/(exp(0.4*(states[14]-5.0))-1.0) if eq_func(variables[56], 1.0) else 11.42*(states[14]-5.0)/(exp(0.4*(states[14]-5.0))-1.0) - variables[138] = 2.0/(variables[136]+variables[137]) - rates[3] = (variables[139]-states[3])/variables[138] - variables[143] = 1.0/(1.0+exp((states[14]+45.0)/5.0)) - variables[140] = 3.75*(states[14]+28.0)/(exp((states[14]+28.0)/4.0)-1.0) if eq_func(variables[56], 1.0) else 3.12*(states[14]+28.0)/(exp((states[14]+28.0)/4.0)-1.0) - variables[141] = 30.0/(1.0+exp(-(states[14]+28.0)/4.0)) if eq_func(variables[56], 1.0) else 25.0/(1.0+exp(-(states[14]+28.0)/4.0)) - variables[142] = (1.2-0.2*variables[110])/(variables[140]+variables[141]) if eq_func(variables[56], 1.0) else 1.0/(variables[140]+variables[141]) - rates[4] = (variables[143]-states[4])/variables[142] - variables[149] = 1.0/(1.0+exp(-(states[14]+37.0)/6.8)) - variables[146] = 1068.0*exp((states[14]+26.3)/30.0) - variables[147] = 1068.0*exp(-(states[14]+26.3)/30.0) - variables[148] = 1.0/(variables[146]+variables[147]) - rates[5] = (variables[149]-states[5])/variables[148] - variables[153] = 1.0/(1.0+exp((states[14]+71.0)/9.0)) - variables[150] = 15.3*exp(-(states[14]+71.0+0.7*variables[110])/83.3) if eq_func(variables[56], 1.0) else 15.3*exp(-(states[14]+71.7)/83.3) - variables[151] = 15.0*exp((states[14]+71.0)/15.38) if eq_func(variables[56], 1.0) else 15.0*exp((states[14]+71.7)/15.38) - variables[152] = 1.0/(variables[150]+variables[151]) - rates[6] = (variables[153]-states[6])/variables[152] - variables[158] = 1.0/(1.0+exp((states[14]+59.37)/13.1)) - variables[159] = 0.0101+0.06517/(0.57*exp(-0.08*(states[14]+49.0)))+2.4e-5*exp(0.1*(states[14]+50.93)) if eq_func(variables[56], 0.0) else 0.001/3.0*(30.31+195.5/(0.5686*exp(-0.08161*(states[14]+39.0+10.0*variables[110]))+0.7174*exp((0.2719-0.1719*variables[110])*1.0*(states[14]+40.93+10.0*variables[110])))) if eq_func(variables[56], 1.0) else 0.0101+0.06517/(0.5686*exp(-0.08161*(states[14]+39.0))+0.7174*exp(0.2719*(states[14]+40.93))) - rates[7] = (variables[158]-states[7])/variables[159] - variables[160] = 1.0/(1.0+exp(-(states[14]-10.93)/19.7)) - variables[161] = 0.001*(2.98+15.59/(1.037*exp(0.09*(states[14]+30.61))+0.369*exp(-0.12*(states[14]+23.84)))) if eq_func(variables[56], 0.0) else 0.0025*(1.191+7.838/(1.037*exp(0.09012*(states[14]+30.61))+0.369*exp(-0.119*(states[14]+23.84)))) if eq_func(variables[56], 1.0) else 0.001*(2.98+19.59/(1.037*exp(0.09012*(states[14]+30.61))+0.369*exp(-0.119*(states[14]+23.84)))) - rates[8] = (variables[160]-states[8])/variables[161] - variables[164] = 1.0/(1.0+exp(-(states[14]+14.2)/10.6)) if neq_func(variables[56], 2.0) else 1.0/(1.0+exp(-(states[14]+13.2)/10.6)) - variables[165] = 1.0/(37.2*exp((states[14]-9.0)/15.9)+0.96*exp(-(states[14]-9.0)/22.5)) if neq_func(variables[56], 2.0) else 1.0/(37.2*exp((states[14]-10.0)/15.9)+0.96*exp(-(states[14]-10.0)/22.5)) - rates[9] = (variables[164]-states[9])/variables[165] - variables[166] = variables[164] - variables[167] = 1.0/(4.2*exp((states[14]-9.0)/17.0)+0.15*exp(-(states[14]-9.0)/21.6)) if neq_func(variables[56], 2.0) else 1.0/(4.2*exp((states[14]-10.0)/17.0)+0.15*exp(-(states[14]-10.0)/21.6)) - rates[10] = (variables[166]-states[10])/variables[167] - variables[169] = 1.0/(1.0+exp((states[14]+18.6)/10.1)) - rates[11] = (variables[169]-states[11])/variables[168] - variables[172] = 14.0/(1.0+exp(-(states[14]-40.0)/9.0)) - variables[173] = 1.0*exp(-states[14]/45.0) - rates[12] = variables[172]*(1.0-states[12])-variables[173]*states[12] - variables[178] = 1.0*exp(-(states[14]+78.91)/26.62) if eq_func(variables[56], 0.0) else 1.0*exp(-(states[14]+78.91)/26.63) - variables[179] = 1.0*exp((states[14]+75.13)/21.25) - rates[13] = variables[178]*(1.0-states[13])-variables[179]*states[13] - variables[118] = variables[117]*pow(variables[48]/(variables[103]+variables[48]), 3.0)*pow(variables[47]/(variables[102]+variables[47]), 2.0)*1.6/(1.5+exp(-(states[14]+60.0)/40.0)) - variables[116] = variables[115]*(pow(variables[48], 3.0)*variables[45]*exp(0.03743*states[14]*variables[89])-pow(variables[49], 3.0)*variables[44]*exp(0.0374*states[14]*(variables[89]-1.0)))/(1.0+variables[88]*(variables[44]*pow(variables[49], 3.0)+variables[45]*pow(variables[48], 3.0))) if eq_func(variables[56], 0.0) else variables[115]*(pow(variables[48], 3.0)*variables[45]*exp(0.03743*states[14]*variables[89])-pow(variables[49], 3.0)*variables[44]*exp(0.03743*states[14]*(variables[89]-1.0)))/(1.0+variables[88]*(variables[44]*pow(variables[49], 3.0)+variables[45]*pow(variables[48], 3.0))) - variables[177] = variables[176]*states[13]*(states[14]-variables[122]) if neq_func(variables[56], 2.0) else variables[176]*states[13]*(states[14]+102.0) - variables[175] = variables[174]*states[13]*(states[14]-variables[121]) if neq_func(variables[56], 2.0) else variables[174]*states[13]*(states[14]-77.6) - variables[171] = variables[170]*pow(states[12], 2.0)*(states[14]-variables[124]) - variables[157] = variables[155]*states[8]*(states[14]-variables[122]) - variables[156] = variables[154]*states[7]*states[8]*(states[14]-variables[122]) - variables[145] = variables[144]*states[5]*states[6]*(states[14]-variables[7]) - variables[135] = variables[134]*(states[4]*states[3]+0.006/(1.0+exp(-(states[14]+14.1)/6.0)))*(states[14]-variables[0]) - variables[128] = 0.0952*exp(-0.063*(states[14]+34.4))/(1.0+1.66*exp(-0.225*(states[14]+63.7)))+0.0869 if eq_func(variables[56], 0.0) else 0.09518*exp(-0.06306*(states[14]+34.4))/(1.0+1.662*exp(-0.2251*(states[14]+63.7)))+0.08693 - variables[129] = (1.0-variables[128])*states[1]+variables[128]*states[2] - variables[183] = variables[125]*pow(states[0], 3.0)*variables[129]*variables[49]*pow(variables[52], 2.0)/(variables[54]*variables[55])*(exp((states[14]-variables[121])*variables[52]/(variables[54]*variables[55]))-1.0)/(exp(states[14]*variables[52]/(variables[54]*variables[55]))-1.0)*states[14] - variables[181] = variables[113]*(states[14]-variables[122]) - variables[182] = variables[114]*(states[14]-variables[123]) - variables[180] = variables[112]*(states[14]-variables[121]) - variables[163] = 0.6*states[9]+0.4*states[10] - variables[184] = variables[162]*variables[163]*states[11]*(states[14]-variables[122]) - rates[14] = -1.0/variables[111]*(variables[183]+variables[135]+variables[145]+variables[156]+variables[157]+variables[184]+variables[171]+variables[175]+variables[177]+variables[180]+variables[182]+variables[181]+variables[116]+variables[118]+variables[120]) + variables[9] = variables[62]*pow(variables[56]/(variables[71]+variables[56]), 3.0)*pow(variables[69]/(variables[70]+variables[69]), 2.0)*1.6/(1.5+exp(-(states[0]+60.0)/40.0)) + variables[10] = variables[49]*(pow(variables[56], 3.0)*variables[58]*exp(0.03743*states[0]*variables[57])-pow(variables[59], 3.0)*variables[60]*exp(0.0374*states[0]*(variables[57]-1.0)))/(1.0+variables[61]*(variables[60]*pow(variables[59], 3.0)+variables[58]*pow(variables[56], 3.0))) if eq_func(variables[2], 0.0) else variables[49]*(pow(variables[56], 3.0)*variables[58]*exp(0.03743*states[0]*variables[57])-pow(variables[59], 3.0)*variables[60]*exp(0.03743*states[0]*(variables[57]-1.0)))/(1.0+variables[61]*(variables[60]*pow(variables[59], 3.0)+variables[58]*pow(variables[56], 3.0))) + variables[14] = variables[176]*states[14]*(states[0]-variables[40]) if neq_func(variables[2], 2.0) else variables[176]*states[14]*(states[0]+102.0) + variables[15] = variables[169]*states[14]*(states[0]-variables[32]) if neq_func(variables[2], 2.0) else variables[169]*states[14]*(states[0]-77.6) + variables[16] = variables[160]*pow(states[13], 2.0)*(states[0]-variables[80]) + variables[18] = variables[135]*states[8]*(states[0]-variables[40]) + variables[19] = variables[128]*states[9]*states[8]*(states[0]-variables[40]) + variables[20] = variables[112]*states[7]*states[6]*(states[0]-variables[119]) + variables[21] = variables[96]*(states[4]*states[5]+0.006/(1.0+exp(-(states[0]+14.1)/6.0)))*(states[0]-variables[103]) + variables[91] = 0.0952*exp(-0.063*(states[0]+34.4))/(1.0+1.66*exp(-0.225*(states[0]+63.7)))+0.0869 if eq_func(variables[2], 0.0) else 0.09518*exp(-0.06306*(states[0]+34.4))/(1.0+1.662*exp(-0.2251*(states[0]+63.7)))+0.08693 + variables[88] = (1.0-variables[91])*states[2]+variables[91]*states[3] + variables[7] = variables[81]*pow(states[1], 3.0)*variables[88]*variables[59]*pow(variables[24], 2.0)/(variables[22]*variables[23])*(exp((states[0]-variables[32])*variables[24]/(variables[22]*variables[23]))-1.0)/(exp(states[0]*variables[24]/(variables[22]*variables[23]))-1.0)*states[0] + variables[11] = variables[33]*(states[0]-variables[40]) + variables[12] = variables[41]*(states[0]-variables[48]) + variables[13] = variables[25]*(states[0]-variables[32]) + variables[153] = 0.6*states[11]+0.4*states[12] + variables[17] = variables[146]*variables[153]*states[10]*(states[0]-variables[40]) + rates[0] = -1.0/variables[4]*(variables[7]+variables[21]+variables[20]+variables[19]+variables[18]+variables[17]+variables[16]+variables[15]+variables[14]+variables[13]+variables[12]+variables[11]+variables[10]+variables[9]+variables[8]) + variables[89] = pow(1.0/(1.0+exp(-states[0]/5.46)), 1.0/3.0) if eq_func(variables[2], 0.0) else pow(1.0/(1.0+exp(-(states[0]+30.32)/5.46)), 1.0/3.0) + variables[90] = 0.0006247/(0.832*exp(-0.335*(states[0]+56.7))+0.627*exp(0.082*(states[0]+65.01)))+4.0e-5 if eq_func(variables[2], 0.0) else 0.0006247/(0.8322166*exp(-0.33566*(states[0]+56.7062))+0.6274*exp(0.0823*(states[0]+65.0131)))+4.569e-5 + rates[1] = (variables[89]-states[1])/variables[90] + variables[92] = 1.0/(1.0+exp((states[0]+66.1)/6.4)) + variables[93] = 3.717e-6*exp(-0.2815*(states[0]+17.11))/(1.0+0.003732*exp(-0.3426*(states[0]+37.76)))+0.0005977 + rates[2] = (variables[92]-states[2])/variables[93] + variables[94] = variables[92] + variables[95] = 3.186e-8*exp(-0.6219*(states[0]+18.8))/(1.0+7.189e-5*exp(-0.6683*(states[0]+34.07)))+0.003556 + rates[3] = (variables[94]-states[3])/variables[95] + variables[104] = 1.0/(1.0+exp(-(states[0]+23.1)/6.0)) if eq_func(variables[2], 0.0) else 1.0/(1.0+exp(-(states[0]+22.3+0.8*variables[0])/6.0)) if eq_func(variables[2], 1.0) else 1.0/(1.0+exp(-(states[0]+22.2)/6.0)) + variables[106] = -28.38*(states[0]+35.0)/(exp(-(states[0]+35.0)/2.5)-1.0)-84.9*states[0]/(exp(-0.208*states[0])-1.0) if eq_func(variables[2], 0.0) else -28.39*(states[0]+35.0)/(exp(-(states[0]+35.0)/2.5)-1.0)-84.9*states[0]/(exp(-0.208*states[0])-1.0) if eq_func(variables[2], 1.0) else -28.4*(states[0]+35.0)/(exp(-(states[0]+35.0)/2.5)-1.0)-84.9*states[0]/(exp(-0.208*states[0])-1.0) + variables[107] = 11.43*(states[0]-5.0)/(exp(0.4*(states[0]-5.0))-1.0) if eq_func(variables[2], 1.0) else 11.42*(states[0]-5.0)/(exp(0.4*(states[0]-5.0))-1.0) + variables[105] = 2.0/(variables[106]+variables[107]) + rates[5] = (variables[104]-states[5])/variables[105] + variables[108] = 1.0/(1.0+exp((states[0]+45.0)/5.0)) + variables[110] = 3.75*(states[0]+28.0)/(exp((states[0]+28.0)/4.0)-1.0) if eq_func(variables[2], 1.0) else 3.12*(states[0]+28.0)/(exp((states[0]+28.0)/4.0)-1.0) + variables[111] = 30.0/(1.0+exp(-(states[0]+28.0)/4.0)) if eq_func(variables[2], 1.0) else 25.0/(1.0+exp(-(states[0]+28.0)/4.0)) + variables[109] = (1.2-0.2*variables[0])/(variables[110]+variables[111]) if eq_func(variables[2], 1.0) else 1.0/(variables[110]+variables[111]) + rates[4] = (variables[108]-states[4])/variables[109] + variables[120] = 1.0/(1.0+exp(-(states[0]+37.0)/6.8)) + variables[122] = 1068.0*exp((states[0]+26.3)/30.0) + variables[123] = 1068.0*exp(-(states[0]+26.3)/30.0) + variables[121] = 1.0/(variables[122]+variables[123]) + rates[7] = (variables[120]-states[7])/variables[121] + variables[124] = 1.0/(1.0+exp((states[0]+71.0)/9.0)) + variables[126] = 15.3*exp(-(states[0]+71.0+0.7*variables[0])/83.3) if eq_func(variables[2], 1.0) else 15.3*exp(-(states[0]+71.7)/83.3) + variables[127] = 15.0*exp((states[0]+71.0)/15.38) if eq_func(variables[2], 1.0) else 15.0*exp((states[0]+71.7)/15.38) + variables[125] = 1.0/(variables[126]+variables[127]) + rates[6] = (variables[124]-states[6])/variables[125] + variables[142] = 1.0/(1.0+exp((states[0]+59.37)/13.1)) + variables[143] = 0.0101+0.06517/(0.57*exp(-0.08*(states[0]+49.0)))+2.4e-5*exp(0.1*(states[0]+50.93)) if eq_func(variables[2], 0.0) else 0.001/3.0*(30.31+195.5/(0.5686*exp(-0.08161*(states[0]+39.0+10.0*variables[0]))+0.7174*exp((0.2719-0.1719*variables[0])*1.0*(states[0]+40.93+10.0*variables[0])))) if eq_func(variables[2], 1.0) else 0.0101+0.06517/(0.5686*exp(-0.08161*(states[0]+39.0))+0.7174*exp(0.2719*(states[0]+40.93))) + rates[9] = (variables[142]-states[9])/variables[143] + variables[144] = 1.0/(1.0+exp(-(states[0]-10.93)/19.7)) + variables[145] = 0.001*(2.98+15.59/(1.037*exp(0.09*(states[0]+30.61))+0.369*exp(-0.12*(states[0]+23.84)))) if eq_func(variables[2], 0.0) else 0.0025*(1.191+7.838/(1.037*exp(0.09012*(states[0]+30.61))+0.369*exp(-0.119*(states[0]+23.84)))) if eq_func(variables[2], 1.0) else 0.001*(2.98+19.59/(1.037*exp(0.09012*(states[0]+30.61))+0.369*exp(-0.119*(states[0]+23.84)))) + rates[8] = (variables[144]-states[8])/variables[145] + variables[154] = 1.0/(1.0+exp(-(states[0]+14.2)/10.6)) if neq_func(variables[2], 2.0) else 1.0/(1.0+exp(-(states[0]+13.2)/10.6)) + variables[155] = 1.0/(37.2*exp((states[0]-9.0)/15.9)+0.96*exp(-(states[0]-9.0)/22.5)) if neq_func(variables[2], 2.0) else 1.0/(37.2*exp((states[0]-10.0)/15.9)+0.96*exp(-(states[0]-10.0)/22.5)) + rates[11] = (variables[154]-states[11])/variables[155] + variables[156] = variables[154] + variables[157] = 1.0/(4.2*exp((states[0]-9.0)/17.0)+0.15*exp(-(states[0]-9.0)/21.6)) if neq_func(variables[2], 2.0) else 1.0/(4.2*exp((states[0]-10.0)/17.0)+0.15*exp(-(states[0]-10.0)/21.6)) + rates[12] = (variables[156]-states[12])/variables[157] + variables[159] = 1.0/(1.0+exp((states[0]+18.6)/10.1)) + rates[10] = (variables[159]-states[10])/variables[158] + variables[167] = 14.0/(1.0+exp(-(states[0]-40.0)/9.0)) + variables[168] = 1.0*exp(-states[0]/45.0) + rates[13] = variables[167]*(1.0-states[13])-variables[168]*states[13] + variables[183] = 1.0*exp(-(states[0]+78.91)/26.62) if eq_func(variables[2], 0.0) else 1.0*exp(-(states[0]+78.91)/26.63) + variables[184] = 1.0*exp((states[0]+75.13)/21.25) + rates[14] = variables[183]*(1.0-states[14])-variables[184]*states[14] def compute_variables(voi, states, rates, variables): - variables[116] = variables[115]*(pow(variables[48], 3.0)*variables[45]*exp(0.03743*states[14]*variables[89])-pow(variables[49], 3.0)*variables[44]*exp(0.0374*states[14]*(variables[89]-1.0)))/(1.0+variables[88]*(variables[44]*pow(variables[49], 3.0)+variables[45]*pow(variables[48], 3.0))) if eq_func(variables[56], 0.0) else variables[115]*(pow(variables[48], 3.0)*variables[45]*exp(0.03743*states[14]*variables[89])-pow(variables[49], 3.0)*variables[44]*exp(0.03743*states[14]*(variables[89]-1.0)))/(1.0+variables[88]*(variables[44]*pow(variables[49], 3.0)+variables[45]*pow(variables[48], 3.0))) - variables[118] = variables[117]*pow(variables[48]/(variables[103]+variables[48]), 3.0)*pow(variables[47]/(variables[102]+variables[47]), 2.0)*1.6/(1.5+exp(-(states[14]+60.0)/40.0)) - variables[126] = pow(1.0/(1.0+exp(-states[14]/5.46)), 1.0/3.0) if eq_func(variables[56], 0.0) else pow(1.0/(1.0+exp(-(states[14]+30.32)/5.46)), 1.0/3.0) - variables[127] = 0.0006247/(0.832*exp(-0.335*(states[14]+56.7))+0.627*exp(0.082*(states[14]+65.01)))+4.0e-5 if eq_func(variables[56], 0.0) else 0.0006247/(0.8322166*exp(-0.33566*(states[14]+56.7062))+0.6274*exp(0.0823*(states[14]+65.0131)))+4.569e-5 - variables[128] = 0.0952*exp(-0.063*(states[14]+34.4))/(1.0+1.66*exp(-0.225*(states[14]+63.7)))+0.0869 if eq_func(variables[56], 0.0) else 0.09518*exp(-0.06306*(states[14]+34.4))/(1.0+1.662*exp(-0.2251*(states[14]+63.7)))+0.08693 - variables[129] = (1.0-variables[128])*states[1]+variables[128]*states[2] - variables[130] = 1.0/(1.0+exp((states[14]+66.1)/6.4)) - variables[131] = variables[130] - variables[132] = 3.717e-6*exp(-0.2815*(states[14]+17.11))/(1.0+0.003732*exp(-0.3426*(states[14]+37.76)))+0.0005977 - variables[133] = 3.186e-8*exp(-0.6219*(states[14]+18.8))/(1.0+7.189e-5*exp(-0.6683*(states[14]+34.07)))+0.003556 - variables[135] = variables[134]*(states[4]*states[3]+0.006/(1.0+exp(-(states[14]+14.1)/6.0)))*(states[14]-variables[0]) - variables[136] = -28.38*(states[14]+35.0)/(exp(-(states[14]+35.0)/2.5)-1.0)-84.9*states[14]/(exp(-0.208*states[14])-1.0) if eq_func(variables[56], 0.0) else -28.39*(states[14]+35.0)/(exp(-(states[14]+35.0)/2.5)-1.0)-84.9*states[14]/(exp(-0.208*states[14])-1.0) if eq_func(variables[56], 1.0) else -28.4*(states[14]+35.0)/(exp(-(states[14]+35.0)/2.5)-1.0)-84.9*states[14]/(exp(-0.208*states[14])-1.0) - variables[137] = 11.43*(states[14]-5.0)/(exp(0.4*(states[14]-5.0))-1.0) if eq_func(variables[56], 1.0) else 11.42*(states[14]-5.0)/(exp(0.4*(states[14]-5.0))-1.0) - variables[138] = 2.0/(variables[136]+variables[137]) - variables[139] = 1.0/(1.0+exp(-(states[14]+23.1)/6.0)) if eq_func(variables[56], 0.0) else 1.0/(1.0+exp(-(states[14]+22.3+0.8*variables[110])/6.0)) if eq_func(variables[56], 1.0) else 1.0/(1.0+exp(-(states[14]+22.2)/6.0)) - variables[140] = 3.75*(states[14]+28.0)/(exp((states[14]+28.0)/4.0)-1.0) if eq_func(variables[56], 1.0) else 3.12*(states[14]+28.0)/(exp((states[14]+28.0)/4.0)-1.0) - variables[141] = 30.0/(1.0+exp(-(states[14]+28.0)/4.0)) if eq_func(variables[56], 1.0) else 25.0/(1.0+exp(-(states[14]+28.0)/4.0)) - variables[142] = (1.2-0.2*variables[110])/(variables[140]+variables[141]) if eq_func(variables[56], 1.0) else 1.0/(variables[140]+variables[141]) - variables[143] = 1.0/(1.0+exp((states[14]+45.0)/5.0)) - variables[145] = variables[144]*states[5]*states[6]*(states[14]-variables[7]) - variables[146] = 1068.0*exp((states[14]+26.3)/30.0) - variables[147] = 1068.0*exp(-(states[14]+26.3)/30.0) - variables[148] = 1.0/(variables[146]+variables[147]) - variables[149] = 1.0/(1.0+exp(-(states[14]+37.0)/6.8)) - variables[150] = 15.3*exp(-(states[14]+71.0+0.7*variables[110])/83.3) if eq_func(variables[56], 1.0) else 15.3*exp(-(states[14]+71.7)/83.3) - variables[151] = 15.0*exp((states[14]+71.0)/15.38) if eq_func(variables[56], 1.0) else 15.0*exp((states[14]+71.7)/15.38) - variables[152] = 1.0/(variables[150]+variables[151]) - variables[153] = 1.0/(1.0+exp((states[14]+71.0)/9.0)) - variables[156] = variables[154]*states[7]*states[8]*(states[14]-variables[122]) - variables[157] = variables[155]*states[8]*(states[14]-variables[122]) - variables[158] = 1.0/(1.0+exp((states[14]+59.37)/13.1)) - variables[159] = 0.0101+0.06517/(0.57*exp(-0.08*(states[14]+49.0)))+2.4e-5*exp(0.1*(states[14]+50.93)) if eq_func(variables[56], 0.0) else 0.001/3.0*(30.31+195.5/(0.5686*exp(-0.08161*(states[14]+39.0+10.0*variables[110]))+0.7174*exp((0.2719-0.1719*variables[110])*1.0*(states[14]+40.93+10.0*variables[110])))) if eq_func(variables[56], 1.0) else 0.0101+0.06517/(0.5686*exp(-0.08161*(states[14]+39.0))+0.7174*exp(0.2719*(states[14]+40.93))) - variables[160] = 1.0/(1.0+exp(-(states[14]-10.93)/19.7)) - variables[161] = 0.001*(2.98+15.59/(1.037*exp(0.09*(states[14]+30.61))+0.369*exp(-0.12*(states[14]+23.84)))) if eq_func(variables[56], 0.0) else 0.0025*(1.191+7.838/(1.037*exp(0.09012*(states[14]+30.61))+0.369*exp(-0.119*(states[14]+23.84)))) if eq_func(variables[56], 1.0) else 0.001*(2.98+19.59/(1.037*exp(0.09012*(states[14]+30.61))+0.369*exp(-0.119*(states[14]+23.84)))) - variables[163] = 0.6*states[9]+0.4*states[10] - variables[164] = 1.0/(1.0+exp(-(states[14]+14.2)/10.6)) if neq_func(variables[56], 2.0) else 1.0/(1.0+exp(-(states[14]+13.2)/10.6)) - variables[165] = 1.0/(37.2*exp((states[14]-9.0)/15.9)+0.96*exp(-(states[14]-9.0)/22.5)) if neq_func(variables[56], 2.0) else 1.0/(37.2*exp((states[14]-10.0)/15.9)+0.96*exp(-(states[14]-10.0)/22.5)) - variables[166] = variables[164] - variables[167] = 1.0/(4.2*exp((states[14]-9.0)/17.0)+0.15*exp(-(states[14]-9.0)/21.6)) if neq_func(variables[56], 2.0) else 1.0/(4.2*exp((states[14]-10.0)/17.0)+0.15*exp(-(states[14]-10.0)/21.6)) - variables[169] = 1.0/(1.0+exp((states[14]+18.6)/10.1)) - variables[171] = variables[170]*pow(states[12], 2.0)*(states[14]-variables[124]) - variables[172] = 14.0/(1.0+exp(-(states[14]-40.0)/9.0)) - variables[173] = 1.0*exp(-states[14]/45.0) - variables[175] = variables[174]*states[13]*(states[14]-variables[121]) if neq_func(variables[56], 2.0) else variables[174]*states[13]*(states[14]-77.6) - variables[177] = variables[176]*states[13]*(states[14]-variables[122]) if neq_func(variables[56], 2.0) else variables[176]*states[13]*(states[14]+102.0) - variables[178] = 1.0*exp(-(states[14]+78.91)/26.62) if eq_func(variables[56], 0.0) else 1.0*exp(-(states[14]+78.91)/26.63) - variables[179] = 1.0*exp((states[14]+75.13)/21.25) - variables[180] = variables[112]*(states[14]-variables[121]) - variables[181] = variables[113]*(states[14]-variables[122]) - variables[182] = variables[114]*(states[14]-variables[123]) - variables[183] = variables[125]*pow(states[0], 3.0)*variables[129]*variables[49]*pow(variables[52], 2.0)/(variables[54]*variables[55])*(exp((states[14]-variables[121])*variables[52]/(variables[54]*variables[55]))-1.0)/(exp(states[14]*variables[52]/(variables[54]*variables[55]))-1.0)*states[14] - variables[184] = variables[162]*variables[163]*states[11]*(states[14]-variables[122]) + variables[13] = variables[25]*(states[0]-variables[32]) + variables[11] = variables[33]*(states[0]-variables[40]) + variables[12] = variables[41]*(states[0]-variables[48]) + variables[10] = variables[49]*(pow(variables[56], 3.0)*variables[58]*exp(0.03743*states[0]*variables[57])-pow(variables[59], 3.0)*variables[60]*exp(0.0374*states[0]*(variables[57]-1.0)))/(1.0+variables[61]*(variables[60]*pow(variables[59], 3.0)+variables[58]*pow(variables[56], 3.0))) if eq_func(variables[2], 0.0) else variables[49]*(pow(variables[56], 3.0)*variables[58]*exp(0.03743*states[0]*variables[57])-pow(variables[59], 3.0)*variables[60]*exp(0.03743*states[0]*(variables[57]-1.0)))/(1.0+variables[61]*(variables[60]*pow(variables[59], 3.0)+variables[58]*pow(variables[56], 3.0))) + variables[9] = variables[62]*pow(variables[56]/(variables[71]+variables[56]), 3.0)*pow(variables[69]/(variables[70]+variables[69]), 2.0)*1.6/(1.5+exp(-(states[0]+60.0)/40.0)) + variables[91] = 0.0952*exp(-0.063*(states[0]+34.4))/(1.0+1.66*exp(-0.225*(states[0]+63.7)))+0.0869 if eq_func(variables[2], 0.0) else 0.09518*exp(-0.06306*(states[0]+34.4))/(1.0+1.662*exp(-0.2251*(states[0]+63.7)))+0.08693 + variables[88] = (1.0-variables[91])*states[2]+variables[91]*states[3] + variables[7] = variables[81]*pow(states[1], 3.0)*variables[88]*variables[59]*pow(variables[24], 2.0)/(variables[22]*variables[23])*(exp((states[0]-variables[32])*variables[24]/(variables[22]*variables[23]))-1.0)/(exp(states[0]*variables[24]/(variables[22]*variables[23]))-1.0)*states[0] + variables[89] = pow(1.0/(1.0+exp(-states[0]/5.46)), 1.0/3.0) if eq_func(variables[2], 0.0) else pow(1.0/(1.0+exp(-(states[0]+30.32)/5.46)), 1.0/3.0) + variables[90] = 0.0006247/(0.832*exp(-0.335*(states[0]+56.7))+0.627*exp(0.082*(states[0]+65.01)))+4.0e-5 if eq_func(variables[2], 0.0) else 0.0006247/(0.8322166*exp(-0.33566*(states[0]+56.7062))+0.6274*exp(0.0823*(states[0]+65.0131)))+4.569e-5 + variables[92] = 1.0/(1.0+exp((states[0]+66.1)/6.4)) + variables[94] = variables[92] + variables[93] = 3.717e-6*exp(-0.2815*(states[0]+17.11))/(1.0+0.003732*exp(-0.3426*(states[0]+37.76)))+0.0005977 + variables[95] = 3.186e-8*exp(-0.6219*(states[0]+18.8))/(1.0+7.189e-5*exp(-0.6683*(states[0]+34.07)))+0.003556 + variables[21] = variables[96]*(states[4]*states[5]+0.006/(1.0+exp(-(states[0]+14.1)/6.0)))*(states[0]-variables[103]) + variables[106] = -28.38*(states[0]+35.0)/(exp(-(states[0]+35.0)/2.5)-1.0)-84.9*states[0]/(exp(-0.208*states[0])-1.0) if eq_func(variables[2], 0.0) else -28.39*(states[0]+35.0)/(exp(-(states[0]+35.0)/2.5)-1.0)-84.9*states[0]/(exp(-0.208*states[0])-1.0) if eq_func(variables[2], 1.0) else -28.4*(states[0]+35.0)/(exp(-(states[0]+35.0)/2.5)-1.0)-84.9*states[0]/(exp(-0.208*states[0])-1.0) + variables[107] = 11.43*(states[0]-5.0)/(exp(0.4*(states[0]-5.0))-1.0) if eq_func(variables[2], 1.0) else 11.42*(states[0]-5.0)/(exp(0.4*(states[0]-5.0))-1.0) + variables[105] = 2.0/(variables[106]+variables[107]) + variables[104] = 1.0/(1.0+exp(-(states[0]+23.1)/6.0)) if eq_func(variables[2], 0.0) else 1.0/(1.0+exp(-(states[0]+22.3+0.8*variables[0])/6.0)) if eq_func(variables[2], 1.0) else 1.0/(1.0+exp(-(states[0]+22.2)/6.0)) + variables[110] = 3.75*(states[0]+28.0)/(exp((states[0]+28.0)/4.0)-1.0) if eq_func(variables[2], 1.0) else 3.12*(states[0]+28.0)/(exp((states[0]+28.0)/4.0)-1.0) + variables[111] = 30.0/(1.0+exp(-(states[0]+28.0)/4.0)) if eq_func(variables[2], 1.0) else 25.0/(1.0+exp(-(states[0]+28.0)/4.0)) + variables[109] = (1.2-0.2*variables[0])/(variables[110]+variables[111]) if eq_func(variables[2], 1.0) else 1.0/(variables[110]+variables[111]) + variables[108] = 1.0/(1.0+exp((states[0]+45.0)/5.0)) + variables[20] = variables[112]*states[7]*states[6]*(states[0]-variables[119]) + variables[122] = 1068.0*exp((states[0]+26.3)/30.0) + variables[123] = 1068.0*exp(-(states[0]+26.3)/30.0) + variables[121] = 1.0/(variables[122]+variables[123]) + variables[120] = 1.0/(1.0+exp(-(states[0]+37.0)/6.8)) + variables[126] = 15.3*exp(-(states[0]+71.0+0.7*variables[0])/83.3) if eq_func(variables[2], 1.0) else 15.3*exp(-(states[0]+71.7)/83.3) + variables[127] = 15.0*exp((states[0]+71.0)/15.38) if eq_func(variables[2], 1.0) else 15.0*exp((states[0]+71.7)/15.38) + variables[125] = 1.0/(variables[126]+variables[127]) + variables[124] = 1.0/(1.0+exp((states[0]+71.0)/9.0)) + variables[19] = variables[128]*states[9]*states[8]*(states[0]-variables[40]) + variables[18] = variables[135]*states[8]*(states[0]-variables[40]) + variables[142] = 1.0/(1.0+exp((states[0]+59.37)/13.1)) + variables[143] = 0.0101+0.06517/(0.57*exp(-0.08*(states[0]+49.0)))+2.4e-5*exp(0.1*(states[0]+50.93)) if eq_func(variables[2], 0.0) else 0.001/3.0*(30.31+195.5/(0.5686*exp(-0.08161*(states[0]+39.0+10.0*variables[0]))+0.7174*exp((0.2719-0.1719*variables[0])*1.0*(states[0]+40.93+10.0*variables[0])))) if eq_func(variables[2], 1.0) else 0.0101+0.06517/(0.5686*exp(-0.08161*(states[0]+39.0))+0.7174*exp(0.2719*(states[0]+40.93))) + variables[144] = 1.0/(1.0+exp(-(states[0]-10.93)/19.7)) + variables[145] = 0.001*(2.98+15.59/(1.037*exp(0.09*(states[0]+30.61))+0.369*exp(-0.12*(states[0]+23.84)))) if eq_func(variables[2], 0.0) else 0.0025*(1.191+7.838/(1.037*exp(0.09012*(states[0]+30.61))+0.369*exp(-0.119*(states[0]+23.84)))) if eq_func(variables[2], 1.0) else 0.001*(2.98+19.59/(1.037*exp(0.09012*(states[0]+30.61))+0.369*exp(-0.119*(states[0]+23.84)))) + variables[153] = 0.6*states[11]+0.4*states[12] + variables[17] = variables[146]*variables[153]*states[10]*(states[0]-variables[40]) + variables[154] = 1.0/(1.0+exp(-(states[0]+14.2)/10.6)) if neq_func(variables[2], 2.0) else 1.0/(1.0+exp(-(states[0]+13.2)/10.6)) + variables[155] = 1.0/(37.2*exp((states[0]-9.0)/15.9)+0.96*exp(-(states[0]-9.0)/22.5)) if neq_func(variables[2], 2.0) else 1.0/(37.2*exp((states[0]-10.0)/15.9)+0.96*exp(-(states[0]-10.0)/22.5)) + variables[156] = variables[154] + variables[157] = 1.0/(4.2*exp((states[0]-9.0)/17.0)+0.15*exp(-(states[0]-9.0)/21.6)) if neq_func(variables[2], 2.0) else 1.0/(4.2*exp((states[0]-10.0)/17.0)+0.15*exp(-(states[0]-10.0)/21.6)) + variables[159] = 1.0/(1.0+exp((states[0]+18.6)/10.1)) + variables[16] = variables[160]*pow(states[13], 2.0)*(states[0]-variables[80]) + variables[167] = 14.0/(1.0+exp(-(states[0]-40.0)/9.0)) + variables[168] = 1.0*exp(-states[0]/45.0) + variables[15] = variables[169]*states[14]*(states[0]-variables[32]) if neq_func(variables[2], 2.0) else variables[169]*states[14]*(states[0]-77.6) + variables[14] = variables[176]*states[14]*(states[0]-variables[40]) if neq_func(variables[2], 2.0) else variables[176]*states[14]*(states[0]+102.0) + variables[183] = 1.0*exp(-(states[0]+78.91)/26.62) if eq_func(variables[2], 0.0) else 1.0*exp(-(states[0]+78.91)/26.63) + variables[184] = 1.0*exp((states[0]+75.13)/21.25) diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.c index 5a3645276..874d5755c 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.algebraic.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 4; const size_t VARIABLE_COUNT = 18; @@ -14,41 +14,53 @@ const size_t VARIABLE_COUNT = 18; const VariableInfo VOI_INFO = {"time", "millisecond", "environment", VARIABLE_OF_INTEGRATION}; const VariableInfo STATE_INFO[] = { - {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"V", "millivolt", "membrane", STATE}, {"h", "dimensionless", "sodium_channel_h_gate", STATE}, - {"n", "dimensionless", "potassium_channel_n_gate", STATE}, - {"V", "millivolt", "membrane", STATE} + {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"n", "dimensionless", "potassium_channel_n_gate", STATE} }; const VariableInfo VARIABLE_INFO[] = { - {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, + {"i_Stim", "microA_per_cm2", "membrane", EXTERNAL}, + {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, {"Cm", "microF_per_cm2", "membrane", CONSTANT}, {"E_R", "millivolt", "membrane", CONSTANT}, - {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, - {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, - {"i_Stim", "microA_per_cm2", "membrane", EXTERNAL}, {"E_L", "millivolt", "leakage_current", COMPUTED_CONSTANT}, - {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, {"E_Na", "millivolt", "sodium_channel", COMPUTED_CONSTANT}, - {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, + {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, {"alpha_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"beta_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"alpha_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"beta_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"E_K", "millivolt", "potassium_channel", COMPUTED_CONSTANT}, - {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, {"alpha_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC}, {"beta_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -56,55 +68,55 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable) +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[0] = 0.3; - variables[1] = 1.0; - variables[2] = 0.0; - variables[3] = 36.0; - variables[4] = 120.0; - states[0] = 0.05; + variables[4] = 1.0; + variables[5] = 0.0; + variables[7] = 0.3; + variables[9] = 120.0; + variables[15] = 36.0; + states[0] = 0.0; states[1] = 0.6; - states[2] = 0.325; - states[3] = 0.0; - variables[5] = externalVariable(voi, states, variables, 5); + states[2] = 0.05; + states[3] = 0.325; + variables[0] = externalVariable(voi, states, rates, variables, 0); } void computeComputedConstants(double *variables) { - variables[6] = variables[2]-10.613; - variables[8] = variables[2]-115.0; - variables[14] = variables[2]+12.0; + variables[6] = variables[5]-10.613; + variables[8] = variables[5]-115.0; + variables[14] = variables[5]+12.0; } void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0]; - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); + variables[0] = externalVariable(voi, states, rates, variables, 0); + variables[1] = variables[7]*(states[0]-variables[6]); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4]; + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2]; + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1]; - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); - variables[17] = 0.125*exp(states[3]/80.0); - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2]; - variables[5] = externalVariable(voi, states, variables, 5); - variables[7] = variables[0]*(states[3]-variables[6]); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1]; + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[17] = 0.125*exp(states[0]/80.0); + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3]; } void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[5] = externalVariable(voi, states, variables, 5); - variables[7] = variables[0]*(states[3]-variables[6]); - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); - variables[17] = 0.125*exp(states[3]/80.0); + variables[0] = externalVariable(voi, states, rates, variables, 0); + variables[1] = variables[7]*(states[0]-variables[6]); + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[17] = 0.125*exp(states[0]/80.0); } diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.h index 9e5e467b6..90f2f2d76 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.h +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -34,9 +34,9 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -typedef double (* ExternalVariable)(double voi, double *states, double *variables, size_t index); +typedef double (* ExternalVariable)(double voi, double *states, double *rates, double *variables, size_t index); -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable); +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.py index 559219591..48c80dcdf 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.py +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.algebraic.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 4 VARIABLE_COUNT = 18 @@ -23,29 +23,29 @@ class VariableType(Enum): VOI_INFO = {"name": "time", "units": "millisecond", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} STATE_INFO = [ - {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE}, {"name": "h", "units": "dimensionless", "component": "sodium_channel_h_gate", "type": VariableType.STATE}, - {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE}, - {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE} + {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE} ] VARIABLE_INFO = [ - {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, + {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.EXTERNAL}, + {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, {"name": "Cm", "units": "microF_per_cm2", "component": "membrane", "type": VariableType.CONSTANT}, {"name": "E_R", "units": "millivolt", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, - {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, - {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.EXTERNAL}, {"name": "E_L", "units": "millivolt", "component": "leakage_current", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, {"name": "E_Na", "units": "millivolt", "component": "sodium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "E_K", "units": "millivolt", "component": "potassium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC} ] @@ -71,50 +71,50 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(voi, states, variables, external_variable): - variables[0] = 0.3 - variables[1] = 1.0 - variables[2] = 0.0 - variables[3] = 36.0 - variables[4] = 120.0 - states[0] = 0.05 +def initialise_variables(voi, states, rates, variables, external_variable): + variables[4] = 1.0 + variables[5] = 0.0 + variables[7] = 0.3 + variables[9] = 120.0 + variables[15] = 36.0 + states[0] = 0.0 states[1] = 0.6 - states[2] = 0.325 - states[3] = 0.0 - variables[5] = external_variable(voi, states, variables, 5) + states[2] = 0.05 + states[3] = 0.325 + variables[0] = external_variable(voi, states, rates, variables, 0) def compute_computed_constants(variables): - variables[6] = variables[2]-10.613 - variables[8] = variables[2]-115.0 - variables[14] = variables[2]+12.0 + variables[6] = variables[5]-10.613 + variables[8] = variables[5]-115.0 + variables[14] = variables[5]+12.0 def compute_rates(voi, states, rates, variables, external_variable): - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0] - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) + variables[0] = external_variable(voi, states, rates, variables, 0) + variables[1] = variables[7]*(states[0]-variables[6]) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4] + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2] + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1] - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) - variables[17] = 0.125*exp(states[3]/80.0) - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2] - variables[5] = external_variable(voi, states, variables, 5) - variables[7] = variables[0]*(states[3]-variables[6]) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1] + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[17] = 0.125*exp(states[0]/80.0) + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3] def compute_variables(voi, states, rates, variables, external_variable): - variables[5] = external_variable(voi, states, variables, 5) - variables[7] = variables[0]*(states[3]-variables[6]) - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) - variables[17] = 0.125*exp(states[3]/80.0) + variables[0] = external_variable(voi, states, rates, variables, 0) + variables[1] = variables[7]*(states[0]-variables[6]) + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[17] = 0.125*exp(states[0]/80.0) diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.c index f2f8900ca..b4bbbd744 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 4; const size_t VARIABLE_COUNT = 18; @@ -14,41 +14,53 @@ const size_t VARIABLE_COUNT = 18; const VariableInfo VOI_INFO = {"time", "millisecond", "environment", VARIABLE_OF_INTEGRATION}; const VariableInfo STATE_INFO[] = { - {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"V", "millivolt", "membrane", STATE}, {"h", "dimensionless", "sodium_channel_h_gate", STATE}, - {"n", "dimensionless", "potassium_channel_n_gate", STATE}, - {"V", "millivolt", "membrane", STATE} + {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"n", "dimensionless", "potassium_channel_n_gate", STATE} }; const VariableInfo VARIABLE_INFO[] = { - {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, + {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, + {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, {"Cm", "microF_per_cm2", "membrane", CONSTANT}, {"E_R", "millivolt", "membrane", CONSTANT}, - {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, - {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, - {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, {"E_L", "millivolt", "leakage_current", COMPUTED_CONSTANT}, - {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, {"E_Na", "millivolt", "sodium_channel", COMPUTED_CONSTANT}, - {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, + {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, {"alpha_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"beta_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"alpha_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"beta_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"E_K", "millivolt", "potassium_channel", COMPUTED_CONSTANT}, - {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, {"alpha_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC}, {"beta_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -56,53 +68,53 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { - variables[0] = 0.3; - variables[1] = 1.0; - variables[2] = 0.0; - variables[3] = 36.0; - variables[4] = 120.0; - states[0] = 0.05; + variables[4] = 1.0; + variables[5] = 0.0; + variables[7] = 0.3; + variables[9] = 120.0; + variables[15] = 36.0; + states[0] = 0.0; states[1] = 0.6; - states[2] = 0.325; - states[3] = 0.0; + states[2] = 0.05; + states[3] = 0.325; } void computeComputedConstants(double *variables) { - variables[6] = variables[2]-10.613; - variables[8] = variables[2]-115.0; - variables[14] = variables[2]+12.0; + variables[6] = variables[5]-10.613; + variables[8] = variables[5]-115.0; + variables[14] = variables[5]+12.0; } void computeRates(double voi, double *states, double *rates, double *variables) { - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0]; - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); + variables[0] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; + variables[1] = variables[7]*(states[0]-variables[6]); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4]; + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2]; + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1]; - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); - variables[17] = 0.125*exp(states[3]/80.0); - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2]; - variables[5] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; - variables[7] = variables[0]*(states[3]-variables[6]); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1]; + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[17] = 0.125*exp(states[0]/80.0); + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3]; } void computeVariables(double voi, double *states, double *rates, double *variables) { - variables[7] = variables[0]*(states[3]-variables[6]); - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); - variables[17] = 0.125*exp(states[3]/80.0); + variables[1] = variables[7]*(states[0]-variables[6]); + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[17] = 0.125*exp(states[0]/80.0); } diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.c index 2c812888c..5965c9d57 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.computed.constant.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 4; const size_t VARIABLE_COUNT = 18; @@ -14,41 +14,53 @@ const size_t VARIABLE_COUNT = 18; const VariableInfo VOI_INFO = {"time", "millisecond", "environment", VARIABLE_OF_INTEGRATION}; const VariableInfo STATE_INFO[] = { - {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"V", "millivolt", "membrane", STATE}, {"h", "dimensionless", "sodium_channel_h_gate", STATE}, - {"n", "dimensionless", "potassium_channel_n_gate", STATE}, - {"V", "millivolt", "membrane", STATE} + {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"n", "dimensionless", "potassium_channel_n_gate", STATE} }; const VariableInfo VARIABLE_INFO[] = { - {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, + {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, + {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, {"Cm", "microF_per_cm2", "membrane", CONSTANT}, {"E_R", "millivolt", "membrane", CONSTANT}, - {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, - {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, - {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, {"E_L", "millivolt", "leakage_current", EXTERNAL}, - {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, {"E_Na", "millivolt", "sodium_channel", COMPUTED_CONSTANT}, - {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, + {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, {"alpha_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"beta_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"alpha_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"beta_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"E_K", "millivolt", "potassium_channel", COMPUTED_CONSTANT}, - {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, {"alpha_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC}, {"beta_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -56,55 +68,55 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable) +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[0] = 0.3; - variables[1] = 1.0; - variables[2] = 0.0; - variables[3] = 36.0; - variables[4] = 120.0; - states[0] = 0.05; + variables[4] = 1.0; + variables[5] = 0.0; + variables[7] = 0.3; + variables[9] = 120.0; + variables[15] = 36.0; + states[0] = 0.0; states[1] = 0.6; - states[2] = 0.325; - states[3] = 0.0; - variables[6] = externalVariable(voi, states, variables, 6); + states[2] = 0.05; + states[3] = 0.325; + variables[6] = externalVariable(voi, states, rates, variables, 6); } void computeComputedConstants(double *variables) { - variables[8] = variables[2]-115.0; - variables[14] = variables[2]+12.0; + variables[8] = variables[5]-115.0; + variables[14] = variables[5]+12.0; } void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0]; - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); + variables[0] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; + variables[6] = externalVariable(voi, states, rates, variables, 6); + variables[1] = variables[7]*(states[0]-variables[6]); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4]; + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2]; + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1]; - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); - variables[17] = 0.125*exp(states[3]/80.0); - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2]; - variables[5] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; - variables[6] = externalVariable(voi, states, variables, 6); - variables[7] = variables[0]*(states[3]-variables[6]); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1]; + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[17] = 0.125*exp(states[0]/80.0); + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3]; } void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[6] = externalVariable(voi, states, variables, 6); - variables[7] = variables[0]*(states[3]-variables[6]); - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); - variables[17] = 0.125*exp(states[3]/80.0); + variables[6] = externalVariable(voi, states, rates, variables, 6); + variables[1] = variables[7]*(states[0]-variables[6]); + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[17] = 0.125*exp(states[0]/80.0); } diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.h index 9e5e467b6..90f2f2d76 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.h +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -34,9 +34,9 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -typedef double (* ExternalVariable)(double voi, double *states, double *variables, size_t index); +typedef double (* ExternalVariable)(double voi, double *states, double *rates, double *variables, size_t index); -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable); +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.py index 26016a53b..638c26a9d 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.py +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.computed.constant.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 4 VARIABLE_COUNT = 18 @@ -23,29 +23,29 @@ class VariableType(Enum): VOI_INFO = {"name": "time", "units": "millisecond", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} STATE_INFO = [ - {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE}, {"name": "h", "units": "dimensionless", "component": "sodium_channel_h_gate", "type": VariableType.STATE}, - {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE}, - {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE} + {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE} ] VARIABLE_INFO = [ - {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, + {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, + {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, {"name": "Cm", "units": "microF_per_cm2", "component": "membrane", "type": VariableType.CONSTANT}, {"name": "E_R", "units": "millivolt", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, - {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, - {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, {"name": "E_L", "units": "millivolt", "component": "leakage_current", "type": VariableType.EXTERNAL}, - {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, {"name": "E_Na", "units": "millivolt", "component": "sodium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "E_K", "units": "millivolt", "component": "potassium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC} ] @@ -71,50 +71,50 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(voi, states, variables, external_variable): - variables[0] = 0.3 - variables[1] = 1.0 - variables[2] = 0.0 - variables[3] = 36.0 - variables[4] = 120.0 - states[0] = 0.05 +def initialise_variables(voi, states, rates, variables, external_variable): + variables[4] = 1.0 + variables[5] = 0.0 + variables[7] = 0.3 + variables[9] = 120.0 + variables[15] = 36.0 + states[0] = 0.0 states[1] = 0.6 - states[2] = 0.325 - states[3] = 0.0 - variables[6] = external_variable(voi, states, variables, 6) + states[2] = 0.05 + states[3] = 0.325 + variables[6] = external_variable(voi, states, rates, variables, 6) def compute_computed_constants(variables): - variables[8] = variables[2]-115.0 - variables[14] = variables[2]+12.0 + variables[8] = variables[5]-115.0 + variables[14] = variables[5]+12.0 def compute_rates(voi, states, rates, variables, external_variable): - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0] - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) + variables[0] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 + variables[6] = external_variable(voi, states, rates, variables, 6) + variables[1] = variables[7]*(states[0]-variables[6]) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4] + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2] + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1] - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) - variables[17] = 0.125*exp(states[3]/80.0) - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2] - variables[5] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 - variables[6] = external_variable(voi, states, variables, 6) - variables[7] = variables[0]*(states[3]-variables[6]) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1] + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[17] = 0.125*exp(states[0]/80.0) + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3] def compute_variables(voi, states, rates, variables, external_variable): - variables[6] = external_variable(voi, states, variables, 6) - variables[7] = variables[0]*(states[3]-variables[6]) - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) - variables[17] = 0.125*exp(states[3]/80.0) + variables[6] = external_variable(voi, states, rates, variables, 6) + variables[1] = variables[7]*(states[0]-variables[6]) + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[17] = 0.125*exp(states[0]/80.0) diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.c index 698876915..a98bde21b 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.constant.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 4; const size_t VARIABLE_COUNT = 18; @@ -14,41 +14,53 @@ const size_t VARIABLE_COUNT = 18; const VariableInfo VOI_INFO = {"time", "millisecond", "environment", VARIABLE_OF_INTEGRATION}; const VariableInfo STATE_INFO[] = { - {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"V", "millivolt", "membrane", STATE}, {"h", "dimensionless", "sodium_channel_h_gate", STATE}, - {"n", "dimensionless", "potassium_channel_n_gate", STATE}, - {"V", "millivolt", "membrane", STATE} + {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"n", "dimensionless", "potassium_channel_n_gate", STATE} }; const VariableInfo VARIABLE_INFO[] = { - {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, + {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, + {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, {"Cm", "microF_per_cm2", "membrane", EXTERNAL}, {"E_R", "millivolt", "membrane", CONSTANT}, - {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, - {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, - {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, {"E_L", "millivolt", "leakage_current", COMPUTED_CONSTANT}, - {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, {"E_Na", "millivolt", "sodium_channel", COMPUTED_CONSTANT}, - {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, + {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, {"alpha_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"beta_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"alpha_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"beta_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"E_K", "millivolt", "potassium_channel", COMPUTED_CONSTANT}, - {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, {"alpha_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC}, {"beta_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -56,55 +68,55 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable) +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[0] = 0.3; - variables[2] = 0.0; - variables[3] = 36.0; - variables[4] = 120.0; - states[0] = 0.05; + variables[5] = 0.0; + variables[7] = 0.3; + variables[9] = 120.0; + variables[15] = 36.0; + states[0] = 0.0; states[1] = 0.6; - states[2] = 0.325; - states[3] = 0.0; - variables[1] = externalVariable(voi, states, variables, 1); + states[2] = 0.05; + states[3] = 0.325; + variables[4] = externalVariable(voi, states, rates, variables, 4); } void computeComputedConstants(double *variables) { - variables[6] = variables[2]-10.613; - variables[8] = variables[2]-115.0; - variables[14] = variables[2]+12.0; + variables[6] = variables[5]-10.613; + variables[8] = variables[5]-115.0; + variables[14] = variables[5]+12.0; } void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0]; - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); + variables[0] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; + variables[4] = externalVariable(voi, states, rates, variables, 4); + variables[1] = variables[7]*(states[0]-variables[6]); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4]; + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2]; + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1]; - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); - variables[17] = 0.125*exp(states[3]/80.0); - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2]; - variables[5] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; - variables[1] = externalVariable(voi, states, variables, 1); - variables[7] = variables[0]*(states[3]-variables[6]); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1]; + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[17] = 0.125*exp(states[0]/80.0); + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3]; } void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[1] = externalVariable(voi, states, variables, 1); - variables[7] = variables[0]*(states[3]-variables[6]); - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); - variables[17] = 0.125*exp(states[3]/80.0); + variables[1] = variables[7]*(states[0]-variables[6]); + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[17] = 0.125*exp(states[0]/80.0); + variables[4] = externalVariable(voi, states, rates, variables, 4); } diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.h index 9e5e467b6..90f2f2d76 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.h +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -34,9 +34,9 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -typedef double (* ExternalVariable)(double voi, double *states, double *variables, size_t index); +typedef double (* ExternalVariable)(double voi, double *states, double *rates, double *variables, size_t index); -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable); +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.py index b7b75bbd8..0a44cad71 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.py +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.constant.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 4 VARIABLE_COUNT = 18 @@ -23,29 +23,29 @@ class VariableType(Enum): VOI_INFO = {"name": "time", "units": "millisecond", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} STATE_INFO = [ - {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE}, {"name": "h", "units": "dimensionless", "component": "sodium_channel_h_gate", "type": VariableType.STATE}, - {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE}, - {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE} + {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE} ] VARIABLE_INFO = [ - {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, + {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, + {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, {"name": "Cm", "units": "microF_per_cm2", "component": "membrane", "type": VariableType.EXTERNAL}, {"name": "E_R", "units": "millivolt", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, - {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, - {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, {"name": "E_L", "units": "millivolt", "component": "leakage_current", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, {"name": "E_Na", "units": "millivolt", "component": "sodium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "E_K", "units": "millivolt", "component": "potassium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC} ] @@ -71,50 +71,50 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(voi, states, variables, external_variable): - variables[0] = 0.3 - variables[2] = 0.0 - variables[3] = 36.0 - variables[4] = 120.0 - states[0] = 0.05 +def initialise_variables(voi, states, rates, variables, external_variable): + variables[5] = 0.0 + variables[7] = 0.3 + variables[9] = 120.0 + variables[15] = 36.0 + states[0] = 0.0 states[1] = 0.6 - states[2] = 0.325 - states[3] = 0.0 - variables[1] = external_variable(voi, states, variables, 1) + states[2] = 0.05 + states[3] = 0.325 + variables[4] = external_variable(voi, states, rates, variables, 4) def compute_computed_constants(variables): - variables[6] = variables[2]-10.613 - variables[8] = variables[2]-115.0 - variables[14] = variables[2]+12.0 + variables[6] = variables[5]-10.613 + variables[8] = variables[5]-115.0 + variables[14] = variables[5]+12.0 def compute_rates(voi, states, rates, variables, external_variable): - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0] - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) + variables[0] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 + variables[4] = external_variable(voi, states, rates, variables, 4) + variables[1] = variables[7]*(states[0]-variables[6]) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4] + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2] + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1] - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) - variables[17] = 0.125*exp(states[3]/80.0) - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2] - variables[5] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 - variables[1] = external_variable(voi, states, variables, 1) - variables[7] = variables[0]*(states[3]-variables[6]) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1] + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[17] = 0.125*exp(states[0]/80.0) + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3] def compute_variables(voi, states, rates, variables, external_variable): - variables[1] = external_variable(voi, states, variables, 1) - variables[7] = variables[0]*(states[3]-variables[6]) - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) - variables[17] = 0.125*exp(states[3]/80.0) + variables[1] = variables[7]*(states[0]-variables[6]) + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[17] = 0.125*exp(states[0]/80.0) + variables[4] = external_variable(voi, states, rates, variables, 4) diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.c new file mode 100644 index 000000000..5d17d3d50 --- /dev/null +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.c @@ -0,0 +1,563 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.dae.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t STATE_COUNT = 4; +const size_t VARIABLE_COUNT = 18; + +const VariableInfo VOI_INFO = {"time", "millisecond", "environment", VARIABLE_OF_INTEGRATION}; + +const VariableInfo STATE_INFO[] = { + {"V", "millivolt", "membrane", STATE}, + {"h", "dimensionless", "sodium_channel_h_gate", STATE}, + {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"n", "dimensionless", "potassium_channel_n_gate", STATE} +}; + +const VariableInfo VARIABLE_INFO[] = { + {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, + {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, + {"Cm", "microF_per_cm2", "membrane", CONSTANT}, + {"E_R", "millivolt", "membrane", CONSTANT}, + {"E_L", "millivolt", "leakage_current", COMPUTED_CONSTANT}, + {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, + {"E_Na", "millivolt", "sodium_channel", COMPUTED_CONSTANT}, + {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, + {"alpha_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, + {"beta_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, + {"alpha_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, + {"beta_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, + {"E_K", "millivolt", "potassium_channel", COMPUTED_CONSTANT}, + {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, + {"alpha_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC}, + {"beta_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC} +}; + +double * createStatesArray() +{ + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +typedef struct { + double voi; + double *states; + double *rates; + double *variables; +} RootFindingInfo; + +extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *), + double *u, int n, void *data); + +void objectiveFunction0(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[0] = u[0]; + + f[0] = variables[0]-(((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0)-0.0; +} + +void findRoot0(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[0]; + + nlaSolve(objectiveFunction0, u, 1, &rfi); + + variables[0] = u[0]; +} + +void objectiveFunction1(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + rates[0] = u[0]; + + f[0] = rates[0]-(-(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4])-0.0; +} + +void findRoot1(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = rates[0]; + + nlaSolve(objectiveFunction1, u, 1, &rfi); + + rates[0] = u[0]; +} + +void objectiveFunction2(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[6] = u[0]; + + f[0] = variables[6]-(variables[5]-10.613)-0.0; +} + +void findRoot2(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[6]; + + nlaSolve(objectiveFunction2, u, 1, &rfi); + + variables[6] = u[0]; +} + +void objectiveFunction3(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[1] = u[0]; + + f[0] = variables[1]-variables[7]*(states[0]-variables[6])-0.0; +} + +void findRoot3(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[1]; + + nlaSolve(objectiveFunction3, u, 1, &rfi); + + variables[1] = u[0]; +} + +void objectiveFunction4(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[8] = u[0]; + + f[0] = variables[8]-(variables[5]-115.0)-0.0; +} + +void findRoot4(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[8]; + + nlaSolve(objectiveFunction4, u, 1, &rfi); + + variables[8] = u[0]; +} + +void objectiveFunction5(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[3] = u[0]; + + f[0] = variables[3]-variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8])-0.0; +} + +void findRoot5(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[3]; + + nlaSolve(objectiveFunction5, u, 1, &rfi); + + variables[3] = u[0]; +} + +void objectiveFunction6(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[10] = u[0]; + + f[0] = variables[10]-0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0)-0.0; +} + +void findRoot6(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[10]; + + nlaSolve(objectiveFunction6, u, 1, &rfi); + + variables[10] = u[0]; +} + +void objectiveFunction7(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[11] = u[0]; + + f[0] = variables[11]-4.0*exp(states[0]/18.0)-0.0; +} + +void findRoot7(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[11]; + + nlaSolve(objectiveFunction7, u, 1, &rfi); + + variables[11] = u[0]; +} + +void objectiveFunction8(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + rates[2] = u[0]; + + f[0] = rates[2]-(variables[10]*(1.0-states[2])-variables[11]*states[2])-0.0; +} + +void findRoot8(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = rates[2]; + + nlaSolve(objectiveFunction8, u, 1, &rfi); + + rates[2] = u[0]; +} + +void objectiveFunction9(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[12] = u[0]; + + f[0] = variables[12]-0.07*exp(states[0]/20.0)-0.0; +} + +void findRoot9(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[12]; + + nlaSolve(objectiveFunction9, u, 1, &rfi); + + variables[12] = u[0]; +} + +void objectiveFunction10(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[13] = u[0]; + + f[0] = variables[13]-1.0/(exp((states[0]+30.0)/10.0)+1.0)-0.0; +} + +void findRoot10(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[13]; + + nlaSolve(objectiveFunction10, u, 1, &rfi); + + variables[13] = u[0]; +} + +void objectiveFunction11(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + rates[1] = u[0]; + + f[0] = rates[1]-(variables[12]*(1.0-states[1])-variables[13]*states[1])-0.0; +} + +void findRoot11(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = rates[1]; + + nlaSolve(objectiveFunction11, u, 1, &rfi); + + rates[1] = u[0]; +} + +void objectiveFunction12(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[14] = u[0]; + + f[0] = variables[14]-(variables[5]+12.0)-0.0; +} + +void findRoot12(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[14]; + + nlaSolve(objectiveFunction12, u, 1, &rfi); + + variables[14] = u[0]; +} + +void objectiveFunction13(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[2] = u[0]; + + f[0] = variables[2]-variables[15]*pow(states[3], 4.0)*(states[0]-variables[14])-0.0; +} + +void findRoot13(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[2]; + + nlaSolve(objectiveFunction13, u, 1, &rfi); + + variables[2] = u[0]; +} + +void objectiveFunction14(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[16] = u[0]; + + f[0] = variables[16]-0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0)-0.0; +} + +void findRoot14(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[16]; + + nlaSolve(objectiveFunction14, u, 1, &rfi); + + variables[16] = u[0]; +} + +void objectiveFunction15(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[17] = u[0]; + + f[0] = variables[17]-0.125*exp(states[0]/80.0)-0.0; +} + +void findRoot15(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[17]; + + nlaSolve(objectiveFunction15, u, 1, &rfi); + + variables[17] = u[0]; +} + +void objectiveFunction16(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + rates[3] = u[0]; + + f[0] = rates[3]-(variables[16]*(1.0-states[3])-variables[17]*states[3])-0.0; +} + +void findRoot16(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = rates[3]; + + nlaSolve(objectiveFunction16, u, 1, &rfi); + + rates[3] = u[0]; +} + +void initialiseVariables(double *states, double *rates, double *variables) +{ + variables[0] = 0.0; + variables[1] = 0.0; + variables[2] = 0.0; + variables[3] = 0.0; + variables[4] = 1.0; + variables[5] = 0.0; + variables[6] = 0.0; + variables[7] = 0.3; + variables[8] = 0.0; + variables[9] = 120.0; + variables[10] = 0.0; + variables[11] = 0.0; + variables[12] = 0.0; + variables[13] = 0.0; + variables[14] = 0.0; + variables[15] = 36.0; + variables[16] = 0.0; + variables[17] = 0.0; + states[0] = 0.0; + states[1] = 0.6; + states[2] = 0.05; + states[3] = 0.325; + rates[0] = 0.0; + rates[1] = 0.0; + rates[2] = 0.0; + rates[3] = 0.0; +} + +void computeComputedConstants(double *variables) +{ +} + +void computeRates(double voi, double *states, double *rates, double *variables) +{ + findRoot0(voi, states, rates, variables); + findRoot2(voi, states, rates, variables); + findRoot3(voi, states, rates, variables); + findRoot14(voi, states, rates, variables); + findRoot15(voi, states, rates, variables); + findRoot16(voi, states, rates, variables); + findRoot12(voi, states, rates, variables); + findRoot13(voi, states, rates, variables); + findRoot9(voi, states, rates, variables); + findRoot10(voi, states, rates, variables); + findRoot11(voi, states, rates, variables); + findRoot6(voi, states, rates, variables); + findRoot7(voi, states, rates, variables); + findRoot8(voi, states, rates, variables); + findRoot4(voi, states, rates, variables); + findRoot5(voi, states, rates, variables); + findRoot1(voi, states, rates, variables); +} + +void computeVariables(double voi, double *states, double *rates, double *variables) +{ + findRoot0(voi, states, rates, variables); + findRoot2(voi, states, rates, variables); + findRoot3(voi, states, rates, variables); + findRoot14(voi, states, rates, variables); + findRoot15(voi, states, rates, variables); + findRoot16(voi, states, rates, variables); + findRoot12(voi, states, rates, variables); + findRoot13(voi, states, rates, variables); + findRoot9(voi, states, rates, variables); + findRoot10(voi, states, rates, variables); + findRoot11(voi, states, rates, variables); + findRoot6(voi, states, rates, variables); + findRoot7(voi, states, rates, variables); + findRoot8(voi, states, rates, variables); + findRoot4(voi, states, rates, variables); + findRoot5(voi, states, rates, variables); + findRoot1(voi, states, rates, variables); +} diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.cellml b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.cellml new file mode 100644 index 000000000..a8a773880 --- /dev/null +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.cellml @@ -0,0 +1,575 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + i_Stim + + + + + 20 + + + + + + time + 10 + + + + time + 10.5 + + + + + 0 + + + + 0 + + + + + + + + + time + + V + + + + + + + + + + i_Stim + + i_Na + i_K + i_L + + + Cm + + + 0 + + + + + + + + + + + + + + + + + + E_Na + + + E_R + 115 + + + 0 + + + + + + i_Na + + + g_Na + + + m + 3 + + h + + + V + E_Na + + + + 0 + + + + + + + + + + + + + + + alpha_m + + + + + 0.1 + + + V + 25 + + + + + + + + + + + V + 25 + + 10 + + + 1 + + + + 0 + + + + + + beta_m + + + 4 + + + + + V + 18 + + + + + 0 + + + + + + + + + time + + m + + + + + + alpha_m + + + 1 + m + + + + + beta_m + m + + + + 0 + + + + + + + + + + + + + + + alpha_h + + + 0.07 + + + + + V + 20 + + + + + 0 + + + + + + beta_h + + + 1 + + + + + + + + + V + 30 + + 10 + + + 1 + + + + 0 + + + + + + + + + time + + h + + + + + + alpha_h + + + 1 + h + + + + + beta_h + h + + + + 0 + + + + + + + + + + + + + + + + + E_K + + + E_R + 12 + + + 0 + + + + + + i_K + + + g_K + + + n + 4 + + + + V + E_K + + + + 0 + + + + + + + + + + + + + + + alpha_n + + + + + 0.01 + + + V + 10 + + + + + + + + + + + V + 10 + + 10 + + + 1 + + + + 0 + + + + + + beta_n + + + 0.125 + + + + + V + 80 + + + + + 0 + + + + + + + + + time + + n + + + + + + alpha_n + + + 1 + n + + + + + beta_n + n + + + + 0 + + + + + + + + + + + + + + + + E_L + + + E_R + 10.613 + + + 0 + + + + + + i_L + + + g_L + + + V + E_L + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.h new file mode 100644 index 000000000..a6105918a --- /dev/null +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.h @@ -0,0 +1,39 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t STATE_COUNT; +extern const size_t VARIABLE_COUNT; + +typedef enum { + VARIABLE_OF_INTEGRATION, + STATE, + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC +} VariableType; + +typedef struct { + char name[8]; + char units[16]; + char component[25]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VOI_INFO; +extern const VariableInfo STATE_INFO[]; +extern const VariableInfo VARIABLE_INFO[]; + +double * createStatesArray(); +double * createVariablesArray(); +void deleteArray(double *array); + +void initialiseVariables(double *states, double *rates, double *variables); +void computeComputedConstants(double *variables); +void computeRates(double voi, double *states, double *rates, double *variables); +void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.py new file mode 100644 index 000000000..3142e999b --- /dev/null +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dae.py @@ -0,0 +1,503 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +STATE_COUNT = 4 +VARIABLE_COUNT = 18 + + +class VariableType(Enum): + VARIABLE_OF_INTEGRATION = 0 + STATE = 1 + CONSTANT = 2 + COMPUTED_CONSTANT = 3 + ALGEBRAIC = 4 + + +VOI_INFO = {"name": "time", "units": "millisecond", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} + +STATE_INFO = [ + {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE}, + {"name": "h", "units": "dimensionless", "component": "sodium_channel_h_gate", "type": VariableType.STATE}, + {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE} +] + +VARIABLE_INFO = [ + {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, + {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "Cm", "units": "microF_per_cm2", "component": "membrane", "type": VariableType.CONSTANT}, + {"name": "E_R", "units": "millivolt", "component": "membrane", "type": VariableType.CONSTANT}, + {"name": "E_L", "units": "millivolt", "component": "leakage_current", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, + {"name": "E_Na", "units": "millivolt", "component": "sodium_channel", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, + {"name": "alpha_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, + {"name": "beta_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, + {"name": "alpha_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, + {"name": "beta_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, + {"name": "E_K", "units": "millivolt", "component": "potassium_channel", "type": VariableType.COMPUTED_CONSTANT}, + {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, + {"name": "alpha_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC}, + {"name": "beta_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC} +] + + +def leq_func(x, y): + return 1.0 if x <= y else 0.0 + + +def geq_func(x, y): + return 1.0 if x >= y else 0.0 + + +def and_func(x, y): + return 1.0 if bool(x) & bool(y) else 0.0 + + +def create_states_array(): + return [nan]*STATE_COUNT + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +from nlasolver import nla_solve + + +def objective_function_0(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[0] = u[0] + + f[0] = variables[0]-(-20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0)-0.0 + + +def find_root_0(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[0] + + u = nla_solve(objective_function_0, u, 1, [voi, states, rates, variables]) + + variables[0] = u[0] + + +def objective_function_1(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + rates[0] = u[0] + + f[0] = rates[0]-(-(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4])-0.0 + + +def find_root_1(voi, states, rates, variables): + u = [nan]*1 + + u[0] = rates[0] + + u = nla_solve(objective_function_1, u, 1, [voi, states, rates, variables]) + + rates[0] = u[0] + + +def objective_function_2(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[6] = u[0] + + f[0] = variables[6]-(variables[5]-10.613)-0.0 + + +def find_root_2(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[6] + + u = nla_solve(objective_function_2, u, 1, [voi, states, rates, variables]) + + variables[6] = u[0] + + +def objective_function_3(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[1] = u[0] + + f[0] = variables[1]-variables[7]*(states[0]-variables[6])-0.0 + + +def find_root_3(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[1] + + u = nla_solve(objective_function_3, u, 1, [voi, states, rates, variables]) + + variables[1] = u[0] + + +def objective_function_4(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[8] = u[0] + + f[0] = variables[8]-(variables[5]-115.0)-0.0 + + +def find_root_4(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[8] + + u = nla_solve(objective_function_4, u, 1, [voi, states, rates, variables]) + + variables[8] = u[0] + + +def objective_function_5(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[3] = u[0] + + f[0] = variables[3]-variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8])-0.0 + + +def find_root_5(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[3] + + u = nla_solve(objective_function_5, u, 1, [voi, states, rates, variables]) + + variables[3] = u[0] + + +def objective_function_6(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[10] = u[0] + + f[0] = variables[10]-0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0)-0.0 + + +def find_root_6(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[10] + + u = nla_solve(objective_function_6, u, 1, [voi, states, rates, variables]) + + variables[10] = u[0] + + +def objective_function_7(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[11] = u[0] + + f[0] = variables[11]-4.0*exp(states[0]/18.0)-0.0 + + +def find_root_7(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[11] + + u = nla_solve(objective_function_7, u, 1, [voi, states, rates, variables]) + + variables[11] = u[0] + + +def objective_function_8(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + rates[2] = u[0] + + f[0] = rates[2]-(variables[10]*(1.0-states[2])-variables[11]*states[2])-0.0 + + +def find_root_8(voi, states, rates, variables): + u = [nan]*1 + + u[0] = rates[2] + + u = nla_solve(objective_function_8, u, 1, [voi, states, rates, variables]) + + rates[2] = u[0] + + +def objective_function_9(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[12] = u[0] + + f[0] = variables[12]-0.07*exp(states[0]/20.0)-0.0 + + +def find_root_9(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[12] + + u = nla_solve(objective_function_9, u, 1, [voi, states, rates, variables]) + + variables[12] = u[0] + + +def objective_function_10(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[13] = u[0] + + f[0] = variables[13]-1.0/(exp((states[0]+30.0)/10.0)+1.0)-0.0 + + +def find_root_10(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[13] + + u = nla_solve(objective_function_10, u, 1, [voi, states, rates, variables]) + + variables[13] = u[0] + + +def objective_function_11(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + rates[1] = u[0] + + f[0] = rates[1]-(variables[12]*(1.0-states[1])-variables[13]*states[1])-0.0 + + +def find_root_11(voi, states, rates, variables): + u = [nan]*1 + + u[0] = rates[1] + + u = nla_solve(objective_function_11, u, 1, [voi, states, rates, variables]) + + rates[1] = u[0] + + +def objective_function_12(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[14] = u[0] + + f[0] = variables[14]-(variables[5]+12.0)-0.0 + + +def find_root_12(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[14] + + u = nla_solve(objective_function_12, u, 1, [voi, states, rates, variables]) + + variables[14] = u[0] + + +def objective_function_13(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[2] = u[0] + + f[0] = variables[2]-variables[15]*pow(states[3], 4.0)*(states[0]-variables[14])-0.0 + + +def find_root_13(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[2] + + u = nla_solve(objective_function_13, u, 1, [voi, states, rates, variables]) + + variables[2] = u[0] + + +def objective_function_14(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[16] = u[0] + + f[0] = variables[16]-0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0)-0.0 + + +def find_root_14(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[16] + + u = nla_solve(objective_function_14, u, 1, [voi, states, rates, variables]) + + variables[16] = u[0] + + +def objective_function_15(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[17] = u[0] + + f[0] = variables[17]-0.125*exp(states[0]/80.0)-0.0 + + +def find_root_15(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[17] + + u = nla_solve(objective_function_15, u, 1, [voi, states, rates, variables]) + + variables[17] = u[0] + + +def objective_function_16(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + rates[3] = u[0] + + f[0] = rates[3]-(variables[16]*(1.0-states[3])-variables[17]*states[3])-0.0 + + +def find_root_16(voi, states, rates, variables): + u = [nan]*1 + + u[0] = rates[3] + + u = nla_solve(objective_function_16, u, 1, [voi, states, rates, variables]) + + rates[3] = u[0] + + +def initialise_variables(states, rates, variables): + variables[0] = 0.0 + variables[1] = 0.0 + variables[2] = 0.0 + variables[3] = 0.0 + variables[4] = 1.0 + variables[5] = 0.0 + variables[6] = 0.0 + variables[7] = 0.3 + variables[8] = 0.0 + variables[9] = 120.0 + variables[10] = 0.0 + variables[11] = 0.0 + variables[12] = 0.0 + variables[13] = 0.0 + variables[14] = 0.0 + variables[15] = 36.0 + variables[16] = 0.0 + variables[17] = 0.0 + states[0] = 0.0 + states[1] = 0.6 + states[2] = 0.05 + states[3] = 0.325 + rates[0] = 0.0 + rates[1] = 0.0 + rates[2] = 0.0 + rates[3] = 0.0 + + +def compute_computed_constants(variables): + pass + + +def compute_rates(voi, states, rates, variables): + find_root_0(voi, states, rates, variables) + find_root_2(voi, states, rates, variables) + find_root_3(voi, states, rates, variables) + find_root_14(voi, states, rates, variables) + find_root_15(voi, states, rates, variables) + find_root_16(voi, states, rates, variables) + find_root_12(voi, states, rates, variables) + find_root_13(voi, states, rates, variables) + find_root_9(voi, states, rates, variables) + find_root_10(voi, states, rates, variables) + find_root_11(voi, states, rates, variables) + find_root_6(voi, states, rates, variables) + find_root_7(voi, states, rates, variables) + find_root_8(voi, states, rates, variables) + find_root_4(voi, states, rates, variables) + find_root_5(voi, states, rates, variables) + find_root_1(voi, states, rates, variables) + + +def compute_variables(voi, states, rates, variables): + find_root_0(voi, states, rates, variables) + find_root_2(voi, states, rates, variables) + find_root_3(voi, states, rates, variables) + find_root_14(voi, states, rates, variables) + find_root_15(voi, states, rates, variables) + find_root_16(voi, states, rates, variables) + find_root_12(voi, states, rates, variables) + find_root_13(voi, states, rates, variables) + find_root_9(voi, states, rates, variables) + find_root_10(voi, states, rates, variables) + find_root_11(voi, states, rates, variables) + find_root_6(voi, states, rates, variables) + find_root_7(voi, states, rates, variables) + find_root_8(voi, states, rates, variables) + find_root_4(voi, states, rates, variables) + find_root_5(voi, states, rates, variables) + find_root_1(voi, states, rates, variables) diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.c index dae5579da..a05e3be3a 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.dependent.algebraic.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 4; const size_t VARIABLE_COUNT = 18; @@ -14,41 +14,53 @@ const size_t VARIABLE_COUNT = 18; const VariableInfo VOI_INFO = {"time", "millisecond", "environment", VARIABLE_OF_INTEGRATION}; const VariableInfo STATE_INFO[] = { - {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"V", "millivolt", "membrane", STATE}, {"h", "dimensionless", "sodium_channel_h_gate", STATE}, - {"n", "dimensionless", "potassium_channel_n_gate", STATE}, - {"V", "millivolt", "membrane", STATE} + {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"n", "dimensionless", "potassium_channel_n_gate", STATE} }; const VariableInfo VARIABLE_INFO[] = { - {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, + {"i_Stim", "microA_per_cm2", "membrane", EXTERNAL}, + {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, {"Cm", "microF_per_cm2", "membrane", CONSTANT}, {"E_R", "millivolt", "membrane", CONSTANT}, - {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, - {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, - {"i_Stim", "microA_per_cm2", "membrane", EXTERNAL}, {"E_L", "millivolt", "leakage_current", COMPUTED_CONSTANT}, - {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, {"E_Na", "millivolt", "sodium_channel", COMPUTED_CONSTANT}, - {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, + {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, {"alpha_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"beta_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"alpha_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"beta_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"E_K", "millivolt", "potassium_channel", COMPUTED_CONSTANT}, - {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, {"alpha_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC}, {"beta_n", "per_millisecond", "potassium_channel_n_gate", EXTERNAL} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -56,56 +68,56 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable) +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[0] = 0.3; - variables[1] = 1.0; - variables[2] = 0.0; - variables[3] = 36.0; - variables[4] = 120.0; - states[0] = 0.05; + variables[4] = 1.0; + variables[5] = 0.0; + variables[7] = 0.3; + variables[9] = 120.0; + variables[15] = 36.0; + states[0] = 0.0; states[1] = 0.6; - states[2] = 0.325; - states[3] = 0.0; - variables[17] = externalVariable(voi, states, variables, 17); - variables[5] = externalVariable(voi, states, variables, 5); + states[2] = 0.05; + states[3] = 0.325; + variables[17] = externalVariable(voi, states, rates, variables, 17); + variables[0] = externalVariable(voi, states, rates, variables, 0); } void computeComputedConstants(double *variables) { - variables[6] = variables[2]-10.613; - variables[8] = variables[2]-115.0; - variables[14] = variables[2]+12.0; + variables[6] = variables[5]-10.613; + variables[8] = variables[5]-115.0; + variables[14] = variables[5]+12.0; } void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0]; - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); + variables[17] = externalVariable(voi, states, rates, variables, 17); + variables[0] = externalVariable(voi, states, rates, variables, 0); + variables[1] = variables[7]*(states[0]-variables[6]); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4]; + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2]; + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1]; - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); - variables[17] = externalVariable(voi, states, variables, 17); - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2]; - variables[5] = externalVariable(voi, states, variables, 5); - variables[7] = variables[0]*(states[3]-variables[6]); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1]; + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3]; } void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[17] = externalVariable(voi, states, variables, 17); - variables[5] = externalVariable(voi, states, variables, 5); - variables[7] = variables[0]*(states[3]-variables[6]); - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); + variables[17] = externalVariable(voi, states, rates, variables, 17); + variables[0] = externalVariable(voi, states, rates, variables, 0); + variables[1] = variables[7]*(states[0]-variables[6]); + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); } diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.h index 9e5e467b6..90f2f2d76 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.h +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -34,9 +34,9 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -typedef double (* ExternalVariable)(double voi, double *states, double *variables, size_t index); +typedef double (* ExternalVariable)(double voi, double *states, double *rates, double *variables, size_t index); -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable); +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.py index dab91bafc..044d7d84d 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.py +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.algebraic.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 4 VARIABLE_COUNT = 18 @@ -23,29 +23,29 @@ class VariableType(Enum): VOI_INFO = {"name": "time", "units": "millisecond", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} STATE_INFO = [ - {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE}, {"name": "h", "units": "dimensionless", "component": "sodium_channel_h_gate", "type": VariableType.STATE}, - {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE}, - {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE} + {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE} ] VARIABLE_INFO = [ - {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, + {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.EXTERNAL}, + {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, {"name": "Cm", "units": "microF_per_cm2", "component": "membrane", "type": VariableType.CONSTANT}, {"name": "E_R", "units": "millivolt", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, - {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, - {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.EXTERNAL}, {"name": "E_L", "units": "millivolt", "component": "leakage_current", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, {"name": "E_Na", "units": "millivolt", "component": "sodium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "E_K", "units": "millivolt", "component": "potassium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.EXTERNAL} ] @@ -71,51 +71,51 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(voi, states, variables, external_variable): - variables[0] = 0.3 - variables[1] = 1.0 - variables[2] = 0.0 - variables[3] = 36.0 - variables[4] = 120.0 - states[0] = 0.05 +def initialise_variables(voi, states, rates, variables, external_variable): + variables[4] = 1.0 + variables[5] = 0.0 + variables[7] = 0.3 + variables[9] = 120.0 + variables[15] = 36.0 + states[0] = 0.0 states[1] = 0.6 - states[2] = 0.325 - states[3] = 0.0 - variables[17] = external_variable(voi, states, variables, 17) - variables[5] = external_variable(voi, states, variables, 5) + states[2] = 0.05 + states[3] = 0.325 + variables[17] = external_variable(voi, states, rates, variables, 17) + variables[0] = external_variable(voi, states, rates, variables, 0) def compute_computed_constants(variables): - variables[6] = variables[2]-10.613 - variables[8] = variables[2]-115.0 - variables[14] = variables[2]+12.0 + variables[6] = variables[5]-10.613 + variables[8] = variables[5]-115.0 + variables[14] = variables[5]+12.0 def compute_rates(voi, states, rates, variables, external_variable): - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0] - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) + variables[17] = external_variable(voi, states, rates, variables, 17) + variables[0] = external_variable(voi, states, rates, variables, 0) + variables[1] = variables[7]*(states[0]-variables[6]) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4] + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2] + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1] - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) - variables[17] = external_variable(voi, states, variables, 17) - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2] - variables[5] = external_variable(voi, states, variables, 5) - variables[7] = variables[0]*(states[3]-variables[6]) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1] + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3] def compute_variables(voi, states, rates, variables, external_variable): - variables[17] = external_variable(voi, states, variables, 17) - variables[5] = external_variable(voi, states, variables, 5) - variables[7] = variables[0]*(states[3]-variables[6]) - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) + variables[17] = external_variable(voi, states, rates, variables, 17) + variables[0] = external_variable(voi, states, rates, variables, 0) + variables[1] = variables[7]*(states[0]-variables[6]) + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.c index 9e1bf201a..4b49173c8 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.dependent.computed.constant.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 4; const size_t VARIABLE_COUNT = 18; @@ -14,41 +14,53 @@ const size_t VARIABLE_COUNT = 18; const VariableInfo VOI_INFO = {"time", "millisecond", "environment", VARIABLE_OF_INTEGRATION}; const VariableInfo STATE_INFO[] = { - {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"V", "millivolt", "membrane", STATE}, {"h", "dimensionless", "sodium_channel_h_gate", STATE}, - {"n", "dimensionless", "potassium_channel_n_gate", STATE}, - {"V", "millivolt", "membrane", STATE} + {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"n", "dimensionless", "potassium_channel_n_gate", STATE} }; const VariableInfo VARIABLE_INFO[] = { - {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, + {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, + {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, {"Cm", "microF_per_cm2", "membrane", CONSTANT}, {"E_R", "millivolt", "membrane", EXTERNAL}, - {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, - {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, - {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, {"E_L", "millivolt", "leakage_current", ALGEBRAIC}, - {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, {"E_Na", "millivolt", "sodium_channel", ALGEBRAIC}, - {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, + {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, {"alpha_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"beta_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"alpha_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"beta_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"E_K", "millivolt", "potassium_channel", EXTERNAL}, - {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, {"alpha_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC}, {"beta_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -56,18 +68,18 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable) +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[0] = 0.3; - variables[1] = 1.0; - variables[3] = 36.0; - variables[4] = 120.0; - states[0] = 0.05; + variables[4] = 1.0; + variables[7] = 0.3; + variables[9] = 120.0; + variables[15] = 36.0; + states[0] = 0.0; states[1] = 0.6; - states[2] = 0.325; - states[3] = 0.0; - variables[14] = externalVariable(voi, states, variables, 14); - variables[2] = externalVariable(voi, states, variables, 2); + states[2] = 0.05; + states[3] = 0.325; + variables[14] = externalVariable(voi, states, rates, variables, 14); + variables[5] = externalVariable(voi, states, rates, variables, 5); } void computeComputedConstants(double *variables) @@ -76,37 +88,39 @@ void computeComputedConstants(double *variables) void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0]; - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); + variables[0] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; + variables[14] = externalVariable(voi, states, rates, variables, 14); + variables[5] = externalVariable(voi, states, rates, variables, 5); + variables[6] = variables[5]-10.613; + variables[1] = variables[7]*(states[0]-variables[6]); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[8] = variables[5]-115.0; + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4]; + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2]; + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1]; - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); - variables[17] = 0.125*exp(states[3]/80.0); - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2]; - variables[5] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; - variables[14] = externalVariable(voi, states, variables, 14); - variables[2] = externalVariable(voi, states, variables, 2); - variables[6] = variables[2]-10.613; - variables[7] = variables[0]*(states[3]-variables[6]); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[8] = variables[2]-115.0; - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1]; + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[17] = 0.125*exp(states[0]/80.0); + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3]; } void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[14] = externalVariable(voi, states, variables, 14); - variables[2] = externalVariable(voi, states, variables, 2); - variables[7] = variables[0]*(states[3]-variables[6]); - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); - variables[17] = 0.125*exp(states[3]/80.0); + variables[14] = externalVariable(voi, states, rates, variables, 14); + variables[5] = externalVariable(voi, states, rates, variables, 5); + variables[6] = variables[5]-10.613; + variables[1] = variables[7]*(states[0]-variables[6]); + variables[8] = variables[5]-115.0; + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[17] = 0.125*exp(states[0]/80.0); } diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.h index 9e5e467b6..90f2f2d76 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.h +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -34,9 +34,9 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -typedef double (* ExternalVariable)(double voi, double *states, double *variables, size_t index); +typedef double (* ExternalVariable)(double voi, double *states, double *rates, double *variables, size_t index); -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable); +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.py index 56e4a0bcd..d1744f67c 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.py +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.computed.constant.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 4 VARIABLE_COUNT = 18 @@ -23,29 +23,29 @@ class VariableType(Enum): VOI_INFO = {"name": "time", "units": "millisecond", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} STATE_INFO = [ - {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE}, {"name": "h", "units": "dimensionless", "component": "sodium_channel_h_gate", "type": VariableType.STATE}, - {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE}, - {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE} + {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE} ] VARIABLE_INFO = [ - {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, + {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, + {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, {"name": "Cm", "units": "microF_per_cm2", "component": "membrane", "type": VariableType.CONSTANT}, {"name": "E_R", "units": "millivolt", "component": "membrane", "type": VariableType.EXTERNAL}, - {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, - {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, - {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, {"name": "E_L", "units": "millivolt", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, - {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, {"name": "E_Na", "units": "millivolt", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, - {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "E_K", "units": "millivolt", "component": "potassium_channel", "type": VariableType.EXTERNAL}, - {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC} ] @@ -71,17 +71,17 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(voi, states, variables, external_variable): - variables[0] = 0.3 - variables[1] = 1.0 - variables[3] = 36.0 - variables[4] = 120.0 - states[0] = 0.05 +def initialise_variables(voi, states, rates, variables, external_variable): + variables[4] = 1.0 + variables[7] = 0.3 + variables[9] = 120.0 + variables[15] = 36.0 + states[0] = 0.0 states[1] = 0.6 - states[2] = 0.325 - states[3] = 0.0 - variables[14] = external_variable(voi, states, variables, 14) - variables[2] = external_variable(voi, states, variables, 2) + states[2] = 0.05 + states[3] = 0.325 + variables[14] = external_variable(voi, states, rates, variables, 14) + variables[5] = external_variable(voi, states, rates, variables, 5) def compute_computed_constants(variables): @@ -89,35 +89,37 @@ def compute_computed_constants(variables): def compute_rates(voi, states, rates, variables, external_variable): - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0] - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) + variables[0] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 + variables[14] = external_variable(voi, states, rates, variables, 14) + variables[5] = external_variable(voi, states, rates, variables, 5) + variables[6] = variables[5]-10.613 + variables[1] = variables[7]*(states[0]-variables[6]) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[8] = variables[5]-115.0 + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4] + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2] + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1] - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) - variables[17] = 0.125*exp(states[3]/80.0) - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2] - variables[5] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 - variables[14] = external_variable(voi, states, variables, 14) - variables[2] = external_variable(voi, states, variables, 2) - variables[6] = variables[2]-10.613 - variables[7] = variables[0]*(states[3]-variables[6]) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[8] = variables[2]-115.0 - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1] + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[17] = 0.125*exp(states[0]/80.0) + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3] def compute_variables(voi, states, rates, variables, external_variable): - variables[14] = external_variable(voi, states, variables, 14) - variables[2] = external_variable(voi, states, variables, 2) - variables[7] = variables[0]*(states[3]-variables[6]) - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) - variables[17] = 0.125*exp(states[3]/80.0) + variables[14] = external_variable(voi, states, rates, variables, 14) + variables[5] = external_variable(voi, states, rates, variables, 5) + variables[6] = variables[5]-10.613 + variables[1] = variables[7]*(states[0]-variables[6]) + variables[8] = variables[5]-115.0 + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[17] = 0.125*exp(states[0]/80.0) diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.c index f5887be49..f619ec3f8 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.dependent.constant.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 4; const size_t VARIABLE_COUNT = 18; @@ -14,41 +14,53 @@ const size_t VARIABLE_COUNT = 18; const VariableInfo VOI_INFO = {"time", "millisecond", "environment", VARIABLE_OF_INTEGRATION}; const VariableInfo STATE_INFO[] = { - {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"V", "millivolt", "membrane", STATE}, {"h", "dimensionless", "sodium_channel_h_gate", STATE}, - {"n", "dimensionless", "potassium_channel_n_gate", STATE}, - {"V", "millivolt", "membrane", STATE} + {"m", "dimensionless", "sodium_channel_m_gate", STATE}, + {"n", "dimensionless", "potassium_channel_n_gate", STATE} }; const VariableInfo VARIABLE_INFO[] = { - {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, + {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, + {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, {"Cm", "microF_per_cm2", "membrane", EXTERNAL}, {"E_R", "millivolt", "membrane", CONSTANT}, - {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, - {"g_Na", "milliS_per_cm2", "sodium_channel", EXTERNAL}, - {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, {"E_L", "millivolt", "leakage_current", COMPUTED_CONSTANT}, - {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, {"E_Na", "millivolt", "sodium_channel", COMPUTED_CONSTANT}, - {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, + {"g_Na", "milliS_per_cm2", "sodium_channel", EXTERNAL}, {"alpha_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"beta_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"alpha_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"beta_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"E_K", "millivolt", "potassium_channel", COMPUTED_CONSTANT}, - {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, {"alpha_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC}, {"beta_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -56,57 +68,57 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable) +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[0] = 0.3; - variables[2] = 0.0; - variables[3] = 36.0; - states[0] = 0.05; + variables[5] = 0.0; + variables[7] = 0.3; + variables[15] = 36.0; + states[0] = 0.0; states[1] = 0.6; - states[2] = 0.325; - states[3] = 0.0; - variables[4] = externalVariable(voi, states, variables, 4); - variables[1] = externalVariable(voi, states, variables, 1); + states[2] = 0.05; + states[3] = 0.325; + variables[9] = externalVariable(voi, states, rates, variables, 9); + variables[4] = externalVariable(voi, states, rates, variables, 4); } void computeComputedConstants(double *variables) { - variables[6] = variables[2]-10.613; - variables[8] = variables[2]-115.0; - variables[14] = variables[2]+12.0; + variables[6] = variables[5]-10.613; + variables[8] = variables[5]-115.0; + variables[14] = variables[5]+12.0; } void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0]; - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); + variables[0] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; + variables[9] = externalVariable(voi, states, rates, variables, 9); + variables[4] = externalVariable(voi, states, rates, variables, 4); + variables[1] = variables[7]*(states[0]-variables[6]); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4]; + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2]; + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1]; - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); - variables[17] = 0.125*exp(states[3]/80.0); - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2]; - variables[5] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; - variables[4] = externalVariable(voi, states, variables, 4); - variables[1] = externalVariable(voi, states, variables, 1); - variables[7] = variables[0]*(states[3]-variables[6]); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1]; + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[17] = 0.125*exp(states[0]/80.0); + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3]; } void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[4] = externalVariable(voi, states, variables, 4); - variables[1] = externalVariable(voi, states, variables, 1); - variables[7] = variables[0]*(states[3]-variables[6]); - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]); - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0); - variables[11] = 4.0*exp(states[3]/18.0); - variables[12] = 0.07*exp(states[3]/20.0); - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0); - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]); - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0); - variables[17] = 0.125*exp(states[3]/80.0); + variables[1] = variables[7]*(states[0]-variables[6]); + variables[9] = externalVariable(voi, states, rates, variables, 9); + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]); + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[11] = 4.0*exp(states[0]/18.0); + variables[12] = 0.07*exp(states[0]/20.0); + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]); + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[17] = 0.125*exp(states[0]/80.0); + variables[4] = externalVariable(voi, states, rates, variables, 4); } diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.h index 9e5e467b6..90f2f2d76 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.h +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -34,9 +34,9 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -typedef double (* ExternalVariable)(double voi, double *states, double *variables, size_t index); +typedef double (* ExternalVariable)(double voi, double *states, double *rates, double *variables, size_t index); -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable); +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.py index 4dbde11cc..5794985f2 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.py +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.constant.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 4 VARIABLE_COUNT = 18 @@ -23,29 +23,29 @@ class VariableType(Enum): VOI_INFO = {"name": "time", "units": "millisecond", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} STATE_INFO = [ - {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE}, {"name": "h", "units": "dimensionless", "component": "sodium_channel_h_gate", "type": VariableType.STATE}, - {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE}, - {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE} + {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE} ] VARIABLE_INFO = [ - {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, + {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, + {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, {"name": "Cm", "units": "microF_per_cm2", "component": "membrane", "type": VariableType.EXTERNAL}, {"name": "E_R", "units": "millivolt", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, - {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.EXTERNAL}, - {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, {"name": "E_L", "units": "millivolt", "component": "leakage_current", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, {"name": "E_Na", "units": "millivolt", "component": "sodium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.EXTERNAL}, {"name": "alpha_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "E_K", "units": "millivolt", "component": "potassium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC} ] @@ -71,52 +71,52 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(voi, states, variables, external_variable): - variables[0] = 0.3 - variables[2] = 0.0 - variables[3] = 36.0 - states[0] = 0.05 +def initialise_variables(voi, states, rates, variables, external_variable): + variables[5] = 0.0 + variables[7] = 0.3 + variables[15] = 36.0 + states[0] = 0.0 states[1] = 0.6 - states[2] = 0.325 - states[3] = 0.0 - variables[4] = external_variable(voi, states, variables, 4) - variables[1] = external_variable(voi, states, variables, 1) + states[2] = 0.05 + states[3] = 0.325 + variables[9] = external_variable(voi, states, rates, variables, 9) + variables[4] = external_variable(voi, states, rates, variables, 4) def compute_computed_constants(variables): - variables[6] = variables[2]-10.613 - variables[8] = variables[2]-115.0 - variables[14] = variables[2]+12.0 + variables[6] = variables[5]-10.613 + variables[8] = variables[5]-115.0 + variables[14] = variables[5]+12.0 def compute_rates(voi, states, rates, variables, external_variable): - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0] - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) + variables[0] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 + variables[9] = external_variable(voi, states, rates, variables, 9) + variables[4] = external_variable(voi, states, rates, variables, 4) + variables[1] = variables[7]*(states[0]-variables[6]) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4] + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2] + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1] - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) - variables[17] = 0.125*exp(states[3]/80.0) - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2] - variables[5] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 - variables[4] = external_variable(voi, states, variables, 4) - variables[1] = external_variable(voi, states, variables, 1) - variables[7] = variables[0]*(states[3]-variables[6]) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1] + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[17] = 0.125*exp(states[0]/80.0) + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3] def compute_variables(voi, states, rates, variables, external_variable): - variables[4] = external_variable(voi, states, variables, 4) - variables[1] = external_variable(voi, states, variables, 1) - variables[7] = variables[0]*(states[3]-variables[6]) - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) - variables[17] = 0.125*exp(states[3]/80.0) + variables[1] = variables[7]*(states[0]-variables[6]) + variables[9] = external_variable(voi, states, rates, variables, 9) + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[17] = 0.125*exp(states[0]/80.0) + variables[4] = external_variable(voi, states, rates, variables, 4) diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.c index b52cc6eb5..450f85a2b 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.dependent.state.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 2; const size_t VARIABLE_COUNT = 20; @@ -19,36 +19,48 @@ const VariableInfo STATE_INFO[] = { }; const VariableInfo VARIABLE_INFO[] = { - {"m", "dimensionless", "sodium_channel_m_gate", EXTERNAL}, + {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, {"V", "millivolt", "membrane", EXTERNAL}, - {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, + {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, {"Cm", "microF_per_cm2", "membrane", CONSTANT}, {"E_R", "millivolt", "membrane", CONSTANT}, - {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, - {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, - {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, {"E_L", "millivolt", "leakage_current", COMPUTED_CONSTANT}, - {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, {"E_Na", "millivolt", "sodium_channel", COMPUTED_CONSTANT}, - {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, + {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, + {"m", "dimensionless", "sodium_channel_m_gate", EXTERNAL}, {"alpha_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"beta_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"alpha_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"beta_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"E_K", "millivolt", "potassium_channel", COMPUTED_CONSTANT}, - {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, {"alpha_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC}, {"beta_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -56,29 +68,29 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable) +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[2] = 0.3; - variables[3] = 1.0; - variables[4] = 0.0; - variables[5] = 36.0; - variables[6] = 120.0; + variables[5] = 1.0; + variables[6] = 0.0; + variables[8] = 0.3; + variables[10] = 120.0; + variables[17] = 36.0; states[0] = 0.6; states[1] = 0.325; - variables[1] = externalVariable(voi, states, variables, 1); - variables[0] = externalVariable(voi, states, variables, 0); + variables[1] = externalVariable(voi, states, rates, variables, 1); + variables[11] = externalVariable(voi, states, rates, variables, 11); } void computeComputedConstants(double *variables) { - variables[8] = variables[4]-10.613; - variables[10] = variables[4]-115.0; - variables[16] = variables[4]+12.0; + variables[7] = variables[6]-10.613; + variables[9] = variables[6]-115.0; + variables[16] = variables[6]+12.0; } void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[1] = externalVariable(voi, states, variables, 1); + variables[1] = externalVariable(voi, states, rates, variables, 1); variables[14] = 0.07*exp(variables[1]/20.0); variables[15] = 1.0/(exp((variables[1]+30.0)/10.0)+1.0); rates[0] = variables[14]*(1.0-states[0])-variables[15]*states[0]; @@ -89,12 +101,12 @@ void computeRates(double voi, double *states, double *rates, double *variables, void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[1] = externalVariable(voi, states, variables, 1); - variables[0] = externalVariable(voi, states, variables, 0); - variables[7] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; - variables[9] = variables[2]*(variables[1]-variables[8]); - variables[11] = variables[6]*pow(variables[0], 3.0)*states[0]*(variables[1]-variables[10]); + variables[0] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; + variables[1] = externalVariable(voi, states, rates, variables, 1); + variables[2] = variables[8]*(variables[1]-variables[7]); + variables[11] = externalVariable(voi, states, rates, variables, 11); + variables[4] = variables[10]*pow(variables[11], 3.0)*states[0]*(variables[1]-variables[9]); variables[12] = 0.1*(variables[1]+25.0)/(exp((variables[1]+25.0)/10.0)-1.0); variables[13] = 4.0*exp(variables[1]/18.0); - variables[17] = variables[5]*pow(states[1], 4.0)*(variables[1]-variables[16]); + variables[3] = variables[17]*pow(states[1], 4.0)*(variables[1]-variables[16]); } diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.h index 9e5e467b6..90f2f2d76 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.h +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -34,9 +34,9 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -typedef double (* ExternalVariable)(double voi, double *states, double *variables, size_t index); +typedef double (* ExternalVariable)(double voi, double *states, double *rates, double *variables, size_t index); -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable); +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.py index 6a3a180e3..58ab6ce15 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.py +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.dependent.state.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 2 VARIABLE_COUNT = 20 @@ -28,24 +28,24 @@ class VariableType(Enum): ] VARIABLE_INFO = [ - {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.EXTERNAL}, + {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.EXTERNAL}, - {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, + {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, {"name": "Cm", "units": "microF_per_cm2", "component": "membrane", "type": VariableType.CONSTANT}, {"name": "E_R", "units": "millivolt", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, - {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, - {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, {"name": "E_L", "units": "millivolt", "component": "leakage_current", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, {"name": "E_Na", "units": "millivolt", "component": "sodium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, + {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.EXTERNAL}, {"name": "alpha_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "E_K", "units": "millivolt", "component": "potassium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC} ] @@ -71,26 +71,26 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(voi, states, variables, external_variable): - variables[2] = 0.3 - variables[3] = 1.0 - variables[4] = 0.0 - variables[5] = 36.0 - variables[6] = 120.0 +def initialise_variables(voi, states, rates, variables, external_variable): + variables[5] = 1.0 + variables[6] = 0.0 + variables[8] = 0.3 + variables[10] = 120.0 + variables[17] = 36.0 states[0] = 0.6 states[1] = 0.325 - variables[1] = external_variable(voi, states, variables, 1) - variables[0] = external_variable(voi, states, variables, 0) + variables[1] = external_variable(voi, states, rates, variables, 1) + variables[11] = external_variable(voi, states, rates, variables, 11) def compute_computed_constants(variables): - variables[8] = variables[4]-10.613 - variables[10] = variables[4]-115.0 - variables[16] = variables[4]+12.0 + variables[7] = variables[6]-10.613 + variables[9] = variables[6]-115.0 + variables[16] = variables[6]+12.0 def compute_rates(voi, states, rates, variables, external_variable): - variables[1] = external_variable(voi, states, variables, 1) + variables[1] = external_variable(voi, states, rates, variables, 1) variables[14] = 0.07*exp(variables[1]/20.0) variables[15] = 1.0/(exp((variables[1]+30.0)/10.0)+1.0) rates[0] = variables[14]*(1.0-states[0])-variables[15]*states[0] @@ -100,11 +100,11 @@ def compute_rates(voi, states, rates, variables, external_variable): def compute_variables(voi, states, rates, variables, external_variable): - variables[1] = external_variable(voi, states, variables, 1) - variables[0] = external_variable(voi, states, variables, 0) - variables[7] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 - variables[9] = variables[2]*(variables[1]-variables[8]) - variables[11] = variables[6]*pow(variables[0], 3.0)*states[0]*(variables[1]-variables[10]) + variables[0] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 + variables[1] = external_variable(voi, states, rates, variables, 1) + variables[2] = variables[8]*(variables[1]-variables[7]) + variables[11] = external_variable(voi, states, rates, variables, 11) + variables[4] = variables[10]*pow(variables[11], 3.0)*states[0]*(variables[1]-variables[9]) variables[12] = 0.1*(variables[1]+25.0)/(exp((variables[1]+25.0)/10.0)-1.0) variables[13] = 4.0*exp(variables[1]/18.0) - variables[17] = variables[5]*pow(states[1], 4.0)*(variables[1]-variables[16]) + variables[3] = variables[17]*pow(states[1], 4.0)*(variables[1]-variables[16]) diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.external.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.external.c index 1f1f0fbe9..5080a59d1 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.external.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.external.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.external.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 3; const size_t VARIABLE_COUNT = 19; @@ -14,41 +14,53 @@ const size_t VARIABLE_COUNT = 19; const VariableInfo VOI_INFO = {"time", "millisecond", "environment", VARIABLE_OF_INTEGRATION}; const VariableInfo STATE_INFO[] = { - {"m", "dimensionless", "sodium_channel_m_gate", STATE}, {"h", "dimensionless", "sodium_channel_h_gate", STATE}, + {"m", "dimensionless", "sodium_channel_m_gate", STATE}, {"n", "dimensionless", "potassium_channel_n_gate", STATE} }; const VariableInfo VARIABLE_INFO[] = { + {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, {"V", "millivolt", "membrane", EXTERNAL}, - {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, + {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"i_Na", "microA_per_cm2", "sodium_channel", EXTERNAL}, {"Cm", "microF_per_cm2", "membrane", CONSTANT}, {"E_R", "millivolt", "membrane", CONSTANT}, - {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, - {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, - {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, {"E_L", "millivolt", "leakage_current", COMPUTED_CONSTANT}, - {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, {"E_Na", "millivolt", "sodium_channel", COMPUTED_CONSTANT}, - {"i_Na", "microA_per_cm2", "sodium_channel", EXTERNAL}, + {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, {"alpha_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"beta_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"alpha_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"beta_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"E_K", "millivolt", "potassium_channel", COMPUTED_CONSTANT}, - {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, {"alpha_n", "per_millisecond", "potassium_channel_n_gate", EXTERNAL}, {"beta_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -56,48 +68,48 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable) +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[1] = 0.3; - variables[2] = 1.0; - variables[3] = 0.0; - variables[4] = 36.0; - variables[5] = 120.0; - states[0] = 0.05; - states[1] = 0.6; + variables[5] = 1.0; + variables[6] = 0.0; + variables[8] = 0.3; + variables[10] = 120.0; + variables[16] = 36.0; + states[0] = 0.6; + states[1] = 0.05; states[2] = 0.325; - variables[0] = externalVariable(voi, states, variables, 0); - variables[17] = externalVariable(voi, states, variables, 17); - variables[10] = externalVariable(voi, states, variables, 10); + variables[1] = externalVariable(voi, states, rates, variables, 1); + variables[17] = externalVariable(voi, states, rates, variables, 17); + variables[4] = externalVariable(voi, states, rates, variables, 4); } void computeComputedConstants(double *variables) { - variables[7] = variables[3]-10.613; - variables[9] = variables[3]-115.0; - variables[15] = variables[3]+12.0; + variables[7] = variables[6]-10.613; + variables[9] = variables[6]-115.0; + variables[15] = variables[6]+12.0; } void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[0] = externalVariable(voi, states, variables, 0); - variables[11] = 0.1*(variables[0]+25.0)/(exp((variables[0]+25.0)/10.0)-1.0); - variables[12] = 4.0*exp(variables[0]/18.0); - rates[0] = variables[11]*(1.0-states[0])-variables[12]*states[0]; - variables[13] = 0.07*exp(variables[0]/20.0); - variables[14] = 1.0/(exp((variables[0]+30.0)/10.0)+1.0); - rates[1] = variables[13]*(1.0-states[1])-variables[14]*states[1]; - variables[17] = externalVariable(voi, states, variables, 17); - variables[18] = 0.125*exp(variables[0]/80.0); + variables[1] = externalVariable(voi, states, rates, variables, 1); + variables[11] = 0.1*(variables[1]+25.0)/(exp((variables[1]+25.0)/10.0)-1.0); + variables[12] = 4.0*exp(variables[1]/18.0); + rates[1] = variables[11]*(1.0-states[1])-variables[12]*states[1]; + variables[13] = 0.07*exp(variables[1]/20.0); + variables[14] = 1.0/(exp((variables[1]+30.0)/10.0)+1.0); + rates[0] = variables[13]*(1.0-states[0])-variables[14]*states[0]; + variables[17] = externalVariable(voi, states, rates, variables, 17); + variables[18] = 0.125*exp(variables[1]/80.0); rates[2] = variables[17]*(1.0-states[2])-variables[18]*states[2]; } void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[0] = externalVariable(voi, states, variables, 0); - variables[6] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; - variables[8] = variables[1]*(variables[0]-variables[7]); - variables[17] = externalVariable(voi, states, variables, 17); - variables[10] = externalVariable(voi, states, variables, 10); - variables[16] = variables[4]*pow(states[2], 4.0)*(variables[0]-variables[15]); + variables[0] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; + variables[1] = externalVariable(voi, states, rates, variables, 1); + variables[2] = variables[8]*(variables[1]-variables[7]); + variables[17] = externalVariable(voi, states, rates, variables, 17); + variables[4] = externalVariable(voi, states, rates, variables, 4); + variables[3] = variables[16]*pow(states[2], 4.0)*(variables[1]-variables[15]); } diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.external.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.external.h index 9e5e467b6..90f2f2d76 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.external.h +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.external.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -34,9 +34,9 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -typedef double (* ExternalVariable)(double voi, double *states, double *variables, size_t index); +typedef double (* ExternalVariable)(double voi, double *states, double *rates, double *variables, size_t index); -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable); +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.external.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.external.py index 51b06fd34..2caf7951d 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.external.py +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.external.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 3 VARIABLE_COUNT = 19 @@ -23,29 +23,29 @@ class VariableType(Enum): VOI_INFO = {"name": "time", "units": "millisecond", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} STATE_INFO = [ - {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, {"name": "h", "units": "dimensionless", "component": "sodium_channel_h_gate", "type": VariableType.STATE}, + {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE} ] VARIABLE_INFO = [ + {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.EXTERNAL}, - {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, + {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.EXTERNAL}, {"name": "Cm", "units": "microF_per_cm2", "component": "membrane", "type": VariableType.CONSTANT}, {"name": "E_R", "units": "millivolt", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, - {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, - {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, {"name": "E_L", "units": "millivolt", "component": "leakage_current", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, {"name": "E_Na", "units": "millivolt", "component": "sodium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.EXTERNAL}, + {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "E_K", "units": "millivolt", "component": "potassium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.EXTERNAL}, {"name": "beta_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC} ] @@ -71,43 +71,43 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(voi, states, variables, external_variable): - variables[1] = 0.3 - variables[2] = 1.0 - variables[3] = 0.0 - variables[4] = 36.0 - variables[5] = 120.0 - states[0] = 0.05 - states[1] = 0.6 +def initialise_variables(voi, states, rates, variables, external_variable): + variables[5] = 1.0 + variables[6] = 0.0 + variables[8] = 0.3 + variables[10] = 120.0 + variables[16] = 36.0 + states[0] = 0.6 + states[1] = 0.05 states[2] = 0.325 - variables[0] = external_variable(voi, states, variables, 0) - variables[17] = external_variable(voi, states, variables, 17) - variables[10] = external_variable(voi, states, variables, 10) + variables[1] = external_variable(voi, states, rates, variables, 1) + variables[17] = external_variable(voi, states, rates, variables, 17) + variables[4] = external_variable(voi, states, rates, variables, 4) def compute_computed_constants(variables): - variables[7] = variables[3]-10.613 - variables[9] = variables[3]-115.0 - variables[15] = variables[3]+12.0 + variables[7] = variables[6]-10.613 + variables[9] = variables[6]-115.0 + variables[15] = variables[6]+12.0 def compute_rates(voi, states, rates, variables, external_variable): - variables[0] = external_variable(voi, states, variables, 0) - variables[11] = 0.1*(variables[0]+25.0)/(exp((variables[0]+25.0)/10.0)-1.0) - variables[12] = 4.0*exp(variables[0]/18.0) - rates[0] = variables[11]*(1.0-states[0])-variables[12]*states[0] - variables[13] = 0.07*exp(variables[0]/20.0) - variables[14] = 1.0/(exp((variables[0]+30.0)/10.0)+1.0) - rates[1] = variables[13]*(1.0-states[1])-variables[14]*states[1] - variables[17] = external_variable(voi, states, variables, 17) - variables[18] = 0.125*exp(variables[0]/80.0) + variables[1] = external_variable(voi, states, rates, variables, 1) + variables[11] = 0.1*(variables[1]+25.0)/(exp((variables[1]+25.0)/10.0)-1.0) + variables[12] = 4.0*exp(variables[1]/18.0) + rates[1] = variables[11]*(1.0-states[1])-variables[12]*states[1] + variables[13] = 0.07*exp(variables[1]/20.0) + variables[14] = 1.0/(exp((variables[1]+30.0)/10.0)+1.0) + rates[0] = variables[13]*(1.0-states[0])-variables[14]*states[0] + variables[17] = external_variable(voi, states, rates, variables, 17) + variables[18] = 0.125*exp(variables[1]/80.0) rates[2] = variables[17]*(1.0-states[2])-variables[18]*states[2] def compute_variables(voi, states, rates, variables, external_variable): - variables[0] = external_variable(voi, states, variables, 0) - variables[6] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 - variables[8] = variables[1]*(variables[0]-variables[7]) - variables[17] = external_variable(voi, states, variables, 17) - variables[10] = external_variable(voi, states, variables, 10) - variables[16] = variables[4]*pow(states[2], 4.0)*(variables[0]-variables[15]) + variables[0] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 + variables[1] = external_variable(voi, states, rates, variables, 1) + variables[2] = variables[8]*(variables[1]-variables[7]) + variables[17] = external_variable(voi, states, rates, variables, 17) + variables[4] = external_variable(voi, states, rates, variables, 4) + variables[3] = variables[16]*pow(states[2], 4.0)*(variables[1]-variables[15]) diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.h index d3c382249..a6105918a 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.h +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.py index 01905cd8d..4ccccffa1 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.py +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 4 VARIABLE_COUNT = 18 @@ -22,29 +22,29 @@ class VariableType(Enum): VOI_INFO = {"name": "time", "units": "millisecond", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} STATE_INFO = [ - {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE}, {"name": "h", "units": "dimensionless", "component": "sodium_channel_h_gate", "type": VariableType.STATE}, - {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE}, - {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE} + {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, + {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE} ] VARIABLE_INFO = [ - {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, + {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, + {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, {"name": "Cm", "units": "microF_per_cm2", "component": "membrane", "type": VariableType.CONSTANT}, {"name": "E_R", "units": "millivolt", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, - {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, - {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, {"name": "E_L", "units": "millivolt", "component": "leakage_current", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, {"name": "E_Na", "units": "millivolt", "component": "sodium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "E_K", "units": "millivolt", "component": "potassium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC} ] @@ -70,48 +70,48 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): - variables[0] = 0.3 - variables[1] = 1.0 - variables[2] = 0.0 - variables[3] = 36.0 - variables[4] = 120.0 - states[0] = 0.05 +def initialise_variables(states, rates, variables): + variables[4] = 1.0 + variables[5] = 0.0 + variables[7] = 0.3 + variables[9] = 120.0 + variables[15] = 36.0 + states[0] = 0.0 states[1] = 0.6 - states[2] = 0.325 - states[3] = 0.0 + states[2] = 0.05 + states[3] = 0.325 def compute_computed_constants(variables): - variables[6] = variables[2]-10.613 - variables[8] = variables[2]-115.0 - variables[14] = variables[2]+12.0 + variables[6] = variables[5]-10.613 + variables[8] = variables[5]-115.0 + variables[14] = variables[5]+12.0 def compute_rates(voi, states, rates, variables): - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - rates[0] = variables[10]*(1.0-states[0])-variables[11]*states[0] - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) + variables[0] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 + variables[1] = variables[7]*(states[0]-variables[6]) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4] + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + rates[2] = variables[10]*(1.0-states[2])-variables[11]*states[2] + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) rates[1] = variables[12]*(1.0-states[1])-variables[13]*states[1] - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) - variables[17] = 0.125*exp(states[3]/80.0) - rates[2] = variables[16]*(1.0-states[2])-variables[17]*states[2] - variables[5] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 - variables[7] = variables[0]*(states[3]-variables[6]) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - rates[3] = -(-variables[5]+variables[9]+variables[15]+variables[7])/variables[1] + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[17] = 0.125*exp(states[0]/80.0) + rates[3] = variables[16]*(1.0-states[3])-variables[17]*states[3] def compute_variables(voi, states, rates, variables): - variables[7] = variables[0]*(states[3]-variables[6]) - variables[9] = variables[4]*pow(states[0], 3.0)*states[1]*(states[3]-variables[8]) - variables[10] = 0.1*(states[3]+25.0)/(exp((states[3]+25.0)/10.0)-1.0) - variables[11] = 4.0*exp(states[3]/18.0) - variables[12] = 0.07*exp(states[3]/20.0) - variables[13] = 1.0/(exp((states[3]+30.0)/10.0)+1.0) - variables[15] = variables[3]*pow(states[2], 4.0)*(states[3]-variables[14]) - variables[16] = 0.01*(states[3]+10.0)/(exp((states[3]+10.0)/10.0)-1.0) - variables[17] = 0.125*exp(states[3]/80.0) + variables[1] = variables[7]*(states[0]-variables[6]) + variables[3] = variables[9]*pow(states[2], 3.0)*states[1]*(states[0]-variables[8]) + variables[10] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[11] = 4.0*exp(states[0]/18.0) + variables[12] = 0.07*exp(states[0]/20.0) + variables[13] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) + variables[2] = variables[15]*pow(states[3], 4.0)*(states[0]-variables[14]) + variables[16] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[17] = 0.125*exp(states[0]/80.0) diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.c b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.c index d392b5ac9..22f5b36d5 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.c +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.state.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 3; const size_t VARIABLE_COUNT = 19; @@ -14,41 +14,53 @@ const size_t VARIABLE_COUNT = 19; const VariableInfo VOI_INFO = {"time", "millisecond", "environment", VARIABLE_OF_INTEGRATION}; const VariableInfo STATE_INFO[] = { + {"V", "millivolt", "membrane", STATE}, {"h", "dimensionless", "sodium_channel_h_gate", STATE}, - {"n", "dimensionless", "potassium_channel_n_gate", STATE}, - {"V", "millivolt", "membrane", STATE} + {"n", "dimensionless", "potassium_channel_n_gate", STATE} }; const VariableInfo VARIABLE_INFO[] = { - {"m", "dimensionless", "sodium_channel_m_gate", EXTERNAL}, - {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, + {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, + {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, {"Cm", "microF_per_cm2", "membrane", CONSTANT}, {"E_R", "millivolt", "membrane", CONSTANT}, - {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, - {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, - {"i_Stim", "microA_per_cm2", "membrane", ALGEBRAIC}, {"E_L", "millivolt", "leakage_current", COMPUTED_CONSTANT}, - {"i_L", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, {"E_Na", "millivolt", "sodium_channel", COMPUTED_CONSTANT}, - {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, + {"g_Na", "milliS_per_cm2", "sodium_channel", CONSTANT}, + {"m", "dimensionless", "sodium_channel_m_gate", EXTERNAL}, {"alpha_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"beta_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"alpha_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"beta_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, {"E_K", "millivolt", "potassium_channel", COMPUTED_CONSTANT}, - {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"g_K", "milliS_per_cm2", "potassium_channel", CONSTANT}, {"alpha_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC}, {"beta_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -56,52 +68,52 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable) +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[1] = 0.3; - variables[2] = 1.0; - variables[3] = 0.0; - variables[4] = 36.0; - variables[5] = 120.0; - states[0] = 0.6; - states[1] = 0.325; - states[2] = 0.0; - variables[0] = externalVariable(voi, states, variables, 0); + variables[4] = 1.0; + variables[5] = 0.0; + variables[7] = 0.3; + variables[9] = 120.0; + variables[16] = 36.0; + states[0] = 0.0; + states[1] = 0.6; + states[2] = 0.325; + variables[10] = externalVariable(voi, states, rates, variables, 10); } void computeComputedConstants(double *variables) { - variables[7] = variables[3]-10.613; - variables[9] = variables[3]-115.0; - variables[15] = variables[3]+12.0; + variables[6] = variables[5]-10.613; + variables[8] = variables[5]-115.0; + variables[15] = variables[5]+12.0; } void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[13] = 0.07*exp(states[2]/20.0); - variables[14] = 1.0/(exp((states[2]+30.0)/10.0)+1.0); - rates[0] = variables[13]*(1.0-states[0])-variables[14]*states[0]; - variables[17] = 0.01*(states[2]+10.0)/(exp((states[2]+10.0)/10.0)-1.0); - variables[18] = 0.125*exp(states[2]/80.0); - rates[1] = variables[17]*(1.0-states[1])-variables[18]*states[1]; - variables[6] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; - variables[8] = variables[1]*(states[2]-variables[7]); - variables[16] = variables[4]*pow(states[1], 4.0)*(states[2]-variables[15]); - variables[0] = externalVariable(voi, states, variables, 0); - variables[10] = variables[5]*pow(variables[0], 3.0)*states[0]*(states[2]-variables[9]); - rates[2] = -(-variables[6]+variables[10]+variables[16]+variables[8])/variables[2]; + variables[0] = ((voi >= 10.0) && (voi <= 10.5))?-20.0:0.0; + variables[1] = variables[7]*(states[0]-variables[6]); + variables[2] = variables[16]*pow(states[2], 4.0)*(states[0]-variables[15]); + variables[10] = externalVariable(voi, states, rates, variables, 10); + variables[3] = variables[9]*pow(variables[10], 3.0)*states[1]*(states[0]-variables[8]); + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4]; + variables[13] = 0.07*exp(states[0]/20.0); + variables[14] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); + rates[1] = variables[13]*(1.0-states[1])-variables[14]*states[1]; + variables[17] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[18] = 0.125*exp(states[0]/80.0); + rates[2] = variables[17]*(1.0-states[2])-variables[18]*states[2]; } void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable) { - variables[0] = externalVariable(voi, states, variables, 0); - variables[8] = variables[1]*(states[2]-variables[7]); - variables[10] = variables[5]*pow(variables[0], 3.0)*states[0]*(states[2]-variables[9]); - variables[11] = 0.1*(states[2]+25.0)/(exp((states[2]+25.0)/10.0)-1.0); - variables[12] = 4.0*exp(states[2]/18.0); - variables[13] = 0.07*exp(states[2]/20.0); - variables[14] = 1.0/(exp((states[2]+30.0)/10.0)+1.0); - variables[16] = variables[4]*pow(states[1], 4.0)*(states[2]-variables[15]); - variables[17] = 0.01*(states[2]+10.0)/(exp((states[2]+10.0)/10.0)-1.0); - variables[18] = 0.125*exp(states[2]/80.0); + variables[1] = variables[7]*(states[0]-variables[6]); + variables[10] = externalVariable(voi, states, rates, variables, 10); + variables[3] = variables[9]*pow(variables[10], 3.0)*states[1]*(states[0]-variables[8]); + variables[11] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0); + variables[12] = 4.0*exp(states[0]/18.0); + variables[13] = 0.07*exp(states[0]/20.0); + variables[14] = 1.0/(exp((states[0]+30.0)/10.0)+1.0); + variables[2] = variables[16]*pow(states[2], 4.0)*(states[0]-variables[15]); + variables[17] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0); + variables[18] = 0.125*exp(states[0]/80.0); } diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.h b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.h index 9e5e467b6..90f2f2d76 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.h +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -34,9 +34,9 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -typedef double (* ExternalVariable)(double voi, double *states, double *variables, size_t index); +typedef double (* ExternalVariable)(double voi, double *states, double *rates, double *variables, size_t index); -void initialiseVariables(double voi, double *states, double *variables, ExternalVariable externalVariable); +void initialiseVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); void computeVariables(double voi, double *states, double *rates, double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.py b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.py index ebde1d6ec..670866666 100644 --- a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.py +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model.state.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 3 VARIABLE_COUNT = 19 @@ -23,29 +23,29 @@ class VariableType(Enum): VOI_INFO = {"name": "time", "units": "millisecond", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} STATE_INFO = [ + {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE}, {"name": "h", "units": "dimensionless", "component": "sodium_channel_h_gate", "type": VariableType.STATE}, - {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE}, - {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE} + {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE} ] VARIABLE_INFO = [ - {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.EXTERNAL}, - {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, + {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, + {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, {"name": "Cm", "units": "microF_per_cm2", "component": "membrane", "type": VariableType.CONSTANT}, {"name": "E_R", "units": "millivolt", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, - {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, - {"name": "i_Stim", "units": "microA_per_cm2", "component": "membrane", "type": VariableType.ALGEBRAIC}, {"name": "E_L", "units": "millivolt", "component": "leakage_current", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_L", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, {"name": "E_Na", "units": "millivolt", "component": "sodium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, + {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.EXTERNAL}, {"name": "alpha_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, {"name": "E_K", "units": "millivolt", "component": "potassium_channel", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_K", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC} ] @@ -71,47 +71,47 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(voi, states, variables, external_variable): - variables[1] = 0.3 - variables[2] = 1.0 - variables[3] = 0.0 - variables[4] = 36.0 - variables[5] = 120.0 - states[0] = 0.6 - states[1] = 0.325 - states[2] = 0.0 - variables[0] = external_variable(voi, states, variables, 0) +def initialise_variables(voi, states, rates, variables, external_variable): + variables[4] = 1.0 + variables[5] = 0.0 + variables[7] = 0.3 + variables[9] = 120.0 + variables[16] = 36.0 + states[0] = 0.0 + states[1] = 0.6 + states[2] = 0.325 + variables[10] = external_variable(voi, states, rates, variables, 10) def compute_computed_constants(variables): - variables[7] = variables[3]-10.613 - variables[9] = variables[3]-115.0 - variables[15] = variables[3]+12.0 + variables[6] = variables[5]-10.613 + variables[8] = variables[5]-115.0 + variables[15] = variables[5]+12.0 def compute_rates(voi, states, rates, variables, external_variable): - variables[13] = 0.07*exp(states[2]/20.0) - variables[14] = 1.0/(exp((states[2]+30.0)/10.0)+1.0) - rates[0] = variables[13]*(1.0-states[0])-variables[14]*states[0] - variables[17] = 0.01*(states[2]+10.0)/(exp((states[2]+10.0)/10.0)-1.0) - variables[18] = 0.125*exp(states[2]/80.0) - rates[1] = variables[17]*(1.0-states[1])-variables[18]*states[1] - variables[6] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 - variables[8] = variables[1]*(states[2]-variables[7]) - variables[16] = variables[4]*pow(states[1], 4.0)*(states[2]-variables[15]) - variables[0] = external_variable(voi, states, variables, 0) - variables[10] = variables[5]*pow(variables[0], 3.0)*states[0]*(states[2]-variables[9]) - rates[2] = -(-variables[6]+variables[10]+variables[16]+variables[8])/variables[2] + variables[0] = -20.0 if and_func(geq_func(voi, 10.0), leq_func(voi, 10.5)) else 0.0 + variables[1] = variables[7]*(states[0]-variables[6]) + variables[2] = variables[16]*pow(states[2], 4.0)*(states[0]-variables[15]) + variables[10] = external_variable(voi, states, rates, variables, 10) + variables[3] = variables[9]*pow(variables[10], 3.0)*states[1]*(states[0]-variables[8]) + rates[0] = -(-variables[0]+variables[3]+variables[2]+variables[1])/variables[4] + variables[13] = 0.07*exp(states[0]/20.0) + variables[14] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) + rates[1] = variables[13]*(1.0-states[1])-variables[14]*states[1] + variables[17] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[18] = 0.125*exp(states[0]/80.0) + rates[2] = variables[17]*(1.0-states[2])-variables[18]*states[2] def compute_variables(voi, states, rates, variables, external_variable): - variables[0] = external_variable(voi, states, variables, 0) - variables[8] = variables[1]*(states[2]-variables[7]) - variables[10] = variables[5]*pow(variables[0], 3.0)*states[0]*(states[2]-variables[9]) - variables[11] = 0.1*(states[2]+25.0)/(exp((states[2]+25.0)/10.0)-1.0) - variables[12] = 4.0*exp(states[2]/18.0) - variables[13] = 0.07*exp(states[2]/20.0) - variables[14] = 1.0/(exp((states[2]+30.0)/10.0)+1.0) - variables[16] = variables[4]*pow(states[1], 4.0)*(states[2]-variables[15]) - variables[17] = 0.01*(states[2]+10.0)/(exp((states[2]+10.0)/10.0)-1.0) - variables[18] = 0.125*exp(states[2]/80.0) + variables[1] = variables[7]*(states[0]-variables[6]) + variables[10] = external_variable(voi, states, rates, variables, 10) + variables[3] = variables[9]*pow(variables[10], 3.0)*states[1]*(states[0]-variables[8]) + variables[11] = 0.1*(states[0]+25.0)/(exp((states[0]+25.0)/10.0)-1.0) + variables[12] = 4.0*exp(states[0]/18.0) + variables[13] = 0.07*exp(states[0]/20.0) + variables[14] = 1.0/(exp((states[0]+30.0)/10.0)+1.0) + variables[2] = variables[16]*pow(states[2], 4.0)*(states[0]-variables[15]) + variables[17] = 0.01*(states[0]+10.0)/(exp((states[0]+10.0)/10.0)-1.0) + variables[18] = 0.125*exp(states[0]/80.0) diff --git a/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model_unknown_vars_on_rhs.cellml b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model_unknown_vars_on_rhs.cellml new file mode 100644 index 000000000..0ffe728ac --- /dev/null +++ b/tests/resources/generator/hodgkin_huxley_squid_axon_model_1952/model_unknown_vars_on_rhs.cellml @@ -0,0 +1,503 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + i_Stim + + + + + 20 + + + + + + time + 10 + + + + time + 10.5 + + + + + 0 + + + + + + + + + + + + + + i_Stim + + i_Na + i_K + i_L + + + Cm + + + + + time + + V + + + + + + + + + + + + + + + + + E_Na + + + E_R + 115 + + + + + + + g_Na + + + m + 3 + + h + + + V + E_Na + + + i_Na + + + + + + + + + + + + + + + + + 0.1 + + + V + 25 + + + + + + + + + + + V + 25 + + 10 + + + 1 + + + alpha_m + + + + beta_m + + + 4 + + + + + V + 18 + + + + + + + + + + time + + m + + + + + + alpha_m + + + 1 + m + + + + + beta_m + m + + + + + + + + + + + + + + + + + 0.07 + + + + + V + 20 + + + + alpha_h + + + + beta_h + + + 1 + + + + + + + + + V + 30 + + 10 + + + 1 + + + + + + + + + time + + h + + + + + + alpha_h + + + 1 + h + + + + + beta_h + h + + + + + + + + + + + + + + + + + E_K + + + E_R + 12 + + + + + + + g_K + + + n + 4 + + + + V + E_K + + + i_K + + + + + + + + + + + + + + + + + 0.01 + + + V + 10 + + + + + + + + + + + V + 10 + + 10 + + + 1 + + + alpha_n + + + + beta_n + + + 0.125 + + + + + V + 80 + + + + + + + + + + time + + n + + + + + + alpha_n + + + 1 + n + + + + + beta_n + n + + + + + + + + + + + + + + + + E_L + + + E_R + 10.613 + + + + + + + g_L + + + V + E_L + + + i_L + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/generator/noble_model_1962/model.c b/tests/resources/generator/noble_model_1962/model.c index eca8d614d..a259161db 100644 --- a/tests/resources/generator/noble_model_1962/model.c +++ b/tests/resources/generator/noble_model_1962/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 4; const size_t VARIABLE_COUNT = 17; @@ -14,21 +14,22 @@ const size_t VARIABLE_COUNT = 17; const VariableInfo VOI_INFO = {"time", "millisecond", "environment", VARIABLE_OF_INTEGRATION}; const VariableInfo STATE_INFO[] = { + {"V", "millivolt", "membrane", STATE}, {"m", "dimensionless", "sodium_channel_m_gate", STATE}, {"h", "dimensionless", "sodium_channel_h_gate", STATE}, - {"n", "dimensionless", "potassium_channel_n_gate", STATE}, - {"V", "millivolt", "membrane", STATE} + {"n", "dimensionless", "potassium_channel_n_gate", STATE} }; const VariableInfo VARIABLE_INFO[] = { - {"E_L", "millivolt", "leakage_current", CONSTANT}, - {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, - {"Cm", "microF_per_cm2", "membrane", CONSTANT}, - {"E_Na", "millivolt", "sodium_channel", CONSTANT}, - {"g_Na_max", "milliS_per_cm2", "sodium_channel", CONSTANT}, + {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, {"i_Leak", "microA_per_cm2", "leakage_current", ALGEBRAIC}, + {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC}, + {"Cm", "microF_per_cm2", "membrane", CONSTANT}, + {"g_L", "milliS_per_cm2", "leakage_current", CONSTANT}, + {"E_L", "millivolt", "leakage_current", CONSTANT}, {"g_Na", "milliS_per_cm2", "sodium_channel", ALGEBRAIC}, - {"i_Na", "microA_per_cm2", "sodium_channel", ALGEBRAIC}, + {"g_Na_max", "milliS_per_cm2", "sodium_channel", CONSTANT}, + {"E_Na", "millivolt", "sodium_channel", CONSTANT}, {"alpha_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"beta_m", "per_millisecond", "sodium_channel_m_gate", ALGEBRAIC}, {"alpha_h", "per_millisecond", "sodium_channel_h_gate", ALGEBRAIC}, @@ -36,18 +37,29 @@ const VariableInfo VARIABLE_INFO[] = { {"g_K1", "milliS_per_cm2", "potassium_channel", ALGEBRAIC}, {"g_K2", "milliS_per_cm2", "potassium_channel", ALGEBRAIC}, {"alpha_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC}, - {"beta_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC}, - {"i_K", "microA_per_cm2", "potassium_channel", ALGEBRAIC} + {"beta_n", "per_millisecond", "potassium_channel_n_gate", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -55,17 +67,17 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { - variables[0] = -60.0; - variables[1] = 0.075; - variables[2] = 12.0; - variables[3] = 40.0; - variables[4] = 400.0; - states[0] = 0.01; - states[1] = 0.8; - states[2] = 0.01; - states[3] = -87.0; + variables[3] = 12.0; + variables[4] = 0.075; + variables[5] = -60.0; + variables[7] = 400.0; + variables[8] = 40.0; + states[0] = -87.0; + states[1] = 0.01; + states[2] = 0.8; + states[3] = 0.01; } void computeComputedConstants(double *variables) @@ -74,36 +86,36 @@ void computeComputedConstants(double *variables) void computeRates(double voi, double *states, double *rates, double *variables) { - variables[8] = 0.1*(-states[3]-48.0)/(exp((-states[3]-48.0)/15.0)-1.0); - variables[9] = 0.12*(states[3]+8.0)/(exp((states[3]+8.0)/5.0)-1.0); - rates[0] = variables[8]*(1.0-states[0])-variables[9]*states[0]; - variables[10] = 0.17*exp((-states[3]-90.0)/20.0); - variables[11] = 1.0/(1.0+exp((-states[3]-42.0)/10.0)); - rates[1] = variables[10]*(1.0-states[1])-variables[11]*states[1]; - variables[14] = 0.0001*(-states[3]-50.0)/(exp((-states[3]-50.0)/10.0)-1.0); - variables[15] = 0.002*exp((-states[3]-90.0)/80.0); - rates[2] = variables[14]*(1.0-states[2])-variables[15]*states[2]; - variables[6] = pow(states[0], 3.0)*states[1]*variables[4]; - variables[7] = (variables[6]+0.14)*(states[3]-variables[3]); - variables[5] = variables[1]*(states[3]-variables[0]); - variables[12] = 1.2*exp((-states[3]-90.0)/50.0)+0.015*exp((states[3]+90.0)/60.0); - variables[13] = 1.2*pow(states[2], 4.0); - variables[16] = (variables[12]+variables[13])*(states[3]+100.0); - rates[3] = -(variables[7]+variables[16]+variables[5])/variables[2]; + variables[6] = pow(states[1], 3.0)*states[2]*variables[7]; + variables[0] = (variables[6]+0.14)*(states[0]-variables[8]); + variables[1] = variables[4]*(states[0]-variables[5]); + variables[13] = 1.2*exp((-states[0]-90.0)/50.0)+0.015*exp((states[0]+90.0)/60.0); + variables[14] = 1.2*pow(states[3], 4.0); + variables[2] = (variables[13]+variables[14])*(states[0]+100.0); + rates[0] = -(variables[0]+variables[2]+variables[1])/variables[3]; + variables[9] = 0.1*(-states[0]-48.0)/(exp((-states[0]-48.0)/15.0)-1.0); + variables[10] = 0.12*(states[0]+8.0)/(exp((states[0]+8.0)/5.0)-1.0); + rates[1] = variables[9]*(1.0-states[1])-variables[10]*states[1]; + variables[11] = 0.17*exp((-states[0]-90.0)/20.0); + variables[12] = 1.0/(1.0+exp((-states[0]-42.0)/10.0)); + rates[2] = variables[11]*(1.0-states[2])-variables[12]*states[2]; + variables[15] = 0.0001*(-states[0]-50.0)/(exp((-states[0]-50.0)/10.0)-1.0); + variables[16] = 0.002*exp((-states[0]-90.0)/80.0); + rates[3] = variables[15]*(1.0-states[3])-variables[16]*states[3]; } void computeVariables(double voi, double *states, double *rates, double *variables) { - variables[5] = variables[1]*(states[3]-variables[0]); - variables[6] = pow(states[0], 3.0)*states[1]*variables[4]; - variables[7] = (variables[6]+0.14)*(states[3]-variables[3]); - variables[8] = 0.1*(-states[3]-48.0)/(exp((-states[3]-48.0)/15.0)-1.0); - variables[9] = 0.12*(states[3]+8.0)/(exp((states[3]+8.0)/5.0)-1.0); - variables[10] = 0.17*exp((-states[3]-90.0)/20.0); - variables[11] = 1.0/(1.0+exp((-states[3]-42.0)/10.0)); - variables[12] = 1.2*exp((-states[3]-90.0)/50.0)+0.015*exp((states[3]+90.0)/60.0); - variables[13] = 1.2*pow(states[2], 4.0); - variables[14] = 0.0001*(-states[3]-50.0)/(exp((-states[3]-50.0)/10.0)-1.0); - variables[15] = 0.002*exp((-states[3]-90.0)/80.0); - variables[16] = (variables[12]+variables[13])*(states[3]+100.0); + variables[1] = variables[4]*(states[0]-variables[5]); + variables[6] = pow(states[1], 3.0)*states[2]*variables[7]; + variables[0] = (variables[6]+0.14)*(states[0]-variables[8]); + variables[9] = 0.1*(-states[0]-48.0)/(exp((-states[0]-48.0)/15.0)-1.0); + variables[10] = 0.12*(states[0]+8.0)/(exp((states[0]+8.0)/5.0)-1.0); + variables[11] = 0.17*exp((-states[0]-90.0)/20.0); + variables[12] = 1.0/(1.0+exp((-states[0]-42.0)/10.0)); + variables[13] = 1.2*exp((-states[0]-90.0)/50.0)+0.015*exp((states[0]+90.0)/60.0); + variables[14] = 1.2*pow(states[3], 4.0); + variables[2] = (variables[13]+variables[14])*(states[0]+100.0); + variables[15] = 0.0001*(-states[0]-50.0)/(exp((-states[0]-50.0)/10.0)-1.0); + variables[16] = 0.002*exp((-states[0]-90.0)/80.0); } diff --git a/tests/resources/generator/noble_model_1962/model.h b/tests/resources/generator/noble_model_1962/model.h index 8aa52ae2f..1f66de15d 100644 --- a/tests/resources/generator/noble_model_1962/model.h +++ b/tests/resources/generator/noble_model_1962/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/noble_model_1962/model.py b/tests/resources/generator/noble_model_1962/model.py index e8e68ddae..2f5b868b5 100644 --- a/tests/resources/generator/noble_model_1962/model.py +++ b/tests/resources/generator/noble_model_1962/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 4 VARIABLE_COUNT = 17 @@ -22,21 +22,22 @@ class VariableType(Enum): VOI_INFO = {"name": "time", "units": "millisecond", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} STATE_INFO = [ + {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE}, {"name": "m", "units": "dimensionless", "component": "sodium_channel_m_gate", "type": VariableType.STATE}, {"name": "h", "units": "dimensionless", "component": "sodium_channel_h_gate", "type": VariableType.STATE}, - {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE}, - {"name": "V", "units": "millivolt", "component": "membrane", "type": VariableType.STATE} + {"name": "n", "units": "dimensionless", "component": "potassium_channel_n_gate", "type": VariableType.STATE} ] VARIABLE_INFO = [ - {"name": "E_L", "units": "millivolt", "component": "leakage_current", "type": VariableType.CONSTANT}, - {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, - {"name": "Cm", "units": "microF_per_cm2", "component": "membrane", "type": VariableType.CONSTANT}, - {"name": "E_Na", "units": "millivolt", "component": "sodium_channel", "type": VariableType.CONSTANT}, - {"name": "g_Na_max", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, + {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, {"name": "i_Leak", "units": "microA_per_cm2", "component": "leakage_current", "type": VariableType.ALGEBRAIC}, + {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "Cm", "units": "microF_per_cm2", "component": "membrane", "type": VariableType.CONSTANT}, + {"name": "g_L", "units": "milliS_per_cm2", "component": "leakage_current", "type": VariableType.CONSTANT}, + {"name": "E_L", "units": "millivolt", "component": "leakage_current", "type": VariableType.CONSTANT}, {"name": "g_Na", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, - {"name": "i_Na", "units": "microA_per_cm2", "component": "sodium_channel", "type": VariableType.ALGEBRAIC}, + {"name": "g_Na_max", "units": "milliS_per_cm2", "component": "sodium_channel", "type": VariableType.CONSTANT}, + {"name": "E_Na", "units": "millivolt", "component": "sodium_channel", "type": VariableType.CONSTANT}, {"name": "alpha_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "beta_m", "units": "per_millisecond", "component": "sodium_channel_m_gate", "type": VariableType.ALGEBRAIC}, {"name": "alpha_h", "units": "per_millisecond", "component": "sodium_channel_h_gate", "type": VariableType.ALGEBRAIC}, @@ -44,8 +45,7 @@ class VariableType(Enum): {"name": "g_K1", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, {"name": "g_K2", "units": "milliS_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC}, {"name": "alpha_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC}, - {"name": "beta_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC}, - {"name": "i_K", "units": "microA_per_cm2", "component": "potassium_channel", "type": VariableType.ALGEBRAIC} + {"name": "beta_n", "units": "per_millisecond", "component": "potassium_channel_n_gate", "type": VariableType.ALGEBRAIC} ] @@ -57,16 +57,16 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): - variables[0] = -60.0 - variables[1] = 0.075 - variables[2] = 12.0 - variables[3] = 40.0 - variables[4] = 400.0 - states[0] = 0.01 - states[1] = 0.8 - states[2] = 0.01 - states[3] = -87.0 +def initialise_variables(states, rates, variables): + variables[3] = 12.0 + variables[4] = 0.075 + variables[5] = -60.0 + variables[7] = 400.0 + variables[8] = 40.0 + states[0] = -87.0 + states[1] = 0.01 + states[2] = 0.8 + states[3] = 0.01 def compute_computed_constants(variables): @@ -74,34 +74,34 @@ def compute_computed_constants(variables): def compute_rates(voi, states, rates, variables): - variables[8] = 0.1*(-states[3]-48.0)/(exp((-states[3]-48.0)/15.0)-1.0) - variables[9] = 0.12*(states[3]+8.0)/(exp((states[3]+8.0)/5.0)-1.0) - rates[0] = variables[8]*(1.0-states[0])-variables[9]*states[0] - variables[10] = 0.17*exp((-states[3]-90.0)/20.0) - variables[11] = 1.0/(1.0+exp((-states[3]-42.0)/10.0)) - rates[1] = variables[10]*(1.0-states[1])-variables[11]*states[1] - variables[14] = 0.0001*(-states[3]-50.0)/(exp((-states[3]-50.0)/10.0)-1.0) - variables[15] = 0.002*exp((-states[3]-90.0)/80.0) - rates[2] = variables[14]*(1.0-states[2])-variables[15]*states[2] - variables[6] = pow(states[0], 3.0)*states[1]*variables[4] - variables[7] = (variables[6]+0.14)*(states[3]-variables[3]) - variables[5] = variables[1]*(states[3]-variables[0]) - variables[12] = 1.2*exp((-states[3]-90.0)/50.0)+0.015*exp((states[3]+90.0)/60.0) - variables[13] = 1.2*pow(states[2], 4.0) - variables[16] = (variables[12]+variables[13])*(states[3]+100.0) - rates[3] = -(variables[7]+variables[16]+variables[5])/variables[2] + variables[6] = pow(states[1], 3.0)*states[2]*variables[7] + variables[0] = (variables[6]+0.14)*(states[0]-variables[8]) + variables[1] = variables[4]*(states[0]-variables[5]) + variables[13] = 1.2*exp((-states[0]-90.0)/50.0)+0.015*exp((states[0]+90.0)/60.0) + variables[14] = 1.2*pow(states[3], 4.0) + variables[2] = (variables[13]+variables[14])*(states[0]+100.0) + rates[0] = -(variables[0]+variables[2]+variables[1])/variables[3] + variables[9] = 0.1*(-states[0]-48.0)/(exp((-states[0]-48.0)/15.0)-1.0) + variables[10] = 0.12*(states[0]+8.0)/(exp((states[0]+8.0)/5.0)-1.0) + rates[1] = variables[9]*(1.0-states[1])-variables[10]*states[1] + variables[11] = 0.17*exp((-states[0]-90.0)/20.0) + variables[12] = 1.0/(1.0+exp((-states[0]-42.0)/10.0)) + rates[2] = variables[11]*(1.0-states[2])-variables[12]*states[2] + variables[15] = 0.0001*(-states[0]-50.0)/(exp((-states[0]-50.0)/10.0)-1.0) + variables[16] = 0.002*exp((-states[0]-90.0)/80.0) + rates[3] = variables[15]*(1.0-states[3])-variables[16]*states[3] def compute_variables(voi, states, rates, variables): - variables[5] = variables[1]*(states[3]-variables[0]) - variables[6] = pow(states[0], 3.0)*states[1]*variables[4] - variables[7] = (variables[6]+0.14)*(states[3]-variables[3]) - variables[8] = 0.1*(-states[3]-48.0)/(exp((-states[3]-48.0)/15.0)-1.0) - variables[9] = 0.12*(states[3]+8.0)/(exp((states[3]+8.0)/5.0)-1.0) - variables[10] = 0.17*exp((-states[3]-90.0)/20.0) - variables[11] = 1.0/(1.0+exp((-states[3]-42.0)/10.0)) - variables[12] = 1.2*exp((-states[3]-90.0)/50.0)+0.015*exp((states[3]+90.0)/60.0) - variables[13] = 1.2*pow(states[2], 4.0) - variables[14] = 0.0001*(-states[3]-50.0)/(exp((-states[3]-50.0)/10.0)-1.0) - variables[15] = 0.002*exp((-states[3]-90.0)/80.0) - variables[16] = (variables[12]+variables[13])*(states[3]+100.0) + variables[1] = variables[4]*(states[0]-variables[5]) + variables[6] = pow(states[1], 3.0)*states[2]*variables[7] + variables[0] = (variables[6]+0.14)*(states[0]-variables[8]) + variables[9] = 0.1*(-states[0]-48.0)/(exp((-states[0]-48.0)/15.0)-1.0) + variables[10] = 0.12*(states[0]+8.0)/(exp((states[0]+8.0)/5.0)-1.0) + variables[11] = 0.17*exp((-states[0]-90.0)/20.0) + variables[12] = 1.0/(1.0+exp((-states[0]-42.0)/10.0)) + variables[13] = 1.2*exp((-states[0]-90.0)/50.0)+0.015*exp((states[0]+90.0)/60.0) + variables[14] = 1.2*pow(states[3], 4.0) + variables[2] = (variables[13]+variables[14])*(states[0]+100.0) + variables[15] = 0.0001*(-states[0]-50.0)/(exp((-states[0]-50.0)/10.0)-1.0) + variables[16] = 0.002*exp((-states[0]-90.0)/80.0) diff --git a/tests/resources/generator/ode_computed_var_on_rhs/model.c b/tests/resources/generator/ode_computed_var_on_rhs/model.c index f6a00c488..c5fd81ced 100644 --- a/tests/resources/generator/ode_computed_var_on_rhs/model.c +++ b/tests/resources/generator/ode_computed_var_on_rhs/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 1; @@ -23,12 +23,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -36,7 +48,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { variables[0] = 1.0; states[0] = 1.0; diff --git a/tests/resources/generator/ode_computed_var_on_rhs/model.h b/tests/resources/generator/ode_computed_var_on_rhs/model.h index 9d284a1ed..caeb40bab 100644 --- a/tests/resources/generator/ode_computed_var_on_rhs/model.h +++ b/tests/resources/generator/ode_computed_var_on_rhs/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/ode_computed_var_on_rhs/model.py b/tests/resources/generator/ode_computed_var_on_rhs/model.py index f52728696..d7af94139 100644 --- a/tests/resources/generator/ode_computed_var_on_rhs/model.py +++ b/tests/resources/generator/ode_computed_var_on_rhs/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 1 @@ -38,7 +38,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): variables[0] = 1.0 states[0] = 1.0 diff --git a/tests/resources/generator/ode_computed_var_on_rhs_one_component/model.c b/tests/resources/generator/ode_computed_var_on_rhs_one_component/model.c index 764229035..7c1ebd0af 100644 --- a/tests/resources/generator/ode_computed_var_on_rhs_one_component/model.c +++ b/tests/resources/generator/ode_computed_var_on_rhs_one_component/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 1; @@ -23,12 +23,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -36,7 +48,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { variables[0] = 1.0; states[0] = 1.0; diff --git a/tests/resources/generator/ode_computed_var_on_rhs_one_component/model.h b/tests/resources/generator/ode_computed_var_on_rhs_one_component/model.h index 2235c5e07..9aad67f7a 100644 --- a/tests/resources/generator/ode_computed_var_on_rhs_one_component/model.h +++ b/tests/resources/generator/ode_computed_var_on_rhs_one_component/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/ode_computed_var_on_rhs_one_component/model.py b/tests/resources/generator/ode_computed_var_on_rhs_one_component/model.py index c996fb3dc..eb791199c 100644 --- a/tests/resources/generator/ode_computed_var_on_rhs_one_component/model.py +++ b/tests/resources/generator/ode_computed_var_on_rhs_one_component/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 1 @@ -38,7 +38,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): variables[0] = 1.0 states[0] = 1.0 diff --git a/tests/resources/generator/ode_const_var_on_rhs/model.c b/tests/resources/generator/ode_const_var_on_rhs/model.c index 77608e4be..ba43658e1 100644 --- a/tests/resources/generator/ode_const_var_on_rhs/model.c +++ b/tests/resources/generator/ode_const_var_on_rhs/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 1; @@ -23,12 +23,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -36,7 +48,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { variables[0] = 1.0; states[0] = 1.0; diff --git a/tests/resources/generator/ode_const_var_on_rhs/model.h b/tests/resources/generator/ode_const_var_on_rhs/model.h index 9d284a1ed..caeb40bab 100644 --- a/tests/resources/generator/ode_const_var_on_rhs/model.h +++ b/tests/resources/generator/ode_const_var_on_rhs/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/ode_const_var_on_rhs/model.py b/tests/resources/generator/ode_const_var_on_rhs/model.py index 4e70b5b02..171d3eb75 100644 --- a/tests/resources/generator/ode_const_var_on_rhs/model.py +++ b/tests/resources/generator/ode_const_var_on_rhs/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 1 @@ -38,7 +38,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): variables[0] = 1.0 states[0] = 1.0 diff --git a/tests/resources/generator/ode_const_var_on_rhs_one_component/model.c b/tests/resources/generator/ode_const_var_on_rhs_one_component/model.c index 4b16ebaf4..8fc12933b 100644 --- a/tests/resources/generator/ode_const_var_on_rhs_one_component/model.c +++ b/tests/resources/generator/ode_const_var_on_rhs_one_component/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 1; @@ -23,12 +23,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -36,7 +48,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { variables[0] = 1.0; states[0] = 1.0; diff --git a/tests/resources/generator/ode_const_var_on_rhs_one_component/model.h b/tests/resources/generator/ode_const_var_on_rhs_one_component/model.h index 2235c5e07..9aad67f7a 100644 --- a/tests/resources/generator/ode_const_var_on_rhs_one_component/model.h +++ b/tests/resources/generator/ode_const_var_on_rhs_one_component/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/ode_const_var_on_rhs_one_component/model.py b/tests/resources/generator/ode_const_var_on_rhs_one_component/model.py index d7c5408d4..05e7479b1 100644 --- a/tests/resources/generator/ode_const_var_on_rhs_one_component/model.py +++ b/tests/resources/generator/ode_const_var_on_rhs_one_component/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 1 @@ -38,7 +38,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): variables[0] = 1.0 states[0] = 1.0 diff --git a/tests/resources/generator/ode_constant_on_rhs/model.c b/tests/resources/generator/ode_constant_on_rhs/model.c index d680f8f17..92f9ace03 100644 --- a/tests/resources/generator/ode_constant_on_rhs/model.c +++ b/tests/resources/generator/ode_constant_on_rhs/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 0; @@ -22,12 +22,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -35,7 +47,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { states[0] = 1.0; } diff --git a/tests/resources/generator/ode_constant_on_rhs/model.h b/tests/resources/generator/ode_constant_on_rhs/model.h index 9d284a1ed..caeb40bab 100644 --- a/tests/resources/generator/ode_constant_on_rhs/model.h +++ b/tests/resources/generator/ode_constant_on_rhs/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/ode_constant_on_rhs/model.py b/tests/resources/generator/ode_constant_on_rhs/model.py index cf43b1062..36a70b444 100644 --- a/tests/resources/generator/ode_constant_on_rhs/model.py +++ b/tests/resources/generator/ode_constant_on_rhs/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 0 @@ -37,7 +37,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): states[0] = 1.0 diff --git a/tests/resources/generator/ode_constant_on_rhs_one_component/model.c b/tests/resources/generator/ode_constant_on_rhs_one_component/model.c index be1410044..83ce2d752 100644 --- a/tests/resources/generator/ode_constant_on_rhs_one_component/model.c +++ b/tests/resources/generator/ode_constant_on_rhs_one_component/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 0; @@ -22,12 +22,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -35,7 +47,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { states[0] = 1.0; } diff --git a/tests/resources/generator/ode_constant_on_rhs_one_component/model.h b/tests/resources/generator/ode_constant_on_rhs_one_component/model.h index 2235c5e07..9aad67f7a 100644 --- a/tests/resources/generator/ode_constant_on_rhs_one_component/model.h +++ b/tests/resources/generator/ode_constant_on_rhs_one_component/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/ode_constant_on_rhs_one_component/model.py b/tests/resources/generator/ode_constant_on_rhs_one_component/model.py index 4ca6dcc0a..5dbb6e4a2 100644 --- a/tests/resources/generator/ode_constant_on_rhs_one_component/model.py +++ b/tests/resources/generator/ode_constant_on_rhs_one_component/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 0 @@ -37,7 +37,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): states[0] = 1.0 diff --git a/tests/resources/generator/ode_multiple_dependent_odes/model.c b/tests/resources/generator/ode_multiple_dependent_odes/model.c index 0941bd7c5..cbe407ba4 100644 --- a/tests/resources/generator/ode_multiple_dependent_odes/model.c +++ b/tests/resources/generator/ode_multiple_dependent_odes/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 2; const size_t VARIABLE_COUNT = 1; @@ -24,12 +24,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -37,7 +49,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { variables[0] = 1.0; states[0] = -2.0; diff --git a/tests/resources/generator/ode_multiple_dependent_odes/model.h b/tests/resources/generator/ode_multiple_dependent_odes/model.h index 71cc6e29d..a685abb66 100644 --- a/tests/resources/generator/ode_multiple_dependent_odes/model.h +++ b/tests/resources/generator/ode_multiple_dependent_odes/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/ode_multiple_dependent_odes/model.py b/tests/resources/generator/ode_multiple_dependent_odes/model.py index 8124728eb..4aec9e342 100644 --- a/tests/resources/generator/ode_multiple_dependent_odes/model.py +++ b/tests/resources/generator/ode_multiple_dependent_odes/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 2 VARIABLE_COUNT = 1 @@ -39,7 +39,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): variables[0] = 1.0 states[0] = -2.0 states[1] = 0.0 diff --git a/tests/resources/generator/ode_multiple_dependent_odes_one_component/model.c b/tests/resources/generator/ode_multiple_dependent_odes_one_component/model.c index b9bcb0888..a31dbee47 100644 --- a/tests/resources/generator/ode_multiple_dependent_odes_one_component/model.c +++ b/tests/resources/generator/ode_multiple_dependent_odes_one_component/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 2; const size_t VARIABLE_COUNT = 1; @@ -24,12 +24,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -37,7 +49,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { variables[0] = 1.0; states[0] = -2.0; diff --git a/tests/resources/generator/ode_multiple_dependent_odes_one_component/model.h b/tests/resources/generator/ode_multiple_dependent_odes_one_component/model.h index 2c46c0e6a..6ac98c1de 100644 --- a/tests/resources/generator/ode_multiple_dependent_odes_one_component/model.h +++ b/tests/resources/generator/ode_multiple_dependent_odes_one_component/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/ode_multiple_dependent_odes_one_component/model.py b/tests/resources/generator/ode_multiple_dependent_odes_one_component/model.py index 6e0987df1..599f63c55 100644 --- a/tests/resources/generator/ode_multiple_dependent_odes_one_component/model.py +++ b/tests/resources/generator/ode_multiple_dependent_odes_one_component/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 2 VARIABLE_COUNT = 1 @@ -39,7 +39,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): variables[0] = 1.0 states[0] = -2.0 states[1] = 0.0 diff --git a/tests/resources/generator/ode_multiple_odes_with_same_name/model.c b/tests/resources/generator/ode_multiple_odes_with_same_name/model.c index 4216df7ca..6f77bc54a 100644 --- a/tests/resources/generator/ode_multiple_odes_with_same_name/model.c +++ b/tests/resources/generator/ode_multiple_odes_with_same_name/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 2; const size_t VARIABLE_COUNT = 1; @@ -24,12 +24,24 @@ const VariableInfo VARIABLE_INFO[] = { double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -37,7 +49,7 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { variables[0] = 1.0; states[0] = 1.0; diff --git a/tests/resources/generator/ode_multiple_odes_with_same_name/model.h b/tests/resources/generator/ode_multiple_odes_with_same_name/model.h index 43889c7ea..7b5c06ff3 100644 --- a/tests/resources/generator/ode_multiple_odes_with_same_name/model.h +++ b/tests/resources/generator/ode_multiple_odes_with_same_name/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/ode_multiple_odes_with_same_name/model.py b/tests/resources/generator/ode_multiple_odes_with_same_name/model.py index 5795c293d..07a516dd1 100644 --- a/tests/resources/generator/ode_multiple_odes_with_same_name/model.py +++ b/tests/resources/generator/ode_multiple_odes_with_same_name/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 2 VARIABLE_COUNT = 1 @@ -39,7 +39,7 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): +def initialise_variables(states, rates, variables): variables[0] = 1.0 states[0] = 1.0 states[1] = 1.0 diff --git a/tests/resources/generator/ode_unknown_var_on_rhs/model.c b/tests/resources/generator/ode_unknown_var_on_rhs/model.c new file mode 100644 index 000000000..8bf7fc824 --- /dev/null +++ b/tests/resources/generator/ode_unknown_var_on_rhs/model.c @@ -0,0 +1,69 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t STATE_COUNT = 2; +const size_t VARIABLE_COUNT = 0; + +const VariableInfo VOI_INFO = {"t", "second", "environment", VARIABLE_OF_INTEGRATION}; + +const VariableInfo STATE_INFO[] = { + {"x", "dimensionless", "my_ode", STATE}, + {"y", "dimensionless", "my_ode", STATE} +}; + +const VariableInfo VARIABLE_INFO[] = { +}; + +double * createStatesArray() +{ + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +void initialiseVariables(double *states, double *rates, double *variables) +{ + states[0] = 1.0; + states[1] = 1.0; +} + +void computeComputedConstants(double *variables) +{ +} + +void computeRates(double voi, double *states, double *rates, double *variables) +{ + rates[0] = 1.0; + rates[1] = states[0]; +} + +void computeVariables(double voi, double *states, double *rates, double *variables) +{ +} diff --git a/tests/resources/generator/ode_unknown_var_on_rhs/model.cellml b/tests/resources/generator/ode_unknown_var_on_rhs/model.cellml new file mode 100644 index 000000000..c487a3aa0 --- /dev/null +++ b/tests/resources/generator/ode_unknown_var_on_rhs/model.cellml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + 1 + + + + t + + x + + + + + x + + + + t + + y + + + + + + + + diff --git a/tests/resources/generator/ode_unknown_var_on_rhs/model.h b/tests/resources/generator/ode_unknown_var_on_rhs/model.h new file mode 100644 index 000000000..caeb40bab --- /dev/null +++ b/tests/resources/generator/ode_unknown_var_on_rhs/model.h @@ -0,0 +1,39 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t STATE_COUNT; +extern const size_t VARIABLE_COUNT; + +typedef enum { + VARIABLE_OF_INTEGRATION, + STATE, + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC +} VariableType; + +typedef struct { + char name[2]; + char units[14]; + char component[12]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VOI_INFO; +extern const VariableInfo STATE_INFO[]; +extern const VariableInfo VARIABLE_INFO[]; + +double * createStatesArray(); +double * createVariablesArray(); +void deleteArray(double *array); + +void initialiseVariables(double *states, double *rates, double *variables); +void computeComputedConstants(double *variables); +void computeRates(double voi, double *states, double *rates, double *variables); +void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/ode_unknown_var_on_rhs/model.py b/tests/resources/generator/ode_unknown_var_on_rhs/model.py new file mode 100644 index 000000000..b5e0efba7 --- /dev/null +++ b/tests/resources/generator/ode_unknown_var_on_rhs/model.py @@ -0,0 +1,56 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +STATE_COUNT = 2 +VARIABLE_COUNT = 0 + + +class VariableType(Enum): + VARIABLE_OF_INTEGRATION = 0 + STATE = 1 + CONSTANT = 2 + COMPUTED_CONSTANT = 3 + ALGEBRAIC = 4 + + +VOI_INFO = {"name": "t", "units": "second", "component": "environment", "type": VariableType.VARIABLE_OF_INTEGRATION} + +STATE_INFO = [ + {"name": "x", "units": "dimensionless", "component": "my_ode", "type": VariableType.STATE}, + {"name": "y", "units": "dimensionless", "component": "my_ode", "type": VariableType.STATE} +] + +VARIABLE_INFO = [ +] + + +def create_states_array(): + return [nan]*STATE_COUNT + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +def initialise_variables(states, rates, variables): + states[0] = 1.0 + states[1] = 1.0 + + +def compute_computed_constants(variables): + pass + + +def compute_rates(voi, states, rates, variables): + rates[0] = 1.0 + rates[1] = states[0] + + +def compute_variables(voi, states, rates, variables): + pass diff --git a/tests/resources/generator/robertson_model_1966/model.dae.c b/tests/resources/generator/robertson_model_1966/model.dae.c new file mode 100644 index 000000000..a807d25b2 --- /dev/null +++ b/tests/resources/generator/robertson_model_1966/model.dae.c @@ -0,0 +1,115 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.dae.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t STATE_COUNT = 2; +const size_t VARIABLE_COUNT = 5; + +const VariableInfo VOI_INFO = {"t", "dimensionless", "main", VARIABLE_OF_INTEGRATION}; + +const VariableInfo STATE_INFO[] = { + {"y1", "dimensionless", "main", STATE}, + {"y2", "dimensionless", "main", STATE} +}; + +const VariableInfo VARIABLE_INFO[] = { + {"k1", "dimensionless", "main", CONSTANT}, + {"k3", "dimensionless", "main", CONSTANT}, + {"y3", "dimensionless", "main", ALGEBRAIC}, + {"k2", "dimensionless", "main", CONSTANT}, + {"y2_scaled", "dimensionless", "main", ALGEBRAIC} +}; + +double * createStatesArray() +{ + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +typedef struct { + double voi; + double *states; + double *rates; + double *variables; +} RootFindingInfo; + +extern void nlaSolve(void (*objectiveFunction)(double *, double *, void *), + double *u, int n, void *data); + +void objectiveFunction0(double *u, double *f, void *data) +{ + double voi = ((RootFindingInfo *) data)->voi; + double *states = ((RootFindingInfo *) data)->states; + double *rates = ((RootFindingInfo *) data)->rates; + double *variables = ((RootFindingInfo *) data)->variables; + + variables[2] = u[0]; + + f[0] = 1.0-(states[0]+states[1]+variables[2]); +} + +void findRoot0(double voi, double *states, double *rates, double *variables) +{ + RootFindingInfo rfi = { voi, states, rates, variables }; + double u[1]; + + u[0] = variables[2]; + + nlaSolve(objectiveFunction0, u, 1, &rfi); + + variables[2] = u[0]; +} + +void initialiseVariables(double *states, double *rates, double *variables) +{ + variables[0] = 0.04; + variables[1] = 1.0e4; + variables[2] = 0.0; + variables[3] = 3.0e7; + states[0] = 1.0; + states[1] = 0.0; +} + +void computeComputedConstants(double *variables) +{ +} + +void computeRates(double voi, double *states, double *rates, double *variables) +{ + findRoot0(voi, states, rates, variables); + rates[0] = -variables[0]*states[0]+variables[1]*states[1]*variables[2]; + rates[1] = variables[0]*states[0]-variables[3]*pow(states[1], 2.0)-variables[1]*states[1]*variables[2]; +} + +void computeVariables(double voi, double *states, double *rates, double *variables) +{ + findRoot0(voi, states, rates, variables); + variables[4] = 10000.0*states[1]; +} diff --git a/tests/resources/generator/robertson_model_1966/model.dae.cellml b/tests/resources/generator/robertson_model_1966/model.dae.cellml new file mode 100644 index 000000000..deeef2a61 --- /dev/null +++ b/tests/resources/generator/robertson_model_1966/model.dae.cellml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + t + + y1 + + + + + + + + k1 + + y1 + + + + k3 + y2 + y3 + + + + + + + + + t + + y2 + + + + + + + + k1 + y1 + + + + k2 + + + y2 + 2 + + + + + + k3 + y2 + y3 + + + + + + 1 + + + y1 + y2 + y3 + + + + + y2_scaled + + + 10000.0 + y2 + + + + + diff --git a/tests/resources/generator/robertson_model_1966/model.dae.h b/tests/resources/generator/robertson_model_1966/model.dae.h new file mode 100644 index 000000000..3dcbda5b4 --- /dev/null +++ b/tests/resources/generator/robertson_model_1966/model.dae.h @@ -0,0 +1,39 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t STATE_COUNT; +extern const size_t VARIABLE_COUNT; + +typedef enum { + VARIABLE_OF_INTEGRATION, + STATE, + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC +} VariableType; + +typedef struct { + char name[10]; + char units[14]; + char component[5]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VOI_INFO; +extern const VariableInfo STATE_INFO[]; +extern const VariableInfo VARIABLE_INFO[]; + +double * createStatesArray(); +double * createVariablesArray(); +void deleteArray(double *array); + +void initialiseVariables(double *states, double *rates, double *variables); +void computeComputedConstants(double *variables); +void computeRates(double voi, double *states, double *rates, double *variables); +void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/robertson_model_1966/model.dae.py b/tests/resources/generator/robertson_model_1966/model.dae.py new file mode 100644 index 000000000..553cb6f9b --- /dev/null +++ b/tests/resources/generator/robertson_model_1966/model.dae.py @@ -0,0 +1,91 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +STATE_COUNT = 2 +VARIABLE_COUNT = 5 + + +class VariableType(Enum): + VARIABLE_OF_INTEGRATION = 0 + STATE = 1 + CONSTANT = 2 + COMPUTED_CONSTANT = 3 + ALGEBRAIC = 4 + + +VOI_INFO = {"name": "t", "units": "dimensionless", "component": "main", "type": VariableType.VARIABLE_OF_INTEGRATION} + +STATE_INFO = [ + {"name": "y1", "units": "dimensionless", "component": "main", "type": VariableType.STATE}, + {"name": "y2", "units": "dimensionless", "component": "main", "type": VariableType.STATE} +] + +VARIABLE_INFO = [ + {"name": "k1", "units": "dimensionless", "component": "main", "type": VariableType.CONSTANT}, + {"name": "k3", "units": "dimensionless", "component": "main", "type": VariableType.CONSTANT}, + {"name": "y3", "units": "dimensionless", "component": "main", "type": VariableType.ALGEBRAIC}, + {"name": "k2", "units": "dimensionless", "component": "main", "type": VariableType.CONSTANT}, + {"name": "y2_scaled", "units": "dimensionless", "component": "main", "type": VariableType.ALGEBRAIC} +] + + +def create_states_array(): + return [nan]*STATE_COUNT + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +from nlasolver import nla_solve + + +def objective_function_0(u, f, data): + voi = data[0] + states = data[1] + rates = data[2] + variables = data[3] + + variables[2] = u[0] + + f[0] = 1.0-(states[0]+states[1]+variables[2]) + + +def find_root_0(voi, states, rates, variables): + u = [nan]*1 + + u[0] = variables[2] + + u = nla_solve(objective_function_0, u, 1, [voi, states, rates, variables]) + + variables[2] = u[0] + + +def initialise_variables(states, rates, variables): + variables[0] = 0.04 + variables[1] = 1.0e4 + variables[2] = 0.0 + variables[3] = 3.0e7 + states[0] = 1.0 + states[1] = 0.0 + + +def compute_computed_constants(variables): + pass + + +def compute_rates(voi, states, rates, variables): + find_root_0(voi, states, rates, variables) + rates[0] = -variables[0]*states[0]+variables[1]*states[1]*variables[2] + rates[1] = variables[0]*states[0]-variables[3]*pow(states[1], 2.0)-variables[1]*states[1]*variables[2] + + +def compute_variables(voi, states, rates, variables): + find_root_0(voi, states, rates, variables) + variables[4] = 10000.0*states[1] diff --git a/tests/resources/generator/robertson_model_1966/model.ode.c b/tests/resources/generator/robertson_model_1966/model.ode.c new file mode 100644 index 000000000..e9e959215 --- /dev/null +++ b/tests/resources/generator/robertson_model_1966/model.ode.c @@ -0,0 +1,80 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.ode.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t STATE_COUNT = 3; +const size_t VARIABLE_COUNT = 4; + +const VariableInfo VOI_INFO = {"t", "dimensionless", "main", VARIABLE_OF_INTEGRATION}; + +const VariableInfo STATE_INFO[] = { + {"y1", "dimensionless", "main", STATE}, + {"y3", "dimensionless", "main", STATE}, + {"y2", "dimensionless", "main", STATE} +}; + +const VariableInfo VARIABLE_INFO[] = { + {"k1", "dimensionless", "main", CONSTANT}, + {"k3", "dimensionless", "main", CONSTANT}, + {"k2", "dimensionless", "main", CONSTANT}, + {"y2_scaled", "dimensionless", "main", ALGEBRAIC} +}; + +double * createStatesArray() +{ + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +void initialiseVariables(double *states, double *rates, double *variables) +{ + variables[0] = 0.04; + variables[1] = 1.0e4; + variables[2] = 3.0e7; + states[0] = 1.0; + states[1] = 0.0; + states[2] = 0.0; +} + +void computeComputedConstants(double *variables) +{ +} + +void computeRates(double voi, double *states, double *rates, double *variables) +{ + rates[0] = -variables[0]*states[0]+variables[1]*states[2]*states[1]; + rates[2] = variables[0]*states[0]-variables[2]*pow(states[2], 2.0)-variables[1]*states[2]*states[1]; + rates[1] = variables[2]*pow(states[2], 2.0); +} + +void computeVariables(double voi, double *states, double *rates, double *variables) +{ + variables[3] = 10000.0*states[2]; +} diff --git a/tests/resources/generator/robertson_model_1966/model.ode.cellml b/tests/resources/generator/robertson_model_1966/model.ode.cellml new file mode 100644 index 000000000..d33c58a98 --- /dev/null +++ b/tests/resources/generator/robertson_model_1966/model.ode.cellml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + t + + y1 + + + + + + + + k1 + + y1 + + + + k3 + y2 + y3 + + + + + + + + + t + + y2 + + + + + + + + k1 + y1 + + + + k2 + + + y2 + 2 + + + + + + k3 + y2 + y3 + + + + + + + + + t + + y3 + + + + k2 + + + y2 + 2 + + + + + + y2_scaled + + + 10000.0 + y2 + + + + + diff --git a/tests/resources/generator/robertson_model_1966/model.ode.h b/tests/resources/generator/robertson_model_1966/model.ode.h new file mode 100644 index 000000000..3dcbda5b4 --- /dev/null +++ b/tests/resources/generator/robertson_model_1966/model.ode.h @@ -0,0 +1,39 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t STATE_COUNT; +extern const size_t VARIABLE_COUNT; + +typedef enum { + VARIABLE_OF_INTEGRATION, + STATE, + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC +} VariableType; + +typedef struct { + char name[10]; + char units[14]; + char component[5]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VOI_INFO; +extern const VariableInfo STATE_INFO[]; +extern const VariableInfo VARIABLE_INFO[]; + +double * createStatesArray(); +double * createVariablesArray(); +void deleteArray(double *array); + +void initialiseVariables(double *states, double *rates, double *variables); +void computeComputedConstants(double *variables); +void computeRates(double voi, double *states, double *rates, double *variables); +void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/robertson_model_1966/model.ode.py b/tests/resources/generator/robertson_model_1966/model.ode.py new file mode 100644 index 000000000..3c0078a47 --- /dev/null +++ b/tests/resources/generator/robertson_model_1966/model.ode.py @@ -0,0 +1,66 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +STATE_COUNT = 3 +VARIABLE_COUNT = 4 + + +class VariableType(Enum): + VARIABLE_OF_INTEGRATION = 0 + STATE = 1 + CONSTANT = 2 + COMPUTED_CONSTANT = 3 + ALGEBRAIC = 4 + + +VOI_INFO = {"name": "t", "units": "dimensionless", "component": "main", "type": VariableType.VARIABLE_OF_INTEGRATION} + +STATE_INFO = [ + {"name": "y1", "units": "dimensionless", "component": "main", "type": VariableType.STATE}, + {"name": "y3", "units": "dimensionless", "component": "main", "type": VariableType.STATE}, + {"name": "y2", "units": "dimensionless", "component": "main", "type": VariableType.STATE} +] + +VARIABLE_INFO = [ + {"name": "k1", "units": "dimensionless", "component": "main", "type": VariableType.CONSTANT}, + {"name": "k3", "units": "dimensionless", "component": "main", "type": VariableType.CONSTANT}, + {"name": "k2", "units": "dimensionless", "component": "main", "type": VariableType.CONSTANT}, + {"name": "y2_scaled", "units": "dimensionless", "component": "main", "type": VariableType.ALGEBRAIC} +] + + +def create_states_array(): + return [nan]*STATE_COUNT + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +def initialise_variables(states, rates, variables): + variables[0] = 0.04 + variables[1] = 1.0e4 + variables[2] = 3.0e7 + states[0] = 1.0 + states[1] = 0.0 + states[2] = 0.0 + + +def compute_computed_constants(variables): + pass + + +def compute_rates(voi, states, rates, variables): + rates[0] = -variables[0]*states[0]+variables[1]*states[2]*states[1] + rates[2] = variables[0]*states[0]-variables[2]*pow(states[2], 2.0)-variables[1]*states[2]*states[1] + rates[1] = variables[2]*pow(states[2], 2.0) + + +def compute_variables(voi, states, rates, variables): + variables[3] = 10000.0*states[2] diff --git a/tests/resources/generator/sine_model_imports/model.c b/tests/resources/generator/sine_model_imports/model.c index 4a569d50f..62e268685 100644 --- a/tests/resources/generator/sine_model_imports/model.c +++ b/tests/resources/generator/sine_model_imports/model.c @@ -1,12 +1,12 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #include "model.h" #include #include -const char VERSION[] = "0.3.0"; -const char LIBCELLML_VERSION[] = "0.4.0"; +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; const size_t STATE_COUNT = 1; const size_t VARIABLE_COUNT = 10; @@ -18,26 +18,38 @@ const VariableInfo STATE_INFO[] = { }; const VariableInfo VARIABLE_INFO[] = { - {"C", "dimensionless", "main", CONSTANT}, - {"deriv_approx_initial_value", "dimensionless", "main", CONSTANT}, {"sin", "dimensionless", "actual_sin", ALGEBRAIC}, + {"deriv_approx_initial_value", "dimensionless", "main", CONSTANT}, + {"sin", "dimensionless", "parabolic_approx_sin", ALGEBRAIC}, + {"C", "dimensionless", "main", CONSTANT}, {"k2_oPi", "dimensionless", "parabolic_approx_sin", COMPUTED_CONSTANT}, {"k2Pi", "dimensionless", "parabolic_approx_sin", COMPUTED_CONSTANT}, {"kPi_2", "dimensionless", "parabolic_approx_sin", COMPUTED_CONSTANT}, {"kPi", "dimensionless", "parabolic_approx_sin", COMPUTED_CONSTANT}, {"kPi_32", "dimensionless", "parabolic_approx_sin", COMPUTED_CONSTANT}, - {"z", "dimensionless", "parabolic_approx_sin", ALGEBRAIC}, - {"sin", "dimensionless", "parabolic_approx_sin", ALGEBRAIC} + {"z", "dimensionless", "parabolic_approx_sin", ALGEBRAIC} }; double * createStatesArray() { - return malloc(STATE_COUNT*sizeof(double)); + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } double * createVariablesArray() { - return malloc(VARIABLE_COUNT*sizeof(double)); + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; } void deleteArray(double *array) @@ -45,15 +57,15 @@ void deleteArray(double *array) free(array); } -void initialiseVariables(double *states, double *variables) +void initialiseVariables(double *states, double *rates, double *variables) { - variables[0] = 0.75; variables[1] = 0.0; - variables[3] = 2.0/3.14159265358979; - variables[4] = 2.0*3.14159265358979; - variables[5] = 3.14159265358979/2.0; - variables[6] = 3.14159265358979; - variables[7] = 3.0*3.14159265358979/2.0; + variables[3] = 0.75; + variables[4] = 2.0/3.14159265358979; + variables[5] = 2.0*3.14159265358979; + variables[6] = 3.14159265358979/2.0; + variables[7] = 3.14159265358979; + variables[8] = 3.0*3.14159265358979/2.0; states[0] = variables[1]; } @@ -68,7 +80,7 @@ void computeRates(double voi, double *states, double *rates, double *variables) void computeVariables(double voi, double *states, double *rates, double *variables) { - variables[2] = sin(voi); - variables[8] = (voi < variables[5])?voi*variables[3]-0.5:(voi < variables[6])?(3.14159265358979-voi)*variables[3]-0.5:(voi < variables[7])?(voi-3.14159265358979)*variables[3]-0.5:(variables[4]-voi)*variables[3]-0.5; - variables[9] = (voi < variables[5])?-variables[8]*variables[8]+variables[0]+variables[8]:(voi < variables[6])?-variables[8]*variables[8]+variables[0]+variables[8]:(voi < variables[7])?variables[8]*variables[8]-variables[0]-variables[8]:variables[8]*variables[8]-variables[0]-variables[8]; + variables[0] = sin(voi); + variables[9] = (voi < variables[6])?voi*variables[4]-0.5:(voi < variables[7])?(3.14159265358979-voi)*variables[4]-0.5:(voi < variables[8])?(voi-3.14159265358979)*variables[4]-0.5:(variables[5]-voi)*variables[4]-0.5; + variables[2] = (voi < variables[6])?-variables[9]*variables[9]+variables[3]+variables[9]:(voi < variables[7])?-variables[9]*variables[9]+variables[3]+variables[9]:(voi < variables[8])?variables[9]*variables[9]-variables[3]-variables[9]:variables[9]*variables[9]-variables[3]-variables[9]; } diff --git a/tests/resources/generator/sine_model_imports/model.h b/tests/resources/generator/sine_model_imports/model.h index 6c89bde8e..58ad0cde8 100644 --- a/tests/resources/generator/sine_model_imports/model.h +++ b/tests/resources/generator/sine_model_imports/model.h @@ -1,4 +1,4 @@ -/* The content of this file was generated using the C profile of libCellML 0.4.0. */ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ #pragma once @@ -33,7 +33,7 @@ double * createStatesArray(); double * createVariablesArray(); void deleteArray(double *array); -void initialiseVariables(double *states, double *variables); +void initialiseVariables(double *states, double *rates, double *variables); void computeComputedConstants(double *variables); void computeRates(double voi, double *states, double *rates, double *variables); void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/sine_model_imports/model.py b/tests/resources/generator/sine_model_imports/model.py index a29075c41..d2846546b 100644 --- a/tests/resources/generator/sine_model_imports/model.py +++ b/tests/resources/generator/sine_model_imports/model.py @@ -1,11 +1,11 @@ -# The content of this file was generated using the Python profile of libCellML 0.4.0. +# The content of this file was generated using the Python profile of libCellML 0.5.0. from enum import Enum from math import * -__version__ = "0.3.1" -LIBCELLML_VERSION = "0.4.0" +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" STATE_COUNT = 1 VARIABLE_COUNT = 10 @@ -26,16 +26,16 @@ class VariableType(Enum): ] VARIABLE_INFO = [ - {"name": "C", "units": "dimensionless", "component": "main", "type": VariableType.CONSTANT}, - {"name": "deriv_approx_initial_value", "units": "dimensionless", "component": "main", "type": VariableType.CONSTANT}, {"name": "sin", "units": "dimensionless", "component": "actual_sin", "type": VariableType.ALGEBRAIC}, + {"name": "deriv_approx_initial_value", "units": "dimensionless", "component": "main", "type": VariableType.CONSTANT}, + {"name": "sin", "units": "dimensionless", "component": "parabolic_approx_sin", "type": VariableType.ALGEBRAIC}, + {"name": "C", "units": "dimensionless", "component": "main", "type": VariableType.CONSTANT}, {"name": "k2_oPi", "units": "dimensionless", "component": "parabolic_approx_sin", "type": VariableType.COMPUTED_CONSTANT}, {"name": "k2Pi", "units": "dimensionless", "component": "parabolic_approx_sin", "type": VariableType.COMPUTED_CONSTANT}, {"name": "kPi_2", "units": "dimensionless", "component": "parabolic_approx_sin", "type": VariableType.COMPUTED_CONSTANT}, {"name": "kPi", "units": "dimensionless", "component": "parabolic_approx_sin", "type": VariableType.COMPUTED_CONSTANT}, {"name": "kPi_32", "units": "dimensionless", "component": "parabolic_approx_sin", "type": VariableType.COMPUTED_CONSTANT}, - {"name": "z", "units": "dimensionless", "component": "parabolic_approx_sin", "type": VariableType.ALGEBRAIC}, - {"name": "sin", "units": "dimensionless", "component": "parabolic_approx_sin", "type": VariableType.ALGEBRAIC} + {"name": "z", "units": "dimensionless", "component": "parabolic_approx_sin", "type": VariableType.ALGEBRAIC} ] @@ -51,14 +51,14 @@ def create_variables_array(): return [nan]*VARIABLE_COUNT -def initialise_variables(states, variables): - variables[0] = 0.75 +def initialise_variables(states, rates, variables): variables[1] = 0.0 - variables[3] = 2.0/3.14159265358979 - variables[4] = 2.0*3.14159265358979 - variables[5] = 3.14159265358979/2.0 - variables[6] = 3.14159265358979 - variables[7] = 3.0*3.14159265358979/2.0 + variables[3] = 0.75 + variables[4] = 2.0/3.14159265358979 + variables[5] = 2.0*3.14159265358979 + variables[6] = 3.14159265358979/2.0 + variables[7] = 3.14159265358979 + variables[8] = 3.0*3.14159265358979/2.0 states[0] = variables[1] @@ -71,6 +71,6 @@ def compute_rates(voi, states, rates, variables): def compute_variables(voi, states, rates, variables): - variables[2] = sin(voi) - variables[8] = voi*variables[3]-0.5 if lt_func(voi, variables[5]) else (3.14159265358979-voi)*variables[3]-0.5 if lt_func(voi, variables[6]) else (voi-3.14159265358979)*variables[3]-0.5 if lt_func(voi, variables[7]) else (variables[4]-voi)*variables[3]-0.5 - variables[9] = -variables[8]*variables[8]+variables[0]+variables[8] if lt_func(voi, variables[5]) else -variables[8]*variables[8]+variables[0]+variables[8] if lt_func(voi, variables[6]) else variables[8]*variables[8]-variables[0]-variables[8] if lt_func(voi, variables[7]) else variables[8]*variables[8]-variables[0]-variables[8] + variables[0] = sin(voi) + variables[9] = voi*variables[4]-0.5 if lt_func(voi, variables[6]) else (3.14159265358979-voi)*variables[4]-0.5 if lt_func(voi, variables[7]) else (voi-3.14159265358979)*variables[4]-0.5 if lt_func(voi, variables[8]) else (variables[5]-voi)*variables[4]-0.5 + variables[2] = -variables[9]*variables[9]+variables[3]+variables[9] if lt_func(voi, variables[6]) else -variables[9]*variables[9]+variables[3]+variables[9] if lt_func(voi, variables[7]) else variables[9]*variables[9]-variables[3]-variables[9] if lt_func(voi, variables[8]) else variables[9]*variables[9]-variables[3]-variables[9] diff --git a/tests/resources/generator/unknown_variable_as_external_variable/model.c b/tests/resources/generator/unknown_variable_as_external_variable/model.c new file mode 100644 index 000000000..9cb6e9c27 --- /dev/null +++ b/tests/resources/generator/unknown_variable_as_external_variable/model.c @@ -0,0 +1,63 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t VARIABLE_COUNT = 10; + +const VariableInfo VARIABLE_INFO[] = { + {"v", "fmol_per_sec", "SLC_template3_ss", ALGEBRAIC}, + {"E", "fmol", "SLC_template3_ss", CONSTANT}, + {"P_0", "per_fmol_sec4", "SLC_template3_ss", CONSTANT}, + {"q_Ao", "fmol", "SLC_template3_ss", CONSTANT}, + {"P_1", "per_fmol_sec4", "SLC_template3_ss", CONSTANT}, + {"q_Ai", "fmol", "SLC_template3_ss", CONSTANT}, + {"P_2", "per_fmol_sec3", "SLC_template3_ss", CONSTANT}, + {"P_5", "per_sec3", "SLC_template3_ss", CONSTANT}, + {"P_4", "per_fmol2_sec3", "SLC_template3_ss", CONSTANT}, + {"P_3", "per_fmol_sec3", "SLC_template3_ss", EXTERNAL} +}; + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +void initialiseVariables(double *variables, ExternalVariable externalVariable) +{ + variables[1] = 1.1; + variables[2] = 21262500.0; + variables[3] = 150.0; + variables[4] = 3402000.0; + variables[5] = 2.0; + variables[6] = 2902500.0; + variables[7] = 810000.0; + variables[8] = 247140.0; + variables[9] = externalVariable(variables, 9); +} + +void computeComputedConstants(double *variables) +{ +} + +void computeVariables(double *variables, ExternalVariable externalVariable) +{ + variables[9] = externalVariable(variables, 9); + variables[0] = variables[1]*(variables[2]*variables[3]-variables[4]*variables[5])/(variables[6]*variables[5]+variables[9]*variables[3]+variables[8]*variables[5]*variables[3]+variables[7]); +} diff --git a/tests/resources/generator/unknown_variable_as_external_variable/model.cellml b/tests/resources/generator/unknown_variable_as_external_variable/model.cellml new file mode 100644 index 000000000..957d5a42a --- /dev/null +++ b/tests/resources/generator/unknown_variable_as_external_variable/model.cellml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + v + + + + + E + + + + + P_0 + q_Ao + + + + P_1 + q_Ai + + + + + + + + P_2 + q_Ai + + + + P_3 + q_Ao + + + + P_4 + q_Ai + q_Ao + + P_5 + + + + + + diff --git a/tests/resources/generator/unknown_variable_as_external_variable/model.h b/tests/resources/generator/unknown_variable_as_external_variable/model.h new file mode 100644 index 000000000..21c1b1569 --- /dev/null +++ b/tests/resources/generator/unknown_variable_as_external_variable/model.h @@ -0,0 +1,35 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t VARIABLE_COUNT; + +typedef enum { + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC, + EXTERNAL +} VariableType; + +typedef struct { + char name[5]; + char units[15]; + char component[17]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VARIABLE_INFO[]; + +double * createVariablesArray(); +void deleteArray(double *array); + +typedef double (* ExternalVariable)(double *variables, size_t index); + +void initialiseVariables(double *variables, ExternalVariable externalVariable); +void computeComputedConstants(double *variables); +void computeVariables(double *variables, ExternalVariable externalVariable); diff --git a/tests/resources/generator/unknown_variable_as_external_variable/model.py b/tests/resources/generator/unknown_variable_as_external_variable/model.py new file mode 100644 index 000000000..655783796 --- /dev/null +++ b/tests/resources/generator/unknown_variable_as_external_variable/model.py @@ -0,0 +1,56 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +VARIABLE_COUNT = 10 + + +class VariableType(Enum): + CONSTANT = 0 + COMPUTED_CONSTANT = 1 + ALGEBRAIC = 2 + EXTERNAL = 3 + + +VARIABLE_INFO = [ + {"name": "v", "units": "fmol_per_sec", "component": "SLC_template3_ss", "type": VariableType.ALGEBRAIC}, + {"name": "E", "units": "fmol", "component": "SLC_template3_ss", "type": VariableType.CONSTANT}, + {"name": "P_0", "units": "per_fmol_sec4", "component": "SLC_template3_ss", "type": VariableType.CONSTANT}, + {"name": "q_Ao", "units": "fmol", "component": "SLC_template3_ss", "type": VariableType.CONSTANT}, + {"name": "P_1", "units": "per_fmol_sec4", "component": "SLC_template3_ss", "type": VariableType.CONSTANT}, + {"name": "q_Ai", "units": "fmol", "component": "SLC_template3_ss", "type": VariableType.CONSTANT}, + {"name": "P_2", "units": "per_fmol_sec3", "component": "SLC_template3_ss", "type": VariableType.CONSTANT}, + {"name": "P_5", "units": "per_sec3", "component": "SLC_template3_ss", "type": VariableType.CONSTANT}, + {"name": "P_4", "units": "per_fmol2_sec3", "component": "SLC_template3_ss", "type": VariableType.CONSTANT}, + {"name": "P_3", "units": "per_fmol_sec3", "component": "SLC_template3_ss", "type": VariableType.EXTERNAL} +] + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +def initialise_variables(variables, external_variable): + variables[1] = 1.1 + variables[2] = 21262500.0 + variables[3] = 150.0 + variables[4] = 3402000.0 + variables[5] = 2.0 + variables[6] = 2902500.0 + variables[7] = 810000.0 + variables[8] = 247140.0 + variables[9] = external_variable(variables, 9) + + +def compute_computed_constants(variables): + pass + + +def compute_variables(variables, external_variable): + variables[9] = external_variable(variables, 9) + variables[0] = variables[1]*(variables[2]*variables[3]-variables[4]*variables[5])/(variables[6]*variables[5]+variables[9]*variables[3]+variables[8]*variables[5]*variables[3]+variables[7]) diff --git a/tests/resources/generator/variable_initialised_using_a_constant/model.c b/tests/resources/generator/variable_initialised_using_a_constant/model.c new file mode 100644 index 000000000..77ddcdddd --- /dev/null +++ b/tests/resources/generator/variable_initialised_using_a_constant/model.c @@ -0,0 +1,68 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#include "model.h" + +#include +#include + +const char VERSION[] = "0.4.0"; +const char LIBCELLML_VERSION[] = "0.5.0"; + +const size_t STATE_COUNT = 1; +const size_t VARIABLE_COUNT = 1; + +const VariableInfo VOI_INFO = {"t", "second", "component_1", VARIABLE_OF_INTEGRATION}; + +const VariableInfo STATE_INFO[] = { + {"X", "dimensionless", "component_1", STATE} +}; + +const VariableInfo VARIABLE_INFO[] = { + {"X_init", "dimensionless", "component_2", CONSTANT} +}; + +double * createStatesArray() +{ + double *res = (double *) malloc(STATE_COUNT*sizeof(double)); + + for (size_t i = 0; i < STATE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +double * createVariablesArray() +{ + double *res = (double *) malloc(VARIABLE_COUNT*sizeof(double)); + + for (size_t i = 0; i < VARIABLE_COUNT; ++i) { + res[i] = NAN; + } + + return res; +} + +void deleteArray(double *array) +{ + free(array); +} + +void initialiseVariables(double *states, double *rates, double *variables) +{ + variables[0] = 7.0; + states[0] = variables[0]; +} + +void computeComputedConstants(double *variables) +{ +} + +void computeRates(double voi, double *states, double *rates, double *variables) +{ + rates[0] = 3.0; +} + +void computeVariables(double voi, double *states, double *rates, double *variables) +{ +} diff --git a/tests/resources/generator/variable_initialised_using_a_constant/model.cellml b/tests/resources/generator/variable_initialised_using_a_constant/model.cellml new file mode 100644 index 000000000..3439329db --- /dev/null +++ b/tests/resources/generator/variable_initialised_using_a_constant/model.cellml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + t + + X + + 3 + + + + + + + + + + diff --git a/tests/resources/generator/variable_initialised_using_a_constant/model.h b/tests/resources/generator/variable_initialised_using_a_constant/model.h new file mode 100644 index 000000000..caeedf9c6 --- /dev/null +++ b/tests/resources/generator/variable_initialised_using_a_constant/model.h @@ -0,0 +1,39 @@ +/* The content of this file was generated using the C profile of libCellML 0.5.0. */ + +#pragma once + +#include + +extern const char VERSION[]; +extern const char LIBCELLML_VERSION[]; + +extern const size_t STATE_COUNT; +extern const size_t VARIABLE_COUNT; + +typedef enum { + VARIABLE_OF_INTEGRATION, + STATE, + CONSTANT, + COMPUTED_CONSTANT, + ALGEBRAIC +} VariableType; + +typedef struct { + char name[7]; + char units[14]; + char component[12]; + VariableType type; +} VariableInfo; + +extern const VariableInfo VOI_INFO; +extern const VariableInfo STATE_INFO[]; +extern const VariableInfo VARIABLE_INFO[]; + +double * createStatesArray(); +double * createVariablesArray(); +void deleteArray(double *array); + +void initialiseVariables(double *states, double *rates, double *variables); +void computeComputedConstants(double *variables); +void computeRates(double voi, double *states, double *rates, double *variables); +void computeVariables(double voi, double *states, double *rates, double *variables); diff --git a/tests/resources/generator/variable_initialised_using_a_constant/model.py b/tests/resources/generator/variable_initialised_using_a_constant/model.py new file mode 100644 index 000000000..4e53eb945 --- /dev/null +++ b/tests/resources/generator/variable_initialised_using_a_constant/model.py @@ -0,0 +1,55 @@ +# The content of this file was generated using the Python profile of libCellML 0.5.0. + +from enum import Enum +from math import * + + +__version__ = "0.4.0" +LIBCELLML_VERSION = "0.5.0" + +STATE_COUNT = 1 +VARIABLE_COUNT = 1 + + +class VariableType(Enum): + VARIABLE_OF_INTEGRATION = 0 + STATE = 1 + CONSTANT = 2 + COMPUTED_CONSTANT = 3 + ALGEBRAIC = 4 + + +VOI_INFO = {"name": "t", "units": "second", "component": "component_1", "type": VariableType.VARIABLE_OF_INTEGRATION} + +STATE_INFO = [ + {"name": "X", "units": "dimensionless", "component": "component_1", "type": VariableType.STATE} +] + +VARIABLE_INFO = [ + {"name": "X_init", "units": "dimensionless", "component": "component_2", "type": VariableType.CONSTANT} +] + + +def create_states_array(): + return [nan]*STATE_COUNT + + +def create_variables_array(): + return [nan]*VARIABLE_COUNT + + +def initialise_variables(states, rates, variables): + variables[0] = 7.0 + states[0] = variables[0] + + +def compute_computed_constants(variables): + pass + + +def compute_rates(voi, states, rates, variables): + rates[0] = 3.0 + + +def compute_variables(voi, states, rates, variables): + pass diff --git a/tests/resources/import-requirements/importExample2.cellml b/tests/resources/import-requirements/importExample2.cellml new file mode 100644 index 000000000..10cfdee70 --- /dev/null +++ b/tests/resources/import-requirements/importExample2.cellml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/tests/resources/importer/HHComplete/GateModel.cellml b/tests/resources/importer/HHComplete/GateModel.cellml new file mode 100644 index 000000000..66aa571ce --- /dev/null +++ b/tests/resources/importer/HHComplete/GateModel.cellml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + t + + X + + + + + + alpha_X + + + 1 + X + + + + + beta_X + X + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/importer/HHComplete/LeakageModel.cellml b/tests/resources/importer/HHComplete/LeakageModel.cellml new file mode 100644 index 000000000..71816b4af --- /dev/null +++ b/tests/resources/importer/HHComplete/LeakageModel.cellml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + i_L + + + g_L + + + V + E_L + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/importer/HHComplete/MembraneModel.cellml b/tests/resources/importer/HHComplete/MembraneModel.cellml new file mode 100644 index 000000000..317d2136c --- /dev/null +++ b/tests/resources/importer/HHComplete/MembraneModel.cellml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + i_tot + + + i_stim + + i_K + i_Na + i_L + + + + + + + + t + + V + + + + + + -1 + i_tot + + Cm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/importer/HHComplete/MembraneModelController.cellml b/tests/resources/importer/HHComplete/MembraneModelController.cellml new file mode 100644 index 000000000..a16ba7314 --- /dev/null +++ b/tests/resources/importer/HHComplete/MembraneModelController.cellml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + i_stim + + + 20 + + + + + t + 10 + + + + t + 10.5 + + + + + 0 + + + + + + diff --git a/tests/resources/importer/HHComplete/PotassiumChannelModel.cellml b/tests/resources/importer/HHComplete/PotassiumChannelModel.cellml new file mode 100644 index 000000000..c129b5e54 --- /dev/null +++ b/tests/resources/importer/HHComplete/PotassiumChannelModel.cellml @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + i_K + + + + + n + 4 + + g_K + + + V + E_K + + + + + + + + + + + + + + + + + + + + alpha_n + + + + + -0.01 + + + V + 65 + + + + + + + + + + + V + 65 + + -10 + + + 1 + + + + + + beta_n + + + 0.125 + + + + + + + V + 75 + + -80 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/importer/HHComplete/SodiumChannelModel.cellml b/tests/resources/importer/HHComplete/SodiumChannelModel.cellml new file mode 100644 index 000000000..9dcca3653 --- /dev/null +++ b/tests/resources/importer/HHComplete/SodiumChannelModel.cellml @@ -0,0 +1,294 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Na_conductance + + + g_Na + h + + + m + 3 + + + + + + i_Na + + + Na_conductance + + + V + E_Na + + + + + + + + + + + + + + + + + + + + + + + alpha_m + + + + + + + 0.1 + + + + V + 50 + + + + + + + + + + + + + V + 50 + + + 10 + + + 1 + + + + + + beta_m + + + 4 + + + + + + + + + V + 75 + + + 18 + + + + + + + + + + + + + + + + + + + + + + + + alpha_h + + + 0.07 + + + + + + + + + V + 75 + + + 20 + + + + + + + beta_h + + + 1 + + + + + + + + + + + V + 45 + + + 10 + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/importer/bondgraph/cpp_coupling.cellml b/tests/resources/importer/bondgraph/cpp_coupling.cellml new file mode 100644 index 000000000..e05112dd2 --- /dev/null +++ b/tests/resources/importer/bondgraph/cpp_coupling.cellml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/importer/bondgraph/cpp_coupling_modules.cellml b/tests/resources/importer/bondgraph/cpp_coupling_modules.cellml new file mode 100644 index 000000000..672ca9a6a --- /dev/null +++ b/tests/resources/importer/bondgraph/cpp_coupling_modules.cellml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + R_v + + + 0.01 + C + + + + + + + + + t + + v + + + + + + + + u + u_out + + + + R + v + + + I + + + + + + + + t + + q_C + + + + v_in + v + + + + + u_C + + + + + q_C + C + + u_ext + + + + + u + + + u_C + + + R_v + + + v_in + v + + + + + + + diff --git a/tests/resources/importer/bondgraph/cpp_coupling_parameters.cellml b/tests/resources/importer/bondgraph/cpp_coupling_parameters.cellml new file mode 100644 index 000000000..f0f252df2 --- /dev/null +++ b/tests/resources/importer/bondgraph/cpp_coupling_parameters.cellml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tests/resources/importer/complexbondgraph/cpp_coupling.cellml b/tests/resources/importer/complexbondgraph/cpp_coupling.cellml new file mode 100644 index 000000000..e05112dd2 --- /dev/null +++ b/tests/resources/importer/complexbondgraph/cpp_coupling.cellml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/importer/complexbondgraph/cpp_coupling_modules.cellml b/tests/resources/importer/complexbondgraph/cpp_coupling_modules.cellml new file mode 100644 index 000000000..672ca9a6a --- /dev/null +++ b/tests/resources/importer/complexbondgraph/cpp_coupling_modules.cellml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + R_v + + + 0.01 + C + + + + + + + + + t + + v + + + + + + + + u + u_out + + + + R + v + + + I + + + + + + + + t + + q_C + + + + v_in + v + + + + + u_C + + + + + q_C + C + + u_ext + + + + + u + + + u_C + + + R_v + + + v_in + v + + + + + + + diff --git a/tests/resources/importer/complexbondgraph/cpp_coupling_parameters.cellml b/tests/resources/importer/complexbondgraph/cpp_coupling_parameters.cellml new file mode 100644 index 000000000..f0f252df2 --- /dev/null +++ b/tests/resources/importer/complexbondgraph/cpp_coupling_parameters.cellml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tests/resources/importer/invalid_model.cellml b/tests/resources/importer/invalid_model.cellml index 1d8be4e52..317951bd6 100644 --- a/tests/resources/importer/invalid_model.cellml +++ b/tests/resources/importer/invalid_model.cellml @@ -1,8 +1,24 @@ + + + + + + + + + + + + + + + + @@ -13,4 +29,15 @@ + + + + + + + + + + + diff --git a/tests/resources/importer/mediumbondgraph/cpp_coupling.cellml b/tests/resources/importer/mediumbondgraph/cpp_coupling.cellml new file mode 100644 index 000000000..f211babc3 --- /dev/null +++ b/tests/resources/importer/mediumbondgraph/cpp_coupling.cellml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/importer/mediumbondgraph/cpp_coupling_modules.cellml b/tests/resources/importer/mediumbondgraph/cpp_coupling_modules.cellml new file mode 100644 index 000000000..53285f086 --- /dev/null +++ b/tests/resources/importer/mediumbondgraph/cpp_coupling_modules.cellml @@ -0,0 +1,19 @@ + + + + + + + + + + R_v + + + 0.01 + C + + + + + diff --git a/tests/resources/importer/mediumbondgraph/cpp_coupling_parameters.cellml b/tests/resources/importer/mediumbondgraph/cpp_coupling_parameters.cellml new file mode 100644 index 000000000..6448668ef --- /dev/null +++ b/tests/resources/importer/mediumbondgraph/cpp_coupling_parameters.cellml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/resources/importer/model1.cellml b/tests/resources/importer/model1.cellml new file mode 100644 index 000000000..4e4df365b --- /dev/null +++ b/tests/resources/importer/model1.cellml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tests/resources/importer/model2.cellml b/tests/resources/importer/model2.cellml new file mode 100644 index 000000000..f81b5b145 --- /dev/null +++ b/tests/resources/importer/model2.cellml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/resources/importer/model_cascaded_units.cellml b/tests/resources/importer/model_cascaded_units.cellml new file mode 100644 index 000000000..161579794 --- /dev/null +++ b/tests/resources/importer/model_cascaded_units.cellml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tests/resources/importer/simple_model.cellml b/tests/resources/importer/simple_model.cellml new file mode 100644 index 000000000..0f48667ab --- /dev/null +++ b/tests/resources/importer/simple_model.cellml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/tests/resources/importer/simple_model_2.cellml b/tests/resources/importer/simple_model_2.cellml new file mode 100644 index 000000000..da28a9232 --- /dev/null +++ b/tests/resources/importer/simple_model_2.cellml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tests/resources/importer/simplebondgraph/cpp_coupling.cellml b/tests/resources/importer/simplebondgraph/cpp_coupling.cellml new file mode 100644 index 000000000..354b0a29a --- /dev/null +++ b/tests/resources/importer/simplebondgraph/cpp_coupling.cellml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tests/resources/importer/simplebondgraph/cpp_coupling_modules.cellml b/tests/resources/importer/simplebondgraph/cpp_coupling_modules.cellml new file mode 100644 index 000000000..4b3e520ee --- /dev/null +++ b/tests/resources/importer/simplebondgraph/cpp_coupling_modules.cellml @@ -0,0 +1,18 @@ + + + + + + + + + R_v + + + 0.01 + C + + + + + diff --git a/tests/resources/importer/simplebondgraph/cpp_coupling_parameters.cellml b/tests/resources/importer/simplebondgraph/cpp_coupling_parameters.cellml new file mode 100644 index 000000000..6448668ef --- /dev/null +++ b/tests/resources/importer/simplebondgraph/cpp_coupling_parameters.cellml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/resources/importer/triangle_units_base.cellml b/tests/resources/importer/triangle_units_base.cellml new file mode 100644 index 000000000..b003466db --- /dev/null +++ b/tests/resources/importer/triangle_units_base.cellml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tests/resources/importer/triangle_units_opposite.cellml b/tests/resources/importer/triangle_units_opposite.cellml new file mode 100644 index 000000000..bbd497bdf --- /dev/null +++ b/tests/resources/importer/triangle_units_opposite.cellml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tests/resources/importer/triangle_units_opposite_I.cellml b/tests/resources/importer/triangle_units_opposite_I.cellml new file mode 100644 index 000000000..dfcbaae46 --- /dev/null +++ b/tests/resources/importer/triangle_units_opposite_I.cellml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tests/resources/importer/triangle_units_point.cellml b/tests/resources/importer/triangle_units_point.cellml new file mode 100644 index 000000000..3d4139543 --- /dev/null +++ b/tests/resources/importer/triangle_units_point.cellml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tests/resources/importer/triangle_units_point_I.cellml b/tests/resources/importer/triangle_units_point_I.cellml new file mode 100644 index 000000000..5bee9e73b --- /dev/null +++ b/tests/resources/importer/triangle_units_point_I.cellml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tests/resources/importer/units/base_model.cellml b/tests/resources/importer/units/base_model.cellml new file mode 100644 index 000000000..85003aee2 --- /dev/null +++ b/tests/resources/importer/units/base_model.cellml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + P + 3.0 + + + + diff --git a/tests/resources/importer/units/base_model_illdefined.cellml b/tests/resources/importer/units/base_model_illdefined.cellml new file mode 100644 index 000000000..bb25ac22a --- /dev/null +++ b/tests/resources/importer/units/base_model_illdefined.cellml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + P + 3.0 + + + + diff --git a/tests/resources/importer/units/left_model.cellml b/tests/resources/importer/units/left_model.cellml new file mode 100644 index 000000000..c76fef6a9 --- /dev/null +++ b/tests/resources/importer/units/left_model.cellml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tests/resources/importer/units/main.cellml b/tests/resources/importer/units/main.cellml new file mode 100644 index 000000000..fba92b78d --- /dev/null +++ b/tests/resources/importer/units/main.cellml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tests/resources/importer/units/right_model.cellml b/tests/resources/importer/units/right_model.cellml new file mode 100644 index 000000000..5345fd2fb --- /dev/null +++ b/tests/resources/importer/units/right_model.cellml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tests/resources/importer/units/units_definitions.cellml b/tests/resources/importer/units/units_definitions.cellml new file mode 100644 index 000000000..d5938a205 --- /dev/null +++ b/tests/resources/importer/units/units_definitions.cellml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tests/resources/invalidmathmlelementschildrenorsiblings.cellml b/tests/resources/invalidmathmlelementschildrenorsiblings.cellml new file mode 100644 index 000000000..991cb71da --- /dev/null +++ b/tests/resources/invalidmathmlelementschildrenorsiblings.cellml @@ -0,0 +1,904 @@ + + + + + + + + + + + + + + + + + + + + + a + + b + + + + + + + + + + + a + + b + + + + + + + + + + + a + + b + + + + + + + + + + + a + + b + + + + + + + + + + + a + + b + + + + + + + + + + + a + + b + + + + + + + + + + + a + + b + + + + + + + + + + + a + + b + + + + + + + + + + + a + + b + + + + + + + + + + + a + + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + b + + + + + + + + + + + a + + b + + + + + + + + + + + a + + b + + + + + + + + + + + a + + + + + a + + b + + + + + a + b + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + a + + b + + + + + a + b + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + + a + + b + + + + + a + b + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + a + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + A + + + + 3 + + + + 1 + + + + 3.21e5 + + + + 1789000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + + + + 1 + + 3 + + + + + 3 + + + + + + + + + + + Three + + + + + + + + Five + + + + + + Three + + 5 + + + + + + 3 + + 5 + + 7 + + + + + + 3 + + Five + + + + + + 1.234e5 + + 6 + + + + + + 1.234 + + 5.678e9 + + + + + + + + + + + + + + a + + + + a + + + + + a + + b + + + + + a + + + + + + + a + + + + + + + + + + + a + + b + + + + + a + + + + + + + a + + + + + + + + + + + a + + b + + + + + a + + + + + + + a + + + + + + + + + true + + + + + + + + + false + + + + + + + + + exponentiale + + + + + + + + + pi + + + + + + + + + infinity + + + + + + + + + notanumber + + + + + diff --git a/tests/resources/modelflattening/user_ex_01/child.cellml b/tests/resources/modelflattening/user_ex_01/child.cellml new file mode 100644 index 000000000..9c831375b --- /dev/null +++ b/tests/resources/modelflattening/user_ex_01/child.cellml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tests/resources/modelflattening/user_ex_01/parent.cellml b/tests/resources/modelflattening/user_ex_01/parent.cellml new file mode 100644 index 000000000..0043e3e73 --- /dev/null +++ b/tests/resources/modelflattening/user_ex_01/parent.cellml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tests/resources/printer/component_with_multiple_math.cellml b/tests/resources/printer/component_with_multiple_math.cellml new file mode 100644 index 000000000..5840f8258 --- /dev/null +++ b/tests/resources/printer/component_with_multiple_math.cellml @@ -0,0 +1,21 @@ + + + + + + + + + nK_stim + 0.3 + + + + + + stimPeriod + 42.6 + + + + diff --git a/tests/test_utils.cpp b/tests/test_utils.cpp index fa27bc4be..8aafe6088 100644 --- a/tests/test_utils.cpp +++ b/tests/test_utils.cpp @@ -231,6 +231,7 @@ void expectEqualIssuesSpecificationHeadingsUrls(const std::vector & { EXPECT_EQ(issues.size(), logger->issueCount()); EXPECT_EQ(specificationHeadings.size(), logger->issueCount()); + EXPECT_EQ(urls.size(), logger->issueCount()); for (size_t i = 0; i < logger->issueCount() && i < issues.size(); ++i) { EXPECT_EQ(issues.at(i), logger->issue(i)->description()); EXPECT_EQ(specificationHeadings.at(i), logger->issue(i)->referenceHeading()); @@ -248,6 +249,8 @@ void expectEqualIssuesCellmlElementTypesLevelsReferenceRulesUrls(const std::vect EXPECT_EQ(issues.size(), logger->issueCount()); EXPECT_EQ(cellmlElementTypes.size(), logger->issueCount()); EXPECT_EQ(levels.size(), logger->issueCount()); + EXPECT_EQ(referenceRules.size(), logger->issueCount()); + EXPECT_EQ(urls.size(), logger->issueCount()); for (size_t i = 0; i < logger->issueCount() && i < issues.size(); ++i) { EXPECT_EQ(issues.at(i), logger->issue(i)->description()); EXPECT_EQ(cellmlElementTypes.at(i), logger->issue(i)->item()->type()); diff --git a/tests/test_utils.h b/tests/test_utils.h index d4c059e87..041910670 100644 --- a/tests/test_utils.h +++ b/tests/test_utils.h @@ -36,7 +36,7 @@ const std::string NON_EMPTY_MATH = " var\n" " \n" " \n" - " 3.442\n" + " 3.442\n" " -9.612\n" " \n" " \n" diff --git a/tests/units/units.cpp b/tests/units/units.cpp index 2a70af66e..c3fb6ae48 100644 --- a/tests/units/units.cpp +++ b/tests/units/units.cpp @@ -363,6 +363,19 @@ TEST(Units, hasUnlinkedUnitsWhenBaseUnitsAddedToVariableButNotModel) EXPECT_TRUE(m->hasUnlinkedUnits()); } +TEST(Units, hasUnlinkedUnitsWhenVariableHasNoUnits) +{ + libcellml::ModelPtr m = libcellml::Model::create(); + libcellml::ComponentPtr c1 = libcellml::Component::create(); + + libcellml::VariablePtr v1 = libcellml::Variable::create(); + + c1->addVariable(v1); + m->addComponent(c1); + + EXPECT_FALSE(m->hasUnlinkedUnits()); +} + TEST(Units, hasLinkedUnitsWhenUnitsObjectAddedToBothModelAndVariable) { libcellml::ModelPtr m = libcellml::Model::create(); @@ -778,6 +791,13 @@ TEST(Units, unitAttributeReference) EXPECT_EQ("NewUnit", u->unitAttributeReference(0)); EXPECT_EQ("", u->unitAttributeReference(4)); + + u->setUnitAttributeReference(0, "NewerUnit"); + EXPECT_EQ("NewerUnit", u->unitAttributeReference(0)); + + u->setUnitAttributeReference(3, "FreshUnit"); + EXPECT_EQ("", u->unitAttributeReference(3)); + EXPECT_EQ("NewerUnit", u->unitAttributeReference(0)); } TEST(Units, unitAttributePrefix) @@ -1057,6 +1077,7 @@ TEST(Units, compareScalingFactorWithNullptrAsFirstParameter) u->addUnit(libcellml::Units::StandardUnit::LUX, 0, 1.0, 1.0); EXPECT_EQ(0.0, libcellml::Units::scalingFactor(nullptr, u)); + EXPECT_EQ(0.0, libcellml::Units::scalingFactor(nullptr, u, false)); } TEST(Units, compareScalingFactorWithNullptrAsSecondParameter) @@ -1066,11 +1087,13 @@ TEST(Units, compareScalingFactorWithNullptrAsSecondParameter) u->addUnit(libcellml::Units::StandardUnit::LUX, 0, 1.0, 1.0); EXPECT_EQ(0.0, libcellml::Units::scalingFactor(u, nullptr)); + EXPECT_EQ(0.0, libcellml::Units::scalingFactor(u, nullptr, false)); } TEST(Units, compareScalingFactorWithNullptrAsBothParameters) { EXPECT_EQ(0.0, libcellml::Units::scalingFactor(nullptr, nullptr)); + EXPECT_EQ(0.0, libcellml::Units::scalingFactor(nullptr, nullptr, false)); } TEST(Units, compareScalingFactorWithUnitBasedOnUnknownUnit) @@ -2700,6 +2723,32 @@ TEST(Units, unknownUnitsScalingFactorIncompatible) EXPECT_EQ(0.0, scaling); } +TEST(ExampleUnits, unitsScalingWithUnresolvedImports) +{ + const std::string modelString = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(modelString); + auto u2 = libcellml::Units::create("units"); + u2->addUnit("banana"); + + model->addUnits(u2); + auto u1 = model->units("strange_units"); + + auto scaling = libcellml::Units::scalingFactor(u1, u2, false); + EXPECT_EQ(0.0, scaling); +} + TEST(Units, circularImportDeeperLevelBaseUnits) { auto model1 = libcellml::Model::create("model1"); @@ -2757,3 +2806,633 @@ TEST(Units, validateConnectionsWithBaseUnits) EXPECT_EQ(size_t(0), validator->issueCount()); } + +TEST(Units, equivalentUnitsMatchingBuiltinUnits) +{ + libcellml::UnitsPtr units = libcellml::Units::create("kelvin"); + units->addUnit(libcellml::Units::StandardUnit::KELVIN); + + libcellml::UnitsPtr unitsClone = units->clone(); + + EXPECT_TRUE(libcellml::Units::compatible(units, unitsClone)); +} + +TEST(Units, equivalentUnitsMatchingBuiltinUnitsFromVariable) +{ + libcellml::ModelPtr model = libcellml::Model::create("unit_compatible_test"); + + libcellml::VariablePtr variable = libcellml::Variable::create("T"); + libcellml::UnitsPtr units = libcellml::Units::create("kelvin"); + units->addUnit(libcellml::Units::StandardUnit::KELVIN); + + model->addUnits(units); + variable->setUnits(units); + + libcellml::VariablePtr variableParam = variable->clone(); + + EXPECT_TRUE(libcellml::Units::compatible(variable->units(), variableParam->units())); +} + +TEST(Units, equivalentUnitsWithImportUsingNonExistentUnits) +{ + const std::string importModelString = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + ""; + const std::string modelString = + "\n" + "\n" + " \n" + " \n" + " \n" + ""; + + libcellml::ImporterPtr importer = libcellml::Importer::create(); + libcellml::ParserPtr parser = libcellml::Parser::create(); + + libcellml::ModelPtr model = parser->parseModel(modelString); + libcellml::ModelPtr importModel = parser->parseModel(importModelString); + + libcellml::UnitsPtr units = libcellml::Units::create("kelvin"); + units->addUnit(libcellml::Units::StandardUnit::KELVIN); + + model->addUnits(units); + + importer->addModel(importModel, "strange_units.cellml"); + importer->resolveImports(model, "."); + + EXPECT_FALSE(libcellml::Units::compatible(model->units(0), units)); +} + +libcellml::ModelPtr prepareImportUnitsWithReferenceToNonStandardUnits(const std::string &importUnitsName) +{ + libcellml::ModelPtr unitsModel = libcellml::Model::create("Units_Database"); + libcellml::ModelPtr model = libcellml::Model::create("main_model"); + + libcellml::UnitsPtr u1 = libcellml::Units::create("fmol"); + u1->addUnit("mole", "femto"); + libcellml::UnitsPtr u2 = libcellml::Units::create("per_fmol"); + u2->addUnit("fmol", -1.0); + libcellml::UnitsPtr u3 = libcellml::Units::create("per_sec"); + u3->addUnit("second", -1.0); + libcellml::UnitsPtr u4 = libcellml::Units::create("per_sec_fmol"); + u4->addUnit("per_sec"); + u4->addUnit("per_fmol"); + libcellml::UnitsPtr u5 = libcellml::Units::create(importUnitsName); + + unitsModel->addUnits(u1); + unitsModel->addUnits(u2); + unitsModel->addUnits(u3); + unitsModel->addUnits(u4); + + libcellml::ImportSourcePtr import = libcellml::ImportSource::create(); + import->setUrl("I_am_a_url"); + import->setModel(unitsModel); + + libcellml::ComponentPtr c = libcellml::Component::create("env"); + libcellml::VariablePtr v = libcellml::Variable::create("v"); + + u5->setImportSource(import); + u5->setImportReference("per_sec_fmol"); + + v->setUnits(u5); + c->addVariable(v); + model->addUnits(u5); + model->addComponent(c); + + EXPECT_FALSE(model->hasUnresolvedImports()); + + libcellml::ImporterPtr i = libcellml::Importer::create(); + + return i->flattenModel(model); +} + +TEST(Units, importUnitsWithReferenceToNonStandardUnits) +{ + libcellml::ModelPtr m = prepareImportUnitsWithReferenceToNonStandardUnits("pre_sec_fmol"); + EXPECT_TRUE(m->hasUnits("fmol")); +} + +TEST(Units, importUnitsWithReferenceToNonStandardUnitsDuplicateName) +{ + libcellml::ModelPtr m = prepareImportUnitsWithReferenceToNonStandardUnits("fmol"); + EXPECT_TRUE(m->hasUnits("fmol_1")); +} + +TEST(Units, importMultipleUnitsFromSameDocumentWithSameUnitsDependency) +{ + libcellml::ModelPtr unitsModel = libcellml::Model::create("Units_Database"); + libcellml::ModelPtr model = libcellml::Model::create("main_model"); + + libcellml::UnitsPtr u1 = libcellml::Units::create("fmol"); + u1->addUnit("mole", "femto"); + libcellml::UnitsPtr u2 = libcellml::Units::create("per_fmol"); + u2->addUnit("fmol", -1.0); + + libcellml::UnitsPtr iu1 = libcellml::Units::create("fmol"); + libcellml::UnitsPtr iu2 = libcellml::Units::create("per_fmol"); + + unitsModel->addUnits(u1); + unitsModel->addUnits(u2); + + libcellml::ImportSourcePtr import = libcellml::ImportSource::create(); + import->setUrl("I_am_a_url"); + import->setModel(unitsModel); + + iu1->setImportSource(import); + iu1->setImportReference("fmol"); + iu2->setImportSource(import); + iu2->setImportReference("per_fmol"); + + model->addUnits(iu1); + model->addUnits(iu2); + + EXPECT_FALSE(model->hasUnresolvedImports()); + + libcellml::ImporterPtr i = libcellml::Importer::create(); + + auto flatModel = i->flattenModel(model); + + EXPECT_EQ(size_t(2), flatModel->unitsCount()); + EXPECT_EQ("fmol", flatModel->units(0)->name()); + EXPECT_EQ("per_fmol", flatModel->units(1)->name()); +} + +TEST(Units, importUnitsMultipleWaysSameDocument) +{ + libcellml::ParserPtr parser = libcellml::Parser::create(); + libcellml::ImporterPtr importer = libcellml::Importer::create(); + + auto model = parser->parseModel(fileContents("importer/units/main.cellml")); + + EXPECT_TRUE(model->hasUnresolvedImports()); + + importer->resolveImports(model, resourcePath("importer/units")); + + EXPECT_FALSE(model->hasUnresolvedImports()); + + auto flatModel = importer->flattenModel(model); + + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(flatModel); + EXPECT_EQ(size_t(2), analyser->issueCount()); +} + +libcellml::ImportSourcePtr createBaseModelImport(libcellml::ModelPtr &importModel, const std::string &resourcePath) +{ + libcellml::ParserPtr parser = libcellml::Parser::create(); + + importModel = parser->parseModel(fileContents(resourcePath)); + + libcellml::ImportSourcePtr import = libcellml::ImportSource::create(); + import->setUrl("I_am_a_url"); + import->setModel(importModel); + + return import; +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceDirectly) +{ + libcellml::ModelPtr importModel; + libcellml::ImporterPtr importer = libcellml::Importer::create(); + libcellml::ImportSourcePtr import = createBaseModelImport(importModel, "importer/units/base_model.cellml"); + + libcellml::ModelPtr model = libcellml::Model::create("main_model"); + + libcellml::UnitsPtr iu = libcellml::Units::create("per_fmol"); + iu->setImportSource(import); + iu->setImportReference("per_fmol"); + + model->addUnits(iu); + + auto flatModel = importer->flattenModel(model); + + EXPECT_EQ(size_t(2), flatModel->unitsCount()); + EXPECT_EQ("per_fmol", flatModel->units(0)->name()); + EXPECT_EQ("fmol", flatModel->units(1)->name()); +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceThroughComponent) +{ + libcellml::ModelPtr importModel; + libcellml::ImporterPtr importer = libcellml::Importer::create(); + libcellml::ImportSourcePtr import = createBaseModelImport(importModel, "importer/units/base_model.cellml"); + + libcellml::ModelPtr model = libcellml::Model::create("main_model"); + + libcellml::ComponentPtr ic = libcellml::Component::create("my_component"); + ic->setImportSource(import); + ic->setImportReference("my_component"); + + model->addComponent(ic); + + auto flatModel = importer->flattenModel(model); + + EXPECT_EQ(size_t(0), importer->issueCount()); +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceDirectlyWithExistingEquivalentUnits) +{ + libcellml::ModelPtr importModel; + libcellml::ImporterPtr importer = libcellml::Importer::create(); + libcellml::ImportSourcePtr import = createBaseModelImport(importModel, "importer/units/base_model.cellml"); + + libcellml::ModelPtr model = libcellml::Model::create("main_model"); + + libcellml::UnitsPtr iu = libcellml::Units::create("per_fmol"); + iu->setImportSource(import); + iu->setImportReference("per_fmol"); + + libcellml::UnitsPtr u = libcellml::Units::create("fmol"); + u->addUnit("mole", "femto"); + model->addUnits(iu); + model->addUnits(u); + + auto flatModel = importer->flattenModel(model); + + EXPECT_EQ(size_t(2), flatModel->unitsCount()); + EXPECT_EQ("per_fmol", flatModel->units(0)->name()); + EXPECT_EQ("fmol", flatModel->units(1)->name()); +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceDirectlyWithExistingEquivalentUnitsWithDifferentName) +{ + libcellml::ModelPtr importModel; + libcellml::ImporterPtr importer = libcellml::Importer::create(); + libcellml::ImportSourcePtr import = createBaseModelImport(importModel, "importer/units/base_model.cellml"); + + libcellml::ModelPtr model = libcellml::Model::create("main_model"); + + libcellml::UnitsPtr iu = libcellml::Units::create("per_fmol"); + iu->setImportSource(import); + iu->setImportReference("per_fmol"); + + libcellml::UnitsPtr u = libcellml::Units::create("femto_mole"); + u->addUnit("mole", "femto"); + model->addUnits(iu); + model->addUnits(u); + + auto flatModel = importer->flattenModel(model); + + EXPECT_EQ(size_t(2), flatModel->unitsCount()); + EXPECT_EQ("per_fmol", flatModel->units(0)->name()); + EXPECT_EQ("femto_mole", flatModel->units(1)->name()); +} + +libcellml::ModelPtr setupFlattenImportedUnitsThroughComponent(const std::string &baseModelName) +{ + libcellml::ModelPtr importModel; + libcellml::ImporterPtr importer = libcellml::Importer::create(); + libcellml::ImportSourcePtr import = createBaseModelImport(importModel, baseModelName); + + libcellml::ModelPtr model = libcellml::Model::create("main_model"); + + libcellml::ComponentPtr ic = libcellml::Component::create("my_component"); + ic->setImportSource(import); + ic->setImportReference("my_component"); + + libcellml::UnitsPtr u = libcellml::Units::create("fmol"); + u->addUnit("mole", "femto"); + + model->addComponent(ic); + model->addUnits(u); + + return importer->flattenModel(model); +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceDirectlyWithExistingEquivalentUnitsThroughComponent) +{ + auto flatModel = setupFlattenImportedUnitsThroughComponent("importer/units/base_model.cellml"); + + EXPECT_EQ(size_t(2), flatModel->unitsCount()); + EXPECT_EQ("fmol", flatModel->units(0)->name()); + EXPECT_EQ("per_fmol", flatModel->units(1)->name()); + EXPECT_EQ("per_fmol", flatModel->component(0)->variable(0)->units()->name()); +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceDirectlyWithExistingEquivalentUnitsThroughComponentContainingIllDefinedUnits) +{ + auto flatModel = setupFlattenImportedUnitsThroughComponent("importer/units/base_model_illdefined.cellml"); + + EXPECT_EQ(nullptr, flatModel); +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceDirectlyWithExistingEquivalentUnitsWithDifferentNameThroughComponent) +{ + libcellml::ModelPtr importModel; + libcellml::ImporterPtr importer = libcellml::Importer::create(); + libcellml::ImportSourcePtr import = createBaseModelImport(importModel, "importer/units/base_model.cellml"); + + libcellml::ModelPtr model = libcellml::Model::create("main_model"); + + libcellml::ComponentPtr ic = libcellml::Component::create("my_component"); + ic->setImportSource(import); + ic->setImportReference("my_component"); + + libcellml::UnitsPtr u = libcellml::Units::create("femtomole"); + u->addUnit("mole", "femto"); + + model->addComponent(ic); + model->addUnits(u); + + auto flatModel = importer->flattenModel(model); + + EXPECT_EQ(size_t(2), flatModel->unitsCount()); + EXPECT_EQ("femtomole", flatModel->units(0)->name()); + EXPECT_EQ("per_fmol", flatModel->units(1)->name()); + EXPECT_EQ("femtomole", flatModel->units(1)->unitAttributeReference(0)); + EXPECT_EQ("per_fmol", flatModel->component(0)->variable(0)->units()->name()); +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceDirectlyWithExistingNonEquivalentUnits) +{ + libcellml::ModelPtr importModel; + libcellml::ImporterPtr importer = libcellml::Importer::create(); + libcellml::ImportSourcePtr import = createBaseModelImport(importModel, "importer/units/base_model.cellml"); + + libcellml::ModelPtr model = libcellml::Model::create("main_model"); + + libcellml::UnitsPtr iu = libcellml::Units::create("per_fmol"); + iu->setImportSource(import); + iu->setImportReference("per_fmol"); + + libcellml::UnitsPtr u = libcellml::Units::create("fmol"); + u->addUnit("farad"); + u->addUnit("mole"); + model->addUnits(iu); + model->addUnits(u); + + auto flatModel = importer->flattenModel(model); + + EXPECT_EQ(size_t(3), flatModel->unitsCount()); + EXPECT_EQ("per_fmol", flatModel->units(0)->name()); + EXPECT_EQ("fmol", flatModel->units(1)->name()); + EXPECT_EQ("fmol_1", flatModel->units(2)->name()); +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceDirectlyWithExistingNonEquivalentUnitsThroughComponent) +{ + libcellml::ModelPtr importModel; + libcellml::ImporterPtr importer = libcellml::Importer::create(); + libcellml::ImportSourcePtr import = createBaseModelImport(importModel, "importer/units/base_model.cellml"); + + libcellml::ModelPtr model = libcellml::Model::create("main_model"); + + libcellml::ComponentPtr ic = libcellml::Component::create("my_component"); + ic->setImportSource(import); + ic->setImportReference("my_component"); + + libcellml::UnitsPtr u = libcellml::Units::create("fmol"); + u->addUnit("farad"); + u->addUnit("mole"); + + model->addComponent(ic); + model->addUnits(u); + + auto flatModel = importer->flattenModel(model); + + EXPECT_EQ(size_t(3), flatModel->unitsCount()); + EXPECT_EQ("fmol", flatModel->units(0)->name()); + EXPECT_EQ("fmol_1", flatModel->units(1)->name()); + EXPECT_EQ("per_fmol", flatModel->units(2)->name()); + EXPECT_EQ("fmol_1", flatModel->units(2)->unitAttributeReference(0)); + EXPECT_EQ("per_fmol", flatModel->component(0)->variable(0)->units()->name()); +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceDirectlyWithExistingNonEquivalentUnitsThroughComponentWithVariableNeedingRenamedUnits) +{ + libcellml::ModelPtr importModel; + libcellml::ImporterPtr importer = libcellml::Importer::create(); + libcellml::ImportSourcePtr import = createBaseModelImport(importModel, "importer/units/base_model.cellml"); + + libcellml::ModelPtr model = libcellml::Model::create("main_model"); + + libcellml::ComponentPtr ic = libcellml::Component::create("my_component"); + ic->setImportSource(import); + ic->setImportReference("my_component"); + + libcellml::VariablePtr v = libcellml::Variable::create("R"); + v->setUnits("fmol"); + importModel->component(0)->addVariable(v); + + libcellml::UnitsPtr u = libcellml::Units::create("fmol"); + u->addUnit("farad"); + u->addUnit("mole"); + + model->addComponent(ic); + model->addUnits(u); + + auto flatModel = importer->flattenModel(model); + + EXPECT_EQ(size_t(3), flatModel->unitsCount()); + EXPECT_EQ("fmol", flatModel->units(0)->name()); + EXPECT_EQ("fmol_1", flatModel->units(1)->name()); + EXPECT_EQ("per_fmol", flatModel->units(2)->name()); + EXPECT_EQ("fmol_1", flatModel->units(2)->unitAttributeReference(0)); + EXPECT_EQ("per_fmol", flatModel->component(0)->variable(0)->units()->name()); + EXPECT_EQ("fmol_1", flatModel->component(0)->variable(1)->units()->name()); +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceDirectlyWithExistingNonEquivalentUnitsThroughComponentWithCnNeedingRenamedUnits) +{ + const std::string math = + "\n" + " \n" + " \n" + " P\n" + " 3.0\n" + " \n" + " \n" + " \n" + " R\n" + " 4.2\n" + " \n" + ""; + + libcellml::ModelPtr importModel; + libcellml::ImporterPtr importer = libcellml::Importer::create(); + libcellml::ImportSourcePtr import = createBaseModelImport(importModel, "importer/units/base_model.cellml"); + + libcellml::ModelPtr model = libcellml::Model::create("main_model"); + + libcellml::ComponentPtr ic = libcellml::Component::create("my_component"); + ic->setImportSource(import); + ic->setImportReference("my_component"); + + importModel->component(0)->setMath(math); + + libcellml::UnitsPtr u = libcellml::Units::create("fmol"); + u->addUnit("farad"); + u->addUnit("mole"); + + model->addComponent(ic); + model->addUnits(u); + + auto flatModel = importer->flattenModel(model); + + EXPECT_EQ(size_t(3), flatModel->unitsCount()); + EXPECT_EQ("fmol", flatModel->units(0)->name()); + EXPECT_EQ("fmol_1", flatModel->units(1)->name()); + EXPECT_EQ("per_fmol", flatModel->units(2)->name()); + EXPECT_EQ("fmol_1", flatModel->units(2)->unitAttributeReference(0)); + EXPECT_EQ("per_fmol", flatModel->component(0)->variable(0)->units()->name()); + EXPECT_TRUE(flatModel->component(0)->math().find("fmol_1") != std::string::npos); +} + +void setupFlattenImportedUnits(libcellml::ImporterPtr &importer, libcellml::ModelPtr &model, const std::string &variation) +{ + libcellml::ModelPtr unitsDefinitionsModel; + libcellml::ImportSourcePtr import = createBaseModelImport(unitsDefinitionsModel, "importer/units/units_definitions.cellml"); + + libcellml::ModelPtr intermediaryImportModel1 = libcellml::Model::create("import_model1"); + libcellml::ModelPtr intermediaryImportModel2 = libcellml::Model::create("import_model2"); + + importer = libcellml::Importer::create(); + + importer->addModel(unitsDefinitionsModel, "units_definitions"); + importer->addModel(intermediaryImportModel1, "int1"); + importer->addModel(intermediaryImportModel2, "int2"); + + model = libcellml::Model::create("main_model"); + + libcellml::UnitsPtr iu1 = libcellml::Units::create("per_fmol"); + iu1->setImportSource(import); + iu1->setImportReference("per_fmol"); + + libcellml::UnitsPtr iu2 = libcellml::Units::create("fmol"); + iu2->setImportSource(import); + iu2->setImportReference("fmol"); + + intermediaryImportModel1->addUnits(iu1); + intermediaryImportModel2->addUnits(iu2); + + libcellml::ImportSourcePtr importIntermediary1 = libcellml::ImportSource::create(); + importIntermediary1->setUrl("I_am_a_url"); + importIntermediary1->setModel(intermediaryImportModel1); + + libcellml::ImportSourcePtr importIntermediary2 = libcellml::ImportSource::create(); + importIntermediary2->setUrl("I_am_a_url"); + importIntermediary2->setModel(intermediaryImportModel2); + + libcellml::UnitsPtr iu3 = libcellml::Units::create("per_fmol"); + iu3->setImportSource(importIntermediary1); + iu3->setImportReference("per_fmol"); + + libcellml::UnitsPtr iu4 = libcellml::Units::create("fmol"); + iu4->setImportSource(importIntermediary2); + iu4->setImportReference("fmol"); + + if (!variation.empty()) { + libcellml::UnitsPtr u = libcellml::Units::create("fmol"); + u->addUnit("mole", "femto"); + if (variation == "int1") { + intermediaryImportModel1->addUnits(u); + } else if (variation == "main") { + model->addUnits(u); + } + } + + model->addUnits(iu3); + model->addUnits(iu4); +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceFromTwoLevelsDeep) +{ + libcellml::ImporterPtr importer; + libcellml::ModelPtr model; + + setupFlattenImportedUnits(importer, model, ""); + + auto flatModel = importer->flattenModel(model); + + EXPECT_EQ(size_t(2), flatModel->unitsCount()); + EXPECT_EQ("per_fmol", flatModel->units(0)->name()); + EXPECT_EQ("fmol", flatModel->units(1)->name()); +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceFromTwoLevelsDeepEquivalentUnitsInIntermediary) +{ + libcellml::ImporterPtr importer; + libcellml::ModelPtr model; + + setupFlattenImportedUnits(importer, model, "int1"); + + auto flatModel = importer->flattenModel(model); + + EXPECT_EQ(size_t(2), flatModel->unitsCount()); + EXPECT_EQ("per_fmol", flatModel->units(0)->name()); + EXPECT_EQ("fmol", flatModel->units(1)->name()); +} + +TEST(Units, flattenImportedUnitsWithNonStandardReferenceFromTwoLevelsDeepEquivalentUnitsInMain) +{ + libcellml::ImporterPtr importer; + libcellml::ModelPtr model; + + setupFlattenImportedUnits(importer, model, "main"); + + auto flatModel = importer->flattenModel(model); + + EXPECT_EQ(size_t(3), flatModel->unitsCount()); + EXPECT_EQ("fmol", flatModel->units(0)->name()); + EXPECT_EQ("per_fmol", flatModel->units(1)->name()); + EXPECT_EQ("fmol", flatModel->units(2)->name()); +} + +TEST(Units, aliasingUnits) +{ + libcellml::UnitsPtr u1 = libcellml::Units::create("per_hour"); + u1->addUnit("mm"); + libcellml::UnitsPtr u2 = libcellml::Units::create("mm"); + u2->addUnit("second", "milli"); + + libcellml::ModelPtr model = libcellml::Model::create("containing_model"); + + model->addUnits(u1); + model->addUnits(u2); + + EXPECT_TRUE(libcellml::Units::equivalent(u1, u2)); +} + +TEST(Units, definedUnitsBaseUnit) +{ + libcellml::UnitsPtr u = libcellml::Units::create("base_unit"); + + EXPECT_TRUE(u->isDefined()); +} + +TEST(Units, definedUnitsStandardUnit) +{ + libcellml::UnitsPtr u = libcellml::Units::create("only_standard_units"); + u->addUnit("second"); + u->addUnit("farad"); + + EXPECT_TRUE(u->isDefined()); +} + +TEST(Units, undefinedUnitsNonStandardUnit) +{ + libcellml::UnitsPtr u = libcellml::Units::create("only_standard_units"); + u->addUnit("battle"); + + EXPECT_FALSE(u->isDefined()); + EXPECT_TRUE(u->isResolved()); +} + +TEST(Units, definedUnitsImport) +{ + libcellml::UnitsPtr u = libcellml::Units::create("only_standard_units"); + + libcellml::ImportSourcePtr importSource = libcellml::ImportSource::create(); + importSource->setUrl("I_am_a_url"); + + u->setImportSource(importSource); + u->setImportReference("ref"); + + EXPECT_FALSE(u->isDefined()); +} diff --git a/tests/validator/validator.cpp b/tests/validator/validator.cpp index 1b76019d5..0bc8ee0f4 100644 --- a/tests/validator/validator.cpp +++ b/tests/validator/validator.cpp @@ -193,6 +193,33 @@ TEST(Validator, modelWithDuplicateComponentsAndUnits) EXPECT_EQ_ISSUES(expectedIssues, validator); } +TEST(Validator, unitsHasReferenceToStandardUnitsDefinedInModel) +{ + const std::string e = "Units is named 'second' which is a protected standard unit name."; + + libcellml::ValidatorPtr validator = libcellml::Validator::create(); + libcellml::ModelPtr model = libcellml::Model::create(); + libcellml::ComponentPtr c1 = libcellml::Component::create(); + libcellml::UnitsPtr u1 = libcellml::Units::create(); + libcellml::UnitsPtr u2 = libcellml::Units::create(); + + model->addComponent(c1); + model->addUnits(u1); + model->addUnits(u2); + + model->setName("model"); + c1->setName("michael"); + u1->setName("keaton"); + u2->setName("second"); + + u1->addUnit("second"); + + validator->validateModel(model); + + EXPECT_EQ(size_t(1), validator->errorCount()); + EXPECT_EQ(e, validator->error(0)->description()); +} + TEST(Validator, unnamedAndDuplicateNamedVariablesWithAndWithoutValidUnits) { const std::vector expectedIssues = { @@ -200,7 +227,9 @@ TEST(Validator, unnamedAndDuplicateNamedVariablesWithAndWithoutValidUnits) "Component 'fargo' contains multiple variables with the name 'margie'. Valid variable names must be unique to their component.", "Variable 'margie' in component 'fargo' does not have any units specified.", "Variable 'ransom' in component 'fargo' has a units reference 'dollars' which is neither standard nor defined in the parent model.", - "Variable 'mullah' in component 'fargo' does not have a valid units attribute. The attribute given is '$$'. CellML identifiers must not contain any characters other than [a-zA-Z0-9_]."}; + "Variable 'mullah' in component 'fargo' does not have a valid units attribute. The attribute given is '$$'. CellML identifiers must not contain any characters other than [a-zA-Z0-9_].", + "Variable '' in component 'fargo' does not have a valid name attribute. CellML identifiers must contain one or more basic Latin alphabetic characters.", + }; libcellml::ValidatorPtr validator = libcellml::Validator::create(); libcellml::ModelPtr model = libcellml::Model::create(); @@ -210,6 +239,7 @@ TEST(Validator, unnamedAndDuplicateNamedVariablesWithAndWithoutValidUnits) libcellml::VariablePtr v3 = libcellml::Variable::create(); libcellml::VariablePtr v4 = libcellml::Variable::create(); libcellml::VariablePtr v5 = libcellml::Variable::create(); + libcellml::VariablePtr v6 = libcellml::Variable::create(); model->addComponent(c1); c1->addVariable(v1); @@ -217,6 +247,7 @@ TEST(Validator, unnamedAndDuplicateNamedVariablesWithAndWithoutValidUnits) c1->addVariable(v3); c1->addVariable(v4); c1->addVariable(v5); + c1->addVariable(v6); model->setName("minnesota"); c1->setName("fargo"); @@ -229,6 +260,8 @@ TEST(Validator, unnamedAndDuplicateNamedVariablesWithAndWithoutValidUnits) v4->setUnits("dollars"); v5->setName("mullah"); v5->setUnits("$$"); + v6->setName(""); + v6->setUnits("second"); validator->validateModel(model); @@ -760,6 +793,11 @@ TEST(Validator, invalidMathMLVariables) "MathML ci element has the child text 'new_bvar' which does not correspond with any variable names present in component 'componentName'.", "W3C MathML DTD error: Element nonsense is not declared in ci list of possible children.", "W3C MathML DTD error: No declaration for element nonsense.", + "Math has a 'eq' element without exactly two MathML siblings.", + "Math has a 'bvar' element which first sibling is not a 'diff' element.", + "Math has a 'ci' element with no identifier as a child.", + "Math has a 'ci' element with no identifier as a child.", + "Math has a 'bvar' element which first sibling is not a 'diff' element.", }; libcellml::ValidatorPtr v = libcellml::Validator::create(); @@ -807,6 +845,7 @@ TEST(Validator, invalidSimpleMathmlCellMLUnits) "MathML ci element has the child text 'B' which does not correspond with any variable names present in component ''.", "W3C MathML DTD error: Element apply content does not follow the DTD, expecting (csymbol | ci | cn | apply | reln | lambda | condition | declare | sep | semantics | annotation | annotation-xml | integers | reals | rationals | naturalnumbers | complexes | primes | exponentiale | imaginaryi | notanumber | true | false | emptyset | pi | eulergamma | infinity | interval | list | matrix | matrixrow | set | vector | piecewise | lowlimit | uplimit | bvar | degree | logbase | momentabout | domainofapplication | inverse | ident | domain | codomain | image | abs | conjugate | exp | factorial | arg | real | imaginary | floor | ceiling | not | ln | sin | cos | tan | sec | csc | cot | sinh | cosh | tanh | sech | csch | coth | arcsin | arccos | arctan | arccosh | arccot | arccoth | arccsc | arccsch | arcsec | arcsech | arcsinh | arctanh | determinant | transpose | card | quotient | divide | power | rem | implies | vectorproduct | scalarproduct | outerproduct | setdiff | fn | compose | plus | times | max | min | gcd | lcm | and | or | xor | union | intersect | cartesianproduct | mean | sdev | variance | median | mode | selector | root | minus | log | int | diff | partialdiff | divergence | grad | curl | laplacian | sum | product | limit | moment | exists | forall | neq | factorof | in | notin | notsubset | notprsubset | tendsto | eq | leq | lt | geq | gt | equivalent | approx | subset | prsubset | mi | mn | mo | mtext | ms | mspace | mrow | mfrac | msqrt | mroot | menclose | mstyle | merror | mpadded | mphantom | mfenced | msub | msup | msubsup | munder | mover | munderover | mmultiscripts | mtable | mtr | mlabeledtr | mtd | maligngroup | malignmark | maction)*, got (CDATA bvar ).", "W3C MathML DTD error: No declaration for attribute units of element ci.", + "Math has a 'bvar' element without exactly two MathML siblings.", }; libcellml::ValidatorPtr v = libcellml::Validator::create(); libcellml::ModelPtr m = libcellml::Model::create(); @@ -829,6 +868,7 @@ TEST(Validator, invalidMathmlCellMLNsOnNode) "Math has a 'bvar' element that is not a supported MathML element.", "MathML ci element has the child text 'B' which does not correspond with any variable names present in component ''.", "W3C MathML DTD error: No declaration for attribute units of element ci.", + "Math has a 'bvar' element without exactly two MathML siblings.", }; libcellml::ValidatorPtr v = libcellml::Validator::create(); libcellml::ModelPtr m = libcellml::Model::create(); @@ -887,6 +927,11 @@ TEST(Validator, invalidMathMLCiAndCnElementsWithCellMLUnits) "Math cn element with the value '2.0' does not have a valid cellml:units attribute. CellML identifiers must contain one or more basic Latin alphabetic characters.", "W3C MathML DTD error: No declaration for attribute units of element ci.", "W3C MathML DTD error: No declaration for attribute units of element ci.", + "Math has a 'cn' element of 'real' type with no valid text node (representing a basic number) as a child.", + "Math has a 'bvar' element which first sibling is not a 'diff' element.", + "Math has a 'ci' element with no identifier as a child.", + "Math has a 'ci' element with no identifier as a child.", + "Math has a 'bvar' element without exactly two MathML siblings.", }; libcellml::ValidatorPtr v = libcellml::Validator::create(); @@ -1589,7 +1634,7 @@ TEST(Validator, validMathCnElements) " C\n" " \n" " \n" - " 3.442\n" + " 3.442\n" " -9.612\n" " \n" " \n" @@ -1623,7 +1668,7 @@ TEST(Validator, validMathCnElementsMissingCellMLNamespace) " C\n" " \n" " \n" - " 3.442\n" + " 3.442\n" " -9.612\n" " \n" " \n" @@ -2110,7 +2155,6 @@ TEST(Validator, unitMissingEquivalentUnits) auto v2 = c2->variable(0); v2->setUnits("second"); - v2->setInterfaceType("public"); libcellml::Variable::addEquivalence(v1, v2); validator->validateModel(m); @@ -2211,6 +2255,59 @@ TEST(Validator, unitStandardUnitsWhichAreNotBaseUnits) EXPECT_EQ_ISSUES(expectedIssues, validator); } +TEST(Validator, unitNonStandardUnitsWhichAreBaseUnits) +{ + const std::vector expectedIssues = { + "Variable 'v1' in component 'c1' has a units reference 'orange' which is neither standard nor defined in the parent model.", + "Variable 'v2' in component 'c2' has a units reference 'apple' which is neither standard nor defined in the parent model.", + }; + + libcellml::ValidatorPtr validator = libcellml::Validator::create(); + libcellml::ModelPtr m = createModelTwoComponentsWithOneVariableEach("m", "c1", "c2", "v1", "v2"); + auto c1 = m->component(0); + auto c2 = m->component(1); + auto v1 = c1->variable(0); + auto v2 = c2->variable(0); + + v1->setUnits("orange"); + v2->setUnits("apple"); + + libcellml::Variable::addEquivalence(v1, v2); // orange != apple. + + validator->validateModel(m); + + EXPECT_EQ_ISSUES(expectedIssues, validator); +} + +TEST(Validator, multipleEquivalentUnitStandardUnitsWhichAreNotBaseUnits) +{ + const std::vector expectedIssues = { + "Variable 'v1' in component 'c1' has units of 'litre' and an equivalent variable 'v2' in component 'c2' with non-matching units of 'gram'. The mismatch is: kilogram^-1, metre^3.", + "Variable 'v1' in component 'c1' has units of 'litre' and an equivalent variable 'v3' in component 'c1' with non-matching units of 'ampere'. The mismatch is: ampere^-1, metre^3, multiplication factor of 10^-3.", + }; + + libcellml::ValidatorPtr validator = libcellml::Validator::create(); + libcellml::ModelPtr m = createModelTwoComponentsWithOneVariableEach("m", "c1", "c2", "v1", "v2"); + auto c1 = m->component(0); + auto c2 = m->component(1); + auto v1 = c1->variable(0); + auto v2 = c2->variable(0); + auto v3 = libcellml::Variable::create("v3"); + v3->setInterfaceType("public"); + c1->addVariable(v3); + + v1->setUnits("litre"); + v2->setUnits("gram"); + v3->setUnits("ampere"); + + libcellml::Variable::addEquivalence(v1, v2); // litre != gram. + libcellml::Variable::addEquivalence(v1, v3); // litre != ampere. + + validator->validateModel(m); + + EXPECT_EQ_ISSUES(expectedIssues, validator); +} + TEST(Validator, unitSimpleCycle) { // Testing that indirect dependence is caught in the unit cycles. The network is: @@ -2257,6 +2354,50 @@ TEST(Validator, unitSimpleCycle) EXPECT_EQ("grandfather", issue->item()->units()->name()); } +TEST(Validator, unitSimpleCycleWithAdditionalIssue) +{ + const std::vector expectedIssues = { + "Model '' does not have a valid name attribute. CellML identifiers must contain one or more basic Latin alphabetic characters.", + "Cyclic units exist: 'grandfather' -> 'child' -> 'father' -> 'grandfather'.", + }; + + libcellml::ValidatorPtr v = libcellml::Validator::create(); + libcellml::ModelPtr m = libcellml::Model::create(); + + libcellml::UnitsPtr u1 = libcellml::Units::create(); + libcellml::UnitsPtr u2 = libcellml::Units::create(); + libcellml::UnitsPtr u3 = libcellml::Units::create(); + + m->setName("model"); + + m->addUnits(u1); + m->addUnits(u2); + m->addUnits(u3); + + u1->setName("grandfather"); // Base unit. + + u2->setName("father"); // First generation. + u2->addUnit("grandfather"); + + u3->setName("child"); // Second generation. + u3->addUnit("father"); + + // Network valid at this stage. + v->validateModel(m); + EXPECT_EQ(size_t(0), v->issueCount()); + + // Time loop Grandfather paradox created! u1 no longer a base variable: u1 -> u3 -> u2 -> u1. + u1->addUnit("child"); + // Add additional validation error. + m->removeName(); + + v->validateModel(m); + + EXPECT_EQ_ISSUES(expectedIssues, v); + auto issue = v->issue(1); + EXPECT_EQ("grandfather", issue->item()->units()->name()); +} + libcellml::ModelPtr unitComplexCycle(bool order) { // Simple testing for the directional dependency of units. The first network is: @@ -2568,8 +2709,58 @@ TEST(Validator, variableEquivalenceUnreachable) c2->addVariable(v2); c3->addVariable(v3); - // invalid equivalence, too far away + // Invalid equivalence, too far away. + libcellml::Variable::addEquivalence(v1, v3); + validator->validateModel(model); + + EXPECT_EQ_ISSUES(expectedIssues, validator); +} + +TEST(Validator, multipleVariableEquivalencesUnreachable) +{ + const std::vector expectedIssues { + "The equivalence between 'v1' in component 'c1' and 'v3' in component 'c3' is invalid. Component 'c1' and 'c3' are neither siblings nor in a parent/child relationship.", + "The equivalence between 'v1' in component 'c1' and 'v4' in component 'c4' is invalid. Component 'c1' and 'c4' are neither siblings nor in a parent/child relationship.", + }; + + libcellml::ModelPtr model = libcellml::Model::create(); + libcellml::ComponentPtr c1 = libcellml::Component::create(); + libcellml::ComponentPtr c2 = libcellml::Component::create(); + libcellml::ComponentPtr c3 = libcellml::Component::create(); + libcellml::ComponentPtr c4 = libcellml::Component::create(); + + libcellml::ValidatorPtr validator = libcellml::Validator::create(); + + model->setName("model"); + c1->setName("c1"); + c2->setName("c2"); + c3->setName("c3"); + c4->setName("c4"); + + model->addComponent(c1); + model->addComponent(c2); + c2->addComponent(c3); + c2->addComponent(c4); + + libcellml::VariablePtr v1 = libcellml::Variable::create(); + v1->setName("v1"); + v1->setUnits("dimensionless"); + + libcellml::VariablePtr v4 = libcellml::Variable::create(); + v4->setName("v4"); + v4->setUnits("dimensionless"); + + libcellml::VariablePtr v3 = libcellml::Variable::create(); + v3->setName("v3"); + v3->setUnits("dimensionless"); + + c1->addVariable(v1); + c4->addVariable(v4); + c3->addVariable(v3); + + // Invalid equivalence, too far away. libcellml::Variable::addEquivalence(v1, v3); + libcellml::Variable::addEquivalence(v1, v4); validator->validateModel(model); EXPECT_EQ_ISSUES(expectedIssues, validator); @@ -2647,8 +2838,10 @@ TEST(Validator, variableEquivalenceUnreachableAndReachableTogether) TEST(Validator, variableInterfaceShouldBePublic) { const std::vector expectedIssues = { - "Variable 'v1' in component 'c1' has no interface type set. The interface type required is 'public'.", + "Variable 'v1' in component 'c1' has an interface type set to 'none' which is not the correct interface type for this variable. The interface type required is 'public'.", + "Variable 'v3' in component 'c1' has no interface type set. The interface type required is 'public'.", "Variable 'v2' in component 'c2' has an interface type set to 'private' which is not the correct interface type for this variable. The interface type required is 'public'.", + "Variable 'v4' in component 'c2' has an interface type set to 'private' which is not the correct interface type for this variable. The interface type required is 'public'.", }; libcellml::ModelPtr model = libcellml::Model::create(); @@ -2672,12 +2865,25 @@ TEST(Validator, variableInterfaceShouldBePublic) v2->setName("v2"); v2->setUnits("dimensionless"); + libcellml::VariablePtr v3 = libcellml::Variable::create(); + v3->setName("v3"); + v3->setUnits("dimensionless"); + + libcellml::VariablePtr v4 = libcellml::Variable::create(); + v4->setName("v4"); + v4->setUnits("dimensionless"); + c1->addVariable(v1); + c1->addVariable(v3); c2->addVariable(v2); + c2->addVariable(v4); libcellml::Variable::addEquivalence(v1, v2); + libcellml::Variable::addEquivalence(v3, v4); + v1->setInterfaceType("none"); v2->setInterfaceType(libcellml::Variable::InterfaceType::PRIVATE); + v4->setInterfaceType(libcellml::Variable::InterfaceType::PRIVATE); validator->validateModel(model); @@ -2919,6 +3125,9 @@ TEST(Validator, duplicateIdAll) " \n" " \n" " \n" + " \n" + " \n" + " \n" " \n" " \n" " \n" @@ -3489,3 +3698,160 @@ TEST(Validator, zOffsetImportThatIllustratesBadPractice) validator->validateModel(model); EXPECT_EQ(size_t(0), validator->errorCount()); } + +TEST(Validator, invalidMathMLElementsChildrenOrSiblings) +{ + const std::vector expectedIssues = { + "Math has a 'apply' element without at least one MathML child.", + "Math has a 'eq' element without exactly two MathML siblings.", + "Math has a 'eq' element which is not the first MathML sibling.", + "Math has a 'neq' element without exactly two MathML siblings.", + "Math has a 'neq' element which is not the first MathML sibling.", + "Math has a 'lt' element without exactly two MathML siblings.", + "Math has a 'lt' element which is not the first MathML sibling.", + "Math has a 'leq' element without exactly two MathML siblings.", + "Math has a 'leq' element which is not the first MathML sibling.", + "Math has a 'gt' element without exactly two MathML siblings.", + "Math has a 'gt' element which is not the first MathML sibling.", + "Math has a 'geq' element without exactly two MathML siblings.", + "Math has a 'geq' element which is not the first MathML sibling.", + "Math has a 'and' element without at least two MathML siblings.", + "Math has a 'and' element which is not the first MathML sibling.", + "Math has a 'or' element without at least two MathML siblings.", + "Math has a 'or' element which is not the first MathML sibling.", + "Math has a 'xor' element without at least two MathML siblings.", + "Math has a 'xor' element which is not the first MathML sibling.", + "Math has a 'not' element without exactly one MathML sibling.", + "Math has a 'not' element which is not the first MathML sibling.", + "Math has a 'plus' element without at least one MathML sibling.", + "Math has a 'plus' element which is not the first MathML sibling.", + "Math has a 'minus' element without exactly one or two MathML siblings.", + "Math has a 'minus' element which is not the first MathML sibling.", + "Math has a 'times' element without at least two MathML siblings.", + "Math has a 'times' element which is not the first MathML sibling.", + "Math has a 'divide' element without exactly two MathML siblings.", + "Math has a 'divide' element which is not the first MathML sibling.", + "Math has a 'power' element without exactly two MathML siblings.", + "Math has a 'power' element which is not the first MathML sibling.", + "Math has a 'root' element without exactly one or two MathML siblings.", + "Math has a 'root' element which is not the first MathML sibling.", + "Math has a 'root' element which is not the first MathML sibling.", + "Math has a 'root' element which first sibling is not a 'degree' element.", + "Math has a 'abs' element without exactly one MathML sibling.", + "Math has a 'abs' element which is not the first MathML sibling.", + "Math has a 'exp' element without exactly one MathML sibling.", + "Math has a 'exp' element which is not the first MathML sibling.", + "Math has a 'ln' element without exactly one MathML sibling.", + "Math has a 'ln' element which is not the first MathML sibling.", + "Math has a 'log' element without exactly one or two MathML siblings.", + "Math has a 'log' element which is not the first MathML sibling.", + "Math has a 'log' element which is not the first MathML sibling.", + "Math has a 'log' element which first sibling is not a 'logbase' element.", + "Math has a 'ceiling' element without exactly one MathML sibling.", + "Math has a 'ceiling' element which is not the first MathML sibling.", + "Math has a 'floor' element without exactly one MathML sibling.", + "Math has a 'floor' element which is not the first MathML sibling.", + "Math has a 'diff' element without exactly two MathML siblings.", + "Math has a 'diff' element which is not the first MathML sibling.", + "Math has a 'diff' element which first sibling is not a 'bvar' element.", + "Math has a 'sin' element without exactly one MathML sibling.", + "Math has a 'sin' element which is not the first MathML sibling.", + "Math has a 'cos' element without exactly one MathML sibling.", + "Math has a 'cos' element which is not the first MathML sibling.", + "Math has a 'tan' element without exactly one MathML sibling.", + "Math has a 'tan' element which is not the first MathML sibling.", + "Math has a 'sec' element without exactly one MathML sibling.", + "Math has a 'sec' element which is not the first MathML sibling.", + "Math has a 'csc' element without exactly one MathML sibling.", + "Math has a 'csc' element which is not the first MathML sibling.", + "Math has a 'cot' element without exactly one MathML sibling.", + "Math has a 'cot' element which is not the first MathML sibling.", + "Math has a 'sinh' element without exactly one MathML sibling.", + "Math has a 'sinh' element which is not the first MathML sibling.", + "Math has a 'cosh' element without exactly one MathML sibling.", + "Math has a 'cosh' element which is not the first MathML sibling.", + "Math has a 'tanh' element without exactly one MathML sibling.", + "Math has a 'tanh' element which is not the first MathML sibling.", + "Math has a 'sech' element without exactly one MathML sibling.", + "Math has a 'sech' element which is not the first MathML sibling.", + "Math has a 'csch' element without exactly one MathML sibling.", + "Math has a 'csch' element which is not the first MathML sibling.", + "Math has a 'coth' element without exactly one MathML sibling.", + "Math has a 'coth' element which is not the first MathML sibling.", + "Math has a 'arcsin' element without exactly one MathML sibling.", + "Math has a 'arcsin' element which is not the first MathML sibling.", + "Math has a 'arccos' element without exactly one MathML sibling.", + "Math has a 'arccos' element which is not the first MathML sibling.", + "Math has a 'arctan' element without exactly one MathML sibling.", + "Math has a 'arctan' element which is not the first MathML sibling.", + "Math has a 'arcsec' element without exactly one MathML sibling.", + "Math has a 'arcsec' element which is not the first MathML sibling.", + "Math has a 'arccsc' element without exactly one MathML sibling.", + "Math has a 'arccsc' element which is not the first MathML sibling.", + "Math has a 'arccot' element without exactly one MathML sibling.", + "Math has a 'arccot' element which is not the first MathML sibling.", + "Math has a 'arcsinh' element without exactly one MathML sibling.", + "Math has a 'arcsinh' element which is not the first MathML sibling.", + "Math has a 'arccosh' element without exactly one MathML sibling.", + "Math has a 'arccosh' element which is not the first MathML sibling.", + "Math has a 'arctanh' element without exactly one MathML sibling.", + "Math has a 'arctanh' element which is not the first MathML sibling.", + "Math has a 'arcsech' element without exactly one MathML sibling.", + "Math has a 'arcsech' element which is not the first MathML sibling.", + "Math has a 'arccsch' element without exactly one MathML sibling.", + "Math has a 'arccsch' element which is not the first MathML sibling.", + "Math has a 'arccoth' element without exactly one MathML sibling.", + "Math has a 'arccoth' element which is not the first MathML sibling.", + "Math has a 'piece' element without exactly two MathML children.", + "Math has a 'otherwise' element without exactly one MathML child.", + "Math has a 'ci' element with no identifier as a child.", + "Math has a 'cn' element which is not in base 10.", + "Math has a 'cn' element which is not of 'real' or 'e-notation' type.", + "Math has a 'cn' element of 'real' type with no valid text node (representing a basic number) as a child.", + "Math has a 'cn' element of 'real' type with no valid text node (representing a basic number) as a child.", + "Math has a 'cn' element of 'real' type with no valid text node (representing a basic number) as a child.", + "Math has a 'cn' element of 'e-notation' type with no valid text node (representing a basic number), no 'sep' element, and/or no valid text node (representing an integer) as children.", + "Math has a 'cn' element of 'e-notation' type with no valid text node (representing a basic number), no 'sep' element, and/or no valid text node (representing an integer) as children.", + "Math has a 'cn' element of 'e-notation' type with no valid text node (representing a basic number), no 'sep' element, and/or no valid text node (representing an integer) as children.", + "Math has a 'cn' element of 'e-notation' type with no valid text node (representing a basic number), no 'sep' element, and/or no valid text node (representing an integer) as children.", + "Math has a 'cn' element of 'e-notation' type with no valid text node (representing a basic number), no 'sep' element, and/or no valid text node (representing an integer) as children.", + "Math has a 'cn' element of 'e-notation' type with no valid text node (representing a basic number), no 'sep' element, and/or no valid text node (representing an integer) as children.", + "Math has a 'cn' element of 'e-notation' type with no valid text node (representing a basic number), no 'sep' element, and/or no valid text node (representing an integer) as children.", + "Math has a 'cn' element of 'e-notation' type with no valid text node (representing a basic number), no 'sep' element, and/or no valid text node (representing an integer) as children.", + "Math has a 'cn' element of 'e-notation' type with no valid text node (representing a basic number), no 'sep' element, and/or no valid text node (representing an integer) as children.", + "Math has a 'degree' element without exactly one or two MathML siblings.", + "Math has a 'degree' element which is not the second MathML sibling.", + "Math has a 'degree' element without exactly one MathML child.", + "Math has a 'degree' element which first sibling is not a 'root' element.", + "Math has a 'root' element which first sibling is not a 'degree' element.", + "Math has a 'degree' element which is not the second MathML sibling.", + "Math has a 'degree' element without exactly one MathML child.", + "Math has a 'logbase' element without exactly two MathML siblings.", + "Math has a 'logbase' element which first sibling is not a 'log' element.", + "Math has a 'log' element which first sibling is not a 'logbase' element.", + "Math has a 'logbase' element which is not the second MathML sibling.", + "Math has a 'logbase' element without exactly one MathML child.", + "Math has a 'bvar' element without exactly two MathML siblings.", + "Math has a 'bvar' element which first sibling is not a 'diff' element.", + "Math has a 'diff' element which first sibling is not a 'bvar' element.", + "Math has a 'bvar' element which is not the second MathML sibling.", + "Math has a 'bvar' element without exactly one or two MathML children.", + "W3C MathML DTD error: Element true was declared EMPTY this one has content.", + "W3C MathML DTD error: Element false was declared EMPTY this one has content.", + "W3C MathML DTD error: Element exponentiale was declared EMPTY this one has content.", + "W3C MathML DTD error: Element pi was declared EMPTY this one has content.", + "W3C MathML DTD error: Element infinity was declared EMPTY this one has content.", + "W3C MathML DTD error: Element notanumber was declared EMPTY this one has content.", + }; + + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("invalidmathmlelementschildrenorsiblings.cellml")); + + EXPECT_EQ(size_t(0), parser->issueCount()); + + auto validator = libcellml::Validator::create(); + + validator->validateModel(model); + + EXPECT_EQ_ISSUES(expectedIssues, validator); +} diff --git a/tests/variable/variable.cpp b/tests/variable/variable.cpp index 97eb15478..29ed00f44 100644 --- a/tests/variable/variable.cpp +++ b/tests/variable/variable.cpp @@ -1413,6 +1413,48 @@ TEST(Variable, removeEquivalenceBothParametersNullptr) EXPECT_FALSE(libcellml::Variable::removeEquivalence(nullptr, nullptr)); } +TEST(Variable, removeEquivalenceFromNonEquivalentVariables) +{ + libcellml::VariablePtr v1 = libcellml::Variable::create("var1"); + libcellml::VariablePtr v2 = libcellml::Variable::create("var2"); + + EXPECT_FALSE(libcellml::Variable::removeEquivalence(v1, v2)); +} + +TEST(Variable, removeAllEquivalences) +{ + libcellml::VariablePtr v1 = libcellml::Variable::create("var1"); + libcellml::VariablePtr v2 = libcellml::Variable::create("var2"); + libcellml::VariablePtr v3 = libcellml::Variable::create("var2"); + + EXPECT_TRUE(libcellml::Variable::addEquivalence(v1, v2)); + EXPECT_TRUE(libcellml::Variable::addEquivalence(v1, v3)); + + EXPECT_EQ(size_t(2), v1->equivalentVariableCount()); + + v1->removeAllEquivalences(); + + EXPECT_EQ(size_t(0), v1->equivalentVariableCount()); +} + +TEST(Variable, removeAllEquivalencesWithDeletedVariable) +{ + libcellml::VariablePtr v1 = libcellml::Variable::create("var1"); + libcellml::VariablePtr v2 = libcellml::Variable::create("var2"); + libcellml::VariablePtr v3 = libcellml::Variable::create("var2"); + + EXPECT_TRUE(libcellml::Variable::addEquivalence(v1, v2)); + EXPECT_TRUE(libcellml::Variable::addEquivalence(v1, v3)); + + EXPECT_EQ(size_t(2), v1->equivalentVariableCount()); + + v3 = nullptr; + + v1->removeAllEquivalences(); + + EXPECT_EQ(size_t(0), v1->equivalentVariableCount()); +} + TEST(Variable, hasEquivalentVariableWithNullptr) { libcellml::ModelPtr m = libcellml::Model::create(); diff --git a/tests/version/version.cpp b/tests/version/version.cpp index 7a846a81a..f4fc6f451 100644 --- a/tests/version/version.cpp +++ b/tests/version/version.cpp @@ -5,8 +5,8 @@ TEST(Version, versionMatch) { unsigned int version = libcellml::version(); - EXPECT_EQ(0x000400U, version); + EXPECT_EQ(0x000500U, version); std::string versionString = libcellml::versionString(); - EXPECT_EQ("0.4.0", versionString); + EXPECT_EQ("0.5.0", versionString); }