Model checks

After a short discussion with Martijn, we came up with a general checking "framework":

  • Checks are enforced by the model containing the packages. A model can be initialized with checks={None, "eager", "defer"}. When None, no checks are done whatsoever. When eager, a check is done when attaching a package to a model. The model is checked once more when the model is being written, since the packages are not immutable and may have changed in the mean time. When defer, the model is checked only when writing.
  • Every package contains a pkg_check method. This package check optionally accepts an ibound to check for alignment, whether there are no values set in inactive cells. This ibound might not be available for an eager check, but it will always be for a deferred check.
  • "Global" checks are always initiated by the model, and the packages simply raise Errors.
  • Some conceptual errors can be checked. For example, there may an isolated part of a model. This is not an issue as long as there is a head dependent boundary present in every part (so any incoming water can get out). scikit-image's morphology presents some very useful tools for these analyses. One way of checking the above is by labelling the areas, then going through the active package cells, and assigning "has_flux", "has_head" markers. A check is then a matter of doing a groupby label and making sure the count for has_head is > 1 for every group.

In general however, we can only spot conceptual errors after an initial (steady-state heads) run. We might be able to write a few functions to facilitate analysis of these outputs (e.g. plots of where the velocities are highest, distributions of velocities, etc.).