postprocessing.py:29:
dfs = flopy.utils.Mf6ListBudget(lst_path, budgetkey=budgetkey).get_dataframes()
disc = float(dfs[0]["PERCENT_DISCREPANCY"].abs().max())
get_dataframes() returns a two-tuple: dfs[0] is the incremental budget (rates for each time step) and dfs[1] is the cumulative budget. Only the incremental one is ever examined.
For the steady-state single-step case the two coincide, so today's 09pwnmodel2 run is checked correctly. For a transient run they do not: a model whose per-step discrepancies each sit just under the threshold can still accumulate a cumulative discrepancy well over it, and check_budget_discrepancy reports success. That is precisely the failure mode a budget check exists to catch, and the transport model is transient.
Suggested fix: take the max over both frames, or check them against separate thresholds and name which one tripped.
Found while writing the test suite. The accompanying test drives the real flopy parser over a real listing, so it will exercise whichever frames the fix reads.
postprocessing.py:29:get_dataframes()returns a two-tuple:dfs[0]is the incremental budget (rates for each time step) anddfs[1]is the cumulative budget. Only the incremental one is ever examined.For the steady-state single-step case the two coincide, so today's 09pwnmodel2 run is checked correctly. For a transient run they do not: a model whose per-step discrepancies each sit just under the threshold can still accumulate a cumulative discrepancy well over it, and
check_budget_discrepancyreports success. That is precisely the failure mode a budget check exists to catch, and the transport model is transient.Suggested fix: take the max over both frames, or check them against separate thresholds and name which one tripped.
Found while writing the test suite. The accompanying test drives the real flopy parser over a real listing, so it will exercise whichever frames the fix reads.