diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..1ff70c2dec --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +tests/cpp/expected_results_py.h5 filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/test_python_cplusplus.yml b/.github/workflows/test_python_cplusplus.yml index bd049e663c..a74c05f29c 100644 --- a/.github/workflows/test_python_cplusplus.yml +++ b/.github/workflows/test_python_cplusplus.yml @@ -32,6 +32,8 @@ jobs: python-version: ${{ matrix.python-version }} - uses: actions/checkout@v4 + with: + lfs: true - run: git fetch --prune --unshallow - run: echo "AMICI_DIR=$(pwd)" >> $GITHUB_ENV @@ -253,6 +255,9 @@ jobs: python-version: "3.11" - uses: actions/checkout@v4 + with: + lfs: true + - run: git fetch --prune --unshallow - name: Install dependencies @@ -315,6 +320,8 @@ jobs: python-version: "3.11" - uses: actions/checkout@v4 + with: + lfs: true - run: git fetch --prune --unshallow - name: Install dependencies diff --git a/.github/workflows/test_python_ver_matrix.yml b/.github/workflows/test_python_ver_matrix.yml index fc1f6888e5..9897ed9184 100644 --- a/.github/workflows/test_python_ver_matrix.yml +++ b/.github/workflows/test_python_ver_matrix.yml @@ -38,6 +38,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 20 + lfs: true - name: Install apt dependencies uses: ./.github/actions/install-apt-dependencies diff --git a/.github/workflows/test_windows.yml b/.github/workflows/test_windows.yml index bc478fc055..5b93e5a0dc 100644 --- a/.github/workflows/test_windows.yml +++ b/.github/workflows/test_windows.yml @@ -32,6 +32,8 @@ jobs: python-version: ${{ matrix.python-version }} - uses: actions/checkout@v4 + with: + lfs: true - run: git fetch --prune --unshallow - shell: bash diff --git a/models/model_calvetti_py/.gitignore b/models/model_calvetti_py/.gitignore new file mode 100644 index 0000000000..fa29cdfff9 --- /dev/null +++ b/models/model_calvetti_py/.gitignore @@ -0,0 +1 @@ +** \ No newline at end of file diff --git a/models/model_calvetti_py/CMakeLists.txt b/models/model_calvetti_py/CMakeLists.txt new file mode 100644 index 0000000000..f7a3f39f4f --- /dev/null +++ b/models/model_calvetti_py/CMakeLists.txt @@ -0,0 +1,151 @@ +# Build AMICI model +cmake_minimum_required(VERSION 3.22) +cmake_policy(VERSION 3.22...3.31) + +project(model_calvetti_py) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +include(CheckCXXCompilerFlag) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() +foreach(flag ${MY_CXX_FLAGS}) + unset(CUR_FLAG_SUPPORTED CACHE) + check_cxx_compiler_flag(${flag} CUR_FLAG_SUPPORTED) + if(${CUR_FLAG_SUPPORTED}) + string(APPEND CMAKE_CXX_FLAGS " ${flag}") + endif() +endforeach() + +if(DEFINED ENV{AMICI_CXXFLAGS}) + message(STATUS "Appending flags from AMICI_CXXFLAGS: $ENV{AMICI_CXXFLAGS}") + add_compile_options("$ENV{AMICI_CXXFLAGS}") +endif() +if(DEFINED ENV{AMICI_LDFLAGS}) + message(STATUS "Appending flags from AMICI_LDFLAGS: $ENV{AMICI_LDFLAGS}") + link_libraries("$ENV{AMICI_LDFLAGS}") +endif() + +find_package(Amici 0.33.0 REQUIRED HINTS + ${CMAKE_CURRENT_LIST_DIR}/../../build) +message(STATUS "Found AMICI ${Amici_DIR}") +set_target_properties(Upstream::amici PROPERTIES + MAP_IMPORTED_CONFIG_RELWITHDEBINFO RelWithDebInfo;Release; + MAP_IMPORTED_CONFIG_RELEASE Release + MAP_IMPORTED_CONFIG_DEBUG Debug;RelWithDebInfo;) + +# Debug build? +if("$ENV{ENABLE_AMICI_DEBUGGING}" OR "$ENV{ENABLE_GCOV_COVERAGE}") + add_compile_options(-UNDEBUG) + if(MSVC) + add_compile_options(-DEBUG) + else() + add_compile_options(-O0 -g) + endif() +endif() + +# coverage options +if($ENV{ENABLE_GCOV_COVERAGE}) + string(APPEND CMAKE_CXX_FLAGS_DEBUG " --coverage") + string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " --coverage") +endif() + +set(MODEL_DIR ${CMAKE_CURRENT_LIST_DIR}) + +set(SRC_LIST_LIB Jy.cpp +Jy.h +create_splines.cpp +dJydsigma.cpp +dJydy.cpp +dJydy.h +dwdw.cpp +dwdw.h +dwdx.cpp +dwdx.h +dx.h +dxdotdw.cpp +dxdotdw.h +dxdotdx_explicit.cpp +dxdotdx_explicit.h +dydx.cpp +h.h +k.h +model_calvetti_py.cpp +model_calvetti_py.h +my.h +root.cpp +sigmay.cpp +sigmay.h +sx.h +w.cpp +w.h +wrapfunctions.cpp +wrapfunctions.h +x.h +x0.cpp +x0_fixedParameters.cpp +xB.h +x_old.h +x_rdata.cpp +x_rdata.h +x_solver.cpp +x_solver.h +xdot.cpp +xdot.h +xdot_old.h +y.cpp +y.h ${MODEL_DIR}/wrapfunctions.cpp) + +add_library(${PROJECT_NAME} ${SRC_LIST_LIB}) + +# ${PROJECT_NAME} might already be "model" +if(NOT TARGET model) + add_library(model ALIAS ${PROJECT_NAME}) +endif() + +# Some special functions require boost +# +# TODO: set some flag during code generation whether the given model requires +# boost. for now, try to find it, add include directories and link against it. +# let the compiler/linker error if it is required but not found +find_package(Boost) + +target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") + +target_link_libraries( + ${PROJECT_NAME} + PUBLIC Upstream::amici + PRIVATE $<$:Boost::boost>) + +if(NOT "${AMICI_PYTHON_BUILD_EXT_ONLY}") + set(SRC_LIST_EXE main.cpp) + add_executable(simulate_${PROJECT_NAME} ${SRC_LIST_EXE}) + target_link_libraries(simulate_${PROJECT_NAME} ${PROJECT_NAME}) +endif() + +# SWIG +option(ENABLE_SWIG "Build swig/python library?" ON) +if(ENABLE_SWIG) + add_subdirectory(swig) +endif() + +# +include(GNUInstallDirs) +install( + TARGETS ${PROJECT_NAME} + EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +export( + EXPORT ${PROJECT_NAME}Targets + FILE ${PROJECT_NAME}Config.cmake + NAMESPACE Upstream::) +# diff --git a/models/model_calvetti_py/Jy.cpp b/models/model_calvetti_py/Jy.cpp new file mode 100644 index 0000000000..e4d9de870e --- /dev/null +++ b/models/model_calvetti_py/Jy.cpp @@ -0,0 +1,40 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_calvetti_py { + +void Jy_model_calvetti_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_V1, 2)) + 0.5*std::pow(-mobs_V1 + obs_V1, 2)/std::pow(sigma_obs_V1, 2); + break; + case 1: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_V2, 2)) + 0.5*std::pow(-mobs_V2 + obs_V2, 2)/std::pow(sigma_obs_V2, 2); + break; + case 2: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_V3, 2)) + 0.5*std::pow(-mobs_V3 + obs_V3, 2)/std::pow(sigma_obs_V3, 2); + break; + case 3: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_f0, 2)) + 0.5*std::pow(-mobs_f0 + obs_f0, 2)/std::pow(sigma_obs_f0, 2); + break; + case 4: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_f1, 2)) + 0.5*std::pow(-mobs_f1 + obs_f1, 2)/std::pow(sigma_obs_f1, 2); + break; + case 5: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_f2, 2)) + 0.5*std::pow(-mobs_f2 + obs_f2, 2)/std::pow(sigma_obs_f2, 2); + break; + } +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/Jy.h b/models/model_calvetti_py/Jy.h new file mode 100644 index 0000000000..23b4923f4c --- /dev/null +++ b/models/model_calvetti_py/Jy.h @@ -0,0 +1,6 @@ +#define Jy0 Jy[0] +#define Jy1 Jy[1] +#define Jy2 Jy[2] +#define Jy3 Jy[3] +#define Jy4 Jy[4] +#define Jy5 Jy[5] diff --git a/models/model_calvetti_py/MANIFEST.in b/models/model_calvetti_py/MANIFEST.in new file mode 100644 index 0000000000..fd78129853 --- /dev/null +++ b/models/model_calvetti_py/MANIFEST.in @@ -0,0 +1,3 @@ +include *.cpp *.h +include CMakeLists.txt +recursive-include swig/ * diff --git a/models/model_calvetti_py/create_splines.cpp b/models/model_calvetti_py/create_splines.cpp new file mode 100644 index 0000000000..9fc045d4c0 --- /dev/null +++ b/models/model_calvetti_py/create_splines.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "amici/splinefunctions.h" +#include +#include "k.h" + +namespace amici { +namespace model_model_calvetti_py { + +std::vector create_splines_model_calvetti_py(const realtype *p, const realtype *k){ + return {}; +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/dJydsigma.cpp b/models/model_calvetti_py/dJydsigma.cpp new file mode 100644 index 0000000000..91f8fdd2fd --- /dev/null +++ b/models/model_calvetti_py/dJydsigma.cpp @@ -0,0 +1,40 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_calvetti_py { + +void dJydsigma_model_calvetti_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydsigma[0] = 1.0/sigma_obs_V1 - 1.0*std::pow(-mobs_V1 + obs_V1, 2)/std::pow(sigma_obs_V1, 3); + break; + case 1: + dJydsigma[1] = 1.0/sigma_obs_V2 - 1.0*std::pow(-mobs_V2 + obs_V2, 2)/std::pow(sigma_obs_V2, 3); + break; + case 2: + dJydsigma[2] = 1.0/sigma_obs_V3 - 1.0*std::pow(-mobs_V3 + obs_V3, 2)/std::pow(sigma_obs_V3, 3); + break; + case 3: + dJydsigma[3] = 1.0/sigma_obs_f0 - 1.0*std::pow(-mobs_f0 + obs_f0, 2)/std::pow(sigma_obs_f0, 3); + break; + case 4: + dJydsigma[4] = 1.0/sigma_obs_f1 - 1.0*std::pow(-mobs_f1 + obs_f1, 2)/std::pow(sigma_obs_f1, 3); + break; + case 5: + dJydsigma[5] = 1.0/sigma_obs_f2 - 1.0*std::pow(-mobs_f2 + obs_f2, 2)/std::pow(sigma_obs_f2, 3); + break; + } +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/dJydy.cpp b/models/model_calvetti_py/dJydy.cpp new file mode 100644 index 0000000000..f6983dfe23 --- /dev/null +++ b/models/model_calvetti_py/dJydy.cpp @@ -0,0 +1,92 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_calvetti_py { + +static constexpr std::array, 6> dJydy_colptrs_model_calvetti_py_ = {{ + {0, 1, 1, 1, 1, 1, 1}, + {0, 0, 1, 1, 1, 1, 1}, + {0, 0, 0, 1, 1, 1, 1}, + {0, 0, 0, 0, 1, 1, 1}, + {0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 1}, +}}; + +void dJydy_colptrs_model_calvetti_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexptrs(gsl::make_span(dJydy_colptrs_model_calvetti_py_[index])); +} +} // namespace model_model_calvetti_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_calvetti_py { + +static constexpr std::array, 6> dJydy_rowvals_model_calvetti_py_ = {{ + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, +}}; + +void dJydy_rowvals_model_calvetti_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexvals(gsl::make_span(dJydy_rowvals_model_calvetti_py_[index])); +} +} // namespace model_model_calvetti_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" +#include "dJydy.h" + +namespace amici { +namespace model_model_calvetti_py { + +void dJydy_model_calvetti_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydy[0] = (-1.0*mobs_V1 + 1.0*obs_V1)/std::pow(sigma_obs_V1, 2); + break; + case 1: + dJydy[0] = (-1.0*mobs_V2 + 1.0*obs_V2)/std::pow(sigma_obs_V2, 2); + break; + case 2: + dJydy[0] = (-1.0*mobs_V3 + 1.0*obs_V3)/std::pow(sigma_obs_V3, 2); + break; + case 3: + dJydy[0] = (-1.0*mobs_f0 + 1.0*obs_f0)/std::pow(sigma_obs_f0, 2); + break; + case 4: + dJydy[0] = (-1.0*mobs_f1 + 1.0*obs_f1)/std::pow(sigma_obs_f1, 2); + break; + case 5: + dJydy[0] = (-1.0*mobs_f2 + 1.0*obs_f2)/std::pow(sigma_obs_f2, 2); + break; + } +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/dJydy.h b/models/model_calvetti_py/dJydy.h new file mode 100644 index 0000000000..3a017051fc --- /dev/null +++ b/models/model_calvetti_py/dJydy.h @@ -0,0 +1,6 @@ +#define dJy0_dobs_V1 dJydy[0] +#define dJy0_dobs_V2_1 dJydy[1] +#define dJy0_dobs_V3_2 dJydy[2] +#define dJy0_dobs_f0_3 dJydy[3] +#define dJy0_dobs_f1_4 dJydy[4] +#define dJy0_dobs_f2_5 dJydy[5] diff --git a/models/model_calvetti_py/dwdw.cpp b/models/model_calvetti_py/dwdw.cpp new file mode 100644 index 0000000000..46b8198b01 --- /dev/null +++ b/models/model_calvetti_py/dwdw.cpp @@ -0,0 +1,83 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_calvetti_py { + +static constexpr std::array dwdw_colptrs_model_calvetti_py_ = { + 0, 1, 2, 3, 4, 5, 6, 6, 6, 7, 9, 12, 16, 16, 16, 16, 16, 16 +}; + +void dwdw_colptrs_model_calvetti_py(SUNMatrixWrapper &dwdw){ + dwdw.set_indexptrs(gsl::make_span(dwdw_colptrs_model_calvetti_py_)); +} +} // namespace model_model_calvetti_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_calvetti_py { + +static constexpr std::array dwdw_rowvals_model_calvetti_py_ = { + 13, 14, 15, 9, 10, 11, 13, 12, 13, 12, 13, 14, 12, 13, 14, 15 +}; + +void dwdw_rowvals_model_calvetti_py(SUNMatrixWrapper &dwdw){ + dwdw.set_indexvals(gsl::make_span(dwdw_rowvals_model_calvetti_py_)); +} +} // namespace model_model_calvetti_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "k.h" +#include "h.h" +#include "w.h" +#include "dwdw.h" + +namespace amici { +namespace model_model_calvetti_py { + +void dwdw_model_calvetti_py(realtype *dwdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, bool include_static){ + // static expressions + if (include_static) { + drate_of_V1_ds = 1.0/31.0; // dwdw[6] + } + + // dynamic expressions + drate_of_V1_dC1ss = (2.0/31.0)*V1/(std::pow(C1ss, 2)*(R3*f3 + f1*(R1 + R2) + f2*(R2 + R3))); // dwdw[0] + drate_of_V2_dC2ss = (2.0/163.0)*V2/(std::pow(C2ss, 2)*(R3*f3 + f2*(R2 + R3))); // dwdw[1] + drate_of_V3_dC3ss = (1.0/61.0)*V3/(std::pow(C3ss, 2)*R3*f3); // dwdw[2] + dR1_dL1 = 3*std::pow(L1, 2)/std::pow(V1, 2); // dwdw[3] + dR2_dL2 = 3*std::pow(L2, 2)/std::pow(V2, 2); // dwdw[4] + dR3_dL3 = 3*std::pow(L3, 2)/std::pow(V3, 2); // dwdw[5] + df0_dR1 = -f1/R1 + (R3*f3 + f1*(R1 + R2) + f2*(R2 + R3))/std::pow(R1, 2) - 2/std::pow(R1, 2); // dwdw[7] + drate_of_V1_dR1 = (2.0/31.0)*V1*f1/(C1ss*std::pow(R3*f3 + f1*(R1 + R2) + f2*(R2 + R3), 2)); // dwdw[8] + df0_dR2 = (-f1 - f2)/R1; // dwdw[9] + drate_of_V1_dR2 = (2.0/31.0)*V1*(f1 + f2)/(C1ss*std::pow(R3*f3 + f1*(R1 + R2) + f2*(R2 + R3), 2)); // dwdw[10] + drate_of_V2_dR2 = (2.0/163.0)*V2*f2/(C2ss*std::pow(R3*f3 + f2*(R2 + R3), 2)); // dwdw[11] + df0_dR3 = (-f2 - f3)/R1; // dwdw[12] + drate_of_V1_dR3 = (2.0/31.0)*V1*(f2 + f3)/(C1ss*std::pow(R3*f3 + f1*(R1 + R2) + f2*(R2 + R3), 2)); // dwdw[13] + drate_of_V2_dR3 = (2.0/163.0)*V2*(f2 + f3)/(C2ss*std::pow(R3*f3 + f2*(R2 + R3), 2)); // dwdw[14] + drate_of_V3_dR3 = (1.0/61.0)*V3/(C3ss*std::pow(R3, 2)*f3); // dwdw[15] +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/dwdw.h b/models/model_calvetti_py/dwdw.h new file mode 100644 index 0000000000..94c2601192 --- /dev/null +++ b/models/model_calvetti_py/dwdw.h @@ -0,0 +1,16 @@ +#define drate_of_V1_dC1ss dwdw[0] +#define drate_of_V2_dC2ss dwdw[1] +#define drate_of_V3_dC3ss dwdw[2] +#define dR1_dL1 dwdw[3] +#define dR2_dL2 dwdw[4] +#define dR3_dL3 dwdw[5] +#define drate_of_V1_ds dwdw[6] +#define df0_dR1 dwdw[7] +#define drate_of_V1_dR1 dwdw[8] +#define df0_dR2 dwdw[9] +#define drate_of_V1_dR2 dwdw[10] +#define drate_of_V2_dR2 dwdw[11] +#define df0_dR3 dwdw[12] +#define drate_of_V1_dR3 dwdw[13] +#define drate_of_V2_dR3 dwdw[14] +#define drate_of_V3_dR3 dwdw[15] diff --git a/models/model_calvetti_py/dwdx.cpp b/models/model_calvetti_py/dwdx.cpp new file mode 100644 index 0000000000..cd8dbf30bf --- /dev/null +++ b/models/model_calvetti_py/dwdx.cpp @@ -0,0 +1,79 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_calvetti_py { + +static constexpr std::array dwdx_colptrs_model_calvetti_py_ = { + 0, 2, 4, 6, 8, 11, 15 +}; + +void dwdx_colptrs_model_calvetti_py(SUNMatrixWrapper &dwdx){ + dwdx.set_indexptrs(gsl::make_span(dwdx_colptrs_model_calvetti_py_)); +} +} // namespace model_model_calvetti_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_calvetti_py { + +static constexpr std::array dwdx_rowvals_model_calvetti_py_ = { + 9, 13, 10, 14, 11, 15, 12, 13, 12, 13, 14, 12, 13, 14, 15 +}; + +void dwdx_rowvals_model_calvetti_py(SUNMatrixWrapper &dwdx){ + dwdx.set_indexvals(gsl::make_span(dwdx_rowvals_model_calvetti_py_)); +} +} // namespace model_model_calvetti_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "k.h" +#include "h.h" +#include "w.h" +#include "dwdx.h" + +namespace amici { +namespace model_model_calvetti_py { + +void dwdx_model_calvetti_py(realtype *dwdx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *spl, bool include_static){ + + // dynamic expressions + dR1_dV1 = -2*std::pow(L1, 3)/std::pow(V1, 3); // dwdx[0] + drate_of_V1_dV1 = -(100.0/899.0)/V1ss - (2.0/31.0)/(C1ss*(R3*f3 + f1*(R1 + R2) + f2*(R2 + R3))); // dwdx[1] + dR2_dV2 = -2*std::pow(L2, 3)/std::pow(V2, 3); // dwdx[2] + drate_of_V2_dV2 = -(100.0/8313.0)/V2ss - (2.0/163.0)/(C2ss*(R3*f3 + f2*(R2 + R3))); // dwdx[3] + dR3_dV3 = -2*std::pow(L3, 3)/std::pow(V3, 3); // dwdx[4] + drate_of_V3_dV3 = -(1.0/121999878.0)/V3ss - (1.0/61.0)/(C3ss*R3*f3); // dwdx[5] + df0_df1 = (-R1 - R2)/R1; // dwdx[6] + drate_of_V1_df1 = (2.0/31.0)*V1*(R1 + R2)/(C1ss*std::pow(R3*f3 + f1*(R1 + R2) + f2*(R2 + R3), 2)); // dwdx[7] + df0_df2 = (-R2 - R3)/R1; // dwdx[8] + drate_of_V1_df2 = (2.0/31.0)*V1*(R2 + R3)/(C1ss*std::pow(R3*f3 + f1*(R1 + R2) + f2*(R2 + R3), 2)); // dwdx[9] + drate_of_V2_df2 = (2.0/163.0)*V2*(R2 + R3)/(C2ss*std::pow(R3*f3 + f2*(R2 + R3), 2)); // dwdx[10] + df0_df3 = -R3/R1; // dwdx[11] + drate_of_V1_df3 = (2.0/31.0)*R3*V1/(C1ss*std::pow(R3*f3 + f1*(R1 + R2) + f2*(R2 + R3), 2)); // dwdx[12] + drate_of_V2_df3 = (2.0/163.0)*R3*V2/(C2ss*std::pow(R3*f3 + f2*(R2 + R3), 2)); // dwdx[13] + drate_of_V3_df3 = (1.0/61.0)*V3/(C3ss*R3*std::pow(f3, 2)); // dwdx[14] +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/dwdx.h b/models/model_calvetti_py/dwdx.h new file mode 100644 index 0000000000..284c8708bb --- /dev/null +++ b/models/model_calvetti_py/dwdx.h @@ -0,0 +1,15 @@ +#define dR1_dV1 dwdx[0] +#define drate_of_V1_dV1 dwdx[1] +#define dR2_dV2 dwdx[2] +#define drate_of_V2_dV2 dwdx[3] +#define dR3_dV3 dwdx[4] +#define drate_of_V3_dV3 dwdx[5] +#define df0_df1 dwdx[6] +#define drate_of_V1_df1 dwdx[7] +#define df0_df2 dwdx[8] +#define drate_of_V1_df2 dwdx[9] +#define drate_of_V2_df2 dwdx[10] +#define df0_df3 dwdx[11] +#define drate_of_V1_df3 dwdx[12] +#define drate_of_V2_df3 dwdx[13] +#define drate_of_V3_df3 dwdx[14] diff --git a/models/model_calvetti_py/dx.h b/models/model_calvetti_py/dx.h new file mode 100644 index 0000000000..fa7b71592d --- /dev/null +++ b/models/model_calvetti_py/dx.h @@ -0,0 +1,6 @@ +#define dV1dt dx[0] +#define dV2dt dx[1] +#define dV3dt dx[2] +#define df1dt dx[3] +#define df2dt dx[4] +#define df3dt dx[5] diff --git a/models/model_calvetti_py/dxdotdw.cpp b/models/model_calvetti_py/dxdotdw.cpp new file mode 100644 index 0000000000..02f2241416 --- /dev/null +++ b/models/model_calvetti_py/dxdotdw.cpp @@ -0,0 +1,70 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_calvetti_py { + +static constexpr std::array dxdotdw_colptrs_model_calvetti_py_ = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 5, 7, 7 +}; + +void dxdotdw_colptrs_model_calvetti_py(SUNMatrixWrapper &dxdotdw){ + dxdotdw.set_indexptrs(gsl::make_span(dxdotdw_colptrs_model_calvetti_py_)); +} +} // namespace model_model_calvetti_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_calvetti_py { + +static constexpr std::array dxdotdw_rowvals_model_calvetti_py_ = { + 3, 0, 3, 1, 4, 2, 5 +}; + +void dxdotdw_rowvals_model_calvetti_py(SUNMatrixWrapper &dxdotdw){ + dxdotdw.set_indexvals(gsl::make_span(dxdotdw_rowvals_model_calvetti_py_)); +} +} // namespace model_model_calvetti_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "k.h" +#include "h.h" +#include "dx.h" +#include "w.h" +#include "dxdotdw.h" + +namespace amici { +namespace model_model_calvetti_py { + +void dxdotdw_model_calvetti_py(realtype *dxdotdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w){ + dae_0_df0 = 1; // dxdotdw[0] + dde_0_drate_of_V1 = 1; // dxdotdw[1] + dae_0_drate_of_V1 = -1; // dxdotdw[2] + dde_1_drate_of_V2 = 1; // dxdotdw[3] + dae_1_drate_of_V2 = -1; // dxdotdw[4] + dde_2_drate_of_V3 = 1; // dxdotdw[5] + dae_2_drate_of_V3 = -1; // dxdotdw[6] +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/dxdotdw.h b/models/model_calvetti_py/dxdotdw.h new file mode 100644 index 0000000000..9d4bf10b0b --- /dev/null +++ b/models/model_calvetti_py/dxdotdw.h @@ -0,0 +1,7 @@ +#define dae_0_df0 dxdotdw[0] +#define dde_0_drate_of_V1 dxdotdw[1] +#define dae_0_drate_of_V1 dxdotdw[2] +#define dde_1_drate_of_V2 dxdotdw[3] +#define dae_1_drate_of_V2 dxdotdw[4] +#define dde_2_drate_of_V3 dxdotdw[5] +#define dae_2_drate_of_V3 dxdotdw[6] diff --git a/models/model_calvetti_py/dxdotdx_explicit.cpp b/models/model_calvetti_py/dxdotdx_explicit.cpp new file mode 100644 index 0000000000..07db46e075 --- /dev/null +++ b/models/model_calvetti_py/dxdotdx_explicit.cpp @@ -0,0 +1,68 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_calvetti_py { + +static constexpr std::array dxdotdx_explicit_colptrs_model_calvetti_py_ = { + 0, 0, 0, 0, 2, 4, 5 +}; + +void dxdotdx_explicit_colptrs_model_calvetti_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexptrs(gsl::make_span(dxdotdx_explicit_colptrs_model_calvetti_py_)); +} +} // namespace model_model_calvetti_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_calvetti_py { + +static constexpr std::array dxdotdx_explicit_rowvals_model_calvetti_py_ = { + 3, 4, 4, 5, 5 +}; + +void dxdotdx_explicit_rowvals_model_calvetti_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexvals(gsl::make_span(dxdotdx_explicit_rowvals_model_calvetti_py_)); +} +} // namespace model_model_calvetti_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "k.h" +#include "h.h" +#include "dx.h" +#include "w.h" +#include "dxdotdx_explicit.h" + +namespace amici { +namespace model_model_calvetti_py { + +void dxdotdx_explicit_model_calvetti_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w){ + dae_0_df1 = -1; // dxdotdx_explicit[0] + dae_1_df1 = 1; // dxdotdx_explicit[1] + dae_1_df2 = -1; // dxdotdx_explicit[2] + dae_2_df2 = 1; // dxdotdx_explicit[3] + dae_2_df3 = -1; // dxdotdx_explicit[4] +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/dxdotdx_explicit.h b/models/model_calvetti_py/dxdotdx_explicit.h new file mode 100644 index 0000000000..7ce270f5c0 --- /dev/null +++ b/models/model_calvetti_py/dxdotdx_explicit.h @@ -0,0 +1,5 @@ +#define dae_0_df1 dxdotdx_explicit[0] +#define dae_1_df1 dxdotdx_explicit[1] +#define dae_1_df2 dxdotdx_explicit[2] +#define dae_2_df2 dxdotdx_explicit[3] +#define dae_2_df3 dxdotdx_explicit[4] diff --git a/models/model_calvetti_py/dydx.cpp b/models/model_calvetti_py/dydx.cpp new file mode 100644 index 0000000000..e7256cdd4f --- /dev/null +++ b/models/model_calvetti_py/dydx.cpp @@ -0,0 +1,32 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "k.h" +#include "h.h" +#include "w.h" +#include "dwdx.h" + +namespace amici { +namespace model_model_calvetti_py { + +void dydx_model_calvetti_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx){ + dydx[0] = 1; + dydx[3] = std::pow(L1, 3)*(2*f1/R1 - 2*(R3*f3 + f1*(R1 + R2) + f2*(R2 + R3))/std::pow(R1, 2) + 4/std::pow(R1, 2))/std::pow(V1, 3); + dydx[7] = 1; + dydx[9] = std::pow(L2, 3)*(2*f1 + 2*f2)/(R1*std::pow(V2, 3)); + dydx[14] = 1; + dydx[15] = std::pow(L3, 3)*(2*f2 + 2*f3)/(R1*std::pow(V3, 3)); + dydx[21] = (-R1 - R2)/R1; + dydx[22] = 1; + dydx[27] = (-R2 - R3)/R1; + dydx[29] = 1; + dydx[33] = -R3/R1; +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/h.h b/models/model_calvetti_py/h.h new file mode 100644 index 0000000000..5d39a700fa --- /dev/null +++ b/models/model_calvetti_py/h.h @@ -0,0 +1,4 @@ +#define Heaviside_0 h[0] +#define Heaviside_1 h[1] +#define Heaviside_2 h[2] +#define Heaviside_3 h[3] diff --git a/models/model_calvetti_py/k.h b/models/model_calvetti_py/k.h new file mode 100644 index 0000000000..a4f061c5f8 --- /dev/null +++ b/models/model_calvetti_py/k.h @@ -0,0 +1,6 @@ +#define V1ss k[0] +#define R1ss k[1] +#define V2ss k[2] +#define R2ss k[3] +#define V3ss k[4] +#define R3ss k[5] diff --git a/models/model_calvetti_py/main.cpp b/models/model_calvetti_py/main.cpp new file mode 100644 index 0000000000..ecdff85a46 --- /dev/null +++ b/models/model_calvetti_py/main.cpp @@ -0,0 +1,93 @@ +#include + +#include "wrapfunctions.h" /* model-provided functions */ +#include /* AMICI base functions */ + +template +std::ostream& operator<<(std::ostream& os, std::vector const& v) { + os << "["; + for (typename std::vector::const_iterator ii = v.begin(); ii != v.end(); + ++ii) { + os << " " << *ii; + } + os << "]"; + return os; +} + +/* + * This is a scaffold for a stand-alone AMICI simulation executable + * demonstrating the basic use of the AMICI C++ API. + */ + +int main() { + std::cout << "********************************" << std::endl; + std::cout << "** Running forward simulation **" << std::endl; + std::cout << "********************************" << std::endl << std::endl; + + // Create a model instance + auto model = amici::generic_model::getModel(); + + // Set desired output timepoints + model->setTimepoints({0.0, 1.0, 10.0, 100.0, 1000.0}); + + // Create a solver instance + auto solver = model->getSolver(); + + // Optionally set integration tolerance + solver->setAbsoluteTolerance(1e-16); + solver->setRelativeTolerance(1e-8); + + // Run the simulation using default parameters set during model import + // (can be changed using model->setParameters() or model->setParameterBy*()) + auto rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print observable time course + auto observable_ids = model->getObservableIds(); + std::cout << "Simulated observables for timepoints " << rdata->ts << "\n\n"; + for (int i_observable = 0; i_observable < rdata->ny; ++i_observable) { + std::cout << observable_ids[i_observable] << ":\n\t"; + for (int i_time = 0; i_time < rdata->nt; ++i_time) { + // rdata->y is a flat 2D array in row-major ordering + std::cout << rdata->y[i_time * rdata->ny + i_observable] << " "; + } + std::cout << std::endl << std::endl; + } + + std::cout << std::endl; + std::cout << "**********************************" << std::endl; + std::cout << "** Forward sensitivity analysis **" << std::endl; + std::cout << "**********************************" << std::endl << std::endl; + + // Enable first-order sensitivity analysis + solver->setSensitivityOrder(amici::SensitivityOrder::first); + // Use forward sensitivities + solver->setSensitivityMethod(amici::SensitivityMethod::forward); + + // Run the simulation + rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print state sensitivities sx... + // ... for the first timepoint... + int i_time = 0; + // ... with respect to the first parameter + int i_nplist = 0; + + // get identifiers from model + auto state_ids = model->getStateIds(); + auto parameter_ids = model->getParameterIds(); + + std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] + << std::endl; // nt x nplist x nx + for (int i_state = 0; i_state < rdata->nx; ++i_state) { + std::cout << "\td(" << state_ids[i_state] << ")/d(" + << parameter_ids[model->plist(i_nplist)] << ") = "; + + // rdata->sx is a flat 3D array in row-major ordering + std::cout << rdata->sx + [i_time * rdata->nplist * rdata->nx + + i_nplist * rdata->nx + i_state]; + std::cout << std::endl; + } + + return 0; +} diff --git a/models/model_calvetti_py/model_calvetti_py.cpp b/models/model_calvetti_py/model_calvetti_py.cpp new file mode 100644 index 0000000000..7c60d40e8f --- /dev/null +++ b/models/model_calvetti_py/model_calvetti_py.cpp @@ -0,0 +1,129 @@ +#include +#include + +namespace amici { + +namespace model_model_calvetti_py { + +// clang-format off + +std::array parameterNames = { + +}; + +std::array fixedParameterNames = { + "V1ss", // k[0] +"R1ss", // k[1] +"V2ss", // k[2] +"R2ss", // k[3] +"V3ss", // k[4] +"R3ss", // k[5] +}; + +std::array stateNames = { + "V1", // x_rdata[0] +"V2", // x_rdata[1] +"V3", // x_rdata[2] +"f1", // x_rdata[3] +"f2", // x_rdata[4] +"f3", // x_rdata[5] +}; + +std::array observableNames = { + "y0", // y[0] +"y1", // y[1] +"y2", // y[2] +"y3", // y[3] +"y4", // y[4] +"y5", // y[5] +}; + +std::array observableScalings = { + ObservableScaling::lin, // y[0] +ObservableScaling::lin, // y[1] +ObservableScaling::lin, // y[2] +ObservableScaling::lin, // y[3] +ObservableScaling::lin, // y[4] +ObservableScaling::lin, // y[5] +}; + +std::array expressionNames = { + "C1ss", // w[0] +"C2ss", // w[1] +"C3ss", // w[2] +"L1", // w[3] +"L2", // w[4] +"L3", // w[5] +"p2", // w[6] +"p3", // w[7] +"s", // w[8] +"R1", // w[9] +"R2", // w[10] +"R3", // w[11] +"f0", // w[12] +"rate_of_V1", // w[13] +"rate_of_V2", // w[14] +"rate_of_V3", // w[15] +"flux_r0", // w[16] +}; + +std::array parameterIds = { + +}; + +std::array fixedParameterIds = { + "V1ss", // k[0] +"R1ss", // k[1] +"V2ss", // k[2] +"R2ss", // k[3] +"V3ss", // k[4] +"R3ss", // k[5] +}; + +std::array stateIds = { + "V1", // x_rdata[0] +"V2", // x_rdata[1] +"V3", // x_rdata[2] +"f1", // x_rdata[3] +"f2", // x_rdata[4] +"f3", // x_rdata[5] +}; + +std::array observableIds = { + "obs_V1", // y[0] +"obs_V2", // y[1] +"obs_V3", // y[2] +"obs_f0", // y[3] +"obs_f1", // y[4] +"obs_f2", // y[5] +}; + +std::array expressionIds = { + "C1ss", // w[0] +"C2ss", // w[1] +"C3ss", // w[2] +"L1", // w[3] +"L2", // w[4] +"L3", // w[5] +"p2", // w[6] +"p3", // w[7] +"s", // w[8] +"R1", // w[9] +"R2", // w[10] +"R3", // w[11] +"f0", // w[12] +"rate_of_V1", // w[13] +"rate_of_V2", // w[14] +"rate_of_V3", // w[15] +"flux_r0", // w[16] +}; + +std::array stateIdxsSolver = { + 0, 1, 2, 3, 4, 5 +}; + +// clang-format on + +} // namespace model_model_calvetti_py + +} // namespace amici diff --git a/models/model_calvetti_py/model_calvetti_py.h b/models/model_calvetti_py/model_calvetti_py.h new file mode 100644 index 0000000000..c1b4d67a23 --- /dev/null +++ b/models/model_calvetti_py/model_calvetti_py.h @@ -0,0 +1,574 @@ +#ifndef _amici_TPL_MODELNAME_h +#define _amici_TPL_MODELNAME_h +#include +#include +#include + +#include "amici/model_dae.h" +#include "amici/splinefunctions.h" +#include "amici/event.h" + +namespace amici { + +class Solver; + +namespace model_model_calvetti_py { + +extern std::array parameterNames; +extern std::array fixedParameterNames; +extern std::array stateNames; +extern std::array observableNames; +extern std::array observableScalings; +extern std::array expressionNames; +extern std::array parameterIds; +extern std::array fixedParameterIds; +extern std::array stateIds; +extern std::array observableIds; +extern std::array expressionIds; +extern std::array stateIdxsSolver; + +extern void Jy_model_calvetti_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydsigma_model_calvetti_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_model_calvetti_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_colptrs_model_calvetti_py(SUNMatrixWrapper &colptrs, int index); +extern void dJydy_rowvals_model_calvetti_py(SUNMatrixWrapper &rowvals, int index); + + + + + + +extern void root_model_calvetti_py(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl); + + + +extern void dwdx_model_calvetti_py(realtype *dwdx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *spl, bool include_static); +extern void dwdx_colptrs_model_calvetti_py(SUNMatrixWrapper &colptrs); +extern void dwdx_rowvals_model_calvetti_py(SUNMatrixWrapper &rowvals); +extern void dwdw_model_calvetti_py(realtype *dwdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, bool include_static); +extern void dwdw_colptrs_model_calvetti_py(SUNMatrixWrapper &colptrs); +extern void dwdw_rowvals_model_calvetti_py(SUNMatrixWrapper &rowvals); +extern void dxdotdw_model_calvetti_py(realtype *dxdotdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w); +extern void dxdotdw_colptrs_model_calvetti_py(SUNMatrixWrapper &colptrs); +extern void dxdotdw_rowvals_model_calvetti_py(SUNMatrixWrapper &rowvals); + + + +extern void dxdotdx_explicit_model_calvetti_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w); +extern void dxdotdx_explicit_colptrs_model_calvetti_py(SUNMatrixWrapper &colptrs); +extern void dxdotdx_explicit_rowvals_model_calvetti_py(SUNMatrixWrapper &rowvals); +extern void dydx_model_calvetti_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx); + + + + + +extern void sigmay_model_calvetti_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y); + + + + +extern void w_model_calvetti_py(realtype *w, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl, const realtype *spl, bool include_static); +extern void x0_model_calvetti_py(realtype *x0, const realtype t, const realtype *p, const realtype *k); +extern void x0_fixedParameters_model_calvetti_py(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs); + + +extern void xdot_model_calvetti_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w); +extern void y_model_calvetti_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); + + + + + + + + +extern void x_solver_model_calvetti_py(realtype *x_solver, const realtype *x_rdata); + + + + + + + + + + + + +extern std::vector create_splines_model_calvetti_py(const realtype *p, const realtype *k); + + + +/** + * @brief AMICI-generated model subclass. + */ +class Model_model_calvetti_py : public amici::Model_DAE { + public: + /** + * @brief Default constructor. + */ + Model_model_calvetti_py() + : amici::Model_DAE( + amici::ModelDimensions( + 6, // nx_rdata + 6, // nxtrue_rdata + 6, // nx_solver + 6, // nxtrue_solver + 0, // nx_solver_reinit + 0, // np + 6, // nk + 6, // ny + 6, // nytrue + 0, // nz + 0, // nztrue + 4, // nevent + 0, // nevent_solver + 0, // nspl + 1, // nobjective + 17, // nw + 15, // ndwdx + 0, // ndwdp + 16, // ndwdw + 7, // ndxdotdw + std::vector{1, 1, 1, 1, 1, 1}, // ndjydy + 0, // ndxrdatadxsolver + 0, // ndxrdatadtcl + 0, // ndtotal_cldx_rdata + 0, // nnz + 6, // ubw + 6, // lbw + true, // pythonGenerated + 0, // ndxdotdp_explicit + 5, // ndxdotdx_explicit + 2 // w_recursion_depth + ), + amici::SimulationParameters( + std::vector{0.28999999999999998, 0.73999999999999999, 0.44, 0.080000000000000002, 0.27000000000000002, 0.17999999999999999}, // fixedParameters + std::vector{} // dynamic parameters + ), + amici::SecondOrderMode::none, // o2mode + std::vector{1.0, 1.0, 1.0, 0.0, 0.0, 0.0}, // idlist + std::vector{}, // z2events + std::vector{ + Event("Heaviside_0", true, true, NAN), + Event("Heaviside_1", true, true, NAN), + Event("Heaviside_2", true, true, NAN), + Event("Heaviside_3", true, true, NAN) + }, // events + {{10.0, {0, 1}}, {12.0, {2, 3}}} // state-independent events + ) { + } + + /** + * @brief Clone this model instance. + * @return A deep copy of this instance. + */ + amici::Model *clone() const override { + return new Model_model_calvetti_py(*this); + } + + void fJrz(realtype *Jrz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fJy(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + Jy_model_calvetti_py(Jy, iy, p, k, y, sigmay, my); + } + + + void fJz(realtype *Jz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override {} + + + void fdJrzdsigma(realtype *dJrzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fdJrzdz(realtype *dJrzdz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fdJydsigma(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydsigma_model_calvetti_py(dJydsigma, iy, p, k, y, sigmay, my); + } + + + void fdJzdsigma(realtype *dJzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override {} + + + void fdJzdz(realtype *dJzdz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const double *mz) override {} + + + void fdeltax(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old) override {} + + + void fdeltasx(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old) override {} + + + void fdeltaxB(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl) override {} + + + void fdeltaqB(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB) override {} + + + void fdrzdp(realtype *drzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdrzdx(realtype *drzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void fdsigmaydp(realtype *dsigmaydp, const realtype t, const realtype *p, const realtype *k, const realtype *y, const int ip) override {} + + + void fdsigmaydy(realtype *dsigmaydy, const realtype t, const realtype *p, const realtype *k, const realtype *y) override {} + + + void fdsigmazdp(realtype *dsigmazdp, const realtype t, const realtype *p, const realtype *k, const int ip) override {} + + + void fdJydy(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydy_model_calvetti_py(dJydy, iy, p, k, y, sigmay, my); + } + + void fdJydy_colptrs(SUNMatrixWrapper &colptrs, int index) override { + dJydy_colptrs_model_calvetti_py(colptrs, index); + } + + void fdJydy_rowvals(SUNMatrixWrapper &rowvals, int index) override { + dJydy_rowvals_model_calvetti_py(rowvals, index); + } + + + std::vector fcreate_splines(const realtype *p, const realtype *k) override { + return create_splines_model_calvetti_py(p, k); + } + + void fdspline_valuesdp(realtype *dspline_valuesdp, const realtype *p, const realtype *k, const int ip) override {} + + void fdspline_slopesdp(realtype *dspline_slopesdp, const realtype *p, const realtype *k, const int ip) override {} + + + void fdwdp(realtype *dwdp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl, bool include_static) override {} + + void fdwdp_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdp_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdx(realtype *dwdx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *spl, bool include_static) override { + dwdx_model_calvetti_py(dwdx, t, x, p, k, h, w, tcl, spl, include_static); + } + + void fdwdx_colptrs(SUNMatrixWrapper &colptrs) override { + dwdx_colptrs_model_calvetti_py(colptrs); + } + + void fdwdx_rowvals(SUNMatrixWrapper &rowvals) override { + dwdx_rowvals_model_calvetti_py(rowvals); + } + + + void fdwdw(realtype *dwdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, bool include_static) override { + dwdw_model_calvetti_py(dwdw, t, x, p, k, h, w, tcl, include_static); + } + + void fdwdw_colptrs(SUNMatrixWrapper &colptrs) override { + dwdw_colptrs_model_calvetti_py(colptrs); + } + + void fdwdw_rowvals(SUNMatrixWrapper &rowvals) override { + dwdw_rowvals_model_calvetti_py(rowvals); + } + + + void fdxdotdw(realtype *dxdotdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w) override { + dxdotdw_model_calvetti_py(dxdotdw, t, x, p, k, h, dx, w); + } + + void fdxdotdw_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdw_colptrs_model_calvetti_py(colptrs); + } + + void fdxdotdw_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdw_rowvals_model_calvetti_py(rowvals); + } + + + void fdxdotdp_explicit(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w) override {} + + void fdxdotdp_explicit_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdxdotdp_explicit_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdx_explicit(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w) override { + dxdotdx_explicit_model_calvetti_py(dxdotdx_explicit, t, x, p, k, h, dx, w); + } + + void fdxdotdx_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdx_explicit_colptrs_model_calvetti_py(colptrs); + } + + void fdxdotdx_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdx_explicit_rowvals_model_calvetti_py(rowvals); + } + + + void fdydx(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { + dydx_model_calvetti_py(dydx, t, x, p, k, h, w, dwdx); + } + + + void fdydp(realtype *dydp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl) override {} + + + void fdzdp(realtype *dzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdzdx(realtype *dzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void froot(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl) override { + root_model_calvetti_py(root, t, x, p, k, h, tcl); + } + + + void frz(realtype *rz, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void fsigmay(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y) override { + sigmay_model_calvetti_py(sigmay, t, p, k, y); + } + + + void fsigmaz(realtype *sigmaz, const realtype t, const realtype *p, const realtype *k) override {} + + + void fstau(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie) override {} + + void fsx0(realtype *sx0, const realtype t, const realtype *x, const realtype *p, const realtype *k, const int ip) override {} + + void fsx0_fixedParameters(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs) override {} + + + void fw(realtype *w, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl, const realtype *spl, bool include_static) override { + w_model_calvetti_py(w, t, x, p, k, h, tcl, spl, include_static); + } + + + void fx0(realtype *x0, const realtype t, const realtype *p, const realtype *k) override { + x0_model_calvetti_py(x0, t, p, k); + } + + + void fx0_fixedParameters(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs) override { + x0_fixedParameters_model_calvetti_py(x0_fixedParameters, t, p, k, reinitialization_state_idxs); + } + + + void fxdot(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w) override { + xdot_model_calvetti_py(xdot, t, x, p, k, h, dx, w); + } + + + void fy(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + y_model_calvetti_py(y, t, x, p, k, h, w); + } + + + void fz(realtype *z, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + + + void fx_solver(realtype *x_solver, const realtype *x_rdata) override { + x_solver_model_calvetti_py(x_solver, x_rdata); + } + + + void ftotal_cl(realtype *total_cl, const realtype *x_rdata, const realtype *p, const realtype *k) override {} + + + void fdx_rdatadx_solver(realtype *dx_rdatadx_solver, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadx_solver_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadx_solver_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdx_rdatadp(realtype *dx_rdatadp, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k, const int ip) override {} + + + void fdx_rdatadtcl(realtype *dx_rdatadtcl, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadtcl_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadtcl_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdtotal_cldp(realtype *dtotal_cldp, const realtype *x_rdata, const realtype *p, const realtype *k, const int ip) override {} + + + void fdtotal_cldx_rdata(realtype *dtotal_cldx_rdata, const realtype *x_rdata, const realtype *p, const realtype *k, const realtype *tcl) override {} + + void fdtotal_cldx_rdata_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdtotal_cldx_rdata_rowvals(SUNMatrixWrapper &rowvals) override {} + + + std::string getName() const override { + return "model_calvetti_py"; + } + + /** + * @brief Get names of the model parameters + * @return the names + */ + std::vector getParameterNames() const override { + return std::vector(parameterNames.begin(), + parameterNames.end()); + } + + /** + * @brief Get names of the model states + * @return the names + */ + std::vector getStateNames() const override { + return std::vector(stateNames.begin(), stateNames.end()); + } + + /** + * @brief Get names of the solver states + * @return the names + */ + std::vector getStateNamesSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto const idx: stateIdxsSolver) { + result.push_back(stateNames[idx]); + } + return result; + } + + /** + * @brief Get names of the fixed model parameters + * @return the names + */ + std::vector getFixedParameterNames() const override { + return std::vector(fixedParameterNames.begin(), + fixedParameterNames.end()); + } + + /** + * @brief Get names of the observables + * @return the names + */ + std::vector getObservableNames() const override { + return std::vector(observableNames.begin(), + observableNames.end()); + } + + /** + * @brief Get names of model expressions + * @return Expression names + */ + std::vector getExpressionNames() const override { + return std::vector(expressionNames.begin(), + expressionNames.end()); + } + + /** + * @brief Get ids of the model parameters + * @return the ids + */ + std::vector getParameterIds() const override { + return std::vector(parameterIds.begin(), + parameterIds.end()); + } + + /** + * @brief Get ids of the model states + * @return the ids + */ + std::vector getStateIds() const override { + return std::vector(stateIds.begin(), stateIds.end()); + } + + /** + * @brief Get ids of the solver states + * @return the ids + */ + std::vector getStateIdsSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto idx: stateIdxsSolver) { + result.push_back(stateIds[idx]); + } + return result; + } + + /** + * @brief Get ids of the fixed model parameters + * @return the ids + */ + std::vector getFixedParameterIds() const override { + return std::vector(fixedParameterIds.begin(), + fixedParameterIds.end()); + } + + /** + * @brief Get ids of the observables + * @return the ids + */ + std::vector getObservableIds() const override { + return std::vector(observableIds.begin(), + observableIds.end()); + } + + /** + * @brief Get IDs of model expressions + * @return Expression IDs + */ + std::vector getExpressionIds() const override { + return std::vector(expressionIds.begin(), + expressionIds.end()); + } + + /** + * @brief function indicating whether reinitialization of states depending + * on fixed parameters is permissible + * @return flag indicating whether reinitialization of states depending on + * fixed parameters is permissible + */ + bool isFixedParameterStateReinitializationAllowed() const override { + return true; + } + + /** + * @brief returns the AMICI version that was used to generate the model + * @return AMICI version string + */ + std::string getAmiciVersion() const override { + return "0.33.0"; + } + + /** + * @brief returns the amici version that was used to generate the model + * @return AMICI git commit hash + */ + std::string getAmiciCommit() const override { + return "bcedb951ddf674996b269489d74f9b86112038ff"; + } + + bool hasQuadraticLLH() const override { + return true; + } + + ObservableScaling getObservableScaling(int iy) const override { + return observableScalings.at(iy); + } +}; + + +} // namespace model_model_calvetti_py + +} // namespace amici + +#endif /* _amici_TPL_MODELNAME_h */ diff --git a/models/model_calvetti_py/my.h b/models/model_calvetti_py/my.h new file mode 100644 index 0000000000..8eef7f37cf --- /dev/null +++ b/models/model_calvetti_py/my.h @@ -0,0 +1,6 @@ +#define mobs_V1 my[0] +#define mobs_V2 my[1] +#define mobs_V3 my[2] +#define mobs_f0 my[3] +#define mobs_f1 my[4] +#define mobs_f2 my[5] diff --git a/models/model_calvetti_py/root.cpp b/models/model_calvetti_py/root.cpp new file mode 100644 index 0000000000..08d9d0b6b5 --- /dev/null +++ b/models/model_calvetti_py/root.cpp @@ -0,0 +1,23 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "k.h" +#include "h.h" + +namespace amici { +namespace model_model_calvetti_py { + +void root_model_calvetti_py(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl){ + root[0] = t - 10; + root[1] = 10 - t; + root[2] = 12 - t; + root[3] = t - 12; +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/setup.py b/models/model_calvetti_py/setup.py new file mode 100644 index 0000000000..64c08d16c4 --- /dev/null +++ b/models/model_calvetti_py/setup.py @@ -0,0 +1,95 @@ +"""AMICI model package setup""" + +import os +import sys +from pathlib import Path + +from amici import _get_amici_path +from amici.custom_commands import AmiciBuildCMakeExtension +from cmake_build_extension import CMakeExtension +from setuptools import find_namespace_packages, setup +import importlib.metadata + + +def get_extension() -> CMakeExtension: + """Get setuptools extension object for this AMICI model package""" + + # Build shared object + prefix_path = Path(_get_amici_path()) + AmiciBuildCMakeExtension.extend_cmake_prefix_path(str(prefix_path)) + + # handle parallel building + # Note: can be empty to use all hardware threads + if (parallel_jobs := os.environ.get("AMICI_PARALLEL_COMPILE")) is not None: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = parallel_jobs + else: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = "1" + + debug_build = os.getenv("ENABLE_AMICI_DEBUGGING", "").lower() in [ + "1", + "true", + ] or os.getenv("ENABLE_GCOV_COVERAGE", "").lower() in ["1", "true"] + + cmake_prefix_path = os.getenv("CMAKE_PREFIX_PATH", "").split(os.pathsep) + cmake_prefix_path.append(prefix_path.as_posix()) + + # If scipy_openblas64 is installed, we make its cmake configuration + # available + amici_distribution = importlib.metadata.distribution("amici") + amici_dir = Path(amici_distribution.locate_file("")) + # this path is created during the amici build if scipy_openblas64 is used + openblas_cmake_dir = amici_dir / "lib" / "cmake" / "openblas" + if openblas_cmake_dir.exists(): + cmake_prefix_path.append(str(openblas_cmake_dir)) + + return CMakeExtension( + name="model_ext", + source_dir=os.getcwd(), + install_prefix="model_calvetti_py", + cmake_configure_options=[ + "-DCMAKE_VERBOSE_MAKEFILE=ON", + f"-DCMAKE_PREFIX_PATH='{';'.join(cmake_prefix_path)}'", + "-DAMICI_PYTHON_BUILD_EXT_ONLY=ON", + f"-DPython3_EXECUTABLE={Path(sys.executable).as_posix()}", + ], + cmake_build_type="Debug" if debug_build else "Release", + ) + + +# Change working directory to setup.py location +os.chdir(os.path.dirname(os.path.abspath(__file__))) + +MODEL_EXT = get_extension() + +CLASSIFIERS = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Science/Research", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python", + "Programming Language :: C++", + "Topic :: Scientific/Engineering :: Bio-Informatics", +] + +CMDCLASS = { + # for CMake-based builds + "build_ext": AmiciBuildCMakeExtension, +} + +# Install +setup( + name="model_calvetti_py", + cmdclass=CMDCLASS, + version="0.1.0", + description="AMICI-generated module for model model_calvetti_py", + url="https://github.com/AMICI-dev/AMICI", + author="model-author-todo", + author_email="model-author-todo", + ext_modules=[MODEL_EXT], + packages=find_namespace_packages(), + install_requires=["amici==0.33.0"], + python_requires=">=3.11", + package_data={}, + zip_safe=False, + classifiers=CLASSIFIERS, +) diff --git a/models/model_calvetti_py/sigmay.cpp b/models/model_calvetti_py/sigmay.cpp new file mode 100644 index 0000000000..2a5002587a --- /dev/null +++ b/models/model_calvetti_py/sigmay.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "k.h" +#include "y.h" +#include "sigmay.h" + +namespace amici { +namespace model_model_calvetti_py { + +void sigmay_model_calvetti_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y){ + sigma_obs_V1 = 1.0; // sigmay[0] + sigma_obs_V2 = 1.0; // sigmay[1] + sigma_obs_V3 = 1.0; // sigmay[2] + sigma_obs_f0 = 1.0; // sigmay[3] + sigma_obs_f1 = 1.0; // sigmay[4] + sigma_obs_f2 = 1.0; // sigmay[5] +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/sigmay.h b/models/model_calvetti_py/sigmay.h new file mode 100644 index 0000000000..08f7fff7df --- /dev/null +++ b/models/model_calvetti_py/sigmay.h @@ -0,0 +1,6 @@ +#define sigma_obs_V1 sigmay[0] +#define sigma_obs_V2 sigmay[1] +#define sigma_obs_V3 sigmay[2] +#define sigma_obs_f0 sigmay[3] +#define sigma_obs_f1 sigmay[4] +#define sigma_obs_f2 sigmay[5] diff --git a/models/model_calvetti_py/swig/CMakeLists.txt b/models/model_calvetti_py/swig/CMakeLists.txt new file mode 100644 index 0000000000..314996c479 --- /dev/null +++ b/models/model_calvetti_py/swig/CMakeLists.txt @@ -0,0 +1,60 @@ +if(DEFINED ENV{SWIG}) + set(SWIG_EXECUTABLE $ENV{SWIG}) +endif() + +find_package(SWIG REQUIRED) +include(${SWIG_USE_FILE}) + +if(DEFINED ENV{PYTHON_EXECUTABLE}) + set(Python3_EXECUTABLE $ENV{PYTHON_EXECUTABLE}) +endif() +# We don't need "Interpreter" here, but without that, FindPython3 will +# ignore the Python version selected via $Python3_EXECUTABLE +find_package(Python3 COMPONENTS Interpreter Development) +include_directories(${Python3_INCLUDE_DIRS}) + +set(SWIG_LIBRARY_NAME _${PROJECT_NAME}) +set(CMAKE_SWIG_FLAGS "") +set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) + +# swig does not use INTERFACE_INCLUDE_DIRS of linked libraries, so add manually +get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) +include_directories(${AMICI_INCLUDE_DIRS} .. ${AMICI_INCLUDE_DIRS}/../swig) + +swig_add_library(${SWIG_LIBRARY_NAME} + TYPE MODULE + LANGUAGE python + SOURCES ${PROJECT_NAME}.i) + + +set_target_properties(${SWIG_LIBRARY_NAME} + PROPERTIES + SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE + PREFIX "" +) + +# Python extension suffix +execute_process( + COMMAND ${Python3_EXECUTABLE} -c + "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))" + OUTPUT_VARIABLE PY_EXT_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE) +if(NOT "${PY_EXT_SUFFIX}" STREQUAL "") + message(STATUS "Python extension suffix is ${PY_EXT_SUFFIX}") + set_target_properties(${SWIG_LIBRARY_NAME} PROPERTIES SUFFIX "${PY_EXT_SUFFIX}" ) +endif() + + +swig_link_libraries(${SWIG_LIBRARY_NAME} + ${Python3_LIBRARIES} + model) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.py + $ DESTINATION .) + +# configure module setup script +set(SETUP_PY_IN ${Amici_DIR}/model_setup.template.py) +set(SETUP_PY_OUT ${CMAKE_CURRENT_BINARY_DIR}/setup.py) + +add_custom_target(install-python + DEPENDS ${SWIG_LIBRARY_NAME} + COMMAND python ${SETUP_PY_OUT} install) diff --git a/models/model_calvetti_py/swig/model_calvetti_py.i b/models/model_calvetti_py/swig/model_calvetti_py.i new file mode 100644 index 0000000000..0047056d52 --- /dev/null +++ b/models/model_calvetti_py/swig/model_calvetti_py.i @@ -0,0 +1,82 @@ +%define MODULEIMPORT +" +import amici +import datetime +import importlib.util +import os +import sysconfig +from pathlib import Path + +ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +_model_calvetti_py = amici._module_from_path( + 'model_calvetti_py._model_calvetti_py' if __package__ or '.' in __name__ + else '_model_calvetti_py', + Path(__file__).parent / f'_model_calvetti_py{ext_suffix}', +) + +def _get_import_time(): + return _model_calvetti_py._get_import_time() + +t_imported = _get_import_time() +t_modified = os.path.getmtime(__file__) +if t_imported < t_modified: + t_imp_str = datetime.datetime.fromtimestamp(t_imported).isoformat() + t_mod_str = datetime.datetime.fromtimestamp(t_modified).isoformat() + module_path = Path(__file__).resolve() + raise RuntimeError( + f'Cannot import extension for model_calvetti_py from ' + f'{module_path}, because an extension in the same location ' + f'has already been imported, but the file was modified on ' + f'disk. \\nImported at {t_imp_str}\\nModified at {t_mod_str}.\\n' + 'Import the module with a different name or restart the ' + 'Python kernel.' + ) +" +%enddef + +%module(package="model_calvetti_py",moduleimport=MODULEIMPORT) model_calvetti_py + +%pythoncode %{ +# the model-package __init__.py module (will be set during import) +_model_module = None + + +%} + +%import amici.i +// Add necessary symbols to generated header + +%{ +#include "wrapfunctions.h" +#include "amici/model_ode.h" +#include "amici/model_dae.h" +using namespace amici; +%} + +// store the time a module was imported +%{ +#include +static std::chrono::time_point _module_import_time; + +static double _get_import_time() { + auto epoch = _module_import_time.time_since_epoch(); + return std::chrono::duration(epoch).count(); +} +%} + +static double _get_import_time(); + +%init %{ + _module_import_time = std::chrono::system_clock::now(); +%} + + +// Make model module accessible from the model +%feature("pythonappend") amici::generic_model::getModel %{ + if '.' in __name__: + val.module = _model_module +%} + + +// Process symbols in header +%include "wrapfunctions.h" diff --git a/models/model_calvetti_py/sx.h b/models/model_calvetti_py/sx.h new file mode 100644 index 0000000000..de9e82ba2f --- /dev/null +++ b/models/model_calvetti_py/sx.h @@ -0,0 +1,6 @@ +#define sx0 sx[0] +#define sx1 sx[1] +#define sx2 sx[2] +#define sx3 sx[3] +#define sx4 sx[4] +#define sx5 sx[5] diff --git a/models/model_calvetti_py/w.cpp b/models/model_calvetti_py/w.cpp new file mode 100644 index 0000000000..9ddc51df48 --- /dev/null +++ b/models/model_calvetti_py/w.cpp @@ -0,0 +1,41 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "k.h" +#include "h.h" +#include "w.h" + +namespace amici { +namespace model_model_calvetti_py { + +void w_model_calvetti_py(realtype *w, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl, const realtype *spl, bool include_static){ + // static expressions + if (include_static) { + C1ss = V1ss/(1.0 - 0.5*R1ss); // w[0] + C2ss = V2ss/(-R1ss - 0.5*R2ss + 1.0); // w[1] + C3ss = V3ss/(-R1ss - R2ss - 0.5*R3ss + 1.0); // w[2] + L1 = std::pow(R1ss, 0.33333333333333331)*std::pow(std::fabs(V1ss), 0.66666666666666663); // w[3] + L2 = std::pow(R2ss, 0.33333333333333331)*std::pow(std::fabs(V2ss), 0.66666666666666663); // w[4] + L3 = std::pow(R3ss, 0.33333333333333331)*std::pow(std::fabs(V3ss), 0.66666666666666663); // w[5] + p2 = 1.0 - R1ss; // w[6] + p3 = -R1ss - R2ss + 1.0; // w[7] + } + + // dynamic expressions + s = Heaviside_0*Heaviside_2; // w[8] + R1 = std::pow(L1, 3)/std::pow(V1, 2); // w[9] + R2 = std::pow(L2, 3)/std::pow(V2, 2); // w[10] + R3 = std::pow(L3, 3)/std::pow(V3, 2); // w[11] + f0 = (-R3*f3 - f1*(R1 + R2) - f2*(R2 + R3))/R1 + 2/R1; // w[12] + rate_of_V1 = -100.0/899.0*V1/V1ss + (1.0/31.0)*s + 129.0/899.0 - 2.0/31.0*V1/(C1ss*(R3*f3 + f1*(R1 + R2) + f2*(R2 + R3))); // w[13] + rate_of_V2 = -100.0/8313.0*V2/V2ss + 151.0/8313.0 - 2.0/163.0*V2/(C2ss*(R3*f3 + f2*(R2 + R3))); // w[14] + rate_of_V3 = -1.0/121999878.0*V3/V3ss + 500000.0/60999939.0 - 1.0/61.0*V3/(C3ss*R3*f3); // w[15] +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/w.h b/models/model_calvetti_py/w.h new file mode 100644 index 0000000000..796ffea41b --- /dev/null +++ b/models/model_calvetti_py/w.h @@ -0,0 +1,17 @@ +#define C1ss w[0] +#define C2ss w[1] +#define C3ss w[2] +#define L1 w[3] +#define L2 w[4] +#define L3 w[5] +#define p2 w[6] +#define p3 w[7] +#define s w[8] +#define R1 w[9] +#define R2 w[10] +#define R3 w[11] +#define f0 w[12] +#define rate_of_V1 w[13] +#define rate_of_V2 w[14] +#define rate_of_V3 w[15] +#define flux_r0 w[16] diff --git a/models/model_calvetti_py/wrapfunctions.cpp b/models/model_calvetti_py/wrapfunctions.cpp new file mode 100644 index 0000000000..9061566fa9 --- /dev/null +++ b/models/model_calvetti_py/wrapfunctions.cpp @@ -0,0 +1,16 @@ +#include "wrapfunctions.h" +#include "model_calvetti_py.h" +#include "amici/model.h" + +namespace amici { +namespace generic_model { + +std::unique_ptr getModel() { + return std::unique_ptr( + new amici::model_model_calvetti_py::Model_model_calvetti_py() + ); +} + +} // namespace generic_model + +} // namespace amici diff --git a/models/model_calvetti_py/wrapfunctions.h b/models/model_calvetti_py/wrapfunctions.h new file mode 100644 index 0000000000..33c8a9d819 --- /dev/null +++ b/models/model_calvetti_py/wrapfunctions.h @@ -0,0 +1,25 @@ +#ifndef _amici_wrapfunctions_h +#define _amici_wrapfunctions_h + +#include + +#include "amici/model.h" + +namespace amici { +namespace generic_model { + + +/** + * @brief Wrapper function to instantiate the linked Amici model without knowing + * the name at compile time. + * @return Model instance + */ +std::unique_ptr getModel(); + + +} // namespace generic_model + +} // namespace amici + + +#endif /* _amici_wrapfunctions_h */ diff --git a/models/model_calvetti_py/x.h b/models/model_calvetti_py/x.h new file mode 100644 index 0000000000..a86417f22f --- /dev/null +++ b/models/model_calvetti_py/x.h @@ -0,0 +1,6 @@ +#define V1 x[0] +#define V2 x[1] +#define V3 x[2] +#define f1 x[3] +#define f2 x[4] +#define f3 x[5] diff --git a/models/model_calvetti_py/x0.cpp b/models/model_calvetti_py/x0.cpp new file mode 100644 index 0000000000..afb3da3c19 --- /dev/null +++ b/models/model_calvetti_py/x0.cpp @@ -0,0 +1,23 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "k.h" + +namespace amici { +namespace model_model_calvetti_py { + +void x0_model_calvetti_py(realtype *x0, const realtype t, const realtype *p, const realtype *k){ + x0[0] = V1ss; + x0[1] = V2ss; + x0[2] = V3ss; + x0[3] = 1.0; + x0[4] = 1.0; + x0[5] = 1.0; +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/x0_fixedParameters.cpp b/models/model_calvetti_py/x0_fixedParameters.cpp new file mode 100644 index 0000000000..0f8960d6e7 --- /dev/null +++ b/models/model_calvetti_py/x0_fixedParameters.cpp @@ -0,0 +1,23 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "k.h" + +namespace amici { +namespace model_model_calvetti_py { + +void x0_fixedParameters_model_calvetti_py(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs){ + if(std::find(reinitialization_state_idxs.cbegin(), reinitialization_state_idxs.cend(), 0) != reinitialization_state_idxs.cend()) + x0_fixedParameters[0] = V1ss; + if(std::find(reinitialization_state_idxs.cbegin(), reinitialization_state_idxs.cend(), 1) != reinitialization_state_idxs.cend()) + x0_fixedParameters[1] = V2ss; + if(std::find(reinitialization_state_idxs.cbegin(), reinitialization_state_idxs.cend(), 2) != reinitialization_state_idxs.cend()) + x0_fixedParameters[2] = V3ss; +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/xB.h b/models/model_calvetti_py/xB.h new file mode 100644 index 0000000000..be1e85170d --- /dev/null +++ b/models/model_calvetti_py/xB.h @@ -0,0 +1,6 @@ +#define xB0 xB[0] +#define xB1 xB[1] +#define xB2 xB[2] +#define xB3 xB[3] +#define xB4 xB[4] +#define xB5 xB[5] diff --git a/models/model_calvetti_py/x_old.h b/models/model_calvetti_py/x_old.h new file mode 100644 index 0000000000..bff664c87e --- /dev/null +++ b/models/model_calvetti_py/x_old.h @@ -0,0 +1,6 @@ +#define x_old0 x_old[0] +#define x_old1 x_old[1] +#define x_old2 x_old[2] +#define x_old3 x_old[3] +#define x_old4 x_old[4] +#define x_old5 x_old[5] diff --git a/models/model_calvetti_py/x_rdata.cpp b/models/model_calvetti_py/x_rdata.cpp new file mode 100644 index 0000000000..bc37e262f3 --- /dev/null +++ b/models/model_calvetti_py/x_rdata.cpp @@ -0,0 +1,24 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "k.h" + +namespace amici { +namespace model_model_calvetti_py { + +void x_rdata_model_calvetti_py(realtype *x_rdata, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k){ + x_rdata[0] = V1; + x_rdata[1] = V2; + x_rdata[2] = V3; + x_rdata[3] = f1; + x_rdata[4] = f2; + x_rdata[5] = f3; +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/x_rdata.h b/models/model_calvetti_py/x_rdata.h new file mode 100644 index 0000000000..891524e885 --- /dev/null +++ b/models/model_calvetti_py/x_rdata.h @@ -0,0 +1,6 @@ +#define V1 x_rdata[0] +#define V2 x_rdata[1] +#define V3 x_rdata[2] +#define f1 x_rdata[3] +#define f2 x_rdata[4] +#define f3 x_rdata[5] diff --git a/models/model_calvetti_py/x_solver.cpp b/models/model_calvetti_py/x_solver.cpp new file mode 100644 index 0000000000..30e74929be --- /dev/null +++ b/models/model_calvetti_py/x_solver.cpp @@ -0,0 +1,23 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x_rdata.h" + +namespace amici { +namespace model_model_calvetti_py { + +void x_solver_model_calvetti_py(realtype *x_solver, const realtype *x_rdata){ + x_solver[0] = V1; + x_solver[1] = V2; + x_solver[2] = V3; + x_solver[3] = f1; + x_solver[4] = f2; + x_solver[5] = f3; +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/x_solver.h b/models/model_calvetti_py/x_solver.h new file mode 100644 index 0000000000..bd271c9f1f --- /dev/null +++ b/models/model_calvetti_py/x_solver.h @@ -0,0 +1,6 @@ +#define x_solver0 x_solver[0] +#define x_solver1 x_solver[1] +#define x_solver2 x_solver[2] +#define x_solver3 x_solver[3] +#define x_solver4 x_solver[4] +#define x_solver5 x_solver[5] diff --git a/models/model_calvetti_py/xdot.cpp b/models/model_calvetti_py/xdot.cpp new file mode 100644 index 0000000000..a6ed253282 --- /dev/null +++ b/models/model_calvetti_py/xdot.cpp @@ -0,0 +1,28 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "k.h" +#include "h.h" +#include "dx.h" +#include "w.h" +#include "xdot.h" + +namespace amici { +namespace model_model_calvetti_py { + +void xdot_model_calvetti_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w){ + de_0 = -dV1dt + rate_of_V1; // xdot[0] + de_1 = -dV2dt + rate_of_V2; // xdot[1] + de_2 = -dV3dt + rate_of_V3; // xdot[2] + ae_0 = f0 - f1 - rate_of_V1; // xdot[3] + ae_1 = f1 - f2 - rate_of_V2; // xdot[4] + ae_2 = f2 - f3 - rate_of_V3; // xdot[5] +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/xdot.h b/models/model_calvetti_py/xdot.h new file mode 100644 index 0000000000..eed9ba1410 --- /dev/null +++ b/models/model_calvetti_py/xdot.h @@ -0,0 +1,6 @@ +#define de_0 xdot[0] +#define de_1 xdot[1] +#define de_2 xdot[2] +#define ae_0 xdot[3] +#define ae_1 xdot[4] +#define ae_2 xdot[5] diff --git a/models/model_calvetti_py/xdot_old.h b/models/model_calvetti_py/xdot_old.h new file mode 100644 index 0000000000..a263a0e4c6 --- /dev/null +++ b/models/model_calvetti_py/xdot_old.h @@ -0,0 +1,6 @@ +#define xdot_old0 xdot_old[0] +#define xdot_old1 xdot_old[1] +#define xdot_old2 xdot_old[2] +#define xdot_old3 xdot_old[3] +#define xdot_old4 xdot_old[4] +#define xdot_old5 xdot_old[5] diff --git a/models/model_calvetti_py/y.cpp b/models/model_calvetti_py/y.cpp new file mode 100644 index 0000000000..d92022d493 --- /dev/null +++ b/models/model_calvetti_py/y.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "k.h" +#include "h.h" +#include "w.h" + +namespace amici { +namespace model_model_calvetti_py { + +void y_model_calvetti_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + y[0] = V1; + y[1] = V2; + y[2] = V3; + y[3] = f0; + y[4] = f1; + y[5] = f2; +} + +} // namespace model_model_calvetti_py +} // namespace amici diff --git a/models/model_calvetti_py/y.h b/models/model_calvetti_py/y.h new file mode 100644 index 0000000000..f378c7bc9f --- /dev/null +++ b/models/model_calvetti_py/y.h @@ -0,0 +1,6 @@ +#define obs_V1 y[0] +#define obs_V2 y[1] +#define obs_V3 y[2] +#define obs_f0 y[3] +#define obs_f1 y[4] +#define obs_f2 y[5] diff --git a/models/model_dirac_py/.gitignore b/models/model_dirac_py/.gitignore new file mode 100644 index 0000000000..fa29cdfff9 --- /dev/null +++ b/models/model_dirac_py/.gitignore @@ -0,0 +1 @@ +** \ No newline at end of file diff --git a/models/model_dirac_py/CMakeLists.txt b/models/model_dirac_py/CMakeLists.txt new file mode 100644 index 0000000000..5ae41874a9 --- /dev/null +++ b/models/model_dirac_py/CMakeLists.txt @@ -0,0 +1,148 @@ +# Build AMICI model +cmake_minimum_required(VERSION 3.22) +cmake_policy(VERSION 3.22...3.31) + +project(model_dirac_py) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +include(CheckCXXCompilerFlag) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() +foreach(flag ${MY_CXX_FLAGS}) + unset(CUR_FLAG_SUPPORTED CACHE) + check_cxx_compiler_flag(${flag} CUR_FLAG_SUPPORTED) + if(${CUR_FLAG_SUPPORTED}) + string(APPEND CMAKE_CXX_FLAGS " ${flag}") + endif() +endforeach() + +if(DEFINED ENV{AMICI_CXXFLAGS}) + message(STATUS "Appending flags from AMICI_CXXFLAGS: $ENV{AMICI_CXXFLAGS}") + add_compile_options("$ENV{AMICI_CXXFLAGS}") +endif() +if(DEFINED ENV{AMICI_LDFLAGS}) + message(STATUS "Appending flags from AMICI_LDFLAGS: $ENV{AMICI_LDFLAGS}") + link_libraries("$ENV{AMICI_LDFLAGS}") +endif() + +find_package(Amici 0.33.0 REQUIRED HINTS + ${CMAKE_CURRENT_LIST_DIR}/../../build) +message(STATUS "Found AMICI ${Amici_DIR}") +set_target_properties(Upstream::amici PROPERTIES + MAP_IMPORTED_CONFIG_RELWITHDEBINFO RelWithDebInfo;Release; + MAP_IMPORTED_CONFIG_RELEASE Release + MAP_IMPORTED_CONFIG_DEBUG Debug;RelWithDebInfo;) + +# Debug build? +if("$ENV{ENABLE_AMICI_DEBUGGING}" OR "$ENV{ENABLE_GCOV_COVERAGE}") + add_compile_options(-UNDEBUG) + if(MSVC) + add_compile_options(-DEBUG) + else() + add_compile_options(-O0 -g) + endif() +endif() + +# coverage options +if($ENV{ENABLE_GCOV_COVERAGE}) + string(APPEND CMAKE_CXX_FLAGS_DEBUG " --coverage") + string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " --coverage") +endif() + +set(MODEL_DIR ${CMAKE_CURRENT_LIST_DIR}) + +set(SRC_LIST_LIB Jy.cpp +Jy.h +create_splines.cpp +dJydsigma.cpp +dJydy.cpp +dJydy.h +deltaqB.cpp +deltasx.cpp +deltax.cpp +dxdotdp_explicit.cpp +dxdotdp_explicit.h +dxdotdx_explicit.cpp +dxdotdx_explicit.h +dydx.cpp +h.h +model_dirac_py.cpp +model_dirac_py.h +my.h +p.h +root.cpp +sigmay.cpp +sigmay.h +stau.cpp +stau.h +sx.h +w.h +wrapfunctions.cpp +wrapfunctions.h +x.h +xB.h +x_old.h +x_rdata.cpp +x_rdata.h +x_solver.cpp +x_solver.h +xdot.cpp +xdot.h +xdot_old.h +y.cpp +y.h ${MODEL_DIR}/wrapfunctions.cpp) + +add_library(${PROJECT_NAME} ${SRC_LIST_LIB}) + +# ${PROJECT_NAME} might already be "model" +if(NOT TARGET model) + add_library(model ALIAS ${PROJECT_NAME}) +endif() + +# Some special functions require boost +# +# TODO: set some flag during code generation whether the given model requires +# boost. for now, try to find it, add include directories and link against it. +# let the compiler/linker error if it is required but not found +find_package(Boost) + +target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") + +target_link_libraries( + ${PROJECT_NAME} + PUBLIC Upstream::amici + PRIVATE $<$:Boost::boost>) + +if(NOT "${AMICI_PYTHON_BUILD_EXT_ONLY}") + set(SRC_LIST_EXE main.cpp) + add_executable(simulate_${PROJECT_NAME} ${SRC_LIST_EXE}) + target_link_libraries(simulate_${PROJECT_NAME} ${PROJECT_NAME}) +endif() + +# SWIG +option(ENABLE_SWIG "Build swig/python library?" ON) +if(ENABLE_SWIG) + add_subdirectory(swig) +endif() + +# +include(GNUInstallDirs) +install( + TARGETS ${PROJECT_NAME} + EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +export( + EXPORT ${PROJECT_NAME}Targets + FILE ${PROJECT_NAME}Config.cmake + NAMESPACE Upstream::) +# diff --git a/models/model_dirac_py/Jy.cpp b/models/model_dirac_py/Jy.cpp new file mode 100644 index 0000000000..8a372baf54 --- /dev/null +++ b/models/model_dirac_py/Jy.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_dirac_py { + +void Jy_model_dirac_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_x2, 2)) + 0.5*std::pow(-mobs_x2 + obs_x2, 2)/std::pow(sigma_obs_x2, 2); + break; + } +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/Jy.h b/models/model_dirac_py/Jy.h new file mode 100644 index 0000000000..6b49699ace --- /dev/null +++ b/models/model_dirac_py/Jy.h @@ -0,0 +1 @@ +#define Jy0 Jy[0] diff --git a/models/model_dirac_py/MANIFEST.in b/models/model_dirac_py/MANIFEST.in new file mode 100644 index 0000000000..fd78129853 --- /dev/null +++ b/models/model_dirac_py/MANIFEST.in @@ -0,0 +1,3 @@ +include *.cpp *.h +include CMakeLists.txt +recursive-include swig/ * diff --git a/models/model_dirac_py/create_splines.cpp b/models/model_dirac_py/create_splines.cpp new file mode 100644 index 0000000000..47eb6cdb90 --- /dev/null +++ b/models/model_dirac_py/create_splines.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "amici/splinefunctions.h" +#include +#include "p.h" + +namespace amici { +namespace model_model_dirac_py { + +std::vector create_splines_model_dirac_py(const realtype *p, const realtype *k){ + return {}; +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/dJydsigma.cpp b/models/model_dirac_py/dJydsigma.cpp new file mode 100644 index 0000000000..3f77eb81e3 --- /dev/null +++ b/models/model_dirac_py/dJydsigma.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_dirac_py { + +void dJydsigma_model_dirac_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydsigma[0] = 1.0/sigma_obs_x2 - 1.0*std::pow(-mobs_x2 + obs_x2, 2)/std::pow(sigma_obs_x2, 3); + break; + } +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/dJydy.cpp b/models/model_dirac_py/dJydy.cpp new file mode 100644 index 0000000000..0fe5a1d858 --- /dev/null +++ b/models/model_dirac_py/dJydy.cpp @@ -0,0 +1,67 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_dirac_py { + +static constexpr std::array, 1> dJydy_colptrs_model_dirac_py_ = {{ + {0, 1}, +}}; + +void dJydy_colptrs_model_dirac_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexptrs(gsl::make_span(dJydy_colptrs_model_dirac_py_[index])); +} +} // namespace model_model_dirac_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_dirac_py { + +static constexpr std::array, 1> dJydy_rowvals_model_dirac_py_ = {{ + {0}, +}}; + +void dJydy_rowvals_model_dirac_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexvals(gsl::make_span(dJydy_rowvals_model_dirac_py_[index])); +} +} // namespace model_model_dirac_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" +#include "dJydy.h" + +namespace amici { +namespace model_model_dirac_py { + +void dJydy_model_dirac_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydy[0] = (-1.0*mobs_x2 + 1.0*obs_x2)/std::pow(sigma_obs_x2, 2); + break; + } +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/dJydy.h b/models/model_dirac_py/dJydy.h new file mode 100644 index 0000000000..98b0565ecc --- /dev/null +++ b/models/model_dirac_py/dJydy.h @@ -0,0 +1 @@ +#define dJy0_dobs_x2 dJydy[0] diff --git a/models/model_dirac_py/deltaqB.cpp b/models/model_dirac_py/deltaqB.cpp new file mode 100644 index 0000000000..98d79c94e5 --- /dev/null +++ b/models/model_dirac_py/deltaqB.cpp @@ -0,0 +1,32 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "xdot.h" +#include "xdot_old.h" +#include "x_old.h" +#include "xB.h" + +namespace amici { +namespace model_model_dirac_py { + +void deltaqB_model_dirac_py(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB){ + switch(ie) { + case 0: + switch(ip) { + case 1: + deltaqB[0] = xB0*(-dx1dt + xdot_old0) + xB1*(-dx2dt + xdot_old1); + break; + } + break; + } +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/deltasx.cpp b/models/model_dirac_py/deltasx.cpp new file mode 100644 index 0000000000..4b6455495f --- /dev/null +++ b/models/model_dirac_py/deltasx.cpp @@ -0,0 +1,37 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "xdot.h" +#include "xdot_old.h" +#include "sx.h" +#include "stau.h" +#include "x_old.h" + +namespace amici { +namespace model_model_dirac_py { + +void deltasx_model_dirac_py(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old){ + switch(ie) { + case 0: + switch(ip) { + case 0: + case 1: + case 2: + case 3: + deltasx[0] = stau0*(dx1dt - xdot_old0); + deltasx[1] = stau0*(dx2dt - xdot_old1); + break; + } + break; + } +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/deltax.cpp b/models/model_dirac_py/deltax.cpp new file mode 100644 index 0000000000..c35ff1cb1b --- /dev/null +++ b/models/model_dirac_py/deltax.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "xdot.h" +#include "x_old.h" + +namespace amici { +namespace model_model_dirac_py { + +void deltax_model_dirac_py(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old){ + switch(ie) { + case 0: + deltax[0] = -x1 + x_old0 + 1; + break; + } +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/dxdotdp_explicit.cpp b/models/model_dirac_py/dxdotdp_explicit.cpp new file mode 100644 index 0000000000..53dc6ff5c5 --- /dev/null +++ b/models/model_dirac_py/dxdotdp_explicit.cpp @@ -0,0 +1,65 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_dirac_py { + +static constexpr std::array dxdotdp_explicit_colptrs_model_dirac_py_ = { + 0, 1, 1, 2, 3 +}; + +void dxdotdp_explicit_colptrs_model_dirac_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexptrs(gsl::make_span(dxdotdp_explicit_colptrs_model_dirac_py_)); +} +} // namespace model_model_dirac_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_dirac_py { + +static constexpr std::array dxdotdp_explicit_rowvals_model_dirac_py_ = { + 0, 1, 1 +}; + +void dxdotdp_explicit_rowvals_model_dirac_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexvals(gsl::make_span(dxdotdp_explicit_rowvals_model_dirac_py_)); +} +} // namespace model_model_dirac_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "w.h" +#include "dxdotdp_explicit.h" + +namespace amici { +namespace model_model_dirac_py { + +void dxdotdp_explicit_model_dirac_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + ddx1dt_dp1 = -x1; // dxdotdp_explicit[0] + ddx2dt_dp3 = x1; // dxdotdp_explicit[1] + ddx2dt_dp4 = -x2; // dxdotdp_explicit[2] +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/dxdotdp_explicit.h b/models/model_dirac_py/dxdotdp_explicit.h new file mode 100644 index 0000000000..0c9f008bf0 --- /dev/null +++ b/models/model_dirac_py/dxdotdp_explicit.h @@ -0,0 +1,3 @@ +#define ddx1dt_dp1 dxdotdp_explicit[0] +#define ddx2dt_dp3 dxdotdp_explicit[1] +#define ddx2dt_dp4 dxdotdp_explicit[2] diff --git a/models/model_dirac_py/dxdotdx_explicit.cpp b/models/model_dirac_py/dxdotdx_explicit.cpp new file mode 100644 index 0000000000..8eaf0a8fc2 --- /dev/null +++ b/models/model_dirac_py/dxdotdx_explicit.cpp @@ -0,0 +1,65 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_dirac_py { + +static constexpr std::array dxdotdx_explicit_colptrs_model_dirac_py_ = { + 0, 2, 3 +}; + +void dxdotdx_explicit_colptrs_model_dirac_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexptrs(gsl::make_span(dxdotdx_explicit_colptrs_model_dirac_py_)); +} +} // namespace model_model_dirac_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_dirac_py { + +static constexpr std::array dxdotdx_explicit_rowvals_model_dirac_py_ = { + 0, 1, 1 +}; + +void dxdotdx_explicit_rowvals_model_dirac_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexvals(gsl::make_span(dxdotdx_explicit_rowvals_model_dirac_py_)); +} +} // namespace model_model_dirac_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "w.h" +#include "dxdotdx_explicit.h" + +namespace amici { +namespace model_model_dirac_py { + +void dxdotdx_explicit_model_dirac_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + ddx1dt_dx1 = -p1; // dxdotdx_explicit[0] + ddx2dt_dx1 = p3; // dxdotdx_explicit[1] + ddx2dt_dx2 = -p4; // dxdotdx_explicit[2] +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/dxdotdx_explicit.h b/models/model_dirac_py/dxdotdx_explicit.h new file mode 100644 index 0000000000..75d0d46ca6 --- /dev/null +++ b/models/model_dirac_py/dxdotdx_explicit.h @@ -0,0 +1,3 @@ +#define ddx1dt_dx1 dxdotdx_explicit[0] +#define ddx2dt_dx1 dxdotdx_explicit[1] +#define ddx2dt_dx2 dxdotdx_explicit[2] diff --git a/models/model_dirac_py/dydx.cpp b/models/model_dirac_py/dydx.cpp new file mode 100644 index 0000000000..5354e78bee --- /dev/null +++ b/models/model_dirac_py/dydx.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" + +namespace amici { +namespace model_model_dirac_py { + +void dydx_model_dirac_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx){ + dydx[1] = 1; +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/h.h b/models/model_dirac_py/h.h new file mode 100644 index 0000000000..9ca3a1f981 --- /dev/null +++ b/models/model_dirac_py/h.h @@ -0,0 +1 @@ +#define _E0 h[0] diff --git a/models/model_dirac_py/main.cpp b/models/model_dirac_py/main.cpp new file mode 100644 index 0000000000..ecdff85a46 --- /dev/null +++ b/models/model_dirac_py/main.cpp @@ -0,0 +1,93 @@ +#include + +#include "wrapfunctions.h" /* model-provided functions */ +#include /* AMICI base functions */ + +template +std::ostream& operator<<(std::ostream& os, std::vector const& v) { + os << "["; + for (typename std::vector::const_iterator ii = v.begin(); ii != v.end(); + ++ii) { + os << " " << *ii; + } + os << "]"; + return os; +} + +/* + * This is a scaffold for a stand-alone AMICI simulation executable + * demonstrating the basic use of the AMICI C++ API. + */ + +int main() { + std::cout << "********************************" << std::endl; + std::cout << "** Running forward simulation **" << std::endl; + std::cout << "********************************" << std::endl << std::endl; + + // Create a model instance + auto model = amici::generic_model::getModel(); + + // Set desired output timepoints + model->setTimepoints({0.0, 1.0, 10.0, 100.0, 1000.0}); + + // Create a solver instance + auto solver = model->getSolver(); + + // Optionally set integration tolerance + solver->setAbsoluteTolerance(1e-16); + solver->setRelativeTolerance(1e-8); + + // Run the simulation using default parameters set during model import + // (can be changed using model->setParameters() or model->setParameterBy*()) + auto rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print observable time course + auto observable_ids = model->getObservableIds(); + std::cout << "Simulated observables for timepoints " << rdata->ts << "\n\n"; + for (int i_observable = 0; i_observable < rdata->ny; ++i_observable) { + std::cout << observable_ids[i_observable] << ":\n\t"; + for (int i_time = 0; i_time < rdata->nt; ++i_time) { + // rdata->y is a flat 2D array in row-major ordering + std::cout << rdata->y[i_time * rdata->ny + i_observable] << " "; + } + std::cout << std::endl << std::endl; + } + + std::cout << std::endl; + std::cout << "**********************************" << std::endl; + std::cout << "** Forward sensitivity analysis **" << std::endl; + std::cout << "**********************************" << std::endl << std::endl; + + // Enable first-order sensitivity analysis + solver->setSensitivityOrder(amici::SensitivityOrder::first); + // Use forward sensitivities + solver->setSensitivityMethod(amici::SensitivityMethod::forward); + + // Run the simulation + rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print state sensitivities sx... + // ... for the first timepoint... + int i_time = 0; + // ... with respect to the first parameter + int i_nplist = 0; + + // get identifiers from model + auto state_ids = model->getStateIds(); + auto parameter_ids = model->getParameterIds(); + + std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] + << std::endl; // nt x nplist x nx + for (int i_state = 0; i_state < rdata->nx; ++i_state) { + std::cout << "\td(" << state_ids[i_state] << ")/d(" + << parameter_ids[model->plist(i_nplist)] << ") = "; + + // rdata->sx is a flat 3D array in row-major ordering + std::cout << rdata->sx + [i_time * rdata->nplist * rdata->nx + + i_nplist * rdata->nx + i_state]; + std::cout << std::endl; + } + + return 0; +} diff --git a/models/model_dirac_py/model_dirac_py.cpp b/models/model_dirac_py/model_dirac_py.cpp new file mode 100644 index 0000000000..b12c0da08a --- /dev/null +++ b/models/model_dirac_py/model_dirac_py.cpp @@ -0,0 +1,70 @@ +#include +#include + +namespace amici { + +namespace model_model_dirac_py { + +// clang-format off + +std::array parameterNames = { + "p1", // p[0] +"p2", // p[1] +"p3", // p[2] +"p4", // p[3] +}; + +std::array fixedParameterNames = { + +}; + +std::array stateNames = { + "x1", // x_rdata[0] +"x2", // x_rdata[1] +}; + +std::array observableNames = { + "y0", // y[0] +}; + +std::array observableScalings = { + ObservableScaling::lin, // y[0] +}; + +std::array expressionNames = { + "flux_r0", // w[0] +}; + +std::array parameterIds = { + "p1", // p[0] +"p2", // p[1] +"p3", // p[2] +"p4", // p[3] +}; + +std::array fixedParameterIds = { + +}; + +std::array stateIds = { + "x1", // x_rdata[0] +"x2", // x_rdata[1] +}; + +std::array observableIds = { + "obs_x2", // y[0] +}; + +std::array expressionIds = { + "flux_r0", // w[0] +}; + +std::array stateIdxsSolver = { + 0, 1 +}; + +// clang-format on + +} // namespace model_model_dirac_py + +} // namespace amici diff --git a/models/model_dirac_py/model_dirac_py.h b/models/model_dirac_py/model_dirac_py.h new file mode 100644 index 0000000000..5162fc0637 --- /dev/null +++ b/models/model_dirac_py/model_dirac_py.h @@ -0,0 +1,561 @@ +#ifndef _amici_TPL_MODELNAME_h +#define _amici_TPL_MODELNAME_h +#include +#include +#include + +#include "amici/model_ode.h" +#include "amici/splinefunctions.h" +#include "amici/event.h" + +namespace amici { + +class Solver; + +namespace model_model_dirac_py { + +extern std::array parameterNames; +extern std::array fixedParameterNames; +extern std::array stateNames; +extern std::array observableNames; +extern std::array observableScalings; +extern std::array expressionNames; +extern std::array parameterIds; +extern std::array fixedParameterIds; +extern std::array stateIds; +extern std::array observableIds; +extern std::array expressionIds; +extern std::array stateIdxsSolver; + +extern void Jy_model_dirac_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydsigma_model_dirac_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_model_dirac_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_colptrs_model_dirac_py(SUNMatrixWrapper &colptrs, int index); +extern void dJydy_rowvals_model_dirac_py(SUNMatrixWrapper &rowvals, int index); + + + + + + +extern void root_model_dirac_py(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl); + + + + + + + + + + + + +extern void dxdotdp_explicit_model_dirac_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void dxdotdp_explicit_colptrs_model_dirac_py(SUNMatrixWrapper &colptrs); +extern void dxdotdp_explicit_rowvals_model_dirac_py(SUNMatrixWrapper &rowvals); +extern void dxdotdx_explicit_model_dirac_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void dxdotdx_explicit_colptrs_model_dirac_py(SUNMatrixWrapper &colptrs); +extern void dxdotdx_explicit_rowvals_model_dirac_py(SUNMatrixWrapper &rowvals); +extern void dydx_model_dirac_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx); + + + + + +extern void sigmay_model_dirac_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y); + + + + + + + + + +extern void xdot_model_dirac_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void y_model_dirac_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); + + +extern void stau_model_dirac_py(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie); +extern void deltax_model_dirac_py(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old); +extern void deltasx_model_dirac_py(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old); + +extern void deltaqB_model_dirac_py(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB); + +extern void x_solver_model_dirac_py(realtype *x_solver, const realtype *x_rdata); + + + + + + + + + + + + +extern std::vector create_splines_model_dirac_py(const realtype *p, const realtype *k); + + + +/** + * @brief AMICI-generated model subclass. + */ +class Model_model_dirac_py : public amici::Model_ODE { + public: + /** + * @brief Default constructor. + */ + Model_model_dirac_py() + : amici::Model_ODE( + amici::ModelDimensions( + 2, // nx_rdata + 2, // nxtrue_rdata + 2, // nx_solver + 2, // nxtrue_solver + 0, // nx_solver_reinit + 4, // np + 0, // nk + 1, // ny + 1, // nytrue + 0, // nz + 0, // nztrue + 1, // nevent + 1, // nevent_solver + 0, // nspl + 1, // nobjective + 1, // nw + 0, // ndwdx + 0, // ndwdp + 0, // ndwdw + 0, // ndxdotdw + std::vector{1}, // ndjydy + 0, // ndxrdatadxsolver + 0, // ndxrdatadtcl + 0, // ndtotal_cldx_rdata + 0, // nnz + 2, // ubw + 2, // lbw + true, // pythonGenerated + 3, // ndxdotdp_explicit + 3, // ndxdotdx_explicit + 0 // w_recursion_depth + ), + amici::SimulationParameters( + std::vector{}, // fixedParameters + std::vector{1.0, 0.5, 2.0, 3.0} // dynamic parameters + ), + amici::SecondOrderMode::none, // o2mode + std::vector{1.0, 1.0}, // idlist + std::vector{}, // z2events + std::vector{ + Event("_E0", true, true, NAN) + }, // events + {} // state-independent events + ) { + } + + /** + * @brief Clone this model instance. + * @return A deep copy of this instance. + */ + amici::Model *clone() const override { + return new Model_model_dirac_py(*this); + } + + void fJrz(realtype *Jrz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fJy(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + Jy_model_dirac_py(Jy, iy, p, k, y, sigmay, my); + } + + + void fJz(realtype *Jz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override {} + + + void fdJrzdsigma(realtype *dJrzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fdJrzdz(realtype *dJrzdz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fdJydsigma(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydsigma_model_dirac_py(dJydsigma, iy, p, k, y, sigmay, my); + } + + + void fdJzdsigma(realtype *dJzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override {} + + + void fdJzdz(realtype *dJzdz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const double *mz) override {} + + + void fdeltax(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old) override { + deltax_model_dirac_py(deltax, t, x, p, k, h, ie, xdot, xdot_old, x_old); + } + + + void fdeltasx(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old) override { + deltasx_model_dirac_py(deltasx, t, x, p, k, h, w, ip, ie, xdot, xdot_old, sx, stau, tcl, x_old); + } + + + void fdeltaxB(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl) override {} + + + void fdeltaqB(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB) override { + deltaqB_model_dirac_py(deltaqB, t, x, p, k, h, dx, ip, ie, xdot, xdot_old, x_old, xB); + } + + + void fdrzdp(realtype *drzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdrzdx(realtype *drzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void fdsigmaydp(realtype *dsigmaydp, const realtype t, const realtype *p, const realtype *k, const realtype *y, const int ip) override {} + + + void fdsigmaydy(realtype *dsigmaydy, const realtype t, const realtype *p, const realtype *k, const realtype *y) override {} + + + void fdsigmazdp(realtype *dsigmazdp, const realtype t, const realtype *p, const realtype *k, const int ip) override {} + + + void fdJydy(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydy_model_dirac_py(dJydy, iy, p, k, y, sigmay, my); + } + + void fdJydy_colptrs(SUNMatrixWrapper &colptrs, int index) override { + dJydy_colptrs_model_dirac_py(colptrs, index); + } + + void fdJydy_rowvals(SUNMatrixWrapper &rowvals, int index) override { + dJydy_rowvals_model_dirac_py(rowvals, index); + } + + + std::vector fcreate_splines(const realtype *p, const realtype *k) override { + return create_splines_model_dirac_py(p, k); + } + + void fdspline_valuesdp(realtype *dspline_valuesdp, const realtype *p, const realtype *k, const int ip) override {} + + void fdspline_slopesdp(realtype *dspline_slopesdp, const realtype *p, const realtype *k, const int ip) override {} + + + void fdwdp(realtype *dwdp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl, bool include_static) override {} + + void fdwdp_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdp_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdx(realtype *dwdx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *spl, bool include_static) override {} + + void fdwdx_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdx_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdw(realtype *dwdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, bool include_static) override {} + + void fdwdw_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdw_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdw(realtype *dxdotdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override {} + + void fdxdotdw_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdxdotdw_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdp_explicit(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + dxdotdp_explicit_model_dirac_py(dxdotdp_explicit, t, x, p, k, h, w); + } + + void fdxdotdp_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdp_explicit_colptrs_model_dirac_py(colptrs); + } + + void fdxdotdp_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdp_explicit_rowvals_model_dirac_py(rowvals); + } + + + void fdxdotdx_explicit(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + dxdotdx_explicit_model_dirac_py(dxdotdx_explicit, t, x, p, k, h, w); + } + + void fdxdotdx_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdx_explicit_colptrs_model_dirac_py(colptrs); + } + + void fdxdotdx_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdx_explicit_rowvals_model_dirac_py(rowvals); + } + + + void fdydx(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { + dydx_model_dirac_py(dydx, t, x, p, k, h, w, dwdx); + } + + + void fdydp(realtype *dydp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl) override {} + + + void fdzdp(realtype *dzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdzdx(realtype *dzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void froot(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl) override { + root_model_dirac_py(root, t, x, p, k, h, tcl); + } + + + void frz(realtype *rz, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void fsigmay(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y) override { + sigmay_model_dirac_py(sigmay, t, p, k, y); + } + + + void fsigmaz(realtype *sigmaz, const realtype t, const realtype *p, const realtype *k) override {} + + + void fstau(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie) override { + stau_model_dirac_py(stau, t, x, p, k, h, dx, tcl, sx, ip, ie); + } + + void fsx0(realtype *sx0, const realtype t, const realtype *x, const realtype *p, const realtype *k, const int ip) override {} + + void fsx0_fixedParameters(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs) override {} + + + void fw(realtype *w, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl, const realtype *spl, bool include_static) override {} + + + void fx0(realtype *x0, const realtype t, const realtype *p, const realtype *k) override {} + + + void fx0_fixedParameters(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs) override {} + + + void fxdot(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + xdot_model_dirac_py(xdot, t, x, p, k, h, w); + } + + + void fy(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + y_model_dirac_py(y, t, x, p, k, h, w); + } + + + void fz(realtype *z, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + + + void fx_solver(realtype *x_solver, const realtype *x_rdata) override { + x_solver_model_dirac_py(x_solver, x_rdata); + } + + + void ftotal_cl(realtype *total_cl, const realtype *x_rdata, const realtype *p, const realtype *k) override {} + + + void fdx_rdatadx_solver(realtype *dx_rdatadx_solver, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadx_solver_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadx_solver_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdx_rdatadp(realtype *dx_rdatadp, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k, const int ip) override {} + + + void fdx_rdatadtcl(realtype *dx_rdatadtcl, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadtcl_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadtcl_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdtotal_cldp(realtype *dtotal_cldp, const realtype *x_rdata, const realtype *p, const realtype *k, const int ip) override {} + + + void fdtotal_cldx_rdata(realtype *dtotal_cldx_rdata, const realtype *x_rdata, const realtype *p, const realtype *k, const realtype *tcl) override {} + + void fdtotal_cldx_rdata_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdtotal_cldx_rdata_rowvals(SUNMatrixWrapper &rowvals) override {} + + + std::string getName() const override { + return "model_dirac_py"; + } + + /** + * @brief Get names of the model parameters + * @return the names + */ + std::vector getParameterNames() const override { + return std::vector(parameterNames.begin(), + parameterNames.end()); + } + + /** + * @brief Get names of the model states + * @return the names + */ + std::vector getStateNames() const override { + return std::vector(stateNames.begin(), stateNames.end()); + } + + /** + * @brief Get names of the solver states + * @return the names + */ + std::vector getStateNamesSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto const idx: stateIdxsSolver) { + result.push_back(stateNames[idx]); + } + return result; + } + + /** + * @brief Get names of the fixed model parameters + * @return the names + */ + std::vector getFixedParameterNames() const override { + return std::vector(fixedParameterNames.begin(), + fixedParameterNames.end()); + } + + /** + * @brief Get names of the observables + * @return the names + */ + std::vector getObservableNames() const override { + return std::vector(observableNames.begin(), + observableNames.end()); + } + + /** + * @brief Get names of model expressions + * @return Expression names + */ + std::vector getExpressionNames() const override { + return std::vector(expressionNames.begin(), + expressionNames.end()); + } + + /** + * @brief Get ids of the model parameters + * @return the ids + */ + std::vector getParameterIds() const override { + return std::vector(parameterIds.begin(), + parameterIds.end()); + } + + /** + * @brief Get ids of the model states + * @return the ids + */ + std::vector getStateIds() const override { + return std::vector(stateIds.begin(), stateIds.end()); + } + + /** + * @brief Get ids of the solver states + * @return the ids + */ + std::vector getStateIdsSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto idx: stateIdxsSolver) { + result.push_back(stateIds[idx]); + } + return result; + } + + /** + * @brief Get ids of the fixed model parameters + * @return the ids + */ + std::vector getFixedParameterIds() const override { + return std::vector(fixedParameterIds.begin(), + fixedParameterIds.end()); + } + + /** + * @brief Get ids of the observables + * @return the ids + */ + std::vector getObservableIds() const override { + return std::vector(observableIds.begin(), + observableIds.end()); + } + + /** + * @brief Get IDs of model expressions + * @return Expression IDs + */ + std::vector getExpressionIds() const override { + return std::vector(expressionIds.begin(), + expressionIds.end()); + } + + /** + * @brief function indicating whether reinitialization of states depending + * on fixed parameters is permissible + * @return flag indicating whether reinitialization of states depending on + * fixed parameters is permissible + */ + bool isFixedParameterStateReinitializationAllowed() const override { + return true; + } + + /** + * @brief returns the AMICI version that was used to generate the model + * @return AMICI version string + */ + std::string getAmiciVersion() const override { + return "0.33.0"; + } + + /** + * @brief returns the amici version that was used to generate the model + * @return AMICI git commit hash + */ + std::string getAmiciCommit() const override { + return "bcedb951ddf674996b269489d74f9b86112038ff"; + } + + bool hasQuadraticLLH() const override { + return true; + } + + ObservableScaling getObservableScaling(int iy) const override { + return observableScalings.at(iy); + } +}; + + +} // namespace model_model_dirac_py + +} // namespace amici + +#endif /* _amici_TPL_MODELNAME_h */ diff --git a/models/model_dirac_py/model_dirac_py/model_dirac_py.py b/models/model_dirac_py/model_dirac_py/model_dirac_py.py new file mode 100644 index 0000000000..fad7c72759 --- /dev/null +++ b/models/model_dirac_py/model_dirac_py/model_dirac_py.py @@ -0,0 +1,108 @@ +# This file was automatically generated by SWIG (https://www.swig.org). +# Version 4.3.1 +# +# Do not make changes to this file unless you know what you are doing - modify +# the SWIG interface file instead. + +from sys import version_info as _swig_python_version_info + +import amici +import datetime +import importlib.util +import os +import sysconfig +from pathlib import Path + +ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +_model_dirac_py = amici._module_from_path( + 'model_dirac_py._model_dirac_py' if __package__ or '.' in __name__ + else '_model_dirac_py', + Path(__file__).parent / f'_model_dirac_py{ext_suffix}', +) + +def _get_import_time(): + return _model_dirac_py._get_import_time() + +t_imported = _get_import_time() +t_modified = os.path.getmtime(__file__) +if t_imported < t_modified: + t_imp_str = datetime.datetime.fromtimestamp(t_imported).isoformat() + t_mod_str = datetime.datetime.fromtimestamp(t_modified).isoformat() + module_path = Path(__file__).resolve() + raise RuntimeError( + f'Cannot import extension for model_dirac_py from ' + f'{module_path}, because an extension in the same location ' + f'has already been imported, but the file was modified on ' + f'disk. \nImported at {t_imp_str}\nModified at {t_mod_str}.\n' + 'Import the module with a different name or restart the ' + 'Python kernel.' + ) + + +try: + import builtins as __builtin__ +except ImportError: + import __builtin__ + +def _swig_repr(self): + try: + strthis = "proxy of " + self.this.__repr__() + except __builtin__.Exception: + strthis = "" + return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) + + +def _swig_setattr_nondynamic_instance_variable(set): + def set_instance_attr(self, name, value): + if name == "this": + set(self, name, value) + elif name == "thisown": + self.this.own(value) + elif hasattr(self, name) and isinstance(getattr(type(self), name), property): + set(self, name, value) + else: + raise AttributeError("You cannot add instance attributes to %s" % self) + return set_instance_attr + + +def _swig_setattr_nondynamic_class_variable(set): + def set_class_attr(cls, name, value): + if hasattr(cls, name) and not isinstance(getattr(cls, name), property): + set(cls, name, value) + else: + raise AttributeError("You cannot add class attributes to %s" % cls) + return set_class_attr + + +def _swig_add_metaclass(metaclass): + """Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass""" + def wrapper(cls): + return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy()) + return wrapper + + +class _SwigNonDynamicMeta(type): + """Meta class to enforce nondynamic attributes (no new attributes) for a class""" + __setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__) + + + +# the model-package __init__.py module (will be set during import) +_model_module = None + + + +import amici + +def _get_import_time(): + return _model_dirac_py._get_import_time() + +def getModel(): + val = _model_dirac_py.getModel() + + if '.' in __name__: + val.module = _model_module + + + return val + diff --git a/models/model_dirac_py/my.h b/models/model_dirac_py/my.h new file mode 100644 index 0000000000..e88a108680 --- /dev/null +++ b/models/model_dirac_py/my.h @@ -0,0 +1 @@ +#define mobs_x2 my[0] diff --git a/models/model_dirac_py/p.h b/models/model_dirac_py/p.h new file mode 100644 index 0000000000..d1c547a672 --- /dev/null +++ b/models/model_dirac_py/p.h @@ -0,0 +1,4 @@ +#define p1 p[0] +#define p2 p[1] +#define p3 p[2] +#define p4 p[3] diff --git a/models/model_dirac_py/root.cpp b/models/model_dirac_py/root.cpp new file mode 100644 index 0000000000..fa68558804 --- /dev/null +++ b/models/model_dirac_py/root.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" + +namespace amici { +namespace model_model_dirac_py { + +void root_model_dirac_py(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl){ + root[0] = -p2 + t; +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/setup.py b/models/model_dirac_py/setup.py new file mode 100644 index 0000000000..00648926a6 --- /dev/null +++ b/models/model_dirac_py/setup.py @@ -0,0 +1,95 @@ +"""AMICI model package setup""" + +import os +import sys +from pathlib import Path + +from amici import _get_amici_path +from amici.custom_commands import AmiciBuildCMakeExtension +from cmake_build_extension import CMakeExtension +from setuptools import find_namespace_packages, setup +import importlib.metadata + + +def get_extension() -> CMakeExtension: + """Get setuptools extension object for this AMICI model package""" + + # Build shared object + prefix_path = Path(_get_amici_path()) + AmiciBuildCMakeExtension.extend_cmake_prefix_path(str(prefix_path)) + + # handle parallel building + # Note: can be empty to use all hardware threads + if (parallel_jobs := os.environ.get("AMICI_PARALLEL_COMPILE")) is not None: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = parallel_jobs + else: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = "1" + + debug_build = os.getenv("ENABLE_AMICI_DEBUGGING", "").lower() in [ + "1", + "true", + ] or os.getenv("ENABLE_GCOV_COVERAGE", "").lower() in ["1", "true"] + + cmake_prefix_path = os.getenv("CMAKE_PREFIX_PATH", "").split(os.pathsep) + cmake_prefix_path.append(prefix_path.as_posix()) + + # If scipy_openblas64 is installed, we make its cmake configuration + # available + amici_distribution = importlib.metadata.distribution("amici") + amici_dir = Path(amici_distribution.locate_file("")) + # this path is created during the amici build if scipy_openblas64 is used + openblas_cmake_dir = amici_dir / "lib" / "cmake" / "openblas" + if openblas_cmake_dir.exists(): + cmake_prefix_path.append(str(openblas_cmake_dir)) + + return CMakeExtension( + name="model_ext", + source_dir=os.getcwd(), + install_prefix="model_dirac_py", + cmake_configure_options=[ + "-DCMAKE_VERBOSE_MAKEFILE=ON", + f"-DCMAKE_PREFIX_PATH='{';'.join(cmake_prefix_path)}'", + "-DAMICI_PYTHON_BUILD_EXT_ONLY=ON", + f"-DPython3_EXECUTABLE={Path(sys.executable).as_posix()}", + ], + cmake_build_type="Debug" if debug_build else "Release", + ) + + +# Change working directory to setup.py location +os.chdir(os.path.dirname(os.path.abspath(__file__))) + +MODEL_EXT = get_extension() + +CLASSIFIERS = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Science/Research", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python", + "Programming Language :: C++", + "Topic :: Scientific/Engineering :: Bio-Informatics", +] + +CMDCLASS = { + # for CMake-based builds + "build_ext": AmiciBuildCMakeExtension, +} + +# Install +setup( + name="model_dirac_py", + cmdclass=CMDCLASS, + version="0.1.0", + description="AMICI-generated module for model model_dirac_py", + url="https://github.com/AMICI-dev/AMICI", + author="model-author-todo", + author_email="model-author-todo", + ext_modules=[MODEL_EXT], + packages=find_namespace_packages(), + install_requires=["amici==0.33.0"], + python_requires=">=3.11", + package_data={}, + zip_safe=False, + classifiers=CLASSIFIERS, +) diff --git a/models/model_dirac_py/sigmay.cpp b/models/model_dirac_py/sigmay.cpp new file mode 100644 index 0000000000..3409c93047 --- /dev/null +++ b/models/model_dirac_py/sigmay.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "y.h" +#include "sigmay.h" + +namespace amici { +namespace model_model_dirac_py { + +void sigmay_model_dirac_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y){ + sigma_obs_x2 = 1.0; // sigmay[0] +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/sigmay.h b/models/model_dirac_py/sigmay.h new file mode 100644 index 0000000000..5552efd82f --- /dev/null +++ b/models/model_dirac_py/sigmay.h @@ -0,0 +1 @@ +#define sigma_obs_x2 sigmay[0] diff --git a/models/model_dirac_py/stau.cpp b/models/model_dirac_py/stau.cpp new file mode 100644 index 0000000000..9392a0a266 --- /dev/null +++ b/models/model_dirac_py/stau.cpp @@ -0,0 +1,29 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "sx.h" + +namespace amici { +namespace model_model_dirac_py { + +void stau_model_dirac_py(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie){ + switch(ie) { + case 0: + switch(ip) { + case 1: + stau[0] = -1; + break; + } + break; + } +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/stau.h b/models/model_dirac_py/stau.h new file mode 100644 index 0000000000..2871b2462c --- /dev/null +++ b/models/model_dirac_py/stau.h @@ -0,0 +1 @@ +#define stau0 stau[0] diff --git a/models/model_dirac_py/swig/CMakeLists.txt b/models/model_dirac_py/swig/CMakeLists.txt new file mode 100644 index 0000000000..314996c479 --- /dev/null +++ b/models/model_dirac_py/swig/CMakeLists.txt @@ -0,0 +1,60 @@ +if(DEFINED ENV{SWIG}) + set(SWIG_EXECUTABLE $ENV{SWIG}) +endif() + +find_package(SWIG REQUIRED) +include(${SWIG_USE_FILE}) + +if(DEFINED ENV{PYTHON_EXECUTABLE}) + set(Python3_EXECUTABLE $ENV{PYTHON_EXECUTABLE}) +endif() +# We don't need "Interpreter" here, but without that, FindPython3 will +# ignore the Python version selected via $Python3_EXECUTABLE +find_package(Python3 COMPONENTS Interpreter Development) +include_directories(${Python3_INCLUDE_DIRS}) + +set(SWIG_LIBRARY_NAME _${PROJECT_NAME}) +set(CMAKE_SWIG_FLAGS "") +set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) + +# swig does not use INTERFACE_INCLUDE_DIRS of linked libraries, so add manually +get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) +include_directories(${AMICI_INCLUDE_DIRS} .. ${AMICI_INCLUDE_DIRS}/../swig) + +swig_add_library(${SWIG_LIBRARY_NAME} + TYPE MODULE + LANGUAGE python + SOURCES ${PROJECT_NAME}.i) + + +set_target_properties(${SWIG_LIBRARY_NAME} + PROPERTIES + SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE + PREFIX "" +) + +# Python extension suffix +execute_process( + COMMAND ${Python3_EXECUTABLE} -c + "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))" + OUTPUT_VARIABLE PY_EXT_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE) +if(NOT "${PY_EXT_SUFFIX}" STREQUAL "") + message(STATUS "Python extension suffix is ${PY_EXT_SUFFIX}") + set_target_properties(${SWIG_LIBRARY_NAME} PROPERTIES SUFFIX "${PY_EXT_SUFFIX}" ) +endif() + + +swig_link_libraries(${SWIG_LIBRARY_NAME} + ${Python3_LIBRARIES} + model) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.py + $ DESTINATION .) + +# configure module setup script +set(SETUP_PY_IN ${Amici_DIR}/model_setup.template.py) +set(SETUP_PY_OUT ${CMAKE_CURRENT_BINARY_DIR}/setup.py) + +add_custom_target(install-python + DEPENDS ${SWIG_LIBRARY_NAME} + COMMAND python ${SETUP_PY_OUT} install) diff --git a/models/model_dirac_py/swig/model_dirac_py.i b/models/model_dirac_py/swig/model_dirac_py.i new file mode 100644 index 0000000000..58116cd70d --- /dev/null +++ b/models/model_dirac_py/swig/model_dirac_py.i @@ -0,0 +1,82 @@ +%define MODULEIMPORT +" +import amici +import datetime +import importlib.util +import os +import sysconfig +from pathlib import Path + +ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +_model_dirac_py = amici._module_from_path( + 'model_dirac_py._model_dirac_py' if __package__ or '.' in __name__ + else '_model_dirac_py', + Path(__file__).parent / f'_model_dirac_py{ext_suffix}', +) + +def _get_import_time(): + return _model_dirac_py._get_import_time() + +t_imported = _get_import_time() +t_modified = os.path.getmtime(__file__) +if t_imported < t_modified: + t_imp_str = datetime.datetime.fromtimestamp(t_imported).isoformat() + t_mod_str = datetime.datetime.fromtimestamp(t_modified).isoformat() + module_path = Path(__file__).resolve() + raise RuntimeError( + f'Cannot import extension for model_dirac_py from ' + f'{module_path}, because an extension in the same location ' + f'has already been imported, but the file was modified on ' + f'disk. \\nImported at {t_imp_str}\\nModified at {t_mod_str}.\\n' + 'Import the module with a different name or restart the ' + 'Python kernel.' + ) +" +%enddef + +%module(package="model_dirac_py",moduleimport=MODULEIMPORT) model_dirac_py + +%pythoncode %{ +# the model-package __init__.py module (will be set during import) +_model_module = None + + +%} + +%import amici.i +// Add necessary symbols to generated header + +%{ +#include "wrapfunctions.h" +#include "amici/model_ode.h" +#include "amici/model_dae.h" +using namespace amici; +%} + +// store the time a module was imported +%{ +#include +static std::chrono::time_point _module_import_time; + +static double _get_import_time() { + auto epoch = _module_import_time.time_since_epoch(); + return std::chrono::duration(epoch).count(); +} +%} + +static double _get_import_time(); + +%init %{ + _module_import_time = std::chrono::system_clock::now(); +%} + + +// Make model module accessible from the model +%feature("pythonappend") amici::generic_model::getModel %{ + if '.' in __name__: + val.module = _model_module +%} + + +// Process symbols in header +%include "wrapfunctions.h" diff --git a/models/model_dirac_py/sx.h b/models/model_dirac_py/sx.h new file mode 100644 index 0000000000..7381ebd50a --- /dev/null +++ b/models/model_dirac_py/sx.h @@ -0,0 +1,2 @@ +#define sx0 sx[0] +#define sx1 sx[1] diff --git a/models/model_dirac_py/w.h b/models/model_dirac_py/w.h new file mode 100644 index 0000000000..c399413a8c --- /dev/null +++ b/models/model_dirac_py/w.h @@ -0,0 +1 @@ +#define flux_r0 w[0] diff --git a/models/model_dirac_py/wrapfunctions.cpp b/models/model_dirac_py/wrapfunctions.cpp new file mode 100644 index 0000000000..9af7c0a091 --- /dev/null +++ b/models/model_dirac_py/wrapfunctions.cpp @@ -0,0 +1,16 @@ +#include "wrapfunctions.h" +#include "model_dirac_py.h" +#include "amici/model.h" + +namespace amici { +namespace generic_model { + +std::unique_ptr getModel() { + return std::unique_ptr( + new amici::model_model_dirac_py::Model_model_dirac_py() + ); +} + +} // namespace generic_model + +} // namespace amici diff --git a/models/model_dirac_py/wrapfunctions.h b/models/model_dirac_py/wrapfunctions.h new file mode 100644 index 0000000000..33c8a9d819 --- /dev/null +++ b/models/model_dirac_py/wrapfunctions.h @@ -0,0 +1,25 @@ +#ifndef _amici_wrapfunctions_h +#define _amici_wrapfunctions_h + +#include + +#include "amici/model.h" + +namespace amici { +namespace generic_model { + + +/** + * @brief Wrapper function to instantiate the linked Amici model without knowing + * the name at compile time. + * @return Model instance + */ +std::unique_ptr getModel(); + + +} // namespace generic_model + +} // namespace amici + + +#endif /* _amici_wrapfunctions_h */ diff --git a/models/model_dirac_py/x.h b/models/model_dirac_py/x.h new file mode 100644 index 0000000000..a3fa3282e3 --- /dev/null +++ b/models/model_dirac_py/x.h @@ -0,0 +1,2 @@ +#define x1 x[0] +#define x2 x[1] diff --git a/models/model_dirac_py/xB.h b/models/model_dirac_py/xB.h new file mode 100644 index 0000000000..21e5ffd7d9 --- /dev/null +++ b/models/model_dirac_py/xB.h @@ -0,0 +1,2 @@ +#define xB0 xB[0] +#define xB1 xB[1] diff --git a/models/model_dirac_py/x_old.h b/models/model_dirac_py/x_old.h new file mode 100644 index 0000000000..751090c25e --- /dev/null +++ b/models/model_dirac_py/x_old.h @@ -0,0 +1,2 @@ +#define x_old0 x_old[0] +#define x_old1 x_old[1] diff --git a/models/model_dirac_py/x_rdata.cpp b/models/model_dirac_py/x_rdata.cpp new file mode 100644 index 0000000000..192e1e406c --- /dev/null +++ b/models/model_dirac_py/x_rdata.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" + +namespace amici { +namespace model_model_dirac_py { + +void x_rdata_model_dirac_py(realtype *x_rdata, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k){ + x_rdata[0] = x1; + x_rdata[1] = x2; +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/x_rdata.h b/models/model_dirac_py/x_rdata.h new file mode 100644 index 0000000000..bd656ca405 --- /dev/null +++ b/models/model_dirac_py/x_rdata.h @@ -0,0 +1,2 @@ +#define x1 x_rdata[0] +#define x2 x_rdata[1] diff --git a/models/model_dirac_py/x_solver.cpp b/models/model_dirac_py/x_solver.cpp new file mode 100644 index 0000000000..1ae12c8765 --- /dev/null +++ b/models/model_dirac_py/x_solver.cpp @@ -0,0 +1,19 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x_rdata.h" + +namespace amici { +namespace model_model_dirac_py { + +void x_solver_model_dirac_py(realtype *x_solver, const realtype *x_rdata){ + x_solver[0] = x1; + x_solver[1] = x2; +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/x_solver.h b/models/model_dirac_py/x_solver.h new file mode 100644 index 0000000000..cd21d15a1f --- /dev/null +++ b/models/model_dirac_py/x_solver.h @@ -0,0 +1,2 @@ +#define x_solver0 x_solver[0] +#define x_solver1 x_solver[1] diff --git a/models/model_dirac_py/xdot.cpp b/models/model_dirac_py/xdot.cpp new file mode 100644 index 0000000000..c1e039f4bc --- /dev/null +++ b/models/model_dirac_py/xdot.cpp @@ -0,0 +1,23 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "w.h" +#include "xdot.h" + +namespace amici { +namespace model_model_dirac_py { + +void xdot_model_dirac_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + dx1dt = -p1*x1; // xdot[0] + dx2dt = p3*x1 - p4*x2; // xdot[1] +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/xdot.h b/models/model_dirac_py/xdot.h new file mode 100644 index 0000000000..81b8ecfe59 --- /dev/null +++ b/models/model_dirac_py/xdot.h @@ -0,0 +1,2 @@ +#define dx1dt xdot[0] +#define dx2dt xdot[1] diff --git a/models/model_dirac_py/xdot_old.h b/models/model_dirac_py/xdot_old.h new file mode 100644 index 0000000000..563f911b86 --- /dev/null +++ b/models/model_dirac_py/xdot_old.h @@ -0,0 +1,2 @@ +#define xdot_old0 xdot_old[0] +#define xdot_old1 xdot_old[1] diff --git a/models/model_dirac_py/y.cpp b/models/model_dirac_py/y.cpp new file mode 100644 index 0000000000..d73c3d7e0a --- /dev/null +++ b/models/model_dirac_py/y.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" + +namespace amici { +namespace model_model_dirac_py { + +void y_model_dirac_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + y[0] = x2; +} + +} // namespace model_model_dirac_py +} // namespace amici diff --git a/models/model_dirac_py/y.h b/models/model_dirac_py/y.h new file mode 100644 index 0000000000..e4df841c03 --- /dev/null +++ b/models/model_dirac_py/y.h @@ -0,0 +1 @@ +#define obs_x2 y[0] diff --git a/models/model_events_py/.gitignore b/models/model_events_py/.gitignore new file mode 100644 index 0000000000..fa29cdfff9 --- /dev/null +++ b/models/model_events_py/.gitignore @@ -0,0 +1 @@ +** \ No newline at end of file diff --git a/models/model_events_py/CMakeLists.txt b/models/model_events_py/CMakeLists.txt new file mode 100644 index 0000000000..a4bc612bfe --- /dev/null +++ b/models/model_events_py/CMakeLists.txt @@ -0,0 +1,168 @@ +# Build AMICI model +cmake_minimum_required(VERSION 3.22) +cmake_policy(VERSION 3.22...3.31) + +project(model_events_py) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +include(CheckCXXCompilerFlag) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() +foreach(flag ${MY_CXX_FLAGS}) + unset(CUR_FLAG_SUPPORTED CACHE) + check_cxx_compiler_flag(${flag} CUR_FLAG_SUPPORTED) + if(${CUR_FLAG_SUPPORTED}) + string(APPEND CMAKE_CXX_FLAGS " ${flag}") + endif() +endforeach() + +if(DEFINED ENV{AMICI_CXXFLAGS}) + message(STATUS "Appending flags from AMICI_CXXFLAGS: $ENV{AMICI_CXXFLAGS}") + add_compile_options("$ENV{AMICI_CXXFLAGS}") +endif() +if(DEFINED ENV{AMICI_LDFLAGS}) + message(STATUS "Appending flags from AMICI_LDFLAGS: $ENV{AMICI_LDFLAGS}") + link_libraries("$ENV{AMICI_LDFLAGS}") +endif() + +find_package(Amici 0.33.0 REQUIRED HINTS + ${CMAKE_CURRENT_LIST_DIR}/../../build) +message(STATUS "Found AMICI ${Amici_DIR}") +set_target_properties(Upstream::amici PROPERTIES + MAP_IMPORTED_CONFIG_RELWITHDEBINFO RelWithDebInfo;Release; + MAP_IMPORTED_CONFIG_RELEASE Release + MAP_IMPORTED_CONFIG_DEBUG Debug;RelWithDebInfo;) + +# Debug build? +if("$ENV{ENABLE_AMICI_DEBUGGING}" OR "$ENV{ENABLE_GCOV_COVERAGE}") + add_compile_options(-UNDEBUG) + if(MSVC) + add_compile_options(-DEBUG) + else() + add_compile_options(-O0 -g) + endif() +endif() + +# coverage options +if($ENV{ENABLE_GCOV_COVERAGE}) + string(APPEND CMAKE_CXX_FLAGS_DEBUG " --coverage") + string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " --coverage") +endif() + +set(MODEL_DIR ${CMAKE_CURRENT_LIST_DIR}) + +set(SRC_LIST_LIB Jrz.cpp +Jy.cpp +Jy.h +Jz.cpp +create_splines.cpp +dJrzdsigma.cpp +dJrzdz.cpp +dJydsigma.cpp +dJydy.cpp +dJydy.h +dJzdsigma.cpp +dJzdz.cpp +deltaqB.cpp +deltasx.cpp +deltaxB.cpp +drzdx.cpp +dxdotdp_explicit.cpp +dxdotdp_explicit.h +dxdotdx_explicit.cpp +dxdotdx_explicit.h +dydp.cpp +dydx.cpp +dzdx.cpp +h.h +k.h +model_events_py.cpp +model_events_py.h +my.h +mz.h +p.h +root.cpp +rz.cpp +rz.h +sigmay.cpp +sigmay.h +sigmaz.cpp +sigmaz.h +stau.cpp +stau.h +sx.h +sx0_fixedParameters.cpp +w.h +wrapfunctions.cpp +wrapfunctions.h +x.h +x0.cpp +x0_fixedParameters.cpp +xB.h +x_old.h +x_rdata.cpp +x_rdata.h +x_solver.cpp +x_solver.h +xdot.cpp +xdot.h +xdot_old.h +y.cpp +y.h +z.cpp +z.h ${MODEL_DIR}/wrapfunctions.cpp) + +add_library(${PROJECT_NAME} ${SRC_LIST_LIB}) + +# ${PROJECT_NAME} might already be "model" +if(NOT TARGET model) + add_library(model ALIAS ${PROJECT_NAME}) +endif() + +# Some special functions require boost +# +# TODO: set some flag during code generation whether the given model requires +# boost. for now, try to find it, add include directories and link against it. +# let the compiler/linker error if it is required but not found +find_package(Boost) + +target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") + +target_link_libraries( + ${PROJECT_NAME} + PUBLIC Upstream::amici + PRIVATE $<$:Boost::boost>) + +if(NOT "${AMICI_PYTHON_BUILD_EXT_ONLY}") + set(SRC_LIST_EXE main.cpp) + add_executable(simulate_${PROJECT_NAME} ${SRC_LIST_EXE}) + target_link_libraries(simulate_${PROJECT_NAME} ${PROJECT_NAME}) +endif() + +# SWIG +option(ENABLE_SWIG "Build swig/python library?" ON) +if(ENABLE_SWIG) + add_subdirectory(swig) +endif() + +# +include(GNUInstallDirs) +install( + TARGETS ${PROJECT_NAME} + EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +export( + EXPORT ${PROJECT_NAME}Targets + FILE ${PROJECT_NAME}Config.cmake + NAMESPACE Upstream::) +# diff --git a/models/model_events_py/Jrz.cpp b/models/model_events_py/Jrz.cpp new file mode 100644 index 0000000000..1b055f2716 --- /dev/null +++ b/models/model_events_py/Jrz.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "rz.h" +#include "sigmaz.h" + +namespace amici { +namespace model_model_events_py { + +void Jrz_model_events_py(realtype *Jrz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz){ + switch(iz) { + case 0: + Jrz[0] = 0.5*std::pow(rz1, 2)/std::pow(sigma_z1, 2) + 0.5*std::log(2*amici::pi*std::pow(sigma_z1, 2)); + Jrz[1] = 0.5*std::pow(rz2, 2)/std::pow(sigma_z2, 2) + 0.5*std::log(2*amici::pi*std::pow(sigma_z2, 2)); + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/Jy.cpp b/models/model_events_py/Jy.cpp new file mode 100644 index 0000000000..244b2244fd --- /dev/null +++ b/models/model_events_py/Jy.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_events_py { + +void Jy_model_events_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_y1, 2)) + 0.5*std::pow(-my1 + y1, 2)/std::pow(sigma_y1, 2); + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/Jy.h b/models/model_events_py/Jy.h new file mode 100644 index 0000000000..6b49699ace --- /dev/null +++ b/models/model_events_py/Jy.h @@ -0,0 +1 @@ +#define Jy0 Jy[0] diff --git a/models/model_events_py/Jz.cpp b/models/model_events_py/Jz.cpp new file mode 100644 index 0000000000..cb742710c7 --- /dev/null +++ b/models/model_events_py/Jz.cpp @@ -0,0 +1,27 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "z.h" +#include "sigmaz.h" +#include "mz.h" + +namespace amici { +namespace model_model_events_py { + +void Jz_model_events_py(realtype *Jz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz){ + switch(iz) { + case 0: + Jz[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_z1, 2)) + 0.5*std::pow(-mz1 + z1, 2)/std::pow(sigma_z1, 2); + Jz[1] = 0.5*std::log(2*amici::pi*std::pow(sigma_z2, 2)) + 0.5*std::pow(-mz2 + z2, 2)/std::pow(sigma_z2, 2); + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/MANIFEST.in b/models/model_events_py/MANIFEST.in new file mode 100644 index 0000000000..fd78129853 --- /dev/null +++ b/models/model_events_py/MANIFEST.in @@ -0,0 +1,3 @@ +include *.cpp *.h +include CMakeLists.txt +recursive-include swig/ * diff --git a/models/model_events_py/create_splines.cpp b/models/model_events_py/create_splines.cpp new file mode 100644 index 0000000000..c6d2587ec4 --- /dev/null +++ b/models/model_events_py/create_splines.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "amici/splinefunctions.h" +#include +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_events_py { + +std::vector create_splines_model_events_py(const realtype *p, const realtype *k){ + return {}; +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/dJrzdsigma.cpp b/models/model_events_py/dJrzdsigma.cpp new file mode 100644 index 0000000000..ec953af5ea --- /dev/null +++ b/models/model_events_py/dJrzdsigma.cpp @@ -0,0 +1,28 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "rz.h" +#include "sigmaz.h" + +namespace amici { +namespace model_model_events_py { + +void dJrzdsigma_model_events_py(realtype *dJrzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz){ + switch(iz) { + case 0: + dJrzdsigma[0] = -1.0*std::pow(rz1, 2)/std::pow(sigma_z1, 3) + 1.0/sigma_z1; + break; + case 1: + dJrzdsigma[1] = -1.0*std::pow(rz2, 2)/std::pow(sigma_z2, 3) + 1.0/sigma_z2; + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/dJrzdz.cpp b/models/model_events_py/dJrzdz.cpp new file mode 100644 index 0000000000..188917a826 --- /dev/null +++ b/models/model_events_py/dJrzdz.cpp @@ -0,0 +1,28 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "rz.h" +#include "sigmaz.h" + +namespace amici { +namespace model_model_events_py { + +void dJrzdz_model_events_py(realtype *dJrzdz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz){ + switch(iz) { + case 0: + dJrzdz[0] = 1.0*rz1/std::pow(sigma_z1, 2); + break; + case 1: + dJrzdz[1] = 1.0*rz2/std::pow(sigma_z2, 2); + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/dJydsigma.cpp b/models/model_events_py/dJydsigma.cpp new file mode 100644 index 0000000000..35e2628aee --- /dev/null +++ b/models/model_events_py/dJydsigma.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_events_py { + +void dJydsigma_model_events_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydsigma[0] = 1.0/sigma_y1 - 1.0*std::pow(-my1 + y1, 2)/std::pow(sigma_y1, 3); + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/dJydy.cpp b/models/model_events_py/dJydy.cpp new file mode 100644 index 0000000000..c71ce21e41 --- /dev/null +++ b/models/model_events_py/dJydy.cpp @@ -0,0 +1,68 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_events_py { + +static constexpr std::array, 1> dJydy_colptrs_model_events_py_ = {{ + {0, 1}, +}}; + +void dJydy_colptrs_model_events_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexptrs(gsl::make_span(dJydy_colptrs_model_events_py_[index])); +} +} // namespace model_model_events_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_events_py { + +static constexpr std::array, 1> dJydy_rowvals_model_events_py_ = {{ + {0}, +}}; + +void dJydy_rowvals_model_events_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexvals(gsl::make_span(dJydy_rowvals_model_events_py_[index])); +} +} // namespace model_model_events_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" +#include "dJydy.h" + +namespace amici { +namespace model_model_events_py { + +void dJydy_model_events_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydy[0] = (-1.0*my1 + 1.0*y1)/std::pow(sigma_y1, 2); + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/dJydy.h b/models/model_events_py/dJydy.h new file mode 100644 index 0000000000..98c02cbb64 --- /dev/null +++ b/models/model_events_py/dJydy.h @@ -0,0 +1 @@ +#define dJy0_dy1 dJydy[0] diff --git a/models/model_events_py/dJzdsigma.cpp b/models/model_events_py/dJzdsigma.cpp new file mode 100644 index 0000000000..725201a5d3 --- /dev/null +++ b/models/model_events_py/dJzdsigma.cpp @@ -0,0 +1,29 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "z.h" +#include "sigmaz.h" +#include "mz.h" + +namespace amici { +namespace model_model_events_py { + +void dJzdsigma_model_events_py(realtype *dJzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz){ + switch(iz) { + case 0: + dJzdsigma[0] = 1.0/sigma_z1 - 1.0*std::pow(-mz1 + z1, 2)/std::pow(sigma_z1, 3); + break; + case 1: + dJzdsigma[1] = 1.0/sigma_z2 - 1.0*std::pow(-mz2 + z2, 2)/std::pow(sigma_z2, 3); + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/dJzdz.cpp b/models/model_events_py/dJzdz.cpp new file mode 100644 index 0000000000..a5a5fc6a45 --- /dev/null +++ b/models/model_events_py/dJzdz.cpp @@ -0,0 +1,29 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "z.h" +#include "sigmaz.h" +#include "mz.h" + +namespace amici { +namespace model_model_events_py { + +void dJzdz_model_events_py(realtype *dJzdz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const double *mz){ + switch(iz) { + case 0: + dJzdz[0] = (-1.0*mz1 + 1.0*z1)/std::pow(sigma_z1, 2); + break; + case 1: + dJzdz[1] = (-1.0*mz2 + 1.0*z2)/std::pow(sigma_z2, 2); + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/deltaqB.cpp b/models/model_events_py/deltaqB.cpp new file mode 100644 index 0000000000..236d5381b8 --- /dev/null +++ b/models/model_events_py/deltaqB.cpp @@ -0,0 +1,34 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "xdot.h" +#include "xdot_old.h" +#include "x_old.h" +#include "xB.h" + +namespace amici { +namespace model_model_events_py { + +void deltaqB_model_events_py(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB){ + switch(ie) { + case 2: + case 3: + switch(ip) { + case 3: + deltaqB[0] = xB0*(-dx1dt + xdot_old0) + xB1*(-dx2dt + xdot_old1) + xB2*(-dx3dt + xdot_old2); + break; + } + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/deltasx.cpp b/models/model_events_py/deltasx.cpp new file mode 100644 index 0000000000..d16555dced --- /dev/null +++ b/models/model_events_py/deltasx.cpp @@ -0,0 +1,42 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "xdot.h" +#include "xdot_old.h" +#include "sx.h" +#include "stau.h" +#include "x_old.h" + +namespace amici { +namespace model_model_events_py { + +void deltasx_model_events_py(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old){ + switch(ie) { + case 0: + case 1: + case 2: + case 3: + switch(ip) { + case 0: + case 1: + case 2: + case 3: + deltasx[0] = stau0*(dx1dt - xdot_old0); + deltasx[1] = stau0*(dx2dt - xdot_old1); + deltasx[2] = stau0*(dx3dt - xdot_old2); + break; + } + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/deltaxB.cpp b/models/model_events_py/deltaxB.cpp new file mode 100644 index 0000000000..3f1b573f93 --- /dev/null +++ b/models/model_events_py/deltaxB.cpp @@ -0,0 +1,34 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "xdot.h" +#include "xdot_old.h" +#include "x_old.h" +#include "xB.h" + +namespace amici { +namespace model_model_events_py { + +void deltaxB_model_events_py(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl){ + switch(ie) { + case 0: + deltaxB[1] = xB0*(dx1dt - xdot_old0)/(Heaviside_4 + p2*x1*std::exp(-1.0/10.0*t) - p3*x2 + x3 - 1) + xB1*(dx2dt - xdot_old1)/(Heaviside_4 + p2*x1*std::exp(-1.0/10.0*t) - p3*x2 + x3 - 1) + xB2*(dx3dt - xdot_old2)/(Heaviside_4 + p2*x1*std::exp(-1.0/10.0*t) - p3*x2 + x3 - 1); + deltaxB[2] = -xB0*(dx1dt - xdot_old0)/(Heaviside_4 + p2*x1*std::exp(-1.0/10.0*t) - p3*x2 + x3 - 1) - xB1*(dx2dt - xdot_old1)/(Heaviside_4 + p2*x1*std::exp(-1.0/10.0*t) - p3*x2 + x3 - 1) - xB2*(dx3dt - xdot_old2)/(Heaviside_4 + p2*x1*std::exp(-1.0/10.0*t) - p3*x2 + x3 - 1); + break; + case 1: + deltaxB[0] = xB0*(dx1dt - xdot_old0)/(Heaviside_4 - p1*x1*(1 - Heaviside_2) + x3 - 1) + xB1*(dx2dt - xdot_old1)/(Heaviside_4 - p1*x1*(1 - Heaviside_2) + x3 - 1) + xB2*(dx3dt - xdot_old2)/(Heaviside_4 - p1*x1*(1 - Heaviside_2) + x3 - 1); + deltaxB[2] = -xB0*(dx1dt - xdot_old0)/(Heaviside_4 - p1*x1*(1 - Heaviside_2) + x3 - 1) - xB1*(dx2dt - xdot_old1)/(Heaviside_4 - p1*x1*(1 - Heaviside_2) + x3 - 1) - xB2*(dx3dt - xdot_old2)/(Heaviside_4 - p1*x1*(1 - Heaviside_2) + x3 - 1); + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/drzdx.cpp b/models/model_events_py/drzdx.cpp new file mode 100644 index 0000000000..8de32d9253 --- /dev/null +++ b/models/model_events_py/drzdx.cpp @@ -0,0 +1,30 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" + +namespace amici { +namespace model_model_events_py { + +void drzdx_model_events_py(realtype *drzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h){ + switch(ie) { + case 0: + drzdx[2] = 1; + drzdx[4] = -1; + break; + case 1: + drzdx[1] = 1; + drzdx[5] = -1; + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/dxdotdp_explicit.cpp b/models/model_events_py/dxdotdp_explicit.cpp new file mode 100644 index 0000000000..51803f2c17 --- /dev/null +++ b/models/model_events_py/dxdotdp_explicit.cpp @@ -0,0 +1,66 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_events_py { + +static constexpr std::array dxdotdp_explicit_colptrs_model_events_py_ = { + 0, 1, 2, 3, 3 +}; + +void dxdotdp_explicit_colptrs_model_events_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexptrs(gsl::make_span(dxdotdp_explicit_colptrs_model_events_py_)); +} +} // namespace model_model_events_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_events_py { + +static constexpr std::array dxdotdp_explicit_rowvals_model_events_py_ = { + 0, 1, 1 +}; + +void dxdotdp_explicit_rowvals_model_events_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexvals(gsl::make_span(dxdotdp_explicit_rowvals_model_events_py_)); +} +} // namespace model_model_events_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "w.h" +#include "dxdotdp_explicit.h" + +namespace amici { +namespace model_model_events_py { + +void dxdotdp_explicit_model_events_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + ddx1dt_dp1 = -x1*(1 - Heaviside_2); // dxdotdp_explicit[0] + ddx2dt_dp2 = x1*std::exp(-1.0/10.0*t); // dxdotdp_explicit[1] + ddx2dt_dp3 = -x2; // dxdotdp_explicit[2] +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/dxdotdp_explicit.h b/models/model_events_py/dxdotdp_explicit.h new file mode 100644 index 0000000000..0d5cb8285e --- /dev/null +++ b/models/model_events_py/dxdotdp_explicit.h @@ -0,0 +1,3 @@ +#define ddx1dt_dp1 dxdotdp_explicit[0] +#define ddx2dt_dp2 dxdotdp_explicit[1] +#define ddx2dt_dp3 dxdotdp_explicit[2] diff --git a/models/model_events_py/dxdotdx_explicit.cpp b/models/model_events_py/dxdotdx_explicit.cpp new file mode 100644 index 0000000000..191814b99d --- /dev/null +++ b/models/model_events_py/dxdotdx_explicit.cpp @@ -0,0 +1,67 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_events_py { + +static constexpr std::array dxdotdx_explicit_colptrs_model_events_py_ = { + 0, 2, 3, 4 +}; + +void dxdotdx_explicit_colptrs_model_events_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexptrs(gsl::make_span(dxdotdx_explicit_colptrs_model_events_py_)); +} +} // namespace model_model_events_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_events_py { + +static constexpr std::array dxdotdx_explicit_rowvals_model_events_py_ = { + 0, 1, 1, 2 +}; + +void dxdotdx_explicit_rowvals_model_events_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexvals(gsl::make_span(dxdotdx_explicit_rowvals_model_events_py_)); +} +} // namespace model_model_events_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "w.h" +#include "dxdotdx_explicit.h" + +namespace amici { +namespace model_model_events_py { + +void dxdotdx_explicit_model_events_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + ddx1dt_dx1 = -p1*(1 - Heaviside_2); // dxdotdx_explicit[0] + ddx2dt_dx1 = p2*std::exp(-1.0/10.0*t); // dxdotdx_explicit[1] + ddx2dt_dx2 = -p3; // dxdotdx_explicit[2] + ddx3dt_dx3 = -1; // dxdotdx_explicit[3] +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/dxdotdx_explicit.h b/models/model_events_py/dxdotdx_explicit.h new file mode 100644 index 0000000000..26fc166444 --- /dev/null +++ b/models/model_events_py/dxdotdx_explicit.h @@ -0,0 +1,4 @@ +#define ddx1dt_dx1 dxdotdx_explicit[0] +#define ddx2dt_dx1 dxdotdx_explicit[1] +#define ddx2dt_dx2 dxdotdx_explicit[2] +#define ddx3dt_dx3 dxdotdx_explicit[3] diff --git a/models/model_events_py/dydp.cpp b/models/model_events_py/dydp.cpp new file mode 100644 index 0000000000..e0921ae555 --- /dev/null +++ b/models/model_events_py/dydp.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" + +namespace amici { +namespace model_model_events_py { + +void dydp_model_events_py(realtype *dydp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl){ + switch(ip) { + case 3: + dydp[0] = x1 + x2 + x3; + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/dydx.cpp b/models/model_events_py/dydx.cpp new file mode 100644 index 0000000000..9b1a4a32a6 --- /dev/null +++ b/models/model_events_py/dydx.cpp @@ -0,0 +1,23 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" + +namespace amici { +namespace model_model_events_py { + +void dydx_model_events_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx){ + dydx[0] = p4; + dydx[1] = p4; + dydx[2] = p4; +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/dzdx.cpp b/models/model_events_py/dzdx.cpp new file mode 100644 index 0000000000..2c6671aa1f --- /dev/null +++ b/models/model_events_py/dzdx.cpp @@ -0,0 +1,30 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" + +namespace amici { +namespace model_model_events_py { + +void dzdx_model_events_py(realtype *dzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h){ + switch(ie) { + case 0: + dzdx[2] = -1/(Heaviside_4 + p2*x1*std::exp(-1.0/10.0*t) - p3*x2 + x3 - 1); + dzdx[4] = 1.0/(Heaviside_4 + p2*x1*std::exp(-1.0/10.0*t) - p3*x2 + x3 - 1); + break; + case 1: + dzdx[1] = -1/(Heaviside_4 - p1*x1*(1 - Heaviside_2) + x3 - 1); + dzdx[5] = 1.0/(Heaviside_4 - p1*x1*(1 - Heaviside_2) + x3 - 1); + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/h.h b/models/model_events_py/h.h new file mode 100644 index 0000000000..951db2de6c --- /dev/null +++ b/models/model_events_py/h.h @@ -0,0 +1,6 @@ +#define event_1 h[0] +#define event_2 h[1] +#define Heaviside_2 h[2] +#define Heaviside_3 h[3] +#define Heaviside_4 h[4] +#define Heaviside_5 h[5] diff --git a/models/model_events_py/k.h b/models/model_events_py/k.h new file mode 100644 index 0000000000..364bd02b0a --- /dev/null +++ b/models/model_events_py/k.h @@ -0,0 +1,4 @@ +#define k1 k[0] +#define k2 k[1] +#define k3 k[2] +#define k4 k[3] diff --git a/models/model_events_py/main.cpp b/models/model_events_py/main.cpp new file mode 100644 index 0000000000..ecdff85a46 --- /dev/null +++ b/models/model_events_py/main.cpp @@ -0,0 +1,93 @@ +#include + +#include "wrapfunctions.h" /* model-provided functions */ +#include /* AMICI base functions */ + +template +std::ostream& operator<<(std::ostream& os, std::vector const& v) { + os << "["; + for (typename std::vector::const_iterator ii = v.begin(); ii != v.end(); + ++ii) { + os << " " << *ii; + } + os << "]"; + return os; +} + +/* + * This is a scaffold for a stand-alone AMICI simulation executable + * demonstrating the basic use of the AMICI C++ API. + */ + +int main() { + std::cout << "********************************" << std::endl; + std::cout << "** Running forward simulation **" << std::endl; + std::cout << "********************************" << std::endl << std::endl; + + // Create a model instance + auto model = amici::generic_model::getModel(); + + // Set desired output timepoints + model->setTimepoints({0.0, 1.0, 10.0, 100.0, 1000.0}); + + // Create a solver instance + auto solver = model->getSolver(); + + // Optionally set integration tolerance + solver->setAbsoluteTolerance(1e-16); + solver->setRelativeTolerance(1e-8); + + // Run the simulation using default parameters set during model import + // (can be changed using model->setParameters() or model->setParameterBy*()) + auto rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print observable time course + auto observable_ids = model->getObservableIds(); + std::cout << "Simulated observables for timepoints " << rdata->ts << "\n\n"; + for (int i_observable = 0; i_observable < rdata->ny; ++i_observable) { + std::cout << observable_ids[i_observable] << ":\n\t"; + for (int i_time = 0; i_time < rdata->nt; ++i_time) { + // rdata->y is a flat 2D array in row-major ordering + std::cout << rdata->y[i_time * rdata->ny + i_observable] << " "; + } + std::cout << std::endl << std::endl; + } + + std::cout << std::endl; + std::cout << "**********************************" << std::endl; + std::cout << "** Forward sensitivity analysis **" << std::endl; + std::cout << "**********************************" << std::endl << std::endl; + + // Enable first-order sensitivity analysis + solver->setSensitivityOrder(amici::SensitivityOrder::first); + // Use forward sensitivities + solver->setSensitivityMethod(amici::SensitivityMethod::forward); + + // Run the simulation + rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print state sensitivities sx... + // ... for the first timepoint... + int i_time = 0; + // ... with respect to the first parameter + int i_nplist = 0; + + // get identifiers from model + auto state_ids = model->getStateIds(); + auto parameter_ids = model->getParameterIds(); + + std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] + << std::endl; // nt x nplist x nx + for (int i_state = 0; i_state < rdata->nx; ++i_state) { + std::cout << "\td(" << state_ids[i_state] << ")/d(" + << parameter_ids[model->plist(i_nplist)] << ") = "; + + // rdata->sx is a flat 3D array in row-major ordering + std::cout << rdata->sx + [i_time * rdata->nplist * rdata->nx + + i_nplist * rdata->nx + i_state]; + std::cout << std::endl; + } + + return 0; +} diff --git a/models/model_events_py/model_events_py.cpp b/models/model_events_py/model_events_py.cpp new file mode 100644 index 0000000000..730ab8bcac --- /dev/null +++ b/models/model_events_py/model_events_py.cpp @@ -0,0 +1,78 @@ +#include +#include + +namespace amici { + +namespace model_model_events_py { + +// clang-format off + +std::array parameterNames = { + "p1", // p[0] +"p2", // p[1] +"p3", // p[2] +"p4", // p[3] +}; + +std::array fixedParameterNames = { + "k1", // k[0] +"k2", // k[1] +"k3", // k[2] +"k4", // k[3] +}; + +std::array stateNames = { + "x1", // x_rdata[0] +"x2", // x_rdata[1] +"x3", // x_rdata[2] +}; + +std::array observableNames = { + "y1", // y[0] +}; + +std::array observableScalings = { + ObservableScaling::lin, // y[0] +}; + +std::array expressionNames = { + "flux_r0", // w[0] +}; + +std::array parameterIds = { + "p1", // p[0] +"p2", // p[1] +"p3", // p[2] +"p4", // p[3] +}; + +std::array fixedParameterIds = { + "k1", // k[0] +"k2", // k[1] +"k3", // k[2] +"k4", // k[3] +}; + +std::array stateIds = { + "x1", // x_rdata[0] +"x2", // x_rdata[1] +"x3", // x_rdata[2] +}; + +std::array observableIds = { + "y1", // y[0] +}; + +std::array expressionIds = { + "flux_r0", // w[0] +}; + +std::array stateIdxsSolver = { + 0, 1, 2 +}; + +// clang-format on + +} // namespace model_model_events_py + +} // namespace amici diff --git a/models/model_events_py/model_events_py.h b/models/model_events_py/model_events_py.h new file mode 100644 index 0000000000..7fa56b11e3 --- /dev/null +++ b/models/model_events_py/model_events_py.h @@ -0,0 +1,596 @@ +#ifndef _amici_TPL_MODELNAME_h +#define _amici_TPL_MODELNAME_h +#include +#include +#include + +#include "amici/model_ode.h" +#include "amici/splinefunctions.h" +#include "amici/event.h" + +namespace amici { + +class Solver; + +namespace model_model_events_py { + +extern std::array parameterNames; +extern std::array fixedParameterNames; +extern std::array stateNames; +extern std::array observableNames; +extern std::array observableScalings; +extern std::array expressionNames; +extern std::array parameterIds; +extern std::array fixedParameterIds; +extern std::array stateIds; +extern std::array observableIds; +extern std::array expressionIds; +extern std::array stateIdxsSolver; + +extern void Jy_model_events_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydsigma_model_events_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_model_events_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_colptrs_model_events_py(SUNMatrixWrapper &colptrs, int index); +extern void dJydy_rowvals_model_events_py(SUNMatrixWrapper &rowvals, int index); +extern void Jz_model_events_py(realtype *Jz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz); +extern void dJzdsigma_model_events_py(realtype *dJzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz); +extern void dJzdz_model_events_py(realtype *dJzdz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const double *mz); +extern void Jrz_model_events_py(realtype *Jrz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz); +extern void dJrzdsigma_model_events_py(realtype *dJrzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz); +extern void dJrzdz_model_events_py(realtype *dJrzdz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz); +extern void root_model_events_py(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl); + + + + + + + + + + + + +extern void dxdotdp_explicit_model_events_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void dxdotdp_explicit_colptrs_model_events_py(SUNMatrixWrapper &colptrs); +extern void dxdotdp_explicit_rowvals_model_events_py(SUNMatrixWrapper &rowvals); +extern void dxdotdx_explicit_model_events_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void dxdotdx_explicit_colptrs_model_events_py(SUNMatrixWrapper &colptrs); +extern void dxdotdx_explicit_rowvals_model_events_py(SUNMatrixWrapper &rowvals); +extern void dydx_model_events_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx); +extern void dydp_model_events_py(realtype *dydp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl); +extern void dzdx_model_events_py(realtype *dzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h); + +extern void drzdx_model_events_py(realtype *drzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h); + +extern void sigmay_model_events_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y); +extern void sigmaz_model_events_py(realtype *sigmaz, const realtype t, const realtype *p, const realtype *k); + + + + +extern void x0_model_events_py(realtype *x0, const realtype t, const realtype *p, const realtype *k); +extern void x0_fixedParameters_model_events_py(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs); + +extern void sx0_fixedParameters_model_events_py(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs); +extern void xdot_model_events_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void y_model_events_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void z_model_events_py(realtype *z, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h); +extern void rz_model_events_py(realtype *rz, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h); +extern void stau_model_events_py(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie); + +extern void deltasx_model_events_py(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old); +extern void deltaxB_model_events_py(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl); +extern void deltaqB_model_events_py(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB); + +extern void x_solver_model_events_py(realtype *x_solver, const realtype *x_rdata); + + + + + + + + + + + + +extern std::vector create_splines_model_events_py(const realtype *p, const realtype *k); + + + +/** + * @brief AMICI-generated model subclass. + */ +class Model_model_events_py : public amici::Model_ODE { + public: + /** + * @brief Default constructor. + */ + Model_model_events_py() + : amici::Model_ODE( + amici::ModelDimensions( + 3, // nx_rdata + 3, // nxtrue_rdata + 3, // nx_solver + 3, // nxtrue_solver + 0, // nx_solver_reinit + 4, // np + 4, // nk + 1, // ny + 1, // nytrue + 2, // nz + 2, // nztrue + 6, // nevent + 4, // nevent_solver + 0, // nspl + 1, // nobjective + 1, // nw + 0, // ndwdx + 0, // ndwdp + 0, // ndwdw + 0, // ndxdotdw + std::vector{1}, // ndjydy + 0, // ndxrdatadxsolver + 0, // ndxrdatadtcl + 0, // ndtotal_cldx_rdata + 0, // nnz + 3, // ubw + 3, // lbw + true, // pythonGenerated + 3, // ndxdotdp_explicit + 4, // ndxdotdx_explicit + 0 // w_recursion_depth + ), + amici::SimulationParameters( + std::vector{4.0, 8.0, 10.0, 4.0}, // fixedParameters + std::vector{0.5, 2.0, 0.5, 0.5} // dynamic parameters + ), + amici::SecondOrderMode::none, // o2mode + std::vector{1.0, 1.0, 1.0}, // idlist + std::vector{1, 2}, // z2events + std::vector{ + Event("event_1", false, true, NAN), + Event("event_2", false, true, NAN), + Event("Heaviside_2", true, true, NAN), + Event("Heaviside_3", true, true, NAN), + Event("Heaviside_4", true, true, NAN), + Event("Heaviside_5", true, true, NAN) + }, // events + {{4.0, {4, 5}}} // state-independent events + ) { + } + + /** + * @brief Clone this model instance. + * @return A deep copy of this instance. + */ + amici::Model *clone() const override { + return new Model_model_events_py(*this); + } + + void fJrz(realtype *Jrz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override { + Jrz_model_events_py(Jrz, iz, p, k, rz, sigmaz); + } + + + void fJy(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + Jy_model_events_py(Jy, iy, p, k, y, sigmay, my); + } + + + void fJz(realtype *Jz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override { + Jz_model_events_py(Jz, iz, p, k, z, sigmaz, mz); + } + + + void fdJrzdsigma(realtype *dJrzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override { + dJrzdsigma_model_events_py(dJrzdsigma, iz, p, k, rz, sigmaz); + } + + + void fdJrzdz(realtype *dJrzdz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override { + dJrzdz_model_events_py(dJrzdz, iz, p, k, rz, sigmaz); + } + + + void fdJydsigma(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydsigma_model_events_py(dJydsigma, iy, p, k, y, sigmay, my); + } + + + void fdJzdsigma(realtype *dJzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override { + dJzdsigma_model_events_py(dJzdsigma, iz, p, k, z, sigmaz, mz); + } + + + void fdJzdz(realtype *dJzdz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const double *mz) override { + dJzdz_model_events_py(dJzdz, iz, p, k, z, sigmaz, mz); + } + + + void fdeltax(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old) override {} + + + void fdeltasx(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old) override { + deltasx_model_events_py(deltasx, t, x, p, k, h, w, ip, ie, xdot, xdot_old, sx, stau, tcl, x_old); + } + + + void fdeltaxB(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl) override { + deltaxB_model_events_py(deltaxB, t, x, p, k, h, dx, ie, xdot, xdot_old, x_old, xB, tcl); + } + + + void fdeltaqB(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB) override { + deltaqB_model_events_py(deltaqB, t, x, p, k, h, dx, ip, ie, xdot, xdot_old, x_old, xB); + } + + + void fdrzdp(realtype *drzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdrzdx(realtype *drzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override { + drzdx_model_events_py(drzdx, ie, t, x, p, k, h); + } + + + void fdsigmaydp(realtype *dsigmaydp, const realtype t, const realtype *p, const realtype *k, const realtype *y, const int ip) override {} + + + void fdsigmaydy(realtype *dsigmaydy, const realtype t, const realtype *p, const realtype *k, const realtype *y) override {} + + + void fdsigmazdp(realtype *dsigmazdp, const realtype t, const realtype *p, const realtype *k, const int ip) override {} + + + void fdJydy(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydy_model_events_py(dJydy, iy, p, k, y, sigmay, my); + } + + void fdJydy_colptrs(SUNMatrixWrapper &colptrs, int index) override { + dJydy_colptrs_model_events_py(colptrs, index); + } + + void fdJydy_rowvals(SUNMatrixWrapper &rowvals, int index) override { + dJydy_rowvals_model_events_py(rowvals, index); + } + + + std::vector fcreate_splines(const realtype *p, const realtype *k) override { + return create_splines_model_events_py(p, k); + } + + void fdspline_valuesdp(realtype *dspline_valuesdp, const realtype *p, const realtype *k, const int ip) override {} + + void fdspline_slopesdp(realtype *dspline_slopesdp, const realtype *p, const realtype *k, const int ip) override {} + + + void fdwdp(realtype *dwdp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl, bool include_static) override {} + + void fdwdp_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdp_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdx(realtype *dwdx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *spl, bool include_static) override {} + + void fdwdx_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdx_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdw(realtype *dwdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, bool include_static) override {} + + void fdwdw_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdw_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdw(realtype *dxdotdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override {} + + void fdxdotdw_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdxdotdw_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdp_explicit(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + dxdotdp_explicit_model_events_py(dxdotdp_explicit, t, x, p, k, h, w); + } + + void fdxdotdp_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdp_explicit_colptrs_model_events_py(colptrs); + } + + void fdxdotdp_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdp_explicit_rowvals_model_events_py(rowvals); + } + + + void fdxdotdx_explicit(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + dxdotdx_explicit_model_events_py(dxdotdx_explicit, t, x, p, k, h, w); + } + + void fdxdotdx_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdx_explicit_colptrs_model_events_py(colptrs); + } + + void fdxdotdx_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdx_explicit_rowvals_model_events_py(rowvals); + } + + + void fdydx(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { + dydx_model_events_py(dydx, t, x, p, k, h, w, dwdx); + } + + + void fdydp(realtype *dydp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl) override { + dydp_model_events_py(dydp, t, x, p, k, h, ip, w, tcl, dtcldp, spl, sspl); + } + + + void fdzdp(realtype *dzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdzdx(realtype *dzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override { + dzdx_model_events_py(dzdx, ie, t, x, p, k, h); + } + + + void froot(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl) override { + root_model_events_py(root, t, x, p, k, h, tcl); + } + + + void frz(realtype *rz, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override { + rz_model_events_py(rz, ie, t, x, p, k, h); + } + + + void fsigmay(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y) override { + sigmay_model_events_py(sigmay, t, p, k, y); + } + + + void fsigmaz(realtype *sigmaz, const realtype t, const realtype *p, const realtype *k) override { + sigmaz_model_events_py(sigmaz, t, p, k); + } + + + void fstau(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie) override { + stau_model_events_py(stau, t, x, p, k, h, dx, tcl, sx, ip, ie); + } + + void fsx0(realtype *sx0, const realtype t, const realtype *x, const realtype *p, const realtype *k, const int ip) override {} + + void fsx0_fixedParameters(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs) override { + sx0_fixedParameters_model_events_py(sx0_fixedParameters, t, x0, p, k, ip, reinitialization_state_idxs); + } + + + void fw(realtype *w, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl, const realtype *spl, bool include_static) override {} + + + void fx0(realtype *x0, const realtype t, const realtype *p, const realtype *k) override { + x0_model_events_py(x0, t, p, k); + } + + + void fx0_fixedParameters(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs) override { + x0_fixedParameters_model_events_py(x0_fixedParameters, t, p, k, reinitialization_state_idxs); + } + + + void fxdot(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + xdot_model_events_py(xdot, t, x, p, k, h, w); + } + + + void fy(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + y_model_events_py(y, t, x, p, k, h, w); + } + + + void fz(realtype *z, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override { + z_model_events_py(z, ie, t, x, p, k, h); + } + + + + + void fx_solver(realtype *x_solver, const realtype *x_rdata) override { + x_solver_model_events_py(x_solver, x_rdata); + } + + + void ftotal_cl(realtype *total_cl, const realtype *x_rdata, const realtype *p, const realtype *k) override {} + + + void fdx_rdatadx_solver(realtype *dx_rdatadx_solver, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadx_solver_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadx_solver_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdx_rdatadp(realtype *dx_rdatadp, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k, const int ip) override {} + + + void fdx_rdatadtcl(realtype *dx_rdatadtcl, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadtcl_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadtcl_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdtotal_cldp(realtype *dtotal_cldp, const realtype *x_rdata, const realtype *p, const realtype *k, const int ip) override {} + + + void fdtotal_cldx_rdata(realtype *dtotal_cldx_rdata, const realtype *x_rdata, const realtype *p, const realtype *k, const realtype *tcl) override {} + + void fdtotal_cldx_rdata_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdtotal_cldx_rdata_rowvals(SUNMatrixWrapper &rowvals) override {} + + + std::string getName() const override { + return "model_events_py"; + } + + /** + * @brief Get names of the model parameters + * @return the names + */ + std::vector getParameterNames() const override { + return std::vector(parameterNames.begin(), + parameterNames.end()); + } + + /** + * @brief Get names of the model states + * @return the names + */ + std::vector getStateNames() const override { + return std::vector(stateNames.begin(), stateNames.end()); + } + + /** + * @brief Get names of the solver states + * @return the names + */ + std::vector getStateNamesSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto const idx: stateIdxsSolver) { + result.push_back(stateNames[idx]); + } + return result; + } + + /** + * @brief Get names of the fixed model parameters + * @return the names + */ + std::vector getFixedParameterNames() const override { + return std::vector(fixedParameterNames.begin(), + fixedParameterNames.end()); + } + + /** + * @brief Get names of the observables + * @return the names + */ + std::vector getObservableNames() const override { + return std::vector(observableNames.begin(), + observableNames.end()); + } + + /** + * @brief Get names of model expressions + * @return Expression names + */ + std::vector getExpressionNames() const override { + return std::vector(expressionNames.begin(), + expressionNames.end()); + } + + /** + * @brief Get ids of the model parameters + * @return the ids + */ + std::vector getParameterIds() const override { + return std::vector(parameterIds.begin(), + parameterIds.end()); + } + + /** + * @brief Get ids of the model states + * @return the ids + */ + std::vector getStateIds() const override { + return std::vector(stateIds.begin(), stateIds.end()); + } + + /** + * @brief Get ids of the solver states + * @return the ids + */ + std::vector getStateIdsSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto idx: stateIdxsSolver) { + result.push_back(stateIds[idx]); + } + return result; + } + + /** + * @brief Get ids of the fixed model parameters + * @return the ids + */ + std::vector getFixedParameterIds() const override { + return std::vector(fixedParameterIds.begin(), + fixedParameterIds.end()); + } + + /** + * @brief Get ids of the observables + * @return the ids + */ + std::vector getObservableIds() const override { + return std::vector(observableIds.begin(), + observableIds.end()); + } + + /** + * @brief Get IDs of model expressions + * @return Expression IDs + */ + std::vector getExpressionIds() const override { + return std::vector(expressionIds.begin(), + expressionIds.end()); + } + + /** + * @brief function indicating whether reinitialization of states depending + * on fixed parameters is permissible + * @return flag indicating whether reinitialization of states depending on + * fixed parameters is permissible + */ + bool isFixedParameterStateReinitializationAllowed() const override { + return true; + } + + /** + * @brief returns the AMICI version that was used to generate the model + * @return AMICI version string + */ + std::string getAmiciVersion() const override { + return "0.33.0"; + } + + /** + * @brief returns the amici version that was used to generate the model + * @return AMICI git commit hash + */ + std::string getAmiciCommit() const override { + return "bcedb951ddf674996b269489d74f9b86112038ff"; + } + + bool hasQuadraticLLH() const override { + return true; + } + + ObservableScaling getObservableScaling(int iy) const override { + return observableScalings.at(iy); + } +}; + + +} // namespace model_model_events_py + +} // namespace amici + +#endif /* _amici_TPL_MODELNAME_h */ diff --git a/models/model_events_py/my.h b/models/model_events_py/my.h new file mode 100644 index 0000000000..3294c09fd3 --- /dev/null +++ b/models/model_events_py/my.h @@ -0,0 +1 @@ +#define my1 my[0] diff --git a/models/model_events_py/mz.h b/models/model_events_py/mz.h new file mode 100644 index 0000000000..1c1ffe5bdf --- /dev/null +++ b/models/model_events_py/mz.h @@ -0,0 +1,2 @@ +#define mz1 mz[0] +#define mz2 mz[1] diff --git a/models/model_events_py/p.h b/models/model_events_py/p.h new file mode 100644 index 0000000000..d1c547a672 --- /dev/null +++ b/models/model_events_py/p.h @@ -0,0 +1,4 @@ +#define p1 p[0] +#define p2 p[1] +#define p3 p[2] +#define p4 p[3] diff --git a/models/model_events_py/root.cpp b/models/model_events_py/root.cpp new file mode 100644 index 0000000000..b086df8619 --- /dev/null +++ b/models/model_events_py/root.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" + +namespace amici { +namespace model_model_events_py { + +void root_model_events_py(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl){ + root[0] = x2 - x3; + root[1] = x1 - x3; + root[2] = p4 - t; + root[3] = -p4 + t; + root[4] = 4 - t; + root[5] = t - 4; +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/rz.cpp b/models/model_events_py/rz.cpp new file mode 100644 index 0000000000..323adb8773 --- /dev/null +++ b/models/model_events_py/rz.cpp @@ -0,0 +1,29 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "rz.h" + +namespace amici { +namespace model_model_events_py { + +void rz_model_events_py(realtype *rz, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h){ + switch(ie) { + case 0: + rz[0] = x2 - x3; + break; + case 1: + rz[1] = x1 - x3; + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/rz.h b/models/model_events_py/rz.h new file mode 100644 index 0000000000..08f8eeb735 --- /dev/null +++ b/models/model_events_py/rz.h @@ -0,0 +1,2 @@ +#define rz1 rz[0] +#define rz2 rz[1] diff --git a/models/model_events_py/setup.py b/models/model_events_py/setup.py new file mode 100644 index 0000000000..7676372a14 --- /dev/null +++ b/models/model_events_py/setup.py @@ -0,0 +1,95 @@ +"""AMICI model package setup""" + +import os +import sys +from pathlib import Path + +from amici import _get_amici_path +from amici.custom_commands import AmiciBuildCMakeExtension +from cmake_build_extension import CMakeExtension +from setuptools import find_namespace_packages, setup +import importlib.metadata + + +def get_extension() -> CMakeExtension: + """Get setuptools extension object for this AMICI model package""" + + # Build shared object + prefix_path = Path(_get_amici_path()) + AmiciBuildCMakeExtension.extend_cmake_prefix_path(str(prefix_path)) + + # handle parallel building + # Note: can be empty to use all hardware threads + if (parallel_jobs := os.environ.get("AMICI_PARALLEL_COMPILE")) is not None: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = parallel_jobs + else: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = "1" + + debug_build = os.getenv("ENABLE_AMICI_DEBUGGING", "").lower() in [ + "1", + "true", + ] or os.getenv("ENABLE_GCOV_COVERAGE", "").lower() in ["1", "true"] + + cmake_prefix_path = os.getenv("CMAKE_PREFIX_PATH", "").split(os.pathsep) + cmake_prefix_path.append(prefix_path.as_posix()) + + # If scipy_openblas64 is installed, we make its cmake configuration + # available + amici_distribution = importlib.metadata.distribution("amici") + amici_dir = Path(amici_distribution.locate_file("")) + # this path is created during the amici build if scipy_openblas64 is used + openblas_cmake_dir = amici_dir / "lib" / "cmake" / "openblas" + if openblas_cmake_dir.exists(): + cmake_prefix_path.append(str(openblas_cmake_dir)) + + return CMakeExtension( + name="model_ext", + source_dir=os.getcwd(), + install_prefix="model_events_py", + cmake_configure_options=[ + "-DCMAKE_VERBOSE_MAKEFILE=ON", + f"-DCMAKE_PREFIX_PATH='{';'.join(cmake_prefix_path)}'", + "-DAMICI_PYTHON_BUILD_EXT_ONLY=ON", + f"-DPython3_EXECUTABLE={Path(sys.executable).as_posix()}", + ], + cmake_build_type="Debug" if debug_build else "Release", + ) + + +# Change working directory to setup.py location +os.chdir(os.path.dirname(os.path.abspath(__file__))) + +MODEL_EXT = get_extension() + +CLASSIFIERS = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Science/Research", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python", + "Programming Language :: C++", + "Topic :: Scientific/Engineering :: Bio-Informatics", +] + +CMDCLASS = { + # for CMake-based builds + "build_ext": AmiciBuildCMakeExtension, +} + +# Install +setup( + name="model_events_py", + cmdclass=CMDCLASS, + version="0.1.0", + description="AMICI-generated module for model model_events_py", + url="https://github.com/AMICI-dev/AMICI", + author="model-author-todo", + author_email="model-author-todo", + ext_modules=[MODEL_EXT], + packages=find_namespace_packages(), + install_requires=["amici==0.33.0"], + python_requires=">=3.11", + package_data={}, + zip_safe=False, + classifiers=CLASSIFIERS, +) diff --git a/models/model_events_py/sigmay.cpp b/models/model_events_py/sigmay.cpp new file mode 100644 index 0000000000..e2c7c41728 --- /dev/null +++ b/models/model_events_py/sigmay.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" + +namespace amici { +namespace model_model_events_py { + +void sigmay_model_events_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y){ + sigma_y1 = 1.0; // sigmay[0] +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/sigmay.h b/models/model_events_py/sigmay.h new file mode 100644 index 0000000000..3e9be142ed --- /dev/null +++ b/models/model_events_py/sigmay.h @@ -0,0 +1 @@ +#define sigma_y1 sigmay[0] diff --git a/models/model_events_py/sigmaz.cpp b/models/model_events_py/sigmaz.cpp new file mode 100644 index 0000000000..b6c79d1ea7 --- /dev/null +++ b/models/model_events_py/sigmaz.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "sigmaz.h" + +namespace amici { +namespace model_model_events_py { + +void sigmaz_model_events_py(realtype *sigmaz, const realtype t, const realtype *p, const realtype *k){ + sigma_z1 = 1.0; // sigmaz[0] + sigma_z2 = 1.0; // sigmaz[1] +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/sigmaz.h b/models/model_events_py/sigmaz.h new file mode 100644 index 0000000000..6eab74a5bf --- /dev/null +++ b/models/model_events_py/sigmaz.h @@ -0,0 +1,2 @@ +#define sigma_z1 sigmaz[0] +#define sigma_z2 sigmaz[1] diff --git a/models/model_events_py/stau.cpp b/models/model_events_py/stau.cpp new file mode 100644 index 0000000000..d74bc2beb4 --- /dev/null +++ b/models/model_events_py/stau.cpp @@ -0,0 +1,51 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "sx.h" + +namespace amici { +namespace model_model_events_py { + +void stau_model_events_py(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie){ + switch(ie) { + case 0: + switch(ip) { + case 0: + case 1: + case 2: + case 3: + stau[0] = (sx1 - sx2)/(Heaviside_4 + p2*x1*std::exp(-1.0/10.0*t) - p3*x2 + x3 - 1); + break; + } + break; + case 1: + switch(ip) { + case 0: + case 1: + case 2: + case 3: + stau[0] = (sx0 - sx2)/(Heaviside_4 - p1*x1*(1 - Heaviside_2) + x3 - 1); + break; + } + break; + case 2: + case 3: + switch(ip) { + case 3: + stau[0] = -1; + break; + } + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/stau.h b/models/model_events_py/stau.h new file mode 100644 index 0000000000..2871b2462c --- /dev/null +++ b/models/model_events_py/stau.h @@ -0,0 +1 @@ +#define stau0 stau[0] diff --git a/models/model_events_py/swig/CMakeLists.txt b/models/model_events_py/swig/CMakeLists.txt new file mode 100644 index 0000000000..314996c479 --- /dev/null +++ b/models/model_events_py/swig/CMakeLists.txt @@ -0,0 +1,60 @@ +if(DEFINED ENV{SWIG}) + set(SWIG_EXECUTABLE $ENV{SWIG}) +endif() + +find_package(SWIG REQUIRED) +include(${SWIG_USE_FILE}) + +if(DEFINED ENV{PYTHON_EXECUTABLE}) + set(Python3_EXECUTABLE $ENV{PYTHON_EXECUTABLE}) +endif() +# We don't need "Interpreter" here, but without that, FindPython3 will +# ignore the Python version selected via $Python3_EXECUTABLE +find_package(Python3 COMPONENTS Interpreter Development) +include_directories(${Python3_INCLUDE_DIRS}) + +set(SWIG_LIBRARY_NAME _${PROJECT_NAME}) +set(CMAKE_SWIG_FLAGS "") +set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) + +# swig does not use INTERFACE_INCLUDE_DIRS of linked libraries, so add manually +get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) +include_directories(${AMICI_INCLUDE_DIRS} .. ${AMICI_INCLUDE_DIRS}/../swig) + +swig_add_library(${SWIG_LIBRARY_NAME} + TYPE MODULE + LANGUAGE python + SOURCES ${PROJECT_NAME}.i) + + +set_target_properties(${SWIG_LIBRARY_NAME} + PROPERTIES + SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE + PREFIX "" +) + +# Python extension suffix +execute_process( + COMMAND ${Python3_EXECUTABLE} -c + "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))" + OUTPUT_VARIABLE PY_EXT_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE) +if(NOT "${PY_EXT_SUFFIX}" STREQUAL "") + message(STATUS "Python extension suffix is ${PY_EXT_SUFFIX}") + set_target_properties(${SWIG_LIBRARY_NAME} PROPERTIES SUFFIX "${PY_EXT_SUFFIX}" ) +endif() + + +swig_link_libraries(${SWIG_LIBRARY_NAME} + ${Python3_LIBRARIES} + model) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.py + $ DESTINATION .) + +# configure module setup script +set(SETUP_PY_IN ${Amici_DIR}/model_setup.template.py) +set(SETUP_PY_OUT ${CMAKE_CURRENT_BINARY_DIR}/setup.py) + +add_custom_target(install-python + DEPENDS ${SWIG_LIBRARY_NAME} + COMMAND python ${SETUP_PY_OUT} install) diff --git a/models/model_events_py/swig/model_events_py.i b/models/model_events_py/swig/model_events_py.i new file mode 100644 index 0000000000..192014f2cd --- /dev/null +++ b/models/model_events_py/swig/model_events_py.i @@ -0,0 +1,82 @@ +%define MODULEIMPORT +" +import amici +import datetime +import importlib.util +import os +import sysconfig +from pathlib import Path + +ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +_model_events_py = amici._module_from_path( + 'model_events_py._model_events_py' if __package__ or '.' in __name__ + else '_model_events_py', + Path(__file__).parent / f'_model_events_py{ext_suffix}', +) + +def _get_import_time(): + return _model_events_py._get_import_time() + +t_imported = _get_import_time() +t_modified = os.path.getmtime(__file__) +if t_imported < t_modified: + t_imp_str = datetime.datetime.fromtimestamp(t_imported).isoformat() + t_mod_str = datetime.datetime.fromtimestamp(t_modified).isoformat() + module_path = Path(__file__).resolve() + raise RuntimeError( + f'Cannot import extension for model_events_py from ' + f'{module_path}, because an extension in the same location ' + f'has already been imported, but the file was modified on ' + f'disk. \\nImported at {t_imp_str}\\nModified at {t_mod_str}.\\n' + 'Import the module with a different name or restart the ' + 'Python kernel.' + ) +" +%enddef + +%module(package="model_events_py",moduleimport=MODULEIMPORT) model_events_py + +%pythoncode %{ +# the model-package __init__.py module (will be set during import) +_model_module = None + + +%} + +%import amici.i +// Add necessary symbols to generated header + +%{ +#include "wrapfunctions.h" +#include "amici/model_ode.h" +#include "amici/model_dae.h" +using namespace amici; +%} + +// store the time a module was imported +%{ +#include +static std::chrono::time_point _module_import_time; + +static double _get_import_time() { + auto epoch = _module_import_time.time_since_epoch(); + return std::chrono::duration(epoch).count(); +} +%} + +static double _get_import_time(); + +%init %{ + _module_import_time = std::chrono::system_clock::now(); +%} + + +// Make model module accessible from the model +%feature("pythonappend") amici::generic_model::getModel %{ + if '.' in __name__: + val.module = _model_module +%} + + +// Process symbols in header +%include "wrapfunctions.h" diff --git a/models/model_events_py/sx.h b/models/model_events_py/sx.h new file mode 100644 index 0000000000..9c6d35b064 --- /dev/null +++ b/models/model_events_py/sx.h @@ -0,0 +1,3 @@ +#define sx0 sx[0] +#define sx1 sx[1] +#define sx2 sx[2] diff --git a/models/model_events_py/sx0_fixedParameters.cpp b/models/model_events_py/sx0_fixedParameters.cpp new file mode 100644 index 0000000000..6cb4d0fe5c --- /dev/null +++ b/models/model_events_py/sx0_fixedParameters.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_events_py { + +void sx0_fixedParameters_model_events_py(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs){ + static const std::array _x0_fixedParameters_idxs = { + 0, 1, 2 + }; + for(auto idx: reinitialization_state_idxs) { + if(std::find(_x0_fixedParameters_idxs.cbegin(), _x0_fixedParameters_idxs.cend(), idx) != _x0_fixedParameters_idxs.cend()) + sx0_fixedParameters[idx] = 0.0; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/w.h b/models/model_events_py/w.h new file mode 100644 index 0000000000..c399413a8c --- /dev/null +++ b/models/model_events_py/w.h @@ -0,0 +1 @@ +#define flux_r0 w[0] diff --git a/models/model_events_py/wrapfunctions.cpp b/models/model_events_py/wrapfunctions.cpp new file mode 100644 index 0000000000..4f53e8b48b --- /dev/null +++ b/models/model_events_py/wrapfunctions.cpp @@ -0,0 +1,16 @@ +#include "wrapfunctions.h" +#include "model_events_py.h" +#include "amici/model.h" + +namespace amici { +namespace generic_model { + +std::unique_ptr getModel() { + return std::unique_ptr( + new amici::model_model_events_py::Model_model_events_py() + ); +} + +} // namespace generic_model + +} // namespace amici diff --git a/models/model_events_py/wrapfunctions.h b/models/model_events_py/wrapfunctions.h new file mode 100644 index 0000000000..33c8a9d819 --- /dev/null +++ b/models/model_events_py/wrapfunctions.h @@ -0,0 +1,25 @@ +#ifndef _amici_wrapfunctions_h +#define _amici_wrapfunctions_h + +#include + +#include "amici/model.h" + +namespace amici { +namespace generic_model { + + +/** + * @brief Wrapper function to instantiate the linked Amici model without knowing + * the name at compile time. + * @return Model instance + */ +std::unique_ptr getModel(); + + +} // namespace generic_model + +} // namespace amici + + +#endif /* _amici_wrapfunctions_h */ diff --git a/models/model_events_py/x.h b/models/model_events_py/x.h new file mode 100644 index 0000000000..7c21f2ef67 --- /dev/null +++ b/models/model_events_py/x.h @@ -0,0 +1,3 @@ +#define x1 x[0] +#define x2 x[1] +#define x3 x[2] diff --git a/models/model_events_py/x0.cpp b/models/model_events_py/x0.cpp new file mode 100644 index 0000000000..42c1cbe251 --- /dev/null +++ b/models/model_events_py/x0.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_events_py { + +void x0_model_events_py(realtype *x0, const realtype t, const realtype *p, const realtype *k){ + x0[0] = k1; + x0[1] = k2; + x0[2] = k3; +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/x0_fixedParameters.cpp b/models/model_events_py/x0_fixedParameters.cpp new file mode 100644 index 0000000000..29226675cd --- /dev/null +++ b/models/model_events_py/x0_fixedParameters.cpp @@ -0,0 +1,24 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_events_py { + +void x0_fixedParameters_model_events_py(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs){ + if(std::find(reinitialization_state_idxs.cbegin(), reinitialization_state_idxs.cend(), 0) != reinitialization_state_idxs.cend()) + x0_fixedParameters[0] = k1; + if(std::find(reinitialization_state_idxs.cbegin(), reinitialization_state_idxs.cend(), 1) != reinitialization_state_idxs.cend()) + x0_fixedParameters[1] = k2; + if(std::find(reinitialization_state_idxs.cbegin(), reinitialization_state_idxs.cend(), 2) != reinitialization_state_idxs.cend()) + x0_fixedParameters[2] = k3; +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/xB.h b/models/model_events_py/xB.h new file mode 100644 index 0000000000..554e8e3429 --- /dev/null +++ b/models/model_events_py/xB.h @@ -0,0 +1,3 @@ +#define xB0 xB[0] +#define xB1 xB[1] +#define xB2 xB[2] diff --git a/models/model_events_py/x_old.h b/models/model_events_py/x_old.h new file mode 100644 index 0000000000..4cda73d4d9 --- /dev/null +++ b/models/model_events_py/x_old.h @@ -0,0 +1,3 @@ +#define x_old0 x_old[0] +#define x_old1 x_old[1] +#define x_old2 x_old[2] diff --git a/models/model_events_py/x_rdata.cpp b/models/model_events_py/x_rdata.cpp new file mode 100644 index 0000000000..c801108187 --- /dev/null +++ b/models/model_events_py/x_rdata.cpp @@ -0,0 +1,22 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_events_py { + +void x_rdata_model_events_py(realtype *x_rdata, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k){ + x_rdata[0] = x1; + x_rdata[1] = x2; + x_rdata[2] = x3; +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/x_rdata.h b/models/model_events_py/x_rdata.h new file mode 100644 index 0000000000..4b2aa926d2 --- /dev/null +++ b/models/model_events_py/x_rdata.h @@ -0,0 +1,3 @@ +#define x1 x_rdata[0] +#define x2 x_rdata[1] +#define x3 x_rdata[2] diff --git a/models/model_events_py/x_solver.cpp b/models/model_events_py/x_solver.cpp new file mode 100644 index 0000000000..a7684d9572 --- /dev/null +++ b/models/model_events_py/x_solver.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x_rdata.h" + +namespace amici { +namespace model_model_events_py { + +void x_solver_model_events_py(realtype *x_solver, const realtype *x_rdata){ + x_solver[0] = x1; + x_solver[1] = x2; + x_solver[2] = x3; +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/x_solver.h b/models/model_events_py/x_solver.h new file mode 100644 index 0000000000..ef1d32a257 --- /dev/null +++ b/models/model_events_py/x_solver.h @@ -0,0 +1,3 @@ +#define x_solver0 x_solver[0] +#define x_solver1 x_solver[1] +#define x_solver2 x_solver[2] diff --git a/models/model_events_py/xdot.cpp b/models/model_events_py/xdot.cpp new file mode 100644 index 0000000000..d55e43da10 --- /dev/null +++ b/models/model_events_py/xdot.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "w.h" +#include "xdot.h" + +namespace amici { +namespace model_model_events_py { + +void xdot_model_events_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + dx1dt = -p1*x1*(1 - Heaviside_2); // xdot[0] + dx2dt = p2*x1*std::exp(-1.0/10.0*t) - p3*x2; // xdot[1] + dx3dt = -Heaviside_4 - x3 + 1; // xdot[2] +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/xdot.h b/models/model_events_py/xdot.h new file mode 100644 index 0000000000..f58eec3752 --- /dev/null +++ b/models/model_events_py/xdot.h @@ -0,0 +1,3 @@ +#define dx1dt xdot[0] +#define dx2dt xdot[1] +#define dx3dt xdot[2] diff --git a/models/model_events_py/xdot_old.h b/models/model_events_py/xdot_old.h new file mode 100644 index 0000000000..93d0dae41d --- /dev/null +++ b/models/model_events_py/xdot_old.h @@ -0,0 +1,3 @@ +#define xdot_old0 xdot_old[0] +#define xdot_old1 xdot_old[1] +#define xdot_old2 xdot_old[2] diff --git a/models/model_events_py/y.cpp b/models/model_events_py/y.cpp new file mode 100644 index 0000000000..1a03426981 --- /dev/null +++ b/models/model_events_py/y.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" + +namespace amici { +namespace model_model_events_py { + +void y_model_events_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + y[0] = p4*(x1 + x2 + x3); +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/y.h b/models/model_events_py/y.h new file mode 100644 index 0000000000..d9a40dc715 --- /dev/null +++ b/models/model_events_py/y.h @@ -0,0 +1 @@ +#define y1 y[0] diff --git a/models/model_events_py/z.cpp b/models/model_events_py/z.cpp new file mode 100644 index 0000000000..c8acaf8153 --- /dev/null +++ b/models/model_events_py/z.cpp @@ -0,0 +1,29 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "z.h" + +namespace amici { +namespace model_model_events_py { + +void z_model_events_py(realtype *z, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h){ + switch(ie) { + case 0: + z[0] = t; + break; + case 1: + z[1] = t; + break; + } +} + +} // namespace model_model_events_py +} // namespace amici diff --git a/models/model_events_py/z.h b/models/model_events_py/z.h new file mode 100644 index 0000000000..6d36e2782c --- /dev/null +++ b/models/model_events_py/z.h @@ -0,0 +1,2 @@ +#define z1 z[0] +#define z2 z[1] diff --git a/models/model_jakstat_adjoint_py/CMakeLists.txt b/models/model_jakstat_adjoint_py/CMakeLists.txt new file mode 100644 index 0000000000..f6106314a3 --- /dev/null +++ b/models/model_jakstat_adjoint_py/CMakeLists.txt @@ -0,0 +1,149 @@ +# Build AMICI model +cmake_minimum_required(VERSION 3.22) +cmake_policy(VERSION 3.22...3.31) + +project(model_jakstat_adjoint_py) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +include(CheckCXXCompilerFlag) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() +foreach(flag ${MY_CXX_FLAGS}) + unset(CUR_FLAG_SUPPORTED CACHE) + check_cxx_compiler_flag(${flag} CUR_FLAG_SUPPORTED) + if(${CUR_FLAG_SUPPORTED}) + string(APPEND CMAKE_CXX_FLAGS " ${flag}") + endif() +endforeach() + +if(DEFINED ENV{AMICI_CXXFLAGS}) + message(STATUS "Appending flags from AMICI_CXXFLAGS: $ENV{AMICI_CXXFLAGS}") + add_compile_options("$ENV{AMICI_CXXFLAGS}") +endif() +if(DEFINED ENV{AMICI_LDFLAGS}) + message(STATUS "Appending flags from AMICI_LDFLAGS: $ENV{AMICI_LDFLAGS}") + link_libraries("$ENV{AMICI_LDFLAGS}") +endif() + +find_package(Amici 0.33.0 REQUIRED HINTS + ${CMAKE_CURRENT_LIST_DIR}/../../build) +message(STATUS "Found AMICI ${Amici_DIR}") +set_target_properties(Upstream::amici PROPERTIES + MAP_IMPORTED_CONFIG_RELWITHDEBINFO RelWithDebInfo;Release; + MAP_IMPORTED_CONFIG_RELEASE Release + MAP_IMPORTED_CONFIG_DEBUG Debug;RelWithDebInfo;) + +# Debug build? +if("$ENV{ENABLE_AMICI_DEBUGGING}" OR "$ENV{ENABLE_GCOV_COVERAGE}") + add_compile_options(-UNDEBUG) + if(MSVC) + add_compile_options(-DEBUG) + else() + add_compile_options(-O0 -g) + endif() +endif() + +# coverage options +if($ENV{ENABLE_GCOV_COVERAGE}) + string(APPEND CMAKE_CXX_FLAGS_DEBUG " --coverage") + string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " --coverage") +endif() + +set(MODEL_DIR ${CMAKE_CURRENT_LIST_DIR}) + +set(SRC_LIST_LIB Jy.cpp +Jy.h +create_splines.cpp +dJydsigma.cpp +dJydy.cpp +dJydy.h +dsigmaydp.cpp +dspline_valuesdp.cpp +dwdp.cpp +dwdp.h +dxdotdp_explicit.cpp +dxdotdp_explicit.h +dxdotdw.cpp +dxdotdw.h +dxdotdx_explicit.cpp +dxdotdx_explicit.h +dydp.cpp +dydx.cpp +k.h +model_jakstat_adjoint_py.cpp +model_jakstat_adjoint_py.h +my.h +p.h +sigmay.cpp +sigmay.h +spl.h +sspl.h +w.cpp +w.h +wrapfunctions.cpp +wrapfunctions.h +x.h +x0.cpp +x_rdata.cpp +x_rdata.h +x_solver.cpp +x_solver.h +xdot.cpp +xdot.h +y.cpp +y.h ${MODEL_DIR}/wrapfunctions.cpp) + +add_library(${PROJECT_NAME} ${SRC_LIST_LIB}) + +# ${PROJECT_NAME} might already be "model" +if(NOT TARGET model) + add_library(model ALIAS ${PROJECT_NAME}) +endif() + +# Some special functions require boost +# +# TODO: set some flag during code generation whether the given model requires +# boost. for now, try to find it, add include directories and link against it. +# let the compiler/linker error if it is required but not found +find_package(Boost) + +target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") + +target_link_libraries( + ${PROJECT_NAME} + PUBLIC Upstream::amici + PRIVATE $<$:Boost::boost>) + +if(NOT "${AMICI_PYTHON_BUILD_EXT_ONLY}") + set(SRC_LIST_EXE main.cpp) + add_executable(simulate_${PROJECT_NAME} ${SRC_LIST_EXE}) + target_link_libraries(simulate_${PROJECT_NAME} ${PROJECT_NAME}) +endif() + +# SWIG +option(ENABLE_SWIG "Build swig/python library?" ON) +if(ENABLE_SWIG) + add_subdirectory(swig) +endif() + +# +include(GNUInstallDirs) +install( + TARGETS ${PROJECT_NAME} + EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +export( + EXPORT ${PROJECT_NAME}Targets + FILE ${PROJECT_NAME}Config.cmake + NAMESPACE Upstream::) +# diff --git a/models/model_jakstat_adjoint_py/Jy.cpp b/models/model_jakstat_adjoint_py/Jy.cpp new file mode 100644 index 0000000000..10d26e174a --- /dev/null +++ b/models/model_jakstat_adjoint_py/Jy.cpp @@ -0,0 +1,32 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void Jy_model_jakstat_adjoint_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_pSTAT, 2)) + 0.5*std::pow(-mobs_pSTAT + obs_pSTAT, 2)/std::pow(sigma_obs_pSTAT, 2); + break; + case 1: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_tSTAT, 2)) + 0.5*std::pow(-mobs_tSTAT + obs_tSTAT, 2)/std::pow(sigma_obs_tSTAT, 2); + break; + case 2: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_spline, 2)) + 0.5*std::pow(-mobs_spline + obs_spline, 2)/std::pow(sigma_obs_spline, 2); + break; + } +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/Jy.h b/models/model_jakstat_adjoint_py/Jy.h new file mode 100644 index 0000000000..e7751bcae0 --- /dev/null +++ b/models/model_jakstat_adjoint_py/Jy.h @@ -0,0 +1,3 @@ +#define Jy0 Jy[0] +#define Jy1 Jy[1] +#define Jy2 Jy[2] diff --git a/models/model_jakstat_adjoint_py/create_splines.cpp b/models/model_jakstat_adjoint_py/create_splines.cpp new file mode 100644 index 0000000000..049ba69b11 --- /dev/null +++ b/models/model_jakstat_adjoint_py/create_splines.cpp @@ -0,0 +1,32 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "amici/splinefunctions.h" +#include +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +std::vector create_splines_model_jakstat_adjoint_py(const realtype *p, const realtype *k){ + return { + HermiteSpline( + {0, 5, 10, 20, 60}, + {sp1, sp2, sp3, sp4, sp5}, + {}, + SplineBoundaryCondition::zeroDerivative, + SplineBoundaryCondition::zeroDerivative, + SplineExtrapolation::constant, + SplineExtrapolation::constant, + true, false, true + ), + }; +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/dJydsigma.cpp b/models/model_jakstat_adjoint_py/dJydsigma.cpp new file mode 100644 index 0000000000..6b7c61457e --- /dev/null +++ b/models/model_jakstat_adjoint_py/dJydsigma.cpp @@ -0,0 +1,32 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void dJydsigma_model_jakstat_adjoint_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydsigma[0] = 1.0/sigma_obs_pSTAT - 1.0*std::pow(-mobs_pSTAT + obs_pSTAT, 2)/std::pow(sigma_obs_pSTAT, 3); + break; + case 1: + dJydsigma[1] = 1.0/sigma_obs_tSTAT - 1.0*std::pow(-mobs_tSTAT + obs_tSTAT, 2)/std::pow(sigma_obs_tSTAT, 3); + break; + case 2: + dJydsigma[2] = 1.0/sigma_obs_spline - 1.0*std::pow(-mobs_spline + obs_spline, 2)/std::pow(sigma_obs_spline, 3); + break; + } +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/dJydy.cpp b/models/model_jakstat_adjoint_py/dJydy.cpp new file mode 100644 index 0000000000..4f5541b842 --- /dev/null +++ b/models/model_jakstat_adjoint_py/dJydy.cpp @@ -0,0 +1,78 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +static constexpr std::array, 3> dJydy_colptrs_model_jakstat_adjoint_py_ = {{ + {0, 1, 1, 1}, + {0, 0, 1, 1}, + {0, 0, 0, 1}, +}}; + +void dJydy_colptrs_model_jakstat_adjoint_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexptrs(gsl::make_span(dJydy_colptrs_model_jakstat_adjoint_py_[index])); +} +} // namespace model_model_jakstat_adjoint_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +static constexpr std::array, 3> dJydy_rowvals_model_jakstat_adjoint_py_ = {{ + {0}, + {0}, + {0}, +}}; + +void dJydy_rowvals_model_jakstat_adjoint_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexvals(gsl::make_span(dJydy_rowvals_model_jakstat_adjoint_py_[index])); +} +} // namespace model_model_jakstat_adjoint_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" +#include "dJydy.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void dJydy_model_jakstat_adjoint_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydy[0] = (-1.0*mobs_pSTAT + 1.0*obs_pSTAT)/std::pow(sigma_obs_pSTAT, 2); + break; + case 1: + dJydy[0] = (-1.0*mobs_tSTAT + 1.0*obs_tSTAT)/std::pow(sigma_obs_tSTAT, 2); + break; + case 2: + dJydy[0] = (-1.0*mobs_spline + 1.0*obs_spline)/std::pow(sigma_obs_spline, 2); + break; + } +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/dJydy.h b/models/model_jakstat_adjoint_py/dJydy.h new file mode 100644 index 0000000000..e7c85d4f30 --- /dev/null +++ b/models/model_jakstat_adjoint_py/dJydy.h @@ -0,0 +1,3 @@ +#define dJy0_dobs_pSTAT dJydy[0] +#define dJy0_dobs_tSTAT_1 dJydy[1] +#define dJy0_dobs_spline_2 dJydy[2] diff --git a/models/model_jakstat_adjoint_py/dsigmaydp.cpp b/models/model_jakstat_adjoint_py/dsigmaydp.cpp new file mode 100644 index 0000000000..5185beaf6a --- /dev/null +++ b/models/model_jakstat_adjoint_py/dsigmaydp.cpp @@ -0,0 +1,30 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void dsigmaydp_model_jakstat_adjoint_py(realtype *dsigmaydp, const realtype t, const realtype *p, const realtype *k, const realtype *y, const int ip){ + switch(ip) { + case 14: + dsigmaydp[0] = 1; + break; + case 15: + dsigmaydp[1] = 1; + break; + case 16: + dsigmaydp[2] = 1; + break; + } +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/dspline_valuesdp.cpp b/models/model_jakstat_adjoint_py/dspline_valuesdp.cpp new file mode 100644 index 0000000000..e9ba219b48 --- /dev/null +++ b/models/model_jakstat_adjoint_py/dspline_valuesdp.cpp @@ -0,0 +1,35 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void dspline_valuesdp_model_jakstat_adjoint_py(realtype *dspline_valuesdp, const realtype *p, const realtype *k, const int ip){ + switch(ip) { + case 5: + dspline_valuesdp[0] = 1; + break; + case 6: + dspline_valuesdp[1] = 1; + break; + case 7: + dspline_valuesdp[2] = 1; + break; + case 8: + dspline_valuesdp[3] = 1; + break; + case 9: + dspline_valuesdp[4] = 1; + break; + } +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/dwdp.cpp b/models/model_jakstat_adjoint_py/dwdp.cpp new file mode 100644 index 0000000000..3ce78097b9 --- /dev/null +++ b/models/model_jakstat_adjoint_py/dwdp.cpp @@ -0,0 +1,71 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +static constexpr std::array dwdp_colptrs_model_jakstat_adjoint_py_ = { + 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5 +}; + +void dwdp_colptrs_model_jakstat_adjoint_py(SUNMatrixWrapper &dwdp){ + dwdp.set_indexptrs(gsl::make_span(dwdp_colptrs_model_jakstat_adjoint_py_)); +} +} // namespace model_model_jakstat_adjoint_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +static constexpr std::array dwdp_rowvals_model_jakstat_adjoint_py_ = { + 0, 0, 0, 0, 0 +}; + +void dwdp_rowvals_model_jakstat_adjoint_py(SUNMatrixWrapper &dwdp){ + dwdp.set_indexvals(gsl::make_span(dwdp_rowvals_model_jakstat_adjoint_py_)); +} +} // namespace model_model_jakstat_adjoint_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "w.h" +#include "spl.h" +#include "sspl.h" +#include "dwdp.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void dwdp_model_jakstat_adjoint_py(realtype *dwdp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl, bool include_static){ + + // dynamic expressions + du_dsp1 = sspl_0_5; // dwdp[0] + du_dsp2 = sspl_0_6; // dwdp[1] + du_dsp3 = sspl_0_7; // dwdp[2] + du_dsp4 = sspl_0_8; // dwdp[3] + du_dsp5 = sspl_0_9; // dwdp[4] +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/dwdp.h b/models/model_jakstat_adjoint_py/dwdp.h new file mode 100644 index 0000000000..a307b86d1c --- /dev/null +++ b/models/model_jakstat_adjoint_py/dwdp.h @@ -0,0 +1,5 @@ +#define du_dsp1 dwdp[0] +#define du_dsp2 dwdp[1] +#define du_dsp3 dwdp[2] +#define du_dsp4 dwdp[3] +#define du_dsp5 dwdp[4] diff --git a/models/model_jakstat_adjoint_py/dxdotdp_explicit.cpp b/models/model_jakstat_adjoint_py/dxdotdp_explicit.cpp new file mode 100644 index 0000000000..7f7fd61360 --- /dev/null +++ b/models/model_jakstat_adjoint_py/dxdotdp_explicit.cpp @@ -0,0 +1,75 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +static constexpr std::array dxdotdp_explicit_colptrs_model_jakstat_adjoint_py_ = { + 0, 2, 4, 6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13 +}; + +void dxdotdp_explicit_colptrs_model_jakstat_adjoint_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexptrs(gsl::make_span(dxdotdp_explicit_colptrs_model_jakstat_adjoint_py_)); +} +} // namespace model_model_jakstat_adjoint_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +static constexpr std::array dxdotdp_explicit_rowvals_model_jakstat_adjoint_py_ = { + 0, 1, 1, 2, 2, 3, 0, 3, 4, 5, 6, 7, 8 +}; + +void dxdotdp_explicit_rowvals_model_jakstat_adjoint_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexvals(gsl::make_span(dxdotdp_explicit_rowvals_model_jakstat_adjoint_py_)); +} +} // namespace model_model_jakstat_adjoint_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "w.h" +#include "dxdotdp_explicit.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void dxdotdp_explicit_model_jakstat_adjoint_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + ddSTATdt_dp1 = -STAT*u; // dxdotdp_explicit[0] + ddpSTATdt_dp1 = STAT*u; // dxdotdp_explicit[1] + ddpSTATdt_dp2 = -2*std::pow(pSTAT, 2); // dxdotdp_explicit[2] + ddpSTAT_pSTATdt_dp2 = std::pow(pSTAT, 2); // dxdotdp_explicit[3] + ddpSTAT_pSTATdt_dp3 = -pSTAT_pSTAT; // dxdotdp_explicit[4] + ddnpSTAT_npSTATdt_dp3 = Omega_cyt*pSTAT_pSTAT/Omega_nuc; // dxdotdp_explicit[5] + ddSTATdt_dp4 = Omega_nuc*nSTAT5/Omega_cyt; // dxdotdp_explicit[6] + ddnpSTAT_npSTATdt_dp4 = -npSTAT_npSTAT; // dxdotdp_explicit[7] + ddnSTAT1dt_dp4 = -nSTAT1 + 2*npSTAT_npSTAT; // dxdotdp_explicit[8] + ddnSTAT2dt_dp4 = nSTAT1 - nSTAT2; // dxdotdp_explicit[9] + ddnSTAT3dt_dp4 = nSTAT2 - nSTAT3; // dxdotdp_explicit[10] + ddnSTAT4dt_dp4 = nSTAT3 - nSTAT4; // dxdotdp_explicit[11] + ddnSTAT5dt_dp4 = nSTAT4 - nSTAT5; // dxdotdp_explicit[12] +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/dxdotdp_explicit.h b/models/model_jakstat_adjoint_py/dxdotdp_explicit.h new file mode 100644 index 0000000000..76857273f2 --- /dev/null +++ b/models/model_jakstat_adjoint_py/dxdotdp_explicit.h @@ -0,0 +1,13 @@ +#define ddSTATdt_dp1 dxdotdp_explicit[0] +#define ddpSTATdt_dp1 dxdotdp_explicit[1] +#define ddpSTATdt_dp2 dxdotdp_explicit[2] +#define ddpSTAT_pSTATdt_dp2 dxdotdp_explicit[3] +#define ddpSTAT_pSTATdt_dp3 dxdotdp_explicit[4] +#define ddnpSTAT_npSTATdt_dp3 dxdotdp_explicit[5] +#define ddSTATdt_dp4 dxdotdp_explicit[6] +#define ddnpSTAT_npSTATdt_dp4 dxdotdp_explicit[7] +#define ddnSTAT1dt_dp4 dxdotdp_explicit[8] +#define ddnSTAT2dt_dp4 dxdotdp_explicit[9] +#define ddnSTAT3dt_dp4 dxdotdp_explicit[10] +#define ddnSTAT4dt_dp4 dxdotdp_explicit[11] +#define ddnSTAT5dt_dp4 dxdotdp_explicit[12] diff --git a/models/model_jakstat_adjoint_py/dxdotdw.cpp b/models/model_jakstat_adjoint_py/dxdotdw.cpp new file mode 100644 index 0000000000..08c37d9e44 --- /dev/null +++ b/models/model_jakstat_adjoint_py/dxdotdw.cpp @@ -0,0 +1,64 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +static constexpr std::array dxdotdw_colptrs_model_jakstat_adjoint_py_ = { + 0, 2, 2 +}; + +void dxdotdw_colptrs_model_jakstat_adjoint_py(SUNMatrixWrapper &dxdotdw){ + dxdotdw.set_indexptrs(gsl::make_span(dxdotdw_colptrs_model_jakstat_adjoint_py_)); +} +} // namespace model_model_jakstat_adjoint_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +static constexpr std::array dxdotdw_rowvals_model_jakstat_adjoint_py_ = { + 0, 1 +}; + +void dxdotdw_rowvals_model_jakstat_adjoint_py(SUNMatrixWrapper &dxdotdw){ + dxdotdw.set_indexvals(gsl::make_span(dxdotdw_rowvals_model_jakstat_adjoint_py_)); +} +} // namespace model_model_jakstat_adjoint_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "w.h" +#include "dxdotdw.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void dxdotdw_model_jakstat_adjoint_py(realtype *dxdotdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + ddSTATdt_du = -STAT*p1; // dxdotdw[0] + ddpSTATdt_du = STAT*p1; // dxdotdw[1] +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/dxdotdw.h b/models/model_jakstat_adjoint_py/dxdotdw.h new file mode 100644 index 0000000000..66c2966a31 --- /dev/null +++ b/models/model_jakstat_adjoint_py/dxdotdw.h @@ -0,0 +1,2 @@ +#define ddSTATdt_du dxdotdw[0] +#define ddpSTATdt_du dxdotdw[1] diff --git a/models/model_jakstat_adjoint_py/dxdotdx_explicit.cpp b/models/model_jakstat_adjoint_py/dxdotdx_explicit.cpp new file mode 100644 index 0000000000..6de84b996b --- /dev/null +++ b/models/model_jakstat_adjoint_py/dxdotdx_explicit.cpp @@ -0,0 +1,80 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +static constexpr std::array dxdotdx_explicit_colptrs_model_jakstat_adjoint_py_ = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 +}; + +void dxdotdx_explicit_colptrs_model_jakstat_adjoint_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexptrs(gsl::make_span(dxdotdx_explicit_colptrs_model_jakstat_adjoint_py_)); +} +} // namespace model_model_jakstat_adjoint_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +static constexpr std::array dxdotdx_explicit_rowvals_model_jakstat_adjoint_py_ = { + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 0, 8 +}; + +void dxdotdx_explicit_rowvals_model_jakstat_adjoint_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexvals(gsl::make_span(dxdotdx_explicit_rowvals_model_jakstat_adjoint_py_)); +} +} // namespace model_model_jakstat_adjoint_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "w.h" +#include "dxdotdx_explicit.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void dxdotdx_explicit_model_jakstat_adjoint_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + ddSTATdt_dSTAT = -p1*u; // dxdotdx_explicit[0] + ddpSTATdt_dSTAT = p1*u; // dxdotdx_explicit[1] + ddpSTATdt_dpSTAT = -4*p2*pSTAT; // dxdotdx_explicit[2] + ddpSTAT_pSTATdt_dpSTAT = 2*p2*pSTAT; // dxdotdx_explicit[3] + ddpSTAT_pSTATdt_dpSTAT_pSTAT = -p3; // dxdotdx_explicit[4] + ddnpSTAT_npSTATdt_dpSTAT_pSTAT = Omega_cyt*p3/Omega_nuc; // dxdotdx_explicit[5] + ddnpSTAT_npSTATdt_dnpSTAT_npSTAT = -p4; // dxdotdx_explicit[6] + ddnSTAT1dt_dnpSTAT_npSTAT = 2*p4; // dxdotdx_explicit[7] + ddnSTAT1dt_dnSTAT1 = -p4; // dxdotdx_explicit[8] + ddnSTAT2dt_dnSTAT1 = p4; // dxdotdx_explicit[9] + ddnSTAT2dt_dnSTAT2 = -p4; // dxdotdx_explicit[10] + ddnSTAT3dt_dnSTAT2 = p4; // dxdotdx_explicit[11] + ddnSTAT3dt_dnSTAT3 = -p4; // dxdotdx_explicit[12] + ddnSTAT4dt_dnSTAT3 = p4; // dxdotdx_explicit[13] + ddnSTAT4dt_dnSTAT4 = -p4; // dxdotdx_explicit[14] + ddnSTAT5dt_dnSTAT4 = p4; // dxdotdx_explicit[15] + ddSTATdt_dnSTAT5 = Omega_nuc*p4/Omega_cyt; // dxdotdx_explicit[16] + ddnSTAT5dt_dnSTAT5 = -p4; // dxdotdx_explicit[17] +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/dxdotdx_explicit.h b/models/model_jakstat_adjoint_py/dxdotdx_explicit.h new file mode 100644 index 0000000000..e6e5defe25 --- /dev/null +++ b/models/model_jakstat_adjoint_py/dxdotdx_explicit.h @@ -0,0 +1,18 @@ +#define ddSTATdt_dSTAT dxdotdx_explicit[0] +#define ddpSTATdt_dSTAT dxdotdx_explicit[1] +#define ddpSTATdt_dpSTAT dxdotdx_explicit[2] +#define ddpSTAT_pSTATdt_dpSTAT dxdotdx_explicit[3] +#define ddpSTAT_pSTATdt_dpSTAT_pSTAT dxdotdx_explicit[4] +#define ddnpSTAT_npSTATdt_dpSTAT_pSTAT dxdotdx_explicit[5] +#define ddnpSTAT_npSTATdt_dnpSTAT_npSTAT dxdotdx_explicit[6] +#define ddnSTAT1dt_dnpSTAT_npSTAT dxdotdx_explicit[7] +#define ddnSTAT1dt_dnSTAT1 dxdotdx_explicit[8] +#define ddnSTAT2dt_dnSTAT1 dxdotdx_explicit[9] +#define ddnSTAT2dt_dnSTAT2 dxdotdx_explicit[10] +#define ddnSTAT3dt_dnSTAT2 dxdotdx_explicit[11] +#define ddnSTAT3dt_dnSTAT3 dxdotdx_explicit[12] +#define ddnSTAT4dt_dnSTAT3 dxdotdx_explicit[13] +#define ddnSTAT4dt_dnSTAT4 dxdotdx_explicit[14] +#define ddnSTAT5dt_dnSTAT4 dxdotdx_explicit[15] +#define ddSTATdt_dnSTAT5 dxdotdx_explicit[16] +#define ddnSTAT5dt_dnSTAT5 dxdotdx_explicit[17] diff --git a/models/model_jakstat_adjoint_py/dydp.cpp b/models/model_jakstat_adjoint_py/dydp.cpp new file mode 100644 index 0000000000..20b8ab55a4 --- /dev/null +++ b/models/model_jakstat_adjoint_py/dydp.cpp @@ -0,0 +1,55 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "w.h" +#include "spl.h" +#include "sspl.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void dydp_model_jakstat_adjoint_py(realtype *dydp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl){ + switch(ip) { + case 4: + dydp[0] = -scale_pSTAT*(pSTAT + 2*pSTAT_pSTAT)/std::pow(init_STAT, 2); + dydp[1] = -scale_tSTAT*(STAT + pSTAT + 2*pSTAT_pSTAT)/std::pow(init_STAT, 2); + break; + case 5: + dydp[2] = sspl_0_5; + break; + case 6: + dydp[2] = sspl_0_6; + break; + case 7: + dydp[2] = sspl_0_7; + break; + case 8: + dydp[2] = sspl_0_8; + break; + case 9: + dydp[2] = sspl_0_9; + break; + case 10: + dydp[1] = 1; + break; + case 11: + dydp[0] = 1; + break; + case 12: + dydp[1] = (STAT + pSTAT + 2*pSTAT_pSTAT)/init_STAT; + break; + case 13: + dydp[0] = (pSTAT + 2*pSTAT_pSTAT)/init_STAT; + break; + } +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/dydx.cpp b/models/model_jakstat_adjoint_py/dydx.cpp new file mode 100644 index 0000000000..2c610803b6 --- /dev/null +++ b/models/model_jakstat_adjoint_py/dydx.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "w.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void dydx_model_jakstat_adjoint_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx){ + dydx[1] = scale_tSTAT/init_STAT; + dydx[3] = scale_pSTAT/init_STAT; + dydx[4] = scale_tSTAT/init_STAT; + dydx[6] = 2*scale_pSTAT/init_STAT; + dydx[7] = 2*scale_tSTAT/init_STAT; +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/k.h b/models/model_jakstat_adjoint_py/k.h new file mode 100644 index 0000000000..b37b70b07c --- /dev/null +++ b/models/model_jakstat_adjoint_py/k.h @@ -0,0 +1,2 @@ +#define Omega_cyt k[0] +#define Omega_nuc k[1] diff --git a/models/model_jakstat_adjoint_py/main.cpp b/models/model_jakstat_adjoint_py/main.cpp new file mode 100644 index 0000000000..ecdff85a46 --- /dev/null +++ b/models/model_jakstat_adjoint_py/main.cpp @@ -0,0 +1,93 @@ +#include + +#include "wrapfunctions.h" /* model-provided functions */ +#include /* AMICI base functions */ + +template +std::ostream& operator<<(std::ostream& os, std::vector const& v) { + os << "["; + for (typename std::vector::const_iterator ii = v.begin(); ii != v.end(); + ++ii) { + os << " " << *ii; + } + os << "]"; + return os; +} + +/* + * This is a scaffold for a stand-alone AMICI simulation executable + * demonstrating the basic use of the AMICI C++ API. + */ + +int main() { + std::cout << "********************************" << std::endl; + std::cout << "** Running forward simulation **" << std::endl; + std::cout << "********************************" << std::endl << std::endl; + + // Create a model instance + auto model = amici::generic_model::getModel(); + + // Set desired output timepoints + model->setTimepoints({0.0, 1.0, 10.0, 100.0, 1000.0}); + + // Create a solver instance + auto solver = model->getSolver(); + + // Optionally set integration tolerance + solver->setAbsoluteTolerance(1e-16); + solver->setRelativeTolerance(1e-8); + + // Run the simulation using default parameters set during model import + // (can be changed using model->setParameters() or model->setParameterBy*()) + auto rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print observable time course + auto observable_ids = model->getObservableIds(); + std::cout << "Simulated observables for timepoints " << rdata->ts << "\n\n"; + for (int i_observable = 0; i_observable < rdata->ny; ++i_observable) { + std::cout << observable_ids[i_observable] << ":\n\t"; + for (int i_time = 0; i_time < rdata->nt; ++i_time) { + // rdata->y is a flat 2D array in row-major ordering + std::cout << rdata->y[i_time * rdata->ny + i_observable] << " "; + } + std::cout << std::endl << std::endl; + } + + std::cout << std::endl; + std::cout << "**********************************" << std::endl; + std::cout << "** Forward sensitivity analysis **" << std::endl; + std::cout << "**********************************" << std::endl << std::endl; + + // Enable first-order sensitivity analysis + solver->setSensitivityOrder(amici::SensitivityOrder::first); + // Use forward sensitivities + solver->setSensitivityMethod(amici::SensitivityMethod::forward); + + // Run the simulation + rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print state sensitivities sx... + // ... for the first timepoint... + int i_time = 0; + // ... with respect to the first parameter + int i_nplist = 0; + + // get identifiers from model + auto state_ids = model->getStateIds(); + auto parameter_ids = model->getParameterIds(); + + std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] + << std::endl; // nt x nplist x nx + for (int i_state = 0; i_state < rdata->nx; ++i_state) { + std::cout << "\td(" << state_ids[i_state] << ")/d(" + << parameter_ids[model->plist(i_nplist)] << ") = "; + + // rdata->sx is a flat 3D array in row-major ordering + std::cout << rdata->sx + [i_time * rdata->nplist * rdata->nx + + i_nplist * rdata->nx + i_state]; + std::cout << std::endl; + } + + return 0; +} diff --git a/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.cpp b/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.cpp new file mode 100644 index 0000000000..e31e5cd7ec --- /dev/null +++ b/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.cpp @@ -0,0 +1,120 @@ +#include +#include + +namespace amici { + +namespace model_model_jakstat_adjoint_py { + +// clang-format off + +std::array parameterNames = { + "p1", // p[0] +"p2", // p[1] +"p3", // p[2] +"p4", // p[3] +"init_STAT", // p[4] +"sp1", // p[5] +"sp2", // p[6] +"sp3", // p[7] +"sp4", // p[8] +"sp5", // p[9] +"offset_tSTAT", // p[10] +"offset_pSTAT", // p[11] +"scale_tSTAT", // p[12] +"scale_pSTAT", // p[13] +"sigma_pSTAT", // p[14] +"sigma_tSTAT", // p[15] +"sigma_pEpoR", // p[16] +}; + +std::array fixedParameterNames = { + "Omega_cyt", // k[0] +"Omega_nuc", // k[1] +}; + +std::array stateNames = { + "STAT", // x_rdata[0] +"pSTAT", // x_rdata[1] +"pSTAT_pSTAT", // x_rdata[2] +"npSTAT_npSTAT", // x_rdata[3] +"nSTAT1", // x_rdata[4] +"nSTAT2", // x_rdata[5] +"nSTAT3", // x_rdata[6] +"nSTAT4", // x_rdata[7] +"nSTAT5", // x_rdata[8] +}; + +std::array observableNames = { + "y0", // y[0] +"y1", // y[1] +"y2", // y[2] +}; + +std::array observableScalings = { + ObservableScaling::lin, // y[0] +ObservableScaling::lin, // y[1] +ObservableScaling::lin, // y[2] +}; + +std::array expressionNames = { + "u", // w[0] +"flux_r0", // w[1] +}; + +std::array parameterIds = { + "p1", // p[0] +"p2", // p[1] +"p3", // p[2] +"p4", // p[3] +"init_STAT", // p[4] +"sp1", // p[5] +"sp2", // p[6] +"sp3", // p[7] +"sp4", // p[8] +"sp5", // p[9] +"offset_tSTAT", // p[10] +"offset_pSTAT", // p[11] +"scale_tSTAT", // p[12] +"scale_pSTAT", // p[13] +"sigma_pSTAT", // p[14] +"sigma_tSTAT", // p[15] +"sigma_pEpoR", // p[16] +}; + +std::array fixedParameterIds = { + "Omega_cyt", // k[0] +"Omega_nuc", // k[1] +}; + +std::array stateIds = { + "STAT", // x_rdata[0] +"pSTAT", // x_rdata[1] +"pSTAT_pSTAT", // x_rdata[2] +"npSTAT_npSTAT", // x_rdata[3] +"nSTAT1", // x_rdata[4] +"nSTAT2", // x_rdata[5] +"nSTAT3", // x_rdata[6] +"nSTAT4", // x_rdata[7] +"nSTAT5", // x_rdata[8] +}; + +std::array observableIds = { + "obs_pSTAT", // y[0] +"obs_tSTAT", // y[1] +"obs_spline", // y[2] +}; + +std::array expressionIds = { + "u", // w[0] +"flux_r0", // w[1] +}; + +std::array stateIdxsSolver = { + 0, 1, 2, 3, 4, 5, 6, 7, 8 +}; + +// clang-format on + +} // namespace model_model_jakstat_adjoint_py + +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h b/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h new file mode 100644 index 0000000000..c023f4e367 --- /dev/null +++ b/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h @@ -0,0 +1,571 @@ +#ifndef _amici_TPL_MODELNAME_h +#define _amici_TPL_MODELNAME_h +#include +#include +#include + +#include "amici/model_ode.h" +#include "amici/splinefunctions.h" +#include "amici/event.h" + +namespace amici { + +class Solver; + +namespace model_model_jakstat_adjoint_py { + +extern std::array parameterNames; +extern std::array fixedParameterNames; +extern std::array stateNames; +extern std::array observableNames; +extern std::array observableScalings; +extern std::array expressionNames; +extern std::array parameterIds; +extern std::array fixedParameterIds; +extern std::array stateIds; +extern std::array observableIds; +extern std::array expressionIds; +extern std::array stateIdxsSolver; + +extern void Jy_model_jakstat_adjoint_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydsigma_model_jakstat_adjoint_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_model_jakstat_adjoint_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_colptrs_model_jakstat_adjoint_py(SUNMatrixWrapper &colptrs, int index); +extern void dJydy_rowvals_model_jakstat_adjoint_py(SUNMatrixWrapper &rowvals, int index); + + + + + + + +extern void dwdp_model_jakstat_adjoint_py(realtype *dwdp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl, bool include_static); +extern void dwdp_colptrs_model_jakstat_adjoint_py(SUNMatrixWrapper &colptrs); +extern void dwdp_rowvals_model_jakstat_adjoint_py(SUNMatrixWrapper &rowvals); + + + + + + +extern void dxdotdw_model_jakstat_adjoint_py(realtype *dxdotdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void dxdotdw_colptrs_model_jakstat_adjoint_py(SUNMatrixWrapper &colptrs); +extern void dxdotdw_rowvals_model_jakstat_adjoint_py(SUNMatrixWrapper &rowvals); +extern void dxdotdp_explicit_model_jakstat_adjoint_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void dxdotdp_explicit_colptrs_model_jakstat_adjoint_py(SUNMatrixWrapper &colptrs); +extern void dxdotdp_explicit_rowvals_model_jakstat_adjoint_py(SUNMatrixWrapper &rowvals); +extern void dxdotdx_explicit_model_jakstat_adjoint_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void dxdotdx_explicit_colptrs_model_jakstat_adjoint_py(SUNMatrixWrapper &colptrs); +extern void dxdotdx_explicit_rowvals_model_jakstat_adjoint_py(SUNMatrixWrapper &rowvals); +extern void dydx_model_jakstat_adjoint_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx); +extern void dydp_model_jakstat_adjoint_py(realtype *dydp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl); + + + + +extern void sigmay_model_jakstat_adjoint_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y); + +extern void dsigmaydp_model_jakstat_adjoint_py(realtype *dsigmaydp, const realtype t, const realtype *p, const realtype *k, const realtype *y, const int ip); + + +extern void w_model_jakstat_adjoint_py(realtype *w, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl, const realtype *spl, bool include_static); +extern void x0_model_jakstat_adjoint_py(realtype *x0, const realtype t, const realtype *p, const realtype *k); + + + +extern void xdot_model_jakstat_adjoint_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void y_model_jakstat_adjoint_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); + + + + + + + + +extern void x_solver_model_jakstat_adjoint_py(realtype *x_solver, const realtype *x_rdata); + + + + + + + + + + + + +extern std::vector create_splines_model_jakstat_adjoint_py(const realtype *p, const realtype *k); +extern void dspline_valuesdp_model_jakstat_adjoint_py(realtype *dspline_valuesdp, const realtype *p, const realtype *k, const int ip); + + +/** + * @brief AMICI-generated model subclass. + */ +class Model_model_jakstat_adjoint_py : public amici::Model_ODE { + public: + /** + * @brief Default constructor. + */ + Model_model_jakstat_adjoint_py() + : amici::Model_ODE( + amici::ModelDimensions( + 9, // nx_rdata + 9, // nxtrue_rdata + 9, // nx_solver + 9, // nxtrue_solver + 0, // nx_solver_reinit + 17, // np + 2, // nk + 3, // ny + 3, // nytrue + 0, // nz + 0, // nztrue + 0, // nevent + 0, // nevent_solver + 1, // nspl + 1, // nobjective + 2, // nw + 0, // ndwdx + 5, // ndwdp + 0, // ndwdw + 2, // ndxdotdw + std::vector{1, 1, 1}, // ndjydy + 0, // ndxrdatadxsolver + 0, // ndxrdatadtcl + 0, // ndtotal_cldx_rdata + 0, // nnz + 9, // ubw + 9, // lbw + true, // pythonGenerated + 13, // ndxdotdp_explicit + 18, // ndxdotdx_explicit + 0 // w_recursion_depth + ), + amici::SimulationParameters( + std::vector{1.3999999999999999, 0.45000000000000001}, // fixedParameters + std::vector{3.9810717055349727, 1000.0, 0.11220184543019635, 0.98287887300003218, 1.0, 0.0015848931924611134, 0.54954087385762451, 0.84139514164519513, 0.38904514499428061, 9.9999999999999991e-6, 0.18197008586099833, 0.22908676527677729, 0.77624711662869172, 1.0641430182243161, 0.31622776601683794, 1.0, 0.31622776601683794} // dynamic parameters + ), + amici::SecondOrderMode::none, // o2mode + std::vector{1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}, // idlist + std::vector{}, // z2events + std::vector{}, // events + {} // state-independent events + ) { + } + + /** + * @brief Clone this model instance. + * @return A deep copy of this instance. + */ + amici::Model *clone() const override { + return new Model_model_jakstat_adjoint_py(*this); + } + + void fJrz(realtype *Jrz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fJy(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + Jy_model_jakstat_adjoint_py(Jy, iy, p, k, y, sigmay, my); + } + + + void fJz(realtype *Jz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override {} + + + void fdJrzdsigma(realtype *dJrzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fdJrzdz(realtype *dJrzdz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fdJydsigma(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydsigma_model_jakstat_adjoint_py(dJydsigma, iy, p, k, y, sigmay, my); + } + + + void fdJzdsigma(realtype *dJzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override {} + + + void fdJzdz(realtype *dJzdz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const double *mz) override {} + + + void fdeltax(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old) override {} + + + void fdeltasx(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old) override {} + + + void fdeltaxB(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl) override {} + + + void fdeltaqB(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB) override {} + + + void fdrzdp(realtype *drzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdrzdx(realtype *drzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void fdsigmaydp(realtype *dsigmaydp, const realtype t, const realtype *p, const realtype *k, const realtype *y, const int ip) override { + dsigmaydp_model_jakstat_adjoint_py(dsigmaydp, t, p, k, y, ip); + } + + + void fdsigmaydy(realtype *dsigmaydy, const realtype t, const realtype *p, const realtype *k, const realtype *y) override {} + + + void fdsigmazdp(realtype *dsigmazdp, const realtype t, const realtype *p, const realtype *k, const int ip) override {} + + + void fdJydy(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydy_model_jakstat_adjoint_py(dJydy, iy, p, k, y, sigmay, my); + } + + void fdJydy_colptrs(SUNMatrixWrapper &colptrs, int index) override { + dJydy_colptrs_model_jakstat_adjoint_py(colptrs, index); + } + + void fdJydy_rowvals(SUNMatrixWrapper &rowvals, int index) override { + dJydy_rowvals_model_jakstat_adjoint_py(rowvals, index); + } + + + std::vector fcreate_splines(const realtype *p, const realtype *k) override { + return create_splines_model_jakstat_adjoint_py(p, k); + } + + void fdspline_valuesdp(realtype *dspline_valuesdp, const realtype *p, const realtype *k, const int ip) override { + dspline_valuesdp_model_jakstat_adjoint_py(dspline_valuesdp, p, k, ip); + } + + void fdspline_slopesdp(realtype *dspline_slopesdp, const realtype *p, const realtype *k, const int ip) override {} + + + void fdwdp(realtype *dwdp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl, bool include_static) override { + dwdp_model_jakstat_adjoint_py(dwdp, t, x, p, k, h, w, tcl, dtcldp, spl, sspl, include_static); + } + + void fdwdp_colptrs(SUNMatrixWrapper &colptrs) override { + dwdp_colptrs_model_jakstat_adjoint_py(colptrs); + } + + void fdwdp_rowvals(SUNMatrixWrapper &rowvals) override { + dwdp_rowvals_model_jakstat_adjoint_py(rowvals); + } + + + void fdwdx(realtype *dwdx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *spl, bool include_static) override {} + + void fdwdx_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdx_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdw(realtype *dwdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, bool include_static) override {} + + void fdwdw_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdw_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdw(realtype *dxdotdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + dxdotdw_model_jakstat_adjoint_py(dxdotdw, t, x, p, k, h, w); + } + + void fdxdotdw_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdw_colptrs_model_jakstat_adjoint_py(colptrs); + } + + void fdxdotdw_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdw_rowvals_model_jakstat_adjoint_py(rowvals); + } + + + void fdxdotdp_explicit(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + dxdotdp_explicit_model_jakstat_adjoint_py(dxdotdp_explicit, t, x, p, k, h, w); + } + + void fdxdotdp_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdp_explicit_colptrs_model_jakstat_adjoint_py(colptrs); + } + + void fdxdotdp_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdp_explicit_rowvals_model_jakstat_adjoint_py(rowvals); + } + + + void fdxdotdx_explicit(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + dxdotdx_explicit_model_jakstat_adjoint_py(dxdotdx_explicit, t, x, p, k, h, w); + } + + void fdxdotdx_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdx_explicit_colptrs_model_jakstat_adjoint_py(colptrs); + } + + void fdxdotdx_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdx_explicit_rowvals_model_jakstat_adjoint_py(rowvals); + } + + + void fdydx(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { + dydx_model_jakstat_adjoint_py(dydx, t, x, p, k, h, w, dwdx); + } + + + void fdydp(realtype *dydp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl) override { + dydp_model_jakstat_adjoint_py(dydp, t, x, p, k, h, ip, w, tcl, dtcldp, spl, sspl); + } + + + void fdzdp(realtype *dzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdzdx(realtype *dzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void froot(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl) override {} + + + void frz(realtype *rz, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void fsigmay(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y) override { + sigmay_model_jakstat_adjoint_py(sigmay, t, p, k, y); + } + + + void fsigmaz(realtype *sigmaz, const realtype t, const realtype *p, const realtype *k) override {} + + + void fstau(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie) override {} + + void fsx0(realtype *sx0, const realtype t, const realtype *x, const realtype *p, const realtype *k, const int ip) override {} + + void fsx0_fixedParameters(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs) override {} + + + void fw(realtype *w, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl, const realtype *spl, bool include_static) override { + w_model_jakstat_adjoint_py(w, t, x, p, k, h, tcl, spl, include_static); + } + + + void fx0(realtype *x0, const realtype t, const realtype *p, const realtype *k) override { + x0_model_jakstat_adjoint_py(x0, t, p, k); + } + + + void fx0_fixedParameters(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs) override {} + + + void fxdot(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + xdot_model_jakstat_adjoint_py(xdot, t, x, p, k, h, w); + } + + + void fy(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + y_model_jakstat_adjoint_py(y, t, x, p, k, h, w); + } + + + void fz(realtype *z, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + + + void fx_solver(realtype *x_solver, const realtype *x_rdata) override { + x_solver_model_jakstat_adjoint_py(x_solver, x_rdata); + } + + + void ftotal_cl(realtype *total_cl, const realtype *x_rdata, const realtype *p, const realtype *k) override {} + + + void fdx_rdatadx_solver(realtype *dx_rdatadx_solver, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadx_solver_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadx_solver_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdx_rdatadp(realtype *dx_rdatadp, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k, const int ip) override {} + + + void fdx_rdatadtcl(realtype *dx_rdatadtcl, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadtcl_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadtcl_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdtotal_cldp(realtype *dtotal_cldp, const realtype *x_rdata, const realtype *p, const realtype *k, const int ip) override {} + + + void fdtotal_cldx_rdata(realtype *dtotal_cldx_rdata, const realtype *x_rdata, const realtype *p, const realtype *k, const realtype *tcl) override {} + + void fdtotal_cldx_rdata_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdtotal_cldx_rdata_rowvals(SUNMatrixWrapper &rowvals) override {} + + + std::string getName() const override { + return "model_jakstat_adjoint_py"; + } + + /** + * @brief Get names of the model parameters + * @return the names + */ + std::vector getParameterNames() const override { + return std::vector(parameterNames.begin(), + parameterNames.end()); + } + + /** + * @brief Get names of the model states + * @return the names + */ + std::vector getStateNames() const override { + return std::vector(stateNames.begin(), stateNames.end()); + } + + /** + * @brief Get names of the solver states + * @return the names + */ + std::vector getStateNamesSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto const idx: stateIdxsSolver) { + result.push_back(stateNames[idx]); + } + return result; + } + + /** + * @brief Get names of the fixed model parameters + * @return the names + */ + std::vector getFixedParameterNames() const override { + return std::vector(fixedParameterNames.begin(), + fixedParameterNames.end()); + } + + /** + * @brief Get names of the observables + * @return the names + */ + std::vector getObservableNames() const override { + return std::vector(observableNames.begin(), + observableNames.end()); + } + + /** + * @brief Get names of model expressions + * @return Expression names + */ + std::vector getExpressionNames() const override { + return std::vector(expressionNames.begin(), + expressionNames.end()); + } + + /** + * @brief Get ids of the model parameters + * @return the ids + */ + std::vector getParameterIds() const override { + return std::vector(parameterIds.begin(), + parameterIds.end()); + } + + /** + * @brief Get ids of the model states + * @return the ids + */ + std::vector getStateIds() const override { + return std::vector(stateIds.begin(), stateIds.end()); + } + + /** + * @brief Get ids of the solver states + * @return the ids + */ + std::vector getStateIdsSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto idx: stateIdxsSolver) { + result.push_back(stateIds[idx]); + } + return result; + } + + /** + * @brief Get ids of the fixed model parameters + * @return the ids + */ + std::vector getFixedParameterIds() const override { + return std::vector(fixedParameterIds.begin(), + fixedParameterIds.end()); + } + + /** + * @brief Get ids of the observables + * @return the ids + */ + std::vector getObservableIds() const override { + return std::vector(observableIds.begin(), + observableIds.end()); + } + + /** + * @brief Get IDs of model expressions + * @return Expression IDs + */ + std::vector getExpressionIds() const override { + return std::vector(expressionIds.begin(), + expressionIds.end()); + } + + /** + * @brief function indicating whether reinitialization of states depending + * on fixed parameters is permissible + * @return flag indicating whether reinitialization of states depending on + * fixed parameters is permissible + */ + bool isFixedParameterStateReinitializationAllowed() const override { + return true; + } + + /** + * @brief returns the AMICI version that was used to generate the model + * @return AMICI version string + */ + std::string getAmiciVersion() const override { + return "0.33.0"; + } + + /** + * @brief returns the amici version that was used to generate the model + * @return AMICI git commit hash + */ + std::string getAmiciCommit() const override { + return "bcedb951ddf674996b269489d74f9b86112038ff"; + } + + bool hasQuadraticLLH() const override { + return true; + } + + ObservableScaling getObservableScaling(int iy) const override { + return observableScalings.at(iy); + } +}; + + +} // namespace model_model_jakstat_adjoint_py + +} // namespace amici + +#endif /* _amici_TPL_MODELNAME_h */ diff --git a/models/model_jakstat_adjoint_py/my.h b/models/model_jakstat_adjoint_py/my.h new file mode 100644 index 0000000000..4bffdb10f0 --- /dev/null +++ b/models/model_jakstat_adjoint_py/my.h @@ -0,0 +1,3 @@ +#define mobs_pSTAT my[0] +#define mobs_tSTAT my[1] +#define mobs_spline my[2] diff --git a/models/model_jakstat_adjoint_py/p.h b/models/model_jakstat_adjoint_py/p.h new file mode 100644 index 0000000000..5d04c77321 --- /dev/null +++ b/models/model_jakstat_adjoint_py/p.h @@ -0,0 +1,17 @@ +#define p1 p[0] +#define p2 p[1] +#define p3 p[2] +#define p4 p[3] +#define init_STAT p[4] +#define sp1 p[5] +#define sp2 p[6] +#define sp3 p[7] +#define sp4 p[8] +#define sp5 p[9] +#define offset_tSTAT p[10] +#define offset_pSTAT p[11] +#define scale_tSTAT p[12] +#define scale_pSTAT p[13] +#define sigma_pSTAT p[14] +#define sigma_tSTAT p[15] +#define sigma_pEpoR p[16] diff --git a/models/model_jakstat_adjoint_py/setup.py b/models/model_jakstat_adjoint_py/setup.py new file mode 100644 index 0000000000..767a3dfe88 --- /dev/null +++ b/models/model_jakstat_adjoint_py/setup.py @@ -0,0 +1,95 @@ +"""AMICI model package setup""" + +import os +import sys +from pathlib import Path + +from amici import _get_amici_path +from amici.custom_commands import AmiciBuildCMakeExtension +from cmake_build_extension import CMakeExtension +from setuptools import find_namespace_packages, setup +import importlib.metadata + + +def get_extension() -> CMakeExtension: + """Get setuptools extension object for this AMICI model package""" + + # Build shared object + prefix_path = Path(_get_amici_path()) + AmiciBuildCMakeExtension.extend_cmake_prefix_path(str(prefix_path)) + + # handle parallel building + # Note: can be empty to use all hardware threads + if (parallel_jobs := os.environ.get("AMICI_PARALLEL_COMPILE")) is not None: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = parallel_jobs + else: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = "1" + + debug_build = os.getenv("ENABLE_AMICI_DEBUGGING", "").lower() in [ + "1", + "true", + ] or os.getenv("ENABLE_GCOV_COVERAGE", "").lower() in ["1", "true"] + + cmake_prefix_path = os.getenv("CMAKE_PREFIX_PATH", "").split(os.pathsep) + cmake_prefix_path.append(prefix_path.as_posix()) + + # If scipy_openblas64 is installed, we make its cmake configuration + # available + amici_distribution = importlib.metadata.distribution("amici") + amici_dir = Path(amici_distribution.locate_file("")) + # this path is created during the amici build if scipy_openblas64 is used + openblas_cmake_dir = amici_dir / "lib" / "cmake" / "openblas" + if openblas_cmake_dir.exists(): + cmake_prefix_path.append(str(openblas_cmake_dir)) + + return CMakeExtension( + name="model_ext", + source_dir=os.getcwd(), + install_prefix="model_jakstat_adjoint_py", + cmake_configure_options=[ + "-DCMAKE_VERBOSE_MAKEFILE=ON", + f"-DCMAKE_PREFIX_PATH='{';'.join(cmake_prefix_path)}'", + "-DAMICI_PYTHON_BUILD_EXT_ONLY=ON", + f"-DPython3_EXECUTABLE={Path(sys.executable).as_posix()}", + ], + cmake_build_type="Debug" if debug_build else "Release", + ) + + +# Change working directory to setup.py location +os.chdir(os.path.dirname(os.path.abspath(__file__))) + +MODEL_EXT = get_extension() + +CLASSIFIERS = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Science/Research", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python", + "Programming Language :: C++", + "Topic :: Scientific/Engineering :: Bio-Informatics", +] + +CMDCLASS = { + # for CMake-based builds + "build_ext": AmiciBuildCMakeExtension, +} + +# Install +setup( + name="model_jakstat_adjoint_py", + cmdclass=CMDCLASS, + version="0.1.0", + description="AMICI-generated module for model model_jakstat_adjoint_py", + url="https://github.com/AMICI-dev/AMICI", + author="model-author-todo", + author_email="model-author-todo", + ext_modules=[MODEL_EXT], + packages=find_namespace_packages(), + install_requires=["amici==0.33.0"], + python_requires=">=3.11", + package_data={}, + zip_safe=False, + classifiers=CLASSIFIERS, +) diff --git a/models/model_jakstat_adjoint_py/sigmay.cpp b/models/model_jakstat_adjoint_py/sigmay.cpp new file mode 100644 index 0000000000..65538128a1 --- /dev/null +++ b/models/model_jakstat_adjoint_py/sigmay.cpp @@ -0,0 +1,23 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void sigmay_model_jakstat_adjoint_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y){ + sigma_obs_pSTAT = sigma_pSTAT; // sigmay[0] + sigma_obs_tSTAT = sigma_tSTAT; // sigmay[1] + sigma_obs_spline = sigma_pEpoR; // sigmay[2] +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/sigmay.h b/models/model_jakstat_adjoint_py/sigmay.h new file mode 100644 index 0000000000..df21677084 --- /dev/null +++ b/models/model_jakstat_adjoint_py/sigmay.h @@ -0,0 +1,3 @@ +#define sigma_obs_pSTAT sigmay[0] +#define sigma_obs_tSTAT sigmay[1] +#define sigma_obs_spline sigmay[2] diff --git a/models/model_jakstat_adjoint_py/spl.h b/models/model_jakstat_adjoint_py/spl.h new file mode 100644 index 0000000000..d0c3ccd47e --- /dev/null +++ b/models/model_jakstat_adjoint_py/spl.h @@ -0,0 +1 @@ +#define spl_0 spl[0] diff --git a/models/model_jakstat_adjoint_py/sspl.h b/models/model_jakstat_adjoint_py/sspl.h new file mode 100644 index 0000000000..582b50374c --- /dev/null +++ b/models/model_jakstat_adjoint_py/sspl.h @@ -0,0 +1,17 @@ +#define sspl_0_0 sspl[0] +#define sspl_0_1 sspl[1] +#define sspl_0_2 sspl[2] +#define sspl_0_3 sspl[3] +#define sspl_0_4 sspl[4] +#define sspl_0_5 sspl[5] +#define sspl_0_6 sspl[6] +#define sspl_0_7 sspl[7] +#define sspl_0_8 sspl[8] +#define sspl_0_9 sspl[9] +#define sspl_0_10 sspl[10] +#define sspl_0_11 sspl[11] +#define sspl_0_12 sspl[12] +#define sspl_0_13 sspl[13] +#define sspl_0_14 sspl[14] +#define sspl_0_15 sspl[15] +#define sspl_0_16 sspl[16] diff --git a/models/model_jakstat_adjoint_py/swig/CMakeLists.txt b/models/model_jakstat_adjoint_py/swig/CMakeLists.txt new file mode 100644 index 0000000000..314996c479 --- /dev/null +++ b/models/model_jakstat_adjoint_py/swig/CMakeLists.txt @@ -0,0 +1,60 @@ +if(DEFINED ENV{SWIG}) + set(SWIG_EXECUTABLE $ENV{SWIG}) +endif() + +find_package(SWIG REQUIRED) +include(${SWIG_USE_FILE}) + +if(DEFINED ENV{PYTHON_EXECUTABLE}) + set(Python3_EXECUTABLE $ENV{PYTHON_EXECUTABLE}) +endif() +# We don't need "Interpreter" here, but without that, FindPython3 will +# ignore the Python version selected via $Python3_EXECUTABLE +find_package(Python3 COMPONENTS Interpreter Development) +include_directories(${Python3_INCLUDE_DIRS}) + +set(SWIG_LIBRARY_NAME _${PROJECT_NAME}) +set(CMAKE_SWIG_FLAGS "") +set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) + +# swig does not use INTERFACE_INCLUDE_DIRS of linked libraries, so add manually +get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) +include_directories(${AMICI_INCLUDE_DIRS} .. ${AMICI_INCLUDE_DIRS}/../swig) + +swig_add_library(${SWIG_LIBRARY_NAME} + TYPE MODULE + LANGUAGE python + SOURCES ${PROJECT_NAME}.i) + + +set_target_properties(${SWIG_LIBRARY_NAME} + PROPERTIES + SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE + PREFIX "" +) + +# Python extension suffix +execute_process( + COMMAND ${Python3_EXECUTABLE} -c + "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))" + OUTPUT_VARIABLE PY_EXT_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE) +if(NOT "${PY_EXT_SUFFIX}" STREQUAL "") + message(STATUS "Python extension suffix is ${PY_EXT_SUFFIX}") + set_target_properties(${SWIG_LIBRARY_NAME} PROPERTIES SUFFIX "${PY_EXT_SUFFIX}" ) +endif() + + +swig_link_libraries(${SWIG_LIBRARY_NAME} + ${Python3_LIBRARIES} + model) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.py + $ DESTINATION .) + +# configure module setup script +set(SETUP_PY_IN ${Amici_DIR}/model_setup.template.py) +set(SETUP_PY_OUT ${CMAKE_CURRENT_BINARY_DIR}/setup.py) + +add_custom_target(install-python + DEPENDS ${SWIG_LIBRARY_NAME} + COMMAND python ${SETUP_PY_OUT} install) diff --git a/models/model_jakstat_adjoint_py/swig/model_jakstat_adjoint_py.i b/models/model_jakstat_adjoint_py/swig/model_jakstat_adjoint_py.i new file mode 100644 index 0000000000..57b2bc3c92 --- /dev/null +++ b/models/model_jakstat_adjoint_py/swig/model_jakstat_adjoint_py.i @@ -0,0 +1,82 @@ +%define MODULEIMPORT +" +import amici +import datetime +import importlib.util +import os +import sysconfig +from pathlib import Path + +ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +_model_jakstat_adjoint_py = amici._module_from_path( + 'model_jakstat_adjoint_py._model_jakstat_adjoint_py' if __package__ or '.' in __name__ + else '_model_jakstat_adjoint_py', + Path(__file__).parent / f'_model_jakstat_adjoint_py{ext_suffix}', +) + +def _get_import_time(): + return _model_jakstat_adjoint_py._get_import_time() + +t_imported = _get_import_time() +t_modified = os.path.getmtime(__file__) +if t_imported < t_modified: + t_imp_str = datetime.datetime.fromtimestamp(t_imported).isoformat() + t_mod_str = datetime.datetime.fromtimestamp(t_modified).isoformat() + module_path = Path(__file__).resolve() + raise RuntimeError( + f'Cannot import extension for model_jakstat_adjoint_py from ' + f'{module_path}, because an extension in the same location ' + f'has already been imported, but the file was modified on ' + f'disk. \\nImported at {t_imp_str}\\nModified at {t_mod_str}.\\n' + 'Import the module with a different name or restart the ' + 'Python kernel.' + ) +" +%enddef + +%module(package="model_jakstat_adjoint_py",moduleimport=MODULEIMPORT) model_jakstat_adjoint_py + +%pythoncode %{ +# the model-package __init__.py module (will be set during import) +_model_module = None + + +%} + +%import amici.i +// Add necessary symbols to generated header + +%{ +#include "wrapfunctions.h" +#include "amici/model_ode.h" +#include "amici/model_dae.h" +using namespace amici; +%} + +// store the time a module was imported +%{ +#include +static std::chrono::time_point _module_import_time; + +static double _get_import_time() { + auto epoch = _module_import_time.time_since_epoch(); + return std::chrono::duration(epoch).count(); +} +%} + +static double _get_import_time(); + +%init %{ + _module_import_time = std::chrono::system_clock::now(); +%} + + +// Make model module accessible from the model +%feature("pythonappend") amici::generic_model::getModel %{ + if '.' in __name__: + val.module = _model_module +%} + + +// Process symbols in header +%include "wrapfunctions.h" diff --git a/models/model_jakstat_adjoint_py/w.cpp b/models/model_jakstat_adjoint_py/w.cpp new file mode 100644 index 0000000000..22f33c8964 --- /dev/null +++ b/models/model_jakstat_adjoint_py/w.cpp @@ -0,0 +1,24 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "spl.h" +#include "w.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void w_model_jakstat_adjoint_py(realtype *w, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl, const realtype *spl, bool include_static){ + + // dynamic expressions + u = spl_0; // w[0] +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/w.h b/models/model_jakstat_adjoint_py/w.h new file mode 100644 index 0000000000..c3be8d685c --- /dev/null +++ b/models/model_jakstat_adjoint_py/w.h @@ -0,0 +1,2 @@ +#define u w[0] +#define flux_r0 w[1] diff --git a/models/model_jakstat_adjoint_py/wrapfunctions.cpp b/models/model_jakstat_adjoint_py/wrapfunctions.cpp new file mode 100644 index 0000000000..ad3eb038f6 --- /dev/null +++ b/models/model_jakstat_adjoint_py/wrapfunctions.cpp @@ -0,0 +1,16 @@ +#include "wrapfunctions.h" +#include "model_jakstat_adjoint_py.h" +#include "amici/model.h" + +namespace amici { +namespace generic_model { + +std::unique_ptr getModel() { + return std::unique_ptr( + new amici::model_model_jakstat_adjoint_py::Model_model_jakstat_adjoint_py() + ); +} + +} // namespace generic_model + +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/wrapfunctions.h b/models/model_jakstat_adjoint_py/wrapfunctions.h new file mode 100644 index 0000000000..33c8a9d819 --- /dev/null +++ b/models/model_jakstat_adjoint_py/wrapfunctions.h @@ -0,0 +1,25 @@ +#ifndef _amici_wrapfunctions_h +#define _amici_wrapfunctions_h + +#include + +#include "amici/model.h" + +namespace amici { +namespace generic_model { + + +/** + * @brief Wrapper function to instantiate the linked Amici model without knowing + * the name at compile time. + * @return Model instance + */ +std::unique_ptr getModel(); + + +} // namespace generic_model + +} // namespace amici + + +#endif /* _amici_wrapfunctions_h */ diff --git a/models/model_jakstat_adjoint_py/x.h b/models/model_jakstat_adjoint_py/x.h new file mode 100644 index 0000000000..a5afc502da --- /dev/null +++ b/models/model_jakstat_adjoint_py/x.h @@ -0,0 +1,9 @@ +#define STAT x[0] +#define pSTAT x[1] +#define pSTAT_pSTAT x[2] +#define npSTAT_npSTAT x[3] +#define nSTAT1 x[4] +#define nSTAT2 x[5] +#define nSTAT3 x[6] +#define nSTAT4 x[7] +#define nSTAT5 x[8] diff --git a/models/model_jakstat_adjoint_py/x0.cpp b/models/model_jakstat_adjoint_py/x0.cpp new file mode 100644 index 0000000000..5cd1532619 --- /dev/null +++ b/models/model_jakstat_adjoint_py/x0.cpp @@ -0,0 +1,19 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void x0_model_jakstat_adjoint_py(realtype *x0, const realtype t, const realtype *p, const realtype *k){ + x0[0] = 1.0; +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/x_rdata.cpp b/models/model_jakstat_adjoint_py/x_rdata.cpp new file mode 100644 index 0000000000..2e1c75a04d --- /dev/null +++ b/models/model_jakstat_adjoint_py/x_rdata.cpp @@ -0,0 +1,28 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void x_rdata_model_jakstat_adjoint_py(realtype *x_rdata, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k){ + x_rdata[0] = STAT; + x_rdata[1] = pSTAT; + x_rdata[2] = pSTAT_pSTAT; + x_rdata[3] = npSTAT_npSTAT; + x_rdata[4] = nSTAT1; + x_rdata[5] = nSTAT2; + x_rdata[6] = nSTAT3; + x_rdata[7] = nSTAT4; + x_rdata[8] = nSTAT5; +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/x_rdata.h b/models/model_jakstat_adjoint_py/x_rdata.h new file mode 100644 index 0000000000..6874dc9297 --- /dev/null +++ b/models/model_jakstat_adjoint_py/x_rdata.h @@ -0,0 +1,9 @@ +#define STAT x_rdata[0] +#define pSTAT x_rdata[1] +#define pSTAT_pSTAT x_rdata[2] +#define npSTAT_npSTAT x_rdata[3] +#define nSTAT1 x_rdata[4] +#define nSTAT2 x_rdata[5] +#define nSTAT3 x_rdata[6] +#define nSTAT4 x_rdata[7] +#define nSTAT5 x_rdata[8] diff --git a/models/model_jakstat_adjoint_py/x_solver.cpp b/models/model_jakstat_adjoint_py/x_solver.cpp new file mode 100644 index 0000000000..a4320133b4 --- /dev/null +++ b/models/model_jakstat_adjoint_py/x_solver.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x_rdata.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void x_solver_model_jakstat_adjoint_py(realtype *x_solver, const realtype *x_rdata){ + x_solver[0] = STAT; + x_solver[1] = pSTAT; + x_solver[2] = pSTAT_pSTAT; + x_solver[3] = npSTAT_npSTAT; + x_solver[4] = nSTAT1; + x_solver[5] = nSTAT2; + x_solver[6] = nSTAT3; + x_solver[7] = nSTAT4; + x_solver[8] = nSTAT5; +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/x_solver.h b/models/model_jakstat_adjoint_py/x_solver.h new file mode 100644 index 0000000000..59f5c2ff0a --- /dev/null +++ b/models/model_jakstat_adjoint_py/x_solver.h @@ -0,0 +1,9 @@ +#define x_solver0 x_solver[0] +#define x_solver1 x_solver[1] +#define x_solver2 x_solver[2] +#define x_solver3 x_solver[3] +#define x_solver4 x_solver[4] +#define x_solver5 x_solver[5] +#define x_solver6 x_solver[6] +#define x_solver7 x_solver[7] +#define x_solver8 x_solver[8] diff --git a/models/model_jakstat_adjoint_py/xdot.cpp b/models/model_jakstat_adjoint_py/xdot.cpp new file mode 100644 index 0000000000..5ee23e0658 --- /dev/null +++ b/models/model_jakstat_adjoint_py/xdot.cpp @@ -0,0 +1,30 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "w.h" +#include "xdot.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void xdot_model_jakstat_adjoint_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + dSTATdt = (-Omega_cyt*STAT*p1*u + Omega_nuc*nSTAT5*p4)/Omega_cyt; // xdot[0] + dpSTATdt = STAT*p1*u - 2*p2*std::pow(pSTAT, 2); // xdot[1] + dpSTAT_pSTATdt = p2*std::pow(pSTAT, 2) - p3*pSTAT_pSTAT; // xdot[2] + dnpSTAT_npSTATdt = (Omega_cyt*p3*pSTAT_pSTAT - Omega_nuc*npSTAT_npSTAT*p4)/Omega_nuc; // xdot[3] + dnSTAT1dt = -p4*(nSTAT1 - 2*npSTAT_npSTAT); // xdot[4] + dnSTAT2dt = p4*(nSTAT1 - nSTAT2); // xdot[5] + dnSTAT3dt = p4*(nSTAT2 - nSTAT3); // xdot[6] + dnSTAT4dt = p4*(nSTAT3 - nSTAT4); // xdot[7] + dnSTAT5dt = p4*(nSTAT4 - nSTAT5); // xdot[8] +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/xdot.h b/models/model_jakstat_adjoint_py/xdot.h new file mode 100644 index 0000000000..6e783f820e --- /dev/null +++ b/models/model_jakstat_adjoint_py/xdot.h @@ -0,0 +1,9 @@ +#define dSTATdt xdot[0] +#define dpSTATdt xdot[1] +#define dpSTAT_pSTATdt xdot[2] +#define dnpSTAT_npSTATdt xdot[3] +#define dnSTAT1dt xdot[4] +#define dnSTAT2dt xdot[5] +#define dnSTAT3dt xdot[6] +#define dnSTAT4dt xdot[7] +#define dnSTAT5dt xdot[8] diff --git a/models/model_jakstat_adjoint_py/y.cpp b/models/model_jakstat_adjoint_py/y.cpp new file mode 100644 index 0000000000..b93e121021 --- /dev/null +++ b/models/model_jakstat_adjoint_py/y.cpp @@ -0,0 +1,23 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "w.h" + +namespace amici { +namespace model_model_jakstat_adjoint_py { + +void y_model_jakstat_adjoint_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + y[0] = offset_pSTAT + scale_pSTAT*(pSTAT + 2*pSTAT_pSTAT)/init_STAT; + y[1] = offset_tSTAT + scale_tSTAT*(STAT + pSTAT + 2*pSTAT_pSTAT)/init_STAT; + y[2] = u; +} + +} // namespace model_model_jakstat_adjoint_py +} // namespace amici diff --git a/models/model_jakstat_adjoint_py/y.h b/models/model_jakstat_adjoint_py/y.h new file mode 100644 index 0000000000..d5426f73d1 --- /dev/null +++ b/models/model_jakstat_adjoint_py/y.h @@ -0,0 +1,3 @@ +#define obs_pSTAT y[0] +#define obs_tSTAT y[1] +#define obs_spline y[2] diff --git a/models/model_nested_events_py/CMakeLists.txt b/models/model_nested_events_py/CMakeLists.txt new file mode 100644 index 0000000000..d162a9e239 --- /dev/null +++ b/models/model_nested_events_py/CMakeLists.txt @@ -0,0 +1,151 @@ +# Build AMICI model +cmake_minimum_required(VERSION 3.22) +cmake_policy(VERSION 3.22...3.31) + +project(model_nested_events_py) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +include(CheckCXXCompilerFlag) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() +foreach(flag ${MY_CXX_FLAGS}) + unset(CUR_FLAG_SUPPORTED CACHE) + check_cxx_compiler_flag(${flag} CUR_FLAG_SUPPORTED) + if(${CUR_FLAG_SUPPORTED}) + string(APPEND CMAKE_CXX_FLAGS " ${flag}") + endif() +endforeach() + +if(DEFINED ENV{AMICI_CXXFLAGS}) + message(STATUS "Appending flags from AMICI_CXXFLAGS: $ENV{AMICI_CXXFLAGS}") + add_compile_options("$ENV{AMICI_CXXFLAGS}") +endif() +if(DEFINED ENV{AMICI_LDFLAGS}) + message(STATUS "Appending flags from AMICI_LDFLAGS: $ENV{AMICI_LDFLAGS}") + link_libraries("$ENV{AMICI_LDFLAGS}") +endif() + +find_package(Amici 0.33.0 REQUIRED HINTS + ${CMAKE_CURRENT_LIST_DIR}/../../build) +message(STATUS "Found AMICI ${Amici_DIR}") +set_target_properties(Upstream::amici PROPERTIES + MAP_IMPORTED_CONFIG_RELWITHDEBINFO RelWithDebInfo;Release; + MAP_IMPORTED_CONFIG_RELEASE Release + MAP_IMPORTED_CONFIG_DEBUG Debug;RelWithDebInfo;) + +# Debug build? +if("$ENV{ENABLE_AMICI_DEBUGGING}" OR "$ENV{ENABLE_GCOV_COVERAGE}") + add_compile_options(-UNDEBUG) + if(MSVC) + add_compile_options(-DEBUG) + else() + add_compile_options(-O0 -g) + endif() +endif() + +# coverage options +if($ENV{ENABLE_GCOV_COVERAGE}) + string(APPEND CMAKE_CXX_FLAGS_DEBUG " --coverage") + string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " --coverage") +endif() + +set(MODEL_DIR ${CMAKE_CURRENT_LIST_DIR}) + +set(SRC_LIST_LIB Jy.cpp +Jy.h +create_splines.cpp +dJydsigma.cpp +dJydy.cpp +dJydy.h +deltaqB.cpp +deltasx.cpp +deltax.cpp +deltaxB.cpp +dxdotdp_explicit.cpp +dxdotdp_explicit.h +dxdotdx_explicit.cpp +dxdotdx_explicit.h +dydx.cpp +h.h +model_nested_events_py.cpp +model_nested_events_py.h +my.h +p.h +root.cpp +sigmay.cpp +sigmay.h +stau.cpp +stau.h +sx.h +sx0.cpp +w.h +wrapfunctions.cpp +wrapfunctions.h +x.h +x0.cpp +xB.h +x_old.h +x_rdata.cpp +x_rdata.h +x_solver.cpp +x_solver.h +xdot.cpp +xdot.h +xdot_old.h +y.cpp +y.h ${MODEL_DIR}/wrapfunctions.cpp) + +add_library(${PROJECT_NAME} ${SRC_LIST_LIB}) + +# ${PROJECT_NAME} might already be "model" +if(NOT TARGET model) + add_library(model ALIAS ${PROJECT_NAME}) +endif() + +# Some special functions require boost +# +# TODO: set some flag during code generation whether the given model requires +# boost. for now, try to find it, add include directories and link against it. +# let the compiler/linker error if it is required but not found +find_package(Boost) + +target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") + +target_link_libraries( + ${PROJECT_NAME} + PUBLIC Upstream::amici + PRIVATE $<$:Boost::boost>) + +if(NOT "${AMICI_PYTHON_BUILD_EXT_ONLY}") + set(SRC_LIST_EXE main.cpp) + add_executable(simulate_${PROJECT_NAME} ${SRC_LIST_EXE}) + target_link_libraries(simulate_${PROJECT_NAME} ${PROJECT_NAME}) +endif() + +# SWIG +option(ENABLE_SWIG "Build swig/python library?" ON) +if(ENABLE_SWIG) + add_subdirectory(swig) +endif() + +# +include(GNUInstallDirs) +install( + TARGETS ${PROJECT_NAME} + EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +export( + EXPORT ${PROJECT_NAME}Targets + FILE ${PROJECT_NAME}Config.cmake + NAMESPACE Upstream::) +# diff --git a/models/model_nested_events_py/Jy.cpp b/models/model_nested_events_py/Jy.cpp new file mode 100644 index 0000000000..72bb72b5d0 --- /dev/null +++ b/models/model_nested_events_py/Jy.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_nested_events_py { + +void Jy_model_nested_events_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_Virus, 2)) + 0.5*std::pow(-mobs_Virus + obs_Virus, 2)/std::pow(sigma_obs_Virus, 2); + break; + } +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/Jy.h b/models/model_nested_events_py/Jy.h new file mode 100644 index 0000000000..6b49699ace --- /dev/null +++ b/models/model_nested_events_py/Jy.h @@ -0,0 +1 @@ +#define Jy0 Jy[0] diff --git a/models/model_nested_events_py/create_splines.cpp b/models/model_nested_events_py/create_splines.cpp new file mode 100644 index 0000000000..0ee747b26f --- /dev/null +++ b/models/model_nested_events_py/create_splines.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "amici/splinefunctions.h" +#include +#include "p.h" + +namespace amici { +namespace model_model_nested_events_py { + +std::vector create_splines_model_nested_events_py(const realtype *p, const realtype *k){ + return {}; +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/dJydsigma.cpp b/models/model_nested_events_py/dJydsigma.cpp new file mode 100644 index 0000000000..e43827c66b --- /dev/null +++ b/models/model_nested_events_py/dJydsigma.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_nested_events_py { + +void dJydsigma_model_nested_events_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydsigma[0] = 1.0/sigma_obs_Virus - 1.0*std::pow(-mobs_Virus + obs_Virus, 2)/std::pow(sigma_obs_Virus, 3); + break; + } +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/dJydy.cpp b/models/model_nested_events_py/dJydy.cpp new file mode 100644 index 0000000000..f34057a58d --- /dev/null +++ b/models/model_nested_events_py/dJydy.cpp @@ -0,0 +1,67 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_nested_events_py { + +static constexpr std::array, 1> dJydy_colptrs_model_nested_events_py_ = {{ + {0, 1}, +}}; + +void dJydy_colptrs_model_nested_events_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexptrs(gsl::make_span(dJydy_colptrs_model_nested_events_py_[index])); +} +} // namespace model_model_nested_events_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_nested_events_py { + +static constexpr std::array, 1> dJydy_rowvals_model_nested_events_py_ = {{ + {0}, +}}; + +void dJydy_rowvals_model_nested_events_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexvals(gsl::make_span(dJydy_rowvals_model_nested_events_py_[index])); +} +} // namespace model_model_nested_events_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" +#include "dJydy.h" + +namespace amici { +namespace model_model_nested_events_py { + +void dJydy_model_nested_events_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydy[0] = (-1.0*mobs_Virus + 1.0*obs_Virus)/std::pow(sigma_obs_Virus, 2); + break; + } +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/dJydy.h b/models/model_nested_events_py/dJydy.h new file mode 100644 index 0000000000..15a21d6466 --- /dev/null +++ b/models/model_nested_events_py/dJydy.h @@ -0,0 +1 @@ +#define dJy0_dobs_Virus dJydy[0] diff --git a/models/model_nested_events_py/deltaqB.cpp b/models/model_nested_events_py/deltaqB.cpp new file mode 100644 index 0000000000..f8833fb8ea --- /dev/null +++ b/models/model_nested_events_py/deltaqB.cpp @@ -0,0 +1,35 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "xdot.h" +#include "xdot_old.h" +#include "x_old.h" +#include "xB.h" + +namespace amici { +namespace model_model_nested_events_py { + +void deltaqB_model_nested_events_py(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB){ + switch(ie) { + case 0: + switch(ip) { + case 1: + deltaqB[0] = xB0; + break; + case 2: + deltaqB[0] = xB0*(-dVirusdt + xdot_old0); + break; + } + break; + } +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/deltasx.cpp b/models/model_nested_events_py/deltasx.cpp new file mode 100644 index 0000000000..7cc2e5c2bf --- /dev/null +++ b/models/model_nested_events_py/deltasx.cpp @@ -0,0 +1,51 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "xdot.h" +#include "xdot_old.h" +#include "sx.h" +#include "stau.h" +#include "x_old.h" + +namespace amici { +namespace model_model_nested_events_py { + +void deltasx_model_nested_events_py(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old){ + switch(ie) { + case 0: + switch(ip) { + case 0: + case 2: + case 3: + case 4: + deltasx[0] = stau0*(dVirusdt - xdot_old0); + break; + case 1: + deltasx[0] = stau0*(dVirusdt - xdot_old0) + 1; + break; + } + break; + case 1: + case 2: + switch(ip) { + case 0: + case 1: + case 2: + case 3: + case 4: + deltasx[0] = stau0*(dVirusdt - xdot_old0); + break; + } + break; + } +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/deltax.cpp b/models/model_nested_events_py/deltax.cpp new file mode 100644 index 0000000000..91b845e21d --- /dev/null +++ b/models/model_nested_events_py/deltax.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "xdot.h" +#include "x_old.h" + +namespace amici { +namespace model_model_nested_events_py { + +void deltax_model_nested_events_py(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old){ + switch(ie) { + case 0: + deltax[0] = V_0_inject - Virus + x_old0; + break; + } +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/deltaxB.cpp b/models/model_nested_events_py/deltaxB.cpp new file mode 100644 index 0000000000..606aa33b08 --- /dev/null +++ b/models/model_nested_events_py/deltaxB.cpp @@ -0,0 +1,31 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "xdot.h" +#include "xdot_old.h" +#include "x_old.h" +#include "xB.h" + +namespace amici { +namespace model_model_nested_events_py { + +void deltaxB_model_nested_events_py(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl){ + switch(ie) { + case 1: + deltaxB[0] = xB0*(dVirusdt - xdot_old0)/(Heaviside_1*Virus*rho_V - Virus*delta_V); + break; + case 2: + deltaxB[0] = -xB0*(dVirusdt - xdot_old0)/(-Heaviside_1*Virus*rho_V + Virus*delta_V); + break; + } +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/dxdotdp_explicit.cpp b/models/model_nested_events_py/dxdotdp_explicit.cpp new file mode 100644 index 0000000000..aef0b3e29d --- /dev/null +++ b/models/model_nested_events_py/dxdotdp_explicit.cpp @@ -0,0 +1,64 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_nested_events_py { + +static constexpr std::array dxdotdp_explicit_colptrs_model_nested_events_py_ = { + 0, 0, 0, 0, 1, 2 +}; + +void dxdotdp_explicit_colptrs_model_nested_events_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexptrs(gsl::make_span(dxdotdp_explicit_colptrs_model_nested_events_py_)); +} +} // namespace model_model_nested_events_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_nested_events_py { + +static constexpr std::array dxdotdp_explicit_rowvals_model_nested_events_py_ = { + 0, 0 +}; + +void dxdotdp_explicit_rowvals_model_nested_events_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexvals(gsl::make_span(dxdotdp_explicit_rowvals_model_nested_events_py_)); +} +} // namespace model_model_nested_events_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "w.h" +#include "dxdotdp_explicit.h" + +namespace amici { +namespace model_model_nested_events_py { + +void dxdotdp_explicit_model_nested_events_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + ddVirusdt_drho_V = Heaviside_1*Virus; // dxdotdp_explicit[0] + ddVirusdt_ddelta_V = -Virus; // dxdotdp_explicit[1] +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/dxdotdp_explicit.h b/models/model_nested_events_py/dxdotdp_explicit.h new file mode 100644 index 0000000000..b63afe81de --- /dev/null +++ b/models/model_nested_events_py/dxdotdp_explicit.h @@ -0,0 +1,2 @@ +#define ddVirusdt_drho_V dxdotdp_explicit[0] +#define ddVirusdt_ddelta_V dxdotdp_explicit[1] diff --git a/models/model_nested_events_py/dxdotdx_explicit.cpp b/models/model_nested_events_py/dxdotdx_explicit.cpp new file mode 100644 index 0000000000..b12a43d7e2 --- /dev/null +++ b/models/model_nested_events_py/dxdotdx_explicit.cpp @@ -0,0 +1,63 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_nested_events_py { + +static constexpr std::array dxdotdx_explicit_colptrs_model_nested_events_py_ = { + 0, 1 +}; + +void dxdotdx_explicit_colptrs_model_nested_events_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexptrs(gsl::make_span(dxdotdx_explicit_colptrs_model_nested_events_py_)); +} +} // namespace model_model_nested_events_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_nested_events_py { + +static constexpr std::array dxdotdx_explicit_rowvals_model_nested_events_py_ = { + 0 +}; + +void dxdotdx_explicit_rowvals_model_nested_events_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexvals(gsl::make_span(dxdotdx_explicit_rowvals_model_nested_events_py_)); +} +} // namespace model_model_nested_events_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "w.h" +#include "dxdotdx_explicit.h" + +namespace amici { +namespace model_model_nested_events_py { + +void dxdotdx_explicit_model_nested_events_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + ddVirusdt_dVirus = Heaviside_1*rho_V - delta_V; // dxdotdx_explicit[0] +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/dxdotdx_explicit.h b/models/model_nested_events_py/dxdotdx_explicit.h new file mode 100644 index 0000000000..492afef74f --- /dev/null +++ b/models/model_nested_events_py/dxdotdx_explicit.h @@ -0,0 +1 @@ +#define ddVirusdt_dVirus dxdotdx_explicit[0] diff --git a/models/model_nested_events_py/dydx.cpp b/models/model_nested_events_py/dydx.cpp new file mode 100644 index 0000000000..4da41566fd --- /dev/null +++ b/models/model_nested_events_py/dydx.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" + +namespace amici { +namespace model_model_nested_events_py { + +void dydx_model_nested_events_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx){ + dydx[0] = 1; +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/h.h b/models/model_nested_events_py/h.h new file mode 100644 index 0000000000..87eb526963 --- /dev/null +++ b/models/model_nested_events_py/h.h @@ -0,0 +1,3 @@ +#define injection h[0] +#define Heaviside_1 h[1] +#define Heaviside_2 h[2] diff --git a/models/model_nested_events_py/main.cpp b/models/model_nested_events_py/main.cpp new file mode 100644 index 0000000000..ecdff85a46 --- /dev/null +++ b/models/model_nested_events_py/main.cpp @@ -0,0 +1,93 @@ +#include + +#include "wrapfunctions.h" /* model-provided functions */ +#include /* AMICI base functions */ + +template +std::ostream& operator<<(std::ostream& os, std::vector const& v) { + os << "["; + for (typename std::vector::const_iterator ii = v.begin(); ii != v.end(); + ++ii) { + os << " " << *ii; + } + os << "]"; + return os; +} + +/* + * This is a scaffold for a stand-alone AMICI simulation executable + * demonstrating the basic use of the AMICI C++ API. + */ + +int main() { + std::cout << "********************************" << std::endl; + std::cout << "** Running forward simulation **" << std::endl; + std::cout << "********************************" << std::endl << std::endl; + + // Create a model instance + auto model = amici::generic_model::getModel(); + + // Set desired output timepoints + model->setTimepoints({0.0, 1.0, 10.0, 100.0, 1000.0}); + + // Create a solver instance + auto solver = model->getSolver(); + + // Optionally set integration tolerance + solver->setAbsoluteTolerance(1e-16); + solver->setRelativeTolerance(1e-8); + + // Run the simulation using default parameters set during model import + // (can be changed using model->setParameters() or model->setParameterBy*()) + auto rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print observable time course + auto observable_ids = model->getObservableIds(); + std::cout << "Simulated observables for timepoints " << rdata->ts << "\n\n"; + for (int i_observable = 0; i_observable < rdata->ny; ++i_observable) { + std::cout << observable_ids[i_observable] << ":\n\t"; + for (int i_time = 0; i_time < rdata->nt; ++i_time) { + // rdata->y is a flat 2D array in row-major ordering + std::cout << rdata->y[i_time * rdata->ny + i_observable] << " "; + } + std::cout << std::endl << std::endl; + } + + std::cout << std::endl; + std::cout << "**********************************" << std::endl; + std::cout << "** Forward sensitivity analysis **" << std::endl; + std::cout << "**********************************" << std::endl << std::endl; + + // Enable first-order sensitivity analysis + solver->setSensitivityOrder(amici::SensitivityOrder::first); + // Use forward sensitivities + solver->setSensitivityMethod(amici::SensitivityMethod::forward); + + // Run the simulation + rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print state sensitivities sx... + // ... for the first timepoint... + int i_time = 0; + // ... with respect to the first parameter + int i_nplist = 0; + + // get identifiers from model + auto state_ids = model->getStateIds(); + auto parameter_ids = model->getParameterIds(); + + std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] + << std::endl; // nt x nplist x nx + for (int i_state = 0; i_state < rdata->nx; ++i_state) { + std::cout << "\td(" << state_ids[i_state] << ")/d(" + << parameter_ids[model->plist(i_nplist)] << ") = "; + + // rdata->sx is a flat 3D array in row-major ordering + std::cout << rdata->sx + [i_time * rdata->nplist * rdata->nx + + i_nplist * rdata->nx + i_state]; + std::cout << std::endl; + } + + return 0; +} diff --git a/models/model_nested_events_py/model_nested_events_py.cpp b/models/model_nested_events_py/model_nested_events_py.cpp new file mode 100644 index 0000000000..5fef2fada0 --- /dev/null +++ b/models/model_nested_events_py/model_nested_events_py.cpp @@ -0,0 +1,70 @@ +#include +#include + +namespace amici { + +namespace model_model_nested_events_py { + +// clang-format off + +std::array parameterNames = { + "V_0", // p[0] +"V_0_inject", // p[1] +"t_0", // p[2] +"rho_V", // p[3] +"delta_V", // p[4] +}; + +std::array fixedParameterNames = { + +}; + +std::array stateNames = { + "Virus", // x_rdata[0] +}; + +std::array observableNames = { + "y0", // y[0] +}; + +std::array observableScalings = { + ObservableScaling::lin, // y[0] +}; + +std::array expressionNames = { + "flux_r0", // w[0] +}; + +std::array parameterIds = { + "V_0", // p[0] +"V_0_inject", // p[1] +"t_0", // p[2] +"rho_V", // p[3] +"delta_V", // p[4] +}; + +std::array fixedParameterIds = { + +}; + +std::array stateIds = { + "Virus", // x_rdata[0] +}; + +std::array observableIds = { + "obs_Virus", // y[0] +}; + +std::array expressionIds = { + "flux_r0", // w[0] +}; + +std::array stateIdxsSolver = { + 0 +}; + +// clang-format on + +} // namespace model_model_nested_events_py + +} // namespace amici diff --git a/models/model_nested_events_py/model_nested_events_py.h b/models/model_nested_events_py/model_nested_events_py.h new file mode 100644 index 0000000000..ed084befb3 --- /dev/null +++ b/models/model_nested_events_py/model_nested_events_py.h @@ -0,0 +1,569 @@ +#ifndef _amici_TPL_MODELNAME_h +#define _amici_TPL_MODELNAME_h +#include +#include +#include + +#include "amici/model_ode.h" +#include "amici/splinefunctions.h" +#include "amici/event.h" + +namespace amici { + +class Solver; + +namespace model_model_nested_events_py { + +extern std::array parameterNames; +extern std::array fixedParameterNames; +extern std::array stateNames; +extern std::array observableNames; +extern std::array observableScalings; +extern std::array expressionNames; +extern std::array parameterIds; +extern std::array fixedParameterIds; +extern std::array stateIds; +extern std::array observableIds; +extern std::array expressionIds; +extern std::array stateIdxsSolver; + +extern void Jy_model_nested_events_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydsigma_model_nested_events_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_model_nested_events_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_colptrs_model_nested_events_py(SUNMatrixWrapper &colptrs, int index); +extern void dJydy_rowvals_model_nested_events_py(SUNMatrixWrapper &rowvals, int index); + + + + + + +extern void root_model_nested_events_py(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl); + + + + + + + + + + + + +extern void dxdotdp_explicit_model_nested_events_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void dxdotdp_explicit_colptrs_model_nested_events_py(SUNMatrixWrapper &colptrs); +extern void dxdotdp_explicit_rowvals_model_nested_events_py(SUNMatrixWrapper &rowvals); +extern void dxdotdx_explicit_model_nested_events_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void dxdotdx_explicit_colptrs_model_nested_events_py(SUNMatrixWrapper &colptrs); +extern void dxdotdx_explicit_rowvals_model_nested_events_py(SUNMatrixWrapper &rowvals); +extern void dydx_model_nested_events_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx); + + + + + +extern void sigmay_model_nested_events_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y); + + + + + +extern void x0_model_nested_events_py(realtype *x0, const realtype t, const realtype *p, const realtype *k); + +extern void sx0_model_nested_events_py(realtype *sx0, const realtype t, const realtype *x, const realtype *p, const realtype *k, const int ip); + +extern void xdot_model_nested_events_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void y_model_nested_events_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); + + +extern void stau_model_nested_events_py(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie); +extern void deltax_model_nested_events_py(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old); +extern void deltasx_model_nested_events_py(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old); +extern void deltaxB_model_nested_events_py(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl); +extern void deltaqB_model_nested_events_py(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB); + +extern void x_solver_model_nested_events_py(realtype *x_solver, const realtype *x_rdata); + + + + + + + + + + + + +extern std::vector create_splines_model_nested_events_py(const realtype *p, const realtype *k); + + + +/** + * @brief AMICI-generated model subclass. + */ +class Model_model_nested_events_py : public amici::Model_ODE { + public: + /** + * @brief Default constructor. + */ + Model_model_nested_events_py() + : amici::Model_ODE( + amici::ModelDimensions( + 1, // nx_rdata + 1, // nxtrue_rdata + 1, // nx_solver + 1, // nxtrue_solver + 0, // nx_solver_reinit + 5, // np + 0, // nk + 1, // ny + 1, // nytrue + 0, // nz + 0, // nztrue + 3, // nevent + 3, // nevent_solver + 0, // nspl + 1, // nobjective + 1, // nw + 0, // ndwdx + 0, // ndwdp + 0, // ndwdw + 0, // ndxdotdw + std::vector{1}, // ndjydy + 0, // ndxrdatadxsolver + 0, // ndxrdatadtcl + 0, // ndtotal_cldx_rdata + 0, // nnz + 1, // ubw + 1, // lbw + true, // pythonGenerated + 2, // ndxdotdp_explicit + 1, // ndxdotdx_explicit + 0 // w_recursion_depth + ), + amici::SimulationParameters( + std::vector{}, // fixedParameters + std::vector{0.10000000000000001, 1000.0, 2.0, 0.80000000000000004, 1.6000000000000001} // dynamic parameters + ), + amici::SecondOrderMode::none, // o2mode + std::vector{1.0}, // idlist + std::vector{}, // z2events + std::vector{ + Event("injection", true, true, NAN), + Event("Heaviside_1", true, true, NAN), + Event("Heaviside_2", true, true, NAN) + }, // events + {} // state-independent events + ) { + } + + /** + * @brief Clone this model instance. + * @return A deep copy of this instance. + */ + amici::Model *clone() const override { + return new Model_model_nested_events_py(*this); + } + + void fJrz(realtype *Jrz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fJy(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + Jy_model_nested_events_py(Jy, iy, p, k, y, sigmay, my); + } + + + void fJz(realtype *Jz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override {} + + + void fdJrzdsigma(realtype *dJrzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fdJrzdz(realtype *dJrzdz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fdJydsigma(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydsigma_model_nested_events_py(dJydsigma, iy, p, k, y, sigmay, my); + } + + + void fdJzdsigma(realtype *dJzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override {} + + + void fdJzdz(realtype *dJzdz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const double *mz) override {} + + + void fdeltax(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old) override { + deltax_model_nested_events_py(deltax, t, x, p, k, h, ie, xdot, xdot_old, x_old); + } + + + void fdeltasx(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old) override { + deltasx_model_nested_events_py(deltasx, t, x, p, k, h, w, ip, ie, xdot, xdot_old, sx, stau, tcl, x_old); + } + + + void fdeltaxB(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl) override { + deltaxB_model_nested_events_py(deltaxB, t, x, p, k, h, dx, ie, xdot, xdot_old, x_old, xB, tcl); + } + + + void fdeltaqB(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB) override { + deltaqB_model_nested_events_py(deltaqB, t, x, p, k, h, dx, ip, ie, xdot, xdot_old, x_old, xB); + } + + + void fdrzdp(realtype *drzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdrzdx(realtype *drzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void fdsigmaydp(realtype *dsigmaydp, const realtype t, const realtype *p, const realtype *k, const realtype *y, const int ip) override {} + + + void fdsigmaydy(realtype *dsigmaydy, const realtype t, const realtype *p, const realtype *k, const realtype *y) override {} + + + void fdsigmazdp(realtype *dsigmazdp, const realtype t, const realtype *p, const realtype *k, const int ip) override {} + + + void fdJydy(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydy_model_nested_events_py(dJydy, iy, p, k, y, sigmay, my); + } + + void fdJydy_colptrs(SUNMatrixWrapper &colptrs, int index) override { + dJydy_colptrs_model_nested_events_py(colptrs, index); + } + + void fdJydy_rowvals(SUNMatrixWrapper &rowvals, int index) override { + dJydy_rowvals_model_nested_events_py(rowvals, index); + } + + + std::vector fcreate_splines(const realtype *p, const realtype *k) override { + return create_splines_model_nested_events_py(p, k); + } + + void fdspline_valuesdp(realtype *dspline_valuesdp, const realtype *p, const realtype *k, const int ip) override {} + + void fdspline_slopesdp(realtype *dspline_slopesdp, const realtype *p, const realtype *k, const int ip) override {} + + + void fdwdp(realtype *dwdp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl, bool include_static) override {} + + void fdwdp_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdp_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdx(realtype *dwdx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *spl, bool include_static) override {} + + void fdwdx_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdx_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdw(realtype *dwdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, bool include_static) override {} + + void fdwdw_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdw_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdw(realtype *dxdotdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override {} + + void fdxdotdw_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdxdotdw_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdp_explicit(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + dxdotdp_explicit_model_nested_events_py(dxdotdp_explicit, t, x, p, k, h, w); + } + + void fdxdotdp_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdp_explicit_colptrs_model_nested_events_py(colptrs); + } + + void fdxdotdp_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdp_explicit_rowvals_model_nested_events_py(rowvals); + } + + + void fdxdotdx_explicit(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + dxdotdx_explicit_model_nested_events_py(dxdotdx_explicit, t, x, p, k, h, w); + } + + void fdxdotdx_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdx_explicit_colptrs_model_nested_events_py(colptrs); + } + + void fdxdotdx_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdx_explicit_rowvals_model_nested_events_py(rowvals); + } + + + void fdydx(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { + dydx_model_nested_events_py(dydx, t, x, p, k, h, w, dwdx); + } + + + void fdydp(realtype *dydp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl) override {} + + + void fdzdp(realtype *dzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdzdx(realtype *dzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void froot(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl) override { + root_model_nested_events_py(root, t, x, p, k, h, tcl); + } + + + void frz(realtype *rz, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void fsigmay(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y) override { + sigmay_model_nested_events_py(sigmay, t, p, k, y); + } + + + void fsigmaz(realtype *sigmaz, const realtype t, const realtype *p, const realtype *k) override {} + + + void fstau(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie) override { + stau_model_nested_events_py(stau, t, x, p, k, h, dx, tcl, sx, ip, ie); + } + + void fsx0(realtype *sx0, const realtype t, const realtype *x, const realtype *p, const realtype *k, const int ip) override { + sx0_model_nested_events_py(sx0, t, x, p, k, ip); + } + + void fsx0_fixedParameters(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs) override {} + + + void fw(realtype *w, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl, const realtype *spl, bool include_static) override {} + + + void fx0(realtype *x0, const realtype t, const realtype *p, const realtype *k) override { + x0_model_nested_events_py(x0, t, p, k); + } + + + void fx0_fixedParameters(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs) override {} + + + void fxdot(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + xdot_model_nested_events_py(xdot, t, x, p, k, h, w); + } + + + void fy(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + y_model_nested_events_py(y, t, x, p, k, h, w); + } + + + void fz(realtype *z, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + + + void fx_solver(realtype *x_solver, const realtype *x_rdata) override { + x_solver_model_nested_events_py(x_solver, x_rdata); + } + + + void ftotal_cl(realtype *total_cl, const realtype *x_rdata, const realtype *p, const realtype *k) override {} + + + void fdx_rdatadx_solver(realtype *dx_rdatadx_solver, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadx_solver_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadx_solver_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdx_rdatadp(realtype *dx_rdatadp, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k, const int ip) override {} + + + void fdx_rdatadtcl(realtype *dx_rdatadtcl, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadtcl_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadtcl_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdtotal_cldp(realtype *dtotal_cldp, const realtype *x_rdata, const realtype *p, const realtype *k, const int ip) override {} + + + void fdtotal_cldx_rdata(realtype *dtotal_cldx_rdata, const realtype *x_rdata, const realtype *p, const realtype *k, const realtype *tcl) override {} + + void fdtotal_cldx_rdata_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdtotal_cldx_rdata_rowvals(SUNMatrixWrapper &rowvals) override {} + + + std::string getName() const override { + return "model_nested_events_py"; + } + + /** + * @brief Get names of the model parameters + * @return the names + */ + std::vector getParameterNames() const override { + return std::vector(parameterNames.begin(), + parameterNames.end()); + } + + /** + * @brief Get names of the model states + * @return the names + */ + std::vector getStateNames() const override { + return std::vector(stateNames.begin(), stateNames.end()); + } + + /** + * @brief Get names of the solver states + * @return the names + */ + std::vector getStateNamesSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto const idx: stateIdxsSolver) { + result.push_back(stateNames[idx]); + } + return result; + } + + /** + * @brief Get names of the fixed model parameters + * @return the names + */ + std::vector getFixedParameterNames() const override { + return std::vector(fixedParameterNames.begin(), + fixedParameterNames.end()); + } + + /** + * @brief Get names of the observables + * @return the names + */ + std::vector getObservableNames() const override { + return std::vector(observableNames.begin(), + observableNames.end()); + } + + /** + * @brief Get names of model expressions + * @return Expression names + */ + std::vector getExpressionNames() const override { + return std::vector(expressionNames.begin(), + expressionNames.end()); + } + + /** + * @brief Get ids of the model parameters + * @return the ids + */ + std::vector getParameterIds() const override { + return std::vector(parameterIds.begin(), + parameterIds.end()); + } + + /** + * @brief Get ids of the model states + * @return the ids + */ + std::vector getStateIds() const override { + return std::vector(stateIds.begin(), stateIds.end()); + } + + /** + * @brief Get ids of the solver states + * @return the ids + */ + std::vector getStateIdsSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto idx: stateIdxsSolver) { + result.push_back(stateIds[idx]); + } + return result; + } + + /** + * @brief Get ids of the fixed model parameters + * @return the ids + */ + std::vector getFixedParameterIds() const override { + return std::vector(fixedParameterIds.begin(), + fixedParameterIds.end()); + } + + /** + * @brief Get ids of the observables + * @return the ids + */ + std::vector getObservableIds() const override { + return std::vector(observableIds.begin(), + observableIds.end()); + } + + /** + * @brief Get IDs of model expressions + * @return Expression IDs + */ + std::vector getExpressionIds() const override { + return std::vector(expressionIds.begin(), + expressionIds.end()); + } + + /** + * @brief function indicating whether reinitialization of states depending + * on fixed parameters is permissible + * @return flag indicating whether reinitialization of states depending on + * fixed parameters is permissible + */ + bool isFixedParameterStateReinitializationAllowed() const override { + return true; + } + + /** + * @brief returns the AMICI version that was used to generate the model + * @return AMICI version string + */ + std::string getAmiciVersion() const override { + return "0.33.0"; + } + + /** + * @brief returns the amici version that was used to generate the model + * @return AMICI git commit hash + */ + std::string getAmiciCommit() const override { + return "bcedb951ddf674996b269489d74f9b86112038ff"; + } + + bool hasQuadraticLLH() const override { + return true; + } + + ObservableScaling getObservableScaling(int iy) const override { + return observableScalings.at(iy); + } +}; + + +} // namespace model_model_nested_events_py + +} // namespace amici + +#endif /* _amici_TPL_MODELNAME_h */ diff --git a/models/model_nested_events_py/my.h b/models/model_nested_events_py/my.h new file mode 100644 index 0000000000..56e07ead52 --- /dev/null +++ b/models/model_nested_events_py/my.h @@ -0,0 +1 @@ +#define mobs_Virus my[0] diff --git a/models/model_nested_events_py/p.h b/models/model_nested_events_py/p.h new file mode 100644 index 0000000000..7be87dc464 --- /dev/null +++ b/models/model_nested_events_py/p.h @@ -0,0 +1,5 @@ +#define V_0 p[0] +#define V_0_inject p[1] +#define t_0 p[2] +#define rho_V p[3] +#define delta_V p[4] diff --git a/models/model_nested_events_py/root.cpp b/models/model_nested_events_py/root.cpp new file mode 100644 index 0000000000..f76cc5c298 --- /dev/null +++ b/models/model_nested_events_py/root.cpp @@ -0,0 +1,22 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" + +namespace amici { +namespace model_model_nested_events_py { + +void root_model_nested_events_py(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl){ + root[0] = t - t_0; + root[1] = Virus - 1; + root[2] = 1 - Virus; +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/setup.py b/models/model_nested_events_py/setup.py new file mode 100644 index 0000000000..d42f740789 --- /dev/null +++ b/models/model_nested_events_py/setup.py @@ -0,0 +1,95 @@ +"""AMICI model package setup""" + +import os +import sys +from pathlib import Path + +from amici import _get_amici_path +from amici.custom_commands import AmiciBuildCMakeExtension +from cmake_build_extension import CMakeExtension +from setuptools import find_namespace_packages, setup +import importlib.metadata + + +def get_extension() -> CMakeExtension: + """Get setuptools extension object for this AMICI model package""" + + # Build shared object + prefix_path = Path(_get_amici_path()) + AmiciBuildCMakeExtension.extend_cmake_prefix_path(str(prefix_path)) + + # handle parallel building + # Note: can be empty to use all hardware threads + if (parallel_jobs := os.environ.get("AMICI_PARALLEL_COMPILE")) is not None: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = parallel_jobs + else: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = "1" + + debug_build = os.getenv("ENABLE_AMICI_DEBUGGING", "").lower() in [ + "1", + "true", + ] or os.getenv("ENABLE_GCOV_COVERAGE", "").lower() in ["1", "true"] + + cmake_prefix_path = os.getenv("CMAKE_PREFIX_PATH", "").split(os.pathsep) + cmake_prefix_path.append(prefix_path.as_posix()) + + # If scipy_openblas64 is installed, we make its cmake configuration + # available + amici_distribution = importlib.metadata.distribution("amici") + amici_dir = Path(amici_distribution.locate_file("")) + # this path is created during the amici build if scipy_openblas64 is used + openblas_cmake_dir = amici_dir / "lib" / "cmake" / "openblas" + if openblas_cmake_dir.exists(): + cmake_prefix_path.append(str(openblas_cmake_dir)) + + return CMakeExtension( + name="model_ext", + source_dir=os.getcwd(), + install_prefix="model_nested_events_py", + cmake_configure_options=[ + "-DCMAKE_VERBOSE_MAKEFILE=ON", + f"-DCMAKE_PREFIX_PATH='{';'.join(cmake_prefix_path)}'", + "-DAMICI_PYTHON_BUILD_EXT_ONLY=ON", + f"-DPython3_EXECUTABLE={Path(sys.executable).as_posix()}", + ], + cmake_build_type="Debug" if debug_build else "Release", + ) + + +# Change working directory to setup.py location +os.chdir(os.path.dirname(os.path.abspath(__file__))) + +MODEL_EXT = get_extension() + +CLASSIFIERS = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Science/Research", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python", + "Programming Language :: C++", + "Topic :: Scientific/Engineering :: Bio-Informatics", +] + +CMDCLASS = { + # for CMake-based builds + "build_ext": AmiciBuildCMakeExtension, +} + +# Install +setup( + name="model_nested_events_py", + cmdclass=CMDCLASS, + version="0.1.0", + description="AMICI-generated module for model model_nested_events_py", + url="https://github.com/AMICI-dev/AMICI", + author="model-author-todo", + author_email="model-author-todo", + ext_modules=[MODEL_EXT], + packages=find_namespace_packages(), + install_requires=["amici==0.33.0"], + python_requires=">=3.11", + package_data={}, + zip_safe=False, + classifiers=CLASSIFIERS, +) diff --git a/models/model_nested_events_py/sigmay.cpp b/models/model_nested_events_py/sigmay.cpp new file mode 100644 index 0000000000..4063094c4d --- /dev/null +++ b/models/model_nested_events_py/sigmay.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "y.h" +#include "sigmay.h" + +namespace amici { +namespace model_model_nested_events_py { + +void sigmay_model_nested_events_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y){ + sigma_obs_Virus = 1.0; // sigmay[0] +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/sigmay.h b/models/model_nested_events_py/sigmay.h new file mode 100644 index 0000000000..91fa1f758b --- /dev/null +++ b/models/model_nested_events_py/sigmay.h @@ -0,0 +1 @@ +#define sigma_obs_Virus sigmay[0] diff --git a/models/model_nested_events_py/stau.cpp b/models/model_nested_events_py/stau.cpp new file mode 100644 index 0000000000..a5df0dc8b1 --- /dev/null +++ b/models/model_nested_events_py/stau.cpp @@ -0,0 +1,51 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "sx.h" + +namespace amici { +namespace model_model_nested_events_py { + +void stau_model_nested_events_py(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie){ + switch(ie) { + case 0: + switch(ip) { + case 2: + stau[0] = -1; + break; + } + break; + case 1: + switch(ip) { + case 0: + case 1: + case 2: + case 3: + case 4: + stau[0] = sx0/(Heaviside_1*Virus*rho_V - Virus*delta_V); + break; + } + break; + case 2: + switch(ip) { + case 0: + case 1: + case 2: + case 3: + case 4: + stau[0] = -sx0/(-Heaviside_1*Virus*rho_V + Virus*delta_V); + break; + } + break; + } +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/stau.h b/models/model_nested_events_py/stau.h new file mode 100644 index 0000000000..2871b2462c --- /dev/null +++ b/models/model_nested_events_py/stau.h @@ -0,0 +1 @@ +#define stau0 stau[0] diff --git a/models/model_nested_events_py/swig/CMakeLists.txt b/models/model_nested_events_py/swig/CMakeLists.txt new file mode 100644 index 0000000000..314996c479 --- /dev/null +++ b/models/model_nested_events_py/swig/CMakeLists.txt @@ -0,0 +1,60 @@ +if(DEFINED ENV{SWIG}) + set(SWIG_EXECUTABLE $ENV{SWIG}) +endif() + +find_package(SWIG REQUIRED) +include(${SWIG_USE_FILE}) + +if(DEFINED ENV{PYTHON_EXECUTABLE}) + set(Python3_EXECUTABLE $ENV{PYTHON_EXECUTABLE}) +endif() +# We don't need "Interpreter" here, but without that, FindPython3 will +# ignore the Python version selected via $Python3_EXECUTABLE +find_package(Python3 COMPONENTS Interpreter Development) +include_directories(${Python3_INCLUDE_DIRS}) + +set(SWIG_LIBRARY_NAME _${PROJECT_NAME}) +set(CMAKE_SWIG_FLAGS "") +set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) + +# swig does not use INTERFACE_INCLUDE_DIRS of linked libraries, so add manually +get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) +include_directories(${AMICI_INCLUDE_DIRS} .. ${AMICI_INCLUDE_DIRS}/../swig) + +swig_add_library(${SWIG_LIBRARY_NAME} + TYPE MODULE + LANGUAGE python + SOURCES ${PROJECT_NAME}.i) + + +set_target_properties(${SWIG_LIBRARY_NAME} + PROPERTIES + SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE + PREFIX "" +) + +# Python extension suffix +execute_process( + COMMAND ${Python3_EXECUTABLE} -c + "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))" + OUTPUT_VARIABLE PY_EXT_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE) +if(NOT "${PY_EXT_SUFFIX}" STREQUAL "") + message(STATUS "Python extension suffix is ${PY_EXT_SUFFIX}") + set_target_properties(${SWIG_LIBRARY_NAME} PROPERTIES SUFFIX "${PY_EXT_SUFFIX}" ) +endif() + + +swig_link_libraries(${SWIG_LIBRARY_NAME} + ${Python3_LIBRARIES} + model) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.py + $ DESTINATION .) + +# configure module setup script +set(SETUP_PY_IN ${Amici_DIR}/model_setup.template.py) +set(SETUP_PY_OUT ${CMAKE_CURRENT_BINARY_DIR}/setup.py) + +add_custom_target(install-python + DEPENDS ${SWIG_LIBRARY_NAME} + COMMAND python ${SETUP_PY_OUT} install) diff --git a/models/model_nested_events_py/swig/model_nested_events_py.i b/models/model_nested_events_py/swig/model_nested_events_py.i new file mode 100644 index 0000000000..ba5af5ebf8 --- /dev/null +++ b/models/model_nested_events_py/swig/model_nested_events_py.i @@ -0,0 +1,82 @@ +%define MODULEIMPORT +" +import amici +import datetime +import importlib.util +import os +import sysconfig +from pathlib import Path + +ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +_model_nested_events_py = amici._module_from_path( + 'model_nested_events_py._model_nested_events_py' if __package__ or '.' in __name__ + else '_model_nested_events_py', + Path(__file__).parent / f'_model_nested_events_py{ext_suffix}', +) + +def _get_import_time(): + return _model_nested_events_py._get_import_time() + +t_imported = _get_import_time() +t_modified = os.path.getmtime(__file__) +if t_imported < t_modified: + t_imp_str = datetime.datetime.fromtimestamp(t_imported).isoformat() + t_mod_str = datetime.datetime.fromtimestamp(t_modified).isoformat() + module_path = Path(__file__).resolve() + raise RuntimeError( + f'Cannot import extension for model_nested_events_py from ' + f'{module_path}, because an extension in the same location ' + f'has already been imported, but the file was modified on ' + f'disk. \\nImported at {t_imp_str}\\nModified at {t_mod_str}.\\n' + 'Import the module with a different name or restart the ' + 'Python kernel.' + ) +" +%enddef + +%module(package="model_nested_events_py",moduleimport=MODULEIMPORT) model_nested_events_py + +%pythoncode %{ +# the model-package __init__.py module (will be set during import) +_model_module = None + + +%} + +%import amici.i +// Add necessary symbols to generated header + +%{ +#include "wrapfunctions.h" +#include "amici/model_ode.h" +#include "amici/model_dae.h" +using namespace amici; +%} + +// store the time a module was imported +%{ +#include +static std::chrono::time_point _module_import_time; + +static double _get_import_time() { + auto epoch = _module_import_time.time_since_epoch(); + return std::chrono::duration(epoch).count(); +} +%} + +static double _get_import_time(); + +%init %{ + _module_import_time = std::chrono::system_clock::now(); +%} + + +// Make model module accessible from the model +%feature("pythonappend") amici::generic_model::getModel %{ + if '.' in __name__: + val.module = _model_module +%} + + +// Process symbols in header +%include "wrapfunctions.h" diff --git a/models/model_nested_events_py/sx.h b/models/model_nested_events_py/sx.h new file mode 100644 index 0000000000..2ac2b9f950 --- /dev/null +++ b/models/model_nested_events_py/sx.h @@ -0,0 +1 @@ +#define sx0 sx[0] diff --git a/models/model_nested_events_py/sx0.cpp b/models/model_nested_events_py/sx0.cpp new file mode 100644 index 0000000000..42f33faf49 --- /dev/null +++ b/models/model_nested_events_py/sx0.cpp @@ -0,0 +1,23 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" + +namespace amici { +namespace model_model_nested_events_py { + +void sx0_model_nested_events_py(realtype *sx0, const realtype t, const realtype *x, const realtype *p, const realtype *k, const int ip){ + switch(ip) { + case 0: + sx0[0] = 1; + break; + } +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/w.h b/models/model_nested_events_py/w.h new file mode 100644 index 0000000000..c399413a8c --- /dev/null +++ b/models/model_nested_events_py/w.h @@ -0,0 +1 @@ +#define flux_r0 w[0] diff --git a/models/model_nested_events_py/wrapfunctions.cpp b/models/model_nested_events_py/wrapfunctions.cpp new file mode 100644 index 0000000000..efe20805bf --- /dev/null +++ b/models/model_nested_events_py/wrapfunctions.cpp @@ -0,0 +1,16 @@ +#include "wrapfunctions.h" +#include "model_nested_events_py.h" +#include "amici/model.h" + +namespace amici { +namespace generic_model { + +std::unique_ptr getModel() { + return std::unique_ptr( + new amici::model_model_nested_events_py::Model_model_nested_events_py() + ); +} + +} // namespace generic_model + +} // namespace amici diff --git a/models/model_nested_events_py/wrapfunctions.h b/models/model_nested_events_py/wrapfunctions.h new file mode 100644 index 0000000000..33c8a9d819 --- /dev/null +++ b/models/model_nested_events_py/wrapfunctions.h @@ -0,0 +1,25 @@ +#ifndef _amici_wrapfunctions_h +#define _amici_wrapfunctions_h + +#include + +#include "amici/model.h" + +namespace amici { +namespace generic_model { + + +/** + * @brief Wrapper function to instantiate the linked Amici model without knowing + * the name at compile time. + * @return Model instance + */ +std::unique_ptr getModel(); + + +} // namespace generic_model + +} // namespace amici + + +#endif /* _amici_wrapfunctions_h */ diff --git a/models/model_nested_events_py/x.h b/models/model_nested_events_py/x.h new file mode 100644 index 0000000000..8576018467 --- /dev/null +++ b/models/model_nested_events_py/x.h @@ -0,0 +1 @@ +#define Virus x[0] diff --git a/models/model_nested_events_py/x0.cpp b/models/model_nested_events_py/x0.cpp new file mode 100644 index 0000000000..8d11b50958 --- /dev/null +++ b/models/model_nested_events_py/x0.cpp @@ -0,0 +1,18 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" + +namespace amici { +namespace model_model_nested_events_py { + +void x0_model_nested_events_py(realtype *x0, const realtype t, const realtype *p, const realtype *k){ + x0[0] = V_0; +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/xB.h b/models/model_nested_events_py/xB.h new file mode 100644 index 0000000000..0d7f8972c7 --- /dev/null +++ b/models/model_nested_events_py/xB.h @@ -0,0 +1 @@ +#define xB0 xB[0] diff --git a/models/model_nested_events_py/x_old.h b/models/model_nested_events_py/x_old.h new file mode 100644 index 0000000000..402ee142c8 --- /dev/null +++ b/models/model_nested_events_py/x_old.h @@ -0,0 +1 @@ +#define x_old0 x_old[0] diff --git a/models/model_nested_events_py/x_rdata.cpp b/models/model_nested_events_py/x_rdata.cpp new file mode 100644 index 0000000000..500204be9b --- /dev/null +++ b/models/model_nested_events_py/x_rdata.cpp @@ -0,0 +1,19 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" + +namespace amici { +namespace model_model_nested_events_py { + +void x_rdata_model_nested_events_py(realtype *x_rdata, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k){ + x_rdata[0] = Virus; +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/x_rdata.h b/models/model_nested_events_py/x_rdata.h new file mode 100644 index 0000000000..4625eb695e --- /dev/null +++ b/models/model_nested_events_py/x_rdata.h @@ -0,0 +1 @@ +#define Virus x_rdata[0] diff --git a/models/model_nested_events_py/x_solver.cpp b/models/model_nested_events_py/x_solver.cpp new file mode 100644 index 0000000000..f93180c063 --- /dev/null +++ b/models/model_nested_events_py/x_solver.cpp @@ -0,0 +1,18 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x_rdata.h" + +namespace amici { +namespace model_model_nested_events_py { + +void x_solver_model_nested_events_py(realtype *x_solver, const realtype *x_rdata){ + x_solver[0] = Virus; +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/x_solver.h b/models/model_nested_events_py/x_solver.h new file mode 100644 index 0000000000..e942494ff4 --- /dev/null +++ b/models/model_nested_events_py/x_solver.h @@ -0,0 +1 @@ +#define x_solver0 x_solver[0] diff --git a/models/model_nested_events_py/xdot.cpp b/models/model_nested_events_py/xdot.cpp new file mode 100644 index 0000000000..aa0a5bbbc1 --- /dev/null +++ b/models/model_nested_events_py/xdot.cpp @@ -0,0 +1,22 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" +#include "w.h" +#include "xdot.h" + +namespace amici { +namespace model_model_nested_events_py { + +void xdot_model_nested_events_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + dVirusdt = Heaviside_1*Virus*rho_V - Virus*delta_V; // xdot[0] +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/xdot.h b/models/model_nested_events_py/xdot.h new file mode 100644 index 0000000000..2972496f33 --- /dev/null +++ b/models/model_nested_events_py/xdot.h @@ -0,0 +1 @@ +#define dVirusdt xdot[0] diff --git a/models/model_nested_events_py/xdot_old.h b/models/model_nested_events_py/xdot_old.h new file mode 100644 index 0000000000..1aa6101f6e --- /dev/null +++ b/models/model_nested_events_py/xdot_old.h @@ -0,0 +1 @@ +#define xdot_old0 xdot_old[0] diff --git a/models/model_nested_events_py/y.cpp b/models/model_nested_events_py/y.cpp new file mode 100644 index 0000000000..1b359b5ab1 --- /dev/null +++ b/models/model_nested_events_py/y.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "h.h" + +namespace amici { +namespace model_model_nested_events_py { + +void y_model_nested_events_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + y[0] = Virus; +} + +} // namespace model_model_nested_events_py +} // namespace amici diff --git a/models/model_nested_events_py/y.h b/models/model_nested_events_py/y.h new file mode 100644 index 0000000000..e4649f8b44 --- /dev/null +++ b/models/model_nested_events_py/y.h @@ -0,0 +1 @@ +#define obs_Virus y[0] diff --git a/models/model_neuron_py/.gitignore b/models/model_neuron_py/.gitignore new file mode 100644 index 0000000000..fa29cdfff9 --- /dev/null +++ b/models/model_neuron_py/.gitignore @@ -0,0 +1 @@ +** \ No newline at end of file diff --git a/models/model_neuron_py/CMakeLists.txt b/models/model_neuron_py/CMakeLists.txt new file mode 100644 index 0000000000..290fb965f6 --- /dev/null +++ b/models/model_neuron_py/CMakeLists.txt @@ -0,0 +1,169 @@ +# Build AMICI model +cmake_minimum_required(VERSION 3.22) +cmake_policy(VERSION 3.22...3.31) + +project(model_neuron_py) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +include(CheckCXXCompilerFlag) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() +foreach(flag ${MY_CXX_FLAGS}) + unset(CUR_FLAG_SUPPORTED CACHE) + check_cxx_compiler_flag(${flag} CUR_FLAG_SUPPORTED) + if(${CUR_FLAG_SUPPORTED}) + string(APPEND CMAKE_CXX_FLAGS " ${flag}") + endif() +endforeach() + +if(DEFINED ENV{AMICI_CXXFLAGS}) + message(STATUS "Appending flags from AMICI_CXXFLAGS: $ENV{AMICI_CXXFLAGS}") + add_compile_options("$ENV{AMICI_CXXFLAGS}") +endif() +if(DEFINED ENV{AMICI_LDFLAGS}) + message(STATUS "Appending flags from AMICI_LDFLAGS: $ENV{AMICI_LDFLAGS}") + link_libraries("$ENV{AMICI_LDFLAGS}") +endif() + +find_package(Amici 0.33.0 REQUIRED HINTS + ${CMAKE_CURRENT_LIST_DIR}/../../build) +message(STATUS "Found AMICI ${Amici_DIR}") +set_target_properties(Upstream::amici PROPERTIES + MAP_IMPORTED_CONFIG_RELWITHDEBINFO RelWithDebInfo;Release; + MAP_IMPORTED_CONFIG_RELEASE Release + MAP_IMPORTED_CONFIG_DEBUG Debug;RelWithDebInfo;) + +# Debug build? +if("$ENV{ENABLE_AMICI_DEBUGGING}" OR "$ENV{ENABLE_GCOV_COVERAGE}") + add_compile_options(-UNDEBUG) + if(MSVC) + add_compile_options(-DEBUG) + else() + add_compile_options(-O0 -g) + endif() +endif() + +# coverage options +if($ENV{ENABLE_GCOV_COVERAGE}) + string(APPEND CMAKE_CXX_FLAGS_DEBUG " --coverage") + string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " --coverage") +endif() + +set(MODEL_DIR ${CMAKE_CURRENT_LIST_DIR}) + +set(SRC_LIST_LIB Jrz.cpp +Jy.cpp +Jy.h +Jz.cpp +create_splines.cpp +dJrzdsigma.cpp +dJrzdz.cpp +dJydsigma.cpp +dJydy.cpp +dJydy.h +dJzdsigma.cpp +dJzdz.cpp +deltaqB.cpp +deltasx.cpp +deltax.cpp +deltaxB.cpp +drzdx.cpp +dxdotdp_explicit.cpp +dxdotdp_explicit.h +dxdotdx_explicit.cpp +dxdotdx_explicit.h +dydx.cpp +dzdx.cpp +h.h +k.h +model_neuron_py.cpp +model_neuron_py.h +my.h +mz.h +p.h +root.cpp +rz.cpp +rz.h +sigmay.cpp +sigmay.h +sigmaz.cpp +sigmaz.h +stau.cpp +stau.h +sx.h +sx0.cpp +sx0_fixedParameters.cpp +w.h +wrapfunctions.cpp +wrapfunctions.h +x.h +x0.cpp +x0_fixedParameters.cpp +xB.h +x_old.h +x_rdata.cpp +x_rdata.h +x_solver.cpp +x_solver.h +xdot.cpp +xdot.h +xdot_old.h +y.cpp +y.h +z.cpp +z.h ${MODEL_DIR}/wrapfunctions.cpp) + +add_library(${PROJECT_NAME} ${SRC_LIST_LIB}) + +# ${PROJECT_NAME} might already be "model" +if(NOT TARGET model) + add_library(model ALIAS ${PROJECT_NAME}) +endif() + +# Some special functions require boost +# +# TODO: set some flag during code generation whether the given model requires +# boost. for now, try to find it, add include directories and link against it. +# let the compiler/linker error if it is required but not found +find_package(Boost) + +target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") + +target_link_libraries( + ${PROJECT_NAME} + PUBLIC Upstream::amici + PRIVATE $<$:Boost::boost>) + +if(NOT "${AMICI_PYTHON_BUILD_EXT_ONLY}") + set(SRC_LIST_EXE main.cpp) + add_executable(simulate_${PROJECT_NAME} ${SRC_LIST_EXE}) + target_link_libraries(simulate_${PROJECT_NAME} ${PROJECT_NAME}) +endif() + +# SWIG +option(ENABLE_SWIG "Build swig/python library?" ON) +if(ENABLE_SWIG) + add_subdirectory(swig) +endif() + +# +include(GNUInstallDirs) +install( + TARGETS ${PROJECT_NAME} + EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +export( + EXPORT ${PROJECT_NAME}Targets + FILE ${PROJECT_NAME}Config.cmake + NAMESPACE Upstream::) +# diff --git a/models/model_neuron_py/Jrz.cpp b/models/model_neuron_py/Jrz.cpp new file mode 100644 index 0000000000..64031b95ef --- /dev/null +++ b/models/model_neuron_py/Jrz.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "rz.h" +#include "sigmaz.h" + +namespace amici { +namespace model_model_neuron_py { + +void Jrz_model_neuron_py(realtype *Jrz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz){ + switch(iz) { + case 0: + Jrz[0] = 0.5*std::pow(rz1, 2)/std::pow(sigma_z1, 2) + 0.5*std::log(2*amici::pi*std::pow(sigma_z1, 2)); + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/Jy.cpp b/models/model_neuron_py/Jy.cpp new file mode 100644 index 0000000000..d3ee0bd6ae --- /dev/null +++ b/models/model_neuron_py/Jy.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_neuron_py { + +void Jy_model_neuron_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_y1, 2)) + 0.5*std::pow(-my1 + y1, 2)/std::pow(sigma_y1, 2); + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/Jy.h b/models/model_neuron_py/Jy.h new file mode 100644 index 0000000000..6b49699ace --- /dev/null +++ b/models/model_neuron_py/Jy.h @@ -0,0 +1 @@ +#define Jy0 Jy[0] diff --git a/models/model_neuron_py/Jz.cpp b/models/model_neuron_py/Jz.cpp new file mode 100644 index 0000000000..cc1db09ca6 --- /dev/null +++ b/models/model_neuron_py/Jz.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "z.h" +#include "sigmaz.h" +#include "mz.h" + +namespace amici { +namespace model_model_neuron_py { + +void Jz_model_neuron_py(realtype *Jz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz){ + switch(iz) { + case 0: + Jz[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_z1, 2)) + 0.5*std::pow(-mz1 + z1, 2)/std::pow(sigma_z1, 2); + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/MANIFEST.in b/models/model_neuron_py/MANIFEST.in new file mode 100644 index 0000000000..fd78129853 --- /dev/null +++ b/models/model_neuron_py/MANIFEST.in @@ -0,0 +1,3 @@ +include *.cpp *.h +include CMakeLists.txt +recursive-include swig/ * diff --git a/models/model_neuron_py/create_splines.cpp b/models/model_neuron_py/create_splines.cpp new file mode 100644 index 0000000000..f65f4181ab --- /dev/null +++ b/models/model_neuron_py/create_splines.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "amici/splinefunctions.h" +#include +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_neuron_py { + +std::vector create_splines_model_neuron_py(const realtype *p, const realtype *k){ + return {}; +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/dJrzdsigma.cpp b/models/model_neuron_py/dJrzdsigma.cpp new file mode 100644 index 0000000000..3e2bd0d107 --- /dev/null +++ b/models/model_neuron_py/dJrzdsigma.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "rz.h" +#include "sigmaz.h" + +namespace amici { +namespace model_model_neuron_py { + +void dJrzdsigma_model_neuron_py(realtype *dJrzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz){ + switch(iz) { + case 0: + dJrzdsigma[0] = -1.0*std::pow(rz1, 2)/std::pow(sigma_z1, 3) + 1.0/sigma_z1; + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/dJrzdz.cpp b/models/model_neuron_py/dJrzdz.cpp new file mode 100644 index 0000000000..5eeba68098 --- /dev/null +++ b/models/model_neuron_py/dJrzdz.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "rz.h" +#include "sigmaz.h" + +namespace amici { +namespace model_model_neuron_py { + +void dJrzdz_model_neuron_py(realtype *dJrzdz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz){ + switch(iz) { + case 0: + dJrzdz[0] = 1.0*rz1/std::pow(sigma_z1, 2); + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/dJydsigma.cpp b/models/model_neuron_py/dJydsigma.cpp new file mode 100644 index 0000000000..88ac235767 --- /dev/null +++ b/models/model_neuron_py/dJydsigma.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_neuron_py { + +void dJydsigma_model_neuron_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydsigma[0] = 1.0/sigma_y1 - 1.0*std::pow(-my1 + y1, 2)/std::pow(sigma_y1, 3); + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/dJydy.cpp b/models/model_neuron_py/dJydy.cpp new file mode 100644 index 0000000000..87d1d946c5 --- /dev/null +++ b/models/model_neuron_py/dJydy.cpp @@ -0,0 +1,68 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_neuron_py { + +static constexpr std::array, 1> dJydy_colptrs_model_neuron_py_ = {{ + {0, 1}, +}}; + +void dJydy_colptrs_model_neuron_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexptrs(gsl::make_span(dJydy_colptrs_model_neuron_py_[index])); +} +} // namespace model_model_neuron_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_neuron_py { + +static constexpr std::array, 1> dJydy_rowvals_model_neuron_py_ = {{ + {0}, +}}; + +void dJydy_rowvals_model_neuron_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexvals(gsl::make_span(dJydy_rowvals_model_neuron_py_[index])); +} +} // namespace model_model_neuron_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" +#include "dJydy.h" + +namespace amici { +namespace model_model_neuron_py { + +void dJydy_model_neuron_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydy[0] = (-1.0*my1 + 1.0*y1)/std::pow(sigma_y1, 2); + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/dJydy.h b/models/model_neuron_py/dJydy.h new file mode 100644 index 0000000000..98c02cbb64 --- /dev/null +++ b/models/model_neuron_py/dJydy.h @@ -0,0 +1 @@ +#define dJy0_dy1 dJydy[0] diff --git a/models/model_neuron_py/dJzdsigma.cpp b/models/model_neuron_py/dJzdsigma.cpp new file mode 100644 index 0000000000..620c508f6e --- /dev/null +++ b/models/model_neuron_py/dJzdsigma.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "z.h" +#include "sigmaz.h" +#include "mz.h" + +namespace amici { +namespace model_model_neuron_py { + +void dJzdsigma_model_neuron_py(realtype *dJzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz){ + switch(iz) { + case 0: + dJzdsigma[0] = 1.0/sigma_z1 - 1.0*std::pow(-mz1 + z1, 2)/std::pow(sigma_z1, 3); + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/dJzdz.cpp b/models/model_neuron_py/dJzdz.cpp new file mode 100644 index 0000000000..dc4b732d31 --- /dev/null +++ b/models/model_neuron_py/dJzdz.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "z.h" +#include "sigmaz.h" +#include "mz.h" + +namespace amici { +namespace model_model_neuron_py { + +void dJzdz_model_neuron_py(realtype *dJzdz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const double *mz){ + switch(iz) { + case 0: + dJzdz[0] = (-1.0*mz1 + 1.0*z1)/std::pow(sigma_z1, 2); + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/deltaqB.cpp b/models/model_neuron_py/deltaqB.cpp new file mode 100644 index 0000000000..8007113821 --- /dev/null +++ b/models/model_neuron_py/deltaqB.cpp @@ -0,0 +1,36 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "xdot.h" +#include "xdot_old.h" +#include "x_old.h" +#include "xB.h" + +namespace amici { +namespace model_model_neuron_py { + +void deltaqB_model_neuron_py(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB){ + switch(ie) { + case 0: + switch(ip) { + case 2: + deltaqB[0] = -xB0; + break; + case 3: + deltaqB[0] = xB1; + break; + } + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/deltasx.cpp b/models/model_neuron_py/deltasx.cpp new file mode 100644 index 0000000000..cd07620882 --- /dev/null +++ b/models/model_neuron_py/deltasx.cpp @@ -0,0 +1,44 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "xdot.h" +#include "xdot_old.h" +#include "sx.h" +#include "stau.h" +#include "x_old.h" + +namespace amici { +namespace model_model_neuron_py { + +void deltasx_model_neuron_py(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old){ + switch(ie) { + case 0: + switch(ip) { + case 0: + case 1: + deltasx[0] = stau0*xdot_old0 + stau0*(dvdt - xdot_old0) - sx0; + deltasx[1] = stau0*(dudt - xdot_old1); + break; + case 2: + deltasx[0] = stau0*xdot_old0 + stau0*(dvdt - xdot_old0) - sx0 - 1; + deltasx[1] = stau0*(dudt - xdot_old1); + break; + case 3: + deltasx[0] = stau0*xdot_old0 + stau0*(dvdt - xdot_old0) - sx0; + deltasx[1] = stau0*(dudt - xdot_old1) + 1; + break; + } + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/deltax.cpp b/models/model_neuron_py/deltax.cpp new file mode 100644 index 0000000000..461df2ed1b --- /dev/null +++ b/models/model_neuron_py/deltax.cpp @@ -0,0 +1,28 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "xdot.h" +#include "x_old.h" + +namespace amici { +namespace model_model_neuron_py { + +void deltax_model_neuron_py(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old){ + switch(ie) { + case 0: + deltax[0] = -c - v; + deltax[1] = d - u + x_old1; + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/deltaxB.cpp b/models/model_neuron_py/deltaxB.cpp new file mode 100644 index 0000000000..81bceeca84 --- /dev/null +++ b/models/model_neuron_py/deltaxB.cpp @@ -0,0 +1,29 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "xdot.h" +#include "xdot_old.h" +#include "x_old.h" +#include "xB.h" + +namespace amici { +namespace model_model_neuron_py { + +void deltaxB_model_neuron_py(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl){ + switch(ie) { + case 0: + deltaxB[0] = xB0*(xdot_old0/(I0 - u + (1.0/25.0)*std::pow(v, 2) + 5*v + 140) + (dvdt - xdot_old0)/(I0 - u + (1.0/25.0)*std::pow(v, 2) + 5*v + 140) - 1) + xB1*(dudt - xdot_old1)/(I0 - u + (1.0/25.0)*std::pow(v, 2) + 5*v + 140); + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/drzdx.cpp b/models/model_neuron_py/drzdx.cpp new file mode 100644 index 0000000000..6b63baeace --- /dev/null +++ b/models/model_neuron_py/drzdx.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" + +namespace amici { +namespace model_model_neuron_py { + +void drzdx_model_neuron_py(realtype *drzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h){ + switch(ie) { + case 0: + drzdx[0] = 1; + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/dxdotdp_explicit.cpp b/models/model_neuron_py/dxdotdp_explicit.cpp new file mode 100644 index 0000000000..48a6bcff9a --- /dev/null +++ b/models/model_neuron_py/dxdotdp_explicit.cpp @@ -0,0 +1,65 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_neuron_py { + +static constexpr std::array dxdotdp_explicit_colptrs_model_neuron_py_ = { + 0, 1, 2, 2, 2 +}; + +void dxdotdp_explicit_colptrs_model_neuron_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexptrs(gsl::make_span(dxdotdp_explicit_colptrs_model_neuron_py_)); +} +} // namespace model_model_neuron_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_neuron_py { + +static constexpr std::array dxdotdp_explicit_rowvals_model_neuron_py_ = { + 1, 1 +}; + +void dxdotdp_explicit_rowvals_model_neuron_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexvals(gsl::make_span(dxdotdp_explicit_rowvals_model_neuron_py_)); +} +} // namespace model_model_neuron_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "w.h" +#include "dxdotdp_explicit.h" + +namespace amici { +namespace model_model_neuron_py { + +void dxdotdp_explicit_model_neuron_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + ddudt_da = b*v - u; // dxdotdp_explicit[0] + ddudt_db = a*v; // dxdotdp_explicit[1] +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/dxdotdp_explicit.h b/models/model_neuron_py/dxdotdp_explicit.h new file mode 100644 index 0000000000..1166f6a1f1 --- /dev/null +++ b/models/model_neuron_py/dxdotdp_explicit.h @@ -0,0 +1,2 @@ +#define ddudt_da dxdotdp_explicit[0] +#define ddudt_db dxdotdp_explicit[1] diff --git a/models/model_neuron_py/dxdotdx_explicit.cpp b/models/model_neuron_py/dxdotdx_explicit.cpp new file mode 100644 index 0000000000..57c42b2eaf --- /dev/null +++ b/models/model_neuron_py/dxdotdx_explicit.cpp @@ -0,0 +1,67 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_neuron_py { + +static constexpr std::array dxdotdx_explicit_colptrs_model_neuron_py_ = { + 0, 2, 4 +}; + +void dxdotdx_explicit_colptrs_model_neuron_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexptrs(gsl::make_span(dxdotdx_explicit_colptrs_model_neuron_py_)); +} +} // namespace model_model_neuron_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_neuron_py { + +static constexpr std::array dxdotdx_explicit_rowvals_model_neuron_py_ = { + 0, 1, 0, 1 +}; + +void dxdotdx_explicit_rowvals_model_neuron_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexvals(gsl::make_span(dxdotdx_explicit_rowvals_model_neuron_py_)); +} +} // namespace model_model_neuron_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "w.h" +#include "dxdotdx_explicit.h" + +namespace amici { +namespace model_model_neuron_py { + +void dxdotdx_explicit_model_neuron_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + ddvdt_dv = (2.0/25.0)*v + 5; // dxdotdx_explicit[0] + ddudt_dv = a*b; // dxdotdx_explicit[1] + ddvdt_du = -1; // dxdotdx_explicit[2] + ddudt_du = -a; // dxdotdx_explicit[3] +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/dxdotdx_explicit.h b/models/model_neuron_py/dxdotdx_explicit.h new file mode 100644 index 0000000000..775c273a44 --- /dev/null +++ b/models/model_neuron_py/dxdotdx_explicit.h @@ -0,0 +1,4 @@ +#define ddvdt_dv dxdotdx_explicit[0] +#define ddudt_dv dxdotdx_explicit[1] +#define ddvdt_du dxdotdx_explicit[2] +#define ddudt_du dxdotdx_explicit[3] diff --git a/models/model_neuron_py/dydx.cpp b/models/model_neuron_py/dydx.cpp new file mode 100644 index 0000000000..d45d84f0bb --- /dev/null +++ b/models/model_neuron_py/dydx.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" + +namespace amici { +namespace model_model_neuron_py { + +void dydx_model_neuron_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx){ + dydx[0] = 1; +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/dzdx.cpp b/models/model_neuron_py/dzdx.cpp new file mode 100644 index 0000000000..d9e2ab9039 --- /dev/null +++ b/models/model_neuron_py/dzdx.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" + +namespace amici { +namespace model_model_neuron_py { + +void dzdx_model_neuron_py(realtype *dzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h){ + switch(ie) { + case 0: + dzdx[0] = -1/(I0 - u + (1.0/25.0)*std::pow(v, 2) + 5*v + 140); + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/h.h b/models/model_neuron_py/h.h new file mode 100644 index 0000000000..4ac34b426d --- /dev/null +++ b/models/model_neuron_py/h.h @@ -0,0 +1 @@ +#define event_1 h[0] diff --git a/models/model_neuron_py/k.h b/models/model_neuron_py/k.h new file mode 100644 index 0000000000..a2c4fa7c72 --- /dev/null +++ b/models/model_neuron_py/k.h @@ -0,0 +1,2 @@ +#define v0 k[0] +#define I0 k[1] diff --git a/models/model_neuron_py/main.cpp b/models/model_neuron_py/main.cpp new file mode 100644 index 0000000000..ecdff85a46 --- /dev/null +++ b/models/model_neuron_py/main.cpp @@ -0,0 +1,93 @@ +#include + +#include "wrapfunctions.h" /* model-provided functions */ +#include /* AMICI base functions */ + +template +std::ostream& operator<<(std::ostream& os, std::vector const& v) { + os << "["; + for (typename std::vector::const_iterator ii = v.begin(); ii != v.end(); + ++ii) { + os << " " << *ii; + } + os << "]"; + return os; +} + +/* + * This is a scaffold for a stand-alone AMICI simulation executable + * demonstrating the basic use of the AMICI C++ API. + */ + +int main() { + std::cout << "********************************" << std::endl; + std::cout << "** Running forward simulation **" << std::endl; + std::cout << "********************************" << std::endl << std::endl; + + // Create a model instance + auto model = amici::generic_model::getModel(); + + // Set desired output timepoints + model->setTimepoints({0.0, 1.0, 10.0, 100.0, 1000.0}); + + // Create a solver instance + auto solver = model->getSolver(); + + // Optionally set integration tolerance + solver->setAbsoluteTolerance(1e-16); + solver->setRelativeTolerance(1e-8); + + // Run the simulation using default parameters set during model import + // (can be changed using model->setParameters() or model->setParameterBy*()) + auto rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print observable time course + auto observable_ids = model->getObservableIds(); + std::cout << "Simulated observables for timepoints " << rdata->ts << "\n\n"; + for (int i_observable = 0; i_observable < rdata->ny; ++i_observable) { + std::cout << observable_ids[i_observable] << ":\n\t"; + for (int i_time = 0; i_time < rdata->nt; ++i_time) { + // rdata->y is a flat 2D array in row-major ordering + std::cout << rdata->y[i_time * rdata->ny + i_observable] << " "; + } + std::cout << std::endl << std::endl; + } + + std::cout << std::endl; + std::cout << "**********************************" << std::endl; + std::cout << "** Forward sensitivity analysis **" << std::endl; + std::cout << "**********************************" << std::endl << std::endl; + + // Enable first-order sensitivity analysis + solver->setSensitivityOrder(amici::SensitivityOrder::first); + // Use forward sensitivities + solver->setSensitivityMethod(amici::SensitivityMethod::forward); + + // Run the simulation + rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print state sensitivities sx... + // ... for the first timepoint... + int i_time = 0; + // ... with respect to the first parameter + int i_nplist = 0; + + // get identifiers from model + auto state_ids = model->getStateIds(); + auto parameter_ids = model->getParameterIds(); + + std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] + << std::endl; // nt x nplist x nx + for (int i_state = 0; i_state < rdata->nx; ++i_state) { + std::cout << "\td(" << state_ids[i_state] << ")/d(" + << parameter_ids[model->plist(i_nplist)] << ") = "; + + // rdata->sx is a flat 3D array in row-major ordering + std::cout << rdata->sx + [i_time * rdata->nplist * rdata->nx + + i_nplist * rdata->nx + i_state]; + std::cout << std::endl; + } + + return 0; +} diff --git a/models/model_neuron_py/model_neuron_py.cpp b/models/model_neuron_py/model_neuron_py.cpp new file mode 100644 index 0000000000..64312c9884 --- /dev/null +++ b/models/model_neuron_py/model_neuron_py.cpp @@ -0,0 +1,72 @@ +#include +#include + +namespace amici { + +namespace model_model_neuron_py { + +// clang-format off + +std::array parameterNames = { + "a", // p[0] +"b", // p[1] +"c", // p[2] +"d", // p[3] +}; + +std::array fixedParameterNames = { + "v0", // k[0] +"I0", // k[1] +}; + +std::array stateNames = { + "v", // x_rdata[0] +"u", // x_rdata[1] +}; + +std::array observableNames = { + "v", // y[0] +}; + +std::array observableScalings = { + ObservableScaling::lin, // y[0] +}; + +std::array expressionNames = { + "flux_r0", // w[0] +}; + +std::array parameterIds = { + "a", // p[0] +"b", // p[1] +"c", // p[2] +"d", // p[3] +}; + +std::array fixedParameterIds = { + "v0", // k[0] +"I0", // k[1] +}; + +std::array stateIds = { + "v", // x_rdata[0] +"u", // x_rdata[1] +}; + +std::array observableIds = { + "y1", // y[0] +}; + +std::array expressionIds = { + "flux_r0", // w[0] +}; + +std::array stateIdxsSolver = { + 0, 1 +}; + +// clang-format on + +} // namespace model_model_neuron_py + +} // namespace amici diff --git a/models/model_neuron_py/model_neuron_py.h b/models/model_neuron_py/model_neuron_py.h new file mode 100644 index 0000000000..143f5de248 --- /dev/null +++ b/models/model_neuron_py/model_neuron_py.h @@ -0,0 +1,593 @@ +#ifndef _amici_TPL_MODELNAME_h +#define _amici_TPL_MODELNAME_h +#include +#include +#include + +#include "amici/model_ode.h" +#include "amici/splinefunctions.h" +#include "amici/event.h" + +namespace amici { + +class Solver; + +namespace model_model_neuron_py { + +extern std::array parameterNames; +extern std::array fixedParameterNames; +extern std::array stateNames; +extern std::array observableNames; +extern std::array observableScalings; +extern std::array expressionNames; +extern std::array parameterIds; +extern std::array fixedParameterIds; +extern std::array stateIds; +extern std::array observableIds; +extern std::array expressionIds; +extern std::array stateIdxsSolver; + +extern void Jy_model_neuron_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydsigma_model_neuron_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_model_neuron_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_colptrs_model_neuron_py(SUNMatrixWrapper &colptrs, int index); +extern void dJydy_rowvals_model_neuron_py(SUNMatrixWrapper &rowvals, int index); +extern void Jz_model_neuron_py(realtype *Jz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz); +extern void dJzdsigma_model_neuron_py(realtype *dJzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz); +extern void dJzdz_model_neuron_py(realtype *dJzdz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const double *mz); +extern void Jrz_model_neuron_py(realtype *Jrz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz); +extern void dJrzdsigma_model_neuron_py(realtype *dJrzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz); +extern void dJrzdz_model_neuron_py(realtype *dJrzdz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz); +extern void root_model_neuron_py(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl); + + + + + + + + + + + + +extern void dxdotdp_explicit_model_neuron_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void dxdotdp_explicit_colptrs_model_neuron_py(SUNMatrixWrapper &colptrs); +extern void dxdotdp_explicit_rowvals_model_neuron_py(SUNMatrixWrapper &rowvals); +extern void dxdotdx_explicit_model_neuron_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void dxdotdx_explicit_colptrs_model_neuron_py(SUNMatrixWrapper &colptrs); +extern void dxdotdx_explicit_rowvals_model_neuron_py(SUNMatrixWrapper &rowvals); +extern void dydx_model_neuron_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx); + +extern void dzdx_model_neuron_py(realtype *dzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h); + +extern void drzdx_model_neuron_py(realtype *drzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h); + +extern void sigmay_model_neuron_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y); +extern void sigmaz_model_neuron_py(realtype *sigmaz, const realtype t, const realtype *p, const realtype *k); + + + + +extern void x0_model_neuron_py(realtype *x0, const realtype t, const realtype *p, const realtype *k); +extern void x0_fixedParameters_model_neuron_py(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs); +extern void sx0_model_neuron_py(realtype *sx0, const realtype t, const realtype *x, const realtype *p, const realtype *k, const int ip); +extern void sx0_fixedParameters_model_neuron_py(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs); +extern void xdot_model_neuron_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void y_model_neuron_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void z_model_neuron_py(realtype *z, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h); +extern void rz_model_neuron_py(realtype *rz, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h); +extern void stau_model_neuron_py(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie); +extern void deltax_model_neuron_py(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old); +extern void deltasx_model_neuron_py(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old); +extern void deltaxB_model_neuron_py(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl); +extern void deltaqB_model_neuron_py(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB); + +extern void x_solver_model_neuron_py(realtype *x_solver, const realtype *x_rdata); + + + + + + + + + + + + +extern std::vector create_splines_model_neuron_py(const realtype *p, const realtype *k); + + + +/** + * @brief AMICI-generated model subclass. + */ +class Model_model_neuron_py : public amici::Model_ODE { + public: + /** + * @brief Default constructor. + */ + Model_model_neuron_py() + : amici::Model_ODE( + amici::ModelDimensions( + 2, // nx_rdata + 2, // nxtrue_rdata + 2, // nx_solver + 2, // nxtrue_solver + 0, // nx_solver_reinit + 4, // np + 2, // nk + 1, // ny + 1, // nytrue + 1, // nz + 1, // nztrue + 1, // nevent + 1, // nevent_solver + 0, // nspl + 1, // nobjective + 1, // nw + 0, // ndwdx + 0, // ndwdp + 0, // ndwdw + 0, // ndxdotdw + std::vector{1}, // ndjydy + 0, // ndxrdatadxsolver + 0, // ndxrdatadtcl + 0, // ndtotal_cldx_rdata + 0, // nnz + 2, // ubw + 2, // lbw + true, // pythonGenerated + 2, // ndxdotdp_explicit + 4, // ndxdotdx_explicit + 0 // w_recursion_depth + ), + amici::SimulationParameters( + std::vector{-60.0, 10.0}, // fixedParameters + std::vector{0.02, 0.29999999999999999, 65.0, 0.90000000000000002} // dynamic parameters + ), + amici::SecondOrderMode::none, // o2mode + std::vector{1.0, 1.0}, // idlist + std::vector{1}, // z2events + std::vector{ + Event("event_1", false, true, NAN) + }, // events + {} // state-independent events + ) { + } + + /** + * @brief Clone this model instance. + * @return A deep copy of this instance. + */ + amici::Model *clone() const override { + return new Model_model_neuron_py(*this); + } + + void fJrz(realtype *Jrz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override { + Jrz_model_neuron_py(Jrz, iz, p, k, rz, sigmaz); + } + + + void fJy(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + Jy_model_neuron_py(Jy, iy, p, k, y, sigmay, my); + } + + + void fJz(realtype *Jz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override { + Jz_model_neuron_py(Jz, iz, p, k, z, sigmaz, mz); + } + + + void fdJrzdsigma(realtype *dJrzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override { + dJrzdsigma_model_neuron_py(dJrzdsigma, iz, p, k, rz, sigmaz); + } + + + void fdJrzdz(realtype *dJrzdz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override { + dJrzdz_model_neuron_py(dJrzdz, iz, p, k, rz, sigmaz); + } + + + void fdJydsigma(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydsigma_model_neuron_py(dJydsigma, iy, p, k, y, sigmay, my); + } + + + void fdJzdsigma(realtype *dJzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override { + dJzdsigma_model_neuron_py(dJzdsigma, iz, p, k, z, sigmaz, mz); + } + + + void fdJzdz(realtype *dJzdz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const double *mz) override { + dJzdz_model_neuron_py(dJzdz, iz, p, k, z, sigmaz, mz); + } + + + void fdeltax(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old) override { + deltax_model_neuron_py(deltax, t, x, p, k, h, ie, xdot, xdot_old, x_old); + } + + + void fdeltasx(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old) override { + deltasx_model_neuron_py(deltasx, t, x, p, k, h, w, ip, ie, xdot, xdot_old, sx, stau, tcl, x_old); + } + + + void fdeltaxB(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl) override { + deltaxB_model_neuron_py(deltaxB, t, x, p, k, h, dx, ie, xdot, xdot_old, x_old, xB, tcl); + } + + + void fdeltaqB(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB) override { + deltaqB_model_neuron_py(deltaqB, t, x, p, k, h, dx, ip, ie, xdot, xdot_old, x_old, xB); + } + + + void fdrzdp(realtype *drzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdrzdx(realtype *drzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override { + drzdx_model_neuron_py(drzdx, ie, t, x, p, k, h); + } + + + void fdsigmaydp(realtype *dsigmaydp, const realtype t, const realtype *p, const realtype *k, const realtype *y, const int ip) override {} + + + void fdsigmaydy(realtype *dsigmaydy, const realtype t, const realtype *p, const realtype *k, const realtype *y) override {} + + + void fdsigmazdp(realtype *dsigmazdp, const realtype t, const realtype *p, const realtype *k, const int ip) override {} + + + void fdJydy(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydy_model_neuron_py(dJydy, iy, p, k, y, sigmay, my); + } + + void fdJydy_colptrs(SUNMatrixWrapper &colptrs, int index) override { + dJydy_colptrs_model_neuron_py(colptrs, index); + } + + void fdJydy_rowvals(SUNMatrixWrapper &rowvals, int index) override { + dJydy_rowvals_model_neuron_py(rowvals, index); + } + + + std::vector fcreate_splines(const realtype *p, const realtype *k) override { + return create_splines_model_neuron_py(p, k); + } + + void fdspline_valuesdp(realtype *dspline_valuesdp, const realtype *p, const realtype *k, const int ip) override {} + + void fdspline_slopesdp(realtype *dspline_slopesdp, const realtype *p, const realtype *k, const int ip) override {} + + + void fdwdp(realtype *dwdp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl, bool include_static) override {} + + void fdwdp_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdp_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdx(realtype *dwdx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *spl, bool include_static) override {} + + void fdwdx_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdx_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdw(realtype *dwdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, bool include_static) override {} + + void fdwdw_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdw_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdw(realtype *dxdotdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override {} + + void fdxdotdw_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdxdotdw_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdp_explicit(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + dxdotdp_explicit_model_neuron_py(dxdotdp_explicit, t, x, p, k, h, w); + } + + void fdxdotdp_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdp_explicit_colptrs_model_neuron_py(colptrs); + } + + void fdxdotdp_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdp_explicit_rowvals_model_neuron_py(rowvals); + } + + + void fdxdotdx_explicit(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + dxdotdx_explicit_model_neuron_py(dxdotdx_explicit, t, x, p, k, h, w); + } + + void fdxdotdx_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdx_explicit_colptrs_model_neuron_py(colptrs); + } + + void fdxdotdx_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdx_explicit_rowvals_model_neuron_py(rowvals); + } + + + void fdydx(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { + dydx_model_neuron_py(dydx, t, x, p, k, h, w, dwdx); + } + + + void fdydp(realtype *dydp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl) override {} + + + void fdzdp(realtype *dzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdzdx(realtype *dzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override { + dzdx_model_neuron_py(dzdx, ie, t, x, p, k, h); + } + + + void froot(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl) override { + root_model_neuron_py(root, t, x, p, k, h, tcl); + } + + + void frz(realtype *rz, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override { + rz_model_neuron_py(rz, ie, t, x, p, k, h); + } + + + void fsigmay(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y) override { + sigmay_model_neuron_py(sigmay, t, p, k, y); + } + + + void fsigmaz(realtype *sigmaz, const realtype t, const realtype *p, const realtype *k) override { + sigmaz_model_neuron_py(sigmaz, t, p, k); + } + + + void fstau(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie) override { + stau_model_neuron_py(stau, t, x, p, k, h, dx, tcl, sx, ip, ie); + } + + void fsx0(realtype *sx0, const realtype t, const realtype *x, const realtype *p, const realtype *k, const int ip) override { + sx0_model_neuron_py(sx0, t, x, p, k, ip); + } + + void fsx0_fixedParameters(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs) override { + sx0_fixedParameters_model_neuron_py(sx0_fixedParameters, t, x0, p, k, ip, reinitialization_state_idxs); + } + + + void fw(realtype *w, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl, const realtype *spl, bool include_static) override {} + + + void fx0(realtype *x0, const realtype t, const realtype *p, const realtype *k) override { + x0_model_neuron_py(x0, t, p, k); + } + + + void fx0_fixedParameters(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs) override { + x0_fixedParameters_model_neuron_py(x0_fixedParameters, t, p, k, reinitialization_state_idxs); + } + + + void fxdot(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + xdot_model_neuron_py(xdot, t, x, p, k, h, w); + } + + + void fy(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + y_model_neuron_py(y, t, x, p, k, h, w); + } + + + void fz(realtype *z, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override { + z_model_neuron_py(z, ie, t, x, p, k, h); + } + + + + + void fx_solver(realtype *x_solver, const realtype *x_rdata) override { + x_solver_model_neuron_py(x_solver, x_rdata); + } + + + void ftotal_cl(realtype *total_cl, const realtype *x_rdata, const realtype *p, const realtype *k) override {} + + + void fdx_rdatadx_solver(realtype *dx_rdatadx_solver, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadx_solver_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadx_solver_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdx_rdatadp(realtype *dx_rdatadp, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k, const int ip) override {} + + + void fdx_rdatadtcl(realtype *dx_rdatadtcl, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadtcl_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadtcl_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdtotal_cldp(realtype *dtotal_cldp, const realtype *x_rdata, const realtype *p, const realtype *k, const int ip) override {} + + + void fdtotal_cldx_rdata(realtype *dtotal_cldx_rdata, const realtype *x_rdata, const realtype *p, const realtype *k, const realtype *tcl) override {} + + void fdtotal_cldx_rdata_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdtotal_cldx_rdata_rowvals(SUNMatrixWrapper &rowvals) override {} + + + std::string getName() const override { + return "model_neuron_py"; + } + + /** + * @brief Get names of the model parameters + * @return the names + */ + std::vector getParameterNames() const override { + return std::vector(parameterNames.begin(), + parameterNames.end()); + } + + /** + * @brief Get names of the model states + * @return the names + */ + std::vector getStateNames() const override { + return std::vector(stateNames.begin(), stateNames.end()); + } + + /** + * @brief Get names of the solver states + * @return the names + */ + std::vector getStateNamesSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto const idx: stateIdxsSolver) { + result.push_back(stateNames[idx]); + } + return result; + } + + /** + * @brief Get names of the fixed model parameters + * @return the names + */ + std::vector getFixedParameterNames() const override { + return std::vector(fixedParameterNames.begin(), + fixedParameterNames.end()); + } + + /** + * @brief Get names of the observables + * @return the names + */ + std::vector getObservableNames() const override { + return std::vector(observableNames.begin(), + observableNames.end()); + } + + /** + * @brief Get names of model expressions + * @return Expression names + */ + std::vector getExpressionNames() const override { + return std::vector(expressionNames.begin(), + expressionNames.end()); + } + + /** + * @brief Get ids of the model parameters + * @return the ids + */ + std::vector getParameterIds() const override { + return std::vector(parameterIds.begin(), + parameterIds.end()); + } + + /** + * @brief Get ids of the model states + * @return the ids + */ + std::vector getStateIds() const override { + return std::vector(stateIds.begin(), stateIds.end()); + } + + /** + * @brief Get ids of the solver states + * @return the ids + */ + std::vector getStateIdsSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto idx: stateIdxsSolver) { + result.push_back(stateIds[idx]); + } + return result; + } + + /** + * @brief Get ids of the fixed model parameters + * @return the ids + */ + std::vector getFixedParameterIds() const override { + return std::vector(fixedParameterIds.begin(), + fixedParameterIds.end()); + } + + /** + * @brief Get ids of the observables + * @return the ids + */ + std::vector getObservableIds() const override { + return std::vector(observableIds.begin(), + observableIds.end()); + } + + /** + * @brief Get IDs of model expressions + * @return Expression IDs + */ + std::vector getExpressionIds() const override { + return std::vector(expressionIds.begin(), + expressionIds.end()); + } + + /** + * @brief function indicating whether reinitialization of states depending + * on fixed parameters is permissible + * @return flag indicating whether reinitialization of states depending on + * fixed parameters is permissible + */ + bool isFixedParameterStateReinitializationAllowed() const override { + return true; + } + + /** + * @brief returns the AMICI version that was used to generate the model + * @return AMICI version string + */ + std::string getAmiciVersion() const override { + return "0.33.0"; + } + + /** + * @brief returns the amici version that was used to generate the model + * @return AMICI git commit hash + */ + std::string getAmiciCommit() const override { + return "bcedb951ddf674996b269489d74f9b86112038ff"; + } + + bool hasQuadraticLLH() const override { + return true; + } + + ObservableScaling getObservableScaling(int iy) const override { + return observableScalings.at(iy); + } +}; + + +} // namespace model_model_neuron_py + +} // namespace amici + +#endif /* _amici_TPL_MODELNAME_h */ diff --git a/models/model_neuron_py/my.h b/models/model_neuron_py/my.h new file mode 100644 index 0000000000..3294c09fd3 --- /dev/null +++ b/models/model_neuron_py/my.h @@ -0,0 +1 @@ +#define my1 my[0] diff --git a/models/model_neuron_py/mz.h b/models/model_neuron_py/mz.h new file mode 100644 index 0000000000..a3b9b91953 --- /dev/null +++ b/models/model_neuron_py/mz.h @@ -0,0 +1 @@ +#define mz1 mz[0] diff --git a/models/model_neuron_py/p.h b/models/model_neuron_py/p.h new file mode 100644 index 0000000000..36a8f04b88 --- /dev/null +++ b/models/model_neuron_py/p.h @@ -0,0 +1,4 @@ +#define a p[0] +#define b p[1] +#define c p[2] +#define d p[3] diff --git a/models/model_neuron_py/root.cpp b/models/model_neuron_py/root.cpp new file mode 100644 index 0000000000..c808f3d1b7 --- /dev/null +++ b/models/model_neuron_py/root.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" + +namespace amici { +namespace model_model_neuron_py { + +void root_model_neuron_py(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl){ + root[0] = v - 30; +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/rz.cpp b/models/model_neuron_py/rz.cpp new file mode 100644 index 0000000000..e3e9c923d3 --- /dev/null +++ b/models/model_neuron_py/rz.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "rz.h" + +namespace amici { +namespace model_model_neuron_py { + +void rz_model_neuron_py(realtype *rz, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h){ + switch(ie) { + case 0: + rz[0] = v - 30; + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/rz.h b/models/model_neuron_py/rz.h new file mode 100644 index 0000000000..4f06bc519d --- /dev/null +++ b/models/model_neuron_py/rz.h @@ -0,0 +1 @@ +#define rz1 rz[0] diff --git a/models/model_neuron_py/setup.py b/models/model_neuron_py/setup.py new file mode 100644 index 0000000000..b3679e3142 --- /dev/null +++ b/models/model_neuron_py/setup.py @@ -0,0 +1,95 @@ +"""AMICI model package setup""" + +import os +import sys +from pathlib import Path + +from amici import _get_amici_path +from amici.custom_commands import AmiciBuildCMakeExtension +from cmake_build_extension import CMakeExtension +from setuptools import find_namespace_packages, setup +import importlib.metadata + + +def get_extension() -> CMakeExtension: + """Get setuptools extension object for this AMICI model package""" + + # Build shared object + prefix_path = Path(_get_amici_path()) + AmiciBuildCMakeExtension.extend_cmake_prefix_path(str(prefix_path)) + + # handle parallel building + # Note: can be empty to use all hardware threads + if (parallel_jobs := os.environ.get("AMICI_PARALLEL_COMPILE")) is not None: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = parallel_jobs + else: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = "1" + + debug_build = os.getenv("ENABLE_AMICI_DEBUGGING", "").lower() in [ + "1", + "true", + ] or os.getenv("ENABLE_GCOV_COVERAGE", "").lower() in ["1", "true"] + + cmake_prefix_path = os.getenv("CMAKE_PREFIX_PATH", "").split(os.pathsep) + cmake_prefix_path.append(prefix_path.as_posix()) + + # If scipy_openblas64 is installed, we make its cmake configuration + # available + amici_distribution = importlib.metadata.distribution("amici") + amici_dir = Path(amici_distribution.locate_file("")) + # this path is created during the amici build if scipy_openblas64 is used + openblas_cmake_dir = amici_dir / "lib" / "cmake" / "openblas" + if openblas_cmake_dir.exists(): + cmake_prefix_path.append(str(openblas_cmake_dir)) + + return CMakeExtension( + name="model_ext", + source_dir=os.getcwd(), + install_prefix="model_neuron_py", + cmake_configure_options=[ + "-DCMAKE_VERBOSE_MAKEFILE=ON", + f"-DCMAKE_PREFIX_PATH='{';'.join(cmake_prefix_path)}'", + "-DAMICI_PYTHON_BUILD_EXT_ONLY=ON", + f"-DPython3_EXECUTABLE={Path(sys.executable).as_posix()}", + ], + cmake_build_type="Debug" if debug_build else "Release", + ) + + +# Change working directory to setup.py location +os.chdir(os.path.dirname(os.path.abspath(__file__))) + +MODEL_EXT = get_extension() + +CLASSIFIERS = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Science/Research", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python", + "Programming Language :: C++", + "Topic :: Scientific/Engineering :: Bio-Informatics", +] + +CMDCLASS = { + # for CMake-based builds + "build_ext": AmiciBuildCMakeExtension, +} + +# Install +setup( + name="model_neuron_py", + cmdclass=CMDCLASS, + version="0.1.0", + description="AMICI-generated module for model model_neuron_py", + url="https://github.com/AMICI-dev/AMICI", + author="model-author-todo", + author_email="model-author-todo", + ext_modules=[MODEL_EXT], + packages=find_namespace_packages(), + install_requires=["amici==0.33.0"], + python_requires=">=3.11", + package_data={}, + zip_safe=False, + classifiers=CLASSIFIERS, +) diff --git a/models/model_neuron_py/sigmay.cpp b/models/model_neuron_py/sigmay.cpp new file mode 100644 index 0000000000..3313de1691 --- /dev/null +++ b/models/model_neuron_py/sigmay.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" + +namespace amici { +namespace model_model_neuron_py { + +void sigmay_model_neuron_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y){ + sigma_y1 = 1.0; // sigmay[0] +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/sigmay.h b/models/model_neuron_py/sigmay.h new file mode 100644 index 0000000000..3e9be142ed --- /dev/null +++ b/models/model_neuron_py/sigmay.h @@ -0,0 +1 @@ +#define sigma_y1 sigmay[0] diff --git a/models/model_neuron_py/sigmaz.cpp b/models/model_neuron_py/sigmaz.cpp new file mode 100644 index 0000000000..275c2029cb --- /dev/null +++ b/models/model_neuron_py/sigmaz.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "sigmaz.h" + +namespace amici { +namespace model_model_neuron_py { + +void sigmaz_model_neuron_py(realtype *sigmaz, const realtype t, const realtype *p, const realtype *k){ + sigma_z1 = 1.0; // sigmaz[0] +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/sigmaz.h b/models/model_neuron_py/sigmaz.h new file mode 100644 index 0000000000..75458f5705 --- /dev/null +++ b/models/model_neuron_py/sigmaz.h @@ -0,0 +1 @@ +#define sigma_z1 sigmaz[0] diff --git a/models/model_neuron_py/stau.cpp b/models/model_neuron_py/stau.cpp new file mode 100644 index 0000000000..476b4b0e7e --- /dev/null +++ b/models/model_neuron_py/stau.cpp @@ -0,0 +1,33 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "sx.h" + +namespace amici { +namespace model_model_neuron_py { + +void stau_model_neuron_py(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie){ + switch(ie) { + case 0: + switch(ip) { + case 0: + case 1: + case 2: + case 3: + stau[0] = sx0/(I0 - u + (1.0/25.0)*std::pow(v, 2) + 5*v + 140); + break; + } + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/stau.h b/models/model_neuron_py/stau.h new file mode 100644 index 0000000000..2871b2462c --- /dev/null +++ b/models/model_neuron_py/stau.h @@ -0,0 +1 @@ +#define stau0 stau[0] diff --git a/models/model_neuron_py/swig/CMakeLists.txt b/models/model_neuron_py/swig/CMakeLists.txt new file mode 100644 index 0000000000..314996c479 --- /dev/null +++ b/models/model_neuron_py/swig/CMakeLists.txt @@ -0,0 +1,60 @@ +if(DEFINED ENV{SWIG}) + set(SWIG_EXECUTABLE $ENV{SWIG}) +endif() + +find_package(SWIG REQUIRED) +include(${SWIG_USE_FILE}) + +if(DEFINED ENV{PYTHON_EXECUTABLE}) + set(Python3_EXECUTABLE $ENV{PYTHON_EXECUTABLE}) +endif() +# We don't need "Interpreter" here, but without that, FindPython3 will +# ignore the Python version selected via $Python3_EXECUTABLE +find_package(Python3 COMPONENTS Interpreter Development) +include_directories(${Python3_INCLUDE_DIRS}) + +set(SWIG_LIBRARY_NAME _${PROJECT_NAME}) +set(CMAKE_SWIG_FLAGS "") +set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) + +# swig does not use INTERFACE_INCLUDE_DIRS of linked libraries, so add manually +get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) +include_directories(${AMICI_INCLUDE_DIRS} .. ${AMICI_INCLUDE_DIRS}/../swig) + +swig_add_library(${SWIG_LIBRARY_NAME} + TYPE MODULE + LANGUAGE python + SOURCES ${PROJECT_NAME}.i) + + +set_target_properties(${SWIG_LIBRARY_NAME} + PROPERTIES + SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE + PREFIX "" +) + +# Python extension suffix +execute_process( + COMMAND ${Python3_EXECUTABLE} -c + "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))" + OUTPUT_VARIABLE PY_EXT_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE) +if(NOT "${PY_EXT_SUFFIX}" STREQUAL "") + message(STATUS "Python extension suffix is ${PY_EXT_SUFFIX}") + set_target_properties(${SWIG_LIBRARY_NAME} PROPERTIES SUFFIX "${PY_EXT_SUFFIX}" ) +endif() + + +swig_link_libraries(${SWIG_LIBRARY_NAME} + ${Python3_LIBRARIES} + model) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.py + $ DESTINATION .) + +# configure module setup script +set(SETUP_PY_IN ${Amici_DIR}/model_setup.template.py) +set(SETUP_PY_OUT ${CMAKE_CURRENT_BINARY_DIR}/setup.py) + +add_custom_target(install-python + DEPENDS ${SWIG_LIBRARY_NAME} + COMMAND python ${SETUP_PY_OUT} install) diff --git a/models/model_neuron_py/swig/model_neuron_py.i b/models/model_neuron_py/swig/model_neuron_py.i new file mode 100644 index 0000000000..9b47c96e87 --- /dev/null +++ b/models/model_neuron_py/swig/model_neuron_py.i @@ -0,0 +1,82 @@ +%define MODULEIMPORT +" +import amici +import datetime +import importlib.util +import os +import sysconfig +from pathlib import Path + +ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +_model_neuron_py = amici._module_from_path( + 'model_neuron_py._model_neuron_py' if __package__ or '.' in __name__ + else '_model_neuron_py', + Path(__file__).parent / f'_model_neuron_py{ext_suffix}', +) + +def _get_import_time(): + return _model_neuron_py._get_import_time() + +t_imported = _get_import_time() +t_modified = os.path.getmtime(__file__) +if t_imported < t_modified: + t_imp_str = datetime.datetime.fromtimestamp(t_imported).isoformat() + t_mod_str = datetime.datetime.fromtimestamp(t_modified).isoformat() + module_path = Path(__file__).resolve() + raise RuntimeError( + f'Cannot import extension for model_neuron_py from ' + f'{module_path}, because an extension in the same location ' + f'has already been imported, but the file was modified on ' + f'disk. \\nImported at {t_imp_str}\\nModified at {t_mod_str}.\\n' + 'Import the module with a different name or restart the ' + 'Python kernel.' + ) +" +%enddef + +%module(package="model_neuron_py",moduleimport=MODULEIMPORT) model_neuron_py + +%pythoncode %{ +# the model-package __init__.py module (will be set during import) +_model_module = None + + +%} + +%import amici.i +// Add necessary symbols to generated header + +%{ +#include "wrapfunctions.h" +#include "amici/model_ode.h" +#include "amici/model_dae.h" +using namespace amici; +%} + +// store the time a module was imported +%{ +#include +static std::chrono::time_point _module_import_time; + +static double _get_import_time() { + auto epoch = _module_import_time.time_since_epoch(); + return std::chrono::duration(epoch).count(); +} +%} + +static double _get_import_time(); + +%init %{ + _module_import_time = std::chrono::system_clock::now(); +%} + + +// Make model module accessible from the model +%feature("pythonappend") amici::generic_model::getModel %{ + if '.' in __name__: + val.module = _model_module +%} + + +// Process symbols in header +%include "wrapfunctions.h" diff --git a/models/model_neuron_py/sx.h b/models/model_neuron_py/sx.h new file mode 100644 index 0000000000..7381ebd50a --- /dev/null +++ b/models/model_neuron_py/sx.h @@ -0,0 +1,2 @@ +#define sx0 sx[0] +#define sx1 sx[1] diff --git a/models/model_neuron_py/sx0.cpp b/models/model_neuron_py/sx0.cpp new file mode 100644 index 0000000000..08738cfdac --- /dev/null +++ b/models/model_neuron_py/sx0.cpp @@ -0,0 +1,24 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_neuron_py { + +void sx0_model_neuron_py(realtype *sx0, const realtype t, const realtype *x, const realtype *p, const realtype *k, const int ip){ + switch(ip) { + case 1: + sx0[1] = v0; + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/sx0_fixedParameters.cpp b/models/model_neuron_py/sx0_fixedParameters.cpp new file mode 100644 index 0000000000..fed7010ed3 --- /dev/null +++ b/models/model_neuron_py/sx0_fixedParameters.cpp @@ -0,0 +1,31 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_neuron_py { + +void sx0_fixedParameters_model_neuron_py(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs){ + static const std::array _x0_fixedParameters_idxs = { + 0, 1 + }; + for(auto idx: reinitialization_state_idxs) { + if(std::find(_x0_fixedParameters_idxs.cbegin(), _x0_fixedParameters_idxs.cend(), idx) != _x0_fixedParameters_idxs.cend()) + sx0_fixedParameters[idx] = 0.0; + } + switch(ip) { + case 1: + if(std::find(reinitialization_state_idxs.cbegin(), reinitialization_state_idxs.cend(), 1) != reinitialization_state_idxs.cend()) + sx0_fixedParameters[1] = v0; + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/w.h b/models/model_neuron_py/w.h new file mode 100644 index 0000000000..c399413a8c --- /dev/null +++ b/models/model_neuron_py/w.h @@ -0,0 +1 @@ +#define flux_r0 w[0] diff --git a/models/model_neuron_py/wrapfunctions.cpp b/models/model_neuron_py/wrapfunctions.cpp new file mode 100644 index 0000000000..a963101e46 --- /dev/null +++ b/models/model_neuron_py/wrapfunctions.cpp @@ -0,0 +1,16 @@ +#include "wrapfunctions.h" +#include "model_neuron_py.h" +#include "amici/model.h" + +namespace amici { +namespace generic_model { + +std::unique_ptr getModel() { + return std::unique_ptr( + new amici::model_model_neuron_py::Model_model_neuron_py() + ); +} + +} // namespace generic_model + +} // namespace amici diff --git a/models/model_neuron_py/wrapfunctions.h b/models/model_neuron_py/wrapfunctions.h new file mode 100644 index 0000000000..33c8a9d819 --- /dev/null +++ b/models/model_neuron_py/wrapfunctions.h @@ -0,0 +1,25 @@ +#ifndef _amici_wrapfunctions_h +#define _amici_wrapfunctions_h + +#include + +#include "amici/model.h" + +namespace amici { +namespace generic_model { + + +/** + * @brief Wrapper function to instantiate the linked Amici model without knowing + * the name at compile time. + * @return Model instance + */ +std::unique_ptr getModel(); + + +} // namespace generic_model + +} // namespace amici + + +#endif /* _amici_wrapfunctions_h */ diff --git a/models/model_neuron_py/x.h b/models/model_neuron_py/x.h new file mode 100644 index 0000000000..9e09cf4a0f --- /dev/null +++ b/models/model_neuron_py/x.h @@ -0,0 +1,2 @@ +#define v x[0] +#define u x[1] diff --git a/models/model_neuron_py/x0.cpp b/models/model_neuron_py/x0.cpp new file mode 100644 index 0000000000..836677abf1 --- /dev/null +++ b/models/model_neuron_py/x0.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_neuron_py { + +void x0_model_neuron_py(realtype *x0, const realtype t, const realtype *p, const realtype *k){ + x0[0] = v0; + x0[1] = b*v0; +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/x0_fixedParameters.cpp b/models/model_neuron_py/x0_fixedParameters.cpp new file mode 100644 index 0000000000..c795601efc --- /dev/null +++ b/models/model_neuron_py/x0_fixedParameters.cpp @@ -0,0 +1,22 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_neuron_py { + +void x0_fixedParameters_model_neuron_py(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs){ + if(std::find(reinitialization_state_idxs.cbegin(), reinitialization_state_idxs.cend(), 0) != reinitialization_state_idxs.cend()) + x0_fixedParameters[0] = v0; + if(std::find(reinitialization_state_idxs.cbegin(), reinitialization_state_idxs.cend(), 1) != reinitialization_state_idxs.cend()) + x0_fixedParameters[1] = b*v0; +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/xB.h b/models/model_neuron_py/xB.h new file mode 100644 index 0000000000..21e5ffd7d9 --- /dev/null +++ b/models/model_neuron_py/xB.h @@ -0,0 +1,2 @@ +#define xB0 xB[0] +#define xB1 xB[1] diff --git a/models/model_neuron_py/x_old.h b/models/model_neuron_py/x_old.h new file mode 100644 index 0000000000..751090c25e --- /dev/null +++ b/models/model_neuron_py/x_old.h @@ -0,0 +1,2 @@ +#define x_old0 x_old[0] +#define x_old1 x_old[1] diff --git a/models/model_neuron_py/x_rdata.cpp b/models/model_neuron_py/x_rdata.cpp new file mode 100644 index 0000000000..b5a8759c8c --- /dev/null +++ b/models/model_neuron_py/x_rdata.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_neuron_py { + +void x_rdata_model_neuron_py(realtype *x_rdata, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k){ + x_rdata[0] = v; + x_rdata[1] = u; +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/x_rdata.h b/models/model_neuron_py/x_rdata.h new file mode 100644 index 0000000000..c42e217196 --- /dev/null +++ b/models/model_neuron_py/x_rdata.h @@ -0,0 +1,2 @@ +#define v x_rdata[0] +#define u x_rdata[1] diff --git a/models/model_neuron_py/x_solver.cpp b/models/model_neuron_py/x_solver.cpp new file mode 100644 index 0000000000..fbee1289f3 --- /dev/null +++ b/models/model_neuron_py/x_solver.cpp @@ -0,0 +1,19 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x_rdata.h" + +namespace amici { +namespace model_model_neuron_py { + +void x_solver_model_neuron_py(realtype *x_solver, const realtype *x_rdata){ + x_solver[0] = v; + x_solver[1] = u; +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/x_solver.h b/models/model_neuron_py/x_solver.h new file mode 100644 index 0000000000..cd21d15a1f --- /dev/null +++ b/models/model_neuron_py/x_solver.h @@ -0,0 +1,2 @@ +#define x_solver0 x_solver[0] +#define x_solver1 x_solver[1] diff --git a/models/model_neuron_py/xdot.cpp b/models/model_neuron_py/xdot.cpp new file mode 100644 index 0000000000..a13e2d900f --- /dev/null +++ b/models/model_neuron_py/xdot.cpp @@ -0,0 +1,24 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "w.h" +#include "xdot.h" + +namespace amici { +namespace model_model_neuron_py { + +void xdot_model_neuron_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + dvdt = I0 - u + (1.0/25.0)*std::pow(v, 2) + 5*v + 140; // xdot[0] + dudt = a*(b*v - u); // xdot[1] +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/xdot.h b/models/model_neuron_py/xdot.h new file mode 100644 index 0000000000..ccaa80b677 --- /dev/null +++ b/models/model_neuron_py/xdot.h @@ -0,0 +1,2 @@ +#define dvdt xdot[0] +#define dudt xdot[1] diff --git a/models/model_neuron_py/xdot_old.h b/models/model_neuron_py/xdot_old.h new file mode 100644 index 0000000000..563f911b86 --- /dev/null +++ b/models/model_neuron_py/xdot_old.h @@ -0,0 +1,2 @@ +#define xdot_old0 xdot_old[0] +#define xdot_old1 xdot_old[1] diff --git a/models/model_neuron_py/y.cpp b/models/model_neuron_py/y.cpp new file mode 100644 index 0000000000..7f07c68373 --- /dev/null +++ b/models/model_neuron_py/y.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" + +namespace amici { +namespace model_model_neuron_py { + +void y_model_neuron_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + y[0] = v; +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/y.h b/models/model_neuron_py/y.h new file mode 100644 index 0000000000..d9a40dc715 --- /dev/null +++ b/models/model_neuron_py/y.h @@ -0,0 +1 @@ +#define y1 y[0] diff --git a/models/model_neuron_py/z.cpp b/models/model_neuron_py/z.cpp new file mode 100644 index 0000000000..a5709ceaad --- /dev/null +++ b/models/model_neuron_py/z.cpp @@ -0,0 +1,26 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "h.h" +#include "z.h" + +namespace amici { +namespace model_model_neuron_py { + +void z_model_neuron_py(realtype *z, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h){ + switch(ie) { + case 0: + z[0] = t; + break; + } +} + +} // namespace model_model_neuron_py +} // namespace amici diff --git a/models/model_neuron_py/z.h b/models/model_neuron_py/z.h new file mode 100644 index 0000000000..bbebfbcea6 --- /dev/null +++ b/models/model_neuron_py/z.h @@ -0,0 +1 @@ +#define z1 z[0] diff --git a/models/model_robertson_py/.gitignore b/models/model_robertson_py/.gitignore new file mode 100644 index 0000000000..fa29cdfff9 --- /dev/null +++ b/models/model_robertson_py/.gitignore @@ -0,0 +1 @@ +** \ No newline at end of file diff --git a/models/model_robertson_py/CMakeLists.txt b/models/model_robertson_py/CMakeLists.txt new file mode 100644 index 0000000000..56cdbdf22b --- /dev/null +++ b/models/model_robertson_py/CMakeLists.txt @@ -0,0 +1,142 @@ +# Build AMICI model +cmake_minimum_required(VERSION 3.22) +cmake_policy(VERSION 3.22...3.31) + +project(model_robertson_py) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +include(CheckCXXCompilerFlag) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() +foreach(flag ${MY_CXX_FLAGS}) + unset(CUR_FLAG_SUPPORTED CACHE) + check_cxx_compiler_flag(${flag} CUR_FLAG_SUPPORTED) + if(${CUR_FLAG_SUPPORTED}) + string(APPEND CMAKE_CXX_FLAGS " ${flag}") + endif() +endforeach() + +if(DEFINED ENV{AMICI_CXXFLAGS}) + message(STATUS "Appending flags from AMICI_CXXFLAGS: $ENV{AMICI_CXXFLAGS}") + add_compile_options("$ENV{AMICI_CXXFLAGS}") +endif() +if(DEFINED ENV{AMICI_LDFLAGS}) + message(STATUS "Appending flags from AMICI_LDFLAGS: $ENV{AMICI_LDFLAGS}") + link_libraries("$ENV{AMICI_LDFLAGS}") +endif() + +find_package(Amici 0.33.0 REQUIRED HINTS + ${CMAKE_CURRENT_LIST_DIR}/../../build) +message(STATUS "Found AMICI ${Amici_DIR}") +set_target_properties(Upstream::amici PROPERTIES + MAP_IMPORTED_CONFIG_RELWITHDEBINFO RelWithDebInfo;Release; + MAP_IMPORTED_CONFIG_RELEASE Release + MAP_IMPORTED_CONFIG_DEBUG Debug;RelWithDebInfo;) + +# Debug build? +if("$ENV{ENABLE_AMICI_DEBUGGING}" OR "$ENV{ENABLE_GCOV_COVERAGE}") + add_compile_options(-UNDEBUG) + if(MSVC) + add_compile_options(-DEBUG) + else() + add_compile_options(-O0 -g) + endif() +endif() + +# coverage options +if($ENV{ENABLE_GCOV_COVERAGE}) + string(APPEND CMAKE_CXX_FLAGS_DEBUG " --coverage") + string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " --coverage") +endif() + +set(MODEL_DIR ${CMAKE_CURRENT_LIST_DIR}) + +set(SRC_LIST_LIB Jy.cpp +Jy.h +create_splines.cpp +dJydsigma.cpp +dJydy.cpp +dJydy.h +dx.h +dxdotdp_explicit.cpp +dxdotdp_explicit.h +dxdotdx_explicit.cpp +dxdotdx_explicit.h +dydx.cpp +k.h +model_robertson_py.cpp +model_robertson_py.h +my.h +p.h +sigmay.cpp +sigmay.h +sx0_fixedParameters.cpp +w.h +wrapfunctions.cpp +wrapfunctions.h +x.h +x0.cpp +x0_fixedParameters.cpp +x_rdata.cpp +x_rdata.h +x_solver.cpp +x_solver.h +xdot.cpp +xdot.h +y.cpp +y.h ${MODEL_DIR}/wrapfunctions.cpp) + +add_library(${PROJECT_NAME} ${SRC_LIST_LIB}) + +# ${PROJECT_NAME} might already be "model" +if(NOT TARGET model) + add_library(model ALIAS ${PROJECT_NAME}) +endif() + +# Some special functions require boost +# +# TODO: set some flag during code generation whether the given model requires +# boost. for now, try to find it, add include directories and link against it. +# let the compiler/linker error if it is required but not found +find_package(Boost) + +target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") + +target_link_libraries( + ${PROJECT_NAME} + PUBLIC Upstream::amici + PRIVATE $<$:Boost::boost>) + +if(NOT "${AMICI_PYTHON_BUILD_EXT_ONLY}") + set(SRC_LIST_EXE main.cpp) + add_executable(simulate_${PROJECT_NAME} ${SRC_LIST_EXE}) + target_link_libraries(simulate_${PROJECT_NAME} ${PROJECT_NAME}) +endif() + +# SWIG +option(ENABLE_SWIG "Build swig/python library?" ON) +if(ENABLE_SWIG) + add_subdirectory(swig) +endif() + +# +include(GNUInstallDirs) +install( + TARGETS ${PROJECT_NAME} + EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +export( + EXPORT ${PROJECT_NAME}Targets + FILE ${PROJECT_NAME}Config.cmake + NAMESPACE Upstream::) +# diff --git a/models/model_robertson_py/Jy.cpp b/models/model_robertson_py/Jy.cpp new file mode 100644 index 0000000000..5d1aa7edbc --- /dev/null +++ b/models/model_robertson_py/Jy.cpp @@ -0,0 +1,32 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_robertson_py { + +void Jy_model_robertson_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_x1, 2)) + 0.5*std::pow(-mobs_x1 + obs_x1, 2)/std::pow(sigma_obs_x1, 2); + break; + case 1: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_x2, 2)) + 0.5*std::pow(-mobs_x2 + obs_x2, 2)/std::pow(sigma_obs_x2, 2); + break; + case 2: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_x3, 2)) + 0.5*std::pow(-mobs_x3 + obs_x3, 2)/std::pow(sigma_obs_x3, 2); + break; + } +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/Jy.h b/models/model_robertson_py/Jy.h new file mode 100644 index 0000000000..e7751bcae0 --- /dev/null +++ b/models/model_robertson_py/Jy.h @@ -0,0 +1,3 @@ +#define Jy0 Jy[0] +#define Jy1 Jy[1] +#define Jy2 Jy[2] diff --git a/models/model_robertson_py/MANIFEST.in b/models/model_robertson_py/MANIFEST.in new file mode 100644 index 0000000000..fd78129853 --- /dev/null +++ b/models/model_robertson_py/MANIFEST.in @@ -0,0 +1,3 @@ +include *.cpp *.h +include CMakeLists.txt +recursive-include swig/ * diff --git a/models/model_robertson_py/create_splines.cpp b/models/model_robertson_py/create_splines.cpp new file mode 100644 index 0000000000..7595383a5c --- /dev/null +++ b/models/model_robertson_py/create_splines.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "amici/splinefunctions.h" +#include +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_robertson_py { + +std::vector create_splines_model_robertson_py(const realtype *p, const realtype *k){ + return {}; +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/dJydsigma.cpp b/models/model_robertson_py/dJydsigma.cpp new file mode 100644 index 0000000000..2d9493301a --- /dev/null +++ b/models/model_robertson_py/dJydsigma.cpp @@ -0,0 +1,32 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_robertson_py { + +void dJydsigma_model_robertson_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydsigma[0] = 1.0/sigma_obs_x1 - 1.0*std::pow(-mobs_x1 + obs_x1, 2)/std::pow(sigma_obs_x1, 3); + break; + case 1: + dJydsigma[1] = 1.0/sigma_obs_x2 - 1.0*std::pow(-mobs_x2 + obs_x2, 2)/std::pow(sigma_obs_x2, 3); + break; + case 2: + dJydsigma[2] = 1.0/sigma_obs_x3 - 1.0*std::pow(-mobs_x3 + obs_x3, 2)/std::pow(sigma_obs_x3, 3); + break; + } +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/dJydy.cpp b/models/model_robertson_py/dJydy.cpp new file mode 100644 index 0000000000..2954000bf9 --- /dev/null +++ b/models/model_robertson_py/dJydy.cpp @@ -0,0 +1,78 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_robertson_py { + +static constexpr std::array, 3> dJydy_colptrs_model_robertson_py_ = {{ + {0, 1, 1, 1}, + {0, 0, 1, 1}, + {0, 0, 0, 1}, +}}; + +void dJydy_colptrs_model_robertson_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexptrs(gsl::make_span(dJydy_colptrs_model_robertson_py_[index])); +} +} // namespace model_model_robertson_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_robertson_py { + +static constexpr std::array, 3> dJydy_rowvals_model_robertson_py_ = {{ + {0}, + {0}, + {0}, +}}; + +void dJydy_rowvals_model_robertson_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexvals(gsl::make_span(dJydy_rowvals_model_robertson_py_[index])); +} +} // namespace model_model_robertson_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" +#include "dJydy.h" + +namespace amici { +namespace model_model_robertson_py { + +void dJydy_model_robertson_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydy[0] = (-1.0*mobs_x1 + 1.0*obs_x1)/std::pow(sigma_obs_x1, 2); + break; + case 1: + dJydy[0] = (-1.0*mobs_x2 + 1.0*obs_x2)/std::pow(sigma_obs_x2, 2); + break; + case 2: + dJydy[0] = (-1.0*mobs_x3 + 1.0*obs_x3)/std::pow(sigma_obs_x3, 2); + break; + } +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/dJydy.h b/models/model_robertson_py/dJydy.h new file mode 100644 index 0000000000..33d960ca6f --- /dev/null +++ b/models/model_robertson_py/dJydy.h @@ -0,0 +1,3 @@ +#define dJy0_dobs_x1 dJydy[0] +#define dJy0_dobs_x2_1 dJydy[1] +#define dJy0_dobs_x3_2 dJydy[2] diff --git a/models/model_robertson_py/dx.h b/models/model_robertson_py/dx.h new file mode 100644 index 0000000000..ffa00e36d7 --- /dev/null +++ b/models/model_robertson_py/dx.h @@ -0,0 +1,3 @@ +#define dx1dt dx[0] +#define dx2dt dx[1] +#define dx3dt dx[2] diff --git a/models/model_robertson_py/dxdotdp_explicit.cpp b/models/model_robertson_py/dxdotdp_explicit.cpp new file mode 100644 index 0000000000..cb39609e0b --- /dev/null +++ b/models/model_robertson_py/dxdotdp_explicit.cpp @@ -0,0 +1,68 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_robertson_py { + +static constexpr std::array dxdotdp_explicit_colptrs_model_robertson_py_ = { + 0, 2, 4, 5 +}; + +void dxdotdp_explicit_colptrs_model_robertson_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexptrs(gsl::make_span(dxdotdp_explicit_colptrs_model_robertson_py_)); +} +} // namespace model_model_robertson_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_robertson_py { + +static constexpr std::array dxdotdp_explicit_rowvals_model_robertson_py_ = { + 0, 1, 0, 1, 1 +}; + +void dxdotdp_explicit_rowvals_model_robertson_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexvals(gsl::make_span(dxdotdp_explicit_rowvals_model_robertson_py_)); +} +} // namespace model_model_robertson_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "dx.h" +#include "w.h" +#include "dxdotdp_explicit.h" + +namespace amici { +namespace model_model_robertson_py { + +void dxdotdp_explicit_model_robertson_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w){ + dde_0_dp1 = -x1; // dxdotdp_explicit[0] + dde_1_dp1 = x1; // dxdotdp_explicit[1] + dde_0_dp2 = x2*x3; // dxdotdp_explicit[2] + dde_1_dp2 = -x2*x3; // dxdotdp_explicit[3] + dde_1_dp3 = -std::pow(x2, 2); // dxdotdp_explicit[4] +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/dxdotdp_explicit.h b/models/model_robertson_py/dxdotdp_explicit.h new file mode 100644 index 0000000000..4efd1e3370 --- /dev/null +++ b/models/model_robertson_py/dxdotdp_explicit.h @@ -0,0 +1,5 @@ +#define dde_0_dp1 dxdotdp_explicit[0] +#define dde_1_dp1 dxdotdp_explicit[1] +#define dde_0_dp2 dxdotdp_explicit[2] +#define dde_1_dp2 dxdotdp_explicit[3] +#define dde_1_dp3 dxdotdp_explicit[4] diff --git a/models/model_robertson_py/dxdotdx_explicit.cpp b/models/model_robertson_py/dxdotdx_explicit.cpp new file mode 100644 index 0000000000..df90e71e9e --- /dev/null +++ b/models/model_robertson_py/dxdotdx_explicit.cpp @@ -0,0 +1,72 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_robertson_py { + +static constexpr std::array dxdotdx_explicit_colptrs_model_robertson_py_ = { + 0, 3, 6, 9 +}; + +void dxdotdx_explicit_colptrs_model_robertson_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexptrs(gsl::make_span(dxdotdx_explicit_colptrs_model_robertson_py_)); +} +} // namespace model_model_robertson_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_robertson_py { + +static constexpr std::array dxdotdx_explicit_rowvals_model_robertson_py_ = { + 0, 1, 2, 0, 1, 2, 0, 1, 2 +}; + +void dxdotdx_explicit_rowvals_model_robertson_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexvals(gsl::make_span(dxdotdx_explicit_rowvals_model_robertson_py_)); +} +} // namespace model_model_robertson_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "dx.h" +#include "w.h" +#include "dxdotdx_explicit.h" + +namespace amici { +namespace model_model_robertson_py { + +void dxdotdx_explicit_model_robertson_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w){ + dde_0_dx1 = -p1; // dxdotdx_explicit[0] + dde_1_dx1 = p1; // dxdotdx_explicit[1] + dae_0_dx1 = 1; // dxdotdx_explicit[2] + dde_0_dx2 = p2*x3; // dxdotdx_explicit[3] + dde_1_dx2 = -p2*x3 - 2*p3*x2; // dxdotdx_explicit[4] + dae_0_dx2 = 1; // dxdotdx_explicit[5] + dde_0_dx3 = p2*x2; // dxdotdx_explicit[6] + dde_1_dx3 = -p2*x2; // dxdotdx_explicit[7] + dae_0_dx3 = 1; // dxdotdx_explicit[8] +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/dxdotdx_explicit.h b/models/model_robertson_py/dxdotdx_explicit.h new file mode 100644 index 0000000000..e1bd2add46 --- /dev/null +++ b/models/model_robertson_py/dxdotdx_explicit.h @@ -0,0 +1,9 @@ +#define dde_0_dx1 dxdotdx_explicit[0] +#define dde_1_dx1 dxdotdx_explicit[1] +#define dae_0_dx1 dxdotdx_explicit[2] +#define dde_0_dx2 dxdotdx_explicit[3] +#define dde_1_dx2 dxdotdx_explicit[4] +#define dae_0_dx2 dxdotdx_explicit[5] +#define dde_0_dx3 dxdotdx_explicit[6] +#define dde_1_dx3 dxdotdx_explicit[7] +#define dae_0_dx3 dxdotdx_explicit[8] diff --git a/models/model_robertson_py/dydx.cpp b/models/model_robertson_py/dydx.cpp new file mode 100644 index 0000000000..156675cdcb --- /dev/null +++ b/models/model_robertson_py/dydx.cpp @@ -0,0 +1,22 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_robertson_py { + +void dydx_model_robertson_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx){ + dydx[0] = 1; + dydx[4] = 10000.0; + dydx[8] = 1; +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/k.h b/models/model_robertson_py/k.h new file mode 100644 index 0000000000..a9a0850b61 --- /dev/null +++ b/models/model_robertson_py/k.h @@ -0,0 +1 @@ +#define k1 k[0] diff --git a/models/model_robertson_py/main.cpp b/models/model_robertson_py/main.cpp new file mode 100644 index 0000000000..ecdff85a46 --- /dev/null +++ b/models/model_robertson_py/main.cpp @@ -0,0 +1,93 @@ +#include + +#include "wrapfunctions.h" /* model-provided functions */ +#include /* AMICI base functions */ + +template +std::ostream& operator<<(std::ostream& os, std::vector const& v) { + os << "["; + for (typename std::vector::const_iterator ii = v.begin(); ii != v.end(); + ++ii) { + os << " " << *ii; + } + os << "]"; + return os; +} + +/* + * This is a scaffold for a stand-alone AMICI simulation executable + * demonstrating the basic use of the AMICI C++ API. + */ + +int main() { + std::cout << "********************************" << std::endl; + std::cout << "** Running forward simulation **" << std::endl; + std::cout << "********************************" << std::endl << std::endl; + + // Create a model instance + auto model = amici::generic_model::getModel(); + + // Set desired output timepoints + model->setTimepoints({0.0, 1.0, 10.0, 100.0, 1000.0}); + + // Create a solver instance + auto solver = model->getSolver(); + + // Optionally set integration tolerance + solver->setAbsoluteTolerance(1e-16); + solver->setRelativeTolerance(1e-8); + + // Run the simulation using default parameters set during model import + // (can be changed using model->setParameters() or model->setParameterBy*()) + auto rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print observable time course + auto observable_ids = model->getObservableIds(); + std::cout << "Simulated observables for timepoints " << rdata->ts << "\n\n"; + for (int i_observable = 0; i_observable < rdata->ny; ++i_observable) { + std::cout << observable_ids[i_observable] << ":\n\t"; + for (int i_time = 0; i_time < rdata->nt; ++i_time) { + // rdata->y is a flat 2D array in row-major ordering + std::cout << rdata->y[i_time * rdata->ny + i_observable] << " "; + } + std::cout << std::endl << std::endl; + } + + std::cout << std::endl; + std::cout << "**********************************" << std::endl; + std::cout << "** Forward sensitivity analysis **" << std::endl; + std::cout << "**********************************" << std::endl << std::endl; + + // Enable first-order sensitivity analysis + solver->setSensitivityOrder(amici::SensitivityOrder::first); + // Use forward sensitivities + solver->setSensitivityMethod(amici::SensitivityMethod::forward); + + // Run the simulation + rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print state sensitivities sx... + // ... for the first timepoint... + int i_time = 0; + // ... with respect to the first parameter + int i_nplist = 0; + + // get identifiers from model + auto state_ids = model->getStateIds(); + auto parameter_ids = model->getParameterIds(); + + std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] + << std::endl; // nt x nplist x nx + for (int i_state = 0; i_state < rdata->nx; ++i_state) { + std::cout << "\td(" << state_ids[i_state] << ")/d(" + << parameter_ids[model->plist(i_nplist)] << ") = "; + + // rdata->sx is a flat 3D array in row-major ordering + std::cout << rdata->sx + [i_time * rdata->nplist * rdata->nx + + i_nplist * rdata->nx + i_state]; + std::cout << std::endl; + } + + return 0; +} diff --git a/models/model_robertson_py/model_robertson_py.cpp b/models/model_robertson_py/model_robertson_py.cpp new file mode 100644 index 0000000000..58f8914f02 --- /dev/null +++ b/models/model_robertson_py/model_robertson_py.cpp @@ -0,0 +1,76 @@ +#include +#include + +namespace amici { + +namespace model_model_robertson_py { + +// clang-format off + +std::array parameterNames = { + "p1", // p[0] +"p2", // p[1] +"p3", // p[2] +}; + +std::array fixedParameterNames = { + "k1", // k[0] +}; + +std::array stateNames = { + "x1", // x_rdata[0] +"x2", // x_rdata[1] +"x3", // x_rdata[2] +}; + +std::array observableNames = { + "y0", // y[0] +"y1", // y[1] +"y2", // y[2] +}; + +std::array observableScalings = { + ObservableScaling::lin, // y[0] +ObservableScaling::lin, // y[1] +ObservableScaling::lin, // y[2] +}; + +std::array expressionNames = { + "flux_r0", // w[0] +}; + +std::array parameterIds = { + "p1", // p[0] +"p2", // p[1] +"p3", // p[2] +}; + +std::array fixedParameterIds = { + "k1", // k[0] +}; + +std::array stateIds = { + "x1", // x_rdata[0] +"x2", // x_rdata[1] +"x3", // x_rdata[2] +}; + +std::array observableIds = { + "obs_x1", // y[0] +"obs_x2", // y[1] +"obs_x3", // y[2] +}; + +std::array expressionIds = { + "flux_r0", // w[0] +}; + +std::array stateIdxsSolver = { + 0, 1, 2 +}; + +// clang-format on + +} // namespace model_model_robertson_py + +} // namespace amici diff --git a/models/model_robertson_py/model_robertson_py.h b/models/model_robertson_py/model_robertson_py.h new file mode 100644 index 0000000000..7f188e3849 --- /dev/null +++ b/models/model_robertson_py/model_robertson_py.h @@ -0,0 +1,555 @@ +#ifndef _amici_TPL_MODELNAME_h +#define _amici_TPL_MODELNAME_h +#include +#include +#include + +#include "amici/model_dae.h" +#include "amici/splinefunctions.h" +#include "amici/event.h" + +namespace amici { + +class Solver; + +namespace model_model_robertson_py { + +extern std::array parameterNames; +extern std::array fixedParameterNames; +extern std::array stateNames; +extern std::array observableNames; +extern std::array observableScalings; +extern std::array expressionNames; +extern std::array parameterIds; +extern std::array fixedParameterIds; +extern std::array stateIds; +extern std::array observableIds; +extern std::array expressionIds; +extern std::array stateIdxsSolver; + +extern void Jy_model_robertson_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydsigma_model_robertson_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_model_robertson_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_colptrs_model_robertson_py(SUNMatrixWrapper &colptrs, int index); +extern void dJydy_rowvals_model_robertson_py(SUNMatrixWrapper &rowvals, int index); + + + + + + + + + + + + + + + + + + + +extern void dxdotdp_explicit_model_robertson_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w); +extern void dxdotdp_explicit_colptrs_model_robertson_py(SUNMatrixWrapper &colptrs); +extern void dxdotdp_explicit_rowvals_model_robertson_py(SUNMatrixWrapper &rowvals); +extern void dxdotdx_explicit_model_robertson_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w); +extern void dxdotdx_explicit_colptrs_model_robertson_py(SUNMatrixWrapper &colptrs); +extern void dxdotdx_explicit_rowvals_model_robertson_py(SUNMatrixWrapper &rowvals); +extern void dydx_model_robertson_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx); + + + + + +extern void sigmay_model_robertson_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y); + + + + + +extern void x0_model_robertson_py(realtype *x0, const realtype t, const realtype *p, const realtype *k); +extern void x0_fixedParameters_model_robertson_py(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs); + +extern void sx0_fixedParameters_model_robertson_py(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs); +extern void xdot_model_robertson_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w); +extern void y_model_robertson_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); + + + + + + + + +extern void x_solver_model_robertson_py(realtype *x_solver, const realtype *x_rdata); + + + + + + + + + + + + +extern std::vector create_splines_model_robertson_py(const realtype *p, const realtype *k); + + + +/** + * @brief AMICI-generated model subclass. + */ +class Model_model_robertson_py : public amici::Model_DAE { + public: + /** + * @brief Default constructor. + */ + Model_model_robertson_py() + : amici::Model_DAE( + amici::ModelDimensions( + 3, // nx_rdata + 3, // nxtrue_rdata + 3, // nx_solver + 3, // nxtrue_solver + 0, // nx_solver_reinit + 3, // np + 1, // nk + 3, // ny + 3, // nytrue + 0, // nz + 0, // nztrue + 0, // nevent + 0, // nevent_solver + 0, // nspl + 1, // nobjective + 1, // nw + 0, // ndwdx + 0, // ndwdp + 0, // ndwdw + 0, // ndxdotdw + std::vector{1, 1, 1}, // ndjydy + 0, // ndxrdatadxsolver + 0, // ndxrdatadtcl + 0, // ndtotal_cldx_rdata + 0, // nnz + 3, // ubw + 3, // lbw + true, // pythonGenerated + 5, // ndxdotdp_explicit + 9, // ndxdotdx_explicit + 0 // w_recursion_depth + ), + amici::SimulationParameters( + std::vector{0.90000000000000002}, // fixedParameters + std::vector{0.040000000000000001, 10000.0, 30000000.0} // dynamic parameters + ), + amici::SecondOrderMode::none, // o2mode + std::vector{1.0, 1.0, 0.0}, // idlist + std::vector{}, // z2events + std::vector{}, // events + {} // state-independent events + ) { + } + + /** + * @brief Clone this model instance. + * @return A deep copy of this instance. + */ + amici::Model *clone() const override { + return new Model_model_robertson_py(*this); + } + + void fJrz(realtype *Jrz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fJy(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + Jy_model_robertson_py(Jy, iy, p, k, y, sigmay, my); + } + + + void fJz(realtype *Jz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override {} + + + void fdJrzdsigma(realtype *dJrzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fdJrzdz(realtype *dJrzdz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fdJydsigma(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydsigma_model_robertson_py(dJydsigma, iy, p, k, y, sigmay, my); + } + + + void fdJzdsigma(realtype *dJzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override {} + + + void fdJzdz(realtype *dJzdz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const double *mz) override {} + + + void fdeltax(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old) override {} + + + void fdeltasx(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old) override {} + + + void fdeltaxB(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl) override {} + + + void fdeltaqB(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB) override {} + + + void fdrzdp(realtype *drzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdrzdx(realtype *drzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void fdsigmaydp(realtype *dsigmaydp, const realtype t, const realtype *p, const realtype *k, const realtype *y, const int ip) override {} + + + void fdsigmaydy(realtype *dsigmaydy, const realtype t, const realtype *p, const realtype *k, const realtype *y) override {} + + + void fdsigmazdp(realtype *dsigmazdp, const realtype t, const realtype *p, const realtype *k, const int ip) override {} + + + void fdJydy(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydy_model_robertson_py(dJydy, iy, p, k, y, sigmay, my); + } + + void fdJydy_colptrs(SUNMatrixWrapper &colptrs, int index) override { + dJydy_colptrs_model_robertson_py(colptrs, index); + } + + void fdJydy_rowvals(SUNMatrixWrapper &rowvals, int index) override { + dJydy_rowvals_model_robertson_py(rowvals, index); + } + + + std::vector fcreate_splines(const realtype *p, const realtype *k) override { + return create_splines_model_robertson_py(p, k); + } + + void fdspline_valuesdp(realtype *dspline_valuesdp, const realtype *p, const realtype *k, const int ip) override {} + + void fdspline_slopesdp(realtype *dspline_slopesdp, const realtype *p, const realtype *k, const int ip) override {} + + + void fdwdp(realtype *dwdp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl, bool include_static) override {} + + void fdwdp_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdp_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdx(realtype *dwdx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *spl, bool include_static) override {} + + void fdwdx_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdx_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdw(realtype *dwdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, bool include_static) override {} + + void fdwdw_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdw_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdw(realtype *dxdotdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w) override {} + + void fdxdotdw_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdxdotdw_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdp_explicit(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w) override { + dxdotdp_explicit_model_robertson_py(dxdotdp_explicit, t, x, p, k, h, dx, w); + } + + void fdxdotdp_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdp_explicit_colptrs_model_robertson_py(colptrs); + } + + void fdxdotdp_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdp_explicit_rowvals_model_robertson_py(rowvals); + } + + + void fdxdotdx_explicit(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w) override { + dxdotdx_explicit_model_robertson_py(dxdotdx_explicit, t, x, p, k, h, dx, w); + } + + void fdxdotdx_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdx_explicit_colptrs_model_robertson_py(colptrs); + } + + void fdxdotdx_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdx_explicit_rowvals_model_robertson_py(rowvals); + } + + + void fdydx(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { + dydx_model_robertson_py(dydx, t, x, p, k, h, w, dwdx); + } + + + void fdydp(realtype *dydp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl) override {} + + + void fdzdp(realtype *dzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdzdx(realtype *dzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void froot(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl) override {} + + + void frz(realtype *rz, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void fsigmay(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y) override { + sigmay_model_robertson_py(sigmay, t, p, k, y); + } + + + void fsigmaz(realtype *sigmaz, const realtype t, const realtype *p, const realtype *k) override {} + + + void fstau(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie) override {} + + void fsx0(realtype *sx0, const realtype t, const realtype *x, const realtype *p, const realtype *k, const int ip) override {} + + void fsx0_fixedParameters(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs) override { + sx0_fixedParameters_model_robertson_py(sx0_fixedParameters, t, x0, p, k, ip, reinitialization_state_idxs); + } + + + void fw(realtype *w, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl, const realtype *spl, bool include_static) override {} + + + void fx0(realtype *x0, const realtype t, const realtype *p, const realtype *k) override { + x0_model_robertson_py(x0, t, p, k); + } + + + void fx0_fixedParameters(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs) override { + x0_fixedParameters_model_robertson_py(x0_fixedParameters, t, p, k, reinitialization_state_idxs); + } + + + void fxdot(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w) override { + xdot_model_robertson_py(xdot, t, x, p, k, h, dx, w); + } + + + void fy(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + y_model_robertson_py(y, t, x, p, k, h, w); + } + + + void fz(realtype *z, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + + + void fx_solver(realtype *x_solver, const realtype *x_rdata) override { + x_solver_model_robertson_py(x_solver, x_rdata); + } + + + void ftotal_cl(realtype *total_cl, const realtype *x_rdata, const realtype *p, const realtype *k) override {} + + + void fdx_rdatadx_solver(realtype *dx_rdatadx_solver, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadx_solver_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadx_solver_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdx_rdatadp(realtype *dx_rdatadp, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k, const int ip) override {} + + + void fdx_rdatadtcl(realtype *dx_rdatadtcl, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadtcl_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadtcl_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdtotal_cldp(realtype *dtotal_cldp, const realtype *x_rdata, const realtype *p, const realtype *k, const int ip) override {} + + + void fdtotal_cldx_rdata(realtype *dtotal_cldx_rdata, const realtype *x_rdata, const realtype *p, const realtype *k, const realtype *tcl) override {} + + void fdtotal_cldx_rdata_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdtotal_cldx_rdata_rowvals(SUNMatrixWrapper &rowvals) override {} + + + std::string getName() const override { + return "model_robertson_py"; + } + + /** + * @brief Get names of the model parameters + * @return the names + */ + std::vector getParameterNames() const override { + return std::vector(parameterNames.begin(), + parameterNames.end()); + } + + /** + * @brief Get names of the model states + * @return the names + */ + std::vector getStateNames() const override { + return std::vector(stateNames.begin(), stateNames.end()); + } + + /** + * @brief Get names of the solver states + * @return the names + */ + std::vector getStateNamesSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto const idx: stateIdxsSolver) { + result.push_back(stateNames[idx]); + } + return result; + } + + /** + * @brief Get names of the fixed model parameters + * @return the names + */ + std::vector getFixedParameterNames() const override { + return std::vector(fixedParameterNames.begin(), + fixedParameterNames.end()); + } + + /** + * @brief Get names of the observables + * @return the names + */ + std::vector getObservableNames() const override { + return std::vector(observableNames.begin(), + observableNames.end()); + } + + /** + * @brief Get names of model expressions + * @return Expression names + */ + std::vector getExpressionNames() const override { + return std::vector(expressionNames.begin(), + expressionNames.end()); + } + + /** + * @brief Get ids of the model parameters + * @return the ids + */ + std::vector getParameterIds() const override { + return std::vector(parameterIds.begin(), + parameterIds.end()); + } + + /** + * @brief Get ids of the model states + * @return the ids + */ + std::vector getStateIds() const override { + return std::vector(stateIds.begin(), stateIds.end()); + } + + /** + * @brief Get ids of the solver states + * @return the ids + */ + std::vector getStateIdsSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto idx: stateIdxsSolver) { + result.push_back(stateIds[idx]); + } + return result; + } + + /** + * @brief Get ids of the fixed model parameters + * @return the ids + */ + std::vector getFixedParameterIds() const override { + return std::vector(fixedParameterIds.begin(), + fixedParameterIds.end()); + } + + /** + * @brief Get ids of the observables + * @return the ids + */ + std::vector getObservableIds() const override { + return std::vector(observableIds.begin(), + observableIds.end()); + } + + /** + * @brief Get IDs of model expressions + * @return Expression IDs + */ + std::vector getExpressionIds() const override { + return std::vector(expressionIds.begin(), + expressionIds.end()); + } + + /** + * @brief function indicating whether reinitialization of states depending + * on fixed parameters is permissible + * @return flag indicating whether reinitialization of states depending on + * fixed parameters is permissible + */ + bool isFixedParameterStateReinitializationAllowed() const override { + return true; + } + + /** + * @brief returns the AMICI version that was used to generate the model + * @return AMICI version string + */ + std::string getAmiciVersion() const override { + return "0.33.0"; + } + + /** + * @brief returns the amici version that was used to generate the model + * @return AMICI git commit hash + */ + std::string getAmiciCommit() const override { + return "bcedb951ddf674996b269489d74f9b86112038ff"; + } + + bool hasQuadraticLLH() const override { + return true; + } + + ObservableScaling getObservableScaling(int iy) const override { + return observableScalings.at(iy); + } +}; + + +} // namespace model_model_robertson_py + +} // namespace amici + +#endif /* _amici_TPL_MODELNAME_h */ diff --git a/models/model_robertson_py/my.h b/models/model_robertson_py/my.h new file mode 100644 index 0000000000..2e142e7fb5 --- /dev/null +++ b/models/model_robertson_py/my.h @@ -0,0 +1,3 @@ +#define mobs_x1 my[0] +#define mobs_x2 my[1] +#define mobs_x3 my[2] diff --git a/models/model_robertson_py/p.h b/models/model_robertson_py/p.h new file mode 100644 index 0000000000..323fde3c06 --- /dev/null +++ b/models/model_robertson_py/p.h @@ -0,0 +1,3 @@ +#define p1 p[0] +#define p2 p[1] +#define p3 p[2] diff --git a/models/model_robertson_py/setup.py b/models/model_robertson_py/setup.py new file mode 100644 index 0000000000..b60d29dc40 --- /dev/null +++ b/models/model_robertson_py/setup.py @@ -0,0 +1,95 @@ +"""AMICI model package setup""" + +import os +import sys +from pathlib import Path + +from amici import _get_amici_path +from amici.custom_commands import AmiciBuildCMakeExtension +from cmake_build_extension import CMakeExtension +from setuptools import find_namespace_packages, setup +import importlib.metadata + + +def get_extension() -> CMakeExtension: + """Get setuptools extension object for this AMICI model package""" + + # Build shared object + prefix_path = Path(_get_amici_path()) + AmiciBuildCMakeExtension.extend_cmake_prefix_path(str(prefix_path)) + + # handle parallel building + # Note: can be empty to use all hardware threads + if (parallel_jobs := os.environ.get("AMICI_PARALLEL_COMPILE")) is not None: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = parallel_jobs + else: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = "1" + + debug_build = os.getenv("ENABLE_AMICI_DEBUGGING", "").lower() in [ + "1", + "true", + ] or os.getenv("ENABLE_GCOV_COVERAGE", "").lower() in ["1", "true"] + + cmake_prefix_path = os.getenv("CMAKE_PREFIX_PATH", "").split(os.pathsep) + cmake_prefix_path.append(prefix_path.as_posix()) + + # If scipy_openblas64 is installed, we make its cmake configuration + # available + amici_distribution = importlib.metadata.distribution("amici") + amici_dir = Path(amici_distribution.locate_file("")) + # this path is created during the amici build if scipy_openblas64 is used + openblas_cmake_dir = amici_dir / "lib" / "cmake" / "openblas" + if openblas_cmake_dir.exists(): + cmake_prefix_path.append(str(openblas_cmake_dir)) + + return CMakeExtension( + name="model_ext", + source_dir=os.getcwd(), + install_prefix="model_robertson_py", + cmake_configure_options=[ + "-DCMAKE_VERBOSE_MAKEFILE=ON", + f"-DCMAKE_PREFIX_PATH='{';'.join(cmake_prefix_path)}'", + "-DAMICI_PYTHON_BUILD_EXT_ONLY=ON", + f"-DPython3_EXECUTABLE={Path(sys.executable).as_posix()}", + ], + cmake_build_type="Debug" if debug_build else "Release", + ) + + +# Change working directory to setup.py location +os.chdir(os.path.dirname(os.path.abspath(__file__))) + +MODEL_EXT = get_extension() + +CLASSIFIERS = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Science/Research", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python", + "Programming Language :: C++", + "Topic :: Scientific/Engineering :: Bio-Informatics", +] + +CMDCLASS = { + # for CMake-based builds + "build_ext": AmiciBuildCMakeExtension, +} + +# Install +setup( + name="model_robertson_py", + cmdclass=CMDCLASS, + version="0.1.0", + description="AMICI-generated module for model model_robertson_py", + url="https://github.com/AMICI-dev/AMICI", + author="model-author-todo", + author_email="model-author-todo", + ext_modules=[MODEL_EXT], + packages=find_namespace_packages(), + install_requires=["amici==0.33.0"], + python_requires=">=3.11", + package_data={}, + zip_safe=False, + classifiers=CLASSIFIERS, +) diff --git a/models/model_robertson_py/sigmay.cpp b/models/model_robertson_py/sigmay.cpp new file mode 100644 index 0000000000..3031a653c2 --- /dev/null +++ b/models/model_robertson_py/sigmay.cpp @@ -0,0 +1,23 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" + +namespace amici { +namespace model_model_robertson_py { + +void sigmay_model_robertson_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y){ + sigma_obs_x1 = 1.0; // sigmay[0] + sigma_obs_x2 = 1.0; // sigmay[1] + sigma_obs_x3 = 1.0; // sigmay[2] +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/sigmay.h b/models/model_robertson_py/sigmay.h new file mode 100644 index 0000000000..6aaf381974 --- /dev/null +++ b/models/model_robertson_py/sigmay.h @@ -0,0 +1,3 @@ +#define sigma_obs_x1 sigmay[0] +#define sigma_obs_x2 sigmay[1] +#define sigma_obs_x3 sigmay[2] diff --git a/models/model_robertson_py/swig/CMakeLists.txt b/models/model_robertson_py/swig/CMakeLists.txt new file mode 100644 index 0000000000..314996c479 --- /dev/null +++ b/models/model_robertson_py/swig/CMakeLists.txt @@ -0,0 +1,60 @@ +if(DEFINED ENV{SWIG}) + set(SWIG_EXECUTABLE $ENV{SWIG}) +endif() + +find_package(SWIG REQUIRED) +include(${SWIG_USE_FILE}) + +if(DEFINED ENV{PYTHON_EXECUTABLE}) + set(Python3_EXECUTABLE $ENV{PYTHON_EXECUTABLE}) +endif() +# We don't need "Interpreter" here, but without that, FindPython3 will +# ignore the Python version selected via $Python3_EXECUTABLE +find_package(Python3 COMPONENTS Interpreter Development) +include_directories(${Python3_INCLUDE_DIRS}) + +set(SWIG_LIBRARY_NAME _${PROJECT_NAME}) +set(CMAKE_SWIG_FLAGS "") +set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) + +# swig does not use INTERFACE_INCLUDE_DIRS of linked libraries, so add manually +get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) +include_directories(${AMICI_INCLUDE_DIRS} .. ${AMICI_INCLUDE_DIRS}/../swig) + +swig_add_library(${SWIG_LIBRARY_NAME} + TYPE MODULE + LANGUAGE python + SOURCES ${PROJECT_NAME}.i) + + +set_target_properties(${SWIG_LIBRARY_NAME} + PROPERTIES + SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE + PREFIX "" +) + +# Python extension suffix +execute_process( + COMMAND ${Python3_EXECUTABLE} -c + "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))" + OUTPUT_VARIABLE PY_EXT_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE) +if(NOT "${PY_EXT_SUFFIX}" STREQUAL "") + message(STATUS "Python extension suffix is ${PY_EXT_SUFFIX}") + set_target_properties(${SWIG_LIBRARY_NAME} PROPERTIES SUFFIX "${PY_EXT_SUFFIX}" ) +endif() + + +swig_link_libraries(${SWIG_LIBRARY_NAME} + ${Python3_LIBRARIES} + model) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.py + $ DESTINATION .) + +# configure module setup script +set(SETUP_PY_IN ${Amici_DIR}/model_setup.template.py) +set(SETUP_PY_OUT ${CMAKE_CURRENT_BINARY_DIR}/setup.py) + +add_custom_target(install-python + DEPENDS ${SWIG_LIBRARY_NAME} + COMMAND python ${SETUP_PY_OUT} install) diff --git a/models/model_robertson_py/swig/model_robertson_py.i b/models/model_robertson_py/swig/model_robertson_py.i new file mode 100644 index 0000000000..3a629ed8b7 --- /dev/null +++ b/models/model_robertson_py/swig/model_robertson_py.i @@ -0,0 +1,82 @@ +%define MODULEIMPORT +" +import amici +import datetime +import importlib.util +import os +import sysconfig +from pathlib import Path + +ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +_model_robertson_py = amici._module_from_path( + 'model_robertson_py._model_robertson_py' if __package__ or '.' in __name__ + else '_model_robertson_py', + Path(__file__).parent / f'_model_robertson_py{ext_suffix}', +) + +def _get_import_time(): + return _model_robertson_py._get_import_time() + +t_imported = _get_import_time() +t_modified = os.path.getmtime(__file__) +if t_imported < t_modified: + t_imp_str = datetime.datetime.fromtimestamp(t_imported).isoformat() + t_mod_str = datetime.datetime.fromtimestamp(t_modified).isoformat() + module_path = Path(__file__).resolve() + raise RuntimeError( + f'Cannot import extension for model_robertson_py from ' + f'{module_path}, because an extension in the same location ' + f'has already been imported, but the file was modified on ' + f'disk. \\nImported at {t_imp_str}\\nModified at {t_mod_str}.\\n' + 'Import the module with a different name or restart the ' + 'Python kernel.' + ) +" +%enddef + +%module(package="model_robertson_py",moduleimport=MODULEIMPORT) model_robertson_py + +%pythoncode %{ +# the model-package __init__.py module (will be set during import) +_model_module = None + + +%} + +%import amici.i +// Add necessary symbols to generated header + +%{ +#include "wrapfunctions.h" +#include "amici/model_ode.h" +#include "amici/model_dae.h" +using namespace amici; +%} + +// store the time a module was imported +%{ +#include +static std::chrono::time_point _module_import_time; + +static double _get_import_time() { + auto epoch = _module_import_time.time_since_epoch(); + return std::chrono::duration(epoch).count(); +} +%} + +static double _get_import_time(); + +%init %{ + _module_import_time = std::chrono::system_clock::now(); +%} + + +// Make model module accessible from the model +%feature("pythonappend") amici::generic_model::getModel %{ + if '.' in __name__: + val.module = _model_module +%} + + +// Process symbols in header +%include "wrapfunctions.h" diff --git a/models/model_robertson_py/sx0_fixedParameters.cpp b/models/model_robertson_py/sx0_fixedParameters.cpp new file mode 100644 index 0000000000..1a7ecb19f0 --- /dev/null +++ b/models/model_robertson_py/sx0_fixedParameters.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_robertson_py { + +void sx0_fixedParameters_model_robertson_py(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs){ + static const std::array _x0_fixedParameters_idxs = { + 0 + }; + for(auto idx: reinitialization_state_idxs) { + if(std::find(_x0_fixedParameters_idxs.cbegin(), _x0_fixedParameters_idxs.cend(), idx) != _x0_fixedParameters_idxs.cend()) + sx0_fixedParameters[idx] = 0.0; + } +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/w.h b/models/model_robertson_py/w.h new file mode 100644 index 0000000000..c399413a8c --- /dev/null +++ b/models/model_robertson_py/w.h @@ -0,0 +1 @@ +#define flux_r0 w[0] diff --git a/models/model_robertson_py/wrapfunctions.cpp b/models/model_robertson_py/wrapfunctions.cpp new file mode 100644 index 0000000000..b3db86631b --- /dev/null +++ b/models/model_robertson_py/wrapfunctions.cpp @@ -0,0 +1,16 @@ +#include "wrapfunctions.h" +#include "model_robertson_py.h" +#include "amici/model.h" + +namespace amici { +namespace generic_model { + +std::unique_ptr getModel() { + return std::unique_ptr( + new amici::model_model_robertson_py::Model_model_robertson_py() + ); +} + +} // namespace generic_model + +} // namespace amici diff --git a/models/model_robertson_py/wrapfunctions.h b/models/model_robertson_py/wrapfunctions.h new file mode 100644 index 0000000000..33c8a9d819 --- /dev/null +++ b/models/model_robertson_py/wrapfunctions.h @@ -0,0 +1,25 @@ +#ifndef _amici_wrapfunctions_h +#define _amici_wrapfunctions_h + +#include + +#include "amici/model.h" + +namespace amici { +namespace generic_model { + + +/** + * @brief Wrapper function to instantiate the linked Amici model without knowing + * the name at compile time. + * @return Model instance + */ +std::unique_ptr getModel(); + + +} // namespace generic_model + +} // namespace amici + + +#endif /* _amici_wrapfunctions_h */ diff --git a/models/model_robertson_py/x.h b/models/model_robertson_py/x.h new file mode 100644 index 0000000000..7c21f2ef67 --- /dev/null +++ b/models/model_robertson_py/x.h @@ -0,0 +1,3 @@ +#define x1 x[0] +#define x2 x[1] +#define x3 x[2] diff --git a/models/model_robertson_py/x0.cpp b/models/model_robertson_py/x0.cpp new file mode 100644 index 0000000000..695f8350e6 --- /dev/null +++ b/models/model_robertson_py/x0.cpp @@ -0,0 +1,19 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_robertson_py { + +void x0_model_robertson_py(realtype *x0, const realtype t, const realtype *p, const realtype *k){ + x0[0] = k1; +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/x0_fixedParameters.cpp b/models/model_robertson_py/x0_fixedParameters.cpp new file mode 100644 index 0000000000..6ec5bc39ea --- /dev/null +++ b/models/model_robertson_py/x0_fixedParameters.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_robertson_py { + +void x0_fixedParameters_model_robertson_py(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs){ + if(std::find(reinitialization_state_idxs.cbegin(), reinitialization_state_idxs.cend(), 0) != reinitialization_state_idxs.cend()) + x0_fixedParameters[0] = k1; +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/x_rdata.cpp b/models/model_robertson_py/x_rdata.cpp new file mode 100644 index 0000000000..f1b9423223 --- /dev/null +++ b/models/model_robertson_py/x_rdata.cpp @@ -0,0 +1,22 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_robertson_py { + +void x_rdata_model_robertson_py(realtype *x_rdata, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k){ + x_rdata[0] = x1; + x_rdata[1] = x2; + x_rdata[2] = x3; +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/x_rdata.h b/models/model_robertson_py/x_rdata.h new file mode 100644 index 0000000000..4b2aa926d2 --- /dev/null +++ b/models/model_robertson_py/x_rdata.h @@ -0,0 +1,3 @@ +#define x1 x_rdata[0] +#define x2 x_rdata[1] +#define x3 x_rdata[2] diff --git a/models/model_robertson_py/x_solver.cpp b/models/model_robertson_py/x_solver.cpp new file mode 100644 index 0000000000..7d357d4408 --- /dev/null +++ b/models/model_robertson_py/x_solver.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x_rdata.h" + +namespace amici { +namespace model_model_robertson_py { + +void x_solver_model_robertson_py(realtype *x_solver, const realtype *x_rdata){ + x_solver[0] = x1; + x_solver[1] = x2; + x_solver[2] = x3; +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/x_solver.h b/models/model_robertson_py/x_solver.h new file mode 100644 index 0000000000..ef1d32a257 --- /dev/null +++ b/models/model_robertson_py/x_solver.h @@ -0,0 +1,3 @@ +#define x_solver0 x_solver[0] +#define x_solver1 x_solver[1] +#define x_solver2 x_solver[2] diff --git a/models/model_robertson_py/xdot.cpp b/models/model_robertson_py/xdot.cpp new file mode 100644 index 0000000000..4bc684afa6 --- /dev/null +++ b/models/model_robertson_py/xdot.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "dx.h" +#include "w.h" +#include "xdot.h" + +namespace amici { +namespace model_model_robertson_py { + +void xdot_model_robertson_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *w){ + de_0 = -dx1dt - p1*x1 + p2*x2*x3; // xdot[0] + de_1 = -dx2dt + p1*x1 - p2*x2*x3 - p3*std::pow(x2, 2); // xdot[1] + ae_0 = x1 + x2 + x3 - 1; // xdot[2] +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/xdot.h b/models/model_robertson_py/xdot.h new file mode 100644 index 0000000000..a266326b94 --- /dev/null +++ b/models/model_robertson_py/xdot.h @@ -0,0 +1,3 @@ +#define de_0 xdot[0] +#define de_1 xdot[1] +#define ae_0 xdot[2] diff --git a/models/model_robertson_py/y.cpp b/models/model_robertson_py/y.cpp new file mode 100644 index 0000000000..df986ee6d3 --- /dev/null +++ b/models/model_robertson_py/y.cpp @@ -0,0 +1,22 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_robertson_py { + +void y_model_robertson_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + y[0] = x1; + y[1] = 10000.0*x2; + y[2] = x3; +} + +} // namespace model_model_robertson_py +} // namespace amici diff --git a/models/model_robertson_py/y.h b/models/model_robertson_py/y.h new file mode 100644 index 0000000000..97f7b0ea74 --- /dev/null +++ b/models/model_robertson_py/y.h @@ -0,0 +1,3 @@ +#define obs_x1 y[0] +#define obs_x2 y[1] +#define obs_x3 y[2] diff --git a/models/model_steadystate_py/CMakeLists.txt b/models/model_steadystate_py/CMakeLists.txt new file mode 100644 index 0000000000..14347328de --- /dev/null +++ b/models/model_steadystate_py/CMakeLists.txt @@ -0,0 +1,141 @@ +# Build AMICI model +cmake_minimum_required(VERSION 3.22) +cmake_policy(VERSION 3.22...3.31) + +project(model_steadystate_py) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +include(CheckCXXCompilerFlag) +set(MY_CXX_FLAGS -Wall -Wno-unused-function -Wno-unused-variable) +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND MY_CXX_FLAGS -Wno-unused-but-set-variable) +endif() +foreach(flag ${MY_CXX_FLAGS}) + unset(CUR_FLAG_SUPPORTED CACHE) + check_cxx_compiler_flag(${flag} CUR_FLAG_SUPPORTED) + if(${CUR_FLAG_SUPPORTED}) + string(APPEND CMAKE_CXX_FLAGS " ${flag}") + endif() +endforeach() + +if(DEFINED ENV{AMICI_CXXFLAGS}) + message(STATUS "Appending flags from AMICI_CXXFLAGS: $ENV{AMICI_CXXFLAGS}") + add_compile_options("$ENV{AMICI_CXXFLAGS}") +endif() +if(DEFINED ENV{AMICI_LDFLAGS}) + message(STATUS "Appending flags from AMICI_LDFLAGS: $ENV{AMICI_LDFLAGS}") + link_libraries("$ENV{AMICI_LDFLAGS}") +endif() + +find_package(Amici 0.33.0 REQUIRED HINTS + ${CMAKE_CURRENT_LIST_DIR}/../../build) +message(STATUS "Found AMICI ${Amici_DIR}") +set_target_properties(Upstream::amici PROPERTIES + MAP_IMPORTED_CONFIG_RELWITHDEBINFO RelWithDebInfo;Release; + MAP_IMPORTED_CONFIG_RELEASE Release + MAP_IMPORTED_CONFIG_DEBUG Debug;RelWithDebInfo;) + +# Debug build? +if("$ENV{ENABLE_AMICI_DEBUGGING}" OR "$ENV{ENABLE_GCOV_COVERAGE}") + add_compile_options(-UNDEBUG) + if(MSVC) + add_compile_options(-DEBUG) + else() + add_compile_options(-O0 -g) + endif() +endif() + +# coverage options +if($ENV{ENABLE_GCOV_COVERAGE}) + string(APPEND CMAKE_CXX_FLAGS_DEBUG " --coverage") + string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " --coverage") +endif() + +set(MODEL_DIR ${CMAKE_CURRENT_LIST_DIR}) + +set(SRC_LIST_LIB Jy.cpp +Jy.h +create_splines.cpp +dJydsigma.cpp +dJydy.cpp +dJydy.h +dxdotdp_explicit.cpp +dxdotdp_explicit.h +dxdotdx_explicit.cpp +dxdotdx_explicit.h +dydx.cpp +k.h +model_steadystate_py.cpp +model_steadystate_py.h +my.h +p.h +sigmay.cpp +sigmay.h +sx0_fixedParameters.cpp +w.h +wrapfunctions.cpp +wrapfunctions.h +x.h +x0.cpp +x0_fixedParameters.cpp +x_rdata.cpp +x_rdata.h +x_solver.cpp +x_solver.h +xdot.cpp +xdot.h +y.cpp +y.h ${MODEL_DIR}/wrapfunctions.cpp) + +add_library(${PROJECT_NAME} ${SRC_LIST_LIB}) + +# ${PROJECT_NAME} might already be "model" +if(NOT TARGET model) + add_library(model ALIAS ${PROJECT_NAME}) +endif() + +# Some special functions require boost +# +# TODO: set some flag during code generation whether the given model requires +# boost. for now, try to find it, add include directories and link against it. +# let the compiler/linker error if it is required but not found +find_package(Boost) + +target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") + +target_link_libraries( + ${PROJECT_NAME} + PUBLIC Upstream::amici + PRIVATE $<$:Boost::boost>) + +if(NOT "${AMICI_PYTHON_BUILD_EXT_ONLY}") + set(SRC_LIST_EXE main.cpp) + add_executable(simulate_${PROJECT_NAME} ${SRC_LIST_EXE}) + target_link_libraries(simulate_${PROJECT_NAME} ${PROJECT_NAME}) +endif() + +# SWIG +option(ENABLE_SWIG "Build swig/python library?" ON) +if(ENABLE_SWIG) + add_subdirectory(swig) +endif() + +# +include(GNUInstallDirs) +install( + TARGETS ${PROJECT_NAME} + EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +export( + EXPORT ${PROJECT_NAME}Targets + FILE ${PROJECT_NAME}Config.cmake + NAMESPACE Upstream::) +# diff --git a/models/model_steadystate_py/Jy.cpp b/models/model_steadystate_py/Jy.cpp new file mode 100644 index 0000000000..8d4f4cafbf --- /dev/null +++ b/models/model_steadystate_py/Jy.cpp @@ -0,0 +1,32 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_steadystate_py { + +void Jy_model_steadystate_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_x1, 2)) + 0.5*std::pow(-mobs_x1 + obs_x1, 2)/std::pow(sigma_obs_x1, 2); + break; + case 1: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_x2, 2)) + 0.5*std::pow(-mobs_x2 + obs_x2, 2)/std::pow(sigma_obs_x2, 2); + break; + case 2: + Jy[0] = 0.5*std::log(2*amici::pi*std::pow(sigma_obs_x3, 2)) + 0.5*std::pow(-mobs_x3 + obs_x3, 2)/std::pow(sigma_obs_x3, 2); + break; + } +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/Jy.h b/models/model_steadystate_py/Jy.h new file mode 100644 index 0000000000..e7751bcae0 --- /dev/null +++ b/models/model_steadystate_py/Jy.h @@ -0,0 +1,3 @@ +#define Jy0 Jy[0] +#define Jy1 Jy[1] +#define Jy2 Jy[2] diff --git a/models/model_steadystate_py/create_splines.cpp b/models/model_steadystate_py/create_splines.cpp new file mode 100644 index 0000000000..c6d71c0e39 --- /dev/null +++ b/models/model_steadystate_py/create_splines.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "amici/splinefunctions.h" +#include +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_steadystate_py { + +std::vector create_splines_model_steadystate_py(const realtype *p, const realtype *k){ + return {}; +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/dJydsigma.cpp b/models/model_steadystate_py/dJydsigma.cpp new file mode 100644 index 0000000000..56a7e6b89e --- /dev/null +++ b/models/model_steadystate_py/dJydsigma.cpp @@ -0,0 +1,32 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" + +namespace amici { +namespace model_model_steadystate_py { + +void dJydsigma_model_steadystate_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydsigma[0] = 1.0/sigma_obs_x1 - 1.0*std::pow(-mobs_x1 + obs_x1, 2)/std::pow(sigma_obs_x1, 3); + break; + case 1: + dJydsigma[1] = 1.0/sigma_obs_x2 - 1.0*std::pow(-mobs_x2 + obs_x2, 2)/std::pow(sigma_obs_x2, 3); + break; + case 2: + dJydsigma[2] = 1.0/sigma_obs_x3 - 1.0*std::pow(-mobs_x3 + obs_x3, 2)/std::pow(sigma_obs_x3, 3); + break; + } +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/dJydy.cpp b/models/model_steadystate_py/dJydy.cpp new file mode 100644 index 0000000000..bd346b1555 --- /dev/null +++ b/models/model_steadystate_py/dJydy.cpp @@ -0,0 +1,78 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_steadystate_py { + +static constexpr std::array, 3> dJydy_colptrs_model_steadystate_py_ = {{ + {0, 1, 1, 1}, + {0, 0, 1, 1}, + {0, 0, 0, 1}, +}}; + +void dJydy_colptrs_model_steadystate_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexptrs(gsl::make_span(dJydy_colptrs_model_steadystate_py_[index])); +} +} // namespace model_model_steadystate_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_steadystate_py { + +static constexpr std::array, 3> dJydy_rowvals_model_steadystate_py_ = {{ + {0}, + {0}, + {0}, +}}; + +void dJydy_rowvals_model_steadystate_py(SUNMatrixWrapper &dJydy, int index){ + dJydy.set_indexvals(gsl::make_span(dJydy_rowvals_model_steadystate_py_[index])); +} +} // namespace model_model_steadystate_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" +#include "my.h" +#include "dJydy.h" + +namespace amici { +namespace model_model_steadystate_py { + +void dJydy_model_steadystate_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my){ + switch(iy) { + case 0: + dJydy[0] = (-1.0*mobs_x1 + 1.0*obs_x1)/std::pow(sigma_obs_x1, 2); + break; + case 1: + dJydy[0] = (-1.0*mobs_x2 + 1.0*obs_x2)/std::pow(sigma_obs_x2, 2); + break; + case 2: + dJydy[0] = (-1.0*mobs_x3 + 1.0*obs_x3)/std::pow(sigma_obs_x3, 2); + break; + } +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/dJydy.h b/models/model_steadystate_py/dJydy.h new file mode 100644 index 0000000000..33d960ca6f --- /dev/null +++ b/models/model_steadystate_py/dJydy.h @@ -0,0 +1,3 @@ +#define dJy0_dobs_x1 dJydy[0] +#define dJy0_dobs_x2_1 dJydy[1] +#define dJy0_dobs_x3_2 dJydy[2] diff --git a/models/model_steadystate_py/dxdotdp_explicit.cpp b/models/model_steadystate_py/dxdotdp_explicit.cpp new file mode 100644 index 0000000000..f6eb174f91 --- /dev/null +++ b/models/model_steadystate_py/dxdotdp_explicit.cpp @@ -0,0 +1,73 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_steadystate_py { + +static constexpr std::array dxdotdp_explicit_colptrs_model_steadystate_py_ = { + 0, 2, 5, 7, 10, 11 +}; + +void dxdotdp_explicit_colptrs_model_steadystate_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexptrs(gsl::make_span(dxdotdp_explicit_colptrs_model_steadystate_py_)); +} +} // namespace model_model_steadystate_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_steadystate_py { + +static constexpr std::array dxdotdp_explicit_rowvals_model_steadystate_py_ = { + 0, 1, 0, 1, 2, 0, 1, 0, 1, 2, 0 +}; + +void dxdotdp_explicit_rowvals_model_steadystate_py(SUNMatrixWrapper &dxdotdp_explicit){ + dxdotdp_explicit.set_indexvals(gsl::make_span(dxdotdp_explicit_rowvals_model_steadystate_py_)); +} +} // namespace model_model_steadystate_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "w.h" +#include "dxdotdp_explicit.h" + +namespace amici { +namespace model_model_steadystate_py { + +void dxdotdp_explicit_model_steadystate_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + ddx1dt_dp1 = -2*std::pow(x1, 2); // dxdotdp_explicit[0] + ddx2dt_dp1 = std::pow(x1, 2); // dxdotdp_explicit[1] + ddx1dt_dp2 = -x1*x2; // dxdotdp_explicit[2] + ddx2dt_dp2 = -x1*x2; // dxdotdp_explicit[3] + ddx3dt_dp2 = x1*x2; // dxdotdp_explicit[4] + ddx1dt_dp3 = 2*x2; // dxdotdp_explicit[5] + ddx2dt_dp3 = -x2; // dxdotdp_explicit[6] + ddx1dt_dp4 = x3; // dxdotdp_explicit[7] + ddx2dt_dp4 = x3; // dxdotdp_explicit[8] + ddx3dt_dp4 = -x3; // dxdotdp_explicit[9] + ddx1dt_dp5 = 1; // dxdotdp_explicit[10] +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/dxdotdp_explicit.h b/models/model_steadystate_py/dxdotdp_explicit.h new file mode 100644 index 0000000000..2ea21418a9 --- /dev/null +++ b/models/model_steadystate_py/dxdotdp_explicit.h @@ -0,0 +1,11 @@ +#define ddx1dt_dp1 dxdotdp_explicit[0] +#define ddx2dt_dp1 dxdotdp_explicit[1] +#define ddx1dt_dp2 dxdotdp_explicit[2] +#define ddx2dt_dp2 dxdotdp_explicit[3] +#define ddx3dt_dp2 dxdotdp_explicit[4] +#define ddx1dt_dp3 dxdotdp_explicit[5] +#define ddx2dt_dp3 dxdotdp_explicit[6] +#define ddx1dt_dp4 dxdotdp_explicit[7] +#define ddx2dt_dp4 dxdotdp_explicit[8] +#define ddx3dt_dp4 dxdotdp_explicit[9] +#define ddx1dt_dp5 dxdotdp_explicit[10] diff --git a/models/model_steadystate_py/dxdotdx_explicit.cpp b/models/model_steadystate_py/dxdotdx_explicit.cpp new file mode 100644 index 0000000000..e9dc972f55 --- /dev/null +++ b/models/model_steadystate_py/dxdotdx_explicit.cpp @@ -0,0 +1,71 @@ +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_steadystate_py { + +static constexpr std::array dxdotdx_explicit_colptrs_model_steadystate_py_ = { + 0, 3, 6, 9 +}; + +void dxdotdx_explicit_colptrs_model_steadystate_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexptrs(gsl::make_span(dxdotdx_explicit_colptrs_model_steadystate_py_)); +} +} // namespace model_model_steadystate_py +} // namespace amici + +#include "amici/sundials_matrix_wrapper.h" +#include "sundials/sundials_types.h" + +#include +#include + +namespace amici { +namespace model_model_steadystate_py { + +static constexpr std::array dxdotdx_explicit_rowvals_model_steadystate_py_ = { + 0, 1, 2, 0, 1, 2, 0, 1, 2 +}; + +void dxdotdx_explicit_rowvals_model_steadystate_py(SUNMatrixWrapper &dxdotdx_explicit){ + dxdotdx_explicit.set_indexvals(gsl::make_span(dxdotdx_explicit_rowvals_model_steadystate_py_)); +} +} // namespace model_model_steadystate_py +} // namespace amici + + + + +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "w.h" +#include "dxdotdx_explicit.h" + +namespace amici { +namespace model_model_steadystate_py { + +void dxdotdx_explicit_model_steadystate_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + ddx1dt_dx1 = -4*p1*x1 - p2*x2; // dxdotdx_explicit[0] + ddx2dt_dx1 = 2*p1*x1 - p2*x2; // dxdotdx_explicit[1] + ddx3dt_dx1 = p2*x2; // dxdotdx_explicit[2] + ddx1dt_dx2 = -p2*x1 + 2*p3; // dxdotdx_explicit[3] + ddx2dt_dx2 = -p2*x1 - p3; // dxdotdx_explicit[4] + ddx3dt_dx2 = p2*x1; // dxdotdx_explicit[5] + ddx1dt_dx3 = p4; // dxdotdx_explicit[6] + ddx2dt_dx3 = p4; // dxdotdx_explicit[7] + ddx3dt_dx3 = -k4 - p4; // dxdotdx_explicit[8] +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/dxdotdx_explicit.h b/models/model_steadystate_py/dxdotdx_explicit.h new file mode 100644 index 0000000000..597980569f --- /dev/null +++ b/models/model_steadystate_py/dxdotdx_explicit.h @@ -0,0 +1,9 @@ +#define ddx1dt_dx1 dxdotdx_explicit[0] +#define ddx2dt_dx1 dxdotdx_explicit[1] +#define ddx3dt_dx1 dxdotdx_explicit[2] +#define ddx1dt_dx2 dxdotdx_explicit[3] +#define ddx2dt_dx2 dxdotdx_explicit[4] +#define ddx3dt_dx2 dxdotdx_explicit[5] +#define ddx1dt_dx3 dxdotdx_explicit[6] +#define ddx2dt_dx3 dxdotdx_explicit[7] +#define ddx3dt_dx3 dxdotdx_explicit[8] diff --git a/models/model_steadystate_py/dydx.cpp b/models/model_steadystate_py/dydx.cpp new file mode 100644 index 0000000000..b3e5241af6 --- /dev/null +++ b/models/model_steadystate_py/dydx.cpp @@ -0,0 +1,22 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_steadystate_py { + +void dydx_model_steadystate_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx){ + dydx[0] = 1; + dydx[4] = 1; + dydx[8] = 1; +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/k.h b/models/model_steadystate_py/k.h new file mode 100644 index 0000000000..364bd02b0a --- /dev/null +++ b/models/model_steadystate_py/k.h @@ -0,0 +1,4 @@ +#define k1 k[0] +#define k2 k[1] +#define k3 k[2] +#define k4 k[3] diff --git a/models/model_steadystate_py/main.cpp b/models/model_steadystate_py/main.cpp new file mode 100644 index 0000000000..ecdff85a46 --- /dev/null +++ b/models/model_steadystate_py/main.cpp @@ -0,0 +1,93 @@ +#include + +#include "wrapfunctions.h" /* model-provided functions */ +#include /* AMICI base functions */ + +template +std::ostream& operator<<(std::ostream& os, std::vector const& v) { + os << "["; + for (typename std::vector::const_iterator ii = v.begin(); ii != v.end(); + ++ii) { + os << " " << *ii; + } + os << "]"; + return os; +} + +/* + * This is a scaffold for a stand-alone AMICI simulation executable + * demonstrating the basic use of the AMICI C++ API. + */ + +int main() { + std::cout << "********************************" << std::endl; + std::cout << "** Running forward simulation **" << std::endl; + std::cout << "********************************" << std::endl << std::endl; + + // Create a model instance + auto model = amici::generic_model::getModel(); + + // Set desired output timepoints + model->setTimepoints({0.0, 1.0, 10.0, 100.0, 1000.0}); + + // Create a solver instance + auto solver = model->getSolver(); + + // Optionally set integration tolerance + solver->setAbsoluteTolerance(1e-16); + solver->setRelativeTolerance(1e-8); + + // Run the simulation using default parameters set during model import + // (can be changed using model->setParameters() or model->setParameterBy*()) + auto rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print observable time course + auto observable_ids = model->getObservableIds(); + std::cout << "Simulated observables for timepoints " << rdata->ts << "\n\n"; + for (int i_observable = 0; i_observable < rdata->ny; ++i_observable) { + std::cout << observable_ids[i_observable] << ":\n\t"; + for (int i_time = 0; i_time < rdata->nt; ++i_time) { + // rdata->y is a flat 2D array in row-major ordering + std::cout << rdata->y[i_time * rdata->ny + i_observable] << " "; + } + std::cout << std::endl << std::endl; + } + + std::cout << std::endl; + std::cout << "**********************************" << std::endl; + std::cout << "** Forward sensitivity analysis **" << std::endl; + std::cout << "**********************************" << std::endl << std::endl; + + // Enable first-order sensitivity analysis + solver->setSensitivityOrder(amici::SensitivityOrder::first); + // Use forward sensitivities + solver->setSensitivityMethod(amici::SensitivityMethod::forward); + + // Run the simulation + rdata = runAmiciSimulation(*solver, nullptr, *model); + + // Print state sensitivities sx... + // ... for the first timepoint... + int i_time = 0; + // ... with respect to the first parameter + int i_nplist = 0; + + // get identifiers from model + auto state_ids = model->getStateIds(); + auto parameter_ids = model->getParameterIds(); + + std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] + << std::endl; // nt x nplist x nx + for (int i_state = 0; i_state < rdata->nx; ++i_state) { + std::cout << "\td(" << state_ids[i_state] << ")/d(" + << parameter_ids[model->plist(i_nplist)] << ") = "; + + // rdata->sx is a flat 3D array in row-major ordering + std::cout << rdata->sx + [i_time * rdata->nplist * rdata->nx + + i_nplist * rdata->nx + i_state]; + std::cout << std::endl; + } + + return 0; +} diff --git a/models/model_steadystate_py/model_steadystate_py.cpp b/models/model_steadystate_py/model_steadystate_py.cpp new file mode 100644 index 0000000000..02962c732f --- /dev/null +++ b/models/model_steadystate_py/model_steadystate_py.cpp @@ -0,0 +1,86 @@ +#include +#include + +namespace amici { + +namespace model_model_steadystate_py { + +// clang-format off + +std::array parameterNames = { + "p1", // p[0] +"p2", // p[1] +"p3", // p[2] +"p4", // p[3] +"p5", // p[4] +}; + +std::array fixedParameterNames = { + "k1", // k[0] +"k2", // k[1] +"k3", // k[2] +"k4", // k[3] +}; + +std::array stateNames = { + "x1", // x_rdata[0] +"x2", // x_rdata[1] +"x3", // x_rdata[2] +}; + +std::array observableNames = { + "y0", // y[0] +"y1", // y[1] +"y2", // y[2] +}; + +std::array observableScalings = { + ObservableScaling::lin, // y[0] +ObservableScaling::lin, // y[1] +ObservableScaling::lin, // y[2] +}; + +std::array expressionNames = { + "flux_r0", // w[0] +}; + +std::array parameterIds = { + "p1", // p[0] +"p2", // p[1] +"p3", // p[2] +"p4", // p[3] +"p5", // p[4] +}; + +std::array fixedParameterIds = { + "k1", // k[0] +"k2", // k[1] +"k3", // k[2] +"k4", // k[3] +}; + +std::array stateIds = { + "x1", // x_rdata[0] +"x2", // x_rdata[1] +"x3", // x_rdata[2] +}; + +std::array observableIds = { + "obs_x1", // y[0] +"obs_x2", // y[1] +"obs_x3", // y[2] +}; + +std::array expressionIds = { + "flux_r0", // w[0] +}; + +std::array stateIdxsSolver = { + 0, 1, 2 +}; + +// clang-format on + +} // namespace model_model_steadystate_py + +} // namespace amici diff --git a/models/model_steadystate_py/model_steadystate_py.h b/models/model_steadystate_py/model_steadystate_py.h new file mode 100644 index 0000000000..289857eb02 --- /dev/null +++ b/models/model_steadystate_py/model_steadystate_py.h @@ -0,0 +1,555 @@ +#ifndef _amici_TPL_MODELNAME_h +#define _amici_TPL_MODELNAME_h +#include +#include +#include + +#include "amici/model_ode.h" +#include "amici/splinefunctions.h" +#include "amici/event.h" + +namespace amici { + +class Solver; + +namespace model_model_steadystate_py { + +extern std::array parameterNames; +extern std::array fixedParameterNames; +extern std::array stateNames; +extern std::array observableNames; +extern std::array observableScalings; +extern std::array expressionNames; +extern std::array parameterIds; +extern std::array fixedParameterIds; +extern std::array stateIds; +extern std::array observableIds; +extern std::array expressionIds; +extern std::array stateIdxsSolver; + +extern void Jy_model_steadystate_py(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydsigma_model_steadystate_py(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_model_steadystate_py(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my); +extern void dJydy_colptrs_model_steadystate_py(SUNMatrixWrapper &colptrs, int index); +extern void dJydy_rowvals_model_steadystate_py(SUNMatrixWrapper &rowvals, int index); + + + + + + + + + + + + + + + + + + + +extern void dxdotdp_explicit_model_steadystate_py(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void dxdotdp_explicit_colptrs_model_steadystate_py(SUNMatrixWrapper &colptrs); +extern void dxdotdp_explicit_rowvals_model_steadystate_py(SUNMatrixWrapper &rowvals); +extern void dxdotdx_explicit_model_steadystate_py(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void dxdotdx_explicit_colptrs_model_steadystate_py(SUNMatrixWrapper &colptrs); +extern void dxdotdx_explicit_rowvals_model_steadystate_py(SUNMatrixWrapper &rowvals); +extern void dydx_model_steadystate_py(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx); + + + + + +extern void sigmay_model_steadystate_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y); + + + + + +extern void x0_model_steadystate_py(realtype *x0, const realtype t, const realtype *p, const realtype *k); +extern void x0_fixedParameters_model_steadystate_py(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs); + +extern void sx0_fixedParameters_model_steadystate_py(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs); +extern void xdot_model_steadystate_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); +extern void y_model_steadystate_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w); + + + + + + + + +extern void x_solver_model_steadystate_py(realtype *x_solver, const realtype *x_rdata); + + + + + + + + + + + + +extern std::vector create_splines_model_steadystate_py(const realtype *p, const realtype *k); + + + +/** + * @brief AMICI-generated model subclass. + */ +class Model_model_steadystate_py : public amici::Model_ODE { + public: + /** + * @brief Default constructor. + */ + Model_model_steadystate_py() + : amici::Model_ODE( + amici::ModelDimensions( + 3, // nx_rdata + 3, // nxtrue_rdata + 3, // nx_solver + 3, // nxtrue_solver + 0, // nx_solver_reinit + 5, // np + 4, // nk + 3, // ny + 3, // nytrue + 0, // nz + 0, // nztrue + 0, // nevent + 0, // nevent_solver + 0, // nspl + 1, // nobjective + 1, // nw + 0, // ndwdx + 0, // ndwdp + 0, // ndwdw + 0, // ndxdotdw + std::vector{1, 1, 1}, // ndjydy + 0, // ndxrdatadxsolver + 0, // ndxrdatadtcl + 0, // ndtotal_cldx_rdata + 0, // nnz + 3, // ubw + 3, // lbw + true, // pythonGenerated + 11, // ndxdotdp_explicit + 9, // ndxdotdx_explicit + 0 // w_recursion_depth + ), + amici::SimulationParameters( + std::vector{0.10000000000000001, 0.40000000000000002, 0.69999999999999996, 1.0}, // fixedParameters + std::vector{1.0, 0.5, 0.40000000000000002, 2.0, 0.10000000000000001} // dynamic parameters + ), + amici::SecondOrderMode::none, // o2mode + std::vector{1.0, 1.0, 1.0}, // idlist + std::vector{}, // z2events + std::vector{}, // events + {} // state-independent events + ) { + } + + /** + * @brief Clone this model instance. + * @return A deep copy of this instance. + */ + amici::Model *clone() const override { + return new Model_model_steadystate_py(*this); + } + + void fJrz(realtype *Jrz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fJy(realtype *Jy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + Jy_model_steadystate_py(Jy, iy, p, k, y, sigmay, my); + } + + + void fJz(realtype *Jz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override {} + + + void fdJrzdsigma(realtype *dJrzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fdJrzdz(realtype *dJrzdz, const int iz, const realtype *p, const realtype *k, const realtype *rz, const realtype *sigmaz) override {} + + + void fdJydsigma(realtype *dJydsigma, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydsigma_model_steadystate_py(dJydsigma, iy, p, k, y, sigmay, my); + } + + + void fdJzdsigma(realtype *dJzdsigma, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const realtype *mz) override {} + + + void fdJzdz(realtype *dJzdz, const int iz, const realtype *p, const realtype *k, const realtype *z, const realtype *sigmaz, const double *mz) override {} + + + void fdeltax(double *deltax, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old) override {} + + + void fdeltasx(realtype *deltasx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *sx, const realtype *stau, const realtype *tcl, const realtype *x_old) override {} + + + void fdeltaxB(realtype *deltaxB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB, const realtype *tcl) override {} + + + void fdeltaqB(realtype *deltaqB, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const int ip, const int ie, const realtype *xdot, const realtype *xdot_old, const realtype *x_old, const realtype *xB) override {} + + + void fdrzdp(realtype *drzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdrzdx(realtype *drzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void fdsigmaydp(realtype *dsigmaydp, const realtype t, const realtype *p, const realtype *k, const realtype *y, const int ip) override {} + + + void fdsigmaydy(realtype *dsigmaydy, const realtype t, const realtype *p, const realtype *k, const realtype *y) override {} + + + void fdsigmazdp(realtype *dsigmazdp, const realtype t, const realtype *p, const realtype *k, const int ip) override {} + + + void fdJydy(realtype *dJydy, const int iy, const realtype *p, const realtype *k, const realtype *y, const realtype *sigmay, const realtype *my) override { + dJydy_model_steadystate_py(dJydy, iy, p, k, y, sigmay, my); + } + + void fdJydy_colptrs(SUNMatrixWrapper &colptrs, int index) override { + dJydy_colptrs_model_steadystate_py(colptrs, index); + } + + void fdJydy_rowvals(SUNMatrixWrapper &rowvals, int index) override { + dJydy_rowvals_model_steadystate_py(rowvals, index); + } + + + std::vector fcreate_splines(const realtype *p, const realtype *k) override { + return create_splines_model_steadystate_py(p, k); + } + + void fdspline_valuesdp(realtype *dspline_valuesdp, const realtype *p, const realtype *k, const int ip) override {} + + void fdspline_slopesdp(realtype *dspline_slopesdp, const realtype *p, const realtype *k, const int ip) override {} + + + void fdwdp(realtype *dwdp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl, bool include_static) override {} + + void fdwdp_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdp_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdx(realtype *dwdx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, const realtype *spl, bool include_static) override {} + + void fdwdx_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdx_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdwdw(realtype *dwdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *tcl, bool include_static) override {} + + void fdwdw_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdwdw_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdw(realtype *dxdotdw, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override {} + + void fdxdotdw_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdxdotdw_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdxdotdp_explicit(realtype *dxdotdp_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + dxdotdp_explicit_model_steadystate_py(dxdotdp_explicit, t, x, p, k, h, w); + } + + void fdxdotdp_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdp_explicit_colptrs_model_steadystate_py(colptrs); + } + + void fdxdotdp_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdp_explicit_rowvals_model_steadystate_py(rowvals); + } + + + void fdxdotdx_explicit(realtype *dxdotdx_explicit, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + dxdotdx_explicit_model_steadystate_py(dxdotdx_explicit, t, x, p, k, h, w); + } + + void fdxdotdx_explicit_colptrs(SUNMatrixWrapper &colptrs) override { + dxdotdx_explicit_colptrs_model_steadystate_py(colptrs); + } + + void fdxdotdx_explicit_rowvals(SUNMatrixWrapper &rowvals) override { + dxdotdx_explicit_rowvals_model_steadystate_py(rowvals); + } + + + void fdydx(realtype *dydx, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w, const realtype *dwdx) override { + dydx_model_steadystate_py(dydx, t, x, p, k, h, w, dwdx); + } + + + void fdydp(realtype *dydp, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip, const realtype *w, const realtype *tcl, const realtype *dtcldp, const realtype *spl, const realtype *sspl) override {} + + + void fdzdp(realtype *dzdp, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const int ip) override {} + + + void fdzdx(realtype *dzdx, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void froot(realtype *root, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl) override {} + + + void frz(realtype *rz, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + void fsigmay(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y) override { + sigmay_model_steadystate_py(sigmay, t, p, k, y); + } + + + void fsigmaz(realtype *sigmaz, const realtype t, const realtype *p, const realtype *k) override {} + + + void fstau(realtype *stau, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *dx, const realtype *tcl, const realtype *sx, const int ip, const int ie) override {} + + void fsx0(realtype *sx0, const realtype t, const realtype *x, const realtype *p, const realtype *k, const int ip) override {} + + void fsx0_fixedParameters(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs) override { + sx0_fixedParameters_model_steadystate_py(sx0_fixedParameters, t, x0, p, k, ip, reinitialization_state_idxs); + } + + + void fw(realtype *w, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl, const realtype *spl, bool include_static) override {} + + + void fx0(realtype *x0, const realtype t, const realtype *p, const realtype *k) override { + x0_model_steadystate_py(x0, t, p, k); + } + + + void fx0_fixedParameters(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs) override { + x0_fixedParameters_model_steadystate_py(x0_fixedParameters, t, p, k, reinitialization_state_idxs); + } + + + void fxdot(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + xdot_model_steadystate_py(xdot, t, x, p, k, h, w); + } + + + void fy(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w) override { + y_model_steadystate_py(y, t, x, p, k, h, w); + } + + + void fz(realtype *z, const int ie, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h) override {} + + + + + void fx_solver(realtype *x_solver, const realtype *x_rdata) override { + x_solver_model_steadystate_py(x_solver, x_rdata); + } + + + void ftotal_cl(realtype *total_cl, const realtype *x_rdata, const realtype *p, const realtype *k) override {} + + + void fdx_rdatadx_solver(realtype *dx_rdatadx_solver, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadx_solver_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadx_solver_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdx_rdatadp(realtype *dx_rdatadp, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k, const int ip) override {} + + + void fdx_rdatadtcl(realtype *dx_rdatadtcl, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k) override {} + + void fdx_rdatadtcl_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdx_rdatadtcl_rowvals(SUNMatrixWrapper &rowvals) override {} + + + void fdtotal_cldp(realtype *dtotal_cldp, const realtype *x_rdata, const realtype *p, const realtype *k, const int ip) override {} + + + void fdtotal_cldx_rdata(realtype *dtotal_cldx_rdata, const realtype *x_rdata, const realtype *p, const realtype *k, const realtype *tcl) override {} + + void fdtotal_cldx_rdata_colptrs(SUNMatrixWrapper &colptrs) override {} + + void fdtotal_cldx_rdata_rowvals(SUNMatrixWrapper &rowvals) override {} + + + std::string getName() const override { + return "model_steadystate_py"; + } + + /** + * @brief Get names of the model parameters + * @return the names + */ + std::vector getParameterNames() const override { + return std::vector(parameterNames.begin(), + parameterNames.end()); + } + + /** + * @brief Get names of the model states + * @return the names + */ + std::vector getStateNames() const override { + return std::vector(stateNames.begin(), stateNames.end()); + } + + /** + * @brief Get names of the solver states + * @return the names + */ + std::vector getStateNamesSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto const idx: stateIdxsSolver) { + result.push_back(stateNames[idx]); + } + return result; + } + + /** + * @brief Get names of the fixed model parameters + * @return the names + */ + std::vector getFixedParameterNames() const override { + return std::vector(fixedParameterNames.begin(), + fixedParameterNames.end()); + } + + /** + * @brief Get names of the observables + * @return the names + */ + std::vector getObservableNames() const override { + return std::vector(observableNames.begin(), + observableNames.end()); + } + + /** + * @brief Get names of model expressions + * @return Expression names + */ + std::vector getExpressionNames() const override { + return std::vector(expressionNames.begin(), + expressionNames.end()); + } + + /** + * @brief Get ids of the model parameters + * @return the ids + */ + std::vector getParameterIds() const override { + return std::vector(parameterIds.begin(), + parameterIds.end()); + } + + /** + * @brief Get ids of the model states + * @return the ids + */ + std::vector getStateIds() const override { + return std::vector(stateIds.begin(), stateIds.end()); + } + + /** + * @brief Get ids of the solver states + * @return the ids + */ + std::vector getStateIdsSolver() const override { + std::vector result; + result.reserve(stateIdxsSolver.size()); + for(auto idx: stateIdxsSolver) { + result.push_back(stateIds[idx]); + } + return result; + } + + /** + * @brief Get ids of the fixed model parameters + * @return the ids + */ + std::vector getFixedParameterIds() const override { + return std::vector(fixedParameterIds.begin(), + fixedParameterIds.end()); + } + + /** + * @brief Get ids of the observables + * @return the ids + */ + std::vector getObservableIds() const override { + return std::vector(observableIds.begin(), + observableIds.end()); + } + + /** + * @brief Get IDs of model expressions + * @return Expression IDs + */ + std::vector getExpressionIds() const override { + return std::vector(expressionIds.begin(), + expressionIds.end()); + } + + /** + * @brief function indicating whether reinitialization of states depending + * on fixed parameters is permissible + * @return flag indicating whether reinitialization of states depending on + * fixed parameters is permissible + */ + bool isFixedParameterStateReinitializationAllowed() const override { + return true; + } + + /** + * @brief returns the AMICI version that was used to generate the model + * @return AMICI version string + */ + std::string getAmiciVersion() const override { + return "0.33.0"; + } + + /** + * @brief returns the amici version that was used to generate the model + * @return AMICI git commit hash + */ + std::string getAmiciCommit() const override { + return "bcedb951ddf674996b269489d74f9b86112038ff"; + } + + bool hasQuadraticLLH() const override { + return true; + } + + ObservableScaling getObservableScaling(int iy) const override { + return observableScalings.at(iy); + } +}; + + +} // namespace model_model_steadystate_py + +} // namespace amici + +#endif /* _amici_TPL_MODELNAME_h */ diff --git a/models/model_steadystate_py/my.h b/models/model_steadystate_py/my.h new file mode 100644 index 0000000000..2e142e7fb5 --- /dev/null +++ b/models/model_steadystate_py/my.h @@ -0,0 +1,3 @@ +#define mobs_x1 my[0] +#define mobs_x2 my[1] +#define mobs_x3 my[2] diff --git a/models/model_steadystate_py/p.h b/models/model_steadystate_py/p.h new file mode 100644 index 0000000000..60d63a258c --- /dev/null +++ b/models/model_steadystate_py/p.h @@ -0,0 +1,5 @@ +#define p1 p[0] +#define p2 p[1] +#define p3 p[2] +#define p4 p[3] +#define p5 p[4] diff --git a/models/model_steadystate_py/setup.py b/models/model_steadystate_py/setup.py new file mode 100644 index 0000000000..5d55a98edc --- /dev/null +++ b/models/model_steadystate_py/setup.py @@ -0,0 +1,95 @@ +"""AMICI model package setup""" + +import os +import sys +from pathlib import Path + +from amici import _get_amici_path +from amici.custom_commands import AmiciBuildCMakeExtension +from cmake_build_extension import CMakeExtension +from setuptools import find_namespace_packages, setup +import importlib.metadata + + +def get_extension() -> CMakeExtension: + """Get setuptools extension object for this AMICI model package""" + + # Build shared object + prefix_path = Path(_get_amici_path()) + AmiciBuildCMakeExtension.extend_cmake_prefix_path(str(prefix_path)) + + # handle parallel building + # Note: can be empty to use all hardware threads + if (parallel_jobs := os.environ.get("AMICI_PARALLEL_COMPILE")) is not None: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = parallel_jobs + else: + os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = "1" + + debug_build = os.getenv("ENABLE_AMICI_DEBUGGING", "").lower() in [ + "1", + "true", + ] or os.getenv("ENABLE_GCOV_COVERAGE", "").lower() in ["1", "true"] + + cmake_prefix_path = os.getenv("CMAKE_PREFIX_PATH", "").split(os.pathsep) + cmake_prefix_path.append(prefix_path.as_posix()) + + # If scipy_openblas64 is installed, we make its cmake configuration + # available + amici_distribution = importlib.metadata.distribution("amici") + amici_dir = Path(amici_distribution.locate_file("")) + # this path is created during the amici build if scipy_openblas64 is used + openblas_cmake_dir = amici_dir / "lib" / "cmake" / "openblas" + if openblas_cmake_dir.exists(): + cmake_prefix_path.append(str(openblas_cmake_dir)) + + return CMakeExtension( + name="model_ext", + source_dir=os.getcwd(), + install_prefix="model_steadystate_py", + cmake_configure_options=[ + "-DCMAKE_VERBOSE_MAKEFILE=ON", + f"-DCMAKE_PREFIX_PATH='{';'.join(cmake_prefix_path)}'", + "-DAMICI_PYTHON_BUILD_EXT_ONLY=ON", + f"-DPython3_EXECUTABLE={Path(sys.executable).as_posix()}", + ], + cmake_build_type="Debug" if debug_build else "Release", + ) + + +# Change working directory to setup.py location +os.chdir(os.path.dirname(os.path.abspath(__file__))) + +MODEL_EXT = get_extension() + +CLASSIFIERS = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Science/Research", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python", + "Programming Language :: C++", + "Topic :: Scientific/Engineering :: Bio-Informatics", +] + +CMDCLASS = { + # for CMake-based builds + "build_ext": AmiciBuildCMakeExtension, +} + +# Install +setup( + name="model_steadystate_py", + cmdclass=CMDCLASS, + version="0.1.0", + description="AMICI-generated module for model model_steadystate_py", + url="https://github.com/AMICI-dev/AMICI", + author="model-author-todo", + author_email="model-author-todo", + ext_modules=[MODEL_EXT], + packages=find_namespace_packages(), + install_requires=["amici==0.33.0"], + python_requires=">=3.11", + package_data={}, + zip_safe=False, + classifiers=CLASSIFIERS, +) diff --git a/models/model_steadystate_py/sigmay.cpp b/models/model_steadystate_py/sigmay.cpp new file mode 100644 index 0000000000..7fb10529dc --- /dev/null +++ b/models/model_steadystate_py/sigmay.cpp @@ -0,0 +1,23 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" +#include "y.h" +#include "sigmay.h" + +namespace amici { +namespace model_model_steadystate_py { + +void sigmay_model_steadystate_py(realtype *sigmay, const realtype t, const realtype *p, const realtype *k, const realtype *y){ + sigma_obs_x1 = 1.0; // sigmay[0] + sigma_obs_x2 = 1.0; // sigmay[1] + sigma_obs_x3 = 1.0; // sigmay[2] +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/sigmay.h b/models/model_steadystate_py/sigmay.h new file mode 100644 index 0000000000..6aaf381974 --- /dev/null +++ b/models/model_steadystate_py/sigmay.h @@ -0,0 +1,3 @@ +#define sigma_obs_x1 sigmay[0] +#define sigma_obs_x2 sigmay[1] +#define sigma_obs_x3 sigmay[2] diff --git a/models/model_steadystate_py/swig/CMakeLists.txt b/models/model_steadystate_py/swig/CMakeLists.txt new file mode 100644 index 0000000000..314996c479 --- /dev/null +++ b/models/model_steadystate_py/swig/CMakeLists.txt @@ -0,0 +1,60 @@ +if(DEFINED ENV{SWIG}) + set(SWIG_EXECUTABLE $ENV{SWIG}) +endif() + +find_package(SWIG REQUIRED) +include(${SWIG_USE_FILE}) + +if(DEFINED ENV{PYTHON_EXECUTABLE}) + set(Python3_EXECUTABLE $ENV{PYTHON_EXECUTABLE}) +endif() +# We don't need "Interpreter" here, but without that, FindPython3 will +# ignore the Python version selected via $Python3_EXECUTABLE +find_package(Python3 COMPONENTS Interpreter Development) +include_directories(${Python3_INCLUDE_DIRS}) + +set(SWIG_LIBRARY_NAME _${PROJECT_NAME}) +set(CMAKE_SWIG_FLAGS "") +set_source_files_properties(${PROJECT_NAME}.i PROPERTIES CPLUSPLUS ON) + +# swig does not use INTERFACE_INCLUDE_DIRS of linked libraries, so add manually +get_target_property(AMICI_INCLUDE_DIRS Upstream::amici INTERFACE_INCLUDE_DIRECTORIES) +include_directories(${AMICI_INCLUDE_DIRS} .. ${AMICI_INCLUDE_DIRS}/../swig) + +swig_add_library(${SWIG_LIBRARY_NAME} + TYPE MODULE + LANGUAGE python + SOURCES ${PROJECT_NAME}.i) + + +set_target_properties(${SWIG_LIBRARY_NAME} + PROPERTIES + SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE + PREFIX "" +) + +# Python extension suffix +execute_process( + COMMAND ${Python3_EXECUTABLE} -c + "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))" + OUTPUT_VARIABLE PY_EXT_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE) +if(NOT "${PY_EXT_SUFFIX}" STREQUAL "") + message(STATUS "Python extension suffix is ${PY_EXT_SUFFIX}") + set_target_properties(${SWIG_LIBRARY_NAME} PROPERTIES SUFFIX "${PY_EXT_SUFFIX}" ) +endif() + + +swig_link_libraries(${SWIG_LIBRARY_NAME} + ${Python3_LIBRARIES} + model) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.py + $ DESTINATION .) + +# configure module setup script +set(SETUP_PY_IN ${Amici_DIR}/model_setup.template.py) +set(SETUP_PY_OUT ${CMAKE_CURRENT_BINARY_DIR}/setup.py) + +add_custom_target(install-python + DEPENDS ${SWIG_LIBRARY_NAME} + COMMAND python ${SETUP_PY_OUT} install) diff --git a/models/model_steadystate_py/swig/model_steadystate_py.i b/models/model_steadystate_py/swig/model_steadystate_py.i new file mode 100644 index 0000000000..0ca0516bcf --- /dev/null +++ b/models/model_steadystate_py/swig/model_steadystate_py.i @@ -0,0 +1,82 @@ +%define MODULEIMPORT +" +import amici +import datetime +import importlib.util +import os +import sysconfig +from pathlib import Path + +ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +_model_steadystate_py = amici._module_from_path( + 'model_steadystate_py._model_steadystate_py' if __package__ or '.' in __name__ + else '_model_steadystate_py', + Path(__file__).parent / f'_model_steadystate_py{ext_suffix}', +) + +def _get_import_time(): + return _model_steadystate_py._get_import_time() + +t_imported = _get_import_time() +t_modified = os.path.getmtime(__file__) +if t_imported < t_modified: + t_imp_str = datetime.datetime.fromtimestamp(t_imported).isoformat() + t_mod_str = datetime.datetime.fromtimestamp(t_modified).isoformat() + module_path = Path(__file__).resolve() + raise RuntimeError( + f'Cannot import extension for model_steadystate_py from ' + f'{module_path}, because an extension in the same location ' + f'has already been imported, but the file was modified on ' + f'disk. \\nImported at {t_imp_str}\\nModified at {t_mod_str}.\\n' + 'Import the module with a different name or restart the ' + 'Python kernel.' + ) +" +%enddef + +%module(package="model_steadystate_py",moduleimport=MODULEIMPORT) model_steadystate_py + +%pythoncode %{ +# the model-package __init__.py module (will be set during import) +_model_module = None + + +%} + +%import amici.i +// Add necessary symbols to generated header + +%{ +#include "wrapfunctions.h" +#include "amici/model_ode.h" +#include "amici/model_dae.h" +using namespace amici; +%} + +// store the time a module was imported +%{ +#include +static std::chrono::time_point _module_import_time; + +static double _get_import_time() { + auto epoch = _module_import_time.time_since_epoch(); + return std::chrono::duration(epoch).count(); +} +%} + +static double _get_import_time(); + +%init %{ + _module_import_time = std::chrono::system_clock::now(); +%} + + +// Make model module accessible from the model +%feature("pythonappend") amici::generic_model::getModel %{ + if '.' in __name__: + val.module = _model_module +%} + + +// Process symbols in header +%include "wrapfunctions.h" diff --git a/models/model_steadystate_py/sx0_fixedParameters.cpp b/models/model_steadystate_py/sx0_fixedParameters.cpp new file mode 100644 index 0000000000..4f6ac58d41 --- /dev/null +++ b/models/model_steadystate_py/sx0_fixedParameters.cpp @@ -0,0 +1,25 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_steadystate_py { + +void sx0_fixedParameters_model_steadystate_py(realtype *sx0_fixedParameters, const realtype t, const realtype *x0, const realtype *p, const realtype *k, const int ip, gsl::span reinitialization_state_idxs){ + static const std::array _x0_fixedParameters_idxs = { + 0, 1, 2 + }; + for(auto idx: reinitialization_state_idxs) { + if(std::find(_x0_fixedParameters_idxs.cbegin(), _x0_fixedParameters_idxs.cend(), idx) != _x0_fixedParameters_idxs.cend()) + sx0_fixedParameters[idx] = 0.0; + } +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/w.h b/models/model_steadystate_py/w.h new file mode 100644 index 0000000000..c399413a8c --- /dev/null +++ b/models/model_steadystate_py/w.h @@ -0,0 +1 @@ +#define flux_r0 w[0] diff --git a/models/model_steadystate_py/wrapfunctions.cpp b/models/model_steadystate_py/wrapfunctions.cpp new file mode 100644 index 0000000000..a7fa2126e3 --- /dev/null +++ b/models/model_steadystate_py/wrapfunctions.cpp @@ -0,0 +1,16 @@ +#include "wrapfunctions.h" +#include "model_steadystate_py.h" +#include "amici/model.h" + +namespace amici { +namespace generic_model { + +std::unique_ptr getModel() { + return std::unique_ptr( + new amici::model_model_steadystate_py::Model_model_steadystate_py() + ); +} + +} // namespace generic_model + +} // namespace amici diff --git a/models/model_steadystate_py/wrapfunctions.h b/models/model_steadystate_py/wrapfunctions.h new file mode 100644 index 0000000000..33c8a9d819 --- /dev/null +++ b/models/model_steadystate_py/wrapfunctions.h @@ -0,0 +1,25 @@ +#ifndef _amici_wrapfunctions_h +#define _amici_wrapfunctions_h + +#include + +#include "amici/model.h" + +namespace amici { +namespace generic_model { + + +/** + * @brief Wrapper function to instantiate the linked Amici model without knowing + * the name at compile time. + * @return Model instance + */ +std::unique_ptr getModel(); + + +} // namespace generic_model + +} // namespace amici + + +#endif /* _amici_wrapfunctions_h */ diff --git a/models/model_steadystate_py/x.h b/models/model_steadystate_py/x.h new file mode 100644 index 0000000000..7c21f2ef67 --- /dev/null +++ b/models/model_steadystate_py/x.h @@ -0,0 +1,3 @@ +#define x1 x[0] +#define x2 x[1] +#define x3 x[2] diff --git a/models/model_steadystate_py/x0.cpp b/models/model_steadystate_py/x0.cpp new file mode 100644 index 0000000000..29d7f0883b --- /dev/null +++ b/models/model_steadystate_py/x0.cpp @@ -0,0 +1,21 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_steadystate_py { + +void x0_model_steadystate_py(realtype *x0, const realtype t, const realtype *p, const realtype *k){ + x0[0] = k1; + x0[1] = k2; + x0[2] = k3; +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/x0_fixedParameters.cpp b/models/model_steadystate_py/x0_fixedParameters.cpp new file mode 100644 index 0000000000..3bba2b4ff3 --- /dev/null +++ b/models/model_steadystate_py/x0_fixedParameters.cpp @@ -0,0 +1,24 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_steadystate_py { + +void x0_fixedParameters_model_steadystate_py(realtype *x0_fixedParameters, const realtype t, const realtype *p, const realtype *k, gsl::span reinitialization_state_idxs){ + if(std::find(reinitialization_state_idxs.cbegin(), reinitialization_state_idxs.cend(), 0) != reinitialization_state_idxs.cend()) + x0_fixedParameters[0] = k1; + if(std::find(reinitialization_state_idxs.cbegin(), reinitialization_state_idxs.cend(), 1) != reinitialization_state_idxs.cend()) + x0_fixedParameters[1] = k2; + if(std::find(reinitialization_state_idxs.cbegin(), reinitialization_state_idxs.cend(), 2) != reinitialization_state_idxs.cend()) + x0_fixedParameters[2] = k3; +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/x_rdata.cpp b/models/model_steadystate_py/x_rdata.cpp new file mode 100644 index 0000000000..1b7afb78af --- /dev/null +++ b/models/model_steadystate_py/x_rdata.cpp @@ -0,0 +1,22 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_steadystate_py { + +void x_rdata_model_steadystate_py(realtype *x_rdata, const realtype *x, const realtype *tcl, const realtype *p, const realtype *k){ + x_rdata[0] = x1; + x_rdata[1] = x2; + x_rdata[2] = x3; +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/x_rdata.h b/models/model_steadystate_py/x_rdata.h new file mode 100644 index 0000000000..4b2aa926d2 --- /dev/null +++ b/models/model_steadystate_py/x_rdata.h @@ -0,0 +1,3 @@ +#define x1 x_rdata[0] +#define x2 x_rdata[1] +#define x3 x_rdata[2] diff --git a/models/model_steadystate_py/x_solver.cpp b/models/model_steadystate_py/x_solver.cpp new file mode 100644 index 0000000000..ad970c7e1a --- /dev/null +++ b/models/model_steadystate_py/x_solver.cpp @@ -0,0 +1,20 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x_rdata.h" + +namespace amici { +namespace model_model_steadystate_py { + +void x_solver_model_steadystate_py(realtype *x_solver, const realtype *x_rdata){ + x_solver[0] = x1; + x_solver[1] = x2; + x_solver[2] = x3; +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/x_solver.h b/models/model_steadystate_py/x_solver.h new file mode 100644 index 0000000000..ef1d32a257 --- /dev/null +++ b/models/model_steadystate_py/x_solver.h @@ -0,0 +1,3 @@ +#define x_solver0 x_solver[0] +#define x_solver1 x_solver[1] +#define x_solver2 x_solver[2] diff --git a/models/model_steadystate_py/xdot.cpp b/models/model_steadystate_py/xdot.cpp new file mode 100644 index 0000000000..9935400d7b --- /dev/null +++ b/models/model_steadystate_py/xdot.cpp @@ -0,0 +1,24 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" +#include "w.h" +#include "xdot.h" + +namespace amici { +namespace model_model_steadystate_py { + +void xdot_model_steadystate_py(realtype *xdot, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + dx1dt = -2*p1*std::pow(x1, 2) - p2*x1*x2 + 2*p3*x2 + p4*x3 + p5; // xdot[0] + dx2dt = p1*std::pow(x1, 2) - p2*x1*x2 - p3*x2 + p4*x3; // xdot[1] + dx3dt = -k4*x3 + p2*x1*x2 - p4*x3; // xdot[2] +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/xdot.h b/models/model_steadystate_py/xdot.h new file mode 100644 index 0000000000..f58eec3752 --- /dev/null +++ b/models/model_steadystate_py/xdot.h @@ -0,0 +1,3 @@ +#define dx1dt xdot[0] +#define dx2dt xdot[1] +#define dx3dt xdot[2] diff --git a/models/model_steadystate_py/y.cpp b/models/model_steadystate_py/y.cpp new file mode 100644 index 0000000000..8a3f87e4ee --- /dev/null +++ b/models/model_steadystate_py/y.cpp @@ -0,0 +1,22 @@ +#include "amici/symbolic_functions.h" +#include "amici/defines.h" +#include "sundials/sundials_types.h" + +#include +#include + +#include "x.h" +#include "p.h" +#include "k.h" + +namespace amici { +namespace model_model_steadystate_py { + +void y_model_steadystate_py(realtype *y, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *w){ + y[0] = x1; + y[1] = x2; + y[2] = x3; +} + +} // namespace model_model_steadystate_py +} // namespace amici diff --git a/models/model_steadystate_py/y.h b/models/model_steadystate_py/y.h new file mode 100644 index 0000000000..97f7b0ea74 --- /dev/null +++ b/models/model_steadystate_py/y.h @@ -0,0 +1,3 @@ +#define obs_x1 y[0] +#define obs_x2 y[1] +#define obs_x3 y[2] diff --git a/python/sdist/amici/gradient_check.py b/python/sdist/amici/gradient_check.py index 86980e58c4..3b6f86572d 100644 --- a/python/sdist/amici/gradient_check.py +++ b/python/sdist/amici/gradient_check.py @@ -344,8 +344,18 @@ def _check_results( :param rtol: relative tolerance for comparison """ + if field in ("rdrm", "messages"): + return result = rdata[field] + + if isinstance(result, str): + if result != expected: + raise AssertionError( + f"Expected {expected} but got {result} for field {field}" + ) + return + if type(result) is float: # noqa E721 result = np.array(result) diff --git a/python/sdist/amici/testing/models.py b/python/sdist/amici/testing/models.py new file mode 100644 index 0000000000..542d6bb8ae --- /dev/null +++ b/python/sdist/amici/testing/models.py @@ -0,0 +1,673 @@ +"""Test models used by AMICI.""" + +from .. import import_model_module, Model +from ..antimony_import import antimony2amici, antimony2sbml +from pathlib import Path +import libsbml +from amici import SbmlImporter, AmiciModel +import sys +import tempfile +from amici.sbml_utils import amici_time_symbol +import sympy as sp +from amici.splines import CubicHermiteSpline + +model_dirac_ant = r""" +p1 = 1; +p2 = 0.5; +p3 = 2; +p4 = 3; + +x1 = 0; +x2 = 0; + +x1' = -p1 * x1 +x2' = p3 * x1 - p4 * x2; + +at time >= p2: x1 = x1 + 1 +""" + + +calvetti_ant = r""" +# constants +V1ss = 0.29; +R1ss = 0.74; +V2ss = 0.44; +R2ss = 0.08; +V3ss = 0.27; +R3ss = 0.18; + +# static expressions +p1 = 1; +p2 = 1 - R1ss; +p3 = 1 - (R1ss + R2ss); +L1 = (R1ss * (V1ss ^ 2)) ^ (1 / 3); +L2 = (R2ss * (V2ss ^ 2)) ^ (1 / 3); +L3 = (R3ss * (V3ss ^ 2)) ^ (1 / 3); +C1ss = V1ss / (p1 - 0.5 * R1ss); +C2ss = V2ss / (p2 - 0.5 * R2ss); +C3ss = V3ss / (p3 - 0.5 * R3ss); + +species V1, V2, V3, f1, f2, f3; +# initial values +V1 = V1ss; +V2 = V2ss; +V3 = V3ss; +f1 = 1; +f2 = 1; +f3 = 1; + +R1 := (L1 ^ 3) / (V1 ^ 2); +R2 := (L2 ^ 3) / (V2 ^ 2); +R3 := (L3 ^ 3) / (V3 ^ 2); +f0 := (2 / R1) - ((R1 + R2) * f1 + (R2 + R3) * f2 + R3 * f3) / R1; +s := piecewise(0, time < 10, 1, time >= 10 & & time <= 12, 0); + +# differential equations +rate_of_V1 := (1 / 31) * (((1.29 - (V1 / V1ss)) / (1.29 - 1)) + s - 2 * (V1 / (C1ss * ((R1 + R2) * f1 + (R2 + R3) * f2 + R3 * f3)))); +V1' = rate_of_V1; +rate_of_V2 := (1 / 163) * (((1.51 - (V2 / V2ss)) / (1.51 - 1)) - 2 * (V2 / (C2ss * ((R2 + R3) * f2 + R3 * f3)))); +V2' = rate_of_V2; +rate_of_V3 := (1 / 122) * (((1000000 - (V3 / V3ss)) / (1000000 - 1)) - 2 * (V3 / (C3ss * (R3 * f3)))); +V3' = rate_of_V3; + +# algebraic equations +# TODO: AMICI does currently not support rateOf(.) inside AlgebraicRules +# 0 = f0-rateOf(V1)-f1; +# 0 = f1-rateOf(V2)-f2; +# 0 = f2-rateOf(V3)-f3; +0 = f0 - rate_of_V1 - f1; +0 = f1 - rate_of_V2 - f2; +0 = f2 - rate_of_V3 - f3; +""" + +robertson_ant = r""" +model robertson + +p1 = 0.04; +p2 = 1e4; +p3 = 3e7; +k1 = 0.9; + +x1 = k1; +x2 = 0; +x3 = 0; + +# differential states +x1' = -p1 * x1 + p2 * x2 * x3; +x2' = p1 * x1 - p2 * x2 * x3 - p3 * x2^2; + +# algebraic equations +0 = x1 + x2 + x3 - 1; + +end +""" + + +def import_model_robertson(outdir: Path = None) -> Model: + """Import the Robertson model.""" + model_name = "model_robertson_py" + + if outdir is None: + outdir = model_name + + antimony2amici( + robertson_ant, + constant_parameters=["k1"], + observables={ + "obs_x1": {"formula": "x1"}, + "obs_x2": {"formula": "1e4 * x2"}, + "obs_x3": {"formula": "x3"}, + }, + model_name=model_name, + output_dir=outdir, + ) + model_module = import_model_module(model_name, outdir) + model = model_module.get_model() + + return model + + +def import_model_calvetti(outdir: Path = None) -> Model: + model_name = "model_calvetti_py" + + if outdir is None: + outdir = model_name + + antimony2amici( + calvetti_ant, + constant_parameters=["V1ss", "R1ss", "V2ss", "R2ss", "V3ss", "R3ss"], + observables={ + "obs_V1": {"formula": "V1"}, + "obs_V2": {"formula": "V2"}, + "obs_V3": {"formula": "V3"}, + "obs_f0": {"formula": "f0"}, + "obs_f1": {"formula": "f1"}, + "obs_f2": {"formula": "f2"}, + }, + model_name=model_name, + output_dir=outdir, + hardcode_symbols=["p1"], + ) + model_module = import_model_module(model_name, outdir) + model = model_module.get_model() + + assert model.getFixedParameterIds() == ( + "V1ss", + "R1ss", + "V2ss", + "R2ss", + "V3ss", + "R3ss", + ) + + return model + + +def import_model_dirac(outdir: Path = None) -> Model: + """Import the Dirac model.""" + model_name = "model_dirac_py" + + if outdir is None: + outdir = model_name + + antimony2amici( + model_dirac_ant, + observables={ + "obs_x2": {"formula": "x2"}, + }, + model_name=model_name, + output_dir=outdir, + ) + model_module = import_model_module(model_name, outdir) + model = model_module.get_model() + + return model + + +def import_model_neuron(outdir: Path = None) -> AmiciModel: + """Python implementation of the neuron model (Hodgkin-Huxley). + + ODEs + ---- + d/dt v: + - 0.04*v^2 + 5*v + 140 - u + I + d/dt u: + - a*(b*v - u); + + Events: + ------- + event_1: + trigger: v - 30 + bolus: [[ -c - v ], + [ 0]] + observable: t + """ + # Model components + species = ["v", "u"] + initial_assignments = { + "v": "v0", + "u": "b*v0", + } + rate_rules = { + "v": "0.04*v^2 + 5*v + 140 - u + I0", + "u": "a*(b*v - u)", + } + parameters = { + "a": 0.02, + "b": 0.3, + "c": 65, + "d": 0.9, + "v0": -60, + "I0": 10, + } + events = { + "event_1": { + "trigger": "v > 30", + "target": ["v", "u"], + "assignment": ["-c", "d+u"], + }, + } + + observables = { + "y1": { + "name": "v", + "formula": "v", + } + } + + event_observables = { + "z1": {"name": "z1", "event": "event_1", "formula": "time"} + } + + sbml_document, sbml_model = create_sbml_model( + initial_assignments=initial_assignments, + parameters=parameters, + rate_rules=rate_rules, + species=species, + events=events, + # uncomment `to_file` to save SBML model to file for inspection + # to_file=sbml_test_models / (model_name + '.sbml'), + ) + + model_name = "model_neuron_py" + constants = ["v0", "I0"] + model = create_amici_model( + sbml_model, + model_name=model_name, + observables=observables, + constant_parameters=constants, + event_observables=event_observables, + output_dir=outdir, + ) + return model + + +def import_model_events(outdir: Path = None) -> AmiciModel: + """Python implementation of the events model. + + ODEs + ---- + d/dt x1: + - -p1*heaviside(t-p4)*x1 + d/dt x2: + - p2*x1*exp(-0.1*t)-p3*x2 + d/dt x3: + - -x3+heaviside(t-4) + + Events: + ------- + event_1: + trigger: x2 > x3 + bolus: 0 + observable: t + event_2: + trigger: x1 > x3 + bolus: 0 + observable: t + """ + # Model components + species = ["x1", "x2", "x3"] + initial_assignments = { + "x1": "k1", + "x2": "k2", + "x3": "k3", + } + rate_rules = { + "x1": "-p1*piecewise(1.0, time>p4, 0.0)*x1", + "x2": "p2*x1*exp(-0.1*time)-p3*x2", + "x3": "-x3+piecewise(1.0, time>4, 0.0)", + } + parameters = { + "p1": 0.5, + "p2": 2, + "p3": 0.5, + "p4": 0.5, + "k1": 4, + "k2": 8, + "k3": 10, + "k4": 4, + } + events = { + "event_1": {"trigger": "x2 > x3", "target": [], "assignment": []}, + "event_2": {"trigger": "x1 > x3", "target": [], "assignment": []}, + } + + observables = { + "y1": { + "name": "y1", + "formula": "p4*(x1+x2+x3)", + } + } + + event_observables = { + "z1": {"name": "z1", "event": "event_1", "formula": "time"}, + "z2": {"name": "z2", "event": "event_2", "formula": "time"}, + } + + sbml_document, sbml_model = create_sbml_model( + initial_assignments=initial_assignments, + parameters=parameters, + rate_rules=rate_rules, + species=species, + events=events, + # uncomment `to_file` to save SBML model to file for inspection + # to_file=sbml_test_models / (model_name + '.sbml'), + ) + + model_name = "model_events_py" + constants = ["k1", "k2", "k3", "k4"] + model = create_amici_model( + sbml_model, + model_name=model_name, + observables=observables, + constant_parameters=constants, + event_observables=event_observables, + output_dir=outdir, + ) + return model + + +def import_model_jakstat(outdir: Path = None) -> AmiciModel: + model_name = "model_jakstat_adjoint_py" + if outdir is None: + outdir = model_name + + # Create basic SBML model without spline + ant_str = r""" + model model_jakstat_adjoint + # parameters + p1 = 10^0.60; + p2 = 10^3; + p3 = 10^-0.95; + p4 = 10^-0.0075; + init_STAT = 10^0; + # spline values + sp1 = 10^-2.8; + sp2 = 10^-0.26; + sp3 = 10^-0.075; + sp4 = 10^-0.41; + sp5 = 10^-5; + # output parameters + offset_tSTAT = 10^-0.74; + offset_pSTAT = 10^-0.64; + scale_tSTAT = 10^-0.11; + scale_pSTAT = 10^0.027; + sigma_pSTAT = 10^-0.5; + sigma_tSTAT = 10^0; + sigma_pEpoR = 10^-0.5; + + # constants + Omega_cyt = 1.4; + Omega_nuc = 0.45; + + # state variables + species STAT, pSTAT, pSTAT_pSTAT, npSTAT_npSTAT, nSTAT1, nSTAT2, nSTAT3, nSTAT4, nSTAT5; + + STAT = init_STAT; + pSTAT = 0; + pSTAT_pSTAT = 0; + npSTAT_npSTAT = 0; + nSTAT1 = 0; + nSTAT2 = 0; + nSTAT3 = 0; + nSTAT4 = 0; + nSTAT5 = 0; + + STAT' = (Omega_nuc*p4*nSTAT5 - Omega_cyt*STAT*p1*u)/Omega_cyt; + pSTAT' = STAT*p1*u - 2*p2*pSTAT^2; + pSTAT_pSTAT' = p2*pSTAT^2 - p3*pSTAT_pSTAT; + npSTAT_npSTAT' = -(Omega_nuc*p4*npSTAT_npSTAT - Omega_cyt*p3*pSTAT_pSTAT)/Omega_nuc; + nSTAT1' = -p4*(nSTAT1 - 2*npSTAT_npSTAT); + nSTAT2' = p4*(nSTAT1 - nSTAT2); + nSTAT3' = p4*(nSTAT2 - nSTAT3); + nSTAT4' = p4*(nSTAT3 - nSTAT4); + nSTAT5' = p4*(nSTAT4 - nSTAT5); + + # target of spline to be added below + var u = 0; + end + """ + sbml_str = antimony2sbml(ant_str) + sbml_doc = libsbml.SBMLReader().readSBMLFromString(sbml_str) + sbml_model = sbml_doc.getModel() + + # Add spline to the SBML model + # Timepoints for spline nodes + nodes = [0, 5, 10, 20, 60] + # Parameterized spline values at nodes + values_at_nodes = [sp.Symbol(f"sp{i + 1}") for i, t in enumerate(nodes)] + # The original MATLAB test used a natural cubic spline, but this is not + # supported during Python import, so we use a cubic Hermite spline instead. + # This is reasonably close to the original spline, but not exactly the + # same. + spline = CubicHermiteSpline( + sbml_id="u", + evaluate_at=amici_time_symbol, + nodes=nodes, + values_at_nodes=values_at_nodes, + extrapolate=("constant", "constant"), + logarithmic_parametrization=True, + ) + spline.add_to_sbml_model(sbml_model, auto_add=False) + + SbmlImporter(sbml_model).sbml2amici( + constant_parameters=["Omega_cyt", "Omega_nuc"], + observables={ + "obs_pSTAT": { + "formula": "offset_pSTAT + scale_pSTAT/init_STAT*(pSTAT + 2*pSTAT_pSTAT)" + }, + "obs_tSTAT": { + "formula": "offset_tSTAT + scale_tSTAT/init_STAT*(STAT + pSTAT + 2*(pSTAT_pSTAT))" + }, + "obs_spline": {"formula": "u"}, + }, + sigmas={ + "obs_pSTAT": "sigma_pSTAT", + "obs_tSTAT": "sigma_tSTAT", + "obs_spline": "sigma_pEpoR", + }, + model_name=model_name, + output_dir=outdir, + ) + model_module = import_model_module(model_name, outdir) + model = model_module.get_model() + return model + + +def import_model_nested_events(outdir: Path = None) -> AmiciModel: + model_name = "model_nested_events_py" + if outdir is None: + outdir = model_name + + ant_str = r""" + model nested_events + + # parameters + V_0 = 0.1; + V_0_inject = 1000; + t_0 = 2; + rho_V = 8e-1; + delta_V = 1.6; + + # state variables + Virus = V_0 + Virus' = piecewise(0, Virus < 1, Virus*rho_V) -Virus*delta_V; + + injection: at time >= t_0: Virus = Virus + V_0_inject; + + end + """ + + antimony2amici( + ant_str, + observables={ + "obs_Virus": {"formula": "Virus"}, + }, + model_name=model_name, + output_dir=outdir, + ) + model_module = import_model_module(model_name, outdir) + model = model_module.get_model() + return model + + +def import_model_steadystate(outdir: Path = None) -> AmiciModel: + model_name = "model_steadystate_py" + if outdir is None: + outdir = model_name + + ant_str = r""" + model model_steadystate + + k1 = 0.1; + k2 = 0.4; + k3 = 0.7; + k4 = 1; + + p1 = 1; + p2 = 0.5; + p3 = 0.4; + p4 = 2; + p5 = 0.1; + + species x1 = k1; + species x2 = k2; + species x3 = k3; + x1' = -2*p1*x1^2 - p2*x1*x2 + 2*p3*x2 + p4*x3 + p5; + x2' = p1*x1^2 - p2*x1*x2 - p3*x2 + p4*x3; + x3' = p2*x1*x2 - p4*x3 - k4*x3; + + end + """ + + antimony2amici( + ant_str, + constant_parameters=["k1", "k2", "k3", "k4"], + observables={ + "obs_x1": {"formula": "x1"}, + "obs_x2": {"formula": "x2"}, + "obs_x3": {"formula": "x3"}, + }, + model_name=model_name, + output_dir=outdir, + ) + model_module = import_model_module(model_name, outdir) + model = model_module.get_model() + return model + + +def import_test_models(): + """Import models required for C++ integration tests.""" + # out_root = Path(os.getcwd()) + repo_root = Path(__file__).parents[4] + out_root = repo_root / "models" + + print(f"Generating test models in {out_root}...") + print("Importing model_dirac_py...") + import_model_dirac(outdir=out_root / "model_dirac_py") + print("Importing model_events_py...") + import_model_events(outdir=out_root / "model_events_py") + print("Importing model_neuron_py...") + import_model_neuron(outdir=out_root / "model_neuron_py") + print("Importing model_calvetti_py...") + import_model_calvetti(outdir=out_root / "model_calvetti_py") + print("Importing model_robertson_py...") + import_model_robertson(outdir=out_root / "model_robertson_py") + print("Importing model_jakstat_adjoint_py...") + import_model_jakstat(outdir=out_root / "model_jakstat_adjoint_py") + print("Importing model_nested_events_py...") + import_model_nested_events(outdir=out_root / "model_nested_events_py") + print("Importing model_steadystate_py...") + import_model_steadystate(outdir=out_root / "model_steadystate_py") + + +def create_sbml_model( + initial_assignments, + parameters, + rate_rules, + species, + events, + to_file: str = None, +): + """Create an SBML model from simple definitions. + + See the model definitions and usage in :py:func:`model` for example input. + + The default initial concentration of species is `1.0`. This can currently + be changed by specifying an initial assignment. + """ + document = libsbml.SBMLDocument(3, 1) + model = document.createModel() + + compartment = model.createCompartment() + compartment.setId("compartment") + compartment.setConstant(True) + compartment.setSize(1) + compartment.setSpatialDimensions(3) + compartment.setUnits("dimensionless") + + for species_id in species: + species = model.createSpecies() + species.setId(species_id) + species.setCompartment("compartment") + species.setConstant(False) + species.setSubstanceUnits("dimensionless") + species.setBoundaryCondition(False) + species.setHasOnlySubstanceUnits(False) + species.setInitialConcentration(1.0) + + for target, formula in initial_assignments.items(): + initial_assignment = model.createInitialAssignment() + initial_assignment.setSymbol(target) + initial_assignment.setMath(libsbml.parseL3Formula(formula)) + + for target, formula in rate_rules.items(): + rate_rule = model.createRateRule() + rate_rule.setVariable(target) + rate_rule.setMath(libsbml.parseL3Formula(formula)) + + for parameter_id, parameter_value in parameters.items(): + parameter = model.createParameter() + parameter.setId(parameter_id) + parameter.setConstant(True) + parameter.setValue(parameter_value) + parameter.setUnits("dimensionless") + + for event_id, event_def in events.items(): + event = model.createEvent() + event.setId(event_id) + event.setName(event_id) + event.setUseValuesFromTriggerTime(False) + trigger = event.createTrigger() + trigger.setMath(libsbml.parseL3Formula(event_def["trigger"])) + trigger.setPersistent(True) + trigger.setInitialValue(True) + + def create_event_assignment(target, assignment): + ea = event.createEventAssignment() + ea.setVariable(target) + ea.setMath(libsbml.parseL3Formula(assignment)) + + if isinstance(event_def["target"], list): + for event_target, event_assignment in zip( + event_def["target"], event_def["assignment"], strict=True + ): + create_event_assignment(event_target, event_assignment) + + else: + create_event_assignment( + event_def["target"], event_def["assignment"] + ) + + if to_file: + libsbml.writeSBMLToFile(document, to_file) + + # Need to return document, else AMICI throws an error. + # (possibly due to garbage collection?) + return document, model + + +def create_amici_model( + sbml_model, model_name, output_dir: Path = None, **kwargs +) -> AmiciModel: + """ + Import an sbml file and create an AMICI model from it + """ + sbml_importer = SbmlImporter(sbml_model) + + if output_dir is None: + sbml_test_models_output_dir = Path("amici_models") + sbml_test_models_output_dir.mkdir(parents=True, exist_ok=True) + # try not to exceed the stupid maximum path length on windows 💩 + output_dir = ( + sbml_test_models_output_dir / model_name + if sys.platform != "win32" + else tempfile.mkdtemp() + ) + + sbml_importer.sbml2amici( + model_name=model_name, output_dir=output_dir, **kwargs + ) + + model_module = import_model_module(model_name, output_dir) + return model_module.getModel() diff --git a/python/tests/test_events.py b/python/tests/test_events.py index c02b27a7f7..87b99d3070 100644 --- a/python/tests/test_events.py +++ b/python/tests/test_events.py @@ -13,9 +13,8 @@ check_trajectories_with_adjoint_sensitivities, check_trajectories_with_forward_sensitivities, check_trajectories_without_sensitivities, - create_amici_model, - create_sbml_model, ) +from amici.testing.models import create_sbml_model, create_amici_model from numpy.testing import assert_allclose pytestmark = pytest.mark.filterwarnings( diff --git a/python/tests/test_heavisides.py b/python/tests/test_heavisides.py index f0f26e470b..0bff2d4164 100644 --- a/python/tests/test_heavisides.py +++ b/python/tests/test_heavisides.py @@ -6,9 +6,8 @@ check_trajectories_with_adjoint_sensitivities, check_trajectories_with_forward_sensitivities, check_trajectories_without_sensitivities, - create_amici_model, - create_sbml_model, ) +from amici.testing.models import create_sbml_model, create_amici_model pytestmark = pytest.mark.filterwarnings( # https://github.com/AMICI-dev/AMICI/issues/18 diff --git a/python/tests/test_observable_events.py b/python/tests/test_observable_events.py index db6fc3d452..09bb26452f 100644 --- a/python/tests/test_observable_events.py +++ b/python/tests/test_observable_events.py @@ -3,197 +3,23 @@ import amici import pytest from test_pregenerated_models import ( - expected_results, + expected_results_matlab, expected_results_file, options_file, verify_simulation_results, ) -from util import create_amici_model, create_sbml_model - - -def model_neuron_def(): - """Python implementation of the neuron model (Hodgkin-Huxley). - - ODEs - ---- - d/dt v: - - 0.04*v^2 + 5*v + 140 - u + I - d/dt u: - - a*(b*v - u); - - Events: - ------- - event_1: - trigger: v - 30 - bolus: [[ -c - v ], - [ 0]] - observable: t - """ - # Model components - species = ["v", "u"] - initial_assignments = { - "v": "v0", - "u": "b*v0", - } - rate_rules = { - "v": "0.04*v^2 + 5*v + 140 - u + I0", - "u": "a*(b*v - u)", - } - parameters = { - "a": 0.02, - "b": 0.3, - "c": 65, - "d": 0.9, - "v0": -60, - "I0": 10, - } - events = { - "event_1": { - "trigger": "v > 30", - "target": ["v", "u"], - "assignment": ["-c", "d+u"], - }, - } - - observables = { - "y1": { - "name": "v", - "formula": "v", - } - } - - event_observables = { - "z1": {"name": "z1", "event": "event_1", "formula": "time"} - } - return ( - initial_assignments, - parameters, - rate_rules, - species, - events, - observables, - event_observables, - ) - - -def model_events_def(): - """Python implementation of the events model. - - ODEs - ---- - d/dt x1: - - -p1*heaviside(t-p4)*x1 - d/dt x2: - - p2*x1*exp(-0.1*t)-p3*x2 - d/dt x3: - - -x3+heaviside(t-4) - - Events: - ------- - event_1: - trigger: x2 > x3 - bolus: 0 - observable: t - event_2: - trigger: x1 > x3 - bolus: 0 - observable: t - """ - # Model components - species = ["x1", "x2", "x3"] - initial_assignments = { - "x1": "k1", - "x2": "k2", - "x3": "k3", - } - rate_rules = { - "x1": "-p1*piecewise(1.0, time>p4, 0.0)*x1", - "x2": "p2*x1*exp(-0.1*time)-p3*x2", - "x3": "-x3+piecewise(1.0, time>4, 0.0)", - } - parameters = { - "p1": 0.5, - "p2": 2, - "p3": 0.5, - "p4": 0.5, - "k1": 4, - "k2": 8, - "k3": 10, - "k4": 4, - } - events = { - "event_1": {"trigger": "x2 > x3", "target": [], "assignment": []}, - "event_2": {"trigger": "x1 > x3", "target": [], "assignment": []}, - } - - observables = { - "y1": { - "name": "y1", - "formula": "p4*(x1+x2+x3)", - } - } - - event_observables = { - "z1": {"name": "z1", "event": "event_1", "formula": "time"}, - "z2": {"name": "z2", "event": "event_2", "formula": "time"}, - } - return ( - initial_assignments, - parameters, - rate_rules, - species, - events, - observables, - event_observables, - ) - - -models = [ - (model_neuron_def, "model_neuron_py", ["v0", "I0"]), - (model_events_def, "model_events_py", ["k1", "k2", "k3", "k4"]), -] +from amici.testing.models import import_model_neuron, import_model_events @pytest.mark.skipif( os.environ.get("AMICI_SKIP_CMAKE_TESTS", "") == "TRUE", reason="skipping cmake based test", ) -@pytest.mark.parametrize("model_def,model_name,constants", models) -def test_models(model_def, model_name, constants): - ( - initial_assignments, - parameters, - rate_rules, - species, - events, - observables, - event_observables, - ) = model_def() - - sbml_document, sbml_model = create_sbml_model( - initial_assignments=initial_assignments, - parameters=parameters, - rate_rules=rate_rules, - species=species, - events=events, - # uncomment `to_file` to save SBML model to file for inspection - # to_file=sbml_test_models / (model_name + '.sbml'), - ) - - model = create_amici_model( - sbml_model, - model_name=model_name, - observables=observables, - constant_parameters=constants, - event_observables=event_observables, - ) - - run_test_cases(model) - - return - - -def run_test_cases(model): +@pytest.mark.parametrize( + "model", [import_model_neuron(), import_model_events()] +) +def test_cases(model): + expected_results = expected_results_matlab solver = model.getSolver() model_name = model.getName() diff --git a/python/tests/test_pregenerated_models.py b/python/tests/test_pregenerated_models.py index ed37a3d5aa..3c86ae3741 100755 --- a/python/tests/test_pregenerated_models.py +++ b/python/tests/test_pregenerated_models.py @@ -15,13 +15,23 @@ cpp_test_dir = Path(__file__).parents[2] / "tests" / "cpp" options_file = str(cpp_test_dir / "testOptions.h5") +# matlab-generated expected results expected_results_file = str(cpp_test_dir / "expectedResults.h5") -expected_results = h5py.File(expected_results_file, "r") +expected_results_matlab = h5py.File(expected_results_file, "r") +# python-generated expected results +expected_results_file_py = str(cpp_test_dir / "expected_results_py.h5") +expected_results_py = h5py.File(expected_results_file_py, "r") model_cases = [ (sub_test, case) - for sub_test in expected_results.keys() - for case in list(expected_results[sub_test].keys()) + for sub_test in expected_results_matlab.keys() + for case in list(expected_results_matlab[sub_test].keys()) +] + +model_cases_py = [ + (sub_test, case) + for sub_test in expected_results_py.keys() + for case in list(expected_results_py[sub_test].keys()) ] @@ -38,6 +48,7 @@ def test_pregenerated_model(sub_test, case): NOTE: requires having run `make python-tests` in /build/ before to build the python modules for the test models. """ + expected_results = expected_results_matlab if case.startswith("sensi2"): model_name = sub_test + "_o2" @@ -55,6 +66,9 @@ def test_pregenerated_model(sub_test, case): / "swig" ) + if not Path(model_swig_folder).exists(): + pytest.skip(f"Model {model_name} not found in {model_swig_folder}.") + test_model_module = amici.import_model_module( module_name=model_name, module_path=model_swig_folder ) @@ -219,6 +233,202 @@ def test_pregenerated_model(sub_test, case): model.getParameterByName("thisParameterDoesNotExist") +@skip_on_valgrind +@pytest.mark.skipif( + os.environ.get("AMICI_SKIP_CMAKE_TESTS", "") == "TRUE", + reason="skipping cmake based test", +) +@pytest.mark.parametrize("sub_test,case", model_cases_py) +def test_pregenerated_model_py(sub_test, case): + """Tests models that were pre-imported and -compiled. + + NOTE: requires having run `make python-tests` in /build/ before to build + the python modules for the test models. + """ + expected_results = expected_results_py + if case.startswith("sensi2"): + model_name = sub_test + "_o2" + else: + model_name = sub_test + + model_swig_folder = str( + Path(__file__).parents[2] + / "build" + / "tests" + / "cpp" + / f"external_{model_name}_py-prefix" + / "src" + / f"external_{model_name}_py-build" + / "swig" + ) + + if not Path(model_swig_folder).exists(): + pytest.skip(f"Model {model_name} not found in {model_swig_folder}.") + + test_model_module = amici.import_model_module( + module_name=f"{model_name}_py", module_path=model_swig_folder + ) + model = test_model_module.getModel() + solver = model.getSolver() + amici.readModelDataFromHDF5( + options_file, model.get(), f"/{sub_test}/{case}/options" + ) + if model_name == "model_steadystate": + model.setSteadyStateComputationMode( + amici.SteadyStateComputationMode.integrateIfNewtonFails + ) + model.setSteadyStateSensitivityMode( + amici.SteadyStateSensitivityMode.integrateIfNewtonFails + ) + amici.readSolverSettingsFromHDF5( + options_file, solver.get(), f"/{sub_test}/{case}/options" + ) + + edata = None + if "data" in expected_results[sub_test][case].keys(): + edata = amici.readSimulationExpData( + str(expected_results_file), f"/{sub_test}/{case}/data", model.get() + ) + rdata = amici.runAmiciSimulation(model, solver, edata) + + check_derivative_opts = dict() + + if model_name == "model_nested_events": + check_derivative_opts["rtol"] = 1e-2 + elif model_name == "model_events": + check_derivative_opts["atol"] = 1e-3 + + if ( + edata + and solver.getSensitivityMethod() + and solver.getSensitivityOrder() + and len(model.getParameterList()) + and not model_name.startswith("model_neuron") + and not case.endswith("byhandpreeq") + ): + check_derivatives( + model, + solver, + edata, + **check_derivative_opts, + ) + + verify_simulation_opts = dict() + + if model_name.startswith("model_neuron"): + verify_simulation_opts["atol"] = 1e-5 + verify_simulation_opts["rtol"] = 1e-2 + + if ( + model_name.startswith("model_robertson") + and case == "sensiforwardSPBCG" + ): + verify_simulation_opts["atol"] = 1e-3 + verify_simulation_opts["rtol"] = 1e-3 + + verify_simulation_results( + rdata, + expected_results[sub_test][case]["results"], + **verify_simulation_opts, + ) + + if model_name == "model_steadystate" and case == "sensiforwarderrorint": + edata = amici.amici.ExpData(model.get()) + + # Test runAmiciSimulations: ensure running twice + # with same ExpData yields same results + if ( + edata + and model_name != "model_neuron_o2" + and not ( + model_name == "model_robertson" and case == "sensiforwardSPBCG" + ) + ): + if isinstance(edata, amici.amici.ExpData): + edatas = [edata, edata] + else: + edatas = [edata.get(), edata.get()] + + rdatas = amici.runAmiciSimulations( + model, solver, edatas, num_threads=2, failfast=False + ) + verify_simulation_results( + rdatas[0], + expected_results[sub_test][case]["results"], + **verify_simulation_opts, + ) + verify_simulation_results( + rdatas[1], + expected_results[sub_test][case]["results"], + **verify_simulation_opts, + ) + + # test residuals mode + if solver.getSensitivityMethod() == amici.SensitivityMethod.adjoint: + with pytest.raises(RuntimeError): + solver.setReturnDataReportingMode(amici.RDataReporting.residuals) + else: + solver.setReturnDataReportingMode(amici.RDataReporting.residuals) + rdata = amici.runAmiciSimulation(model, solver, edata) + verify_simulation_results( + rdata, + expected_results[sub_test][case]["results"], + fields=["t", "res", "sres", "y", "sy", "sigmay", "ssigmay"], + **verify_simulation_opts, + ) + with pytest.raises(RuntimeError): + solver.setSensitivityMethod(amici.SensitivityMethod.adjoint) + + chi2_ref = rdata.chi2 + + # test likelihood mode + solver.setReturnDataReportingMode(amici.RDataReporting.likelihood) + rdata = amici.runAmiciSimulation(model, solver, edata) + verify_simulation_results( + rdata, + expected_results[sub_test][case]["results"], + fields=["t", "llh", "sllh", "s2llh", "FIM"], + **verify_simulation_opts, + ) + + # test sigma residuals + + if ( + model_name == "model_jakstat_adjoint" + and solver.getSensitivityMethod() != amici.SensitivityMethod.adjoint + ): + model.setAddSigmaResiduals(True) + solver.setReturnDataReportingMode(amici.RDataReporting.full) + rdata = amici.runAmiciSimulation(model, solver, edata) + # check whether activation changes chi2 + assert chi2_ref != rdata.chi2 + + if ( + edata + and solver.getSensitivityMethod() + and solver.getSensitivityOrder() + and len(model.getParameterList()) + ): + check_derivatives(model, solver, edata, **check_derivative_opts) + + chi2_ref = rdata.chi2 + res_ref = rdata.res + + model.setMinimumSigmaResiduals(100) + rdata = amici.runAmiciSimulation(model, solver, edata) + # check whether changing the minimum changes res but not chi2 + assert np.isclose(chi2_ref, rdata.chi2) + assert not np.allclose(res_ref, rdata.res) + + model.setMinimumSigmaResiduals(-10) + rdata = amici.runAmiciSimulation(model, solver, edata) + # check whether having a bad minimum results in nan chi2 + assert np.isnan(rdata.chi2) + + with pytest.raises(RuntimeError): + model.getParameterByName("thisParameterDoesNotExist") + + def verify_simulation_results( rdata, expected_results, fields=None, atol=1e-8, rtol=1e-4 ): @@ -273,7 +483,7 @@ def verify_simulation_results( ) else: if field not in fields: - assert rdata[field] is None, field + # assert rdata[field] is None, field continue if field == "s2llh": _check_results( @@ -293,6 +503,7 @@ def verify_simulation_results( ) for attr in attrs: - _check_results( - rdata, attr, expected_results.attrs[attr], atol=atol, rtol=rtol - ) + expected_val = expected_results.attrs[attr] + if isinstance(expected_val, bytes): + expected_val = expected_val.decode("utf-8") + _check_results(rdata, attr, expected_val, atol=atol, rtol=rtol) diff --git a/python/tests/util.py b/python/tests/util.py index d8706ffd60..ce872bdf6d 100644 --- a/python/tests/util.py +++ b/python/tests/util.py @@ -4,7 +4,6 @@ import tempfile from pathlib import Path -import libsbml import numpy as np import pandas as pd @@ -45,92 +44,6 @@ def create_amici_model(sbml_model, model_name, **kwargs) -> AmiciModel: return model_module.getModel() -def create_sbml_model( - initial_assignments, - parameters, - rate_rules, - species, - events, - to_file: str = None, -): - """Create an SBML model from simple definitions. - - See the model definitions and usage in :py:func:`model` for example input. - - The default initial concentration of species is `1.0`. This can currently - be changed by specifying an initial assignment. - """ - document = libsbml.SBMLDocument(3, 1) - model = document.createModel() - - compartment = model.createCompartment() - compartment.setId("compartment") - compartment.setConstant(True) - compartment.setSize(1) - compartment.setSpatialDimensions(3) - compartment.setUnits("dimensionless") - - for species_id in species: - species = model.createSpecies() - species.setId(species_id) - species.setCompartment("compartment") - species.setConstant(False) - species.setSubstanceUnits("dimensionless") - species.setBoundaryCondition(False) - species.setHasOnlySubstanceUnits(False) - species.setInitialConcentration(1.0) - - for target, formula in initial_assignments.items(): - initial_assignment = model.createInitialAssignment() - initial_assignment.setSymbol(target) - initial_assignment.setMath(libsbml.parseL3Formula(formula)) - - for target, formula in rate_rules.items(): - rate_rule = model.createRateRule() - rate_rule.setVariable(target) - rate_rule.setMath(libsbml.parseL3Formula(formula)) - - for parameter_id, parameter_value in parameters.items(): - parameter = model.createParameter() - parameter.setId(parameter_id) - parameter.setConstant(True) - parameter.setValue(parameter_value) - parameter.setUnits("dimensionless") - - for event_id, event_def in events.items(): - event = model.createEvent() - event.setId(event_id) - event.setName(event_id) - event.setUseValuesFromTriggerTime(False) - trigger = event.createTrigger() - trigger.setMath(libsbml.parseL3Formula(event_def["trigger"])) - trigger.setPersistent(True) - trigger.setInitialValue(True) - - def create_event_assignment(target, assignment): - ea = event.createEventAssignment() - ea.setVariable(target) - ea.setMath(libsbml.parseL3Formula(assignment)) - - if isinstance(event_def["target"], list): - for event_target, event_assignment in zip( - event_def["target"], event_def["assignment"], strict=True - ): - create_event_assignment(event_target, event_assignment) - - else: - create_event_assignment( - event_def["target"], event_def["assignment"] - ) - - if to_file: - libsbml.writeSBMLToFile(document, to_file) - - # Need to return document, else AMICI throws an error. - # (possibly due to garbage collection?) - return document, model - - def check_trajectories_without_sensitivities( amici_model: AmiciModel, result_expected_x: np.ndarray, diff --git a/tests/cpp/CMakeLists.txt b/tests/cpp/CMakeLists.txt index 7d0096ae39..584384ce97 100644 --- a/tests/cpp/CMakeLists.txt +++ b/tests/cpp/CMakeLists.txt @@ -35,6 +35,13 @@ add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src project(amiciIntegrationTests) +# Generate test models +add_custom_target( + import_test_models + COMMAND "${CMAKE_SOURCE_DIR}/venv/bin/python" "-c" "from amici.testing.models import import_test_models; import_test_models()" + VERBATIM +) + # models depend on Upstream::amici add_library(Upstream::amici ALIAS amici) @@ -53,16 +60,9 @@ target_link_libraries( # Names of models for which tests are to be run set(TEST_MODELS - dirac - steadystate - jakstat_adjoint jakstat_adjoint_o2 - neuron neuron_o2 - events - nested_events - robertson - calvetti) + ) if(ENABLE_SWIG AND ENABLE_PYTHON) add_custom_target( @@ -75,6 +75,76 @@ add_subdirectory(unittests) include(ExternalProject) + + +# Amici testing library +add_library(amici-testing-py testfunctions.cpp) +target_compile_definitions( + amici-testing-py + PUBLIC NEW_OPTION_FILE="${CMAKE_CURRENT_SOURCE_DIR}/testOptions.h5" + PUBLIC HDFFILE="${CMAKE_CURRENT_SOURCE_DIR}/expected_results_py.h5" + PUBLIC HDFFILEWRITE="${CMAKE_CURRENT_SOURCE_DIR}/writeResults.h5") +target_include_directories(amici-testing-py PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries( + amici-testing-py + PUBLIC Upstream::amici + PUBLIC gtest_main) + + + +set(PY_TEST_MODELS + dirac_py + events_py + calvetti_py + neuron_py + nested_events_py + steadystate_py + robertson_py + jakstat_adjoint_py + # TODO jakstat_adjoint_o2 -- requires 2nd-order sensitivities + # TODO neuron_o2 -- requires 2nd-order sensitivities +) +foreach(MODEL IN ITEMS ${PY_TEST_MODELS}) + # Build model + string( + CONCAT MODEL_LIBRARY_DIR + "${CMAKE_CURRENT_BINARY_DIR}/external_model_${MODEL}-prefix/src/" + "external_model_${MODEL}-build/") + string( + CONCAT MODEL_LIBRARY + "${MODEL_LIBRARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}model_${MODEL}" + "${CMAKE_STATIC_LIBRARY_SUFFIX}") + ExternalProject_Add( + external_model_${MODEL} + PREFIX "" + SOURCE_DIR "${CMAKE_SOURCE_DIR}/models/model_${MODEL}/" + INSTALL_COMMAND "" + TEST_COMMAND "" + BUILD_ALWAYS 1 + DEPENDS amici + CMAKE_ARGS "-DCMAKE_BUILD_TYPE=Debug" + BUILD_BYPRODUCTS "${MODEL_LIBRARY}") + # Rebuild if amici files are updated + ExternalProject_Add_StepDependencies(external_model_${MODEL} build amici) + # add_dependencies(external_model_${MODEL} import_test_models) + add_library(model_${MODEL} STATIC IMPORTED) + add_dependencies(model_${MODEL} external_model_${MODEL}) + + set_target_properties( + model_${MODEL} + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${CMAKE_SOURCE_DIR}/models/model_${MODEL}/" IMPORTED_LOCATION + "${MODEL_LIBRARY}") + # Build tests for this model + # strip "_py" suffix + string(REPLACE "_py" "" subdir ${MODEL}) + add_subdirectory(${subdir}) + if(TARGET python-tests) + add_dependencies(python-tests external_model_${MODEL}) + endif() +endforeach() + + foreach(MODEL IN ITEMS ${TEST_MODELS}) # Build model string( diff --git a/tests/cpp/calvetti/CMakeLists.txt b/tests/cpp/calvetti/CMakeLists.txt index 5f3db0773e..ca20efda10 100644 --- a/tests/cpp/calvetti/CMakeLists.txt +++ b/tests/cpp/calvetti/CMakeLists.txt @@ -9,11 +9,11 @@ add_executable(${PROJECT_NAME} ${SRC_LIST}) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}) +add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}_py) target_link_libraries(${PROJECT_NAME} - amici-testing - model_${MODEL_NAME} + amici-testing-py + model_${MODEL_NAME}_py gtest_main ) diff --git a/tests/cpp/dirac/CMakeLists.txt b/tests/cpp/dirac/CMakeLists.txt index 5f3db0773e..ca20efda10 100644 --- a/tests/cpp/dirac/CMakeLists.txt +++ b/tests/cpp/dirac/CMakeLists.txt @@ -9,11 +9,11 @@ add_executable(${PROJECT_NAME} ${SRC_LIST}) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}) +add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}_py) target_link_libraries(${PROJECT_NAME} - amici-testing - model_${MODEL_NAME} + amici-testing-py + model_${MODEL_NAME}_py gtest_main ) diff --git a/tests/cpp/events/CMakeLists.txt b/tests/cpp/events/CMakeLists.txt index 5f3db0773e..ca20efda10 100644 --- a/tests/cpp/events/CMakeLists.txt +++ b/tests/cpp/events/CMakeLists.txt @@ -9,11 +9,11 @@ add_executable(${PROJECT_NAME} ${SRC_LIST}) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}) +add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}_py) target_link_libraries(${PROJECT_NAME} - amici-testing - model_${MODEL_NAME} + amici-testing-py + model_${MODEL_NAME}_py gtest_main ) diff --git a/tests/cpp/expected_results_py.h5 b/tests/cpp/expected_results_py.h5 new file mode 100644 index 0000000000..27130fcd21 --- /dev/null +++ b/tests/cpp/expected_results_py.h5 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e956b1076a4274abcac09ed631325e382d5f4ec438147ed9f94420a87ad1889a +size 1847292 diff --git a/tests/cpp/generate_expected_results.py b/tests/cpp/generate_expected_results.py new file mode 100755 index 0000000000..da9cde971e --- /dev/null +++ b/tests/cpp/generate_expected_results.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +"""Generate HDF5 file with expected results for the C++ tests.""" + +from amici.testing.models import ( + import_model_dirac, + import_model_events, + import_model_neuron, + import_model_calvetti, + import_model_jakstat, + import_model_nested_events, + import_model_steadystate, + import_model_robertson, +) +from pathlib import Path +from amici import ( + writeReturnData, + readModelDataFromHDF5, + readSolverSettingsFromHDF5, + readSimulationExpData, +) +import subprocess +import h5py +from amici import runAmiciSimulation +import amici + +repo_root = Path(__file__).parents[2] +outfile = Path(__file__).parent / "expected_results_py.h5" + + +def handle_model(id_: str, model: amici.Model): + # write model settings to h5 + script = repo_root / "tests" / "generateTestConfig" / f"example_{id_}.py" + subprocess.run([script, str(outfile)]) + + # read test case IDs + with h5py.File(outfile, "r") as f: + cases = list(f[f"model_{id_}"]) + print(id_, cases) + + # generate expected results for each case + for case in cases: + # create a new model instance for each case, to ensure no interference + model = model.module.get_model() + readModelDataFromHDF5( + str(outfile), model.get(), f"/model_{id_}/{case}/options" + ) + solver = model.getSolver() + readSolverSettingsFromHDF5( + str(outfile), solver, f"/model_{id_}/{case}/options" + ) + # read ExpData if data/ exists + try: + edata = readSimulationExpData( + str(outfile), f"/model_{id_}/{case}/data", model.get() + ) + except RuntimeError: + edata = None + + rdata = runAmiciSimulation(model, solver, edata) + writeReturnData( + rdata._swigptr.get(), str(outfile), f"/model_{id_}/{case}/results" + ) + + +def main(): + """Generate expected results for the C++ tests.""" + handle_model("dirac", import_model_dirac()) + handle_model("events", import_model_events()) + handle_model("neuron", import_model_neuron()) + handle_model("calvetti", import_model_calvetti()) + handle_model("robertson", import_model_robertson()) + handle_model("jakstat_adjoint", import_model_jakstat()) + handle_model("nested_events", import_model_nested_events()) + handle_model("steadystate", import_model_steadystate()) + + +if __name__ == "__main__": + main() diff --git a/tests/cpp/jakstat_adjoint/CMakeLists.txt b/tests/cpp/jakstat_adjoint/CMakeLists.txt index 5f3db0773e..ca20efda10 100644 --- a/tests/cpp/jakstat_adjoint/CMakeLists.txt +++ b/tests/cpp/jakstat_adjoint/CMakeLists.txt @@ -9,11 +9,11 @@ add_executable(${PROJECT_NAME} ${SRC_LIST}) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}) +add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}_py) target_link_libraries(${PROJECT_NAME} - amici-testing - model_${MODEL_NAME} + amici-testing-py + model_${MODEL_NAME}_py gtest_main ) diff --git a/tests/cpp/nested_events/CMakeLists.txt b/tests/cpp/nested_events/CMakeLists.txt index 5f3db0773e..ca20efda10 100644 --- a/tests/cpp/nested_events/CMakeLists.txt +++ b/tests/cpp/nested_events/CMakeLists.txt @@ -9,11 +9,11 @@ add_executable(${PROJECT_NAME} ${SRC_LIST}) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}) +add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}_py) target_link_libraries(${PROJECT_NAME} - amici-testing - model_${MODEL_NAME} + amici-testing-py + model_${MODEL_NAME}_py gtest_main ) diff --git a/tests/cpp/neuron/CMakeLists.txt b/tests/cpp/neuron/CMakeLists.txt index 5f3db0773e..ca20efda10 100644 --- a/tests/cpp/neuron/CMakeLists.txt +++ b/tests/cpp/neuron/CMakeLists.txt @@ -9,11 +9,11 @@ add_executable(${PROJECT_NAME} ${SRC_LIST}) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}) +add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}_py) target_link_libraries(${PROJECT_NAME} - amici-testing - model_${MODEL_NAME} + amici-testing-py + model_${MODEL_NAME}_py gtest_main ) diff --git a/tests/cpp/robertson/CMakeLists.txt b/tests/cpp/robertson/CMakeLists.txt index 5f3db0773e..ca20efda10 100644 --- a/tests/cpp/robertson/CMakeLists.txt +++ b/tests/cpp/robertson/CMakeLists.txt @@ -9,11 +9,11 @@ add_executable(${PROJECT_NAME} ${SRC_LIST}) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}) +add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}_py) target_link_libraries(${PROJECT_NAME} - amici-testing - model_${MODEL_NAME} + amici-testing-py + model_${MODEL_NAME}_py gtest_main ) diff --git a/tests/cpp/steadystate/CMakeLists.txt b/tests/cpp/steadystate/CMakeLists.txt index 5f3db0773e..ca20efda10 100644 --- a/tests/cpp/steadystate/CMakeLists.txt +++ b/tests/cpp/steadystate/CMakeLists.txt @@ -9,11 +9,11 @@ add_executable(${PROJECT_NAME} ${SRC_LIST}) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}) +add_dependencies(${PROJECT_NAME} external_model_${MODEL_NAME}_py) target_link_libraries(${PROJECT_NAME} - amici-testing - model_${MODEL_NAME} + amici-testing-py + model_${MODEL_NAME}_py gtest_main ) diff --git a/tests/cpp/steadystate/tests1.cpp b/tests/cpp/steadystate/tests1.cpp index 109cc9eecb..59739a7112 100644 --- a/tests/cpp/steadystate/tests1.cpp +++ b/tests/cpp/steadystate/tests1.cpp @@ -1,6 +1,7 @@ #include "testfunctions.h" #include "wrapfunctions.h" +#include "model_steadystate_py.h" #include @@ -52,7 +53,7 @@ TEST(ExampleSteadystate, CloneModel) { auto modelA = amici::generic_model::getModel(); auto modelB = std::make_unique< - amici::model_model_steadystate::Model_model_steadystate>(); + amici::model_model_steadystate_py::Model_model_steadystate_py>(); ASSERT_EQ(*modelA, *modelB); } diff --git a/tests/cpp/testfunctions.cpp b/tests/cpp/testfunctions.cpp index 8a8054f147..a16c2ac44b 100644 --- a/tests/cpp/testfunctions.cpp +++ b/tests/cpp/testfunctions.cpp @@ -6,8 +6,9 @@ #include // for __cxa_demangle #include #include -#include #include +#include +#include #include "gtest/gtest.h" @@ -175,6 +176,12 @@ void verifyReturnData(std::string const& hdffile, std::string const& resultPath, std::vector expected; auto statusExp = hdf5::getIntScalarAttribute(file, resultPath, "status"); + if(rdata->status != statusExp && !rdata->messages.empty()) { + std::cerr<<"Messages:"<messages) { + std::cerr << std::format("[{}][{}] {}", static_cast(msg.severity), msg.identifier, msg.message)<< std::endl; + } + } ASSERT_EQ(statusExp, rdata->status); double llhExp = hdf5::getDoubleScalarAttribute(file, resultPath, "llh"); diff --git a/tests/cpp/unittests/CMakeLists.txt b/tests/cpp/unittests/CMakeLists.txt index 475c89f220..2171bde8ff 100644 --- a/tests/cpp/unittests/CMakeLists.txt +++ b/tests/cpp/unittests/CMakeLists.txt @@ -11,7 +11,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) if(Boost_SERIALIZATION_FOUND) target_sources(${PROJECT_NAME} PRIVATE testSerialization.cpp) endif() -target_link_libraries(${PROJECT_NAME} amici-testing Upstream::amici +target_link_libraries(${PROJECT_NAME} amici-testing-py Upstream::amici Boost::serialization gtest_main) include(GoogleTest) diff --git a/tests/generateTestConfig/example_jakstat.py b/tests/generateTestConfig/example_jakstat_adjoint.py similarity index 100% rename from tests/generateTestConfig/example_jakstat.py rename to tests/generateTestConfig/example_jakstat_adjoint.py diff --git a/tests/generateTestConfig/example_steadystate.py b/tests/generateTestConfig/example_steadystate.py index 80e8a776d2..c294872923 100755 --- a/tests/generateTestConfig/example_steadystate.py +++ b/tests/generateTestConfig/example_steadystate.py @@ -2,12 +2,18 @@ import sys import numpy as np + +from amici import ( + SensitivityOrder, + SteadyStateSensitivityMode, + SteadyStateComputationMode, +) from example import AmiciExample class ExampleSteadystate(AmiciExample): def __init__(self): - AmiciExample.__init__(self) + super().__init__() self.numX = 3 self.numP = 5 @@ -17,6 +23,12 @@ def __init__(self): self.modelOptions["kappa"] = [0.1, 0.4, 0.7, 1] self.modelOptions["ts"] = np.linspace(0, 100, 50) self.modelOptions["pscale"] = 2 + self.modelOptions["steadyStateComputationMode"] = int( + SteadyStateComputationMode.integrateIfNewtonFails + ) + self.modelOptions["steadyStateSensitivityMode"] = int( + SteadyStateSensitivityMode.integrateIfNewtonFails + ) def writeNoSensi(filename): @@ -34,7 +46,7 @@ def writeSensiForward(filename): ex.modelOptions["ts"] = np.append(np.linspace(0, 100, 50), np.inf) ex.solverOptions["sens_ind"] = np.arange(0, ex.numP) - ex.solverOptions["sensi"] = 1 + ex.solverOptions["sensi"] = int(SensitivityOrder.first) ex.solverOptions["ss_tol_factor"] = 1.0 ex.solverOptions["ss_tol_sensi_factor"] = 1.0 @@ -46,7 +58,7 @@ def writeSensiForwardPlist(filename): ex.modelOptions["ts"] = np.append(np.linspace(0, 100, 50), np.inf) ex.solverOptions["sens_ind"] = [3, 1, 2, 4] - ex.solverOptions["sensi"] = 1 + ex.solverOptions["sensi"] = int(SensitivityOrder.first) ex.solverOptions["ss_tol_factor"] = 1.0 ex.solverOptions["ss_tol_sensi_factor"] = 1.0 @@ -58,7 +70,7 @@ def writeSensiForwardDense(filename): ex.modelOptions["ts"] = np.append(np.linspace(0, 100, 50), np.inf) ex.solverOptions["sens_ind"] = np.arange(0, ex.numP) - ex.solverOptions["sensi"] = 1 + ex.solverOptions["sensi"] = int(SensitivityOrder.first) ex.solverOptions["linsol"] = 1 ex.solverOptions["ss_tol_factor"] = 1.0 ex.solverOptions["ss_tol_sensi_factor"] = 1.0 @@ -70,7 +82,7 @@ def writeSensiForwardErrorInt(filename): ex.modelOptions["ts"] = np.append(np.linspace(0, 100, 50), np.inf) ex.solverOptions["sens_ind"] = np.arange(0, ex.numP) - ex.solverOptions["sensi"] = 1 + ex.solverOptions["sensi"] = int(SensitivityOrder.first) ex.solverOptions["linsol"] = 9 ex.solverOptions["maxsteps"] = 100 ex.solverOptions["ss_tol_factor"] = 1.0 @@ -83,7 +95,7 @@ def writeSensiForwardErrorNewt(filename): ex = ExampleSteadystate() ex.modelOptions["ts"] = [0, np.inf] - ex.solverOptions["sensi"] = 1 + ex.solverOptions["sensi"] = int(SensitivityOrder.first) ex.solverOptions["sens_ind"] = np.arange(0, ex.numP) ex.solverOptions["linsol"] = 9 ex.solverOptions["maxsteps"] = 100 @@ -120,7 +132,7 @@ def writeSensiFwdNewtonPreeq(filename): ex.data["t"] = np.linspace(0, 5, 10) ex.modelOptions["ts"] = np.linspace(0, 5, 10) - ex.solverOptions["sensi"] = 1 + ex.solverOptions["sensi"] = int(SensitivityOrder.first) ex.solverOptions["sensi_meth"] = 1 ex.solverOptions["atol"] = 10**-16 ex.solverOptions["rtol"] = 10**-12 @@ -160,7 +172,7 @@ def writeSensiAdjNewtonPreeq(filename): ex.data["t"] = np.linspace(0, 5, 10) ex.modelOptions["ts"] = np.linspace(0, 5, 10) - ex.solverOptions["sensi"] = 1 + ex.solverOptions["sensi"] = int(SensitivityOrder.first) ex.solverOptions["sensi_meth"] = 2 ex.solverOptions["atol"] = 10**-16 ex.solverOptions["rtol"] = 10**-12 @@ -200,7 +212,7 @@ def writeSensiFwdSimPreeq(filename): ex.data["t"] = np.linspace(0, 5, 10) ex.modelOptions["ts"] = np.linspace(0, 5, 10) - ex.solverOptions["sensi"] = 1 + ex.solverOptions["sensi"] = int(SensitivityOrder.first) ex.solverOptions["sensi_meth"] = 1 ex.solverOptions["atol"] = 10**-16 ex.solverOptions["rtol"] = 10**-12 @@ -241,7 +253,7 @@ def writeSensiFwdSimPreeqFSA(filename): ex.modelOptions["ts"] = np.linspace(0, 5, 10) ex.modelOptions["steadyStateSensitivityMode"] = 1 - ex.solverOptions["sensi"] = 1 + ex.solverOptions["sensi"] = int(SensitivityOrder.first) ex.solverOptions["sensi_meth"] = 1 ex.solverOptions["atol"] = 10**-16 ex.solverOptions["rtol"] = 10**-12 @@ -281,7 +293,7 @@ def writeSensiAdjSimPreeq(filename): ex.data["t"] = np.linspace(0, 5, 10) ex.modelOptions["ts"] = np.linspace(0, 5, 10) - ex.solverOptions["sensi"] = 1 + ex.solverOptions["sensi"] = int(SensitivityOrder.first) ex.solverOptions["sensi_meth"] = 2 ex.solverOptions["atol"] = 10**-16 ex.solverOptions["rtol"] = 10**-12 @@ -322,7 +334,7 @@ def writeSensiAdjSimPreeqFSA(filename): ex.modelOptions["ts"] = np.linspace(0, 5, 10) ex.modelOptions["steadyStateSensitivityMode"] = 1 - ex.solverOptions["sensi"] = 1 + ex.solverOptions["sensi"] = int(SensitivityOrder.first) ex.solverOptions["sensi_meth"] = 2 ex.solverOptions["atol"] = 10**-16 ex.solverOptions["rtol"] = 10**-12 @@ -340,7 +352,7 @@ def writeSensiFwdByhandPreeq(filename): ex = ExampleSteadystate() ex.modelOptions["ts"] = np.linspace(0, 5, 10) - ex.solverOptions["sensi"] = 1 + ex.solverOptions["sensi"] = int(SensitivityOrder.first) ex.solverOptions["sensi_meth"] = 1 ex.solverOptions["x0"] = np.array( [0.532609637980272, 0.625849232840357, 0.066666666666667] @@ -391,7 +403,7 @@ def writeSensiAdjByhandPreeq(filename): ex.data["t"] = np.linspace(0, 5, 10) ex.modelOptions["ts"] = np.linspace(0, 5, 10) - ex.solverOptions["sensi"] = 1 + ex.solverOptions["sensi"] = int(SensitivityOrder.first) ex.solverOptions["sensi_meth"] = 2 ex.solverOptions["x0"] = np.array( [0.532609637980272, 0.625849232840357, 0.066666666666667] diff --git a/tests/generateTestConfigurationForExamples.sh b/tests/generateTestConfigurationForExamples.sh index e54f6f5ecc..8b8ef24e75 100755 --- a/tests/generateTestConfigurationForExamples.sh +++ b/tests/generateTestConfigurationForExamples.sh @@ -16,7 +16,7 @@ rm "${TEST_FILE}" cd "${AMICI_PATH}/tests/generateTestConfig" ./example_dirac.py "${TEST_FILE}" ./example_events.py "${TEST_FILE}" -./example_jakstat.py "${TEST_FILE}" +./example_jakstat_adjoint.py "${TEST_FILE}" ./example_nested_events.py "${TEST_FILE}" ./example_neuron.py "${TEST_FILE}" ./example_robertson.py "${TEST_FILE}"