Skip to content

Commit

Permalink
Fix SUNContext in ModelStateDerived copy ctor (AMICI-dev#2583)
Browse files Browse the repository at this point in the history
When copying SUNDIALS objects, we need to make sure they have a valid `SUNContext` set.
When copying `ModelStateDerived`, the `SUNContext` needs to be updated. Otherwise,
dangling SUNContext pointers likely result in segfaults later on (AMICI-dev#2579).

This was done only for a subset of objects. In particular the ones added only during
AMICI-dev#2505 were missing, because of other changes
happening in parallel.

To make this less messy: Add `set_ctx(.)` functions all our sundials vector/matrix
wrappers.

Closes AMICI-dev#2579.
  • Loading branch information
dweindl authored Nov 10, 2024
1 parent e84a042 commit 5c70794
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 62 deletions.
90 changes: 28 additions & 62 deletions include/amici/model_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,71 +146,37 @@ struct ModelStateDerived {
, dwdw_(other.dwdw_)
, dwdx_hierarchical_(other.dwdx_hierarchical_)
, dJydy_dense_(other.dJydy_dense_) {
// Update the SUNContext of all matrices
if (J_.data()) {
J_.get()->sunctx = sunctx_;
// Update the SUNContext of all SUNDIALS objects
J_.set_ctx(sunctx_);
JB_.set_ctx(sunctx_);
dxdotdw_.set_ctx(sunctx_);
dwdx_.set_ctx(sunctx_);
dwdp_.set_ctx(sunctx_);
M_.set_ctx(sunctx_);
MSparse_.set_ctx(sunctx_);
dfdx_.set_ctx(sunctx_);
dxdotdp_full.set_ctx(sunctx_);
dxdotdp_explicit.set_ctx(sunctx_);
dxdotdp_implicit.set_ctx(sunctx_);
dxdotdx_explicit.set_ctx(sunctx_);
dxdotdx_implicit.set_ctx(sunctx_);
dx_rdatadx_solver.set_ctx(sunctx_);
dx_rdatadtcl.set_ctx(sunctx_);
dtotal_cldx_rdata.set_ctx(sunctx_);
dxdotdp.set_ctx(sunctx_);

for (auto& dJydy : dJydy_) {
dJydy.set_ctx(sunctx_);
}
if (JB_.data()) {
JB_.get()->sunctx = sunctx_;
for (auto& dwdp : dwdp_hierarchical_) {
dwdp.set_ctx(sunctx_);
}
if (dxdotdw_.data()) {
dxdotdw_.get()->sunctx = sunctx_;
}
if (dwdx_.data()) {
dwdx_.get()->sunctx = sunctx_;
}
if (dwdp_.data()) {
dwdp_.get()->sunctx = sunctx_;
}
if (M_.data()) {
M_.get()->sunctx = sunctx_;
}
if (MSparse_.data()) {
MSparse_.get()->sunctx = sunctx_;
}
if (dfdx_.data()) {
dfdx_.get()->sunctx = sunctx_;
}
if (dxdotdp_full.data()) {
dxdotdp_full.get()->sunctx = sunctx_;
}
if (dxdotdp_explicit.data()) {
dxdotdp_explicit.get()->sunctx = sunctx_;
}
if (dxdotdp_implicit.data()) {
dxdotdp_implicit.get()->sunctx = sunctx_;
}
if (dxdotdx_explicit.data()) {
dxdotdx_explicit.get()->sunctx = sunctx_;
}
if (dxdotdx_implicit.data()) {
dxdotdx_implicit.get()->sunctx = sunctx_;
}
if (dx_rdatadx_solver.data()) {
dx_rdatadx_solver.get()->sunctx = sunctx_;
}
if (dx_rdatadtcl.data()) {
dx_rdatadtcl.get()->sunctx = sunctx_;
}
if (dtotal_cldx_rdata.data()) {
dtotal_cldx_rdata.get()->sunctx = sunctx_;
}
for (auto const& dwdp : dwdp_hierarchical_) {
if (dwdp.data()) {
dwdp.get()->sunctx = sunctx_;
}
}
for (auto const& dwdx : dwdx_hierarchical_) {
if (dwdx.data()) {
dwdx.get()->sunctx = sunctx_;
}
}
if (dwdw_.data()) {
dwdw_.get()->sunctx = sunctx_;
}
if (dJydy_dense_.data()) {
dJydy_dense_.get()->sunctx = sunctx_;
for (auto& dwdx : dwdx_hierarchical_) {
dwdx.set_ctx(sunctx_);
}
sspl_.set_ctx(sunctx_);
dwdw_.set_ctx(sunctx_);
dJydy_dense_.set_ctx(sunctx_);
}

/**
Expand Down
13 changes: 13 additions & 0 deletions include/amici/sundials_matrix_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,19 @@ class SUNMatrixWrapper {
*/
SUNContext get_ctx() const;

/**
* @brief Set SUNContext
*
* Update the SUNContext of the wrapped SUNMatrix.
*
* @param ctx SUNDIALS context to set
*/
void set_ctx(SUNContext ctx) {
if (matrix_) {
matrix_->sunctx = ctx;
}
}

private:
/**
* @brief SUNMatrix to which all methods are applied
Expand Down
14 changes: 14 additions & 0 deletions include/amici/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,20 @@ class AmiVectorArray {
*/
void copy(AmiVectorArray const& other);

/**
* @brief Set SUNContext
*
* If any AmiVector is non-empty, this changes the current SUNContext of the
* associated N_Vector. If empty, do nothing.
*
* @param ctx SUNDIALS context to set
*/
void set_ctx(SUNContext ctx) {
for (auto& vec : vec_array_) {
vec.set_ctx(ctx);
}
}

private:
/** main data storage */
std::vector<AmiVector> vec_array_;
Expand Down

0 comments on commit 5c70794

Please sign in to comment.