diff --git a/cmake/base64encoder.cpp b/cmake/base64encoder.cpp
index 0621bb70e..344874f85 100644
--- a/cmake/base64encoder.cpp
+++ b/cmake/base64encoder.cpp
@@ -25,7 +25,7 @@ int main(int pArgC, char *pArgV[])
// Convert the given file to a base64-encoded string.
if (pArgC != 2) {
- std::cerr << "Usage: " << pArgV[0] << " " << std::endl;
+ std::cerr << "Usage: " << pArgV[0] << " \n";
return 1;
}
@@ -37,7 +37,7 @@ int main(int pArgC, char *pArgV[])
file.read(buffer, fileSize);
if (!file) {
- std::cerr << "Error: the file could not be read." << std::endl;
+ std::cerr << "Error: the file could not be read.\n";
return 1;
}
@@ -48,7 +48,7 @@ int main(int pArgC, char *pArgV[])
modp_b64_encode(base64, buffer, fileSize);
- std::cout << base64 << std::endl;
+ std::cout << base64 << "\n";
delete[] base64;
delete[] buffer;
diff --git a/cmake/packages.cmake b/cmake/packages.cmake
index d82c042fd..4b7cd621c 100644
--- a/cmake/packages.cmake
+++ b/cmake/packages.cmake
@@ -193,9 +193,9 @@ function(retrieve_package PACKAGE_NAME PACKAGE_VERSION PACKAGE_REPOSITORY RELEAS
set(PACKAGE_URL "https://github.com/opencor/${PACKAGE_REPOSITORY}/releases/download/${RELEASE_TAG}/${PACKAGE_FILE}")
if("${PACKAGE_NAME}" STREQUAL "libCellML")
- #---GRY--- THIS IS TEMPORARY UNTIL libCellML HAS AN OFFICIAL RELEASE WITH THE INTERPRETER.
+ #---GRY--- USE THIS VERSION OF libCellML WHICH CORRESPONDS TO PR #1256 UNTIL IT GETS MERGED IN.
- set(PACKAGE_URL "https://github.com/agarny/${PACKAGE_REPOSITORY}/releases/download/707e211/${PACKAGE_FILE}")
+ set(PACKAGE_URL "https://github.com/agarny/${PACKAGE_REPOSITORY}/releases/download/04d8d15/${PACKAGE_FILE}")
endif()
set(ATTEMPT 1)
diff --git a/scripts/genericclean b/scripts/genericclean
index 719c3e1e9..3b6bf0326 100755
--- a/scripts/genericclean
+++ b/scripts/genericclean
@@ -8,11 +8,8 @@ fi
appDir=$(cd $(dirname $0); pwd)/..
-for i in _skbuild build src/bindings/python/libopencor.egg-info tests/install/build; do
- rm -fr $appDir/$i
-done
-
-find $appDir -name .DS_Store -exec rm -f {} \;
+find $appDir -type f -name .DS_Store -exec rm -f {} \; 2> /dev/null
+find $appDir -type d \( -name .pytest_cache -o -name __pycache__ -o -name _skbuild -o -name build \) -exec rm -fr {} \; 2> /dev/null
if [ "$1" = "all" ]; then
rm -fr $appDir/prebuilt/* > /dev/null 2>&1
diff --git a/scripts/genericclean.bat b/scripts/genericclean.bat
index dc444efc1..4199e46a4 100644
--- a/scripts/genericclean.bat
+++ b/scripts/genericclean.bat
@@ -11,7 +11,9 @@ IF "%1" == "all" (
SET AppDir=%~dp0..\
SET OrigDir=!CD!
-FOR /D %%I IN (_skbuild build src\bindings\python\libopencor.egg-info tests\install\build) DO IF EXIST !AppDir!%%I RMDIR /S /Q !AppDir!%%I
+FOR /R "%AppDir%" %%d IN (.pytest_cache __pycache__ _skbuild build) DO (
+ IF EXIST "%%d" RMDIR /S /Q "%%d"
+)
IF "%1" == "all" (
IF EXIST !AppDir!prebuilt (
diff --git a/src/3rdparty/libCellML/CMakeLists.txt b/src/3rdparty/libCellML/CMakeLists.txt
index bf8eb5e64..61ab247f6 100644
--- a/src/3rdparty/libCellML/CMakeLists.txt
+++ b/src/3rdparty/libCellML/CMakeLists.txt
@@ -34,49 +34,49 @@ if(LIBOPENCOR_PREBUILT_LIBCELLML OR ONLY_BUILD_JAVASCRIPT_THIRD_PARTY_LIBRARIES)
if(EMSCRIPTEN)
retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION}
${PACKAGE_REPOSITORY} ${RELEASE_TAG}
- e6e9bfdc883280289aa6131598b617b54672ae72)
+ 13a93a71d210b4ec3af336180f5d386b1e6d44c9)
else()
if(WIN32)
if(RELEASE_MODE)
if(INTEL_MODE)
retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION}
${PACKAGE_REPOSITORY} ${RELEASE_TAG}
- c688813b383c5759cb4982c1d6737f0fa0d68462)
+ 25c2e2dd016a47e9fff6a81b610de7be6cdb6bbc)
else()
retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION}
${PACKAGE_REPOSITORY} ${RELEASE_TAG}
- a1cab436551c576ab8d1bd16b6156e246134b733)
+ bb4b2e898776d03abd0644e2662d97034725f8d7)
endif()
else()
if(INTEL_MODE)
retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION}
${PACKAGE_REPOSITORY} ${RELEASE_TAG}
- 9623a3a236f4eadd9a9e7614b66fad916f07ea1d)
+ 526cfc4d623af35081c37e865f37b856cd39fe0a)
else()
retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION}
${PACKAGE_REPOSITORY} ${RELEASE_TAG}
- d486630d09a245f8b35670304f259019afb70fc9)
+ 770ac1735960bf4d01564fee6a09ff33a62486ab)
endif()
endif()
elseif(APPLE)
if(INTEL_MODE)
retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION}
${PACKAGE_REPOSITORY} ${RELEASE_TAG}
- 62768aa55bea80757378c706cb190043173991fb)
+ 836e28f4bce436fbee88f109a4f050b9e4dd68f6)
else()
retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION}
${PACKAGE_REPOSITORY} ${RELEASE_TAG}
- c80100db4e298acc5a1e2ea06c71c7b2766e49d4)
+ 555c258f6541ca7c51c54445a02386c5a619d754)
endif()
else()
if(INTEL_MODE)
retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION}
${PACKAGE_REPOSITORY} ${RELEASE_TAG}
- 1ce868ce9918deb8972f869f63817cbfbf6a411e)
+ 0842347a0a7abf4c6350aa44a6142ad5ba22a397)
else()
retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION}
${PACKAGE_REPOSITORY} ${RELEASE_TAG}
- deb06fa9adcae7a786f8150e3fa77aafa175e297)
+ 235fb4aa20bc3dde6ad28483775f2e41e9a093ef)
endif()
endif()
endif()
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0c5eb4da0..7db742ce3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -131,6 +131,7 @@ set(API_MODULE_FILE ${GIT_API_MODULE_FILE})
set(INTERNAL_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/file/filemanager.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/misc/compiler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/misc/utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/solver/solver.cpp
${CMAKE_CURRENT_SOURCE_DIR}/solver/solvercvode.cpp
@@ -148,12 +149,6 @@ set(INTERNAL_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/support/sedml/sedmlfile.cpp
)
-if(NOT EMSCRIPTEN)
- list(APPEND INTERNAL_SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/misc/compiler.cpp
- )
-endif()
-
set(GIT_API_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/file/file.cpp
${CMAKE_CURRENT_SOURCE_DIR}/file/filemanager.cpp
@@ -214,6 +209,8 @@ set(SOURCE_FILES
)
set(INTERNAL_HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/misc/compiler_p.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/misc/compiler.h
${CMAKE_CURRENT_SOURCE_DIR}/misc/utils.h
${CMAKE_CURRENT_SOURCE_DIR}/solver/solver_p.h
${CMAKE_CURRENT_SOURCE_DIR}/solver/solvercvode_p.h
@@ -236,13 +233,6 @@ set(INTERNAL_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/unittestingexport.h
)
-if(NOT EMSCRIPTEN)
- list(APPEND INTERNAL_HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/misc/compiler_p.h
- ${CMAKE_CURRENT_SOURCE_DIR}/misc/compiler.h
- )
-endif()
-
set(GIT_HEADER_FILES
${INTERNAL_HEADER_FILES}
${THIRD_PARTY_HEADER_FILES}
@@ -281,9 +271,10 @@ if(EMSCRIPTEN)
# Set the flags for our generated .js file.
# Note #1: we use -O3 to get the best performance, -sALLOW_MEMORY_GROWTH to allow the memory to grow dynamically,
- # -sEXPORT_ES6=1 to export ES6 classes, -sEXPORTED_FUNCTIONS to export the functions we need,
- # -sINLINING_LIMIT to increase the inlining limit, -sSINGLE_FILE=1 to generate a single file, -sSTACK_SIZE
- # to increase the stack size, and --bind to generate the necessary bindings.
+ # -sASSERTIONS=0 to disable assertions (which are not needed in production), -sEXPORT_ES6=1 to export ES6
+ # classes, -sEXPORTED_FUNCTIONS to export the functions we need, -sINLINING_LIMIT to increase the inlining
+ # limit, -sSINGLE_FILE=1 to generate a single file, -sSTACK_SIZE to increase the stack size, and --bind to
+ # generate the necessary bindings.
# Note #2: by default, Emscripten uses 64KB of stack, but this is not enough for "complex" models such as the Zhang
# et al. model (see https://github.com/agarny/COR/blob/master/Models/zhang_SAN_model_2000_all.cellml). For
# that model, we need about 108KB of stack. However, Emscripten originally used to use 5MB of stack (see
@@ -301,7 +292,7 @@ if(EMSCRIPTEN)
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES
COMPILE_FLAGS "-O3"
- LINK_FLAGS "-O3 -sALLOW_MEMORY_GROWTH -sEXPORT_ES6=1 -sEXPORTED_FUNCTIONS=[_malloc,_free] -sEXPORTED_RUNTIME_METHODS=HEAPU8 -sINLINING_LIMIT -sSINGLE_FILE=1 -sSTACK_SIZE=4MB --bind")
+ LINK_FLAGS "-O3 -sALLOW_MEMORY_GROWTH -sASSERTIONS=0 -sEXPORT_ES6=1 -sEXPORTED_FUNCTIONS=[_malloc,_free] -sEXPORTED_RUNTIME_METHODS=HEAPU8 -sINLINING_LIMIT -sSINGLE_FILE=1 -sSTACK_SIZE=4MB --bind")
# Create a .tgz file for our generated .js file that can be used to distribute our JavaScript bindings.
diff --git a/src/api/libopencor/seddocument.h b/src/api/libopencor/seddocument.h
index 1adc0d76e..a79daac22 100644
--- a/src/api/libopencor/seddocument.h
+++ b/src/api/libopencor/seddocument.h
@@ -320,17 +320,10 @@ class LIBOPENCOR_EXPORT SedDocument: public Logger
*
* Create an instance of this simulation experiment description.
*
- * @param pCompiled Whether the instance of this simulation experiment description is to be compiled (as opposed to
- * being interpreted).
- *
* @return A smart pointer to a @ref SedInstance object.
*/
-#ifdef __EMSCRIPTEN__
SedInstancePtr instantiate();
-#else
- SedInstancePtr instantiate(bool pCompiled = true);
-#endif
private:
class Impl; /**< Forward declaration of the implementation class, @private. */
diff --git a/src/api/libopencor/sedinstance.h b/src/api/libopencor/sedinstance.h
index d4026ea85..9343aee75 100644
--- a/src/api/libopencor/sedinstance.h
+++ b/src/api/libopencor/sedinstance.h
@@ -98,7 +98,7 @@ class LIBOPENCOR_EXPORT SedInstance: public Logger
private:
class Impl; /**< Forward declaration of the implementation class, @private. */
- explicit SedInstance(const SedDocumentPtr &pDocument, bool pCompiled); /**< Constructor @private. */
+ explicit SedInstance(const SedDocumentPtr &pDocument); /**< Constructor @private. */
Impl *pimpl(); /**< Private implementation pointer, @private. */
const Impl *pimpl() const; /**< Constant private implementation pointer, @private. */
diff --git a/src/api/libopencor/sedinstancetask.h b/src/api/libopencor/sedinstancetask.h
index d4141f168..e4e953093 100644
--- a/src/api/libopencor/sedinstancetask.h
+++ b/src/api/libopencor/sedinstancetask.h
@@ -335,7 +335,7 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger
private:
class Impl; /**< Forward declaration of the implementation class, @private. */
- explicit SedInstanceTask(const SedAbstractTaskPtr &pTask, bool pCompiled); /**< Constructor @private. */
+ explicit SedInstanceTask(const SedAbstractTaskPtr &pTask); /**< Constructor @private. */
Impl *pimpl(); /**< Private implementation pointer, @private. */
const Impl *pimpl() const; /**< Constant private implementation pointer, @private. */
diff --git a/src/api/libopencor/solvernla.h b/src/api/libopencor/solvernla.h
index 2017c74cd..a1fad8f34 100644
--- a/src/api/libopencor/solvernla.h
+++ b/src/api/libopencor/solvernla.h
@@ -33,7 +33,7 @@ class LIBOPENCOR_EXPORT SolverNla: public Solver
friend class SedSimulation;
public:
- using ComputeSystem = void (*)(double *pU, double *pF, void *pUserData); /**< Signature of the method that computes the system of NLA equations. */
+ using ComputeObjectiveFunction = void (*)(double *pU, double *pF, void *pUserData); /**< Signature of the method that computes the objective function of the NLA system. */
/**
* Constructors, destructor, and assignment operators.
@@ -54,15 +54,19 @@ class LIBOPENCOR_EXPORT SolverNla: public Solver
*
* Solve the NLA system.
*
- * @param pComputeSystem The method that computes the system of NLA equations.
+ * @param pComputeObjectiveFunction The method that computes the objective function of the NLA system.
* @param pU The initial guess for the solution of the NLA system.
* @param pN The number of variables in the NLA system.
- * @param pUserData Some user data that may be passed to @p pComputeSystem.
+ * @param pUserData User data, if any, that are passed to @p pComputeObjectiveFunction.
*
* @return @c true if the NLA system could be solved, @c false otherwise.
*/
- bool solve(ComputeSystem pComputeSystem, double *pU, size_t pN, void *pUserData);
+#ifdef __EMSCRIPTEN__
+ bool solve(size_t pComputeObjectiveFunctionIndex, double *pU, size_t pN, void *pUserData);
+#else
+ bool solve(ComputeObjectiveFunction pComputeObjectiveFunction, double *pU, size_t pN, void *pUserData);
+#endif
protected:
class Impl; /**< Forward declaration of the implementation class, @private. */
diff --git a/src/bindings/javascript/solver.cpp b/src/bindings/javascript/solver.cpp
index 527094c17..9ae61733e 100644
--- a/src/bindings/javascript/solver.cpp
+++ b/src/bindings/javascript/solver.cpp
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
+#include "solvernla_p.h"
+
#include
void solverApi()
@@ -47,6 +49,11 @@ void solverApi()
// SolverNla API.
+ emscripten::function("nlaSolve", emscripten::optional_override([](uintptr_t pNlaSolverAddress, size_t pObjectiveFunctionIndex, uintptr_t pU, size_t pN, uintptr_t pData) {
+ libOpenCOR::nlaSolve(pNlaSolverAddress, pObjectiveFunctionIndex,
+ reinterpret_cast(pU), pN, reinterpret_cast(pData));
+ }));
+
emscripten::class_>("SolverNla")
.smart_ptr("SolverNla");
diff --git a/src/bindings/python/sed.cpp b/src/bindings/python/sed.cpp
index 0e83f2745..2c640fc22 100644
--- a/src/bindings/python/sed.cpp
+++ b/src/bindings/python/sed.cpp
@@ -89,7 +89,7 @@ void sedApi(nb::module_ &m)
.def("add_task", &libOpenCOR::SedDocument::addTask, "Add a task.", nb::arg("task").none())
.def("remove_task", &libOpenCOR::SedDocument::removeTask, "Remove a task.", nb::arg("task").none())
.def("remove_all_tasks", &libOpenCOR::SedDocument::removeAllTasks, "Remove all tasks.")
- .def("instantiate", &libOpenCOR::SedDocument::instantiate, "Instantiate this SedDocument object.", nb::arg("compiled") = true);
+ .def("instantiate", &libOpenCOR::SedDocument::instantiate, "Instantiate this SedDocument object.");
// SedInstance API.
diff --git a/src/misc/compiler.cpp b/src/misc/compiler.cpp
index ce31723f4..ff07a31ed 100644
--- a/src/misc/compiler.cpp
+++ b/src/misc/compiler.cpp
@@ -17,6 +17,7 @@ limitations under the License.
#include "compiler_p.h"
#include "clangbegin.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CodeGenAction.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
@@ -27,11 +28,16 @@ limitations under the License.
#include "clangend.h"
#include "llvmbegin.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
#include "llvm-c/Core.h"
#include "llvmend.h"
+#include
#include
namespace libOpenCOR {
@@ -55,22 +61,28 @@ std::string llvmClangError(llvm::Error pError)
} // namespace
+#ifdef __EMSCRIPTEN__
+bool Compiler::Impl::compile(const std::string &pCode, UnsignedChars &pWasmModule)
+#else
bool Compiler::Impl::compile(const std::string &pCode)
+#endif
{
// Reset ourselves.
+#ifndef __EMSCRIPTEN__
mLljit.reset(nullptr);
+#endif
removeAllIssues();
// Create a diagnostics engine.
- auto diagnosticOptions = llvm::IntrusiveRefCntPtr(new clang::DiagnosticOptions {});
+ auto diagnosticOptions = llvm::IntrusiveRefCntPtr(std::make_unique());
std::string diagnostics;
llvm::raw_string_ostream outputStream(diagnostics);
- auto diagnosticsEngine = llvm::IntrusiveRefCntPtr(new clang::DiagnosticsEngine {llvm::IntrusiveRefCntPtr(new clang::DiagnosticIDs {}),
- &*diagnosticOptions,
- new clang::TextDiagnosticPrinter {outputStream, &*diagnosticOptions}});
+ auto diagnosticsEngine = llvm::IntrusiveRefCntPtr(std::make_unique(llvm::IntrusiveRefCntPtr(std::make_unique()),
+ &*diagnosticOptions,
+ std::make_unique(outputStream, &*diagnosticOptions).release()));
diagnosticsEngine->setWarningsAsErrors(true);
@@ -84,11 +96,7 @@ bool Compiler::Impl::compile(const std::string &pCode)
static constexpr auto DUMMY_FILE_NAME = "dummy.c";
static const std::vector COMPILATION_ARGUMENTS = {"clang", "-fsyntax-only",
-#ifdef NDEBUG
"-O3",
-#else
- "-g", "-O0",
-#endif
"-fno-math-errno",
"-fno-stack-protector",
DUMMY_FILE_NAME};
@@ -146,17 +154,17 @@ bool Compiler::Impl::compile(const std::string &pCode)
// Create a compiler instance.
- clang::CompilerInstance compilerInstance;
+ auto compilerInstance = std::make_unique();
- compilerInstance.setDiagnostics(diagnosticsEngine.get());
- compilerInstance.setVerboseOutputStream(llvm::nulls());
+ compilerInstance->setDiagnostics(diagnosticsEngine.get());
+ compilerInstance->setVerboseOutputStream(llvm::nulls());
// Create a compiler invocation object.
#ifndef CODE_COVERAGE_ENABLED
bool res =
#endif
- clang::CompilerInvocation::CreateFromArgs(compilerInstance.getInvocation(),
+ clang::CompilerInvocation::CreateFromArgs(compilerInstance->getInvocation(),
commandArguments,
*diagnosticsEngine);
@@ -170,8 +178,7 @@ bool Compiler::Impl::compile(const std::string &pCode)
// Map our code to a memory buffer.
- auto code = R"(
-// Arithmetic operators.
+ auto code = R"(// Arithmetic operators.
extern double pow(double, double);
extern double sqrt(double);
@@ -190,15 +197,12 @@ extern double fmod(double, double);
extern double sin(double);
extern double cos(double);
extern double tan(double);
-
extern double sinh(double);
extern double cosh(double);
extern double tanh(double);
-
extern double asin(double);
extern double acos(double);
extern double atan(double);
-
extern double asinh(double);
extern double acosh(double);
extern double atanh(double);
@@ -207,16 +211,18 @@ extern double atanh(double);
#define INFINITY (__builtin_inf())
#define NAN (__builtin_nan(""))
+
)" + pCode;
- compilerInstance.getInvocation().getPreprocessorOpts().addRemappedFile(DUMMY_FILE_NAME,
- llvm::MemoryBuffer::getMemBuffer(code).release());
+ compilerInstance->getInvocation().getPreprocessorOpts().addRemappedFile(DUMMY_FILE_NAME,
+ llvm::MemoryBuffer::getMemBuffer(code).release());
// Compile the given code, resulting in an LLVM bitcode module.
- std::unique_ptr codeGenAction(new clang::EmitLLVMOnlyAction {llvm::unwrap(LLVMGetGlobalContext())});
+ auto llvmContext = std::make_unique();
+ auto codeGenAction = std::make_unique(llvmContext.get());
- if (!compilerInstance.ExecuteAction(*codeGenAction)) {
+ if (!compilerInstance->ExecuteAction(*codeGenAction)) {
addError("The given code could not be compiled.");
static constexpr auto ERROR = ": error: ";
@@ -266,35 +272,87 @@ extern double atanh(double);
return false;
}
- // Retrieve the LLVM bitcode module.
+ // Retrieve the LLVM module.
auto module = codeGenAction->takeModule();
#ifndef CODE_COVERAGE_ENABLED
if (module == nullptr) {
- addError("The LLVM bitcode module could not be retrieved.");
+ addError("The LLVM module could not be retrieved.");
return false;
}
#endif
- // Initialise the native target (and its ASM printer), so not only can we then create an execution engine, but more
- // importantly its data layout will match that of our target platform.
+ // Initialise the native target and its ASM printer.
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
+#ifdef __EMSCRIPTEN__
+ // Look up the target.
+
+ std::string error;
+ auto target = llvm::TargetRegistry::lookupTarget(module->getTargetTriple(), error);
+
+ if (target == nullptr) {
+ error[0] = static_cast(tolower(error[0]));
+
+ addError(std::string("the target (").append(module->getTargetTriple()).append(") could not be found: ").append(error));
+
+ return false;
+ }
+
+ // Create a target machine.
+
+ auto targetMachine = std::unique_ptr(target->createTargetMachine(module->getTargetTriple(),
+ "generic", "",
+ llvm::TargetOptions(),
+ llvm::Reloc::Static));
+
+ if (targetMachine == nullptr) {
+ addError("A target machine could not be created.");
+
+ return false;
+ }
+
+ // Get the target machine to emit some WebAssembly code.
+
+ llvm::legacy::PassManager passManager;
+ llvm::SmallVector outputBuffer;
+ llvm::raw_svector_ostream output(outputBuffer);
+
+ if (targetMachine->addPassesToEmitFile(passManager, output, nullptr, llvm::CGFT_ObjectFile)) {
+ addError("The target machine cannot emit some WebAssembly code.");
+
+ return false;
+ }
+
+ passManager.run(*module);
+
+ // Retrieve the WebAssembly code.
+
+ pWasmModule.assign(outputBuffer.begin(), outputBuffer.end());
+
+ if (pWasmModule.empty()) {
+ addError("No WebAssembly code could be generated.");
+
+ return false;
+ }
+
+ return true;
+#else
// Create an ORC-based JIT and keep track of it.
auto lljit = llvm::orc::LLJITBuilder().create();
-#ifndef CODE_COVERAGE_ENABLED
+# ifndef CODE_COVERAGE_ENABLED
if (!lljit) {
addError(std::string("An ORC-based JIT could not be created").append(llvmClangError(lljit.takeError())).append("."));
return false;
}
-#endif
+# endif
mLljit = std::move(*lljit);
@@ -302,37 +360,38 @@ extern double atanh(double);
auto dynamicLibrarySearchGenerator = llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(mLljit->getDataLayout().getGlobalPrefix());
-#ifndef CODE_COVERAGE_ENABLED
+# ifndef CODE_COVERAGE_ENABLED
if (!dynamicLibrarySearchGenerator) {
addError(std::string("The dynamic library search generator could not be created").append(llvmClangError(dynamicLibrarySearchGenerator.takeError())).append("."));
return false;
}
-#endif
+# endif
mLljit->getMainJITDylib().addGenerator(std::move(*dynamicLibrarySearchGenerator));
// Add our LLVM bitcode module to our ORC-based JIT.
- auto llvmContext = std::make_unique();
auto threadSafeModule = llvm::orc::ThreadSafeModule(std::move(module), std::move(llvmContext));
-#ifdef CODE_COVERAGE_ENABLED
+# ifdef CODE_COVERAGE_ENABLED
const bool res =
-#else
+# else
res =
-#endif
+# endif
!mLljit->addIRModule(std::move(threadSafeModule));
-#ifndef CODE_COVERAGE_ENABLED
+# ifndef CODE_COVERAGE_ENABLED
if (!res) {
addError("The LLVM bitcode module could not be added to the ORC-based JIT.");
}
-#endif
+# endif
return res;
+#endif
}
+#ifndef __EMSCRIPTEN__
bool Compiler::Impl::addFunction(const std::string &pName, void *pFunction)
{
// Add the given function to our ORC-based JIT. Note that we assume that we have a valid ORC-based JIT, function
@@ -342,11 +401,11 @@ bool Compiler::Impl::addFunction(const std::string &pName, void *pFunction)
{mLljit->mangleAndIntern(pName), llvm::JITEvaluatedSymbol(llvm::pointerToJITTargetAddress(pFunction), llvm::JITSymbolFlags::Exported)},
}));
-#ifndef CODE_COVERAGE_ENABLED
+# ifndef CODE_COVERAGE_ENABLED
if (!res) {
addError(std::string("The ").append(pName).append("() function could not be added to the compiler."));
}
-#endif
+# endif
return res;
}
@@ -364,6 +423,7 @@ void *Compiler::Impl::function(const std::string &pName) const
return {};
}
+#endif
Compiler::Compiler()
: Logger(new Impl {})
@@ -390,6 +450,12 @@ CompilerPtr Compiler::create()
return CompilerPtr {new Compiler {}};
}
+#ifdef __EMSCRIPTEN__
+bool Compiler::compile(const std::string &pCode, UnsignedChars &pWasmModule)
+{
+ return pimpl()->compile(pCode, pWasmModule);
+}
+#else
bool Compiler::compile(const std::string &pCode)
{
return pimpl()->compile(pCode);
@@ -404,5 +470,6 @@ void *Compiler::function(const std::string &pName) const
{
return pimpl()->function(pName);
}
+#endif
} // namespace libOpenCOR
diff --git a/src/misc/compiler.h b/src/misc/compiler.h
index 5916eb754..71fcff3d3 100644
--- a/src/misc/compiler.h
+++ b/src/misc/compiler.h
@@ -40,11 +40,15 @@ class LIBOPENCOR_UNIT_TESTING_EXPORT Compiler: public Logger
static CompilerPtr create();
+#ifdef __EMSCRIPTEN__
+ bool compile(const std::string &pCode, UnsignedChars &pWasmModule);
+#else
bool compile(const std::string &pCode);
bool addFunction(const std::string &pName, void *pFunction);
void *function(const std::string &pName) const;
+#endif
private:
class Impl;
diff --git a/src/misc/compiler_p.h b/src/misc/compiler_p.h
index dcd08ae14..4476c5c48 100644
--- a/src/misc/compiler_p.h
+++ b/src/misc/compiler_p.h
@@ -20,15 +20,20 @@ limitations under the License.
#include "compiler.h"
-#include "llvmbegin.h"
-#include "llvm/ExecutionEngine/Orc/LLJIT.h"
-#include "llvmend.h"
+#ifndef __EMSCRIPTEN__
+# include "llvmbegin.h"
+# include "llvm/ExecutionEngine/Orc/LLJIT.h"
+# include "llvmend.h"
+#endif
namespace libOpenCOR {
class Compiler::Impl: public Logger::Impl
{
public:
+#ifdef __EMSCRIPTEN__
+ bool compile(const std::string &pCode, UnsignedChars &pWasmModule);
+#else
std::unique_ptr mLljit;
bool compile(const std::string &pCode);
@@ -36,6 +41,7 @@ class Compiler::Impl: public Logger::Impl
bool addFunction(const std::string &pName, void *pFunction);
void *function(const std::string &pName) const;
+#endif
};
} // namespace libOpenCOR
diff --git a/src/misc/utils.cpp b/src/misc/utils.cpp
index 77365de47..c2e3eb2bb 100644
--- a/src/misc/utils.cpp
+++ b/src/misc/utils.cpp
@@ -16,6 +16,8 @@ limitations under the License.
#include "utils.h"
+#include "libopencor/issue.h"
+
#ifndef __EMSCRIPTEN__
# include "curl/curl.h"
#endif
@@ -29,6 +31,7 @@ limitations under the License.
#include
#include
#include
+#include
#include
#include
@@ -36,12 +39,105 @@ limitations under the License.
# include
#endif
+#ifdef ERROR
+# undef ERROR
+#endif
+
#ifdef NAN
# undef NAN
#endif
namespace libOpenCOR {
+#ifndef CODE_COVERAGE_ENABLED
+void printIssues(const LoggerPtr &pLogger)
+{
+ std::cout << "---[ISSUES]---[BEGIN]\n";
+
+ for (auto &issue : pLogger->issues()) {
+ std::cout << ((issue->type() == Issue::Type::ERROR) ? "ERROR" : "WARNING") << ": " << issue->description() << "\n";
+ }
+
+ std::cout << "---[ISSUES]---[END]\n";
+}
+
+void printHexDump(const UnsignedChars &pBytes)
+{
+ static constexpr auto BYTES_PER_LINE = 16;
+ static constexpr auto ADDRESS_WIDTH = 8;
+ static constexpr auto FIRST_ASCII_CHARACTER = 32;
+ static constexpr auto LAST_ASCII_CHARACTER = 126;
+
+ std::cout << "---[BYTES]---[BEGIN]\n";
+
+ for (size_t i = 0; i < pBytes.size(); i += BYTES_PER_LINE) {
+ // Print the offset.
+
+ std::cout << std::hex << std::setfill('0') << std::setw(ADDRESS_WIDTH) << i << " ";
+
+ // Print hex bytes.
+
+ for (size_t j = 0; j < BYTES_PER_LINE; ++j) {
+ if (i + j < pBytes.size()) {
+ std::cout << std::hex << std::setfill('0') << std::setw(2) << static_cast(pBytes[i + j]);
+ } else {
+ std::cout << " ";
+ }
+
+ // Add an extra space after 8 bytes.
+
+ if (j == ADDRESS_WIDTH - 1) {
+ std::cout << " ";
+ } else {
+ std::cout << " ";
+ }
+ }
+
+ std::cout << " |";
+
+ // Print the ASCII representation.
+
+ const size_t bytesOnThisLine = (pBytes.size() - i < BYTES_PER_LINE) ? (pBytes.size() - i) : BYTES_PER_LINE;
+
+ for (size_t j = 0; j < bytesOnThisLine; ++j) {
+ auto byte = pBytes[i + j];
+
+ if (byte >= FIRST_ASCII_CHARACTER && byte <= LAST_ASCII_CHARACTER) {
+ std::cout << static_cast(byte);
+ } else {
+ std::cout << ".";
+ }
+ }
+
+ for (size_t j = bytesOnThisLine; j < BYTES_PER_LINE; ++j) {
+ std::cout << " ";
+ }
+
+ std::cout << "|\n";
+ }
+
+ std::cout << std::dec;
+
+ std::cout << "---[BYTES]---[END]\n";
+}
+
+void printArray(const std::string &pName, const Doubles &pDoubles)
+{
+ std::cout << "---[ARRAY]---[" << pName << "]---[BEGIN]\n";
+
+ if (!pDoubles.empty()) {
+ const auto arraySize = pDoubles.size();
+ const auto indexWidth = static_cast(log10(static_cast(arraySize - 1))) + 1;
+
+ for (size_t i = 0; i < arraySize; ++i) {
+ std::cout << "[" << std::setfill('0') << std::setw(indexWidth) << i << "] " << pDoubles[i] << "\n";
+ }
+ }
+
+ std::cout << "---[ARRAY]---[" << pName << "]---[END]\n";
+}
+#endif
+
bool fuzzyCompare(double pNb1, double pNb2)
{
static constexpr double ONE_TRILLION = 1000000000000.0;
@@ -232,7 +328,7 @@ using TimeVal = struct
namespace {
-int getTimeOfDay(TimeVal &pTimeVal)
+void getTimeOfDay(TimeVal &pTimeVal)
{
// Based off https://stackoverflow.com/a/58162122.
@@ -241,8 +337,6 @@ int getTimeOfDay(TimeVal &pTimeVal)
pTimeVal.seconds = static_cast(seconds.count());
pTimeVal.microeconds = static_cast(std::chrono::duration_cast(duration - seconds).count());
-
- return 0;
}
std::filesystem::path uniqueFilePath()
@@ -389,21 +483,13 @@ UnsignedChars fileContents(const std::filesystem::path &pFilePath)
}
#endif
-char *nlaSolverAddress(SolverNla *pNlaSolver)
+std::string nlaSolverAddress(SolverNla *pNlaSolver)
{
std::ostringstream oss;
- oss << pNlaSolver;
-
- auto str = oss.str();
- auto len = str.size();
- auto *res = new char[len + 1];
+ oss << "0x" << std::hex << reinterpret_cast(pNlaSolver);
- std::ranges::copy(str, res);
-
- res[len] = '\0'; // NOLINT
-
- return res;
+ return oss.str();
}
bool toBool(const std::string &pString)
@@ -495,104 +581,6 @@ std::string toString(const UnsignedChars &pBytes)
return {reinterpret_cast(pBytes.data()), pBytes.size()};
}
-SolverCvode::IntegrationMethod toCvodeIntegrationMethod(const std::string &pIntegrationMethod)
-{
- return (pIntegrationMethod == "BDF") ?
- SolverCvode::IntegrationMethod::BDF :
- SolverCvode::IntegrationMethod::ADAMS_MOULTON;
-}
-
-std::string toString(SolverCvode::IntegrationMethod pIntegrationMethod)
-{
- return (pIntegrationMethod == SolverCvode::IntegrationMethod::BDF) ?
- "BDF" :
- "Adams-Moulton";
-}
-
-SolverCvode::IterationType toCvodeIterationType(const std::string &pIterationType)
-{
- return (pIterationType == "Functional") ?
- SolverCvode::IterationType::FUNCTIONAL :
- SolverCvode::IterationType::NEWTON;
-}
-
-std::string toString(SolverCvode::IterationType pIterationType)
-{
- return (pIterationType == SolverCvode::IterationType::FUNCTIONAL) ?
- "Functional" :
- "Newton";
-}
-
-SolverCvode::LinearSolver toCvodeLinearSolver(const std::string &pLinearSolver)
-{
- return (pLinearSolver == "Dense") ?
- SolverCvode::LinearSolver::DENSE :
- (pLinearSolver == "Banded") ?
- SolverCvode::LinearSolver::BANDED :
- (pLinearSolver == "Diagonal") ?
- SolverCvode::LinearSolver::DIAGONAL :
- (pLinearSolver == "GMRES") ?
- SolverCvode::LinearSolver::GMRES :
- (pLinearSolver == "BiCGStab") ?
- SolverCvode::LinearSolver::BICGSTAB :
- SolverCvode::LinearSolver::TFQMR;
-}
-
-std::string toString(SolverCvode::LinearSolver pLinearSolver)
-{
- return (pLinearSolver == SolverCvode::LinearSolver::DENSE) ?
- "Dense" :
- (pLinearSolver == SolverCvode::LinearSolver::BANDED) ?
- "Banded" :
- (pLinearSolver == SolverCvode::LinearSolver::DIAGONAL) ?
- "Diagonal" :
- (pLinearSolver == SolverCvode::LinearSolver::GMRES) ?
- "GMRES" :
- (pLinearSolver == SolverCvode::LinearSolver::BICGSTAB) ?
- "BiCGStab" :
- "TFQMR";
-}
-
-SolverCvode::Preconditioner toCvodePreconditioner(const std::string &pPreconditioner)
-{
- return (pPreconditioner == "No") ?
- SolverCvode::Preconditioner::NO :
- SolverCvode::Preconditioner::BANDED;
-}
-
-std::string toString(SolverCvode::Preconditioner pPreconditioner)
-{
- return (pPreconditioner == SolverCvode::Preconditioner::NO) ?
- "No" :
- "Banded";
-}
-
-SolverKinsol::LinearSolver toKinsolLinearSolver(const std::string &pLinearSolver)
-{
- return (pLinearSolver == "Dense") ?
- SolverKinsol::LinearSolver::DENSE :
- (pLinearSolver == "Banded") ?
- SolverKinsol::LinearSolver::BANDED :
- (pLinearSolver == "GMRES") ?
- SolverKinsol::LinearSolver::GMRES :
- (pLinearSolver == "BiCGStab") ?
- SolverKinsol::LinearSolver::BICGSTAB :
- SolverKinsol::LinearSolver::TFQMR;
-}
-
-std::string toString(SolverKinsol::LinearSolver pLinearSolver)
-{
- return (pLinearSolver == SolverKinsol::LinearSolver::DENSE) ?
- "Dense" :
- (pLinearSolver == SolverKinsol::LinearSolver::BANDED) ?
- "Banded" :
- (pLinearSolver == SolverKinsol::LinearSolver::GMRES) ?
- "GMRES" :
- (pLinearSolver == SolverKinsol::LinearSolver::BICGSTAB) ?
- "BiCGStab" :
- "TFQMR";
-}
-
const xmlChar *toConstXmlCharPtr(const std::string &pString)
{
return reinterpret_cast(pString.c_str());
diff --git a/src/misc/utils.h b/src/misc/utils.h
index 234760b21..f3928ea07 100644
--- a/src/misc/utils.h
+++ b/src/misc/utils.h
@@ -70,14 +70,20 @@ using StringStringMap = std::map;
# define ASSERT_LE(x, y) assert(x <= y)
#endif
+#ifndef CODE_COVERAGE_ENABLED
+void LIBOPENCOR_UNIT_TESTING_EXPORT printIssues(const LoggerPtr &pLogger);
+void LIBOPENCOR_UNIT_TESTING_EXPORT printHexDump(const UnsignedChars &pBytes);
+void LIBOPENCOR_UNIT_TESTING_EXPORT printArray(const std::string &pName, const Doubles &pDoubles);
+#endif
+
bool LIBOPENCOR_UNIT_TESTING_EXPORT fuzzyCompare(double pNb1, double pNb2);
#ifdef BUILDING_USING_MSVC
std::string LIBOPENCOR_UNIT_TESTING_EXPORT forwardSlashPath(const std::string &pPath);
#endif
-std::filesystem::path LIBOPENCOR_UNIT_TESTING_EXPORT stringToPath(const std::string &pString);
-std::string LIBOPENCOR_UNIT_TESTING_EXPORT pathToString(const std::filesystem::path &pPath);
+std::filesystem::path stringToPath(const std::string &pString);
+std::string pathToString(const std::filesystem::path &pPath);
#ifdef BUILDING_USING_MSVC
std::string LIBOPENCOR_UNIT_TESTING_EXPORT canonicalFileName(const std::string &pFileName, bool pIsRemoteFile = false);
@@ -94,7 +100,7 @@ std::tuple downloadFile(const std::string &pUrl);
UnsignedChars LIBOPENCOR_UNIT_TESTING_EXPORT fileContents(const std::filesystem::path &pFilePath);
#endif
-char LIBOPENCOR_UNIT_TESTING_EXPORT *nlaSolverAddress(SolverNla *pNlaSolver);
+std::string nlaSolverAddress(SolverNla *pNlaSolver);
bool toBool(const std::string &pString);
std::string toString(bool pBoolean);
@@ -111,21 +117,6 @@ std::string toString(double pNumber);
std::string LIBOPENCOR_UNIT_TESTING_EXPORT toString(const UnsignedChars &pBytes);
-SolverCvode::IntegrationMethod toCvodeIntegrationMethod(const std::string &pIntegrationMethod);
-std::string toString(SolverCvode::IntegrationMethod pIntegrationMethod);
-
-SolverCvode::IterationType toCvodeIterationType(const std::string &pIterationType);
-std::string toString(SolverCvode::IterationType pIterationType);
-
-SolverCvode::LinearSolver toCvodeLinearSolver(const std::string &pLinearSolver);
-std::string toString(SolverCvode::LinearSolver pLinearSolver);
-
-SolverCvode::Preconditioner toCvodePreconditioner(const std::string &pPreconditioner);
-std::string toString(SolverCvode::Preconditioner pPreconditioner);
-
-SolverKinsol::LinearSolver toKinsolLinearSolver(const std::string &pLinearSolver);
-std::string toString(SolverKinsol::LinearSolver pLinearSolver);
-
const xmlChar *toConstXmlCharPtr(const std::string &pString);
libcellml::ComponentPtr owningComponent(const libcellml::VariablePtr &pVariable);
diff --git a/src/sed/seddocument.cpp b/src/sed/seddocument.cpp
index bf7131bdd..451288e08 100644
--- a/src/sed/seddocument.cpp
+++ b/src/sed/seddocument.cpp
@@ -608,16 +608,9 @@ bool SedDocument::removeAllTasks()
return pimpl()->removeAllTasks();
}
-#ifdef __EMSCRIPTEN__
SedInstancePtr SedDocument::instantiate()
{
- return SedInstance::Impl::create(shared_from_this(), false);
-}
-#else
-SedInstancePtr SedDocument::instantiate(bool pCompiled)
-{
- return SedInstance::Impl::create(shared_from_this(), pCompiled);
+ return SedInstance::Impl::create(shared_from_this());
}
-#endif
} // namespace libOpenCOR
diff --git a/src/sed/sedinstance.cpp b/src/sed/sedinstance.cpp
index d9b2c5213..b402f3045 100644
--- a/src/sed/sedinstance.cpp
+++ b/src/sed/sedinstance.cpp
@@ -22,12 +22,12 @@ limitations under the License.
namespace libOpenCOR {
-SedInstancePtr SedInstance::Impl::create(const SedDocumentPtr &pDocument, bool pCompiled)
+SedInstancePtr SedInstance::Impl::create(const SedDocumentPtr &pDocument)
{
- return SedInstancePtr {new SedInstance(pDocument, pCompiled)};
+ return SedInstancePtr {new SedInstance(pDocument)};
}
-SedInstance::Impl::Impl(const SedDocumentPtr &pDocument, bool pCompiled)
+SedInstance::Impl::Impl(const SedDocumentPtr &pDocument)
: Logger::Impl()
{
// Check whether there are some outputs that should be generated or, failing that, whether there are some tasks that
@@ -58,7 +58,7 @@ SedInstance::Impl::Impl(const SedDocumentPtr &pDocument, bool pCompiled)
if (tasksValid) {
for (const auto &task : tasks) {
- auto taskInstance = SedInstanceTask::Impl::create(task, pCompiled);
+ auto taskInstance = SedInstanceTask::Impl::create(task);
mTasks.push_back(taskInstance);
@@ -115,8 +115,8 @@ SedInstanceTaskPtr SedInstance::Impl::task(size_t pIndex) const
return mTasks[pIndex];
}
-SedInstance::SedInstance(const SedDocumentPtr &pDocument, bool pCompiled)
- : Logger(new Impl(pDocument, pCompiled))
+SedInstance::SedInstance(const SedDocumentPtr &pDocument)
+ : Logger(new Impl(pDocument))
{
}
diff --git a/src/sed/sedinstance_p.h b/src/sed/sedinstance_p.h
index 1ac8e7685..4b5dbc183 100644
--- a/src/sed/sedinstance_p.h
+++ b/src/sed/sedinstance_p.h
@@ -27,9 +27,9 @@ class SedInstance::Impl: public Logger::Impl
public:
SedInstanceTaskPtrs mTasks;
- static SedInstancePtr create(const SedDocumentPtr &pDocument, bool pCompiled);
+ static SedInstancePtr create(const SedDocumentPtr &pDocument);
- explicit Impl(const SedDocumentPtr &pDocument, bool pCompiled);
+ explicit Impl(const SedDocumentPtr &pDocument);
double run();
diff --git a/src/sed/sedinstancetask.cpp b/src/sed/sedinstancetask.cpp
index 1a3519c62..8d6f41c5b 100644
--- a/src/sed/sedinstancetask.cpp
+++ b/src/sed/sedinstancetask.cpp
@@ -25,19 +25,26 @@ limitations under the License.
namespace libOpenCOR {
-SedInstanceTaskPtr SedInstanceTask::Impl::create(const SedAbstractTaskPtr &pTask, bool pCompiled)
+SedInstanceTaskPtr SedInstanceTask::Impl::create(const SedAbstractTaskPtr &pTask)
{
- auto res = SedInstanceTaskPtr {new SedInstanceTask {pTask, pCompiled}};
+ auto res = SedInstanceTaskPtr {new SedInstanceTask {pTask}};
res->pimpl()->mOwner = res;
- res->pimpl()->initialise();
+ // Initialise the instance task, but only if there are no issues with it.
+
+#ifndef CODE_COVERAGE_ENABLED
+ if (!res->hasIssues()) {
+#endif
+ res->pimpl()->initialise();
+#ifndef CODE_COVERAGE_ENABLED
+ }
+#endif
return res;
}
-SedInstanceTask::Impl::Impl(const SedAbstractTaskPtr &pTask, bool pCompiled)
- : mCompiled(pCompiled)
+SedInstanceTask::Impl::Impl(const SedAbstractTaskPtr &pTask)
{
//---GRY--- AT THIS STAGE, WE ONLY SUPPORT SedTask TASKS, HENCE WE ASSERT (FOR NOW) THAT pTask IS INDEED A SedTask
// OBJECT.
@@ -62,7 +69,7 @@ SedInstanceTask::Impl::Impl(const SedAbstractTaskPtr &pTask, bool pCompiled)
mOdeSolver = (odeSolver != nullptr) ? std::dynamic_pointer_cast(odeSolver->pimpl()->duplicate()) : nullptr;
mNlaSolver = (nlaSolver != nullptr) ? std::dynamic_pointer_cast(nlaSolver->pimpl()->duplicate()) : nullptr;
- mRuntime = cellmlFile->runtime(mNlaSolver, mCompiled);
+ mRuntime = cellmlFile->runtime(mNlaSolver);
#ifndef CODE_COVERAGE_ENABLED
if (mRuntime->hasErrors()) {
@@ -149,41 +156,39 @@ void SedInstanceTask::Impl::initialise()
if (mSedUniformTimeCourse != nullptr) {
mVoi = mSedUniformTimeCourse->pimpl()->mOutputStartTime;
-#ifndef __EMSCRIPTEN__
- if (mCompiled) {
- mRuntime->initialiseCompiledVariablesForDifferentialModel()(mStates, mRates, mConstants, mComputedConstants, mAlgebraic);
-
- applyChanges();
-
- mRuntime->computeCompiledComputedConstants()(mConstants, mComputedConstants);
- mRuntime->computeCompiledRates()(mVoi, mStates, mRates, mConstants, mComputedConstants, mAlgebraic);
- mRuntime->computeCompiledVariablesForDifferentialModel()(mVoi, mStates, mRates, mConstants, mComputedConstants, mAlgebraic);
- } else {
+#ifdef __EMSCRIPTEN__
+ mRuntime->initialiseVariablesForDifferentialModel(mStates, mRates, mConstants, mComputedConstants, mAlgebraic);
+#else
+ mRuntime->initialiseVariablesForDifferentialModel()(mStates, mRates, mConstants, mComputedConstants, mAlgebraic);
#endif
- mRuntime->initialiseInterpretedVariablesForDifferentialModel()(mStates, mRates, mConstants, mComputedConstants, mAlgebraic);
-
- applyChanges();
-
- mRuntime->computeInterpretedComputedConstants()(mConstants, mComputedConstants);
- mRuntime->computeInterpretedRates()(mVoi, mStates, mRates, mConstants, mComputedConstants, mAlgebraic);
- mRuntime->computeInterpretedVariablesForDifferentialModel()(mVoi, mStates, mRates, mConstants, mComputedConstants, mAlgebraic);
-#ifndef __EMSCRIPTEN__
- }
- } else if (mCompiled) {
- mRuntime->initialiseCompiledVariablesForAlgebraicModel()(mConstants, mComputedConstants, mAlgebraic);
applyChanges();
- mRuntime->computeCompiledComputedConstants()(mConstants, mComputedConstants);
- mRuntime->computeCompiledVariablesForAlgebraicModel()(mConstants, mComputedConstants, mAlgebraic);
+#ifdef __EMSCRIPTEN__
+ mRuntime->computeComputedConstants(mConstants, mComputedConstants);
+ mRuntime->computeRates(mVoi, mStates, mRates, mConstants, mComputedConstants, mAlgebraic);
+ mRuntime->computeVariablesForDifferentialModel(mVoi, mStates, mRates, mConstants, mComputedConstants, mAlgebraic);
+#else
+ mRuntime->computeComputedConstants()(mConstants, mComputedConstants);
+ mRuntime->computeRates()(mVoi, mStates, mRates, mConstants, mComputedConstants, mAlgebraic);
+ mRuntime->computeVariablesForDifferentialModel()(mVoi, mStates, mRates, mConstants, mComputedConstants, mAlgebraic);
#endif
} else {
- mRuntime->initialiseInterpretedVariablesForAlgebraicModel()(mConstants, mComputedConstants, mAlgebraic);
+#ifdef __EMSCRIPTEN__
+ mRuntime->initialiseVariablesForAlgebraicModel(mConstants, mComputedConstants, mAlgebraic);
+#else
+ mRuntime->initialiseVariablesForAlgebraicModel()(mConstants, mComputedConstants, mAlgebraic);
+#endif
applyChanges();
- mRuntime->computeInterpretedComputedConstants()(mConstants, mComputedConstants);
- mRuntime->computeInterpretedVariablesForAlgebraicModel()(mConstants, mComputedConstants, mAlgebraic);
+#ifdef __EMSCRIPTEN__
+ mRuntime->computeComputedConstants(mConstants, mComputedConstants);
+ mRuntime->computeVariablesForAlgebraicModel(mConstants, mComputedConstants, mAlgebraic);
+#else
+ mRuntime->computeComputedConstants()(mConstants, mComputedConstants);
+ mRuntime->computeVariablesForAlgebraicModel()(mConstants, mComputedConstants, mAlgebraic);
+#endif
}
// Make sure that the NLA solver, should it have been used, didn't report any issues.
@@ -199,7 +204,7 @@ void SedInstanceTask::Impl::initialise()
if (mDifferentialModel) {
if (!mOdeSolver->pimpl()->initialise(mVoi, mAnalyserModel->stateCount(), mStates, mRates,
mConstants, mComputedConstants, mAlgebraic,
- mRuntime->computeCompiledRates(), mRuntime->computeInterpretedRates())) {
+ mRuntime)) {
addIssues(mOdeSolver);
return;
@@ -264,16 +269,12 @@ double SedInstanceTask::Impl::run()
return 0.0;
}
-#ifndef __EMSCRIPTEN__
- if (mCompiled) {
- mRuntime->computeCompiledVariablesForDifferentialModel()(mVoi, mStates, mRates,
- mConstants, mComputedConstants, mAlgebraic);
- } else {
-#endif
- mRuntime->computeInterpretedVariablesForDifferentialModel()(mVoi, mStates, mRates,
- mConstants, mComputedConstants, mAlgebraic);
-#ifndef __EMSCRIPTEN__
- }
+#ifdef __EMSCRIPTEN__
+ mRuntime->computeVariablesForDifferentialModel(mVoi, mStates, mRates,
+ mConstants, mComputedConstants, mAlgebraic);
+#else
+ mRuntime->computeVariablesForDifferentialModel()(mVoi, mStates, mRates,
+ mConstants, mComputedConstants, mAlgebraic);
#endif
//---GRY--- WE NEED TO CHECK FOR POSSIBLE NLA ISSUES, BUT FOR CODE COVERAGE WE NEED A MODEL THAT WOULD
@@ -498,8 +499,8 @@ std::string SedInstanceTask::Impl::algebraicUnit(size_t pIndex) const
return mAnalyserModel->algebraic()[pIndex]->variable()->units()->name();
}
-SedInstanceTask::SedInstanceTask(const SedAbstractTaskPtr &pTask, bool pCompiled)
- : Logger(new Impl(pTask, pCompiled))
+SedInstanceTask::SedInstanceTask(const SedAbstractTaskPtr &pTask)
+ : Logger(new Impl(pTask))
{
}
diff --git a/src/sed/sedinstancetask_p.h b/src/sed/sedinstancetask_p.h
index 73920fe67..ac41b223e 100644
--- a/src/sed/sedinstancetask_p.h
+++ b/src/sed/sedinstancetask_p.h
@@ -49,7 +49,6 @@ class SedInstanceTask::Impl: public Logger::Impl
libcellml::AnalyserModelPtr mAnalyserModel;
SolverOdePtr mOdeSolver;
SolverNlaPtr mNlaSolver;
- bool mCompiled = true;
double mVoi = 0.0;
double *mStates = nullptr;
@@ -66,9 +65,9 @@ class SedInstanceTask::Impl: public Logger::Impl
SedInstanceTaskResults mResults;
- static SedInstanceTaskPtr create(const SedAbstractTaskPtr &pTask, bool pCompiled);
+ static SedInstanceTaskPtr create(const SedAbstractTaskPtr &pTask);
- explicit Impl(const SedAbstractTaskPtr &pTask, bool pCompiled);
+ explicit Impl(const SedAbstractTaskPtr &pTask);
void trackResults(size_t pIndex);
diff --git a/src/solver/solvercvode.cpp b/src/solver/solvercvode.cpp
index 1c8b08c2d..01dacfd94 100644
--- a/src/solver/solvercvode.cpp
+++ b/src/solver/solvercvode.cpp
@@ -37,6 +37,48 @@ limitations under the License.
namespace libOpenCOR {
+// Some utilities.
+
+namespace {
+
+std::string toString(SolverCvode::IntegrationMethod pIntegrationMethod)
+{
+ return (pIntegrationMethod == SolverCvode::IntegrationMethod::BDF) ?
+ "BDF" :
+ "Adams-Moulton";
+}
+
+std::string toString(SolverCvode::IterationType pIterationType)
+{
+ return (pIterationType == SolverCvode::IterationType::FUNCTIONAL) ?
+ "Functional" :
+ "Newton";
+}
+
+std::string toString(SolverCvode::LinearSolver pLinearSolver)
+{
+ return (pLinearSolver == SolverCvode::LinearSolver::DENSE) ?
+ "Dense" :
+ (pLinearSolver == SolverCvode::LinearSolver::BANDED) ?
+ "Banded" :
+ (pLinearSolver == SolverCvode::LinearSolver::DIAGONAL) ?
+ "Diagonal" :
+ (pLinearSolver == SolverCvode::LinearSolver::GMRES) ?
+ "GMRES" :
+ (pLinearSolver == SolverCvode::LinearSolver::BICGSTAB) ?
+ "BiCGStab" :
+ "TFQMR";
+}
+
+std::string toString(SolverCvode::Preconditioner pPreconditioner)
+{
+ return (pPreconditioner == SolverCvode::Preconditioner::NO) ?
+ "No" :
+ "Banded";
+}
+
+} // namespace
+
// Right-hand side function.
namespace {
@@ -64,13 +106,13 @@ int rhsFunction(double pVoi, N_Vector pStates, N_Vector pRates, void *pUserData)
{
auto *userData = static_cast(pUserData);
- if (userData->computeCompiledRates != nullptr) {
- userData->computeCompiledRates(pVoi, N_VGetArrayPointer_Serial(pStates), N_VGetArrayPointer_Serial(pRates),
- userData->constants, userData->computedConstants, userData->algebraic);
- } else {
- userData->computeInterpretedRates(pVoi, N_VGetArrayPointer_Serial(pStates), N_VGetArrayPointer_Serial(pRates),
+#ifdef __EMSCRIPTEN__
+ userData->runtime->computeRates(pVoi, N_VGetArrayPointer_Serial(pStates), N_VGetArrayPointer_Serial(pRates),
+ userData->constants, userData->computedConstants, userData->algebraic);
+#else
+ userData->runtime->computeRates()(pVoi, N_VGetArrayPointer_Serial(pStates), N_VGetArrayPointer_Serial(pRates),
userData->constants, userData->computedConstants, userData->algebraic);
- }
+#endif
return 0;
}
@@ -119,7 +161,9 @@ void SolverCvode::Impl::populate(libsedml::SedAlgorithm *pAlgorithm)
value = toString(DEFAULT_INTEGRATION_METHOD);
}
- mIntegrationMethod = toCvodeIntegrationMethod(value);
+ mIntegrationMethod = (value == "BDF") ?
+ SolverCvode::IntegrationMethod::BDF :
+ SolverCvode::IntegrationMethod::ADAMS_MOULTON;
} else if (kisaoId == "KISAO:0000476") {
if ((value != "Functional") && (value != "Newton")) {
addWarning(std::string("The iteration type ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be equal to 'Functional' or 'Newton'. A ").append(toString(DEFAULT_ITERATION_TYPE)).append(" iteration type will be used instead."));
@@ -127,7 +171,9 @@ void SolverCvode::Impl::populate(libsedml::SedAlgorithm *pAlgorithm)
value = toString(DEFAULT_ITERATION_TYPE);
}
- mIterationType = toCvodeIterationType(value);
+ mIterationType = (value == "Functional") ?
+ SolverCvode::IterationType::FUNCTIONAL :
+ SolverCvode::IterationType::NEWTON;
} else if (kisaoId == "KISAO:0000477") {
if ((value != "Dense") && (value != "Banded") && (value != "Diagonal") && (value != "GMRES") && (value != "BiCGStab") && (value != "TFQMR")) {
addWarning(std::string("The linear solver ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be equal to 'Dense', 'Banded', 'Diagonal', 'GMRES', 'BiCGStab', or 'TFQMR'. A ").append(toString(DEFAULT_LINEAR_SOLVER)).append(" linear solver will be used instead."));
@@ -135,7 +181,17 @@ void SolverCvode::Impl::populate(libsedml::SedAlgorithm *pAlgorithm)
value = toString(DEFAULT_LINEAR_SOLVER);
}
- mLinearSolver = toCvodeLinearSolver(value);
+ mLinearSolver = (value == "Dense") ?
+ SolverCvode::LinearSolver::DENSE :
+ (value == "Banded") ?
+ SolverCvode::LinearSolver::BANDED :
+ (value == "Diagonal") ?
+ SolverCvode::LinearSolver::DIAGONAL :
+ (value == "GMRES") ?
+ SolverCvode::LinearSolver::GMRES :
+ (value == "BiCGStab") ?
+ SolverCvode::LinearSolver::BICGSTAB :
+ SolverCvode::LinearSolver::TFQMR;
} else if (kisaoId == "KISAO:0000478") {
if ((value != "No") && (value != "Banded")) {
addWarning(std::string("The preconditioner ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be equal to 'No' or 'Banded'. A ").append(toString(DEFAULT_PRECONDITIONER)).append(" preconditioner will be used instead."));
@@ -143,7 +199,9 @@ void SolverCvode::Impl::populate(libsedml::SedAlgorithm *pAlgorithm)
value = toString(DEFAULT_PRECONDITIONER);
}
- mPreconditioner = toCvodePreconditioner(value);
+ mPreconditioner = (value == "No") ?
+ SolverCvode::Preconditioner::NO :
+ SolverCvode::Preconditioner::BANDED;
} else if (kisaoId == "KISAO:0000479") {
mUpperHalfBandwidth = toInt(value);
@@ -247,8 +305,7 @@ StringStringMap SolverCvode::Impl::properties() const
bool SolverCvode::Impl::initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates)
+ const CellmlFileRuntimePtr &pRuntime)
{
resetInternals();
removeAllIssues();
@@ -257,7 +314,7 @@ bool SolverCvode::Impl::initialise(double pVoi, size_t pSize, double *pStates, d
SolverOde::Impl::initialise(pVoi, pSize, pStates, pRates,
pConstants, pComputedConstants, pAlgebraic,
- pComputeCompiledRates, pComputeInterpretedRates);
+ pRuntime);
// Check the solver's properties.
@@ -342,8 +399,7 @@ bool SolverCvode::Impl::initialise(double pVoi, size_t pSize, double *pStates, d
mUserData.constants = pConstants;
mUserData.computedConstants = pComputedConstants;
mUserData.algebraic = pAlgebraic;
- mUserData.computeCompiledRates = pComputeCompiledRates;
- mUserData.computeInterpretedRates = pComputeInterpretedRates;
+ mUserData.runtime = pRuntime;
ASSERT_EQ(CVodeSetUserData(mSolver, &mUserData), CV_SUCCESS);
diff --git a/src/solver/solvercvode_p.h b/src/solver/solvercvode_p.h
index ac5af0fde..365989b94 100644
--- a/src/solver/solvercvode_p.h
+++ b/src/solver/solvercvode_p.h
@@ -33,8 +33,7 @@ struct SolverCvodeUserData
double *computedConstants = nullptr;
double *algebraic = nullptr;
- CellmlFileRuntime::ComputeCompiledRates computeCompiledRates = nullptr;
- CellmlFileRuntime::ComputeInterpretedRates computeInterpretedRates = nullptr;
+ CellmlFileRuntimePtr runtime;
};
class SolverCvode::Impl: public SolverOde::Impl
@@ -91,8 +90,7 @@ class SolverCvode::Impl: public SolverOde::Impl
bool initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates) override;
+ const CellmlFileRuntimePtr &pRuntime) override;
/*---GRY--- TO BE UNCOMMENTED ONCE WE ACTUALLY NEED IT.
bool reinitialise(double pVoi) override;
*/
diff --git a/src/solver/solverforwardeuler.cpp b/src/solver/solverforwardeuler.cpp
index 94a6e987f..ed12d8732 100644
--- a/src/solver/solverforwardeuler.cpp
+++ b/src/solver/solverforwardeuler.cpp
@@ -32,8 +32,7 @@ SolverPtr SolverForwardEuler::Impl::duplicate()
bool SolverForwardEuler::Impl::initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates)
+ const CellmlFileRuntimePtr &pRuntime)
{
removeAllIssues();
@@ -41,7 +40,7 @@ bool SolverForwardEuler::Impl::initialise(double pVoi, size_t pSize, double *pSt
return SolverOdeFixedStep::Impl::initialise(pVoi, pSize, pStates, pRates,
pConstants, pComputedConstants, pAlgebraic,
- pComputeCompiledRates, pComputeInterpretedRates);
+ pRuntime);
}
bool SolverForwardEuler::Impl::solve(double &pVoi, double pVoiEnd)
diff --git a/src/solver/solverforwardeuler_p.h b/src/solver/solverforwardeuler_p.h
index e71c4f376..bf34215de 100644
--- a/src/solver/solverforwardeuler_p.h
+++ b/src/solver/solverforwardeuler_p.h
@@ -31,8 +31,7 @@ class SolverForwardEuler::Impl: public SolverOdeFixedStep::Impl
bool initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates) override;
+ const CellmlFileRuntimePtr &pRuntime) override;
bool solve(double &pVoi, double pVoiEnd) override;
};
diff --git a/src/solver/solverfourthorderrungekutta.cpp b/src/solver/solverfourthorderrungekutta.cpp
index 565c2ead1..138f11238 100644
--- a/src/solver/solverfourthorderrungekutta.cpp
+++ b/src/solver/solverfourthorderrungekutta.cpp
@@ -32,8 +32,7 @@ SolverPtr SolverFourthOrderRungeKutta::Impl::duplicate()
bool SolverFourthOrderRungeKutta::Impl::initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates)
+ const CellmlFileRuntimePtr &pRuntime)
{
removeAllIssues();
@@ -41,7 +40,7 @@ bool SolverFourthOrderRungeKutta::Impl::initialise(double pVoi, size_t pSize, do
if (!SolverOdeFixedStep::Impl::initialise(pVoi, pSize, pStates, pRates,
pConstants, pComputedConstants, pAlgebraic,
- pComputeCompiledRates, pComputeInterpretedRates)) {
+ pRuntime)) {
return false;
}
diff --git a/src/solver/solverfourthorderrungekutta_p.h b/src/solver/solverfourthorderrungekutta_p.h
index f9ad63ede..06c22181e 100644
--- a/src/solver/solverfourthorderrungekutta_p.h
+++ b/src/solver/solverfourthorderrungekutta_p.h
@@ -41,8 +41,7 @@ class SolverFourthOrderRungeKutta::Impl: public SolverOdeFixedStep::Impl
bool initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates) override;
+ const CellmlFileRuntimePtr &pRuntime) override;
bool solve(double &pVoi, double pVoiEnd) override;
};
diff --git a/src/solver/solverheun.cpp b/src/solver/solverheun.cpp
index 01af070fa..5748db2cd 100644
--- a/src/solver/solverheun.cpp
+++ b/src/solver/solverheun.cpp
@@ -32,8 +32,7 @@ SolverPtr SolverHeun::Impl::duplicate()
bool SolverHeun::Impl::initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates)
+ const CellmlFileRuntimePtr &pRuntime)
{
removeAllIssues();
@@ -41,7 +40,7 @@ bool SolverHeun::Impl::initialise(double pVoi, size_t pSize, double *pStates, do
if (!SolverOdeFixedStep::Impl::initialise(pVoi, pSize, pStates, pRates,
pConstants, pComputedConstants, pAlgebraic,
- pComputeCompiledRates, pComputeInterpretedRates)) {
+ pRuntime)) {
return false;
}
diff --git a/src/solver/solverheun_p.h b/src/solver/solverheun_p.h
index 3190f899e..14e6603fd 100644
--- a/src/solver/solverheun_p.h
+++ b/src/solver/solverheun_p.h
@@ -37,8 +37,7 @@ class SolverHeun::Impl: public SolverOdeFixedStep::Impl
bool initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates) override;
+ const CellmlFileRuntimePtr &pRuntime) override;
bool solve(double &pVoi, double pVoiEnd) override;
};
diff --git a/src/solver/solverkinsol.cpp b/src/solver/solverkinsol.cpp
index 66eb96193..27dccc9ee 100644
--- a/src/solver/solverkinsol.cpp
+++ b/src/solver/solverkinsol.cpp
@@ -34,6 +34,25 @@ limitations under the License.
namespace libOpenCOR {
+// Some utilities.
+
+namespace {
+
+std::string toString(SolverKinsol::LinearSolver pLinearSolver)
+{
+ return (pLinearSolver == SolverKinsol::LinearSolver::DENSE) ?
+ "Dense" :
+ (pLinearSolver == SolverKinsol::LinearSolver::BANDED) ?
+ "Banded" :
+ (pLinearSolver == SolverKinsol::LinearSolver::GMRES) ?
+ "GMRES" :
+ (pLinearSolver == SolverKinsol::LinearSolver::BICGSTAB) ?
+ "BiCGStab" :
+ "TFQMR";
+}
+
+} // namespace
+
// Compute system.
namespace {
@@ -53,18 +72,33 @@ void errorHandler(int pLine, const char *pFunction, const char *pFile, const cha
}
#endif
+#ifdef __EMSCRIPTEN__
+static constexpr auto MAX_SIZE_T = std::numeric_limits::max();
+#endif
+
struct SolverKinsolUserData
{
- SolverNla::ComputeSystem computeSystem = nullptr;
+#ifdef __EMSCRIPTEN__
+ size_t computeObjectiveFunctionIndex = MAX_SIZE_T;
+#else
+ SolverNla::ComputeObjectiveFunction computeObjectiveFunction = nullptr;
+#endif
void *userData = nullptr;
};
-int computeSystem(N_Vector pU, N_Vector pF, void *pUserData)
+int computeObjectiveFunction(N_Vector pU, N_Vector pF, void *pUserData)
{
auto *userData = static_cast(pUserData);
- userData->computeSystem(N_VGetArrayPointer_Serial(pU), N_VGetArrayPointer_Serial(pF), userData->userData);
+#ifdef __EMSCRIPTEN__
+ // clang-format off
+ EM_ASM({
+ Module.objectiveFunctions[$0]($1, $2, $3);
+ }, userData->computeObjectiveFunctionIndex, N_VGetArrayPointer_Serial(pU), N_VGetArrayPointer_Serial(pF), userData->userData); // clang-format on
+#else
+ userData->computeObjectiveFunction(N_VGetArrayPointer_Serial(pU), N_VGetArrayPointer_Serial(pF), userData->userData);
+#endif
return 0;
}
@@ -100,7 +134,15 @@ void SolverKinsol::Impl::populate(libsedml::SedAlgorithm *pAlgorithm)
value = toString(DEFAULT_LINEAR_SOLVER);
}
- mLinearSolver = toKinsolLinearSolver(value);
+ mLinearSolver = (value == "Dense") ?
+ SolverKinsol::LinearSolver::DENSE :
+ (value == "Banded") ?
+ SolverKinsol::LinearSolver::BANDED :
+ (value == "GMRES") ?
+ SolverKinsol::LinearSolver::GMRES :
+ (value == "BiCGStab") ?
+ SolverKinsol::LinearSolver::BICGSTAB :
+ SolverKinsol::LinearSolver::TFQMR;
} else if (kisaoId == "KISAO:0000479") {
mUpperHalfBandwidth = toInt(value);
@@ -188,11 +230,15 @@ void SolverKinsol::Impl::setLowerHalfBandwidth(int pLowerHalfBandwidth)
mLowerHalfBandwidth = pLowerHalfBandwidth;
}
-bool SolverKinsol::Impl::solve(ComputeSystem pComputeSystem, double *pU, size_t pN, void *pUserData)
+#ifdef __EMSCRIPTEN__
+bool SolverKinsol::Impl::solve(size_t pComputeObjectiveFunctionIndex, double *pU, size_t pN, void *pUserData)
+#else
+bool SolverKinsol::Impl::solve(ComputeObjectiveFunction pComputeObjectiveFunction, double *pU, size_t pN, void *pUserData)
+#endif
{
removeAllIssues();
- // We don't have any data associated with the given pComputeSystem, so get some by first making sure that the
+ // We don't have any data associated with the given objective function, so get some by first making sure that the
// solver's properties are all valid.
if (mMaximumNumberOfIterations <= 0) {
@@ -252,7 +298,7 @@ bool SolverKinsol::Impl::solve(ComputeSystem pComputeSystem, double *pU, size_t
N_VConst(1.0, ones);
- ASSERT_EQ(KINInit(solver, computeSystem, u), KIN_SUCCESS);
+ ASSERT_EQ(KINInit(solver, computeObjectiveFunction, u), KIN_SUCCESS);
// Set our linear solver.
@@ -293,7 +339,11 @@ bool SolverKinsol::Impl::solve(ComputeSystem pComputeSystem, double *pU, size_t
SolverKinsolUserData userData;
- userData.computeSystem = pComputeSystem;
+#ifdef __EMSCRIPTEN__
+ userData.computeObjectiveFunctionIndex = pComputeObjectiveFunctionIndex;
+#else
+ userData.computeObjectiveFunction = pComputeObjectiveFunction;
+#endif
userData.userData = pUserData;
ASSERT_EQ(KINSetUserData(solver, &userData), KIN_SUCCESS);
diff --git a/src/solver/solverkinsol_p.h b/src/solver/solverkinsol_p.h
index 5ee2b42b0..19ce31e99 100644
--- a/src/solver/solverkinsol_p.h
+++ b/src/solver/solverkinsol_p.h
@@ -57,7 +57,11 @@ class SolverKinsol::Impl: public SolverNla::Impl
int lowerHalfBandwidth() const;
void setLowerHalfBandwidth(int pLowerHalfBandwidth);
- bool solve(ComputeSystem pComputeSystem, double *pU, size_t pN, void *pUserData) override;
+#ifdef __EMSCRIPTEN__
+ bool solve(size_t pComputeObjectiveFunctionIndex, double *pU, size_t pN, void *pUserData) override;
+#else
+ bool solve(ComputeObjectiveFunction pComputeObjectiveFunction, double *pU, size_t pN, void *pUserData) override;
+#endif
};
} // namespace libOpenCOR
diff --git a/src/solver/solvernla.cpp b/src/solver/solvernla.cpp
index ae4f28f62..c3dfd1f54 100644
--- a/src/solver/solvernla.cpp
+++ b/src/solver/solvernla.cpp
@@ -20,18 +20,18 @@ limitations under the License.
namespace libOpenCOR {
-void nlaSolve(const char *pNlaSolverAddress, void (*pObjectiveFunction)(double *, double *, void *),
+#ifdef __EMSCRIPTEN__
+void nlaSolve(uintptr_t pNlaSolverAddress, size_t pObjectiveFunctionIndex, double *pU, size_t pN, void *pData)
+{
+ reinterpret_cast(pNlaSolverAddress)->solve(pObjectiveFunctionIndex, pU, pN, pData);
+}
+#else
+void nlaSolve(uintptr_t pNlaSolverAddress, void (*pObjectiveFunction)(double *, double *, void *),
double *pU, size_t pN, void *pData)
{
- std::istringstream iss(pNlaSolverAddress);
- void *ptr = nullptr;
-
- iss >> ptr;
-
- ASSERT_NE(ptr, nullptr);
-
- reinterpret_cast(ptr)->solve(pObjectiveFunction, pU, pN, pData);
+ reinterpret_cast(pNlaSolverAddress)->solve(pObjectiveFunction, pU, pN, pData); // NOLINT
}
+#endif
SolverNla::Impl::Impl(const std::string &pId, const std::string &pName)
: Solver::Impl(pId, pName)
@@ -58,9 +58,16 @@ Solver::Type SolverNla::type() const
return Type::NLA;
}
-bool SolverNla::solve(ComputeSystem pComputeSystem, double *pU, size_t pN, void *pUserData)
+#ifdef __EMSCRIPTEN__
+bool SolverNla::solve(size_t pComputeObjectiveFunctionIndex, double *pU, size_t pN, void *pUserData)
+{
+ return pimpl()->solve(pComputeObjectiveFunctionIndex, pU, pN, pUserData);
+}
+#else
+bool SolverNla::solve(ComputeObjectiveFunction pComputeObjectiveFunction, double *pU, size_t pN, void *pUserData)
{
- return pimpl()->solve(pComputeSystem, pU, pN, pUserData);
+ return pimpl()->solve(pComputeObjectiveFunction, pU, pN, pUserData);
}
+#endif
} // namespace libOpenCOR
diff --git a/src/solver/solvernla_p.h b/src/solver/solvernla_p.h
index 9a7dc76c8..cc6b7564f 100644
--- a/src/solver/solvernla_p.h
+++ b/src/solver/solvernla_p.h
@@ -22,16 +22,23 @@ limitations under the License.
namespace libOpenCOR {
-void LIBOPENCOR_UNIT_TESTING_EXPORT nlaSolve(const char *pNlaSolverAddress,
- void (*pObjectiveFunction)(double *, double *, void *),
- double *pU, size_t pN, void *pData);
+#ifdef __EMSCRIPTEN__
+void nlaSolve(uintptr_t pNlaSolverAddress, size_t pObjectiveFunctionIndex, double *pU, size_t pN, void *pData);
+#else
+void nlaSolve(uintptr_t pNlaSolverAddress, void (*pObjectiveFunction)(double *, double *, void *),
+ double *pU, size_t pN, void *pData);
+#endif
class SolverNla::Impl: public Solver::Impl
{
public:
explicit Impl(const std::string &pId, const std::string &pName);
- virtual bool solve(ComputeSystem pComputeSystem, double *pU, size_t pN, void *pUserData) = 0;
+#ifdef __EMSCRIPTEN__
+ virtual bool solve(size_t pComputeObjectiveFunctionIndex, double *pU, size_t pN, void *pUserData) = 0;
+#else
+ virtual bool solve(ComputeObjectiveFunction pComputeObjectiveFunction, double *pU, size_t pN, void *pUserData) = 0;
+#endif
};
} // namespace libOpenCOR
diff --git a/src/solver/solverode.cpp b/src/solver/solverode.cpp
index f9a04490c..dec2d15d5 100644
--- a/src/solver/solverode.cpp
+++ b/src/solver/solverode.cpp
@@ -25,8 +25,7 @@ SolverOde::Impl::Impl(const std::string &pId, const std::string &pName)
bool SolverOde::Impl::initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates)
+ const CellmlFileRuntimePtr &pRuntime)
{
(void)pVoi;
@@ -38,8 +37,7 @@ bool SolverOde::Impl::initialise(double pVoi, size_t pSize, double *pStates, dou
mComputedConstants = pComputedConstants;
mAlgebraic = pAlgebraic;
- mComputeCompiledRates = pComputeCompiledRates;
- mComputeInterpretedRates = std::move(pComputeInterpretedRates);
+ mRuntime = pRuntime;
return true;
}
@@ -56,11 +54,11 @@ bool SolverOde::Impl::reinitialise(double pVoi)
void SolverOde::Impl::computeRates(double pVoi, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic) const
{
- if (mComputeCompiledRates != nullptr) {
- mComputeCompiledRates(pVoi, pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
- } else {
- mComputeInterpretedRates(pVoi, pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
- }
+#ifdef __EMSCRIPTEN__
+ mRuntime->computeRates(pVoi, pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
+#else
+ mRuntime->computeRates()(pVoi, pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
+#endif
}
SolverOde::SolverOde(Impl *pPimpl)
diff --git a/src/solver/solverode_p.h b/src/solver/solverode_p.h
index d23ab6b2e..0725be743 100644
--- a/src/solver/solverode_p.h
+++ b/src/solver/solverode_p.h
@@ -35,15 +35,13 @@ class SolverOde::Impl: public Solver::Impl
double *mComputedConstants = nullptr;
double *mAlgebraic = nullptr;
- CellmlFileRuntime::ComputeCompiledRates mComputeCompiledRates = nullptr;
- CellmlFileRuntime::ComputeInterpretedRates mComputeInterpretedRates = nullptr;
+ CellmlFileRuntimePtr mRuntime;
explicit Impl(const std::string &pId, const std::string &pName);
virtual bool initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates) = 0;
+ const CellmlFileRuntimePtr &pRuntime) = 0;
/*---GRY--- TO BE UNCOMMENTED ONCE WE ACTUALLY NEED IT.
virtual bool reinitialise(double pVoi);
*/
diff --git a/src/solver/solverodefixedstep.cpp b/src/solver/solverodefixedstep.cpp
index 443aa1291..2f1460011 100644
--- a/src/solver/solverodefixedstep.cpp
+++ b/src/solver/solverodefixedstep.cpp
@@ -70,14 +70,13 @@ StringStringMap SolverOdeFixedStep::Impl::properties() const
bool SolverOdeFixedStep::Impl::initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates)
+ const CellmlFileRuntimePtr &pRuntime)
{
// Initialise the ODE solver itself.
SolverOde::Impl::initialise(pVoi, pSize, pStates, pRates,
pConstants, pComputedConstants, pAlgebraic,
- pComputeCompiledRates, pComputeInterpretedRates);
+ pRuntime);
// Check the solver's properties.
diff --git a/src/solver/solverodefixedstep_p.h b/src/solver/solverodefixedstep_p.h
index 251676902..0a279cd4a 100644
--- a/src/solver/solverodefixedstep_p.h
+++ b/src/solver/solverodefixedstep_p.h
@@ -41,8 +41,7 @@ class SolverOdeFixedStep::Impl: public SolverOde::Impl
bool initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates) override;
+ const CellmlFileRuntimePtr &pRuntime) override;
double step() const;
void setStep(double pStep);
diff --git a/src/solver/solversecondorderrungekutta.cpp b/src/solver/solversecondorderrungekutta.cpp
index 75ec7cc9b..f1a6fb1ea 100644
--- a/src/solver/solversecondorderrungekutta.cpp
+++ b/src/solver/solversecondorderrungekutta.cpp
@@ -32,8 +32,7 @@ SolverPtr SolverSecondOrderRungeKutta::Impl::duplicate()
bool SolverSecondOrderRungeKutta::Impl::initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates)
+ const CellmlFileRuntimePtr &pRuntime)
{
removeAllIssues();
@@ -41,7 +40,7 @@ bool SolverSecondOrderRungeKutta::Impl::initialise(double pVoi, size_t pSize, do
if (!SolverOdeFixedStep::Impl::initialise(pVoi, pSize, pStates, pRates,
pConstants, pComputedConstants, pAlgebraic,
- pComputeCompiledRates, pComputeInterpretedRates)) {
+ pRuntime)) {
return false;
}
diff --git a/src/solver/solversecondorderrungekutta_p.h b/src/solver/solversecondorderrungekutta_p.h
index a22d05cf6..dfbe5d8ed 100644
--- a/src/solver/solversecondorderrungekutta_p.h
+++ b/src/solver/solversecondorderrungekutta_p.h
@@ -35,8 +35,7 @@ class SolverSecondOrderRungeKutta::Impl: public SolverOdeFixedStep::Impl
bool initialise(double pVoi, size_t pSize, double *pStates, double *pRates,
double *pConstants, double *pComputedConstants, double *pAlgebraic,
- CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates,
- CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates) override;
+ const CellmlFileRuntimePtr &pRuntime) override;
bool solve(double &pVoi, double pVoiEnd) override;
};
diff --git a/src/support/cellml/cellmlfile.cpp b/src/support/cellml/cellmlfile.cpp
index 6a477cd68..57a65649f 100644
--- a/src/support/cellml/cellmlfile.cpp
+++ b/src/support/cellml/cellmlfile.cpp
@@ -55,16 +55,6 @@ CellmlFile::Impl::Impl(const FilePtr &pFile, const libcellml::ModelPtr &pModel,
if (mAnalyser->errorCount() != 0) {
addIssues(mAnalyser);
}
-
- //---GRY--- WHEN USING OUR JavaScript BINDINGS, TEMPORARILY MAKE SURE THAT THE MODEL IS EITHER AN ALGEBRAIC MODEL OR AN ODE MODEL.
-
-#ifdef __EMSCRIPTEN__
- if (!hasIssues()
- && (mAnalyserModel->type() != libcellml::AnalyserModel::Type::ALGEBRAIC)
- && (mAnalyserModel->type() != libcellml::AnalyserModel::Type::ODE)) {
- addError("Only CellML files describing either an algebraic model or an ODE model are currently supported.");
- }
-#endif
}
void CellmlFile::Impl::populateDocument(const SedDocumentPtr &pDocument) const
@@ -122,10 +112,9 @@ libcellml::AnalyserModelPtr CellmlFile::Impl::analyserModel() const
return mAnalyserModel;
}
-CellmlFileRuntimePtr CellmlFile::Impl::runtime(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver,
- bool pCompiled)
+CellmlFileRuntimePtr CellmlFile::Impl::runtime(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver)
{
- return CellmlFileRuntime::create(pCellmlFile, pNlaSolver, pCompiled);
+ return CellmlFileRuntime::create(pCellmlFile, pNlaSolver);
}
CellmlFile::CellmlFile(const FilePtr &pFile, const libcellml::ModelPtr &pModel, bool pStrict)
@@ -200,9 +189,9 @@ libcellml::AnalyserModelPtr CellmlFile::analyserModel() const
return pimpl()->analyserModel();
}
-CellmlFileRuntimePtr CellmlFile::runtime(const SolverNlaPtr &pNlaSolver, bool pCompiled)
+CellmlFileRuntimePtr CellmlFile::runtime(const SolverNlaPtr &pNlaSolver)
{
- return CellmlFile::Impl::runtime(shared_from_this(), pNlaSolver, pCompiled);
+ return CellmlFile::Impl::runtime(shared_from_this(), pNlaSolver);
}
} // namespace libOpenCOR
diff --git a/src/support/cellml/cellmlfile.h b/src/support/cellml/cellmlfile.h
index e2e9b7624..cbc4e5a2b 100644
--- a/src/support/cellml/cellmlfile.h
+++ b/src/support/cellml/cellmlfile.h
@@ -26,7 +26,6 @@ limitations under the License.
#include "libcellml/generator.h"
#include "libcellml/generatorprofile.h"
#include "libcellml/importer.h"
-#include "libcellml/interpreter.h"
#include "libcellml/model.h"
#include "libcellml/parser.h"
#include "libcellml/units.h"
@@ -64,7 +63,7 @@ class LIBOPENCOR_UNIT_TESTING_EXPORT CellmlFile: public Logger
libcellml::AnalyserPtr analyser() const;
libcellml::AnalyserModelPtr analyserModel() const;
- CellmlFileRuntimePtr runtime(const SolverNlaPtr &pNlaSolver = {}, bool pCompiled = true);
+ CellmlFileRuntimePtr runtime(const SolverNlaPtr &pNlaSolver = {});
private:
class Impl;
diff --git a/src/support/cellml/cellmlfile_p.h b/src/support/cellml/cellmlfile_p.h
index ec62556ef..34f0c3100 100644
--- a/src/support/cellml/cellmlfile_p.h
+++ b/src/support/cellml/cellmlfile_p.h
@@ -40,8 +40,7 @@ class CellmlFile::Impl: public Logger::Impl
libcellml::AnalyserPtr analyser() const;
libcellml::AnalyserModelPtr analyserModel() const;
- static CellmlFileRuntimePtr runtime(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver,
- bool pCompiled);
+ static CellmlFileRuntimePtr runtime(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver);
};
} // namespace libOpenCOR
diff --git a/src/support/cellml/cellmlfileruntime.cpp b/src/support/cellml/cellmlfileruntime.cpp
index 0dd42c377..f00d1cece 100644
--- a/src/support/cellml/cellmlfileruntime.cpp
+++ b/src/support/cellml/cellmlfileruntime.cpp
@@ -21,7 +21,139 @@ limitations under the License.
namespace libOpenCOR {
-CellmlFileRuntime::Impl::Impl(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver, bool pCompiled)
+#ifdef __EMSCRIPTEN__
+// Some utilities.
+
+namespace {
+
+std::string exportJavaScriptName(const std::string &pName)
+{
+ return std::string("__attribute__((export_name(\"").append(pName).append("\")))\n");
+}
+
+void *instantiateWebAssemblyModule(UnsignedChars pWasmModule, bool pDifferentialModel, bool pIsOdeModel,
+ bool pIsAlgebraicModel, bool pHasObjectiveFunctions)
+{
+ // clang-format off
+ return EM_ASM_PTR({
+ try {
+ // Instantiate the WebAssembly module.
+
+ const wasmBytes = new Uint8Array(HEAPU8.subarray($0, $0 + $1));
+ const wasmModule = new WebAssembly.Module(wasmBytes);
+ const wasmInstance = new WebAssembly.Instance(wasmModule, {
+ env: {
+ __linear_memory: wasmMemory,
+ __indirect_function_table: wasmTable,
+
+ // Some standard C library functions.
+
+ free: _free,
+ malloc: _malloc,
+
+ // NLA solve function.
+
+ nlaSolve: function(nlaSolverAddress, objectiveFunctionIndex, u, n, data) {
+ Module.nlaSolve(Number(nlaSolverAddress), Number(objectiveFunctionIndex), Number(u), Number(n), Number(data));
+ },
+
+ // Arithmetic operators.
+
+ pow: Math.pow,
+ // sqrt() is not needed.
+ // fabs() is not needed.
+ exp: Math.exp,
+ // log() is not needed.
+ // log10() is not needed.
+ // ceil() is not needed.
+ // floor() is not needed.
+ // fmin() is not needed.
+ // fmax() is not needed.
+ // fmod() is not needed.
+
+ // Trigonometric operators.
+
+ sin: Math.sin,
+ cos: Math.cos,
+ tan: Math.tan,
+ sinh: Math.sinh,
+ cosh: Math.cosh,
+ tanh: Math.tanh,
+ asin: Math.asin,
+ acos: Math.acos,
+ atan: Math.atan,
+ asinh: Math.asinh,
+ acosh: Math.acosh,
+ atanh: Math.atanh,
+
+ // Constants.
+
+ // INFINITY is not needed.
+ // NAN is not needed.
+ }
+ });
+
+ // Retrieve the functions needed to compute the model.
+
+ if ($2) {
+ Module.initialiseVariables = wasmInstance.exports.initialiseVariables;
+ Module.computeComputedConstants = wasmInstance.exports.computeComputedConstants;
+ Module.computeRates = wasmInstance.exports.computeRates;
+ Module.computeVariables = wasmInstance.exports.computeVariables;
+
+ if ((Module.initialiseVariables === undefined)
+ || (Module.computeComputedConstants === undefined)
+ || (Module.computeRates === undefined)
+ || (Module.computeVariables === undefined)) {
+ throw new Error("The functions needed to compute the " + ($3 ? "ODE" : "DAE") + " model could not be retrieved.");
+ }
+ } else {
+ Module.initialiseVariables = wasmInstance.exports.initialiseVariables;
+ Module.computeComputedConstants = wasmInstance.exports.computeComputedConstants;
+ Module.computeVariables = wasmInstance.exports.computeVariables;
+
+ if ((Module.initialiseVariables === undefined)
+ || (Module.computeComputedConstants === undefined)
+ || (Module.computeVariables === undefined)) {
+ throw new Error("The functions needed to compute the " + ($4 ? "algebraic" : "NLA") + " model could not be retrieved.");
+ }
+ }
+
+ // Retrieve the objective functions, if any.
+
+ if ($5) {
+ Module.objectiveFunctions = {};
+
+ for (let name in wasmInstance.exports) {
+ if (name.startsWith("objectiveFunction")) {
+ const objectiveFunctionIndex = parseInt(name.replace("objectiveFunction", ""));
+
+ Module.objectiveFunctions[objectiveFunctionIndex] = wasmInstance.exports[name];
+ }
+ }
+
+ if (Object.keys(Module.objectiveFunctions).length === 0) {
+ throw new Error("The objective functions could not be retrieved.");
+ }
+ }
+
+ return null;
+ } catch (error) {
+ const errorMessage = error.toString();
+ const errorMessageLength = lengthBytesUTF8(errorMessage) + 1;
+ const errorMessagePtr = _malloc(errorMessageLength);
+
+ stringToUTF8(errorMessage, errorMessagePtr, errorMessageLength);
+
+ return errorMessagePtr;
+ }
+ }, pWasmModule.data(), pWasmModule.size(), pDifferentialModel, pIsOdeModel, pIsAlgebraicModel, pHasObjectiveFunctions); // clang-format on
+}
+
+} // namespace
+#endif
+
+CellmlFileRuntime::Impl::Impl(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver)
{
auto cellmlFileAnalyser = pCellmlFile->analyser();
@@ -34,223 +166,344 @@ CellmlFileRuntime::Impl::Impl(const CellmlFilePtr &pCellmlFile, const SolverNlaP
mNlaSolverAddress = nlaSolverAddress(pNlaSolver.get());
}
- // Get either a compiled or an interpreted version of the runtime.
-
-#ifndef __EMSCRIPTEN__
- if (pCompiled) {
- // Determine the type of the model.
-
- auto cellmlFileType = pCellmlFile->type();
- auto differentialModel = (cellmlFileType == libcellml::AnalyserModel::Type::ODE)
- || (cellmlFileType == libcellml::AnalyserModel::Type::DAE);
-
- // Generate some code for the given CellML file.
-
- auto generator = libcellml::Generator::create();
- auto generatorProfile = libcellml::GeneratorProfile::create();
-
- generatorProfile->setOriginCommentString("");
- generatorProfile->setImplementationHeaderString("");
- generatorProfile->setImplementationVersionString("");
- generatorProfile->setImplementationStateCountString("");
- generatorProfile->setImplementationConstantCountString("");
- generatorProfile->setImplementationComputedConstantCountString("");
- generatorProfile->setImplementationAlgebraicCountString("");
- generatorProfile->setImplementationExternalCountString("");
- generatorProfile->setImplementationLibcellmlVersionString("");
- generatorProfile->setImplementationVoiInfoString("");
- generatorProfile->setImplementationStateInfoString("");
- generatorProfile->setImplementationConstantInfoString("");
- generatorProfile->setImplementationComputedConstantInfoString("");
- generatorProfile->setImplementationAlgebraicInfoString("");
- generatorProfile->setImplementationExternalInfoString("");
- generatorProfile->setImplementationCreateStatesArrayMethodString("");
- generatorProfile->setImplementationCreateConstantsArrayMethodString("");
- generatorProfile->setImplementationCreateComputedConstantsArrayMethodString("");
- generatorProfile->setImplementationCreateAlgebraicArrayMethodString("");
- generatorProfile->setImplementationCreateExternalsArrayMethodString("");
- generatorProfile->setImplementationDeleteArrayMethodString("");
-
- if (pNlaSolver != nullptr) {
- generatorProfile->setExternNlaSolveMethodString("typedef unsigned long long size_t;\n"
- "\n"
- "extern void nlaSolve(const char *, void (*objectiveFunction)(double *, double *, void *),\n"
- " double *u, size_t n, void *data);\n");
- generatorProfile->setNlaSolveCallString(differentialModel, false,
- std::string("nlaSolve(\"") + mNlaSolverAddress + "\", objectiveFunction[INDEX], u, [SIZE], &rfi);\n");
+ // Determine the type of the model.
+
+ auto cellmlFileType = pCellmlFile->type();
+ auto differentialModel = (cellmlFileType == libcellml::AnalyserModel::Type::ODE)
+ || (cellmlFileType == libcellml::AnalyserModel::Type::DAE);
+
+ // Generate some code for the given CellML file.
+
+ auto generator = libcellml::Generator::create();
+ auto generatorProfile = libcellml::GeneratorProfile::create();
+
+ generatorProfile->setOriginCommentString("");
+ generatorProfile->setImplementationHeaderString("");
+ generatorProfile->setImplementationVersionString("");
+ generatorProfile->setImplementationStateCountString("");
+ generatorProfile->setImplementationConstantCountString("");
+ generatorProfile->setImplementationComputedConstantCountString("");
+ generatorProfile->setImplementationAlgebraicCountString("");
+ generatorProfile->setImplementationExternalCountString("");
+ generatorProfile->setImplementationLibcellmlVersionString("");
+ generatorProfile->setImplementationVoiInfoString("");
+ generatorProfile->setImplementationStateInfoString("");
+ generatorProfile->setImplementationConstantInfoString("");
+ generatorProfile->setImplementationComputedConstantInfoString("");
+ generatorProfile->setImplementationAlgebraicInfoString("");
+ generatorProfile->setImplementationExternalInfoString("");
+ generatorProfile->setImplementationCreateStatesArrayMethodString("");
+ generatorProfile->setImplementationCreateConstantsArrayMethodString("");
+ generatorProfile->setImplementationCreateComputedConstantsArrayMethodString("");
+ generatorProfile->setImplementationCreateAlgebraicArrayMethodString("");
+ generatorProfile->setImplementationCreateExternalsArrayMethodString("");
+ generatorProfile->setImplementationDeleteArrayMethodString("");
+
+ static constexpr auto WITH_EXTERNAL_VARIABLES = false;
+
+#ifdef __EMSCRIPTEN__
+ // Allocate the memory needed by our objective functions on the heap rather than on the stack.
+
+ if (pNlaSolver != nullptr) {
+ if (differentialModel) {
+ generatorProfile->setFindRootMethodString(differentialModel, WITH_EXTERNAL_VARIABLES,
+ R"(void findRoot[INDEX](double voi, double *states, double *rates, double *constants, double *computedConstants, double *algebraic)
+{
+ RootFindingInfo *rfi = (RootFindingInfo *) malloc(sizeof(RootFindingInfo));
+ double *u = (double *) malloc([SIZE] * sizeof(double));
+
+ rfi->voi = voi;
+ rfi->states = states;
+ rfi->rates = rates;
+ rfi->constants = constants;
+ rfi->computedConstants = computedConstants;
+ rfi->algebraic = algebraic;
+
+[CODE]
+
+ free(u);
+ free(rfi);
+}
+)");
+ } else {
+ generatorProfile->setFindRootMethodString(differentialModel, WITH_EXTERNAL_VARIABLES,
+ R"(void findRoot[INDEX](double *constants, double *computedConstants, double *algebraic)
+{
+ RootFindingInfo *rfi = (RootFindingInfo *) malloc(sizeof(RootFindingInfo));
+ double *u = (double *) malloc([SIZE] * sizeof(double));
+
+ rfi->constants = constants;
+ rfi->computedConstants = computedConstants;
+ rfi->algebraic = algebraic;
+
+[CODE]
+
+ free(u);
+ free(rfi);
+}
+)");
}
+ }
+
+ // Export our various methods.
+
+ generatorProfile->setImplementationInitialiseVariablesMethodString(differentialModel,
+ exportJavaScriptName("initialiseVariables").append(generatorProfile->implementationInitialiseVariablesMethodString(differentialModel)));
+ generatorProfile->setImplementationComputeComputedConstantsMethodString(exportJavaScriptName("computeComputedConstants").append(generatorProfile->implementationComputeComputedConstantsMethodString()));
+ generatorProfile->setImplementationComputeRatesMethodString(WITH_EXTERNAL_VARIABLES,
+ exportJavaScriptName("computeRates").append(generatorProfile->implementationComputeRatesMethodString(WITH_EXTERNAL_VARIABLES)));
+ generatorProfile->setImplementationComputeVariablesMethodString(differentialModel, WITH_EXTERNAL_VARIABLES,
+ exportJavaScriptName("computeVariables").append(generatorProfile->implementationComputeVariablesMethodString(differentialModel, WITH_EXTERNAL_VARIABLES)));
+#endif
- generator->setModel(pCellmlFile->analyserModel());
- generator->setProfile(generatorProfile);
+ if (pNlaSolver != nullptr) {
+ // Note: both uintptr_t and size_t are defined as follows:
+ // - Emscripten (wasm32): unsigned int (which is the same as unsigned long on 32 bits and is what we
+ // need to use here since malloc() expects an unsigned long);
+ // - Windows (64 bits): unsigned long long; and
+ // - Linux/macOS (64 bits): unsigned long.
+
+#ifdef __EMSCRIPTEN__
+ generatorProfile->setExternNlaSolveMethodString(R"(typedef unsigned long uintptr_t;
+typedef unsigned long size_t;
+
+extern void *malloc(size_t size);
+extern void free(void *ptr);
+
+extern void nlaSolve(uintptr_t nlaSolverAddress, size_t objectiveFunctionIndex, uintptr_t u, size_t n, uintptr_t data);
+)");
+ generatorProfile->setNlaSolveCallString(differentialModel, WITH_EXTERNAL_VARIABLES,
+ std::string("nlaSolve(").append(mNlaSolverAddress).append(", [INDEX], (uintptr_t) u, [SIZE], (uintptr_t) rfi);\n"));
+#else
+# ifdef BUILDING_USING_MSVC
+ generatorProfile->setExternNlaSolveMethodString(R"(typedef unsigned long long uintptr_t;
+typedef unsigned long long size_t;
+
+extern void nlaSolve(uintptr_t nlaSolverAddress, void (*objectiveFunction)(double *, double *, void *),
+ double *u, size_t n, void *data);
+)");
+# else
+ generatorProfile->setExternNlaSolveMethodString(R"(typedef unsigned long uintptr_t;
+typedef unsigned long size_t;
+
+extern void nlaSolve(uintptr_t nlaSolverAddress, void (*objectiveFunction)(double *, double *, void *),
+ double *u, size_t n, void *data);
+)");
+# endif
+ generatorProfile->setNlaSolveCallString(differentialModel, WITH_EXTERNAL_VARIABLES,
+ std::string("nlaSolve(").append(mNlaSolverAddress).append(", objectiveFunction[INDEX], u, [SIZE], &rfi);\n"));
+#endif
+ }
+
+ generator->setModel(pCellmlFile->analyserModel());
+ generator->setProfile(generatorProfile);
+
+#ifdef __EMSCRIPTEN__
+ // Export our various objective functions.
+
+ auto implementationCode = generator->implementationCode();
+
+ if (pNlaSolver != nullptr) {
+ std::vector handledNlaSystemIndices;
- // Compile the generated code.
+ for (const auto &equation : pCellmlFile->analyserModel()->equations()) {
+ if (equation->type() == libcellml::AnalyserEquation::Type::NLA) {
+ auto nlaSystemIndex = equation->nlaSystemIndex();
- mCompiler = Compiler::create();
+ if (std::find(handledNlaSystemIndices.begin(), handledNlaSystemIndices.end(), nlaSystemIndex) == handledNlaSystemIndices.end()) {
+ auto objectiveFunctionName = std::string("objectiveFunction").append(std::to_string(nlaSystemIndex));
+ implementationCode.insert(implementationCode.find("void " + objectiveFunctionName),
+ exportJavaScriptName(objectiveFunctionName));
+
+ handledNlaSystemIndices.push_back(nlaSystemIndex);
+ }
+ }
+ }
+ }
+#endif
+
+ // Compile the generated code.
+
+ mCompiler = Compiler::create();
+
+#ifdef __EMSCRIPTEN__
+ if (!mCompiler->compile(implementationCode, mWasmModule)) {
+ // The compilation failed, so add the issues it generated.
+
+ addIssues(mCompiler);
+
+ return;
+ }
+
+ // Instantiate the WebAssembly module.
+
+ auto errorMessagePtr = instantiateWebAssemblyModule(mWasmModule, differentialModel,
+ cellmlFileType == libcellml::AnalyserModel::Type::ODE,
+ cellmlFileType == libcellml::AnalyserModel::Type::ALGEBRAIC,
+ pNlaSolver != nullptr);
+
+ if (errorMessagePtr != nullptr) {
+ std::string jsErrorMessage(reinterpret_cast(errorMessagePtr));
+
+ free(errorMessagePtr);
+
+ addError(std::string("The WebAssembly module could not be instantiated (").append(jsErrorMessage).append(")."));
+
+ return;
+ }
+#else
# ifdef CODE_COVERAGE_ENABLED
- mCompiler->compile(generator->implementationCode());
+ mCompiler->compile(generator->implementationCode());
# else
- if (!mCompiler->compile(generator->implementationCode())) {
- // The compilation failed, so add the issues it generated.
+ if (!mCompiler->compile(generator->implementationCode())) {
+ // The compilation failed, so add the issues it generated.
- addIssues(mCompiler);
+ addIssues(mCompiler);
- return;
- }
+ return;
+ }
# endif
- // Make sure that our compiler knows about nlaSolve(), if needed.
+ // Make sure that our compiler knows about nlaSolve(), if needed.
- if ((cellmlFileType == libcellml::AnalyserModel::Type::NLA)
- || (cellmlFileType == libcellml::AnalyserModel::Type::DAE)) {
+ if ((cellmlFileType == libcellml::AnalyserModel::Type::NLA)
+ || (cellmlFileType == libcellml::AnalyserModel::Type::DAE)) {
# ifndef CODE_COVERAGE_ENABLED
- const bool functionAdded =
+ const bool functionAdded =
# endif
- mCompiler->addFunction("nlaSolve", reinterpret_cast(nlaSolve));
+ mCompiler->addFunction("nlaSolve", reinterpret_cast(nlaSolve));
# ifndef CODE_COVERAGE_ENABLED
- if (!functionAdded) {
- addIssues(mCompiler);
+ if (!functionAdded) {
+ addIssues(mCompiler);
- return;
- }
-# endif
+ return;
}
+# endif
+ }
- // Retrieve our algebraic/differential functions and make sure that we managed to retrieve them.
+ // Retrieve our algebraic/differential functions and make sure that we managed to retrieve them.
- if (differentialModel) {
- mInitialiseCompiledVariablesForDifferentialModel = reinterpret_cast(mCompiler->function("initialiseVariables"));
- mComputeCompiledComputedConstants = reinterpret_cast(mCompiler->function("computeComputedConstants"));
- mComputeCompiledRates = reinterpret_cast(mCompiler->function("computeRates"));
- mComputeCompiledVariablesForDifferentialModel = reinterpret_cast(mCompiler->function("computeVariables"));
+ if (differentialModel) {
+ mInitialiseVariablesForDifferentialModel = reinterpret_cast(mCompiler->function("initialiseVariables"));
+ mComputeComputedConstants = reinterpret_cast(mCompiler->function("computeComputedConstants"));
+ mComputeRates = reinterpret_cast(mCompiler->function("computeRates"));
+ mComputeVariablesForDifferentialModel = reinterpret_cast(mCompiler->function("computeVariables"));
# ifndef CODE_COVERAGE_ENABLED
- if ((mInitialiseCompiledVariablesForDifferentialModel == nullptr)
- || (mComputeCompiledComputedConstants == nullptr)
- || (mComputeCompiledRates == nullptr)
- || (mComputeCompiledVariablesForDifferentialModel == nullptr)) {
- if (cellmlFileType == libcellml::AnalyserModel::Type::ODE) {
- addError("The functions needed to compute the ODE model could not be retrieved.");
- } else {
- addError("The functions needed to compute the DAE model could not be retrieved.");
- }
- }
+ if ((mInitialiseVariablesForDifferentialModel == nullptr)
+ || (mComputeComputedConstants == nullptr)
+ || (mComputeRates == nullptr)
+ || (mComputeVariablesForDifferentialModel == nullptr)) {
+ addError(std::string("The functions needed to compute the ").append((cellmlFileType == libcellml::AnalyserModel::Type::ODE) ? "ODE" : "DAE").append(" model could not be retrieved."));
+ }
# endif
- } else {
- mInitialiseCompiledVariablesForAlgebraicModel = reinterpret_cast(mCompiler->function("initialiseVariables"));
- mComputeCompiledComputedConstants = reinterpret_cast(mCompiler->function("computeComputedConstants"));
- mComputeCompiledVariablesForAlgebraicModel = reinterpret_cast(mCompiler->function("computeVariables"));
+ } else {
+ mInitialiseVariablesForAlgebraicModel = reinterpret_cast(mCompiler->function("initialiseVariables"));
+ mComputeComputedConstants = reinterpret_cast(mCompiler->function("computeComputedConstants"));
+ mComputeVariablesForAlgebraicModel = reinterpret_cast(mCompiler->function("computeVariables"));
# ifndef CODE_COVERAGE_ENABLED
- if ((mInitialiseCompiledVariablesForAlgebraicModel == nullptr)
- || (mComputeCompiledComputedConstants == nullptr)
- || (mComputeCompiledVariablesForAlgebraicModel == nullptr)) {
- if (cellmlFileType == libcellml::AnalyserModel::Type::ALGEBRAIC) {
- addError("The functions needed to compute the algebraic model could not be retrieved.");
- } else {
- addError("The functions needed to compute the NLA model could not be retrieved.");
- }
- }
-# endif
+ if ((mInitialiseVariablesForAlgebraicModel == nullptr)
+ || (mComputeComputedConstants == nullptr)
+ || (mComputeVariablesForAlgebraicModel == nullptr)) {
+ addError(std::string("The functions needed to compute the ").append((cellmlFileType == libcellml::AnalyserModel::Type::ALGEBRAIC) ? "algebraic" : "NLA").append(" model could not be retrieved."));
}
- } else {
-#endif
- auto interpreter = libcellml::Interpreter::create();
-
- interpreter->setModel(pCellmlFile->analyserModel());
-
- mInitialiseInterpretedVariablesForAlgebraicModel = InitialiseInterpretedVariablesForAlgebraicModel([interpreter](double *pConstants, double *pComputedConstants, double *pAlgebraic) {
- interpreter->initialiseVariables(pConstants, pComputedConstants, pAlgebraic);
- });
- mInitialiseInterpretedVariablesForDifferentialModel = InitialiseInterpretedVariablesForDifferentialModel([interpreter](double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) {
- interpreter->initialiseVariables(pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
- });
- mComputeInterpretedComputedConstants = ComputeInterpretedComputedConstants([interpreter](double *pConstants, double *pComputedConstants) {
- interpreter->computeComputedConstants(pConstants, pComputedConstants);
- });
- mComputeInterpretedRates = ComputeInterpretedRates([interpreter](double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) {
- interpreter->computeRates(pVoi, pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
- });
- mComputeInterpretedVariablesForAlgebraicModel = ComputeInterpretedVariablesForAlgebraicModel([interpreter](double *pConstants, double *pComputedConstants, double *pAlgebraic) {
- interpreter->computeVariables(pConstants, pComputedConstants, pAlgebraic);
- });
- mComputeInterpretedVariablesForDifferentialModel = ComputeInterpretedVariablesForDifferentialModel([interpreter](double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) {
- interpreter->computeVariables(pVoi, pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
- });
-#ifndef __EMSCRIPTEN__
+# endif
}
#endif
}
}
-CellmlFileRuntime::Impl::~Impl()
-{
- delete[] mNlaSolverAddress;
-}
+#ifdef __EMSCRIPTEN__
+EM_JS(void, jsInitialiseVariablesForAlgebraicModel, (double *pConstants, double *pComputedConstants, double *pAlgebraic), {
+ Module.initialiseVariables(pConstants, pComputedConstants, pAlgebraic);
+});
-CellmlFileRuntime::InitialiseCompiledVariablesForAlgebraicModel CellmlFileRuntime::Impl::initialiseCompiledVariablesForAlgebraicModel() const
+void CellmlFileRuntime::Impl::initialiseVariablesForAlgebraicModel(double *pConstants, double *pComputedConstants, double *pAlgebraic) const
{
- return mInitialiseCompiledVariablesForAlgebraicModel;
+ jsInitialiseVariablesForAlgebraicModel(pConstants, pComputedConstants, pAlgebraic);
}
-CellmlFileRuntime::InitialiseCompiledVariablesForDifferentialModel CellmlFileRuntime::Impl::initialiseCompiledVariablesForDifferentialModel() const
+EM_JS(void, jsInitialiseVariablesForDifferentialModel, (double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic), {
+ Module.initialiseVariables(pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
+});
+
+void CellmlFileRuntime::Impl::initialiseVariablesForDifferentialModel(double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) const
{
- return mInitialiseCompiledVariablesForDifferentialModel;
+ jsInitialiseVariablesForDifferentialModel(pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
}
-CellmlFileRuntime::ComputeCompiledComputedConstants CellmlFileRuntime::Impl::computeCompiledComputedConstants() const
+EM_JS(void, jsComputeComputedConstants, (double *pConstants, double *pComputedConstants), {
+ Module.computeComputedConstants(pConstants, pComputedConstants);
+});
+
+void CellmlFileRuntime::Impl::computeComputedConstants(double *pConstants, double *pComputedConstants) const
{
- return mComputeCompiledComputedConstants;
+ jsComputeComputedConstants(pConstants, pComputedConstants);
}
-CellmlFileRuntime::ComputeCompiledRates CellmlFileRuntime::Impl::computeCompiledRates() const
+EM_JS(void, jsComputeRates, (double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic), {
+ Module.computeRates(pVoi, pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
+});
+
+void CellmlFileRuntime::Impl::computeRates(double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) const
{
- return mComputeCompiledRates;
+ jsComputeRates(pVoi, pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
}
-CellmlFileRuntime::ComputeCompiledVariablesForAlgebraicModel CellmlFileRuntime::Impl::computeCompiledVariablesForAlgebraicModel() const
+EM_JS(void, jsComputeVariablesForAlgebraicModel, (double *pConstants, double *pComputedConstants, double *pAlgebraic), {
+ Module.computeVariables(pConstants, pComputedConstants, pAlgebraic);
+});
+
+void CellmlFileRuntime::Impl::computeVariablesForAlgebraicModel(double *pConstants, double *pComputedConstants, double *pAlgebraic) const
{
- return mComputeCompiledVariablesForAlgebraicModel;
+ jsComputeVariablesForAlgebraicModel(pConstants, pComputedConstants, pAlgebraic);
}
-CellmlFileRuntime::ComputeCompiledVariablesForDifferentialModel CellmlFileRuntime::Impl::computeCompiledVariablesForDifferentialModel() const
+EM_JS(void, jsComputeVariablesForDifferentialModel, (double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic), {
+ Module.computeVariables(pVoi, pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
+});
+
+void CellmlFileRuntime::Impl::computeVariablesForDifferentialModel(double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) const
{
- return mComputeCompiledVariablesForDifferentialModel;
+ jsComputeVariablesForDifferentialModel(pVoi, pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
}
-
-CellmlFileRuntime::InitialiseInterpretedVariablesForAlgebraicModel CellmlFileRuntime::Impl::initialiseInterpretedVariablesForAlgebraicModel() const
+#else
+CellmlFileRuntime::InitialiseVariablesForAlgebraicModel CellmlFileRuntime::Impl::initialiseVariablesForAlgebraicModel() const
{
- return mInitialiseInterpretedVariablesForAlgebraicModel;
+ return mInitialiseVariablesForAlgebraicModel;
}
-CellmlFileRuntime::InitialiseInterpretedVariablesForDifferentialModel CellmlFileRuntime::Impl::initialiseInterpretedVariablesForDifferentialModel() const
+CellmlFileRuntime::InitialiseVariablesForDifferentialModel CellmlFileRuntime::Impl::initialiseVariablesForDifferentialModel() const
{
- return mInitialiseInterpretedVariablesForDifferentialModel;
+ return mInitialiseVariablesForDifferentialModel;
}
-CellmlFileRuntime::ComputeInterpretedComputedConstants CellmlFileRuntime::Impl::computeInterpretedComputedConstants() const
+CellmlFileRuntime::ComputeComputedConstants CellmlFileRuntime::Impl::computeComputedConstants() const
{
- return mComputeInterpretedComputedConstants;
+ return mComputeComputedConstants;
}
-CellmlFileRuntime::ComputeInterpretedRates CellmlFileRuntime::Impl::computeInterpretedRates() const
+CellmlFileRuntime::ComputeRates CellmlFileRuntime::Impl::computeRates() const
{
- return mComputeInterpretedRates;
+ return mComputeRates;
}
-CellmlFileRuntime::ComputeInterpretedVariablesForAlgebraicModel CellmlFileRuntime::Impl::computeInterpretedVariablesForAlgebraicModel() const
+CellmlFileRuntime::ComputeVariablesForAlgebraicModel CellmlFileRuntime::Impl::computeVariablesForAlgebraicModel() const
{
- return mComputeInterpretedVariablesForAlgebraicModel;
+ return mComputeVariablesForAlgebraicModel;
}
-CellmlFileRuntime::ComputeInterpretedVariablesForDifferentialModel CellmlFileRuntime::Impl::computeInterpretedVariablesForDifferentialModel() const
+CellmlFileRuntime::ComputeVariablesForDifferentialModel CellmlFileRuntime::Impl::computeVariablesForDifferentialModel() const
{
- return mComputeInterpretedVariablesForDifferentialModel;
+ return mComputeVariablesForDifferentialModel;
}
+#endif
-CellmlFileRuntime::CellmlFileRuntime(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver, bool pCompiled)
- : Logger(new Impl {pCellmlFile, pNlaSolver, pCompiled})
+CellmlFileRuntime::CellmlFileRuntime(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver)
+ : Logger(new Impl {pCellmlFile, pNlaSolver})
{
}
@@ -269,70 +522,71 @@ const CellmlFileRuntime::Impl *CellmlFileRuntime::pimpl() const
return static_cast(Logger::mPimpl);
}
-CellmlFileRuntimePtr CellmlFileRuntime::create(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver,
- bool pCompiled)
+CellmlFileRuntimePtr CellmlFileRuntime::create(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver)
{
- return CellmlFileRuntimePtr {new CellmlFileRuntime {pCellmlFile, pNlaSolver, pCompiled}};
+ return CellmlFileRuntimePtr {new CellmlFileRuntime {pCellmlFile, pNlaSolver}};
}
-CellmlFileRuntime::InitialiseCompiledVariablesForAlgebraicModel CellmlFileRuntime::initialiseCompiledVariablesForAlgebraicModel() const
+#ifdef __EMSCRIPTEN__
+void CellmlFileRuntime::initialiseVariablesForAlgebraicModel(double *pConstants, double *pComputedConstants, double *pAlgebraic) const
{
- return pimpl()->initialiseCompiledVariablesForAlgebraicModel();
+ pimpl()->initialiseVariablesForAlgebraicModel(pConstants, pComputedConstants, pAlgebraic);
}
-CellmlFileRuntime::InitialiseCompiledVariablesForDifferentialModel CellmlFileRuntime::initialiseCompiledVariablesForDifferentialModel() const
+void CellmlFileRuntime::initialiseVariablesForDifferentialModel(double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) const
{
- return pimpl()->initialiseCompiledVariablesForDifferentialModel();
+ pimpl()->initialiseVariablesForDifferentialModel(pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
}
-CellmlFileRuntime::ComputeCompiledComputedConstants CellmlFileRuntime::computeCompiledComputedConstants() const
+void CellmlFileRuntime::computeComputedConstants(double *pConstants, double *pComputedConstants) const
{
- return pimpl()->computeCompiledComputedConstants();
+ pimpl()->computeComputedConstants(pConstants, pComputedConstants);
}
-CellmlFileRuntime::ComputeCompiledRates CellmlFileRuntime::computeCompiledRates() const
+void CellmlFileRuntime::computeRates(double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) const
{
- return pimpl()->computeCompiledRates();
+ pimpl()->computeRates(pVoi, pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
}
-CellmlFileRuntime::ComputeCompiledVariablesForAlgebraicModel CellmlFileRuntime::computeCompiledVariablesForAlgebraicModel() const
+void CellmlFileRuntime::computeVariablesForAlgebraicModel(double *pConstants, double *pComputedConstants, double *pAlgebraic) const
{
- return pimpl()->computeCompiledVariablesForAlgebraicModel();
+ pimpl()->computeVariablesForAlgebraicModel(pConstants, pComputedConstants, pAlgebraic);
}
-CellmlFileRuntime::ComputeCompiledVariablesForDifferentialModel CellmlFileRuntime::computeCompiledVariablesForDifferentialModel() const
+void CellmlFileRuntime::computeVariablesForDifferentialModel(double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) const
{
- return pimpl()->computeCompiledVariablesForDifferentialModel();
+ pimpl()->computeVariablesForDifferentialModel(pVoi, pStates, pRates, pConstants, pComputedConstants, pAlgebraic);
}
-
-CellmlFileRuntime::InitialiseInterpretedVariablesForAlgebraicModel CellmlFileRuntime::initialiseInterpretedVariablesForAlgebraicModel() const
+#else
+CellmlFileRuntime::InitialiseVariablesForAlgebraicModel CellmlFileRuntime::initialiseVariablesForAlgebraicModel() const
{
- return pimpl()->initialiseInterpretedVariablesForAlgebraicModel();
+ return pimpl()->initialiseVariablesForAlgebraicModel();
}
-CellmlFileRuntime::InitialiseInterpretedVariablesForDifferentialModel CellmlFileRuntime::initialiseInterpretedVariablesForDifferentialModel() const
+CellmlFileRuntime::InitialiseVariablesForDifferentialModel CellmlFileRuntime::initialiseVariablesForDifferentialModel() const
{
- return pimpl()->initialiseInterpretedVariablesForDifferentialModel();
+ return pimpl()->initialiseVariablesForDifferentialModel();
}
-CellmlFileRuntime::ComputeInterpretedComputedConstants CellmlFileRuntime::computeInterpretedComputedConstants() const
+CellmlFileRuntime::ComputeComputedConstants CellmlFileRuntime::computeComputedConstants() const
{
- return pimpl()->computeInterpretedComputedConstants();
+ return pimpl()->computeComputedConstants();
}
-CellmlFileRuntime::ComputeInterpretedRates CellmlFileRuntime::computeInterpretedRates() const
+CellmlFileRuntime::ComputeRates CellmlFileRuntime::computeRates() const
{
- return pimpl()->computeInterpretedRates();
+ return pimpl()->computeRates();
}
-CellmlFileRuntime::ComputeInterpretedVariablesForAlgebraicModel CellmlFileRuntime::computeInterpretedVariablesForAlgebraicModel() const
+CellmlFileRuntime::ComputeVariablesForAlgebraicModel CellmlFileRuntime::computeVariablesForAlgebraicModel() const
{
- return pimpl()->computeInterpretedVariablesForAlgebraicModel();
+ return pimpl()->computeVariablesForAlgebraicModel();
}
-CellmlFileRuntime::ComputeInterpretedVariablesForDifferentialModel CellmlFileRuntime::computeInterpretedVariablesForDifferentialModel() const
+CellmlFileRuntime::ComputeVariablesForDifferentialModel CellmlFileRuntime::computeVariablesForDifferentialModel() const
{
- return pimpl()->computeInterpretedVariablesForDifferentialModel();
+ return pimpl()->computeVariablesForDifferentialModel();
}
+#endif
} // namespace libOpenCOR
diff --git a/src/support/cellml/cellmlfileruntime.h b/src/support/cellml/cellmlfileruntime.h
index 954897c47..f8372e52f 100644
--- a/src/support/cellml/cellmlfileruntime.h
+++ b/src/support/cellml/cellmlfileruntime.h
@@ -31,19 +31,14 @@ using CellmlFileRuntimePtr = std::shared_ptr;
class CellmlFileRuntime: public Logger
{
public:
- using InitialiseCompiledVariablesForAlgebraicModel = void (*)(double *pConstants, double *pComputedConstants, double *pAlgebraic);
- using InitialiseCompiledVariablesForDifferentialModel = void (*)(double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic);
- using ComputeCompiledComputedConstants = void (*)(double *pConstants, double *pComputedConstants);
- using ComputeCompiledRates = void (*)(double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic);
- using ComputeCompiledVariablesForAlgebraicModel = void (*)(double *pConstants, double *pComputedConstants, double *pAlgebraic);
- using ComputeCompiledVariablesForDifferentialModel = void (*)(double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic);
-
- using InitialiseInterpretedVariablesForAlgebraicModel = std::function;
- using InitialiseInterpretedVariablesForDifferentialModel = std::function;
- using ComputeInterpretedComputedConstants = std::function;
- using ComputeInterpretedRates = std::function;
- using ComputeInterpretedVariablesForAlgebraicModel = std::function;
- using ComputeInterpretedVariablesForDifferentialModel = std::function;
+#ifndef __EMSCRIPTEN__
+ using InitialiseVariablesForAlgebraicModel = void (*)(double *pConstants, double *pComputedConstants, double *pAlgebraic);
+ using InitialiseVariablesForDifferentialModel = void (*)(double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic);
+ using ComputeComputedConstants = void (*)(double *pConstants, double *pComputedConstants);
+ using ComputeRates = void (*)(double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic);
+ using ComputeVariablesForAlgebraicModel = void (*)(double *pConstants, double *pComputedConstants, double *pAlgebraic);
+ using ComputeVariablesForDifferentialModel = void (*)(double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic);
+#endif
CellmlFileRuntime() = delete;
~CellmlFileRuntime() override;
@@ -54,27 +49,28 @@ class CellmlFileRuntime: public Logger
CellmlFileRuntime &operator=(const CellmlFileRuntime &pRhs) = delete;
CellmlFileRuntime &operator=(CellmlFileRuntime &&pRhs) noexcept = delete;
- static CellmlFileRuntimePtr create(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver,
- bool pCompiled);
-
- InitialiseCompiledVariablesForAlgebraicModel initialiseCompiledVariablesForAlgebraicModel() const;
- InitialiseCompiledVariablesForDifferentialModel initialiseCompiledVariablesForDifferentialModel() const;
- ComputeCompiledComputedConstants computeCompiledComputedConstants() const;
- ComputeCompiledRates computeCompiledRates() const;
- ComputeCompiledVariablesForAlgebraicModel computeCompiledVariablesForAlgebraicModel() const;
- ComputeCompiledVariablesForDifferentialModel computeCompiledVariablesForDifferentialModel() const;
-
- InitialiseInterpretedVariablesForAlgebraicModel initialiseInterpretedVariablesForAlgebraicModel() const;
- InitialiseInterpretedVariablesForDifferentialModel initialiseInterpretedVariablesForDifferentialModel() const;
- ComputeInterpretedComputedConstants computeInterpretedComputedConstants() const;
- ComputeInterpretedRates computeInterpretedRates() const;
- ComputeInterpretedVariablesForAlgebraicModel computeInterpretedVariablesForAlgebraicModel() const;
- ComputeInterpretedVariablesForDifferentialModel computeInterpretedVariablesForDifferentialModel() const;
+ static CellmlFileRuntimePtr create(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver);
+
+#ifdef __EMSCRIPTEN__
+ void initialiseVariablesForAlgebraicModel(double *pConstants, double *pComputedConstants, double *pAlgebraic) const;
+ void initialiseVariablesForDifferentialModel(double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) const;
+ void computeComputedConstants(double *pConstants, double *pComputedConstants) const;
+ void computeRates(double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) const;
+ void computeVariablesForAlgebraicModel(double *pConstants, double *pComputedConstants, double *pAlgebraic) const;
+ void computeVariablesForDifferentialModel(double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) const;
+#else
+ InitialiseVariablesForAlgebraicModel initialiseVariablesForAlgebraicModel() const;
+ InitialiseVariablesForDifferentialModel initialiseVariablesForDifferentialModel() const;
+ ComputeComputedConstants computeComputedConstants() const;
+ ComputeRates computeRates() const;
+ ComputeVariablesForAlgebraicModel computeVariablesForAlgebraicModel() const;
+ ComputeVariablesForDifferentialModel computeVariablesForDifferentialModel() const;
+#endif
private:
class Impl;
- explicit CellmlFileRuntime(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver, bool pCompiled);
+ explicit CellmlFileRuntime(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver);
Impl *pimpl();
const Impl *pimpl() const;
diff --git a/src/support/cellml/cellmlfileruntime_p.h b/src/support/cellml/cellmlfileruntime_p.h
index bc69869b6..7cda231c3 100644
--- a/src/support/cellml/cellmlfileruntime_p.h
+++ b/src/support/cellml/cellmlfileruntime_p.h
@@ -26,42 +26,38 @@ namespace libOpenCOR {
class CellmlFileRuntime::Impl: public Logger::Impl
{
public:
-#ifndef __EMSCRIPTEN__
CompilerPtr mCompiler = nullptr;
+ std::string mNlaSolverAddress;
+#ifdef __EMSCRIPTEN__
+ UnsignedChars mWasmModule;
#endif
- char *mNlaSolverAddress = nullptr;
-
- InitialiseCompiledVariablesForAlgebraicModel mInitialiseCompiledVariablesForAlgebraicModel = nullptr;
- InitialiseCompiledVariablesForDifferentialModel mInitialiseCompiledVariablesForDifferentialModel = nullptr;
- ComputeCompiledComputedConstants mComputeCompiledComputedConstants = nullptr;
- ComputeCompiledRates mComputeCompiledRates = nullptr;
- ComputeCompiledVariablesForAlgebraicModel mComputeCompiledVariablesForAlgebraicModel = nullptr;
- ComputeCompiledVariablesForDifferentialModel mComputeCompiledVariablesForDifferentialModel = nullptr;
-
- InitialiseInterpretedVariablesForAlgebraicModel mInitialiseInterpretedVariablesForAlgebraicModel = nullptr;
- InitialiseInterpretedVariablesForDifferentialModel mInitialiseInterpretedVariablesForDifferentialModel = nullptr;
- ComputeInterpretedComputedConstants mComputeInterpretedComputedConstants = nullptr;
- ComputeInterpretedRates mComputeInterpretedRates = nullptr;
- ComputeInterpretedVariablesForAlgebraicModel mComputeInterpretedVariablesForAlgebraicModel = nullptr;
- ComputeInterpretedVariablesForDifferentialModel mComputeInterpretedVariablesForDifferentialModel = nullptr;
-
- explicit Impl(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver, bool pCompiled);
- ~Impl() override;
-
- CellmlFileRuntime::InitialiseCompiledVariablesForAlgebraicModel initialiseCompiledVariablesForAlgebraicModel() const;
- CellmlFileRuntime::InitialiseCompiledVariablesForDifferentialModel initialiseCompiledVariablesForDifferentialModel() const;
- CellmlFileRuntime::ComputeCompiledComputedConstants computeCompiledComputedConstants() const;
- CellmlFileRuntime::ComputeCompiledRates computeCompiledRates() const;
- CellmlFileRuntime::ComputeCompiledVariablesForAlgebraicModel computeCompiledVariablesForAlgebraicModel() const;
- CellmlFileRuntime::ComputeCompiledVariablesForDifferentialModel computeCompiledVariablesForDifferentialModel() const;
+#ifndef __EMSCRIPTEN__
+ InitialiseVariablesForAlgebraicModel mInitialiseVariablesForAlgebraicModel = nullptr;
+ InitialiseVariablesForDifferentialModel mInitialiseVariablesForDifferentialModel = nullptr;
+ ComputeComputedConstants mComputeComputedConstants = nullptr;
+ ComputeRates mComputeRates = nullptr;
+ ComputeVariablesForAlgebraicModel mComputeVariablesForAlgebraicModel = nullptr;
+ ComputeVariablesForDifferentialModel mComputeVariablesForDifferentialModel = nullptr;
+#endif
- CellmlFileRuntime::InitialiseInterpretedVariablesForAlgebraicModel initialiseInterpretedVariablesForAlgebraicModel() const;
- CellmlFileRuntime::InitialiseInterpretedVariablesForDifferentialModel initialiseInterpretedVariablesForDifferentialModel() const;
- CellmlFileRuntime::ComputeInterpretedComputedConstants computeInterpretedComputedConstants() const;
- CellmlFileRuntime::ComputeInterpretedRates computeInterpretedRates() const;
- CellmlFileRuntime::ComputeInterpretedVariablesForAlgebraicModel computeInterpretedVariablesForAlgebraicModel() const;
- CellmlFileRuntime::ComputeInterpretedVariablesForDifferentialModel computeInterpretedVariablesForDifferentialModel() const;
+ explicit Impl(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver);
+
+#ifdef __EMSCRIPTEN__
+ void initialiseVariablesForAlgebraicModel(double *pConstants, double *pComputedConstants, double *pAlgebraic) const;
+ void initialiseVariablesForDifferentialModel(double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) const;
+ void computeComputedConstants(double *pConstants, double *pComputedConstants) const;
+ void computeRates(double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) const;
+ void computeVariablesForAlgebraicModel(double *pConstants, double *pComputedConstants, double *pAlgebraic) const;
+ void computeVariablesForDifferentialModel(double pVoi, double *pStates, double *pRates, double *pConstants, double *pComputedConstants, double *pAlgebraic) const;
+#else
+ CellmlFileRuntime::InitialiseVariablesForAlgebraicModel initialiseVariablesForAlgebraicModel() const;
+ CellmlFileRuntime::InitialiseVariablesForDifferentialModel initialiseVariablesForDifferentialModel() const;
+ CellmlFileRuntime::ComputeComputedConstants computeComputedConstants() const;
+ CellmlFileRuntime::ComputeRates computeRates() const;
+ CellmlFileRuntime::ComputeVariablesForAlgebraicModel computeVariablesForAlgebraicModel() const;
+ CellmlFileRuntime::ComputeVariablesForDifferentialModel computeVariablesForDifferentialModel() const;
+#endif
};
} // namespace libOpenCOR
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 8eac5a613..dd9226ba5 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -123,6 +123,7 @@ string(REPLACE "\"" "\\\"" SOLVER_NLA2_CONTENTS "${SOLVER_NLA2_CONTENTS}")
file(READ res/api/sed/algebraic.cellml ALGEBRAIC_CONTENTS)
file(READ res/api/sed/dae.cellml DAE_CONTENTS)
+file(READ res/api/sed/math.cellml MATH_CONTENTS)
file(READ res/api/sed/nla.cellml NLA_CONTENTS)
file(READ res/api/sed/overconstrained.cellml OVERCONSTRAINED_CONTENTS)
file(READ res/api/sed/underconstrained.cellml UNDERCONSTRAINED_CONTENTS)
@@ -130,6 +131,7 @@ file(READ res/api/sed/unsuitably_constrained.cellml UNSUITABLY_CONSTRAINED_CONTE
string(REPLACE "\"" "\\\"" ALGEBRAIC_CONTENTS "${ALGEBRAIC_CONTENTS}")
string(REPLACE "\"" "\\\"" DAE_CONTENTS "${DAE_CONTENTS}")
+string(REPLACE "\"" "\\\"" MATH_CONTENTS "${MATH_CONTENTS}")
string(REPLACE "\"" "\\\"" NLA_CONTENTS "${NLA_CONTENTS}")
string(REPLACE "\"" "\\\"" OVERCONSTRAINED_CONTENTS "${OVERCONSTRAINED_CONTENTS}")
string(REPLACE "\"" "\\\"" UNDERCONSTRAINED_CONTENTS "${UNDERCONSTRAINED_CONTENTS}")
diff --git a/tests/api/sed/coveragetests.cpp b/tests/api/sed/coveragetests.cpp
index 408aab0df..39f829c17 100644
--- a/tests/api/sed/coveragetests.cpp
+++ b/tests/api/sed/coveragetests.cpp
@@ -20,6 +20,8 @@ limitations under the License.
#include
+static const auto NoDoubles = std::vector {};
+
TEST(CoverageSedTest, initialise)
{
static const std::string expectedSerialisation = R"(
@@ -409,8 +411,6 @@ TEST(CoverageSedTest, sedUniformTimeCourse)
EXPECT_EQ(simulation->numberOfSteps(), NUMBER_OF_STEPS);
}
-static const auto NoDoubles = std::vector {};
-
TEST(CoverageSedTest, sedInstanceAndSedInstanceTaskDifferentialModel)
{
static const libOpenCOR::ExpectedIssues EXPECTED_ISSUES = {
@@ -556,3 +556,33 @@ TEST(CoverageSedTest, solver)
EXPECT_FALSE(instance->hasIssues());
}
+
+TEST(CoverageSedTest, math)
+{
+ auto file = libOpenCOR::File::create(libOpenCOR::resourcePath("api/sed/math.cellml"));
+ auto document = libOpenCOR::SedDocument::create(file);
+ auto instance = document->instantiate();
+ auto instanceTask = instance->tasks()[0];
+
+ EXPECT_EQ(instanceTask->constantCount(), 0);
+ EXPECT_EQ(instanceTask->computedConstantCount(), 37);
+ EXPECT_EQ(instanceTask->algebraicCount(), 0);
+
+ instance->run();
+
+ static const auto COMPUTED_CONSTANT_VALUES = std::vector({243.0, 3.0, 7.0, 20.085536923187668, 1.0986122886681098, 0.47712125471966244, 4.0, 3.0, 3.0, 5.0,
+ 3.0, 0.14112000805986721, -0.98999249660044542, -0.1425465430742778, -1.0101086659079939,
+ 7.0861673957371867, -7.0152525514345339, 10.017874927409903, 10.067661995777765,
+ 0.99505475368673046, 0.099327927419433207, 0.099821569668822732, 1.0049698233136892,
+ 0.30469265401539747, 1.266103672779499, 1.2490457723982544, 1.2309594173407747,
+ 0.33983690945412193, 0.32175055439664219, 1.8184464592320668, 1.7627471740390861,
+ 0.30951960420311175, 1.8738202425274144, 0.32745015023725843, 0.34657359027997264,
+ std::numeric_limits::infinity(), std::numeric_limits::quiet_NaN()});
+ static const auto COMPUTED_CONSTANT_ABS_TOLS = std::vector({0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001,
+ 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001,
+ 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001,
+ 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001,
+ 0.0000001, 0.0000001, 0.0000001, 0.0000001, 0.0000001});
+
+ EXPECT_EQ_VALUES(instanceTask, 0, {}, {}, {}, {}, {}, {}, COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS, {}, {});
+}
diff --git a/tests/api/sed/instancetests.cpp b/tests/api/sed/instancetests.cpp
index d37842d10..f08f1c537 100644
--- a/tests/api/sed/instancetests.cpp
+++ b/tests/api/sed/instancetests.cpp
@@ -87,49 +87,28 @@ TEST(InstanceSedTest, unsuitablyConstrainedCellmlFile)
EXPECT_EQ_ISSUES(instance, EXPECTED_ISSUES);
}
-namespace {
-
-void runAlgebraicModel(bool pCompiled)
+TEST(InstanceSedTest, algebraicModel)
{
auto file = libOpenCOR::File::create(libOpenCOR::resourcePath("api/sed/algebraic.cellml"));
auto document = libOpenCOR::SedDocument::create(file);
- auto instance = document->instantiate(pCompiled);
+ auto instance = document->instantiate();
instance->run();
EXPECT_FALSE(instance->hasIssues());
}
-} // namespace
-
-TEST(InstanceSedTest, compiledAlgebraicModel)
-{
- runAlgebraicModel(true);
-}
-
-TEST(InstanceSedTest, interpretedAlgebraicModel)
-{
- runAlgebraicModel(false);
-}
-
-namespace {
-
-void runOdeModel(bool pCompiled)
+TEST(InstanceSedTest, odeModel)
{
const libOpenCOR::ExpectedIssues EXPECTED_ISSUES = {
#ifdef BUILDING_ON_INTEL
{libOpenCOR::Issue::Type::ERROR, "At t = 0.00140013827899996, mxstep steps taken before reaching tout."},
#else
- {
- libOpenCOR::Issue::Type::ERROR,
+ {libOpenCOR::Issue::Type::ERROR,
# ifdef BUILDING_ON_WINDOWS
- pCompiled ?
- "At t = 0.00140013827899821, mxstep steps taken before reaching tout." :
- "At t = 0.00140013827899996, mxstep steps taken before reaching tout.",
+ "At t = 0.00140013827899821, mxstep steps taken before reaching tout."
# else
- pCompiled ?
- "At t = 0.00140013827899707, mxstep steps taken before reaching tout." :
- "At t = 0.00140013827900052, mxstep steps taken before reaching tout.",
+ "At t = 0.00140013827899707, mxstep steps taken before reaching tout."
# endif
},
#endif
@@ -145,7 +124,7 @@ void runOdeModel(bool pCompiled)
cvode->setMaximumNumberOfSteps(NOK_MAXIMUM_NUMBER_OF_STEPS);
- auto instance = document->instantiate(pCompiled);
+ auto instance = document->instantiate();
EXPECT_FALSE(instance->hasIssues());
@@ -157,25 +136,13 @@ void runOdeModel(bool pCompiled)
cvode->setMaximumNumberOfSteps(OK_MAXIMUM_NUMBER_OF_STEPS);
- instance = document->instantiate(pCompiled);
+ instance = document->instantiate();
instance->run();
EXPECT_FALSE(instance->hasIssues());
}
-} // namespace
-
-TEST(InstanceSedTest, compiledOdeModel)
-{
- runOdeModel(true);
-}
-
-TEST(InstanceSedTest, interpretedOdeModel)
-{
- runOdeModel(false);
-}
-
TEST(InstanceSedTest, odeModelWithNoOdeSolver)
{
static const libOpenCOR::ExpectedIssues EXPECTED_ISSUES = {
@@ -194,8 +161,6 @@ TEST(InstanceSedTest, odeModelWithNoOdeSolver)
TEST(InstanceSedTest, nlaModel)
{
- //---GRY--- AS FOR THE ALGEBRAIC AND ODE MODELS, WE WILL NEED TO ADD AN INTERPRETED VERSION OF THIS TEST.
-
static const libOpenCOR::ExpectedIssues EXPECTED_ISSUES = {
{libOpenCOR::Issue::Type::ERROR, "The upper half-bandwidth cannot be equal to -1. It must be between 0 and 0."},
};
@@ -237,8 +202,6 @@ TEST(InstanceSedTest, nlaModelWithNoNlaSolver)
TEST(InstanceSedTest, daeModel)
{
- //---GRY--- AS FOR THE ALGEBRAIC AND ODE MODELS, WE WILL NEED TO ADD AN INTERPRETED VERSION OF THIS TEST.
-
static const libOpenCOR::ExpectedIssues EXPECTED_ISSUES = {
{libOpenCOR::Issue::Type::ERROR, "The upper half-bandwidth cannot be equal to -1. It must be between 0 and 0."},
};
diff --git a/tests/api/solver/cvodetests.cpp b/tests/api/solver/cvodetests.cpp
index a21150875..0e75258b0 100644
--- a/tests/api/solver/cvodetests.cpp
+++ b/tests/api/solver/cvodetests.cpp
@@ -172,30 +172,7 @@ TEST(CvodeSolverTest, absoluteToleranceValueWithInvalidNumber)
EXPECT_EQ_ISSUES(instance, EXPECTED_ISSUES);
}
-namespace {
-
-void cvodeSolve(const libOpenCOR::Doubles &pStateValues, const libOpenCOR::Doubles &pStateAbsTols,
- const libOpenCOR::Doubles &pRateValues, const libOpenCOR::Doubles &pRateAbsTols,
- const libOpenCOR::Doubles &pConstantValues, const libOpenCOR::Doubles &pConstantAbsTols,
- const libOpenCOR::Doubles &pComputedConstantValues, const libOpenCOR::Doubles &pComputedConstantAbsTols,
- const libOpenCOR::Doubles &pAlgebraicValues, const libOpenCOR::Doubles &pAlgebraicAbsTols,
- bool pCompiled)
-{
- auto file = libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"));
- auto document = libOpenCOR::SedDocument::create(file);
-
- OdeModel::run(document,
- pStateValues, pStateAbsTols,
- pRateValues, pRateAbsTols,
- pConstantValues, pConstantAbsTols,
- pComputedConstantValues, pComputedConstantAbsTols,
- pAlgebraicValues, pAlgebraicAbsTols,
- pCompiled);
-}
-
-} // namespace
-
-TEST(CvodeSolverTest, compiledSolve)
+TEST(CvodeSolverTest, solve)
{
static const auto STATE_VALUES = std::vector({-63.886, 0.135007, 0.984333, 0.740973});
static const auto STATE_ABS_TOLS = std::vector({0.001, 0.000001, 0.000001, 0.000001});
@@ -208,33 +185,15 @@ TEST(CvodeSolverTest, compiledSolve)
static const auto ALGEBRAIC_VALUES = std::vector({0.0, -15.9819, -823.517, 789.779, 3.9699, 0.11499, 0.00287, 0.96735, 0.54133, 0.056246});
static const auto ALGEBRAIC_ABS_TOLS = std::vector({0.0, 0.0001, 0.001, 0.001, 0.0001, 0.00001, 0.00001, 0.00001, 0.00001, 0.000001});
- cvodeSolve(STATE_VALUES, STATE_ABS_TOLS,
- RATE_VALUES, RATE_ABS_TOLS,
- CONSTANT_VALUES, CONSTANT_ABS_TOLS,
- COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
-}
+ auto file = libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"));
+ auto document = libOpenCOR::SedDocument::create(file);
-TEST(CvodeSolverTest, interpretedSolve)
-{
- static const auto STATE_VALUES = std::vector({-63.886, 0.135008, 0.984333, 0.740972});
- static const auto STATE_ABS_TOLS = std::vector({0.001, 0.000001, 0.000001, 0.000001});
- static const auto RATE_VALUES = std::vector({49.725, -0.128193, -0.05090, 0.09865});
- static const auto RATE_ABS_TOLS = std::vector({0.001, 0.000001, 0.00001, 0.00001});
- static const auto CONSTANT_VALUES = std::vector({1.0, 0.0, 0.3, 120.0, 36.0});
- static const auto CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0, 0.0, 0.0});
- static const auto COMPUTED_CONSTANT_VALUES = std::vector({-10.613, -115.0, 12.0});
- static const auto COMPUTED_CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0});
- static const auto ALGEBRAIC_VALUES = std::vector({0.0, -15.9819, -823.517, 789.779, 3.9699, 0.11499, 0.00287, 0.967347, 0.54133, 0.056246});
- static const auto ALGEBRAIC_ABS_TOLS = std::vector({0.0, 0.0001, 0.001, 0.001, 0.0001, 0.00001, 0.00001, 0.000001, 0.00001, 0.000001});
-
- cvodeSolve(STATE_VALUES, STATE_ABS_TOLS,
- RATE_VALUES, RATE_ABS_TOLS,
- CONSTANT_VALUES, CONSTANT_ABS_TOLS,
- COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- false);
+ OdeModel::run(document,
+ STATE_VALUES, STATE_ABS_TOLS,
+ RATE_VALUES, RATE_ABS_TOLS,
+ CONSTANT_VALUES, CONSTANT_ABS_TOLS,
+ COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
TEST(CvodeSolverTest, solveWithoutInterpolateSolution)
@@ -262,8 +221,7 @@ TEST(CvodeSolverTest, solveWithoutInterpolateSolution)
RATE_VALUES, RATE_ABS_TOLS,
CONSTANT_VALUES, CONSTANT_ABS_TOLS,
COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
TEST(CvodeSolverTest, solveWithAdamsMoultonIntegrationMethod)
@@ -291,8 +249,7 @@ TEST(CvodeSolverTest, solveWithAdamsMoultonIntegrationMethod)
RATE_VALUES, RATE_ABS_TOLS,
CONSTANT_VALUES, CONSTANT_ABS_TOLS,
COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
TEST(CvodeSolverTest, solveWithFunctionalIterationType)
@@ -320,8 +277,7 @@ TEST(CvodeSolverTest, solveWithFunctionalIterationType)
RATE_VALUES, RATE_ABS_TOLS,
CONSTANT_VALUES, CONSTANT_ABS_TOLS,
COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
TEST(CvodeSolverTest, solveWithBandedLinearSolver)
@@ -349,8 +305,7 @@ TEST(CvodeSolverTest, solveWithBandedLinearSolver)
RATE_VALUES, RATE_ABS_TOLS,
CONSTANT_VALUES, CONSTANT_ABS_TOLS,
COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
TEST(CvodeSolverTest, solveWithDiagonalLinearSolver)
@@ -378,8 +333,7 @@ TEST(CvodeSolverTest, solveWithDiagonalLinearSolver)
RATE_VALUES, RATE_ABS_TOLS,
CONSTANT_VALUES, CONSTANT_ABS_TOLS,
COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
TEST(CvodeSolverTest, solveWithGmresLinearSolver)
@@ -407,8 +361,7 @@ TEST(CvodeSolverTest, solveWithGmresLinearSolver)
RATE_VALUES, RATE_ABS_TOLS,
CONSTANT_VALUES, CONSTANT_ABS_TOLS,
COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
TEST(CvodeSolverTest, solveWithBicgstabLinearSolver)
@@ -436,8 +389,7 @@ TEST(CvodeSolverTest, solveWithBicgstabLinearSolver)
RATE_VALUES, RATE_ABS_TOLS,
CONSTANT_VALUES, CONSTANT_ABS_TOLS,
COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
TEST(CvodeSolverTest, solveWithTfqmrLinearSolver)
@@ -465,8 +417,7 @@ TEST(CvodeSolverTest, solveWithTfqmrLinearSolver)
RATE_VALUES, RATE_ABS_TOLS,
CONSTANT_VALUES, CONSTANT_ABS_TOLS,
COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
TEST(CvodeSolverTest, solveWithGmresLinearSolverAndNoPreconditioner)
@@ -495,8 +446,7 @@ TEST(CvodeSolverTest, solveWithGmresLinearSolverAndNoPreconditioner)
RATE_VALUES, RATE_ABS_TOLS,
CONSTANT_VALUES, CONSTANT_ABS_TOLS,
COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
TEST(CvodeSolverTest, solveWithBicgstabLinearSolverAndNoPreconditioner)
@@ -525,8 +475,7 @@ TEST(CvodeSolverTest, solveWithBicgstabLinearSolverAndNoPreconditioner)
RATE_VALUES, RATE_ABS_TOLS,
CONSTANT_VALUES, CONSTANT_ABS_TOLS,
COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
TEST(CvodeSolverTest, solveWithTfqmrLinearSolverAndNoPreconditioner)
@@ -555,6 +504,5 @@ TEST(CvodeSolverTest, solveWithTfqmrLinearSolverAndNoPreconditioner)
RATE_VALUES, RATE_ABS_TOLS,
CONSTANT_VALUES, CONSTANT_ABS_TOLS,
COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
diff --git a/tests/api/solver/forwardeulertests.cpp b/tests/api/solver/forwardeulertests.cpp
index 0ebe496b9..77307b7f2 100644
--- a/tests/api/solver/forwardeulertests.cpp
+++ b/tests/api/solver/forwardeulertests.cpp
@@ -37,16 +37,19 @@ TEST(ForwardEulerSolverTest, stepValueWithInvalidNumber)
EXPECT_EQ_ISSUES(instance, EXPECTED_ISSUES);
}
-namespace {
-
-void forwardEulerSolve(const libOpenCOR::Doubles &pStateValues, const libOpenCOR::Doubles &pStateAbsTols,
- const libOpenCOR::Doubles &pRateValues, const libOpenCOR::Doubles &pRateAbsTols,
- const libOpenCOR::Doubles &pConstantValues, const libOpenCOR::Doubles &pConstantAbsTols,
- const libOpenCOR::Doubles &pComputedConstantValues, const libOpenCOR::Doubles &pComputedConstantAbsTols,
- const libOpenCOR::Doubles &pAlgebraicValues, const libOpenCOR::Doubles &pAlgebraicAbsTols,
- bool pCompiled)
+TEST(ForwardEulerSolverTest, solve)
{
static const auto STEP = 0.0123;
+ static const auto STATE_VALUES = std::vector({-63.787727, 0.134748, 0.984255, 0.741178});
+ static const auto STATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
+ static const auto RATE_VALUES = std::vector({49.73577, -0.127963, -0.051257, 0.098331});
+ static const auto RATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
+ static const auto CONSTANT_VALUES = std::vector({1.0, 0.0, 0.3, 120.0, 36.0});
+ static const auto CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0, 0.0, 0.0});
+ static const auto COMPUTED_CONSTANT_VALUES = std::vector({-10.613, -115.0, 12.0});
+ static const auto COMPUTED_CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0});
+ static const auto ALGEBRAIC_VALUES = std::vector({0.0, -15.952418, -823.361177, 789.590304, 3.960664, 0.115617, 0.002884, 0.967035, 0.54037, 0.056315});
+ static const auto ALGEBRAIC_ABS_TOLS = std::vector({0.0, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.00001, 0.000001});
auto file = libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"));
auto document = libOpenCOR::SedDocument::create(file);
@@ -58,43 +61,9 @@ void forwardEulerSolve(const libOpenCOR::Doubles &pStateValues, const libOpenCOR
simulation->setOdeSolver(solver);
OdeModel::run(document,
- pStateValues, pStateAbsTols,
- pRateValues, pRateAbsTols,
- pConstantValues, pConstantAbsTols,
- pComputedConstantValues, pComputedConstantAbsTols,
- pAlgebraicValues, pAlgebraicAbsTols,
- pCompiled);
-}
-
-} // namespace
-
-static const auto STATE_VALUES = std::vector({-63.787727, 0.134748, 0.984255, 0.741178});
-static const auto STATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
-static const auto RATE_VALUES = std::vector({49.73577, -0.127963, -0.051257, 0.098331});
-static const auto RATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
-static const auto CONSTANT_VALUES = std::vector({1.0, 0.0, 0.3, 120.0, 36.0});
-static const auto CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0, 0.0, 0.0});
-static const auto COMPUTED_CONSTANT_VALUES = std::vector({-10.613, -115.0, 12.0});
-static const auto COMPUTED_CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0});
-static const auto ALGEBRAIC_VALUES = std::vector({0.0, -15.952418, -823.361177, 789.590304, 3.960664, 0.115617, 0.002884, 0.967035, 0.54037, 0.056315});
-static const auto ALGEBRAIC_ABS_TOLS = std::vector({0.0, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.00001, 0.000001});
-
-TEST(ForwardEulerSolverTest, compiledSolve)
-{
- forwardEulerSolve(STATE_VALUES, STATE_ABS_TOLS,
- RATE_VALUES, RATE_ABS_TOLS,
- CONSTANT_VALUES, CONSTANT_ABS_TOLS,
- COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
-}
-
-TEST(ForwardEulerSolverTest, interpretedSolve)
-{
- forwardEulerSolve(STATE_VALUES, STATE_ABS_TOLS,
- RATE_VALUES, RATE_ABS_TOLS,
- CONSTANT_VALUES, CONSTANT_ABS_TOLS,
- COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- false);
+ STATE_VALUES, STATE_ABS_TOLS,
+ RATE_VALUES, RATE_ABS_TOLS,
+ CONSTANT_VALUES, CONSTANT_ABS_TOLS,
+ COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
diff --git a/tests/api/solver/fourthorderrungekuttatests.cpp b/tests/api/solver/fourthorderrungekuttatests.cpp
index 2452a7126..c0de99eaf 100644
--- a/tests/api/solver/fourthorderrungekuttatests.cpp
+++ b/tests/api/solver/fourthorderrungekuttatests.cpp
@@ -37,16 +37,19 @@ TEST(FourthOrderRungeKuttaSolverTest, stepValueWithInvalidNumber)
EXPECT_EQ_ISSUES(instance, EXPECTED_ISSUES);
}
-namespace {
-
-void fourthOrderRungeKuttaSolve(const libOpenCOR::Doubles &pStateValues, const libOpenCOR::Doubles &pStateAbsTols,
- const libOpenCOR::Doubles &pRateValues, const libOpenCOR::Doubles &pRateAbsTols,
- const libOpenCOR::Doubles &pConstantValues, const libOpenCOR::Doubles &pConstantAbsTols,
- const libOpenCOR::Doubles &pComputedConstantValues, const libOpenCOR::Doubles &pComputedConstantAbsTols,
- const libOpenCOR::Doubles &pAlgebraicValues, const libOpenCOR::Doubles &pAlgebraicAbsTols,
- bool pCompiled)
+TEST(FourthOrderRungeKuttaSolverTest, solve)
{
static const auto STEP = 0.0123;
+ static const auto STATE_VALUES = std::vector({-63.821233, 0.134844, 0.984267, 0.741105});
+ static const auto STATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
+ static const auto RATE_VALUES = std::vector({49.702735, -0.127922, -0.051225, 0.098266});
+ static const auto RATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
+ static const auto CONSTANT_VALUES = std::vector({1.0, 0.0, 0.3, 120.0, 36.0});
+ static const auto CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0, 0.0, 0.0});
+ static const auto COMPUTED_CONSTANT_VALUES = std::vector({-10.613, -115.0, 12.0});
+ static const auto COMPUTED_CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0});
+ static const auto ALGEBRAIC_VALUES = std::vector({0.0, -15.96247, -823.402257, 789.661995, 3.963806, 0.115402, 0.002879, 0.967141, 0.540698, 0.056292});
+ static const auto ALGEBRAIC_ABS_TOLS = std::vector({0.0, 0.00001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001});
auto file = libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"));
auto document = libOpenCOR::SedDocument::create(file);
@@ -58,43 +61,9 @@ void fourthOrderRungeKuttaSolve(const libOpenCOR::Doubles &pStateValues, const l
simulation->setOdeSolver(solver);
OdeModel::run(document,
- pStateValues, pStateAbsTols,
- pRateValues, pRateAbsTols,
- pConstantValues, pConstantAbsTols,
- pComputedConstantValues, pComputedConstantAbsTols,
- pAlgebraicValues, pAlgebraicAbsTols,
- pCompiled);
-}
-
-} // namespace
-
-static const auto STATE_VALUES = std::vector({-63.821233, 0.134844, 0.984267, 0.741105});
-static const auto STATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
-static const auto RATE_VALUES = std::vector({49.702735, -0.127922, -0.051225, 0.098266});
-static const auto RATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
-static const auto CONSTANT_VALUES = std::vector({1.0, 0.0, 0.3, 120.0, 36.0});
-static const auto CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0, 0.0, 0.0});
-static const auto COMPUTED_CONSTANT_VALUES = std::vector({-10.613, -115.0, 12.0});
-static const auto COMPUTED_CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0});
-static const auto ALGEBRAIC_VALUES = std::vector({0.0, -15.96247, -823.402257, 789.661995, 3.963806, 0.115402, 0.002879, 0.967141, 0.540698, 0.056292});
-static const auto ALGEBRAIC_ABS_TOLS = std::vector({0.0, 0.00001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001});
-
-TEST(FourthOrderRungeKuttaSolverTest, compiledSolve)
-{
- fourthOrderRungeKuttaSolve(STATE_VALUES, STATE_ABS_TOLS,
- RATE_VALUES, RATE_ABS_TOLS,
- CONSTANT_VALUES, CONSTANT_ABS_TOLS,
- COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
-}
-
-TEST(FourthOrderRungeKuttaSolverTest, interpretedSolve)
-{
- fourthOrderRungeKuttaSolve(STATE_VALUES, STATE_ABS_TOLS,
- RATE_VALUES, RATE_ABS_TOLS,
- CONSTANT_VALUES, CONSTANT_ABS_TOLS,
- COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- false);
+ STATE_VALUES, STATE_ABS_TOLS,
+ RATE_VALUES, RATE_ABS_TOLS,
+ CONSTANT_VALUES, CONSTANT_ABS_TOLS,
+ COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
diff --git a/tests/api/solver/heuntests.cpp b/tests/api/solver/heuntests.cpp
index 21d8a31b9..9bb9d50ae 100644
--- a/tests/api/solver/heuntests.cpp
+++ b/tests/api/solver/heuntests.cpp
@@ -37,16 +37,19 @@ TEST(HeunSolverTest, stepValueWithInvalidNumber)
EXPECT_EQ_ISSUES(instance, EXPECTED_ISSUES);
}
-namespace {
-
-void heunSolve(const libOpenCOR::Doubles &pStateValues, const libOpenCOR::Doubles &pStateAbsTols,
- const libOpenCOR::Doubles &pRateValues, const libOpenCOR::Doubles &pRateAbsTols,
- const libOpenCOR::Doubles &pConstantValues, const libOpenCOR::Doubles &pConstantAbsTols,
- const libOpenCOR::Doubles &pComputedConstantValues, const libOpenCOR::Doubles &pComputedConstantAbsTols,
- const libOpenCOR::Doubles &pAlgebraicValues, const libOpenCOR::Doubles &pAlgebraicAbsTols,
- bool pCompiled)
+TEST(HeunSolverTest, solve)
{
static const auto STEP = 0.0123;
+ static const auto STATE_VALUES = std::vector({-63.691259, 0.134516, 0.984133, 0.74137});
+ static const auto STATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
+ static const auto RATE_VALUES = std::vector({49.66942, -0.127532, -0.051693, 0.097711});
+ static const auto RATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
+ static const auto CONSTANT_VALUES = std::vector({1.0, 0.0, 0.3, 120.0, 36.0});
+ static const auto CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0, 0.0, 0.0});
+ static const auto COMPUTED_CONSTANT_VALUES = std::vector({-10.613, -115.0, 12.0});
+ static const auto COMPUTED_CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0});
+ static const auto ALGEBRAIC_VALUES = std::vector({0.0, -15.923478, -823.166811, 789.421406, 3.951622, 0.116239, 0.002898, 0.966726, 0.539425, 0.056383});
+ static const auto ALGEBRAIC_ABS_TOLS = std::vector({0.0, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001});
auto file = libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"));
auto document = libOpenCOR::SedDocument::create(file);
@@ -58,43 +61,9 @@ void heunSolve(const libOpenCOR::Doubles &pStateValues, const libOpenCOR::Double
simulation->setOdeSolver(solver);
OdeModel::run(document,
- pStateValues, pStateAbsTols,
- pRateValues, pRateAbsTols,
- pConstantValues, pConstantAbsTols,
- pComputedConstantValues, pComputedConstantAbsTols,
- pAlgebraicValues, pAlgebraicAbsTols,
- pCompiled);
-}
-
-} // namespace
-
-static const auto STATE_VALUES = std::vector({-63.691259, 0.134516, 0.984133, 0.74137});
-static const auto STATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
-static const auto RATE_VALUES = std::vector({49.66942, -0.127532, -0.051693, 0.097711});
-static const auto RATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
-static const auto CONSTANT_VALUES = std::vector({1.0, 0.0, 0.3, 120.0, 36.0});
-static const auto CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0, 0.0, 0.0});
-static const auto COMPUTED_CONSTANT_VALUES = std::vector({-10.613, -115.0, 12.0});
-static const auto COMPUTED_CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0});
-static const auto ALGEBRAIC_VALUES = std::vector({0.0, -15.923478, -823.166811, 789.421406, 3.951622, 0.116239, 0.002898, 0.966726, 0.539425, 0.056383});
-static const auto ALGEBRAIC_ABS_TOLS = std::vector({0.0, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001});
-
-TEST(HeunSolverTest, compiledSolve)
-{
- heunSolve(STATE_VALUES, STATE_ABS_TOLS,
- RATE_VALUES, RATE_ABS_TOLS,
- CONSTANT_VALUES, CONSTANT_ABS_TOLS,
- COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
-}
-
-TEST(HeunSolverTest, interpretedSolve)
-{
- heunSolve(STATE_VALUES, STATE_ABS_TOLS,
- RATE_VALUES, RATE_ABS_TOLS,
- CONSTANT_VALUES, CONSTANT_ABS_TOLS,
- COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- false);
+ STATE_VALUES, STATE_ABS_TOLS,
+ RATE_VALUES, RATE_ABS_TOLS,
+ CONSTANT_VALUES, CONSTANT_ABS_TOLS,
+ COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
diff --git a/tests/api/solver/kinsoltests.cpp b/tests/api/solver/kinsoltests.cpp
index 9871a7495..f43439338 100644
--- a/tests/api/solver/kinsoltests.cpp
+++ b/tests/api/solver/kinsoltests.cpp
@@ -112,9 +112,6 @@ TEST(KinsolSolverTest, bandedLinearSolverAndLowerHalfBandwidthValueWithNumberToo
EXPECT_EQ_ISSUES(instance, EXPECTED_ISSUES);
}
-//---GRY--- RENAME THIS TEST compiledSolve AND CREATE ONE CALLED interpretedSolve ONCE WE CAN INTERPRET NLA-BASED
-// MODELS.
-
static const auto ABS_TOL = 1e-05;
namespace {
diff --git a/tests/api/solver/odemodel.cpp b/tests/api/solver/odemodel.cpp
index dc9087a07..aaccd56e6 100644
--- a/tests/api/solver/odemodel.cpp
+++ b/tests/api/solver/odemodel.cpp
@@ -23,8 +23,7 @@ void run(const libOpenCOR::SedDocumentPtr &pDocument,
const libOpenCOR::Doubles &pRateValues, const libOpenCOR::Doubles &pRateAbsTols,
const libOpenCOR::Doubles &pConstantValues, const libOpenCOR::Doubles &pConstantAbsTols,
const libOpenCOR::Doubles &pComputedConstantValues, const libOpenCOR::Doubles &pComputedConstantAbsTols,
- const libOpenCOR::Doubles &pAlgebraicValues, const libOpenCOR::Doubles &pAlgebraicAbsTols,
- bool pCompiled)
+ const libOpenCOR::Doubles &pAlgebraicValues, const libOpenCOR::Doubles &pAlgebraicAbsTols)
{
static const auto OUTPUT_END_TIME = 50.0;
static const auto NUMBER_OF_STEPS = 50000;
@@ -34,7 +33,7 @@ void run(const libOpenCOR::SedDocumentPtr &pDocument,
simulation->setOutputEndTime(OUTPUT_END_TIME);
simulation->setNumberOfSteps(NUMBER_OF_STEPS);
- auto instance = pDocument->instantiate(pCompiled);
+ auto instance = pDocument->instantiate();
instance->run();
diff --git a/tests/api/solver/odemodel.h b/tests/api/solver/odemodel.h
index abdb13278..d00ea8cae 100644
--- a/tests/api/solver/odemodel.h
+++ b/tests/api/solver/odemodel.h
@@ -27,7 +27,6 @@ void run(const libOpenCOR::SedDocumentPtr &pDocument,
const libOpenCOR::Doubles &pRateValues, const libOpenCOR::Doubles &pRateAbsTols,
const libOpenCOR::Doubles &pConstantValues, const libOpenCOR::Doubles &pConstantAbsTols,
const libOpenCOR::Doubles &pComputedConstantValues, const libOpenCOR::Doubles &pComputedConstantAbsTols,
- const libOpenCOR::Doubles &pAlgebraicValues, const libOpenCOR::Doubles &pAlgebraicAbsTols,
- bool pCompiled);
+ const libOpenCOR::Doubles &pAlgebraicValues, const libOpenCOR::Doubles &pAlgebraicAbsTols);
} // namespace OdeModel
diff --git a/tests/api/solver/secondorderrungekuttatests.cpp b/tests/api/solver/secondorderrungekuttatests.cpp
index a52c723f0..d35df4ce5 100644
--- a/tests/api/solver/secondorderrungekuttatests.cpp
+++ b/tests/api/solver/secondorderrungekuttatests.cpp
@@ -37,16 +37,19 @@ TEST(SecondOrderRungeKuttaSolverTest, stepValueWithInvalidNumber)
EXPECT_EQ_ISSUES(instance, EXPECTED_ISSUES);
}
-namespace {
-
-void secondOrderRungeKuttaSolve(const libOpenCOR::Doubles &pStateValues, const libOpenCOR::Doubles &pStateAbsTols,
- const libOpenCOR::Doubles &pRateValues, const libOpenCOR::Doubles &pRateAbsTols,
- const libOpenCOR::Doubles &pConstantValues, const libOpenCOR::Doubles &pConstantAbsTols,
- const libOpenCOR::Doubles &pComputedConstantValues, const libOpenCOR::Doubles &pComputedConstantAbsTols,
- const libOpenCOR::Doubles &pAlgebraicValues, const libOpenCOR::Doubles &pAlgebraicAbsTols,
- bool pCompiled)
+TEST(SecondOrderRungeKuttaSolverTest, solve)
{
static const auto STEP = 0.0123;
+ static const auto STATE_VALUES = std::vector({-63.886525, 0.135009, 0.984334, 0.740971});
+ static const auto STATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
+ static const auto RATE_VALUES = std::vector({49.725722, -0.128194, -0.050903, 0.098651});
+ static const auto RATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
+ static const auto CONSTANT_VALUES = std::vector({1.0, 0.0, 0.3, 120.0, 36.0});
+ static const auto CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0, 0.0, 0.0});
+ static const auto COMPUTED_CONSTANT_VALUES = std::vector({-10.613, -115.0, 12.0});
+ static const auto COMPUTED_CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0});
+ static const auto ALGEBRAIC_VALUES = std::vector({0.0, -15.982058, -823.516942, 789.779614, 3.969929, 0.114985, 0.00287, 0.967348, 0.541338, 0.056246});
+ static const auto ALGEBRAIC_ABS_TOLS = std::vector({0.0, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.00001, 0.000001, 0.000001, 0.000001});
auto file = libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"));
auto document = libOpenCOR::SedDocument::create(file);
@@ -58,43 +61,9 @@ void secondOrderRungeKuttaSolve(const libOpenCOR::Doubles &pStateValues, const l
simulation->setOdeSolver(solver);
OdeModel::run(document,
- pStateValues, pStateAbsTols,
- pRateValues, pRateAbsTols,
- pConstantValues, pConstantAbsTols,
- pComputedConstantValues, pComputedConstantAbsTols,
- pAlgebraicValues, pAlgebraicAbsTols,
- pCompiled);
-}
-
-} // namespace
-
-static const auto STATE_VALUES = std::vector({-63.886525, 0.135009, 0.984334, 0.740971});
-static const auto STATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
-static const auto RATE_VALUES = std::vector({49.725722, -0.128194, -0.050903, 0.098651});
-static const auto RATE_ABS_TOLS = std::vector({0.000001, 0.000001, 0.000001, 0.000001});
-static const auto CONSTANT_VALUES = std::vector({1.0, 0.0, 0.3, 120.0, 36.0});
-static const auto CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0, 0.0, 0.0});
-static const auto COMPUTED_CONSTANT_VALUES = std::vector({-10.613, -115.0, 12.0});
-static const auto COMPUTED_CONSTANT_ABS_TOLS = std::vector({0.0, 0.0, 0.0});
-static const auto ALGEBRAIC_VALUES = std::vector({0.0, -15.982058, -823.516942, 789.779614, 3.969929, 0.114985, 0.00287, 0.967348, 0.541338, 0.056246});
-static const auto ALGEBRAIC_ABS_TOLS = std::vector({0.0, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.00001, 0.000001, 0.000001, 0.000001});
-
-TEST(SecondOrderRungeKuttaSolverTest, compiledSolve)
-{
- secondOrderRungeKuttaSolve(STATE_VALUES, STATE_ABS_TOLS,
- RATE_VALUES, RATE_ABS_TOLS,
- CONSTANT_VALUES, CONSTANT_ABS_TOLS,
- COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- true);
-}
-
-TEST(SecondOrderRungeKuttaSolverTest, interpretedSolve)
-{
- secondOrderRungeKuttaSolve(STATE_VALUES, STATE_ABS_TOLS,
- RATE_VALUES, RATE_ABS_TOLS,
- CONSTANT_VALUES, CONSTANT_ABS_TOLS,
- COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
- ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS,
- false);
+ STATE_VALUES, STATE_ABS_TOLS,
+ RATE_VALUES, RATE_ABS_TOLS,
+ CONSTANT_VALUES, CONSTANT_ABS_TOLS,
+ COMPUTED_CONSTANT_VALUES, COMPUTED_CONSTANT_ABS_TOLS,
+ ALGEBRAIC_VALUES, ALGEBRAIC_ABS_TOLS);
}
diff --git a/tests/bindings/javascript/ode.model.js b/tests/bindings/javascript/ode.model.js
index c449a283b..e6e11738a 100644
--- a/tests/bindings/javascript/ode.model.js
+++ b/tests/bindings/javascript/ode.model.js
@@ -19,10 +19,15 @@ import { expectValues } from "./utils.js";
export function run(
document,
stateValues,
+ statePrecisions,
rateValues,
+ ratePrecisions,
constantValues,
+ constantPrecisions,
computedConstantValues,
+ computedConstantPrecisions,
algebraicValues,
+ algebraicPrecisions,
) {
const simulation = document.simulations.get(0);
@@ -39,9 +44,14 @@ export function run(
instanceTask,
13000,
stateValues,
+ statePrecisions,
rateValues,
+ ratePrecisions,
constantValues,
+ constantPrecisions,
computedConstantValues,
+ computedConstantPrecisions,
algebraicValues,
+ algebraicPrecisions,
);
}
diff --git a/tests/bindings/javascript/res/index.html b/tests/bindings/javascript/res/index.html
index 28c6224a2..23ad6cbc9 100644
--- a/tests/bindings/javascript/res/index.html
+++ b/tests/bindings/javascript/res/index.html
@@ -73,11 +73,10 @@
-
-
- Issues:
+
@@ -110,12 +109,6 @@
-
-
diff --git a/tests/bindings/javascript/res/res/libopencor.js b/tests/bindings/javascript/res/res/libopencor.js
index 95727f40a..0d1f9b873 100644
--- a/tests/bindings/javascript/res/res/libopencor.js
+++ b/tests/bindings/javascript/res/res/libopencor.js
@@ -27,14 +27,34 @@ export function showPage(page) {
});
}
-function showError(error) {
- if (!error.endsWith(".")) {
- error += ".";
+function showIssues(issues) {
+ const issuesElement = $("#issues");
+
+ issuesElement.empty();
+
+ if (issues instanceof Array) {
+ for (let i = 0; i < issues.length; ++i) {
+ issuesElement.append(
+ '
Error: ' +
+ formattedIssueDescription(issues[i]) +
+ "",
+ );
+ }
+ } else {
+ for (let i = 0; i < issues.size(); ++i) {
+ const issue = issues.get(i);
+
+ issuesElement.append(
+ '
' +
+ issue.typeAsString +
+ ": " +
+ formattedIssueDescription(issue.description) +
+ "",
+ );
+ }
}
- $("#errorMessage").html(error);
-
- updateFileUi(false, false, true, true, false);
+ updateFileUi(true, true, true, false);
}
function listFiles() {
@@ -56,13 +76,11 @@ function listFiles() {
function updateFileUi(
fileInfoDisplay,
fileIssuesDisplay,
- fileErrorDisplay,
resetButtonDisplay,
simulationDisplay,
) {
$("#fileInfo").css("display", fileInfoDisplay ? "block" : "none");
$("#fileIssues").css("display", fileIssuesDisplay ? "block" : "none");
- $("#fileError").css("display", fileErrorDisplay ? "block" : "none");
$("#reset").css("display", resetButtonDisplay ? "block" : "none");
$("#simulation").css("display", simulationDisplay ? "block" : "none");
@@ -94,7 +112,7 @@ export function reset() {
resetObjects();
- updateFileUi(false, false, false, false, false);
+ updateFileUi(false, false, false, false);
}
function addAxisElement(axis, name) {
@@ -257,36 +275,44 @@ $(() => {
// Display any issues with the file or run it.
- let hasIssues = false;
-
if (knownFile) {
if (file.hasIssues) {
- const issuesElement = $("#issues");
- const fileIssues = file.issues;
+ showIssues(file.issues);
+ } else {
+ // Retrieve some information about the simulation.
- issuesElement.empty();
+ document = new loc.SedDocument(file);
- for (let i = 0; i < fileIssues.size(); ++i) {
- const issue = fileIssues.get(i);
+ if (document.hasIssues) {
+ showIssues(document.issues);
- issuesElement.append(
- '
' +
- issue.typeAsString +
- ": " +
- formattedIssueDescription(issue.description) +
- "",
- );
+ return;
}
- hasIssues = true;
- } else {
- // Retrieve some information about the simulation.
-
- document = new loc.SedDocument(file);
simulation = document.simulations.get(0);
+
+ if (simulation !== null && simulation.hasIssues) {
+ showIssues(simulation.issues);
+
+ return;
+ }
+
instance = document.instantiate();
+
+ if (instance !== null && instance.hasIssues) {
+ showIssues(instance.issues);
+
+ return;
+ }
+
instanceTask = instance.tasks.get(0);
+ if (instanceTask !== null && instanceTask.hasIssues) {
+ showIssues(instanceTask.issues);
+
+ return;
+ }
+
$("#endingPoint").val(simulation.outputEndTime);
$("#endingPointUnit").text(instanceTask.voiUnit);
@@ -309,20 +335,20 @@ $(() => {
// axes information.
updatePlottingAreaAndAxesInfo();
+
+ updateFileUi(true, false, true, true);
}
}
-
- updateFileUi(true, hasIssues, false, true, knownFile && !hasIssues);
} catch (exception) {
- showError(exception.message);
+ showIssues([exception.message]);
}
};
fileReader.onerror = () => {
- showError(fileReader.error.message);
+ showIssues([fileReader.error.message]);
};
} else {
- updateFileUi(false, false, false, false, false);
+ updateFileUi(false, false, false, false);
}
};
diff --git a/tests/bindings/javascript/sed.coverage.test.js b/tests/bindings/javascript/sed.coverage.test.js
index bbcee8653..b45ec4547 100644
--- a/tests/bindings/javascript/sed.coverage.test.js
+++ b/tests/bindings/javascript/sed.coverage.test.js
@@ -16,7 +16,7 @@ limitations under the License.
import libOpenCOR from "./libopencor.js";
import * as utils from "./utils.js";
-import { expectIssues } from "./utils.js";
+import { expectIssues, expectValues } from "./utils.js";
const loc = await libOpenCOR();
@@ -26,6 +26,7 @@ describe("Sed coverage tests", () => {
let unsupportedSedChangesContentsPtr;
let solverOdeContentsPtr;
let solverNla1ContentsPtr;
+ let mathContentsPtr;
beforeAll(() => {
sedChangesContentsPtr = utils.allocateMemory(
@@ -45,6 +46,7 @@ describe("Sed coverage tests", () => {
loc,
utils.SOLVER_NLA1_CONTENTS,
);
+ mathContentsPtr = utils.allocateMemory(loc, utils.MATH_CONTENTS);
});
afterAll(() => {
@@ -53,6 +55,7 @@ describe("Sed coverage tests", () => {
utils.freeMemory(loc, unsupportedSedChangesContentsPtr);
utils.freeMemory(loc, solverOdeContentsPtr);
utils.freeMemory(loc, solverNla1ContentsPtr);
+ utils.freeMemory(loc, mathContentsPtr);
});
function sedTaskExpectedSerialisation(withProperties) {
@@ -514,14 +517,10 @@ describe("Sed coverage tests", () => {
file.delete();
});
- /*---GRY--- TO BE UNCOMMENTED ONCE WE CAN INTERPRET A MODEL WITH ONE/SEVERAL NLA SYSTEM/S.
test("SedInstanceAndSedInstanceTaskNonDifferentialModel", () => {
const file = new loc.File(utils.CELLML_FILE);
- file.setContents(
- solverNla1ContentsPtr,
- utils.SOLVER_NLA1_CONTENTS.length,
- );
+ file.setContents(solverNla1ContentsPtr, utils.SOLVER_NLA1_CONTENTS.length);
const document = new loc.SedDocument(file);
@@ -549,7 +548,6 @@ describe("Sed coverage tests", () => {
document.delete();
file.delete();
});
- */
test("SedDocument", () => {
let file = new loc.File(utils.HTTP_REMOTE_CELLML_FILE);
@@ -634,4 +632,76 @@ describe("Sed coverage tests", () => {
document.delete();
file.delete();
});
+
+ test("Math", () => {
+ const file = new loc.File(utils.CELLML_FILE);
+
+ file.setContents(mathContentsPtr, utils.MATH_CONTENTS.length);
+
+ const document = new loc.SedDocument(file);
+ const instance = document.instantiate();
+ const instanceTask = instance.tasks.get(0);
+
+ expect(instanceTask.constantCount).toBe(0);
+ expect(instanceTask.computedConstantCount).toBe(37);
+ expect(instanceTask.algebraicCount).toBe(0);
+
+ instance.run();
+
+ expectValues(
+ instanceTask,
+ 0,
+ [],
+ [],
+ [],
+ [],
+ [],
+ [],
+ [
+ 243.0,
+ 3.0,
+ 7.0,
+ 20.085536923187668,
+ 1.0986122886681098,
+ 0.47712125471966244,
+ 4.0,
+ 3.0,
+ 3.0,
+ 5.0,
+ 3.0,
+ 0.1411200080598672,
+ -0.9899924966004454,
+ -0.1425465430742778,
+ -1.0101086659079939,
+ 7.086167395737187,
+ -7.015252551434534,
+ 10.017874927409903,
+ 10.067661995777765,
+ 0.9950547536867305,
+ 0.0993279274194332,
+ 0.09982156966882273,
+ 1.0049698233136892,
+ 0.3046926540153975,
+ 1.2661036727794992,
+ 1.2490457723982544,
+ 1.2309594173407747,
+ 0.3398369094541219,
+ 0.3217505543966422,
+ 1.8184464592320668,
+ 1.7627471740390859,
+ 0.30951960420311175,
+ 1.8738202425274144,
+ 0.32745015023725843,
+ 0.34657359027997264,
+ Infinity,
+ NaN,
+ ],
+ [
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ ],
+ [],
+ [],
+ );
+ });
});
diff --git a/tests/bindings/javascript/sed.instance.test.js b/tests/bindings/javascript/sed.instance.test.js
index 173a37596..ba5e838b1 100644
--- a/tests/bindings/javascript/sed.instance.test.js
+++ b/tests/bindings/javascript/sed.instance.test.js
@@ -270,7 +270,6 @@ describe("Sed instance tests", () => {
file.delete();
});
- /*---GRY--- TO BE UNCOMMENTED ONCE WE CAN INTERPRET A MODEL WITH ONE/SEVERAL NLA SYSTEM/S.
test("NLA model", () => {
const file = new loc.File(utils.CELLML_FILE);
@@ -327,9 +326,7 @@ describe("Sed instance tests", () => {
document.delete();
file.delete();
});
- */
- /*---GRY--- TO BE UNCOMMENTED ONCE WE CAN INTERPRET A MODEL WITH ONE/SEVERAL NLA SYSTEM/S.
test("DAE model", () => {
const file = new loc.File(utils.CELLML_FILE);
@@ -374,7 +371,6 @@ describe("Sed instance tests", () => {
document.delete();
file.delete();
});
- */
test("DAE model with no ODE or NLA solver", () => {
const file = new loc.File(utils.CELLML_FILE);
@@ -389,7 +385,6 @@ describe("Sed instance tests", () => {
const instance = document.instantiate();
- /*---GRY--- TO BE UNCOMMENTED ONCE WE CAN INTERPRET A MODEL WITH ONE/SEVERAL NLA SYSTEM/S.
expectIssues(loc, instance, [
[
loc.Issue.Type.ERROR,
@@ -400,7 +395,6 @@ describe("Sed instance tests", () => {
"Simulation 'simulation1' is to be used with model 'model1' which requires an NLA solver but none is provided.",
],
]);
- */
instance.delete();
document.delete();
diff --git a/tests/bindings/javascript/solver.coverage.test.js b/tests/bindings/javascript/solver.coverage.test.js
index 8e26bd5a0..30e58f7c4 100644
--- a/tests/bindings/javascript/solver.coverage.test.js
+++ b/tests/bindings/javascript/solver.coverage.test.js
@@ -77,7 +77,6 @@ describe("Solver coverage tests", () => {
file.delete();
});
- /*---GRY--- ENABLE THIS TEST ONCE WE CAN INTERPRET NLA-BASED MODELS.
test("Algebraic changes", () => {
// We want to solve a system of three unknowns:
// Variables:
@@ -116,8 +115,8 @@ describe("Solver coverage tests", () => {
expect(instanceTask.stateCount).toBe(0);
expect(instanceTask.rateCount).toBe(0);
- expect(instanceTask.constantCount).toBe(0);
- expect(instanceTask.computedConstantCount).toBe(0);
+ expect(instanceTask.constantCount).toBe(1);
+ expect(instanceTask.computedConstantCount).toBe(1);
expect(instanceTask.algebraicCount).toBe(3);
expect(instanceTask.algebraic(0).get(0)).toBeCloseTo(33.33333, 5);
@@ -128,5 +127,4 @@ describe("Solver coverage tests", () => {
document.delete();
file.delete();
});
- */
});
diff --git a/tests/bindings/javascript/solver.cvode.test.js b/tests/bindings/javascript/solver.cvode.test.js
index 40e8af26a..3f1287f24 100644
--- a/tests/bindings/javascript/solver.cvode.test.js
+++ b/tests/bindings/javascript/solver.cvode.test.js
@@ -245,14 +245,26 @@ describe("Solver CVODE tests", () => {
odeModel.run(
document,
- [-63.886006, 0.135007, 0.984334, 0.740972],
- [49.72578, -0.128193, -0.050905, 0.098649],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, -15.981902, -823.516722, 789.778714, 3.96988, 0.114988, 0.00287,
- 0.967346, 0.541333, 0.056246,
+ -63.886250327293745, 0.13500806843489388, 0.9843336119444306,
+ 0.7409718295171003,
],
+ [3, 6, 6, 6],
+ [
+ 49.725700307489824, -0.1281933409028202, -0.050902572494876855,
+ 0.09864999300596061,
+ ],
+ [3, 6, 5, 5],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, -15.981975098188123, -823.5166486227178, 789.7791369560812,
+ 3.9699027454989695, 0.11498635979013846, 0.002869628921262234,
+ 0.9673471419816907, 0.5413354590998287, 0.056246038290390175,
+ ],
+ [7, 4, 2, 3, 4, 5, 7, 6, 5, 6],
);
document.delete();
@@ -272,14 +284,26 @@ describe("Solver CVODE tests", () => {
odeModel.run(
document,
- [-63.886395, 0.135008, 0.984334, 0.740972],
- [49.725709, -0.128194, -0.050903, 0.098651],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, -15.982019, -823.51695, 789.77946, 3.969916, 0.114985, 0.00287,
- 0.967348, 0.541337, 0.056246,
+ -63.88639507849153, 0.1350083126473699, 0.9843340818649865,
+ 0.7409715439143221,
+ ],
+ [6, 7, 7, 7],
+ [
+ 49.72570880449381, -0.12819363057743782, -0.050903078877701416,
+ 0.09865054326291173,
],
+ [6, 7, 7, 7],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, -15.98201852354746, -823.5169497826655, 789.7794600735924,
+ 3.9699163220783995, 0.11498543510422823, 0.002869608152226214,
+ 0.9673475991991235, 0.5413368772943074, 0.05624593651946458,
+ ],
+ [7, 6, 5, 5, 7, 7, 7, 7, 7, 7],
);
document.delete();
@@ -299,14 +323,26 @@ describe("Solver CVODE tests", () => {
odeModel.run(
document,
- [-63.888155, 0.135013, 0.984336, 0.740968],
- [49.725742, -0.128199, -0.050896, 0.098658],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, -15.982546, -823.520056, 789.782845, 3.970081, 0.114974, 0.002869,
- 0.967353, 0.541354, 0.056245,
+ -63.887813934797826, 0.13501191292213002, 0.9843355542098364,
+ 0.7409686747551986,
+ ],
+ [2, 4, 5, 4],
+ [
+ 49.72620260336583, -0.12819788722747028, -0.05089750341316691,
+ 0.09865693092730915,
+ ],
+ [2, 4, 4, 4],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, -15.982444180439348, -823.5195918535778, 789.7821411983648,
+ 3.97004940067058, 0.11497637169423897, 0.0028694045813660754,
+ 0.9673520805329192, 0.5413507785037981, 0.056244938967039075,
],
+ [7, 2, 2, 2, 3, 4, 6, 4, 4, 5],
);
document.delete();
@@ -326,14 +362,26 @@ describe("Solver CVODE tests", () => {
odeModel.run(
document,
- [-63.88619, 0.135008, 0.984334, 0.740972],
- [49.72565, -0.128193, -0.050904, 0.09865],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, -15.981957, -823.516742, 789.779253, 3.969897, 0.114987, 0.00287,
- 0.967347, 0.541335, 0.056246,
+ -63.886282061359374, 0.135008093417601, 0.9843339833821376,
+ 0.7409718122756039,
],
+ [3, 6, 6, 6],
+ [
+ 49.72538296330156, -0.12819336464938047, -0.050903478581860076,
+ 0.09865009949522247,
+ ],
+ [3, 6, 5, 6],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, -15.981984618407811, -823.5169163515275, 789.7796868336728,
+ 3.9699057219161293, 0.11498615706894559, 0.0028696243680162202,
+ 0.967347242218821, 0.5413357700131285, 0.056246015978951215,
+ ],
+ [7, 4, 3, 3, 4, 5, 7, 6, 5, 6],
);
document.delete();
@@ -353,14 +401,26 @@ describe("Solver CVODE tests", () => {
odeModel.run(
document,
- [-54.957552, 0.114715, 0.971364, 0.756968],
- [47.196456, -0.10208, -0.092979, 0.062976],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, -13.303366, -791.427395, 757.54033, 3.153423, 0.188831, 0.004484,
- 0.923844, 0.454648, 0.062887,
+ -54.95816860466446, 0.11471650712970222, 0.9713656209644033,
+ 0.756967274462986,
+ ],
+ [3, 5, 5, 6],
+ [
+ 47.19692686937322, -0.10208187002903986, -0.0929754636050344,
+ 0.06297792796897843,
],
+ [3, 5, 5, 5],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, -13.303550581399337, -791.4336008281795, 757.5464682504468,
+ 3.1534773935628353, 0.1888245073098595, 0.004484319750222318,
+ 0.9238480455513784, 0.4546536035795939, 0.06288682169446458,
+ ],
+ [7, 3, 2, 2, 4, 5, 6, 5, 5, 6],
);
document.delete();
@@ -380,14 +440,26 @@ describe("Solver CVODE tests", () => {
odeModel.run(
document,
- [-63.886488, 0.135009, 0.984334, 0.740972],
- [49.725561, -0.128191, -0.050903, 0.098651],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, -15.982046, -823.518024, 789.780604, 3.969925, 0.114985, 0.00287,
- 0.967348, 0.541338, 0.056246,
+ -63.88448960386081, 0.13500371980870626, 0.9843320337747878,
+ 0.740975648022661,
+ ],
+ [2, 4, 6, 5],
+ [
+ 49.72470056973946, -0.1281877408620835, -0.05090942244126474,
+ 0.0986375194818581,
+ ],
+ [2, 4, 3, 4],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, -15.981446881158242, -823.5145165709908, 789.777104114329,
+ 3.9697376035476495, 0.114997608072391, 0.0028698815635271745,
+ 0.9673415799887405, 0.5413182085040471, 0.05624727622548335,
],
+ [7, 2, 1, 2, 3, 4, 6, 4, 4, 5],
);
document.delete();
@@ -407,14 +479,26 @@ describe("Solver CVODE tests", () => {
odeModel.run(
document,
- [9.518468, 0.367366, 0.01612, 0.491145],
- [-0.864067, 0.064354, 0.001718, -0.052716],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, 6.03944, -5.198281, 0.022996, 0.112958, 6.787605, 0.112665,
- 0.018857, 0.032306, 0.140794,
+ 9.518467927238342, 0.36736556858518055, 0.01612044160716401,
+ 0.49114455278457375,
],
+ [7, 7, 7, 7],
+ [
+ -0.8640672736946257, 0.06435448571982208, 0.0017177341020318897,
+ -0.05271611541688017,
+ ],
+ [7, 7, 7, 7],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, 6.039440378171502, -5.198280618006445, 0.02299557473368303,
+ 0.11295819992492505, 6.787604864938159, 0.11266498023914563,
+ 0.018856763703178375, 0.03230635782390115, 0.14079354343581396,
+ ],
+ [7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
);
document.delete();
@@ -434,14 +518,26 @@ describe("Solver CVODE tests", () => {
odeModel.run(
document,
- [9.518406, 0.36737, 0.016121, 0.491141],
- [-0.864079, 0.064354, 0.001718, -0.052715],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, 6.039422, -5.198258, 0.022996, 0.112959, 6.787581, 0.112665,
- 0.018857, 0.032306, 0.140793,
+ 9.518405563384688, 0.3673701689782409, 0.016120565942342176,
+ 0.49114094269101,
+ ],
+ [7, 7, 7, 7],
+ [
+ -0.8640794309120806, 0.06435358502313818, 0.0017178663683860092,
+ -0.05271535789078276,
],
+ [7, 7, 7, 7],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, 6.039421669015407, -5.198258417710488, 0.02299638327958176,
+ 0.11295872334992325, 6.7875813482457605, 0.11266462892857637,
+ 0.018856879084051228, 0.03230648942381701, 0.14079343368050753,
+ ],
+ [7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
);
document.delete();
@@ -461,14 +557,26 @@ describe("Solver CVODE tests", () => {
odeModel.run(
document,
- [9.518097, 0.367396, 0.016121, 0.491122],
- [-0.864142, 0.064349, 0.001718, -0.052711],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, 6.039329, -5.198098, 0.023, 0.112961, 6.787465, 0.112663, 0.018857,
- 0.032307, 0.140793,
+ 9.5180969791175, 0.36739578686621527, 0.016121150676415584,
+ 0.4911219162005304,
+ ],
+ [5, 6, 6, 6],
+ [
+ -0.8641450065405636, 0.06434891371052368, 0.0017179872368887157,
+ -0.05271147016114454,
+ ],
+ [5, 6, 2, 7],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, 6.03932909373525, -5.198099254585335, 0.02300043256789237,
+ 0.11296131335573398, 6.787464985864513, 0.11266289061538902,
+ 0.018857450013451658, 0.03230714060351441, 0.14079289059857297,
],
+ [7, 5, 5, 6, 7, 5, 7, 7, 7, 7],
);
document.delete();
@@ -489,14 +597,26 @@ describe("Solver CVODE tests", () => {
odeModel.run(
document,
- [-63.88632, 0.135008, 0.984334, 0.740972],
- [49.725847, -0.128194, -0.050904, 0.09865],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, -15.981996, -823.516944, 789.779343, 3.969909, 0.114986, 0.00287,
- 0.967347, 0.541336, 0.056246,
+ -63.88610210255769, 0.13500770971929016, 0.9843329698410943,
+ 0.7409720924682706,
],
+ [3, 6, 5, 6],
+ [
+ 49.726333013075525, -0.12819299724421862, -0.05091538950854948,
+ 0.09865029693084587,
+ ],
+ [2, 6, 4, 6],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, -15.981930630767307, -823.5162090645707, 789.7777832194464,
+ 3.9698888431371406, 0.1149873066730832, 0.002869650188840514,
+ 0.967346673786178, 0.5413340068738324, 0.056246142503663964,
+ ],
+ [7, 4, 2, 2, 4, 5, 7, 6, 5, 6],
);
document.delete();
@@ -517,14 +637,26 @@ describe("Solver CVODE tests", () => {
odeModel.run(
document,
- [-63.886025, 0.135008, 0.984333, 0.740972],
- [49.725781, -0.128193, -0.050904, 0.098649],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, -15.981908, -823.516709, 789.778962, 3.969882, 0.114988, 0.00287,
- 0.967346, 0.541333, 0.056246,
+ -63.88580250259205, 0.13500689029927881, 0.9843332002100482,
+ 0.740972698029834,
+ ],
+ [4, 6, 6, 7],
+ [
+ 49.725495533208736, -0.12819193324161038, -0.050904587288098005,
+ 0.09864807163623063,
],
+ [5, 6, 6, 6],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, -15.981840750777614, -823.515649881427, 789.7781734161576,
+ 3.969860742950322, 0.1149892205886294, 0.0028696931765173905,
+ 0.9673457274239244, 0.5413310715560667, 0.05624635314583791,
+ ],
+ [7, 4, 3, 3, 5, 6, 7, 6, 6, 7],
);
document.delete();
@@ -545,14 +677,26 @@ describe("Solver CVODE tests", () => {
odeModel.run(
document,
- [-63.886116, 0.135008, 0.984333, 0.740972],
- [49.725704, -0.128193, -0.050903, 0.098649],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, -15.981935, -823.516302, 789.778803, 3.96989, 0.114987, 0.00287,
- 0.967347, 0.541334, 0.056246,
+ -63.88590096494604, 0.13500714432443245, 0.9843333109015502,
+ 0.7409725093281302,
+ ],
+ [3, 5, 5, 5],
+ [
+ 49.72555013681926, -0.12819226308184883, -0.050905813346241904,
+ 0.09864850534796382,
+ ],
+ [3, 5, 5, 5],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, -15.981870289483812, -823.5158795070533, 789.7784045107686,
+ 3.969869977962206, 0.11498859158427523, 0.0028696790487148967,
+ 0.967346038445092, 0.5413320362365842, 0.056246283919026335,
],
+ [7, 3, 2, 2, 4, 5, 6, 5, 5, 6],
);
document.delete();
diff --git a/tests/bindings/javascript/solver.forwardeuler.test.js b/tests/bindings/javascript/solver.forwardeuler.test.js
index ea81ef54d..391330ccb 100644
--- a/tests/bindings/javascript/solver.forwardeuler.test.js
+++ b/tests/bindings/javascript/solver.forwardeuler.test.js
@@ -75,14 +75,26 @@ describe("Solver Forward Euler tests", () => {
odeModel.run(
document,
- [-63.787727, 0.134748, 0.984255, 0.741178],
- [49.73577, -0.127963, -0.051257, 0.098331],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, -15.952418, -823.361177, 789.590304, 3.960664, 0.115617, 0.002884,
- 0.967035, 0.54037, 0.056315,
+ -63.787727309843625, 0.13474847497254067, 0.9842548213064144,
+ 0.7411775397899871,
],
+ [7, 7, 7, 7],
+ [
+ 49.7357696419333, -0.12796285748502675, -0.05125742132748939,
+ 0.09833105129202654,
+ ],
+ [7, 7, 7, 7],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, -15.952418192953086, -823.361177370372, 789.5903038580856,
+ 3.9606641552180855, 0.11561746333925438, 0.002883800022109427,
+ 0.9670345037893372, 0.5403702607259089, 0.05631535007932082,
+ ],
+ [7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
);
solver.delete();
diff --git a/tests/bindings/javascript/solver.fourthorderrungekutta.test.js b/tests/bindings/javascript/solver.fourthorderrungekutta.test.js
index 818774925..82a7b004d 100644
--- a/tests/bindings/javascript/solver.fourthorderrungekutta.test.js
+++ b/tests/bindings/javascript/solver.fourthorderrungekutta.test.js
@@ -75,14 +75,26 @@ describe("Solver Fourth-Order Runge-Kutta tests", () => {
odeModel.run(
document,
- [-63.821233, 0.134844, 0.984267, 0.741105],
- [49.702735, -0.127922, -0.051225, 0.098266],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, -15.96247, -823.402257, 789.661995, 3.963806, 0.115402, 0.002879,
- 0.967141, 0.540698, 0.056292,
+ -63.821233121797334, 0.13484386454832029, 0.9842671578347936,
+ 0.7411048872918694,
],
+ [7, 7, 7, 7],
+ [
+ 49.70273520660513, -0.1279222891468715, -0.051224913137817824,
+ 0.0982660916488527,
+ ],
+ [7, 7, 7, 7],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, -15.9624699365392, -823.4022571720553, 789.6619953203995,
+ 3.9638055464297928, 0.11540244924165802, 0.002878972863622386,
+ 0.9671411492217459, 0.540698489075857, 0.05629176887371371,
+ ],
+ [7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
);
solver.delete();
diff --git a/tests/bindings/javascript/solver.heun.test.js b/tests/bindings/javascript/solver.heun.test.js
index 34226e7f2..5eb435873 100644
--- a/tests/bindings/javascript/solver.heun.test.js
+++ b/tests/bindings/javascript/solver.heun.test.js
@@ -75,14 +75,26 @@ describe("Solver Heun tests", () => {
odeModel.run(
document,
- [-63.691259, 0.134516, 0.984133, 0.74137],
- [49.66942, -0.127532, -0.051693, 0.097711],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, -15.923478, -823.166811, 789.421406, 3.951622, 0.116239, 0.002898,
- 0.966726, 0.539425, 0.056383,
+ -63.69125875774881, 0.13451645104446466, 0.9841326274924806,
+ 0.7413698256563633,
],
+ [7, 7, 7, 7],
+ [
+ 49.66942041994269, -0.12753246872257323, -0.051692906785376816,
+ 0.09771071198596298,
+ ],
+ [7, 7, 7, 7],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, -15.923477627324644, -823.1668113969306, 789.4214057021819,
+ 3.95162235535478, 0.11623876280854108, 0.002897743423202202,
+ 0.9667255844752269, 0.539425339436885, 0.05638329929313714,
+ ],
+ [7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
);
solver.delete();
diff --git a/tests/bindings/javascript/solver.kinsol.test.js b/tests/bindings/javascript/solver.kinsol.test.js
index 0b4bbbb7f..f4322e4cb 100644
--- a/tests/bindings/javascript/solver.kinsol.test.js
+++ b/tests/bindings/javascript/solver.kinsol.test.js
@@ -16,8 +16,7 @@ limitations under the License.
import libOpenCOR from "./libopencor.js";
import * as utils from "./utils.js";
-//---GRY--- TO BE ENABLED ONCE WE CAN INTERPRET NLA-BASED MODELS.
-// import { expectIssues } from "./utils.js";
+import { expectIssues } from "./utils.js";
const loc = await libOpenCOR();
@@ -41,16 +40,10 @@ describe("Solver KINSOL tests", () => {
utils.freeMemory(loc, solverNla2ContentsPtr);
});
- test("Dummy", () => {});
-
- /*---GRY--- ENABLE THOSE TESTS ONCE WE CAN INTERPRET NLA-BASED MODELS.
test("Maximum number of iterations value with invalid number", () => {
const file = new loc.File(utils.CELLML_FILE);
- file.setContents(
- solverNla1ContentsPtr,
- utils.SOLVER_NLA1_CONTENTS.length,
- );
+ file.setContents(solverNla1ContentsPtr, utils.SOLVER_NLA1_CONTENTS.length);
const document = new loc.SedDocument(file);
const simulation = document.simulations.get(0);
@@ -63,7 +56,7 @@ describe("Solver KINSOL tests", () => {
expectIssues(loc, instance, [
[
loc.Issue.Type.ERROR,
- "The maximum number of iterations cannot be equal to 0. It must be greater than 0.",
+ "The maximum number of iterations cannot be equal to -1. It must be greater than 0.",
],
]);
@@ -75,10 +68,7 @@ describe("Solver KINSOL tests", () => {
test("Banded linear solver and upper half-bandwidth value with number too small", () => {
const file = new loc.File(utils.CELLML_FILE);
- file.setContents(
- solverNla2ContentsPtr,
- utils.SOLVER_NLA2_CONTENTS.length,
- );
+ file.setContents(solverNla2ContentsPtr, utils.SOLVER_NLA2_CONTENTS.length);
const document = new loc.SedDocument(file);
const simulation = document.simulations.get(0);
@@ -104,10 +94,7 @@ describe("Solver KINSOL tests", () => {
test("Banded linear solver and upper half-bandwidth value with number too big", () => {
const file = new loc.File(utils.CELLML_FILE);
- file.setContents(
- solverNla1ContentsPtr,
- utils.SOLVER_NLA1_CONTENTS.length,
- );
+ file.setContents(solverNla1ContentsPtr, utils.SOLVER_NLA1_CONTENTS.length);
const document = new loc.SedDocument(file);
const simulation = document.simulations.get(0);
@@ -133,10 +120,7 @@ describe("Solver KINSOL tests", () => {
test("Banded linear solver and lower half-bandwidth value with number too small", () => {
const file = new loc.File(utils.CELLML_FILE);
- file.setContents(
- solverNla2ContentsPtr,
- utils.SOLVER_NLA2_CONTENTS.length,
- );
+ file.setContents(solverNla2ContentsPtr, utils.SOLVER_NLA2_CONTENTS.length);
const document = new loc.SedDocument(file);
const simulation = document.simulations.get(0);
@@ -162,10 +146,7 @@ describe("Solver KINSOL tests", () => {
test("Banded linear solver and lower half-bandwidth value with number too big", () => {
const file = new loc.File(utils.CELLML_FILE);
- file.setContents(
- solverNla1ContentsPtr,
- utils.SOLVER_NLA1_CONTENTS.length,
- );
+ file.setContents(solverNla1ContentsPtr, utils.SOLVER_NLA1_CONTENTS.length);
const document = new loc.SedDocument(file);
const simulation = document.simulations.get(0);
@@ -215,10 +196,7 @@ describe("Solver KINSOL tests", () => {
test("Solve", () => {
const file = new loc.File(utils.CELLML_FILE);
- file.setContents(
- solverNla1ContentsPtr,
- utils.SOLVER_NLA1_CONTENTS.length,
- );
+ file.setContents(solverNla1ContentsPtr, utils.SOLVER_NLA1_CONTENTS.length);
const document = new loc.SedDocument(file);
const instance = document.instantiate();
@@ -235,10 +213,7 @@ describe("Solver KINSOL tests", () => {
test("Solve with banded linear solver", () => {
const file = new loc.File(utils.CELLML_FILE);
- file.setContents(
- solverNla2ContentsPtr,
- utils.SOLVER_NLA2_CONTENTS.length,
- );
+ file.setContents(solverNla2ContentsPtr, utils.SOLVER_NLA2_CONTENTS.length);
const document = new loc.SedDocument(file);
const simulation = document.simulations.get(0);
@@ -262,10 +237,7 @@ describe("Solver KINSOL tests", () => {
test("Solve with GMRES linear solver", () => {
const file = new loc.File(utils.CELLML_FILE);
- file.setContents(
- solverNla1ContentsPtr,
- utils.SOLVER_NLA1_CONTENTS.length,
- );
+ file.setContents(solverNla1ContentsPtr, utils.SOLVER_NLA1_CONTENTS.length);
const document = new loc.SedDocument(file);
const simulation = document.simulations.get(0);
@@ -287,10 +259,7 @@ describe("Solver KINSOL tests", () => {
test("Solve with BiCGStab linear solver", () => {
const file = new loc.File(utils.CELLML_FILE);
- file.setContents(
- solverNla2ContentsPtr,
- utils.SOLVER_NLA2_CONTENTS.length,
- );
+ file.setContents(solverNla2ContentsPtr, utils.SOLVER_NLA2_CONTENTS.length);
const document = new loc.SedDocument(file);
const simulation = document.simulations.get(0);
@@ -312,10 +281,7 @@ describe("Solver KINSOL tests", () => {
test("Solve with TFQMR linear solver", () => {
const file = new loc.File(utils.CELLML_FILE);
- file.setContents(
- solverNla1ContentsPtr,
- utils.SOLVER_NLA1_CONTENTS.length,
- );
+ file.setContents(solverNla1ContentsPtr, utils.SOLVER_NLA1_CONTENTS.length);
const document = new loc.SedDocument(file);
const simulation = document.simulations.get(0);
@@ -333,5 +299,4 @@ describe("Solver KINSOL tests", () => {
document.delete();
file.delete();
});
- */
});
diff --git a/tests/bindings/javascript/solver.secondorderrungekutta.test.js b/tests/bindings/javascript/solver.secondorderrungekutta.test.js
index 1f08ee9ae..db8404028 100644
--- a/tests/bindings/javascript/solver.secondorderrungekutta.test.js
+++ b/tests/bindings/javascript/solver.secondorderrungekutta.test.js
@@ -75,14 +75,26 @@ describe("Solver Second-Order Runge-Kutta tests", () => {
odeModel.run(
document,
- [-63.886525, 0.135009, 0.984334, 0.740971],
- [49.725722, -0.128194, -0.050903, 0.098651],
- [1.0, 0.0, 0.3, 120.0, 36.0],
- [-10.613, -115.0, 12.0],
[
- 0.0, -15.982058, -823.516942, 789.779614, 3.969929, 0.114985, 0.00287,
- 0.967348, 0.541338, 0.056246,
+ -63.88652516147998, 0.13500864016199698, 0.9843341849003562,
+ 0.7409712245332702,
],
+ [7, 7, 7, 7],
+ [
+ 49.725721814665114, -0.12819399753080235, -0.0509025737713709,
+ 0.09865110169688351,
+ ],
+ [7, 7, 7, 7],
+ [1, 0, 0.3, 120, 36],
+ [7, 7, 7, 7, 7],
+ [-10.613, -115, 12],
+ [7, 7, 7],
+ [
+ 0, -15.982057548443994, -823.5169415955212, 789.7796140225834,
+ 3.969928522897354, 0.11498460412672941, 0.0028695894879267065,
+ 0.9673480100796346, 0.5413381517778336, 0.056245845061545056,
+ ],
+ [7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
);
solver.delete();
diff --git a/tests/bindings/javascript/utils.js.in b/tests/bindings/javascript/utils.js.in
index 66adef441..84291582b 100644
--- a/tests/bindings/javascript/utils.js.in
+++ b/tests/bindings/javascript/utils.js.in
@@ -105,6 +105,7 @@ export const SOLVER_NLA2_CONTENTS = stringToArrayBuffer(
export const ALGEBRAIC_CONTENTS = stringToArrayBuffer(`@ALGEBRAIC_CONTENTS@`);
export const DAE_CONTENTS = stringToArrayBuffer(`@DAE_CONTENTS@`);
+export const MATH_CONTENTS = stringToArrayBuffer(`@MATH_CONTENTS@`);
export const NLA_CONTENTS = stringToArrayBuffer(`@NLA_CONTENTS@`);
export const OVERCONSTRAINED_CONTENTS = stringToArrayBuffer(
@@ -151,41 +152,67 @@ export function expectIssues(loc, logger, expectedIssues) {
}
}
+function expectValue(value, expectedValue, precision) {
+ if (expectedValue === Infinity) {
+ expect(value).toBe(Infinity);
+ } else if (Number.isNaN(expectedValue)) {
+ expect(Number.isNaN(value)).toBe(true);
+ } else {
+ expect(value).toBeCloseTo(expectedValue, precision);
+ }
+}
+
export function expectValues(
instanceTask,
index,
stateValues,
+ statePrecisions,
rateValues,
+ ratePrecisions,
constantValues,
+ constantPrecisions,
computedConstantValues,
+ computedConstantPrecisions,
algebraicValues,
+ algebraicPrecisions,
) {
for (let i = 0; i < instanceTask.stateCount; ++i) {
- expect(instanceTask.stateAsArray(i)[index]).toBeCloseTo(stateValues[i], 6);
+ expectValue(
+ instanceTask.stateAsArray(i)[index],
+ stateValues[i],
+ statePrecisions[i],
+ );
}
for (let i = 0; i < instanceTask.rateCount; ++i) {
- expect(instanceTask.rateAsArray(i)[index]).toBeCloseTo(rateValues[i], 6);
+ expectValue(
+ instanceTask.rateAsArray(i)[index],
+ rateValues[i],
+ ratePrecisions[i],
+ );
}
for (let i = 0; i < instanceTask.constantCount; ++i) {
- expect(instanceTask.constantAsArray(i)[index]).toBeCloseTo(
+ expectValue(
+ instanceTask.constantAsArray(i)[index],
constantValues[i],
- 6,
+ constantPrecisions[i],
);
}
for (let i = 0; i < instanceTask.computedConstantCount; ++i) {
- expect(instanceTask.computedConstantAsArray(i)[index]).toBeCloseTo(
+ expectValue(
+ instanceTask.computedConstantAsArray(i)[index],
computedConstantValues[i],
- 6,
+ computedConstantPrecisions[i],
);
}
for (let i = 0; i < instanceTask.algebraicCount; ++i) {
- expect(instanceTask.algebraicAsArray(i)[index]).toBeCloseTo(
+ expectValue(
+ instanceTask.algebraicAsArray(i)[index],
algebraicValues[i],
- 6,
+ algebraicPrecisions[i],
);
}
}
diff --git a/tests/bindings/python/ode_model.py b/tests/bindings/python/ode_model.py
index 1093b34cb..9f9b3c925 100644
--- a/tests/bindings/python/ode_model.py
+++ b/tests/bindings/python/ode_model.py
@@ -28,14 +28,13 @@ def run(
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- compiled=True,
):
simulation = document.simulations[0]
simulation.output_end_time = 50.0
simulation.number_of_steps = 50000
- instance = document.instantiate(compiled)
+ instance = document.instantiate()
instance.run()
diff --git a/tests/bindings/python/test_sed_coverage.py b/tests/bindings/python/test_sed_coverage.py
index 1df010de3..0ff724e36 100644
--- a/tests/bindings/python/test_sed_coverage.py
+++ b/tests/bindings/python/test_sed_coverage.py
@@ -14,8 +14,9 @@
import libopencor as loc
+import math
import utils
-from utils import assert_issues
+from utils import assert_issues, assert_values
def test_initialise():
@@ -503,3 +504,110 @@ def test_solver():
instance.run()
assert instance.has_issues == False
+
+
+def test_math():
+ computed_constant_values = [
+ 243.0,
+ 3.0,
+ 7.0,
+ 20.085536923187668,
+ 1.0986122886681098,
+ 0.47712125471966244,
+ 4.0,
+ 3.0,
+ 3.0,
+ 5.0,
+ 3.0,
+ 0.14112000805986721,
+ -0.98999249660044542,
+ -0.1425465430742778,
+ -1.0101086659079939,
+ 7.0861673957371867,
+ -7.0152525514345339,
+ 10.017874927409903,
+ 10.067661995777765,
+ 0.99505475368673046,
+ 0.099327927419433207,
+ 0.099821569668822732,
+ 1.0049698233136892,
+ 0.3046926540153975,
+ 1.266103672779499,
+ 1.2490457723982544,
+ 1.2309594173407747,
+ 0.33983690945412193,
+ 0.32175055439664219,
+ 1.8184464592320668,
+ 1.7627471740390861,
+ 0.30951960420311175,
+ 1.8738202425274144,
+ 0.32745015023725843,
+ 0.34657359027997264,
+ math.inf,
+ math.nan,
+ ]
+ computed_constant_abs_tols = [
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ 0.0000001,
+ ]
+
+ file = loc.File(utils.resource_path("api/sed/math.cellml"))
+ document = loc.SedDocument(file)
+ instance = document.instantiate()
+ instance_task = instance.tasks[0]
+
+ assert instance_task.constant_count == 0
+ assert instance_task.computed_constant_count == 37
+ assert instance_task.algebraic_count == 0
+
+ instance.run()
+
+ assert_values(
+ instance_task,
+ 0,
+ [],
+ [],
+ [],
+ [],
+ [],
+ [],
+ computed_constant_values,
+ computed_constant_abs_tols,
+ [],
+ [],
+ )
diff --git a/tests/bindings/python/test_sed_instance.py b/tests/bindings/python/test_sed_instance.py
index 66c5c25fc..2b70228eb 100644
--- a/tests/bindings/python/test_sed_instance.py
+++ b/tests/bindings/python/test_sed_instance.py
@@ -113,34 +113,26 @@ def test_unsuitable_constrained_cellml_file():
assert_issues(instance, expected_issues)
-def run_algebraic_model(compiled):
+def run_algebraic_model():
file = loc.File(utils.resource_path("api/sed/algebraic.cellml"))
document = loc.SedDocument(file)
- instance = document.instantiate(compiled)
+ instance = document.instantiate()
instance.run()
assert instance.has_issues == False
-def test_compiled_algebraic_model():
- run_algebraic_model(True)
-
-
-def test_interpreted_algebraic_model():
- run_algebraic_model(False)
+def test_algebraic_model():
+ run_algebraic_model()
-def run_ode_model(compiled):
+def run_ode_model():
expected_issues = [
[
loc.Issue.Type.Error,
(
- (
- "At t = 0.00140013827899707, mxstep steps taken before reaching tout."
- if compiled
- else "At t = 0.00140013827900052, mxstep steps taken before reaching tout."
- )
+ "At t = 0.00140013827899707, mxstep steps taken before reaching tout."
if platform.system() == "Darwin"
else "At t = 0.00140013827899996, mxstep steps taken before reaching tout."
),
@@ -154,7 +146,7 @@ def run_ode_model(compiled):
cvode.maximum_number_of_steps = 10
- instance = document.instantiate(compiled)
+ instance = document.instantiate()
assert instance.has_issues == False
@@ -164,19 +156,15 @@ def run_ode_model(compiled):
cvode.maximum_number_of_steps = 500
- instance = document.instantiate(compiled)
+ instance = document.instantiate()
instance.run()
assert instance.has_issues == False
-def test_compiled_ode_model():
- run_ode_model(True)
-
-
-def test_interpreted_ode_model():
- run_ode_model(False)
+def test_ode_model():
+ run_ode_model()
def test_ode_model_with_no_ode_solver():
@@ -198,8 +186,6 @@ def test_ode_model_with_no_ode_solver():
def test_nla_model():
- # ---GRY--- AS FOR THE ALGEBRAIC AND ODE MODELS, WE WILL NEED TO ADD AN INTERPRETED VERSION OF THIS TEST.
-
expected_issues = [
[
loc.Issue.Type.Error,
@@ -245,8 +231,6 @@ def test_nla_model_with_no_nla_solver():
def test_dae_model():
- # ---GRY--- AS FOR THE ALGEBRAIC AND ODE MODELS, WE WILL NEED TO ADD AN INTERPRETED VERSION OF THIS TEST.
-
expected_issues = [
[
loc.Issue.Type.Error,
diff --git a/tests/bindings/python/test_solver_cvode.py b/tests/bindings/python/test_solver_cvode.py
index 7cb2dc43e..81c882392 100644
--- a/tests/bindings/python/test_solver_cvode.py
+++ b/tests/bindings/python/test_solver_cvode.py
@@ -195,7 +195,6 @@ def cvode_solve(
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- compiled,
):
file = loc.File(utils.resource_path("api/solver/ode.cellml"))
document = loc.SedDocument(file)
@@ -212,11 +211,10 @@ def cvode_solve(
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- compiled,
)
-def test_compiled_solve():
+def test_solve():
state_values = [-63.886, 0.135007, 0.984333, 0.740973]
state_abs_tols = [0.001, 0.000001, 0.000001, 0.000001]
rate_values = [49.726, -0.128192, -0.050904, 0.098649]
@@ -261,56 +259,6 @@ def test_compiled_solve():
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- True,
- )
-
-
-def test_interpreted_solve():
- state_values = [-63.886, 0.135008, 0.984333, 0.740972]
- state_abs_tols = [0.001, 0.000001, 0.000001, 0.000001]
- rate_values = [49.726, -0.128193, -0.05090, 0.09865]
- rate_abs_tols = [0.001, 0.000001, 0.00001, 0.00001]
- constant_values = [1.0, 0.0, 0.3, 120.0, 36.0]
- constant_abs_tols = [0.0, 0.0, 0.0, 0.0, 0.0]
- computed_constant_values = [-10.613, -115.0, 12.0]
- computed_constant_abs_tols = [0.0, 0.0, 0.0]
- algebraic_values = [
- 0.0,
- -15.9819,
- -823.517,
- 789.779,
- 3.9699,
- 0.11499,
- 0.002869,
- 0.967347,
- 0.54133,
- 0.056246,
- ]
- algebraic_abs_tols = [
- 0.0,
- 0.0001,
- 0.001,
- 0.001,
- 0.0001,
- 0.00001,
- 0.000001,
- 0.000001,
- 0.00001,
- 0.000001,
- ]
-
- cvode_solve(
- state_values,
- state_abs_tols,
- rate_values,
- rate_abs_tols,
- constant_values,
- constant_abs_tols,
- computed_constant_values,
- computed_constant_abs_tols,
- algebraic_values,
- algebraic_abs_tols,
- False,
)
diff --git a/tests/bindings/python/test_solver_forwardeuler.py b/tests/bindings/python/test_solver_forwardeuler.py
index fda196bfc..a1d57a3e1 100644
--- a/tests/bindings/python/test_solver_forwardeuler.py
+++ b/tests/bindings/python/test_solver_forwardeuler.py
@@ -54,7 +54,6 @@ def forward_euler_solve(
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- compiled,
):
file = loc.File(utils.resource_path("api/solver/ode.cellml"))
document = loc.SedDocument(file)
@@ -77,7 +76,6 @@ def forward_euler_solve(
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- compiled,
)
@@ -115,7 +113,7 @@ def forward_euler_solve(
]
-def test_compiled_solve():
+def test_solve():
forward_euler_solve(
state_values,
state_abs_tols,
@@ -127,21 +125,4 @@ def test_compiled_solve():
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- True,
- )
-
-
-def test_interpreted_solve():
- forward_euler_solve(
- state_values,
- state_abs_tols,
- rate_values,
- rate_abs_tols,
- constant_values,
- constant_abs_tols,
- computed_constant_values,
- computed_constant_abs_tols,
- algebraic_values,
- algebraic_abs_tols,
- False,
)
diff --git a/tests/bindings/python/test_solver_fourthorderrungekutta.py b/tests/bindings/python/test_solver_fourthorderrungekutta.py
index b145fc427..e987d9463 100644
--- a/tests/bindings/python/test_solver_fourthorderrungekutta.py
+++ b/tests/bindings/python/test_solver_fourthorderrungekutta.py
@@ -54,7 +54,6 @@ def fourth_order_runge_kutta_solve(
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- compiled,
):
file = loc.File(utils.resource_path("api/solver/ode.cellml"))
document = loc.SedDocument(file)
@@ -77,7 +76,6 @@ def fourth_order_runge_kutta_solve(
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- compiled,
)
@@ -115,7 +113,7 @@ def fourth_order_runge_kutta_solve(
]
-def test_compiled_solve():
+def test_solve():
fourth_order_runge_kutta_solve(
state_values,
state_abs_tols,
@@ -127,21 +125,4 @@ def test_compiled_solve():
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- True,
- )
-
-
-def test_interpreted_solve():
- fourth_order_runge_kutta_solve(
- state_values,
- state_abs_tols,
- rate_values,
- rate_abs_tols,
- constant_values,
- constant_abs_tols,
- computed_constant_values,
- computed_constant_abs_tols,
- algebraic_values,
- algebraic_abs_tols,
- False,
)
diff --git a/tests/bindings/python/test_solver_heun.py b/tests/bindings/python/test_solver_heun.py
index c4107b936..c3d4cffb2 100644
--- a/tests/bindings/python/test_solver_heun.py
+++ b/tests/bindings/python/test_solver_heun.py
@@ -54,7 +54,6 @@ def heun_solve(
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- compiled,
):
file = loc.File(utils.resource_path("api/solver/ode.cellml"))
document = loc.SedDocument(file)
@@ -77,7 +76,6 @@ def heun_solve(
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- compiled,
)
@@ -115,7 +113,7 @@ def heun_solve(
]
-def test_compiled_solve():
+def test_solve():
heun_solve(
state_values,
state_abs_tols,
@@ -127,21 +125,4 @@ def test_compiled_solve():
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- True,
- )
-
-
-def test_interpreted_solve():
- heun_solve(
- state_values,
- state_abs_tols,
- rate_values,
- rate_abs_tols,
- constant_values,
- constant_abs_tols,
- computed_constant_values,
- computed_constant_abs_tols,
- algebraic_values,
- algebraic_abs_tols,
- False,
)
diff --git a/tests/bindings/python/test_solver_kinsol.py b/tests/bindings/python/test_solver_kinsol.py
index 7a6892ba3..5aeb25fac 100644
--- a/tests/bindings/python/test_solver_kinsol.py
+++ b/tests/bindings/python/test_solver_kinsol.py
@@ -124,10 +124,6 @@ def test_banded_linear_solver_and_lower_half_bandwidth_value_with_number_too_big
assert_issues(instance, expected_issues)
-# ---GRY--- RENAME THIS TEST test_compiled_solve AND CREATE ONE CALLED test_interpreted_solve ONCE WE CAN INTERPRET
-# NLA-BASED MODELS.
-
-
ABS_TOL = 1e-05
diff --git a/tests/bindings/python/test_solver_secondorderrungekutta.py b/tests/bindings/python/test_solver_secondorderrungekutta.py
index 1f17a5070..fb8c4c31a 100644
--- a/tests/bindings/python/test_solver_secondorderrungekutta.py
+++ b/tests/bindings/python/test_solver_secondorderrungekutta.py
@@ -54,7 +54,6 @@ def second_order_runge_kutta_solve(
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- compiled,
):
file = loc.File(utils.resource_path("api/solver/ode.cellml"))
document = loc.SedDocument(file)
@@ -77,7 +76,6 @@ def second_order_runge_kutta_solve(
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- compiled,
)
@@ -115,7 +113,7 @@ def second_order_runge_kutta_solve(
]
-def test_compiled_solve():
+def test_solve():
second_order_runge_kutta_solve(
state_values,
state_abs_tols,
@@ -127,21 +125,4 @@ def test_compiled_solve():
computed_constant_abs_tols,
algebraic_values,
algebraic_abs_tols,
- True,
- )
-
-
-def test_interpreted_solve():
- second_order_runge_kutta_solve(
- state_values,
- state_abs_tols,
- rate_values,
- rate_abs_tols,
- constant_values,
- constant_abs_tols,
- computed_constant_values,
- computed_constant_abs_tols,
- algebraic_values,
- algebraic_abs_tols,
- False,
)
diff --git a/tests/bindings/python/utils.py.in b/tests/bindings/python/utils.py.in
index c217a6643..314122f36 100644
--- a/tests/bindings/python/utils.py.in
+++ b/tests/bindings/python/utils.py.in
@@ -15,6 +15,7 @@
import base64
import libopencor as loc
+import math
import os
import pathlib
import platform
@@ -79,6 +80,15 @@ def assert_issues(logger, expected_issues):
assert issues[i].type_as_string == "Warning"
+def assert_value(value, expected_value, abs_tol):
+ if math.isinf(expected_value):
+ assert math.isinf(value) is True
+ elif math.isnan(expected_value):
+ assert math.isnan(value) is True
+ else:
+ assert value == pytest.approx(expected_value, abs=abs_tol)
+
+
def assert_values(
instance_task,
index,
@@ -94,28 +104,30 @@ def assert_values(
algebraic_abs_tols,
):
for i in range(instance_task.state_count):
- assert instance_task.state(i)[index] == pytest.approx(
- state_values[i], abs=state_abs_tols[i]
- )
+ assert_value(instance_task.state(i)[index], state_values[i], state_abs_tols[i])
for i in range(instance_task.rate_count):
- assert instance_task.rate(i)[index] == pytest.approx(
- rate_values[i], abs=rate_abs_tols[i]
- )
+ assert_value(instance_task.rate(i)[index], rate_values[i], rate_abs_tols[i])
for i in range(instance_task.constant_count):
- assert instance_task.constant(i)[index] == pytest.approx(
- constant_values[i], abs=constant_abs_tols[i]
+ assert_value(
+ instance_task.constant(i)[index],
+ constant_values[i],
+ constant_abs_tols[i],
)
for i in range(instance_task.computed_constant_count):
- assert instance_task.computed_constant(i)[index] == pytest.approx(
- computed_constant_values[i], abs=computed_constant_abs_tols[i]
+ assert_value(
+ instance_task.computed_constant(i)[index],
+ computed_constant_values[i],
+ computed_constant_abs_tols[i],
)
for i in range(instance_task.algebraic_count):
- assert instance_task.algebraic(i)[index] == pytest.approx(
- algebraic_values[i], abs=algebraic_abs_tols[i]
+ assert_value(
+ instance_task.algebraic(i)[index],
+ algebraic_values[i],
+ algebraic_abs_tols[i],
)
diff --git a/tests/install/src/main.cpp b/tests/install/src/main.cpp
index 38e478b30..0735a673c 100644
--- a/tests/install/src/main.cpp
+++ b/tests/install/src/main.cpp
@@ -5,10 +5,10 @@ int main()
{
// Output the version of libOpenCOR.
- std::cout << "---[ libOpenCOR version information ]---" << std::endl;
- std::cout << std::endl;
- std::cout << "Version: " << libOpenCOR::version() << std::endl;
- std::cout << "Version string: " << libOpenCOR::versionString() << std::endl;
+ std::cout << "---[ libOpenCOR version information ]---\n";
+ std::cout << "\n";
+ std::cout << "Version: " << libOpenCOR::version() << "\n";
+ std::cout << "Version string: " << libOpenCOR::versionString() << "\n";
// Load a COMBINE archive from GitHub and output some information about it.
@@ -25,21 +25,21 @@ int main()
auto instanceTask = instance->tasks()[0];
- std::cout << std::endl;
- std::cout << "---[ File information ]---" << std::endl;
- std::cout << std::endl;
- std::cout << "URL: " << file->url() << std::endl;
- std::cout << "Number of:" << std::endl;
- std::cout << " - States and rates: " << instanceTask->stateCount() << std::endl;
- std::cout << " - Constants: " << instanceTask->constantCount() << std::endl;
- std::cout << " - Computed constants: " << instanceTask->computedConstantCount() << std::endl;
- std::cout << " - Algebraic variables: " << instanceTask->algebraicCount() << std::endl;
+ std::cout << "\n";
+ std::cout << "---[ File information ]---\n";
+ std::cout << "\n";
+ std::cout << "URL: " << file->url() << "\n";
+ std::cout << "Number of:\n";
+ std::cout << " - States and rates: " << instanceTask->stateCount() << "\n";
+ std::cout << " - Constants: " << instanceTask->constantCount() << "\n";
+ std::cout << " - Computed constants: " << instanceTask->computedConstantCount() << "\n";
+ std::cout << " - Algebraic variables: " << instanceTask->algebraicCount() << "\n";
// Output the results of the simulation.
- std::cout << std::endl;
- std::cout << "---[ Simulation results ]---" << std::endl;
- std::cout << std::endl;
+ std::cout << "\n";
+ std::cout << "---[ Simulation results ]---\n";
+ std::cout << "\n";
std::cout << instanceTask->voiName() << " (" << instanceTask->voiUnit() << ")";
for (size_t i = 0; i < instanceTask->stateCount(); ++i) {
@@ -62,7 +62,7 @@ int main()
std::cout << "," << instanceTask->algebraicName(i) << " (" << instanceTask->algebraicUnit(i) << ")";
}
- std::cout << std::endl;
+ std::cout << "\n";
for (size_t j = 0; j < instanceTask->voi().size(); ++j) {
std::cout << instanceTask->voi()[j];
@@ -87,7 +87,7 @@ int main()
std::cout << "," << instanceTask->algebraic(i)[j];
}
- std::cout << std::endl;
+ std::cout << "\n";
}
return 0;
diff --git a/tests/res/api/sed/math.cellml b/tests/res/api/sed/math.cellml
new file mode 100644
index 000000000..f799076b4
--- /dev/null
+++ b/tests/res/api/sed/math.cellml
@@ -0,0 +1,343 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/utils.cpp b/tests/utils.cpp
index 38ac39af6..da21c8726 100644
--- a/tests/utils.cpp
+++ b/tests/utils.cpp
@@ -20,26 +20,12 @@ limitations under the License.
#include "../extern/modp_b64/modp_b64.h"
+#include
#include
#include
namespace libOpenCOR {
-void printIssues(const LoggerPtr &pLogger)
-{
- printf("---[ISSUES]---[BEGIN]\n"); // NOLINT
-
- for (auto &issue : pLogger->issues()) {
- const auto *type = (issue->type() == Issue::Type::ERROR) ?
- "ERROR" :
- "WARNING";
-
- printf("%s: %s\n", type, issue->description().c_str()); // NOLINT
- }
-
- printf("---[ISSUES]---[END]\n"); // NOLINT
-}
-
void expectEqualIssues(const LoggerPtr &pLogger, const ExpectedIssues &pExpectedIssues)
{
auto issues = pLogger->issues();
@@ -58,6 +44,21 @@ void expectEqualIssues(const LoggerPtr &pLogger, const ExpectedIssues &pExpected
}
}
+namespace {
+
+void expectEqualValue(double pValue, double pExpectedValue, double pAbsTol)
+{
+ if (std::isinf(pExpectedValue)) {
+ EXPECT_TRUE(std::isinf(pValue));
+ } else if (std::isnan(pExpectedValue)) {
+ EXPECT_TRUE(std::isnan(pValue));
+ } else {
+ EXPECT_NEAR(pValue, pExpectedValue, pAbsTol);
+ }
+}
+
+} // namespace
+
void expectEqualValues(const SedInstanceTaskPtr &pInstanceTask, size_t pIndex,
const Doubles &pStateValues, const Doubles &pStateAbsTols,
const Doubles &pRateValues, const Doubles &pRateAbsTols,
@@ -66,23 +67,23 @@ void expectEqualValues(const SedInstanceTaskPtr &pInstanceTask, size_t pIndex,
const Doubles &pAlgebraicValues, const Doubles &pAlgebraicAbsTols)
{
for (size_t i = 0; i < pInstanceTask->stateCount(); ++i) {
- EXPECT_NEAR(pInstanceTask->state(i)[pIndex], pStateValues[i], pStateAbsTols[i]);
+ expectEqualValue(pInstanceTask->state(i)[pIndex], pStateValues[i], pStateAbsTols[i]);
}
for (size_t i = 0; i < pInstanceTask->rateCount(); ++i) {
- EXPECT_NEAR(pInstanceTask->rate(i)[pIndex], pRateValues[i], pRateAbsTols[i]);
+ expectEqualValue(pInstanceTask->rate(i)[pIndex], pRateValues[i], pRateAbsTols[i]);
}
for (size_t i = 0; i < pInstanceTask->constantCount(); ++i) {
- EXPECT_NEAR(pInstanceTask->constant(i)[pIndex], pConstantValues[i], pConstantAbsTols[i]);
+ expectEqualValue(pInstanceTask->constant(i)[pIndex], pConstantValues[i], pConstantAbsTols[i]);
}
for (size_t i = 0; i < pInstanceTask->computedConstantCount(); ++i) {
- EXPECT_NEAR(pInstanceTask->computedConstant(i)[pIndex], pComputedConstantValues[i], pComputedConstantAbsTols[i]);
+ expectEqualValue(pInstanceTask->computedConstant(i)[pIndex], pComputedConstantValues[i], pComputedConstantAbsTols[i]);
}
for (size_t i = 0; i < pInstanceTask->algebraicCount(); ++i) {
- EXPECT_NEAR(pInstanceTask->algebraic(i)[pIndex], pAlgebraicValues[i], pAlgebraicAbsTols[i]);
+ expectEqualValue(pInstanceTask->algebraic(i)[pIndex], pAlgebraicValues[i], pAlgebraicAbsTols[i]);
}
}
diff --git a/tests/utils.h.in b/tests/utils.h.in
index ef1e6edd7..2b117f78f 100644
--- a/tests/utils.h.in
+++ b/tests/utils.h.in
@@ -66,8 +66,6 @@ static constexpr auto WARNING_CELLML_CONTENTS = "@WARNING_CELLML_CONTENTS_C@";
static constexpr auto SEDML_CONTENTS = "@SEDML_CONTENTS_C@";
static constexpr auto BASE64_COMBINE_ARCHIVE_CONTENTS = "@BASE64_COMBINE_ARCHIVE_CONTENTS@";
-void printIssues(const LoggerPtr &pLogger);
-
typedef struct
{
Issue::Type type;