From 2906611fda0488a95fde73a8312313bf91686e42 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Tue, 5 Mar 2024 16:47:42 +0100 Subject: [PATCH 1/5] Add new return code constant LSETUP_FAIL (#2353) --- include/amici/defines.h | 1 + src/amici.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/include/amici/defines.h b/include/amici/defines.h index f5ed1e62bb..210710b7ba 100644 --- a/include/amici/defines.h +++ b/include/amici/defines.h @@ -68,6 +68,7 @@ constexpr int AMICI_TOO_MUCH_WORK= -1; constexpr int AMICI_TOO_MUCH_ACC= -2; constexpr int AMICI_ERR_FAILURE= -3; constexpr int AMICI_CONV_FAILURE= -4; +constexpr int AMICI_LSETUP_FAIL= -6; constexpr int AMICI_RHSFUNC_FAIL= -8; constexpr int AMICI_FIRST_RHSFUNC_ERR= -9; constexpr int AMICI_ILL_INPUT= -22; diff --git a/src/amici.cpp b/src/amici.cpp index ecff1ea786..ef6d640e13 100644 --- a/src/amici.cpp +++ b/src/amici.cpp @@ -69,6 +69,7 @@ std::map simulation_status_to_str_map = { {AMICI_MAX_TIME_EXCEEDED, "AMICI_MAX_TIME_EXCEEDED"}, {AMICI_SUCCESS, "AMICI_SUCCESS"}, {AMICI_NOT_RUN, "AMICI_NOT_RUN"}, + {AMICI_LSETUP_FAIL, "AMICI_LSETUP_FAIL"}, }; std::unique_ptr runAmiciSimulation( From 2235ab7d7d4943bb88b071e4da090a4e0b9b37a3 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Tue, 5 Mar 2024 16:48:50 +0100 Subject: [PATCH 2/5] Fix in-place building of model wheels (#2352) Fix `python -m build -n` for generated model packages. Fixes half of #2285 --- python/sdist/amici/MANIFEST.template.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/sdist/amici/MANIFEST.template.in b/python/sdist/amici/MANIFEST.template.in index eb3b1b450f..fd78129853 100644 --- a/python/sdist/amici/MANIFEST.template.in +++ b/python/sdist/amici/MANIFEST.template.in @@ -1 +1,3 @@ include *.cpp *.h +include CMakeLists.txt +recursive-include swig/ * From 777deb0a1a3e50d39b6f6e1e172cf754514d62f3 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Tue, 5 Mar 2024 18:49:36 +0100 Subject: [PATCH 3/5] Always include timepoints in NaN/Inf warnings (#2347) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always include timepoints in NaN/Inf warnings Closes #2328 --------- Co-authored-by: Fabian Fröhlich --- include/amici/model.h | 7 +++-- src/amici.cpp | 4 +-- src/model.cpp | 69 +++++++++++++++++++++++++------------------ src/model_dae.cpp | 3 +- src/model_ode.cpp | 3 +- src/solver_cvodes.cpp | 34 +++++++++++---------- src/solver_idas.cpp | 30 +++++++++++-------- 7 files changed, 89 insertions(+), 61 deletions(-) diff --git a/include/amici/model.h b/include/amici/model.h index 13de007e00..29b98aa913 100644 --- a/include/amici/model.h +++ b/include/amici/model.h @@ -1334,10 +1334,12 @@ class Model : public AbstractModel, public ModelDimensions { * * @param array * @param model_quantity The model quantity `array` corresponds to + * @param t Current timepoint * @return */ int checkFinite( - gsl::span array, ModelQuantity model_quantity + gsl::span array, ModelQuantity model_quantity, + realtype t ) const; /** * @brief Check if the given array has only finite elements. @@ -1347,11 +1349,12 @@ class Model : public AbstractModel, public ModelDimensions { * @param array Flattened matrix * @param model_quantity The model quantity `array` corresponds to * @param num_cols Number of columns of the non-flattened matrix + * @param t Current timepoint * @return */ int checkFinite( gsl::span array, ModelQuantity model_quantity, - size_t num_cols + size_t num_cols, realtype t ) const; /** diff --git a/src/amici.cpp b/src/amici.cpp index ef6d640e13..cc8c2f00ab 100644 --- a/src/amici.cpp +++ b/src/amici.cpp @@ -223,8 +223,8 @@ std::unique_ptr runAmiciSimulation( try { rdata->processSimulationObjects( - preeq.get(), fwd.get(), bwd_success ? bwd.get() : nullptr, posteq.get(), - model, solver, edata + preeq.get(), fwd.get(), bwd_success ? bwd.get() : nullptr, + posteq.get(), model, solver, edata ); } catch (std::exception const& ex) { rdata->status = AMICI_ERROR; diff --git a/src/model.cpp b/src/model.cpp index b671de3c73..cefdf1ac97 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -372,7 +372,7 @@ void Model::initializeStates(AmiVector& x) { std::copy(x0_solver.cbegin(), x0_solver.cend(), x.data()); } - checkFinite(x.getVector(), ModelQuantity::x0); + checkFinite(x.getVector(), ModelQuantity::x0, t0()); } void Model::initializeSplines() { @@ -1482,7 +1482,7 @@ void Model::addStateEventUpdate( ); if (always_check_finite_) { - checkFinite(derived_state_.deltax_, ModelQuantity::deltax); + checkFinite(derived_state_.deltax_, ModelQuantity::deltax, t); } // update @@ -1536,7 +1536,7 @@ void Model::addAdjointStateEventUpdate( ); if (always_check_finite_) { - checkFinite(derived_state_.deltaxB_, ModelQuantity::deltaxB); + checkFinite(derived_state_.deltaxB_, ModelQuantity::deltaxB, t); } // apply update @@ -1582,7 +1582,7 @@ void Model::updateHeavisideB(int const* rootsfound) { } int Model::checkFinite( - gsl::span array, ModelQuantity model_quantity + gsl::span array, ModelQuantity model_quantity, realtype t ) const { auto it = std::find_if(array.begin(), array.end(), [](realtype x) { return !std::isfinite(x); @@ -1654,23 +1654,27 @@ int Model::checkFinite( gsl_ExpectsDebug(false); model_quantity_str = std::to_string(static_cast(model_quantity)); } - if (logger) + if (logger) { + auto t_msg = std::isfinite(t) + ? std::string(" at t=" + std::to_string(t) + " ") + : std::string(); + logger->log( LogSeverity::warning, msg_id, - "AMICI encountered a %s value for %s[%i] (%s)", + "AMICI encountered a %s value for %s[%i] (%s)%s", non_finite_type.c_str(), model_quantity_str.c_str(), - gsl::narrow(flat_index), element_id.c_str() + gsl::narrow(flat_index), element_id.c_str(), t_msg.c_str() ); - + } // check upstream, without infinite recursion if (model_quantity != ModelQuantity::k && model_quantity != ModelQuantity::p && model_quantity != ModelQuantity::ts) { - checkFinite(state_.fixedParameters, ModelQuantity::k); - checkFinite(state_.unscaledParameters, ModelQuantity::p); - checkFinite(simulation_parameters_.ts_, ModelQuantity::ts); + checkFinite(state_.fixedParameters, ModelQuantity::k, t); + checkFinite(state_.unscaledParameters, ModelQuantity::p, t); + checkFinite(simulation_parameters_.ts_, ModelQuantity::ts, t); if (!always_check_finite_ && model_quantity != ModelQuantity::w) { // don't check twice if always_check_finite_ is true - checkFinite(derived_state_.w_, ModelQuantity::w); + checkFinite(derived_state_.w_, ModelQuantity::w, t); } } return AMICI_RECOVERABLE_ERROR; @@ -1678,7 +1682,7 @@ int Model::checkFinite( int Model::checkFinite( gsl::span array, ModelQuantity model_quantity, - size_t num_cols + size_t num_cols, realtype t ) const { auto it = std::find_if(array.begin(), array.end(), [](realtype x) { return !std::isfinite(x); @@ -1768,19 +1772,25 @@ int Model::checkFinite( model_quantity_str = std::to_string(static_cast(model_quantity)); } - if (logger) + if (logger) { + auto t_msg = std::isfinite(t) + ? std::string(" at t=" + std::to_string(t) + " ") + : std::string(); + logger->log( LogSeverity::warning, msg_id, - "AMICI encountered a %s value for %s[%i] (%s, %s)", + "AMICI encountered a %s value for %s[%i] (%s, %s)%s", non_finite_type.c_str(), model_quantity_str.c_str(), - gsl::narrow(flat_index), row_id.c_str(), col_id.c_str() + gsl::narrow(flat_index), row_id.c_str(), col_id.c_str(), + t_msg.c_str() ); + } // check upstream - checkFinite(state_.fixedParameters, ModelQuantity::k); - checkFinite(state_.unscaledParameters, ModelQuantity::p); - checkFinite(simulation_parameters_.ts_, ModelQuantity::ts); - checkFinite(derived_state_.w_, ModelQuantity::w); + checkFinite(state_.fixedParameters, ModelQuantity::k, t); + checkFinite(state_.unscaledParameters, ModelQuantity::p, t); + checkFinite(simulation_parameters_.ts_, ModelQuantity::ts, t); + checkFinite(derived_state_.w_, ModelQuantity::w, t); return AMICI_RECOVERABLE_ERROR; } @@ -1868,10 +1878,10 @@ int Model::checkFinite(SUNMatrix m, ModelQuantity model_quantity, realtype t) ); // check upstream - checkFinite(state_.fixedParameters, ModelQuantity::k); - checkFinite(state_.unscaledParameters, ModelQuantity::p); - checkFinite(simulation_parameters_.ts_, ModelQuantity::ts); - checkFinite(derived_state_.w_, ModelQuantity::w); + checkFinite(state_.fixedParameters, ModelQuantity::k, t); + checkFinite(state_.unscaledParameters, ModelQuantity::p, t); + checkFinite(simulation_parameters_.ts_, ModelQuantity::ts, t); + checkFinite(derived_state_.w_, ModelQuantity::w, t); return AMICI_RECOVERABLE_ERROR; } @@ -1895,7 +1905,7 @@ void Model::fx0(AmiVector& x) { state_.unscaledParameters.data(), state_.fixedParameters.data() ); - checkFinite(derived_state_.x_rdata_, ModelQuantity::x0_rdata); + checkFinite(derived_state_.x_rdata_, ModelQuantity::x0_rdata, t0()); } void Model::fx0_fixedParameters(AmiVector& x) { @@ -1982,7 +1992,10 @@ void Model::fx_rdata(AmiVector& x_rdata, AmiVector const& x) { state_.unscaledParameters.data(), state_.fixedParameters.data() ); if (always_check_finite_) - checkFinite(x_rdata.getVector(), ModelQuantity::x_rdata); + checkFinite( + x_rdata.getVector(), ModelQuantity::x_rdata, + std::numeric_limits::quiet_NaN() + ); } void Model::fsx_rdata( @@ -2072,7 +2085,7 @@ void Model::fy(realtype const t, AmiVector const& x) { if (always_check_finite_) { checkFinite( - gsl::make_span(derived_state_.y_.data(), ny), ModelQuantity::y + gsl::make_span(derived_state_.y_.data(), ny), ModelQuantity::y, t ); } } @@ -2875,7 +2888,7 @@ void Model::fw(realtype const t, realtype const* x, bool include_static) { state_.spl_.data(), include_static); if (always_check_finite_) { - checkFinite(derived_state_.w_, ModelQuantity::w); + checkFinite(derived_state_.w_, ModelQuantity::w, t); } } diff --git a/src/model_dae.cpp b/src/model_dae.cpp index ad397bc82f..22025e1181 100644 --- a/src/model_dae.cpp +++ b/src/model_dae.cpp @@ -138,7 +138,8 @@ void Model_DAE::fJDiag( fJSparse(t, 0.0, x.getNVector(), dx.getNVector(), derived_state_.J_); derived_state_.J_.refresh(); derived_state_.J_.to_diag(JDiag.getNVector()); - if (checkFinite(JDiag.getVector(), ModelQuantity::JDiag) != AMICI_SUCCESS) + if (checkFinite(JDiag.getVector(), ModelQuantity::JDiag, t) + != AMICI_SUCCESS) throw AmiException("Evaluation of fJDiag failed!"); } diff --git a/src/model_ode.cpp b/src/model_ode.cpp index e3e401e1bf..787df210ef 100644 --- a/src/model_ode.cpp +++ b/src/model_ode.cpp @@ -122,7 +122,8 @@ void Model_ODE::fJDiag( AmiVector const& x, AmiVector const& /*dx*/ ) { fJDiag(t, JDiag.getNVector(), x.getNVector()); - if (checkFinite(JDiag.getVector(), ModelQuantity::JDiag) != AMICI_SUCCESS) + if (checkFinite(JDiag.getVector(), ModelQuantity::JDiag, t) + != AMICI_SUCCESS) throw AmiException("Evaluation of fJDiag failed!"); } diff --git a/src/solver_cvodes.cpp b/src/solver_cvodes.cpp index 4fe97720d8..0952724457 100644 --- a/src/solver_cvodes.cpp +++ b/src/solver_cvodes.cpp @@ -927,7 +927,7 @@ fJB(realtype t, N_Vector x, N_Vector xB, N_Vector xBdot, SUNMatrix JB, Expects(model); model->fJB(t, x, xB, xBdot, JB); - return model->checkFinite(gsl::make_span(JB), ModelQuantity::JB); + return model->checkFinite(gsl::make_span(JB), ModelQuantity::JB, t); } /** @@ -978,7 +978,7 @@ static int fJSparseB( Expects(model); model->fJSparseB(t, x, xB, xBdot, JB); - return model->checkFinite(gsl::make_span(JB), ModelQuantity::JB); + return model->checkFinite(gsl::make_span(JB), ModelQuantity::JB, t); } /** @@ -1041,7 +1041,7 @@ fJv(N_Vector v, N_Vector Jv, realtype t, N_Vector x, N_Vector /*xdot*/, Expects(model); model->fJv(v, Jv, t, x); - return model->checkFinite(gsl::make_span(Jv), ModelQuantity::Jv); + return model->checkFinite(gsl::make_span(Jv), ModelQuantity::Jv, t); } /** @@ -1067,7 +1067,7 @@ static int fJvB( Expects(model); model->fJvB(vB, JvB, t, x, xB); - return model->checkFinite(gsl::make_span(JvB), ModelQuantity::JvB); + return model->checkFinite(gsl::make_span(JvB), ModelQuantity::JvB, t); } /** @@ -1094,7 +1094,7 @@ static int froot(realtype t, N_Vector x, realtype* root, void* user_data) { model->froot(t, x, gsl::make_span(root, model->ne_solver)); } return model->checkFinite( - gsl::make_span(root, model->ne_solver), ModelQuantity::root + gsl::make_span(root, model->ne_solver), ModelQuantity::root, t ); } @@ -1119,7 +1119,7 @@ static int fxdot(realtype t, N_Vector x, N_Vector xdot, void* user_data) { } if (t > 1e200 - && !model->checkFinite(gsl::make_span(x), ModelQuantity::xdot)) { + && !model->checkFinite(gsl::make_span(x), ModelQuantity::xdot, t)) { /* when t is large (typically ~1e300), CVODES may pass all NaN x to fxdot from which we typically cannot recover. To save time on normal execution, we do not always want to check finiteness @@ -1128,7 +1128,7 @@ static int fxdot(realtype t, N_Vector x, N_Vector xdot, void* user_data) { } model->fxdot(t, x, xdot); - return model->checkFinite(gsl::make_span(xdot), ModelQuantity::xdot); + return model->checkFinite(gsl::make_span(xdot), ModelQuantity::xdot, t); } /** @@ -1154,7 +1154,7 @@ fxBdot(realtype t, N_Vector x, N_Vector xB, N_Vector xBdot, void* user_data) { } model->fxBdot(t, x, xB, xBdot); - return model->checkFinite(gsl::make_span(xBdot), ModelQuantity::xBdot); + return model->checkFinite(gsl::make_span(xBdot), ModelQuantity::xBdot, t); } /** @@ -1174,7 +1174,7 @@ fqBdot(realtype t, N_Vector x, N_Vector xB, N_Vector qBdot, void* user_data) { Expects(model); model->fqBdot(t, x, xB, qBdot); - return model->checkFinite(gsl::make_span(qBdot), ModelQuantity::qBdot); + return model->checkFinite(gsl::make_span(qBdot), ModelQuantity::qBdot, t); } /** @@ -1193,7 +1193,9 @@ static int fxBdot_ss(realtype t, N_Vector xB, N_Vector xBdot, void* user_data) { Expects(model); model->fxBdot_ss(t, xB, xBdot); - return model->checkFinite(gsl::make_span(xBdot), ModelQuantity::xBdot_ss); + return model->checkFinite( + gsl::make_span(xBdot), ModelQuantity::xBdot_ss, t + ); } /** @@ -1212,7 +1214,9 @@ static int fqBdot_ss(realtype t, N_Vector xB, N_Vector qBdot, void* user_data) { Expects(model); model->fqBdot_ss(t, xB, qBdot); - return model->checkFinite(gsl::make_span(qBdot), ModelQuantity::qBdot_ss); + return model->checkFinite( + gsl::make_span(qBdot), ModelQuantity::qBdot_ss, t + ); } /** @@ -1228,8 +1232,8 @@ static int fqBdot_ss(realtype t, N_Vector xB, N_Vector qBdot, void* user_data) { * @return status flag indicating successful execution */ static int fJSparseB_ss( - realtype /*t*/, N_Vector /*x*/, N_Vector xBdot, SUNMatrix JB, - void* user_data, N_Vector /*tmp1*/, N_Vector /*tmp2*/, N_Vector /*tmp3*/ + realtype t, N_Vector /*x*/, N_Vector xBdot, SUNMatrix JB, void* user_data, + N_Vector /*tmp1*/, N_Vector /*tmp2*/, N_Vector /*tmp3*/ ) { auto typed_udata = static_cast(user_data); Expects(typed_udata); @@ -1238,7 +1242,7 @@ static int fJSparseB_ss( model->fJSparseB_ss(JB); return model->checkFinite( - gsl::make_span(xBdot), ModelQuantity::JSparseB_ss + gsl::make_span(xBdot), ModelQuantity::JSparseB_ss, t ); } @@ -1267,7 +1271,7 @@ static int fsxdot( Expects(model); model->fsxdot(t, x, ip, sx, sxdot); - return model->checkFinite(gsl::make_span(sxdot), ModelQuantity::sxdot); + return model->checkFinite(gsl::make_span(sxdot), ModelQuantity::sxdot, t); } bool operator==(CVodeSolver const& a, CVodeSolver const& b) { diff --git a/src/solver_idas.cpp b/src/solver_idas.cpp index 1c69a041db..fa08bc29f9 100644 --- a/src/solver_idas.cpp +++ b/src/solver_idas.cpp @@ -1065,7 +1065,7 @@ int fJv( Expects(model); model->fJv(t, x, dx, v, Jv, cj); - return model->checkFinite(gsl::make_span(Jv), ModelQuantity::Jv); + return model->checkFinite(gsl::make_span(Jv), ModelQuantity::Jv, t); } /** @@ -1096,7 +1096,7 @@ int fJvB( Expects(model); model->fJvB(t, x, dx, xB, dxB, vB, JvB, cj); - return model->checkFinite(gsl::make_span(JvB), ModelQuantity::JvB); + return model->checkFinite(gsl::make_span(JvB), ModelQuantity::JvB, t); } /** @@ -1118,7 +1118,7 @@ int froot( model->froot(t, x, dx, gsl::make_span(root, model->ne)); return model->checkFinite( - gsl::make_span(root, model->ne), ModelQuantity::root + gsl::make_span(root, model->ne), ModelQuantity::root, t ); } @@ -1144,7 +1144,7 @@ int fxdot(realtype t, N_Vector x, N_Vector dx, N_Vector xdot, void* user_data) { } if (t > 1e200 - && !model->checkFinite(gsl::make_span(x), ModelQuantity::xdot)) { + && !model->checkFinite(gsl::make_span(x), ModelQuantity::xdot, t)) { /* when t is large (typically ~1e300), CVODES may pass all NaN x to fxdot from which we typically cannot recover. To save time on normal execution, we do not always want to check finiteness @@ -1153,7 +1153,7 @@ int fxdot(realtype t, N_Vector x, N_Vector dx, N_Vector xdot, void* user_data) { } model->fxdot(t, x, dx, xdot); - return model->checkFinite(gsl::make_span(xdot), ModelQuantity::xdot); + return model->checkFinite(gsl::make_span(xdot), ModelQuantity::xdot, t); } /** @@ -1183,7 +1183,7 @@ int fxBdot( } model->fxBdot(t, x, dx, xB, dxB, xBdot); - return model->checkFinite(gsl::make_span(xBdot), ModelQuantity::xBdot); + return model->checkFinite(gsl::make_span(xBdot), ModelQuantity::xBdot, t); } /** @@ -1208,7 +1208,7 @@ int fqBdot( Expects(model); model->fqBdot(t, x, dx, xB, dxB, qBdot); - return model->checkFinite(gsl::make_span(qBdot), ModelQuantity::qBdot); + return model->checkFinite(gsl::make_span(qBdot), ModelQuantity::qBdot, t); } /** @@ -1230,7 +1230,9 @@ static int fxBdot_ss( Expects(model); model->fxBdot_ss(t, xB, dxB, xBdot); - return model->checkFinite(gsl::make_span(xBdot), ModelQuantity::xBdot_ss); + return model->checkFinite( + gsl::make_span(xBdot), ModelQuantity::xBdot_ss, t + ); } /** @@ -1252,7 +1254,9 @@ static int fqBdot_ss( Expects(model); model->fqBdot_ss(t, xB, dxB, qBdot); - return model->checkFinite(gsl::make_span(qBdot), ModelQuantity::qBdot_ss); + return model->checkFinite( + gsl::make_span(qBdot), ModelQuantity::qBdot_ss, t + ); } /** @@ -1270,7 +1274,7 @@ static int fqBdot_ss( * @return status flag indicating successful execution */ static int fJSparseB_ss( - realtype /*t*/, realtype /*cj*/, N_Vector /*x*/, N_Vector /*dx*/, + realtype t, realtype /*cj*/, N_Vector /*x*/, N_Vector /*dx*/, N_Vector xBdot, SUNMatrix JB, void* user_data, N_Vector /*tmp1*/, N_Vector /*tmp2*/, N_Vector /*tmp3*/ ) { @@ -1281,7 +1285,7 @@ static int fJSparseB_ss( model->fJSparseB_ss(JB); return model->checkFinite( - gsl::make_span(xBdot), ModelQuantity::JSparseB_ss + gsl::make_span(xBdot), ModelQuantity::JSparseB_ss, t ); } @@ -1314,7 +1318,9 @@ int fsxdot( for (int ip = 0; ip < model->nplist(); ip++) { model->fsxdot(t, x, dx, ip, sx[ip], sdx[ip], sxdot[ip]); - if (model->checkFinite(gsl::make_span(sxdot[ip]), ModelQuantity::sxdot) + if (model->checkFinite( + gsl::make_span(sxdot[ip]), ModelQuantity::sxdot, t + ) != AMICI_SUCCESS) return AMICI_RECOVERABLE_ERROR; } From 89b00cf2758d85ac5eb920cf9dfb170656af3234 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Tue, 5 Mar 2024 18:59:08 +0100 Subject: [PATCH 4/5] Make is-zero-checks compatible to the upcoming sympy>1.12 (#2350) Current sympy master (tested: 0ededfcfc033ddca2d1d54a0eda85bf53c63761c): ```python IPython console for SymPy 1.13.dev (Python 3.12.2-64-bit) (ground types: python) In [1]: Float(0) == 0 Out[1]: False In [2]: Float(0).is_zero Out[2]: True ``` vs 1.12: ```python Python console for SymPy 1.12 (Python 3.12.2-64-bit) (ground types: python) >>> Float(0) == 0 True >>> Float(0).is_zero True ``` Therefore, replace `== 0` by `.is_zero`. Amongst other potential issues, this fixes zeros in sparse matrices. Closes #2320. --- python/sdist/amici/cxxcodeprinter.py | 2 +- python/sdist/amici/de_model.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/sdist/amici/cxxcodeprinter.py b/python/sdist/amici/cxxcodeprinter.py index adc4c25454..fb98b0aca0 100644 --- a/python/sdist/amici/cxxcodeprinter.py +++ b/python/sdist/amici/cxxcodeprinter.py @@ -339,7 +339,7 @@ def csc_matrix( for col in range(ncols): symbol_col_ptrs.append(idx) for row in range(nrows): - if matrix[row, col] == 0: + if matrix[row, col].is_zero: continue symbol_row_vals.append(row) diff --git a/python/sdist/amici/de_model.py b/python/sdist/amici/de_model.py index b69cc6ba68..ea2807df52 100644 --- a/python/sdist/amici/de_model.py +++ b/python/sdist/amici/de_model.py @@ -2115,7 +2115,7 @@ def state_is_constant(self, ix: int) -> bool: if isinstance(state, AlgebraicState): return False - return state.get_dt() == 0.0 + return state.get_dt().is_zero def conservation_law_has_multispecies(self, tcl: ConservationLaw) -> bool: """ @@ -2179,7 +2179,7 @@ def _get_unique_root( return None for root in roots: - if sp.simplify(root_found - root.get_val()) == 0: + if sp.simplify(root_found - root.get_val()).is_zero: return root.get_id() # create an event for a new root function From 0fea90d9cfb043bd00934a2247c2f1f4c18617b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fr=C3=B6hlich?= Date: Tue, 5 Mar 2024 19:22:03 +0000 Subject: [PATCH 5/5] fix venv and BLAS --- .github/workflows/test_petab_test_suite.yml | 8 ++++---- .github/workflows/test_python_cplusplus.yml | 14 +++++++------- .github/workflows/test_python_ver_matrix.yml | 6 +++--- .gitignore | 1 + CMakeLists.txt | 2 +- cmake/AmiciConfig.cmake | 2 ++ scripts/buildAmici.sh | 5 ++++- scripts/installAmiciArchive.sh | 10 +++++----- scripts/installAmiciSource.sh | 2 +- scripts/run-SBMLTestsuite.sh | 2 +- scripts/run-codecov.sh | 2 +- scripts/run-python-tests.sh | 2 +- scripts/run-valgrind-py.sh | 2 +- 13 files changed, 32 insertions(+), 26 deletions(-) diff --git a/.github/workflows/test_petab_test_suite.yml b/.github/workflows/test_petab_test_suite.yml index 6301269e03..b6465d554b 100644 --- a/.github/workflows/test_petab_test_suite.yml +++ b/.github/workflows/test_petab_test_suite.yml @@ -57,7 +57,7 @@ jobs: - name: Install petab run: | - source ./build/venv/bin/activate \ + source ./venv/bin/activate \ && pip3 install wheel pytest shyaml pytest-cov pysb # retrieve test models @@ -65,19 +65,19 @@ jobs: run: | git clone --depth 1 --branch main \ https://github.com/PEtab-dev/petab_test_suite \ - && source ./build/venv/bin/activate \ + && source ./venv/bin/activate \ && cd petab_test_suite && pip3 install -e . - name: Run PEtab-related unit tests run: | - source ./build/venv/bin/activate \ + source ./venv/bin/activate \ && pytest --cov-report=xml:coverage.xml \ --cov=./ python/tests/test_*petab*.py python/tests/petab/ # run test models - name: Run PEtab test suite run: | - source ./build/venv/bin/activate \ + source ./venv/bin/activate \ && AMICI_PARALLEL_COMPILE="" pytest -v \ --cov-report=xml:coverage.xml \ --cov-append \ diff --git a/.github/workflows/test_python_cplusplus.yml b/.github/workflows/test_python_cplusplus.yml index 58dd5480e5..f729d47867 100644 --- a/.github/workflows/test_python_cplusplus.yml +++ b/.github/workflows/test_python_cplusplus.yml @@ -45,11 +45,11 @@ jobs: run: scripts/installAmiciSource.sh - name: Check OpenMP support - run: source build/venv/bin/activate && python -c "import amici; import sys; sys.exit(not amici.compiledWithOpenMP())" + run: source venv/bin/activate && python -c "import amici; import sys; sys.exit(not amici.compiledWithOpenMP())" - name: Python tests (part 1) run: | - source build/venv/bin/activate \ + source venv/bin/activate \ && pytest \ --ignore-glob=*petab* \ --ignore-glob=*test_splines.py \ @@ -64,7 +64,7 @@ jobs: - name: Python tests splines if: ${{ github.base_ref == 'master' || github.event.merge_group.base_ref == 'master'}} run: | - source build/venv/bin/activate \ + source venv/bin/activate \ && pytest \ --cov=amici \ --cov-report=xml:"${AMICI_DIR}/build/coverage_py.xml" \ @@ -138,7 +138,7 @@ jobs: - name: Python tests run: | - source build/venv/bin/activate \ + source venv/bin/activate \ && pytest \ --cov=amici \ --cov-report=xml:"${AMICI_DIR}/build/coverage_py.xml" \ @@ -214,7 +214,7 @@ jobs: - name: Install notebook dependencies run: | - source build/venv/bin/activate \ + source venv/bin/activate \ && pip install jax[cpu] - name: example notebooks @@ -251,7 +251,7 @@ jobs: run: scripts/installAmiciSource.sh - name: Check OpenMP support - run: source build/venv/bin/activate && python -c "import amici; import sys; sys.exit(not amici.compiledWithOpenMP())" + run: source venv/bin/activate && python -c "import amici; import sys; sys.exit(not amici.compiledWithOpenMP())" - name: cppcheck run: scripts/run-cppcheck.sh @@ -296,7 +296,7 @@ jobs: scripts/installAmiciSource.sh - name: Check OpenMP support - run: source build/venv/bin/activate && python -c "import amici; import sys; sys.exit(not amici.compiledWithOpenMP())" + run: source venv/bin/activate && python -c "import amici; import sys; sys.exit(not amici.compiledWithOpenMP())" - name: Get BioNetGen run: scripts/buildBNGL.sh diff --git a/.github/workflows/test_python_ver_matrix.yml b/.github/workflows/test_python_ver_matrix.yml index 28b86d1c01..414daadccc 100644 --- a/.github/workflows/test_python_ver_matrix.yml +++ b/.github/workflows/test_python_ver_matrix.yml @@ -51,15 +51,15 @@ jobs: run: scripts/installAmiciSource.sh # install pysb before sympy to allow for sympy>=1.12 (https://github.com/pysb/pysb/commit/e83937cb8c74afc9b2fa96595b68464946745f33) - - run: source build/venv/bin/activate && pip3 install git+https://github.com/pysb/pysb + - run: source venv/bin/activate && pip3 install git+https://github.com/pysb/pysb # until sympy>1.12 is released - - run: source build/venv/bin/activate && pip3 install git+https://github.com/sympy/sympy.git@master + - run: source venv/bin/activate && pip3 install git+https://github.com/sympy/sympy.git@master if: matrix.python-version == '3.12' - name: Python tests run: | - source build/venv/bin/activate \ + source venv/bin/activate \ && python3 -m pytest \ --durations=10 \ --ignore-glob=*petab* \ diff --git a/.gitignore b/.gitignore index 60b9ff5031..4dc2884415 100644 --- a/.gitignore +++ b/.gitignore @@ -202,3 +202,4 @@ CS_Signalling_ERBB_RAS_AKT/ cache_fiddy/* debug/* tests/benchmark-models/cache_fiddy/* +venv/* diff --git a/CMakeLists.txt b/CMakeLists.txt index 324426f2a7..144585a19a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -354,12 +354,12 @@ target_link_libraries( SUNDIALS::sunnonlinsolfixedpoint_static SUNDIALS::cvodes_static SUNDIALS::idas_static - ${BLAS_LIBRARIES} $<$:Boost::chrono> $<$:OpenMP::OpenMP_CXX> ${CMAKE_DL_LIBS} PRIVATE $<$:SUNDIALS::sundials_sunlinsolsuperlumt> + BLAS::BLAS ) if(HDF5_FOUND) diff --git a/cmake/AmiciConfig.cmake b/cmake/AmiciConfig.cmake index ebef45d6e0..9f7a8d20a2 100644 --- a/cmake/AmiciConfig.cmake +++ b/cmake/AmiciConfig.cmake @@ -62,6 +62,8 @@ if(@HDF5_FOUND@) REQUIRED) endif() +find_package(BLAS) + include("${CMAKE_CURRENT_LIST_DIR}/AmiciTargets.cmake") check_required_components(Amici) diff --git a/scripts/buildAmici.sh b/scripts/buildAmici.sh index 507a391621..84e2afa22f 100755 --- a/scripts/buildAmici.sh +++ b/scripts/buildAmici.sh @@ -25,7 +25,10 @@ else fi # required for build swig interface -pip show numpy > /dev/null || python3 -m pip install numpy +python3 -m venv "${amici_path}/venv" +source "${amici_path}/venv/bin/activate" +export PYTHON_EXECUTABLE="${amici_path}/venv/bin/python" +pip3 show numpy > /dev/null || python3 -m pip install numpy ${cmake} \ -Wdev -DAMICI_CXX_OPTIONS="-Wall;-Wextra${extra_cxx_flags}" \ diff --git a/scripts/installAmiciArchive.sh b/scripts/installAmiciArchive.sh index 25de4f9f93..a48c98a425 100755 --- a/scripts/installAmiciArchive.sh +++ b/scripts/installAmiciArchive.sh @@ -18,18 +18,18 @@ rm -f ${AMICI_PATH}/python/sdist/amici/amici_without_hdf5.py # test install from archive set +e -python3 -m venv ${AMICI_PATH}/build/venvArchive --clear +python3 -m venv ${AMICI_PATH}/venvArchive --clear # in case this fails (usually due to missing ensurepip, try getting pip # manually if [[ $? ]]; then set -e - python3 -m venv ${AMICI_PATH}/build/venvArchive --clear --without-pip - source ${AMICI_PATH}/build/venvArchive/bin/activate + python3 -m venv ${AMICI_PATH}/venvArchive --clear --without-pip + source ${AMICI_PATH}/venvArchive/bin/activate curl https://bootstrap.pypa.io/get-pip.py -o ${AMICI_PATH}/build/get-pip.py - python ${AMICI_PATH}/build/get-pip.py + python ${AMICI_PATH}/get-pip.py else set -e - source ${AMICI_PATH}/build/venvArchive/bin/activate + source ${AMICI_PATH}/venvArchive/bin/activate fi pip install $(ls -t ${AMICI_PATH}/build/python/amici-*.tar.gz | head -1) diff --git a/scripts/installAmiciSource.sh b/scripts/installAmiciSource.sh index bbb4bf4a83..37088c0933 100755 --- a/scripts/installAmiciSource.sh +++ b/scripts/installAmiciSource.sh @@ -5,7 +5,7 @@ set -e SCRIPT_PATH=$(dirname $BASH_SOURCE) AMICI_PATH=$(cd "$SCRIPT_PATH/.." && pwd) -venv_dir="${AMICI_PATH}/build/venv" +venv_dir="${AMICI_PATH}/venv" # Disabled until cmake package is made compatible with updated setup.py #make python-wheel #pip3 install --user --prefix= `ls -t ${AMICI_PATH}/build/python/amici-*.whl | head -1` diff --git a/scripts/run-SBMLTestsuite.sh b/scripts/run-SBMLTestsuite.sh index 97c2033751..a3dcee1681 100755 --- a/scripts/run-SBMLTestsuite.sh +++ b/scripts/run-SBMLTestsuite.sh @@ -9,7 +9,7 @@ if [[ ! -d "tests/sbml-test-suite" ]]; then mv -f ./sbml-test-suite ./tests/sbml-test-suite fi -source build/venv/bin/activate +source venv/bin/activate pip show pytest-xdist > /dev/null 2>&1 || pip install pytest-xdist pip install coverage pytest-cov diff --git a/scripts/run-codecov.sh b/scripts/run-codecov.sh index 42d76f7a0e..f5f253b5c9 100755 --- a/scripts/run-codecov.sh +++ b/scripts/run-codecov.sh @@ -4,7 +4,7 @@ script_path=$(dirname $BASH_SOURCE) amici_path=$(cd "$script_path"/.. && pwd) -source "${amici_path}"/build/venv/bin/activate +source "${amici_path}"/venv/bin/activate pip install coverage pytest pytest-cov if [[ -z "${BNGPATH}" ]]; then diff --git a/scripts/run-python-tests.sh b/scripts/run-python-tests.sh index d58a1c8dec..0fed628fce 100755 --- a/scripts/run-python-tests.sh +++ b/scripts/run-python-tests.sh @@ -12,7 +12,7 @@ if [[ -z "${BNGPATH}" ]]; then fi cd "${amici_path}"/python/tests -source "${amici_path}"/build/venv/bin/activate +source "${amici_path}"/venv/bin/activate # PEtab tests are run separately pytest \ diff --git a/scripts/run-valgrind-py.sh b/scripts/run-valgrind-py.sh index c2a6239ad4..9621c24d31 100755 --- a/scripts/run-valgrind-py.sh +++ b/scripts/run-valgrind-py.sh @@ -15,7 +15,7 @@ if [ $# -eq 0 ] then # No arguments supplied, run all tests cd "${amici_path}"/python/tests - source "${amici_path}"/build/venv/bin/activate + source "${amici_path}"/venv/bin/activate command=(python -m pytest -vv --ignore-glob=*petab* -W 'ignore:Signature ') # ^ ignores the following warning that occurs only under valgrind, # e.g. `valgrind python -c "import h5py"`: