fix(cmake): patch selected-output leak in IPhreeqc 3.5.0

Fix memory leak in Phreeqc-coupled reactive transport

Phreeqc-coupled ComponentTransport runs leak memory linearly per timestep, proportional to the number of chemical systems. A production h–c model reported ~7 MB/step and was OOM-killed around timestep 1000 of 1527. The cause is in the vendored IPhreeqc 3.5.0, not in OGS code.

  • Root cause

IPhreeqc::check_database() runs at the top of every RunString() and is meant to empty the per-run selected-output buffers, but both of its map-clearing loops terminate on begin() instead of end(), so neither body ever executes:

for (; mit != SelectedOutputStringMap.begin(); ++mit)
for (; lit != this->SelectedOutputLinesMap.begin(); ++lit)

SelectedOutputStringMap survives because an explicit clear() precedes the loops. SelectedOutputLinesMap has no clear() anywhere in 3.5.0, while update_selected_out() pushes every line of the selected-output table into it on every run — so it grows without bound for the lifetime of the instance. UnLoadDatabase() carries the same typo, so reloading the database does not reclaim it either; only DestroyIPhreeqc does.

It only triggers under SetSelectedOutputStringOn(true), i.e. exactly our stream data exchange (use_stream_for_data_exchange, default true since 6.5.8). OGS reads results via GetSelectedOutputString() and never calls GetSelectedOutputStringLine(), so every accumulated byte is waste. Under MPI each rank leaks independently.

  • Change

One-line backport as a CPM patch, wired in with the same __patch_args pattern already used for metis/gklib/mgis.

  • Follow-up

Upstream IPhreeqc 3.7.6 already replaced both broken loops with a plain clear(), so the proper fix is to move the pin. ufz/iphreeqc only carries 3.5.0-1…3.5.0-3 and all three are affected, so that upgrade needs its own MR and testing. This patch unblocks users now.

Merge request reports

Loading
Loading