Skip to content

Commit eb3fd4a

Browse files
authored
Split expressions into static and dynamic (#2303)
Split expressions in `w` and its derivatives into dynamic (explicitly or implicitly time-dependent) and static ones. Evaluate static ones only when needed, i.e. after (re)initializing x_rdata or parameters. See #1269
1 parent 6a1cc3c commit eb3fd4a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+999
-645
lines changed

.github/actions/setup-amici-cpp/action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ runs:
1818
- run: echo "ENABLE_GCOV_COVERAGE=TRUE" >> $GITHUB_ENV
1919
shell: bash
2020

21+
- run: echo "PYTHONFAULTHANDLER=1" >> $GITHUB_ENV
22+
shell: bash
23+
2124
- name: Set up Sonar tools
2225
uses: ./.github/actions/setup-sonar-tools
2326

include/amici/abstract_model.h

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -820,11 +820,15 @@ class AbstractModel {
820820
* @param h Heaviside vector
821821
* @param tcl total abundances for conservation laws
822822
* @param spl spline value vector
823+
* @param include_static Whether to (re-)evaluate only dynamic expressions
824+
* (false) or also static expressions (true).
825+
* Dynamic expressions are those that depend directly or indirectly on time,
826+
* static expressions are those that don't.
823827
*/
824828
virtual void
825829
fw(realtype* w, realtype const t, realtype const* x, realtype const* p,
826830
realtype const* k, realtype const* h, realtype const* tcl,
827-
realtype const* spl);
831+
realtype const* spl, bool include_static = true);
828832

829833
/**
830834
* @brief Model-specific sparse implementation of dwdp
@@ -840,12 +844,16 @@ class AbstractModel {
840844
* @param spl spline value vector
841845
* @param sspl sensitivities of spline values vector w.r.t. parameters \f$ p
842846
* \f$
847+
* @param include_static Whether to (re-)evaluate only dynamic expressions
848+
* (false) or also static expressions (true).
849+
* Dynamic expressions are those that depend directly or indirectly on time,
850+
* static expressions are those that don't.
843851
*/
844852
virtual void fdwdp(
845853
realtype* dwdp, realtype const t, realtype const* x, realtype const* p,
846854
realtype const* k, realtype const* h, realtype const* w,
847855
realtype const* tcl, realtype const* stcl, realtype const* spl,
848-
realtype const* sspl
856+
realtype const* sspl, bool include_static = true
849857
);
850858

851859
/**
@@ -860,28 +868,6 @@ class AbstractModel {
860868
*/
861869
virtual void fdwdp_rowvals(SUNMatrixWrapper& dwdp);
862870

863-
/**
864-
* @brief Model-specific sensitivity implementation of dwdp
865-
* @param dwdp Recurring terms in xdot, parameter derivative
866-
* @param t timepoint
867-
* @param x vector with the states
868-
* @param p parameter vector
869-
* @param k constants vector
870-
* @param h Heaviside vector
871-
* @param w vector with helper variables
872-
* @param tcl total abundances for conservation laws
873-
* @param stcl sensitivities of total abundances for conservation laws
874-
* @param spl spline value vector
875-
* @param sspl sensitivities of spline values vector
876-
* @param ip sensitivity parameter index
877-
*/
878-
virtual void fdwdp(
879-
realtype* dwdp, realtype const t, realtype const* x, realtype const* p,
880-
realtype const* k, realtype const* h, realtype const* w,
881-
realtype const* tcl, realtype const* stcl, realtype const* spl,
882-
realtype const* sspl, int ip
883-
);
884-
885871
/**
886872
* @brief Model-specific implementation of dwdx, data part
887873
* @param dwdx Recurring terms in xdot, state derivative
@@ -893,11 +879,15 @@ class AbstractModel {
893879
* @param w vector with helper variables
894880
* @param tcl total abundances for conservation laws
895881
* @param spl spline value vector
882+
* @param include_static Whether to (re-)evaluate only dynamic expressions
883+
* (false) or also static expressions (true).
884+
* Dynamic expressions are those that depend directly or indirectly on time,
885+
* static expressions are those that don't.
896886
*/
897887
virtual void fdwdx(
898888
realtype* dwdx, realtype const t, realtype const* x, realtype const* p,
899889
realtype const* k, realtype const* h, realtype const* w,
900-
realtype const* tcl, realtype const* spl
890+
realtype const* tcl, realtype const* spl, bool include_static = true
901891
);
902892

903893
/**
@@ -922,11 +912,15 @@ class AbstractModel {
922912
* @param h Heaviside vector
923913
* @param w vector with helper variables
924914
* @param tcl Total abundances for conservation laws
915+
* @param include_static Whether to (re-)evaluate only dynamic expressions
916+
* (false) or also static expressions (true).
917+
* Dynamic expressions are those that depend directly or indirectly on time,
918+
* static expressions are those that don't.
925919
*/
926920
virtual void fdwdw(
927921
realtype* dwdw, realtype t, realtype const* x, realtype const* p,
928922
realtype const* k, realtype const* h, realtype const* w,
929-
realtype const* tcl
923+
realtype const* tcl, bool include_static = true
930924
);
931925

932926
/**

include/amici/model.h

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,18 @@ class Model : public AbstractModel, public ModelDimensions {
239239
bool computeSensitivities, std::vector<int>& roots_found
240240
);
241241

242+
/**
243+
* @brief Re-initialize model properties after changing simulation context.
244+
* @param t Timepoint
245+
* @param x Reference to state variables
246+
* @param sx Reference to state variable sensitivities
247+
* @param computeSensitivities Flag indicating whether sensitivities are to
248+
* be computed
249+
*/
250+
void reinitialize(
251+
realtype t, AmiVector& x, AmiVectorArray& sx, bool computeSensitivities
252+
);
253+
242254
/**
243255
* @brief Initialize model properties.
244256
* @param xB Adjoint state variables
@@ -1828,29 +1840,45 @@ class Model : public AbstractModel, public ModelDimensions {
18281840
* @brief Compute recurring terms in xdot.
18291841
* @param t Timepoint
18301842
* @param x Array with the states
1843+
* @param include_static Whether to (re-)evaluate only dynamic expressions
1844+
* (false) or also static expressions (true).
1845+
* Dynamic expressions are those that depend directly or indirectly on time,
1846+
* static expressions are those that don't.
18311847
*/
1832-
void fw(realtype t, realtype const* x);
1848+
void fw(realtype t, realtype const* x, bool include_static = true);
18331849

18341850
/**
18351851
* @brief Compute parameter derivative for recurring terms in xdot.
18361852
* @param t Timepoint
18371853
* @param x Array with the states
1854+
* @param include_static Whether to (re-)evaluate only dynamic expressions
1855+
* (false) or also static expressions (true).
1856+
* Dynamic expressions are those that depend directly or indirectly on time,
1857+
* static expressions are those that don't.
18381858
*/
1839-
void fdwdp(realtype t, realtype const* x);
1859+
void fdwdp(realtype t, realtype const* x, bool include_static = true);
18401860

18411861
/**
18421862
* @brief Compute state derivative for recurring terms in xdot.
18431863
* @param t Timepoint
18441864
* @param x Array with the states
1865+
* @param include_static Whether to (re-)evaluate only dynamic expressions
1866+
* (false) or also static expressions (true).
1867+
* Dynamic expressions are those that depend directly or indirectly on time,
1868+
* static expressions are those that don't.
18451869
*/
1846-
void fdwdx(realtype t, realtype const* x);
1870+
void fdwdx(realtype t, realtype const* x, bool include_static = true);
18471871

18481872
/**
18491873
* @brief Compute self derivative for recurring terms in xdot.
18501874
* @param t Timepoint
18511875
* @param x Array with the states
1876+
* @param include_static Whether to (re-)evaluate only dynamic expressions
1877+
* (false) or also static expressions (true).
1878+
* Dynamic expressions are those that depend directly or indirectly on time,
1879+
* static expressions are those that don't.
18521880
*/
1853-
void fdwdw(realtype t, realtype const* x);
1881+
void fdwdw(realtype t, realtype const* x, bool include_static = true);
18541882

18551883
/**
18561884
* @brief Compute fx_rdata.

matlab/@amifun/getArgs.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,11 @@
108108
case 'dJrzdsigma'
109109
this.argstr = '(double *dJrzdsigma, const int iz, const realtype *p, const realtype *k, const double *rz, const double *sigmaz)';
110110
case 'w'
111-
this.argstr = '(realtype *w, const realtype t, const realtype *x, const realtype *p, const realtype *k, const realtype *h, const realtype *tcl, const realtype *spl)';
111+
this.argstr = '(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)';
112112
case 'dwdp'
113-
this.argstr = '(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 *stcl, const realtype *spl, const realtype *sspl)';
113+
this.argstr = '(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 *stcl, const realtype *spl, const realtype *sspl, bool include_static)';
114114
case 'dwdx'
115-
this.argstr = '(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)';
115+
this.argstr = '(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)';
116116
case 'M'
117117
this.argstr = '(realtype *M, const realtype t, const realtype *x, const realtype *p, const realtype *k)';
118118
otherwise

matlab/@amimodel/generateC.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ function generateC(this)
209209
end
210210
fprintf(fid,'};\n\n');
211211
fprintf(fid,['} // namespace model_' this.modelname '\n\n']);
212-
fprintf(fid,'} // namespace amici \n\n');
212+
fprintf(fid,'} // namespace amici\n\n');
213213
fprintf(fid,['#endif /* _amici_' this.modelname '_h */\n']);
214214
fclose(fid);
215215

@@ -253,6 +253,7 @@ function generateC(this)
253253

254254
argstr = strrep(argstr,'realtype','');
255255
argstr = strrep(argstr,'int','');
256+
argstr = strrep(argstr,'bool','');
256257
argstr = strrep(argstr,'const','');
257258
argstr = strrep(argstr,'double','');
258259
argstr = strrep(argstr,'SUNMatrixContent_Sparse','');

models/model_calvetti/CMakeLists.txt

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Build AMICI model
22
cmake_minimum_required(VERSION 3.15)
3+
cmake_policy(VERSION 3.15...3.27)
4+
5+
# cmake >=3.27
6+
if(POLICY CMP0144)
7+
cmake_policy(SET CMP0144 NEW)
8+
endif(POLICY CMP0144)
39

410
project(model_calvetti)
511

@@ -14,7 +20,7 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
1420
endif()
1521
foreach(flag ${MY_CXX_FLAGS})
1622
unset(CUR_FLAG_SUPPORTED CACHE)
17-
check_cxx_compiler_flag(-Werror ${flag} CUR_FLAG_SUPPORTED)
23+
check_cxx_compiler_flag(${flag} CUR_FLAG_SUPPORTED)
1824
if(${CUR_FLAG_SUPPORTED})
1925
string(APPEND CMAKE_CXX_FLAGS " ${flag}")
2026
endif()
@@ -33,6 +39,23 @@ find_package(Amici REQUIRED HINTS
3339
${CMAKE_CURRENT_LIST_DIR}/../../build)
3440
message(STATUS "Found AMICI ${Amici_DIR}")
3541

42+
# Debug build?
43+
if("$ENV{ENABLE_AMICI_DEBUGGING}" OR "$ENV{ENABLE_GCOV_COVERAGE}")
44+
add_compile_options(-UNDEBUG)
45+
if(MSVC)
46+
add_compile_options(-DEBUG)
47+
else()
48+
add_compile_options(-O0 -g)
49+
endif()
50+
set(CMAKE_BUILD_TYPE "Debug")
51+
endif()
52+
53+
# coverage options
54+
if($ENV{ENABLE_GCOV_COVERAGE})
55+
string(APPEND CMAKE_CXX_FLAGS_DEBUG " --coverage")
56+
string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " --coverage")
57+
endif()
58+
3659
set(MODEL_DIR ${CMAKE_CURRENT_LIST_DIR})
3760

3861
set(SRC_LIST_LIB ${MODEL_DIR}/JSparse.cpp
@@ -73,18 +96,6 @@ if(NOT "${AMICI_PYTHON_BUILD_EXT_ONLY}")
7396
target_link_libraries(simulate_${PROJECT_NAME} ${PROJECT_NAME})
7497
endif()
7598

76-
# Debug build?
77-
if("$ENV{ENABLE_AMICI_DEBUGGING}" OR "$ENV{ENABLE_GCOV_COVERAGE}")
78-
add_compile_options(-UNDEBUG -O0 -g)
79-
set(CMAKE_BUILD_TYPE "Debug")
80-
endif()
81-
82-
# coverage options
83-
if($ENV{ENABLE_GCOV_COVERAGE})
84-
string(APPEND CMAKE_CXX_FLAGS_DEBUG " --coverage")
85-
string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " --coverage")
86-
endif()
87-
8899
# SWIG
89100
option(ENABLE_SWIG "Build swig/python library?" ON)
90101
if(ENABLE_SWIG)

models/model_calvetti/dwdx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace amici {
1010

1111
namespace model_model_calvetti{
1212

13-
void dwdx_model_calvetti(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) {
13+
void dwdx_model_calvetti(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) {
1414
dwdx[0] = 1.0/(x[0]*x[0]*x[0])*-2.0;
1515
dwdx[1] = k[1]*w[15]*dwdx[0];
1616
dwdx[2] = dwdx[1];

models/model_calvetti/main.cpp

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
#include <iostream>
22

3-
#include <amici/amici.h> /* AMICI base functions */
4-
#include "wrapfunctions.h" /* model-provided functions */
3+
#include "wrapfunctions.h" /* model-provided functions */
4+
#include <amici/amici.h> /* AMICI base functions */
55

6-
template < class T >
7-
std::ostream& operator << (std::ostream& os, const std::vector<T>& v)
8-
{
6+
template <class T>
7+
std::ostream& operator<<(std::ostream& os, std::vector<T> const& v) {
98
os << "[";
10-
for (typename std::vector<T>::const_iterator ii = v.begin(); ii != v.end(); ++ii)
11-
{
9+
for (typename std::vector<T>::const_iterator ii = v.begin(); ii != v.end();
10+
++ii) {
1211
os << " " << *ii;
1312
}
1413
os << "]";
@@ -21,9 +20,9 @@ std::ostream& operator << (std::ostream& os, const std::vector<T>& v)
2120
*/
2221

2322
int main() {
24-
std::cout<<"********************************"<<std::endl;
25-
std::cout<<"** Running forward simulation **"<<std::endl;
26-
std::cout<<"********************************"<<std::endl<<std::endl;
23+
std::cout << "********************************" << std::endl;
24+
std::cout << "** Running forward simulation **" << std::endl;
25+
std::cout << "********************************" << std::endl << std::endl;
2726

2827
// Create a model instance
2928
auto model = amici::generic_model::getModel();
@@ -44,21 +43,20 @@ int main() {
4443

4544
// Print observable time course
4645
auto observable_ids = model->getObservableIds();
47-
std::cout<<"Simulated observables for timepoints "<<rdata->ts<<"\n\n";
48-
for(int i_observable = 0; i_observable < rdata->ny; ++i_observable) {
49-
std::cout<<observable_ids[i_observable]<<":\n\t";
50-
for(int i_time = 0; i_time < rdata->nt; ++i_time) {
46+
std::cout << "Simulated observables for timepoints " << rdata->ts << "\n\n";
47+
for (int i_observable = 0; i_observable < rdata->ny; ++i_observable) {
48+
std::cout << observable_ids[i_observable] << ":\n\t";
49+
for (int i_time = 0; i_time < rdata->nt; ++i_time) {
5150
// rdata->y is a flat 2D array in row-major ordering
52-
std::cout<<rdata->y[i_time * rdata->ny + i_observable]<<" ";
51+
std::cout << rdata->y[i_time * rdata->ny + i_observable] << " ";
5352
}
54-
std::cout<<std::endl<<std::endl;
53+
std::cout << std::endl << std::endl;
5554
}
5655

57-
58-
std::cout<<std::endl;
59-
std::cout<<"**********************************"<<std::endl;
60-
std::cout<<"** Forward sensitivity analysis **"<<std::endl;
61-
std::cout<<"**********************************"<<std::endl<<std::endl;
56+
std::cout << std::endl;
57+
std::cout << "**********************************" << std::endl;
58+
std::cout << "** Forward sensitivity analysis **" << std::endl;
59+
std::cout << "**********************************" << std::endl << std::endl;
6260

6361
// Enable first-order sensitivity analysis
6462
solver->setSensitivityOrder(amici::SensitivityOrder::first);
@@ -78,18 +76,17 @@ int main() {
7876
auto state_ids = model->getStateIds();
7977
auto parameter_ids = model->getParameterIds();
8078

81-
std::cout<<"State sensitivities for timepoint "
82-
<<rdata->ts[i_time]
83-
<<std::endl;//nt x nplist x nx
84-
for(int i_state= 0; i_state < rdata->nx; ++i_state) {
85-
std::cout<<"\td("<<state_ids[i_state]<<")/d("
86-
<<parameter_ids[model->plist(i_nplist)]<<") = ";
79+
std::cout << "State sensitivities for timepoint " << rdata->ts[i_time]
80+
<< std::endl; // nt x nplist x nx
81+
for (int i_state = 0; i_state < rdata->nx; ++i_state) {
82+
std::cout << "\td(" << state_ids[i_state] << ")/d("
83+
<< parameter_ids[model->plist(i_nplist)] << ") = ";
8784

8885
// rdata->sx is a flat 3D array in row-major ordering
89-
std::cout<<rdata->sx[i_time * rdata->nplist * rdata->nx
90-
+ i_nplist * rdata->nx
91-
+ i_state];
92-
std::cout<<std::endl;
86+
std::cout << rdata->sx
87+
[i_time * rdata->nplist * rdata->nx
88+
+ i_nplist * rdata->nx + i_state];
89+
std::cout << std::endl;
9390
}
9491

9592
return 0;

0 commit comments

Comments
 (0)