diff --git a/src/api/libcellml/interpreter.h b/src/api/libcellml/interpreter.h index bed0b44fc2..b51b4d9477 100644 --- a/src/api/libcellml/interpreter.h +++ b/src/api/libcellml/interpreter.h @@ -19,6 +19,8 @@ limitations under the License. #include "libcellml/exportdefinitions.h" #include "libcellml/types.h" +#include + namespace libcellml { /** @@ -75,59 +77,32 @@ class LIBCELLML_EXPORT Interpreter */ double voi(); - /** - * @brief Get the number of states in the model. - * - * Return the number of states in the model. If the model doesn't have any states then 0 is returned. - * - * @return The number of states in the model as a @c size_t. - */ - size_t stateCount(); - /** * @brief Get the model's states. * * Return the model's states. If the model doesn't have any states then @c nullptr is returned. * - * @return The model's states as an array of @c double. - */ - double *states(); - - /** - * @brief Get the number of rates in the model. - * - * Return the number of rates in the model. If the model doesn't have any rates then 0 is returned. - * - * @return The number of rates in the model as a @c size_t. + * @return The model's states as a @c std::vector of @c double. */ - size_t rateCount(); + std::vector states(); /** * @brief Get the model's rates. * * Return the model's rates. If the model doesn't have any rates then @c nullptr is returned. * - * @return The model's rates as an array of @c double. - */ - double *rates(); - - /** - * @brief Get the number of variables in the model. - * - * Return the number of variables in the model. If the model doesn't have any variables then 0 is returned. - * - * @return The number of variables in the model as a @c size_t. + * @return The model's rates as a @c std::vector of @c double. */ - size_t variableCount(); + std::vector rates(); /** * @brief Get the model's variables. * * Return the model's variables. * - * @return The model's variables as an array of @c double. + * @return The model's variables as a @c std::vector of @c double. */ - double *variables(); + std::vector variables(); /** * @brief Initialise the model's variables. diff --git a/src/bindings/interface/interpreter.i b/src/bindings/interface/interpreter.i index f85c9ec184..63d257ee13 100644 --- a/src/bindings/interface/interpreter.i +++ b/src/bindings/interface/interpreter.i @@ -3,6 +3,7 @@ #define LIBCELLML_EXPORT %include +%include %import "analysermodel.i" %import "createconstructor.i" @@ -19,21 +20,12 @@ %feature("docstring") libcellml::Interpreter::voi "Returns the value of the model's variable of integration."; -%feature("docstring") libcellml::Interpreter::stateCount -"Returns the number of states in the model."; - %feature("docstring") libcellml::Interpreter::states "Returns the model's states."; -%feature("docstring") libcellml::Interpreter::rateCount -"Returns the number of rates in the model."; - %feature("docstring") libcellml::Interpreter::rates "Returns the model's rates."; -%feature("docstring") libcellml::Interpreter::variableCount -"Returns the number of variables in the model."; - %feature("docstring") libcellml::Interpreter::variables "Returns the model's variables."; @@ -53,6 +45,8 @@ #include "libcellml/interpreter.h" %} +%template(DoubleVector) std::vector; + %pythoncode %{ # libCellML generated wrapper code starts here. %} diff --git a/src/bindings/javascript/interpreter.cpp b/src/bindings/javascript/interpreter.cpp index ab3ef817c2..f1777a0ee4 100644 --- a/src/bindings/javascript/interpreter.cpp +++ b/src/bindings/javascript/interpreter.cpp @@ -27,39 +27,9 @@ EMSCRIPTEN_BINDINGS(libcellml_interpreter) .function("model", &libcellml::Interpreter::model) .function("setModel", &libcellml::Interpreter::setModel) .function("voi", &libcellml::Interpreter::voi) - .function("stateCount", &libcellml::Interpreter::stateCount) - .function("states", emscripten::optional_override([](libcellml::InterpreterPtr &interpreter) { - auto states = interpreter->states(); - auto stateCount = interpreter->stateCount(); - auto view = emscripten::typed_memory_view(stateCount, states); - auto res = emscripten::val::global("Uint8Array").new_(stateCount); - - res.call("set", view); - - return res; - })) - .function("rateCount", &libcellml::Interpreter::rateCount) - .function("rates", emscripten::optional_override([](libcellml::InterpreterPtr &interpreter) { - auto rates = interpreter->rates(); - auto rateCount = interpreter->rateCount(); - auto view = emscripten::typed_memory_view(rateCount, rates); - auto res = emscripten::val::global("Uint8Array").new_(rateCount); - - res.call("set", view); - - return res; - })) - .function("variableCount", &libcellml::Interpreter::variableCount) - .function("variables", emscripten::optional_override([](libcellml::InterpreterPtr &interpreter) { - auto variables = interpreter->variables(); - auto variableCount = interpreter->variableCount(); - auto view = emscripten::typed_memory_view(variableCount, variables); - auto res = emscripten::val::global("Uint8Array").new_(variableCount); - - res.call("set", view); - - return res; - })) + .function("states", &libcellml::Interpreter::states) + .function("rates", &libcellml::Interpreter::rates) + .function("variables", &libcellml::Interpreter::variables) .function("initialiseVariables", &libcellml::Interpreter::initialiseVariables) .function("computeComputedConstants", &libcellml::Interpreter::computeComputedConstants) .function("computeRates", &libcellml::Interpreter::computeRates) diff --git a/src/bindings/javascript/types.cpp b/src/bindings/javascript/types.cpp index 647501563a..ad746d3360 100644 --- a/src/bindings/javascript/types.cpp +++ b/src/bindings/javascript/types.cpp @@ -22,6 +22,7 @@ using namespace emscripten; EMSCRIPTEN_BINDINGS(libcellml_types) { + register_vector("VectorDouble"); register_vector("VectorString"); register_vector("VectorAnyCellmlElementPtr"); register_vector("VectorVariablePtr"); diff --git a/src/interpreter.cpp b/src/interpreter.cpp index 0d0ed91129..cfce76f8fb 100644 --- a/src/interpreter.cpp +++ b/src/interpreter.cpp @@ -16,10 +16,31 @@ limitations under the License. #include "libcellml/interpreter.h" +#include "libcellml/analysermodel.h" + #include "interpreter_p.h" namespace libcellml { +void Interpreter::InterpreterImpl::setModel(const AnalyserModelPtr &model) +{ + mModel = model; + + if (mModel != nullptr) { + mStates.resize(mModel->stateCount()); + mRates.resize(mModel->stateCount()); + mVariables.resize(mModel->variableCount()); + + mVoi = 0.0; + + static const auto NaN = std::numeric_limits::quiet_NaN(); + + std::fill(mStates.begin(), mStates.end(), NaN); + std::fill(mRates.begin(), mRates.end(), NaN); + std::fill(mVariables.begin(), mVariables.end(), NaN); + } +} + Interpreter::Interpreter() : mPimpl(new InterpreterImpl()) { @@ -42,7 +63,7 @@ AnalyserModelPtr Interpreter::model() void Interpreter::setModel(const AnalyserModelPtr &model) { - mPimpl->mModel = model; + mPimpl->setModel(model); } double Interpreter::voi() @@ -50,32 +71,17 @@ double Interpreter::voi() return mPimpl->mVoi; } -size_t Interpreter::stateCount() -{ - return mPimpl->mStateCount; -} - -double *Interpreter::states() +std::vector Interpreter::states() { return mPimpl->mStates; } -size_t Interpreter::rateCount() -{ - return mPimpl->mRateCount; -} - -double *Interpreter::rates() +std::vector Interpreter::rates() { return mPimpl->mRates; } -size_t Interpreter::variableCount() -{ - return mPimpl->mVariableCount; -} - -double *Interpreter::variables() +std::vector Interpreter::variables() { return mPimpl->mVariables; } diff --git a/src/interpreter_p.h b/src/interpreter_p.h index 203ad15aeb..ebdf4a4196 100644 --- a/src/interpreter_p.h +++ b/src/interpreter_p.h @@ -32,15 +32,11 @@ struct Interpreter::InterpreterImpl AnalyserModelPtr mModel; double mVoi = 0.0; + std::vector mStates; + std::vector mRates; + std::vector mVariables; - size_t mStateCount = 0; - double *mStates = nullptr; - - size_t mRateCount = 0; - double *mRates = nullptr; - - size_t mVariableCount = 0; - double *mVariables = nullptr; + void setModel(const AnalyserModelPtr &model); }; } // namespace libcellml diff --git a/tests/bindings/javascript/interpreter.test.js b/tests/bindings/javascript/interpreter.test.js index bbf7a816da..1da562f3b4 100644 --- a/tests/bindings/javascript/interpreter.test.js +++ b/tests/bindings/javascript/interpreter.test.js @@ -15,7 +15,7 @@ limitations under the License. */ const loadLibCellML = require('libcellml.js/libcellml.common') -const { basicModel } = require('./resources') +const { hhSquidAxon1952 } = require('./resources') let libcellml = null @@ -27,7 +27,7 @@ describe("Interpreter tests", () => { const i = new libcellml.Interpreter() const p = new libcellml.Parser(true) - m = p.parseModel(basicModel) + m = p.parseModel(hhSquidAxon1952) a = new libcellml.Analyser() a.analyseModel(m) @@ -40,14 +40,9 @@ describe("Interpreter tests", () => { expect(i.voi()).toBe(0.0) - expect(i.stateCount()).toBe(0) - expect(i.states()).toHaveLength(0) - - expect(i.rateCount()).toBe(0) - expect(i.rates()).toHaveLength(0) - - expect(i.variableCount()).toBe(0) - expect(i.variables()).toHaveLength(0) + expect(i.states().size()).toBe(4) + expect(i.rates().size()).toBe(4) + expect(i.variables().size()).toBe(18) i.initialiseVariables() i.computeComputedConstants() diff --git a/tests/bindings/python/test_interpreter.py b/tests/bindings/python/test_interpreter.py index 5a3dd9962c..354a5c8f56 100644 --- a/tests/bindings/python/test_interpreter.py +++ b/tests/bindings/python/test_interpreter.py @@ -12,7 +12,7 @@ def test_create_destroy(self): x = Interpreter() del x - def test_algebraic_eqn_computed_var_on_rhs(self): + def test_hodgkin_huxley_squid_axon_model_1952(self): from libcellml import Analyser from libcellml import AnalyserModel from libcellml import Interpreter @@ -20,14 +20,14 @@ def test_algebraic_eqn_computed_var_on_rhs(self): from test_resources import file_contents p = Parser() - m = p.parseModel(file_contents('generator/algebraic_eqn_computed_var_on_rhs/model.cellml')) - + m = p.parseModel(file_contents('generator/hodgkin_huxley_squid_axon_model_1952/model.cellml')) a = Analyser() + a.analyseModel(m) am = a.model() - self.assertEqual(AnalyserModel.Type.ALGEBRAIC, am.type()) + self.assertEqual(AnalyserModel.Type.ODE, am.type()) i = Interpreter() @@ -39,14 +39,9 @@ def test_algebraic_eqn_computed_var_on_rhs(self): self.assertEqual(0.0, i.voi()) - self.assertEqual(0, i.stateCount()) - self.assertIsNone(i.states()) - - self.assertEqual(0, i.rateCount()) - self.assertIsNone(i.rates()) - - self.assertEqual(0, i.variableCount()) - self.assertIsNone(i.variables()) + self.assertEqual(4, len(i.states())) + self.assertEqual(4, len(i.rates())) + self.assertEqual(18, len(i.variables())) i.initialiseVariables() i.computeComputedConstants() diff --git a/tests/generator/generator.cpp b/tests/generator/generator.cpp index e1e7cd86d2..e98dedce13 100644 --- a/tests/generator/generator.cpp +++ b/tests/generator/generator.cpp @@ -45,14 +45,9 @@ TEST(Generator, emptyModel) EXPECT_EQ(0.0, interpreter->voi()); - EXPECT_EQ(size_t(0), interpreter->stateCount()); - EXPECT_EQ(nullptr, interpreter->states()); - - EXPECT_EQ(size_t(0), interpreter->rateCount()); - EXPECT_EQ(nullptr, interpreter->rates()); - - EXPECT_EQ(size_t(0), interpreter->variableCount()); - EXPECT_EQ(nullptr, interpreter->variables()); + EXPECT_EQ(size_t(0), interpreter->states().size()); + EXPECT_EQ(size_t(0), interpreter->rates().size()); + EXPECT_EQ(size_t(0), interpreter->variables().size()); } TEST(Generator, algebraicEqnComputedVarOnRhs)