Skip to content

feat(fmi) Expose the cell saturated fraction to the other models#2764

Draft
Manangka wants to merge 2 commits into
MODFLOW-ORG:developfrom
Manangka:forward_saturation
Draft

feat(fmi) Expose the cell saturated fraction to the other models#2764
Manangka wants to merge 2 commits into
MODFLOW-ORG:developfrom
Manangka:forward_saturation

Conversation

@Manangka
Copy link
Copy Markdown
Contributor

In the Transport and Energy models the saturation, $S_w$, is required in the mst and est packages.
However these values aren't exposed through the FMI.
Instead they are computed using the gwfstrgss and gwfstrgsy rates.

mst:
$f_{storage} = \frac{ \partial \left(S_w \theta C\right)}{\partial t}$

There are several reasons to switch to using the saturation directly:

  • The code becomes clearer. We can now recognize the equation as is stated in the documentation
  • The computation from rate to cell saturation works fine for confined cases, but when we are working with unconfined cases their is an additional requirement that needs to be fulfilled i.e. Sy = theta
  • My main motive for this change is In preparation of the higher order time integration. For that i need to store saturation for multiple older timesteps (or compute it using gwfstrgss and gwfstrgsy but that means that i have to store those for multiple time steps). This change makes it possible to do.

Note
After this change we can almost entirely get rid of gwfstrgss and gwfstrgsy in the FMI. It only being used in 1 place in the prt-fmi file.

Checklist of items for pull request

  • Replaced section above with description of pull request
  • Closed issue #xxxx
  • Referenced issue or pull request #xxxx
  • Added new test or modified an existing test
  • Ran ruff on new and modified python scripts in .doc, autotests, doc, distribution, pymake, and utils subdirectories.
  • Formatted new and modified Fortran source files with fprettify
  • Added doxygen comments to new and modified procedures
  • Updated meson files, makefiles, and Visual Studio project files for new source files
  • Updated definition files
  • Updated develop.toml with a plain-language description of the bug fix, change, feature; required for changes that may affect users
  • Updated input and output guide
  • Removed checklist items not relevant to this pull request

For additional information see instructions for contributing and instructions for developing.

@Manangka Manangka requested a review from mjr-deltares April 14, 2026 15:20
@Manangka Manangka marked this pull request as ready for review April 14, 2026 15:20
Copy link
Copy Markdown
Contributor

@mjr-deltares mjr-deltares left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks clean, generally OK I'd say, but those 2 comments below need some follow up.

nr = this%dis%get_nodenumber(nu, 0)
if (nr <= 0) cycle
this%gwfsat(nr) = this%bfr%auxvar(1, i)
this%gwfsat_old(nr) = this%bfr%auxvar(1, i)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to do it this way, you also have to write sat_old to the budget file, see the sav_sat subroutine in gwf-npf.f90. But technically, sat_old is already in the file though...

this%fmi%memoryPath)
call mem_allocate(this%fmi%gwfsat, this%neq, 'GWFSAT', &
this%fmi%memoryPath)
call mem_allocate(this%fmi%gwfsat_old, this%neq, 'GWFSAT_OLD', &
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the data also has to be copied in to the interface model. This is done in GwtGwtConnection.f90, for example, for gwfsat you see there:

call this%cfg_dv('GWFSAT', 'FMI', SYNC_NDS, (/STG_BFR_EXG_AD/))

which copies gwfsat at the stage STG_BFR_EXG_AD.

And, for parallel, this data might not be there. So we also have to add it to the MPI sync. It should be simple, just follow the whereabouts of this variable in VirtualGwtModel:

type(VirtualDbl1dType), pointer :: fmi_gwfsat => null()

and the same for VirtualGweModel. That, and adding a parallel test of course, should get you there.

Copy link
Copy Markdown
Contributor

@christianlangevin christianlangevin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this approach is set up to handle changes in compressible storage. Of course, this is often quite small if reasonable values are used for specific storage. Also, as I'm sure you know, a similar approach is used for the advanced transport packages.

if (this%fmi%igwfstrgsy /= 0) vold = vold + this%fmi%gwfstrgsy(n) * delt
vsolid = vcell * (DONE - this%porosity(n))

vnew = vcell * this%fmi%gwfsat(n) * this%porosity(n)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this recalculation of vnew and vold does it give the same results as the calculations that you replaced? The previous equations calculate based on compressible and pore volume changes. I feel like this new approach does not account for changes in compressible water volume. For a confined aquifer, it looks like vnew and vold will always be the same.

@Manangka Manangka marked this pull request as draft April 20, 2026 14:55
@Manangka
Copy link
Copy Markdown
Contributor Author

@christianlangevin @mjr-deltares I'm putting this PR on a hold for now till our meeting next week

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants