You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi,
I had a situation where the forward and adjoint run finished, but my disk ran out of space before it finished writing the output for the adjoint. Just wanted to see if there is a way to just run the adjoint if the forward run is already complete? It would be great to reuse the forward run to rerun the adjoint with different solver settings or in cases like this with storage constraints.
Also, FYI here is my workaround for splitting storage across disks. Long story short it involves changing some code in the pm.py file.
Description:
When providing a full path to hdf5_name in Mf6Adj.solve_gwf(), the adjoint run fails due to incorrect construction of the adjoint HDF5 filename.
Reproduction:
Run MF6-Adj with a forward HDF5 written to a different filesystem (e.g., Windows mount in WSL):
Error:
FileNotFoundError: [Errno 2] Unable to synchronously create file
unable to open file:
name = '/mnt/c/mf6adj_storage/adjoint_solution_phi_heads_/mnt/c/mf6adj_storage/forward.hdf5'
Root Cause:
The adjoint filename is constructed by concatenating strings using the full forward HDF5 path. For example:
This is not a valid file path and causes h5py to fail.
Expected Behavior:
hdf5_name should accept either:
a filename (current behavior), or
a full path (expected behavior)
The adjoint filename should be constructed safely, e.g.:
import os
base = os.path.basename(hdf5_name)
adjoint_fname = f"adjoint_solution_{pm_name}_{base}"
Ideally, the user should be able to control the adjoint output path independently of the forward file.
Impact
This prevents workflows where:
The forward solution is written to one disk (e.g., fast or large storage)
The adjoint solution is written to another disk
This is important for large models where:
forward HDF5 files can be large
disk usage must be split across volumes (e.g., C: vs WSL filesystem)
Current workaround:
Manually modifying mf6adj source code
Suggested Fix:
Add an optional argument to control adjoint output path, e.g.:
def solve_adjoint(..., hdf5_adjoint_solution_fname=None):
and pass this through to PerformanceMeasure.solve_adjoint()
This would allow:
forward written to one location
adjoint written to a different location
Environment:
WSL2 (Ubuntu 22.04)
Forward written to /mnt/c/...
Adjoint run from Linux filesystem (/home/...)
Summary:
mf6adj currently assumes hdf5_name is a simple filename and does not handle full paths safely. This breaks adjoint runs and prevents multi-disk workflows for large models.
Below is a diff to mimic the fix i am using. So far it seems to be working.
diff --git a/mf6adj/pm.py b/mf6adj/pm.py
index XXXXXXX..YYYYYYY 100644
--- a/mf6adj/pm.py+++ b/mf6adj/pm.py@@ -XXX,12 +XXX,24 @@ def solve_adjoint(
- if hdf5_adjoint_solution_fname is None:- pth = os.path.split(hdf5_forward_solution_fname)[0]- hdf5_adjoint_solution_fname = os.path.join(- pth,- f"adjoint_solution_{self._name}_" + hdf5_forward_solution_fname,- )+ if hdf5_adjoint_solution_fname is None:+ # FIX: avoid embedding full forward path in filename+ # use only the basename of the forward HDF5 file+ fwd_base = os.path.basename(hdf5_forward_solution_fname)++ # Option 1 (minimal fix): write adjoint next to forward file+ fwd_dir = os.path.dirname(hdf5_forward_solution_fname)+ hdf5_adjoint_solution_fname = os.path.join(+ fwd_dir,+ f"adjoint_solution_{self._name}_{fwd_base}",+ )++ # Option 2 (alternative behavior):+ # write adjoint to current working directory instead+ # hdf5_adjoint_solution_fname = os.path.join(+ # os.getcwd(),+ # f"adjoint_solution_{self._name}_{fwd_base}",+ # )
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Hi,
I had a situation where the forward and adjoint run finished, but my disk ran out of space before it finished writing the output for the adjoint. Just wanted to see if there is a way to just run the adjoint if the forward run is already complete? It would be great to reuse the forward run to rerun the adjoint with different solver settings or in cases like this with storage constraints.
Also, FYI here is my workaround for splitting storage across disks. Long story short it involves changing some code in the pm.py file.
Description:
When providing a full path to hdf5_name in Mf6Adj.solve_gwf(), the adjoint run fails due to incorrect construction of the adjoint HDF5 filename.
Reproduction:
Run MF6-Adj with a forward HDF5 written to a different filesystem (e.g., Windows mount in WSL):
adj.solve_gwf(
hdf5_name="/mnt/c/mf6adj_storage/forward.hdf5",
verbose=False
)
Then run:
adj.solve_adjoint()
Error:
FileNotFoundError: [Errno 2] Unable to synchronously create file
unable to open file:
name = '/mnt/c/mf6adj_storage/adjoint_solution_phi_heads_/mnt/c/mf6adj_storage/forward.hdf5'
Root Cause:
The adjoint filename is constructed by concatenating strings using the full forward HDF5 path. For example:
adjoint_fname = "adjoint_solution_" + pm_name + "_" + hdf5_name
When hdf5_name is a full path, this produces an invalid path such as:
adjoint_solution_phi_heads_/mnt/c/mf6adj_storage/forward.hdf5
This is not a valid file path and causes h5py to fail.
Expected Behavior:
hdf5_name should accept either:
The adjoint filename should be constructed safely, e.g.:
import os
base = os.path.basename(hdf5_name)
adjoint_fname = f"adjoint_solution_{pm_name}_{base}"
Impact
This prevents workflows where:
This is important for large models where:
Current workaround:
Suggested Fix:
def solve_adjoint(..., hdf5_adjoint_solution_fname=None):
and pass this through to PerformanceMeasure.solve_adjoint()
This would allow:
Environment:
Summary:
mf6adj currently assumes hdf5_name is a simple filename and does not handle full paths safely. This breaks adjoint runs and prevents multi-disk workflows for large models.
Below is a diff to mimic the fix i am using. So far it seems to be working.
Beta Was this translation helpful? Give feedback.
All reactions