Skip to content

Commit 2922a4b

Browse files
authored
Fix (some) ASA event handling (#2797)
* Fix backward simulation: In the forward simulation, measurements are handled after events. So for the backward integration, events should be handled after data points. * Make Heaviside updates more visible * Store Heaviside values and additional other pre-event state during event handling for the backward simulation * Remove the now obsolete `Model::updateHeavisideB`
1 parent a3dc1cc commit 2922a4b

File tree

5 files changed

+47
-28
lines changed

5 files changed

+47
-28
lines changed

include/amici/forwardproblem.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,40 @@ struct Discontinuity {
2525
* @brief Constructor.
2626
* @param time
2727
* @param root_info
28+
* @param x_pre
2829
* @param xdot_pre
2930
* @param x_post
3031
* @param xdot_post
32+
* @param h_pre
33+
* @param total_cl_pre
3134
*/
3235
explicit Discontinuity(
3336
realtype time, std::vector<int> const& root_info = std::vector<int>(),
37+
AmiVector const& x_pre = AmiVector(),
3438
AmiVector const& xdot_pre = AmiVector(),
3539
AmiVector const& x_post = AmiVector(),
36-
AmiVector const& xdot_post = AmiVector()
40+
AmiVector const& xdot_post = AmiVector(),
41+
std::vector<realtype> const& h_pre = std::vector<realtype>(),
42+
std::vector<realtype> const& total_cl_pre = std::vector<realtype>(0)
3743
)
3844
: time(time)
3945
, x_post(x_post)
46+
, x_pre(x_pre)
4047
, xdot_post(xdot_post)
4148
, xdot_pre(xdot_pre)
42-
, root_info(root_info) {}
49+
, root_info(root_info)
50+
, h_pre(h_pre)
51+
, total_cl_pre(total_cl_pre) {}
4352

4453
/** Time of discontinuity. */
4554
realtype time;
4655

4756
/** Post-event state vector (dimension nx). */
4857
AmiVector x_post;
4958

59+
/** Pre-event state vector (dimension nx). */
60+
AmiVector x_pre;
61+
5062
/** Post-event differential state vectors (dimension nx). */
5163
AmiVector xdot_post;
5264

@@ -61,6 +73,16 @@ struct Discontinuity {
6173
* if not. See CVodeGetRootInfo for details.
6274
*/
6375
std::vector<int> root_info;
76+
77+
/**
78+
* Flag indicating whether a certain Heaviside function should be active or
79+
* not, pre-event value (dimension: `ne`)
80+
*/
81+
std::vector<realtype> h_pre;
82+
83+
/** Total abundances for conservation laws
84+
(dimension: `nx_rdata - nx_solver`) */
85+
std::vector<realtype> total_cl_pre;
6486
};
6587

6688
/**

include/amici/model.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,15 +1359,6 @@ class Model : public AbstractModel, public ModelDimensions {
13591359
*/
13601360
void updateHeaviside(std::vector<int> const& rootsfound);
13611361

1362-
/**
1363-
* @brief Updates the Heaviside variables `h` on event occurrences in the
1364-
* backward problem.
1365-
* @param rootsfound Provides the direction of the zero-crossing, so adding
1366-
* it will give the right update to the Heaviside variables (zero if no root
1367-
* was found)
1368-
*/
1369-
void updateHeavisideB(int const* rootsfound);
1370-
13711362
/**
13721363
* @brief Check if the given array has only finite elements.
13731364
*

src/backwardproblem.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,11 @@ void EventHandlingBwdSimulator::handleEventB(
129129
ws_->nroots_[ie]--;
130130
}
131131

132-
model_->updateHeavisideB(disc.root_info.data());
132+
// apply pre-event state
133+
auto state = model_->getModelState();
134+
state.h = disc.h_pre;
135+
state.total_cl = disc.total_cl_pre;
136+
model_->setModelState(state);
133137
}
134138

135139
void EventHandlingBwdSimulator::handleDataPointB(
@@ -218,18 +222,18 @@ void EventHandlingBwdSimulator::run(
218222
);
219223
}
220224

221-
// handle discontinuity
222-
if (!ws_->discs_.empty() && tnext == ws_->discs_.back().time) {
223-
handleEventB(ws_->discs_.back(), dJzdx);
224-
ws_->discs_.pop_back();
225-
}
226-
227225
// handle data-point
228226
if (it >= 0 && tnext == timepoints[it]) {
229227
handleDataPointB(it, dJydx);
230228
it--;
231229
}
232230

231+
// handle discontinuity
232+
if (!ws_->discs_.empty() && tnext == ws_->discs_.back().time) {
233+
handleEventB(ws_->discs_.back(), dJzdx);
234+
ws_->discs_.pop_back();
235+
}
236+
233237
// reinitialize state
234238
solver_->reInitB(ws_->which, t_, ws_->xB_, ws_->dxB_);
235239
solver_->quadReInitB(ws_->which, ws_->xQB_);

src/forwardproblem.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,6 @@ void EventHandlingSimulator::handle_event(
304304
store_event(edata);
305305

306306
store_pre_event_state(seflag, initial_event);
307-
308-
if (!initial_event) {
309-
model_->updateHeaviside(ws_->roots_found);
310-
}
311307
};
312308

313309
// store post-event information that is to be saved
@@ -325,6 +321,10 @@ void EventHandlingSimulator::handle_event(
325321

326322
store_pre_event_info(false);
327323

324+
if (!initial_event) {
325+
model_->updateHeaviside(ws_->roots_found);
326+
}
327+
328328
// Collect all triggered events waiting for execution
329329
for (int ie = 0; ie < model_->ne; ie++) {
330330
// only consider transitions false -> true
@@ -379,7 +379,12 @@ void EventHandlingSimulator::handle_event(
379379
// and add it to the list of pending events if necessary
380380
if (detect_secondary_events()) {
381381
store_post_event_info();
382+
382383
store_pre_event_info(true);
384+
385+
if (!initial_event) {
386+
model_->updateHeaviside(ws_->roots_found);
387+
}
383388
}
384389
}
385390
store_post_event_info();
@@ -474,6 +479,9 @@ void EventHandlingSimulator::store_pre_event_state(
474479
}
475480
} else if (solver_->computingASA()) {
476481
result.discs.back().xdot_pre = ws_->xdot_old;
482+
result.discs.back().x_pre = ws_->x_old;
483+
result.discs.back().h_pre = model_->getModelState().h;
484+
result.discs.back().total_cl_pre = model_->getModelState().total_cl;
477485
}
478486
}
479487

src/model.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,12 +1559,6 @@ void Model::updateHeaviside(std::vector<int> const& rootsfound) {
15591559
}
15601560
}
15611561

1562-
void Model::updateHeavisideB(int const* rootsfound) {
1563-
for (int ie = 0; ie < ne; ie++) {
1564-
state_.h.at(ie) -= rootsfound[ie];
1565-
}
1566-
}
1567-
15681562
int Model::checkFinite(
15691563
gsl::span<realtype const> array, ModelQuantity model_quantity, realtype t
15701564
) const {

0 commit comments

Comments
 (0)