Skip to content

Conversation

@Huite
Copy link
Contributor

@Huite Huite commented Jul 11, 2024

This would allow us to do fancy downscaling, basically getting rid of respighi: instead of MODFLOW, we can directly call this function.

@Huite Huite requested a review from JoerivanEngelen July 11, 2024 14:16
@Huite Huite marked this pull request as draft July 11, 2024 14:16
@Huite Huite requested review from JoerivanEngelen and removed request for JoerivanEngelen July 11, 2024 14:19
@JoerivanEngelen
Copy link
Contributor

Some screenshots for context: The poisson interpolation allows interpolating ditches with recharge.

This would looks something like this for ditches:
image
Where purple line is the ditch level (boundary condition), blue line is the laplacian interpolation, and red line the poisson interpolation. This is an example for negative recharge AFAIK (was still work in progress and the sign got swapped accidentily, but it was the best screenshot I have to explain the context somewhat).

After fixing the sign errors this turned into:
image

@sonarqubecloud
Copy link

@Huite
Copy link
Contributor Author

Huite commented Jul 15, 2024

After some reflection: the respighi scaling method requires us to use "weak" boundaries as well (e.g. RIV or GHB).

With only hard boundaries, if you downscale at 25.0 m, the value at 25.0 m gets burned into the grid directly. This means that if the ditch distance is <50 m or so, you will only get the boundary conditions (like ditch stages). This would mean that for e.g. the peaty areas of South-Holland, the scaling essentially fails.

It's relatively easy to add a robin boundary (a GHB) as optional arguments for the system of equations.

This allows the interpolated head to deviate somewhat from the provided robin values.

@Manangka Manangka force-pushed the master branch 3 times, most recently from 05ac3f7 to 5694d30 Compare September 17, 2024 15:58
@Huite
Copy link
Contributor Author

Huite commented Mar 3, 2025

Few quick notes:

#1239 removed the pcg module.

However, the same method can be easily applied.
We should add robin_coeficient and robin_value for the robin boundary conditions, as well as neumann_value for the neumann boundary condition.

In terms of the _interpolate function:

def _interpolate(
    arr: np.ndarray,
    connectivity: sparse.csr_matrix,
    direct: bool,
    delta: float,
    relax: float,
    rtol: float,
    atol: float,
    maxiter: int,
    robin_coefficient: FloatArray | None = None,
    robin_value: FloatArray | None = None,
    neumann_value: FloatArray | None = None,
):
    ar1d = arr.ravel()
    unknown = np.isnan(ar1d)
    known = ~unknown

    if robin_coefficient is None:
        robin_coefficient = 0.0
    if robin_value is None:
        robin_value = 0.0
    if neumann_value is None:
        neumann_value = 0.0

    # Set up system of equations.
    matrix = connectivity.copy()
    matrix.setdiag(-matrix.sum(axis=1).A[:, 0] - robin_coefficient
    rhs = -matrix[:, known].dot(ar1d[known]) - (robin_coefficient * robin_value)

We can make it a bit nicer and support multiple boundary conditions in a single cell by allowing an additional dimension for these, either by using np.add.at or by simply looping over the extra dimension.

It would also be good to support non-equidistant and unstructured grids (by taking the centroid-to-centroid distance into account for the coefficient matrix), as xugrid can do. For unstructured grids, it's a simple case of taking the connectivity from the Ugrid2d topology instead of generating it for the cartesian neighbors.

Might be easiest to scrap this PR and start from current master.

@JoerivanEngelen
Copy link
Contributor

Will be followed up upon in #1470

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