Пример #1
0
def ext_theis_tpl_3d(
    time,
    rad,
    storage,
    cond_gmean,
    len_scale,
    hurst,
    var=None,
    c=1.0,
    anis=1,
    lat_ext=1.0,
    rate=-1e-4,
    r_well=0.0,
    r_bound=np.inf,
    h_bound=0.0,
    K_well="KH",
    prop=1.6,
    far_err=0.01,
    struc_grid=True,
    parts=30,
    lap_kwargs=None,
):
    """
    The extended Theis solution for truncated power-law fields in 3D.

    The extended Theis solution for transient flow under
    a pumping condition in a confined aquifer with anisotropy in 3D.
    The type curve is describing the effective drawdown
    in a 3-dimensional statistical framework,
    where the conductivity distribution is
    following a log-normal distribution with a truncated power-law
    correlation function build on superposition of gaussian modes.

    Parameters
    ----------
    time : :class:`numpy.ndarray`
        Array with all time-points where the function should be evaluated
    rad : :class:`numpy.ndarray`
        Array with all radii where the function should be evaluated
    storage : :class:`float`
        Storage of the aquifer.
    cond_gmean : :class:`float`
        Geometric-mean conductivity.
    len_scale : :class:`float`
        Corralation-length of log-conductivity.
    hurst: :class:`float`
        Hurst coefficient of the TPL model. Should be in (0, 1).
    var : :class:`float`
        Variance of the log-conductivity.
        If var is given, c will be calculated accordingly.
        Default: :any:`None`
    c : :class:`float`, optional
        Intensity of variation in the TPL model.
        Is overwritten if var is given.
        Default: ``1.0``
    anis : :class:`float`, optional
        Anisotropy-ratio of the vertical and horizontal corralation-lengths.
        Default: 1.0
    lat_ext : :class:`float`, optional
        Lateral extend of the aquifer (thickness).
        Default: ``1.0``
    rate : :class:`float`, optional
        Pumpingrate at the well. Default: -1e-4
    r_well : :class:`float`, optional
        Radius of the pumping-well. Default: ``0.0``
    r_bound : :class:`float`, optional
        Radius of the outer boundary of the aquifer. Default: ``np.inf``
    h_bound : :class:`float`, optional
        Reference head at the outer boundary as well as initial condition.
        Default: ``0.0``
    K_well : :class:`float`, optional
        Explicit conductivity value at the well. One can choose between the
        harmonic mean (``"KH"``), the arithmetic mean (``"KA"``) or an
        arbitrary float value. Default: ``"KH"``
    prop: :class:`float`, optional
        Proportionality factor used within the upscaling procedure.
        Default: ``1.6``
    far_err : :class:`float`, optional
        Relative error for the farfield transmissivity for calculating the
        cutoff-point of the solution. Default: ``0.01``
    struc_grid : :class:`bool`, optional
        If this is set to ``False``, the `rad` and `time` array will be merged
        and interpreted as single, r-t points. In this case they need to have
        the same shapes. Otherwise a structured r-t grid is created.
        Default: ``True``
    parts : :class:`int`, optional
        Since the solution is calculated by setting the transmissivity to local
        constant values, one needs to specify the number of partitions of the
        transmissivity. Default: ``30``
    lap_kwargs : :class:`dict` or :any:`None` optional
        Dictionary for :any:`get_lap_inv` containing `method` and
        `method_dict`. The default is equivalent to
        ``lap_kwargs = {"method": "stehfest", "method_dict": None}``.
        Default: :any:`None`

    Returns
    -------
    head : :class:`numpy.ndarray`
        Array with all heads at the given radii and time-points.

    Notes
    -----
    If you want to use cartesian coordiantes, just use the formula
    ``r = sqrt(x**2 + y**2)``
    """
    # check the input
    if r_well < 0.0:
        raise ValueError("The wellradius needs to be >= 0")
    if not r_bound > r_well:
        raise ValueError("The upper boundary needs to be > well radius")
    if not storage > 0.0:
        raise ValueError("The storage needs to be positive.")
    if not cond_gmean > 0.0:
        raise ValueError("The gmean conductivity needs to be positive.")
    if not len_scale > 0.0:
        raise ValueError("The correlationlength needs to be positive.")
    if not 0 < hurst < 1:
        raise ValueError("Hurst coefficient needs to be in (0,1)")
    if var is not None and var < 0.0:
        raise ValueError("The variance needs to be positive.")
    if var is None and not c > 0.0:
        raise ValueError("The intensity of variation needs to be positive.")
    if K_well != "KA" and K_well != "KH" and not isinstance(K_well, float):
        raise ValueError(
            "The well-conductivity should be given as float or 'KA' resp 'KH'")
    if isinstance(K_well, float) and not K_well > 0.0:
        raise ValueError("The well-conductivity needs to be positive.")
    if not prop > 0.0:
        raise ValueError("The proportionality factor needs to be positive.")
    if parts <= 1:
        raise ValueError("The numbor of partitions needs to be at least 2")
    if not 0.0 < far_err < 1.0:
        raise ValueError(
            "The relative error of Conductivity needs to be within (0,1)")
    # genearte rlast from a given relativ-error to farfield-conductivity
    r_last = TPL_CG_error(far_err, cond_gmean, len_scale, hurst, var, c, anis,
                          3, K_well, prop)
    # generate the partition points
    if r_last > r_well:
        R_part = specialrange_cut(r_well, r_bound, parts + 1, r_last)
    else:
        R_part = np.array([r_well, r_bound])
    # calculate the harmonic mean conductivity values within each partition
    K_part = annular_hmean(
        TPL_CG,
        R_part,
        ann_dim=2,
        cond_gmean=cond_gmean,
        len_scale=len_scale,
        hurst=hurst,
        var=var,
        c=c,
        anis=anis,
        dim=3,
        K_well=K_well,
        prop=prop,
    )
    K_well = TPL_CG(r_well, cond_gmean, len_scale, hurst, var, c, anis, 3,
                    K_well, prop)
    return ext_grf(
        time=time,
        rad=rad,
        S_part=np.full_like(K_part, storage),
        K_part=K_part,
        R_part=R_part,
        dim=2,
        lat_ext=lat_ext,
        rate=rate,
        h_bound=h_bound,
        K_well=K_well,
        struc_grid=struc_grid,
        lap_kwargs=lap_kwargs,
    )
Пример #2
0
def ext_theis_2d(
    time,
    rad,
    storage,
    trans_gmean,
    var,
    len_scale,
    rate=-1e-4,
    r_well=0.0,
    r_bound=np.inf,
    h_bound=0.0,
    T_well=None,
    prop=1.6,
    struc_grid=True,
    far_err=0.01,
    parts=30,
    lap_kwargs=None,
):
    """
    The extended Theis solution in 2D.

    The extended Theis solution for transient flow under
    a pumping condition in a confined aquifer.
    The type curve is describing the effective drawdown
    in a 2D statistical framework, where the transmissivity distribution is
    following a log-normal distribution with a gaussian correlation function.

    Parameters
    ----------
    time : :class:`numpy.ndarray`
        Array with all time-points where the function should be evaluated
    rad : :class:`numpy.ndarray`
        Array with all radii where the function should be evaluated
    storage : :class:`float`
        Storage of the aquifer.
    trans_gmean : :class:`float`
        Geometric-mean transmissivity.
    var : :class:`float`
        Variance of log-transmissivity.
    len_scale : :class:`float`
        Correlation-length of log-transmissivity.
    rate : :class:`float`, optional
        Pumpingrate at the well. Default: -1e-4
    r_well : :class:`float`, optional
        Radius of the pumping-well. Default: ``0.0``
    r_bound : :class:`float`, optional
        Radius of the outer boundary of the aquifer. Default: ``np.inf``
    h_bound : :class:`float`, optional
        Reference head at the outer boundary as well as initial condition.
        Default: ``0.0``
    T_well : :class:`float`, optional
        Explicit transmissivity value at the well. Harmonic mean by default.
    prop: :class:`float`, optional
        Proportionality factor used within the upscaling procedure.
        Default: ``1.6``
    far_err : :class:`float`, optional
        Relative error for the farfield transmissivity for calculating the
        cutoff-point of the solution. Default: ``0.01``
    struc_grid : :class:`bool`, optional
        If this is set to ``False``, the `rad` and `time` array will be merged
        and interpreted as single, r-t points. In this case they need to have
        the same shapes. Otherwise a structured r-t grid is created.
        Default: ``True``
    parts : :class:`int`, optional
        Since the solution is calculated by setting the transmissivity to local
        constant values, one needs to specify the number of partitions of the
        transmissivity. Default: ``30``
    lap_kwargs : :class:`dict` or :any:`None` optional
        Dictionary for :any:`get_lap_inv` containing `method` and
        `method_dict`. The default is equivalent to
        ``lap_kwargs = {"method": "stehfest", "method_dict": None}``.
        Default: :any:`None`

    Returns
    -------
    head : :class:`numpy.ndarray`
        Array with all heads at the given radii and time-points.

    Notes
    -----
    If you want to use cartesian coordiantes, just use the formula
    ``r = sqrt(x**2 + y**2)``

    Examples
    --------
    >>> ext_theis_2d([10,100], [1,2,3], 0.001, 0.001, 1, 10, -0.001)
    array([[-0.33737576, -0.17400123, -0.09489812],
           [-0.58443489, -0.40847176, -0.31095166]])
    """
    lap_kwargs = {} if lap_kwargs is None else lap_kwargs
    # check the input
    if r_well < 0.0:
        raise ValueError("The wellradius needs to be >= 0")
    if not r_bound > r_well:
        raise ValueError("The upper boundary needs to be > well radius")
    if not storage > 0.0:
        raise ValueError("The Storage needs to be positive.")
    if not trans_gmean > 0.0:
        raise ValueError("The Transmissivity needs to be positive.")
    if var < 0.0:
        raise ValueError("The variance needs to be positive.")
    if not len_scale > 0.0:
        raise ValueError("The correlationlength needs to be positive.")
    if T_well is not None and not T_well > 0.0:
        raise ValueError("The well Transmissivity needs to be positive.")
    if not prop > 0.0:
        raise ValueError("The proportionality factor needs to be positive.")
    if parts <= 1:
        raise ValueError("The numbor of partitions needs to be at least 2")
    if not 0.0 < far_err < 1.0:
        raise ValueError(
            "The relative error of Transmissivity needs to be within (0,1)")
    # genearte rlast from a given relativ-error to farfield-transmissivity
    r_last = T_CG_error(far_err, trans_gmean, var, len_scale, T_well, prop)
    # generate the partition points
    if r_last > r_well:
        R_part = specialrange_cut(r_well, r_bound, parts + 1, r_last)
    else:
        R_part = np.array([r_well, r_bound])
    # calculate the harmonic mean transmissivity values within each partition
    T_part = annular_hmean(
        T_CG,
        R_part,
        trans_gmean=trans_gmean,
        var=var,
        len_scale=len_scale,
        T_well=T_well,
        prop=prop,
    )
    T_well = T_CG(r_well, trans_gmean, var, len_scale, T_well, prop)
    return ext_grf(
        time=time,
        rad=rad,
        S_part=np.full_like(T_part, storage),
        K_part=T_part,
        R_part=R_part,
        dim=2,
        lat_ext=1,
        rate=rate,
        h_bound=h_bound,
        K_well=T_well,
        struc_grid=struc_grid,
        lap_kwargs=lap_kwargs,
    )
Пример #3
0
def theis(
    time,
    rad,
    storage,
    transmissivity,
    rate=-1e-4,
    r_well=0.0,
    r_bound=np.inf,
    h_bound=0.0,
    struc_grid=True,
    lap_kwargs=None,
):
    """
    The Theis solution.

    The Theis solution for transient flow under a pumping condition
    in a confined and homogeneous aquifer.
    This solution was presented in [Theis35]_.

    Parameters
    ----------
    time : :class:`numpy.ndarray`
        Array with all time-points where the function should be evaluated
    rad : :class:`numpy.ndarray`
        Array with all radii where the function should be evaluated
    storage : :class:`float`
        Storage coefficient of the aquifer.
    conductivity : :class:`float`
        Conductivity of the aquifer.
    rate : :class:`float`, optional
        Pumpingrate at the well. Default: -1e-4
    r_well : :class:`float`, optional
        Inner radius of the pumping-well. Default: ``0.0``
    r_bound : :class:`float`, optional
        Radius of the outer boundariy of the aquifer. Default: ``np.inf``
    h_bound : :class:`float`, optional
        Reference head at the outer boundary, as well as initial condition.
        Default: ``0.0``
    struc_grid : :class:`bool`, optional
        If this is set to ``False``, the `rad` and `time` array will be merged
        and interpreted as single, r-t points. In this case they need to have
        the same shapes. Otherwise a structured r-t grid is created.
        Default: ``True``
    lap_kwargs : :class:`dict` or :any:`None` optional
        Dictionary for :any:`get_lap_inv` containing `method` and
        `method_dict`. The default is equivalent to
        ``lap_kwargs = {"method": "stehfest", "method_dict": None}``.
        Default: :any:`None`

    Returns
    -------
    head : :class:`numpy.ndarray`
        Array with all heads at the given radii and time-points.

    References
    ----------
    .. [Theis35] Theis, C.,
       ''The relation between the lowering of the piezometric surface and the
       rate and duration of discharge of a well using groundwater storage'',
       Trans. Am. Geophys. Union, 16, 519-524, 1935
    """
    if np.isclose(r_well, 0) and np.isposinf(r_bound) and lap_kwargs is None:
        return well_solution(time, rad, storage, transmissivity, rate)
    return ext_grf(
        time=time,
        rad=rad,
        S_part=[storage],
        K_part=[transmissivity],
        R_part=[r_well, r_bound],
        dim=2,
        lat_ext=1,
        rate=rate,
        K_well=None,
        h_bound=h_bound,
        lap_kwargs=lap_kwargs,
        struc_grid=struc_grid,
    )
Пример #4
0
def neuman2004(
    time,
    rad,
    storage,
    trans_gmean,
    var,
    len_scale,
    rate=-1e-4,
    r_well=0.0,
    r_bound=np.inf,
    h_bound=0.0,
    struc_grid=True,
    parts=30,
    lap_kwargs=None,
):
    """
    The transient solution for the apparent transmissivity from [Neuman2004].

    This solution is build on the apparent transmissivity from Neuman 2004,
    which represents a mean drawdown in an ensemble of pumping tests in
    heterogeneous transmissivity fields following an exponential covariance.

    Parameters
    ----------
    time : :class:`numpy.ndarray`
        Array with all time-points where the function should be evaluated.
    rad : :class:`numpy.ndarray`
        Array with all radii where the function should be evaluated.
    storage : :class:`float`
        Storage of the aquifer.
    trans_gmean : :class:`float`
        Geometric-mean transmissivity.
    var : :class:`float`
        Variance of log-transmissivity.
    len_scale : :class:`float`
        Correlation-length of log-transmissivity.
    rate : :class:`float`, optional
        Pumpingrate at the well. Default: -1e-4
    r_well : :class:`float`, optional
        Radius of the pumping-well. Default: ``0.0``
    r_bound : :class:`float`, optional
        Radius of the outer boundary of the aquifer. Default: ``np.inf``
    h_bound : :class:`float`, optional
        Reference head at the outer boundary as well as initial condition.
        Default: ``0.0``
    struc_grid : :class:`bool`, optional
        If this is set to ``False``, the `rad` and `time` array will be merged
        and interpreted as single, r-t points. In this case they need to have
        the same shapes. Otherwise a structured r-t grid is created.
        Default: ``True``
    parts : :class:`int`, optional
        Since the solution is calculated by setting the transmissivity to local
        constant values, one needs to specify the number of partitions of the
        transmissivity. Default: ``30``
    lap_kwargs : :class:`dict` or :any:`None` optional
        Dictionary for :any:`get_lap_inv` containing `method` and
        `method_dict`. The default is equivalent to
        ``lap_kwargs = {"method": "stehfest", "method_dict": None}``.
        Default: :any:`None`

    Returns
    -------
    head : :class:`numpy.ndarray`
        Array with all heads at the given radii and time-points.

    References
    ----------
    .. [Neuman2004] Neuman, Shlomo P., Alberto Guadagnini, and Monica Riva.
       ''Type-curve estimation of statistical heterogeneity.''
       Water resources research 40.4, 2004
    """
    # check the input
    if r_well < 0.0:
        raise ValueError("The wellradius needs to be >= 0")
    if not r_bound > r_well:
        raise ValueError("The upper boundary needs to be > well radius")
    if not storage > 0.0:
        raise ValueError("The Storage needs to be positive.")
    if not trans_gmean > 0.0:
        raise ValueError("The Transmissivity needs to be positive.")
    if var < 0.0:
        raise ValueError("The variance needs to be positive.")
    if not len_scale > 0.0:
        raise ValueError("The correlationlength needs to be positive.")
    if parts <= 1:
        raise ValueError("The numbor of partitions needs to be at least 2")
    # genearte rlast from a given relativ-error to farfield-transmissivity
    r_last = 2 * len_scale
    # generate the partition points
    if r_last > r_well:
        R_part = specialrange_cut(r_well, r_bound, parts + 1, r_last)
    else:
        R_part = np.array([r_well, r_bound])
    # calculate the harmonic mean transmissivity values within each partition
    T_part = annular_hmean(
        neuman2004_trans,
        R_part,
        trans_gmean=trans_gmean,
        var=var,
        len_scale=len_scale,
    )
    T_well = neuman2004_trans(r_well, trans_gmean, var, len_scale)
    return ext_grf(
        time=time,
        rad=rad,
        S_part=np.full_like(T_part, storage),
        K_part=T_part,
        R_part=R_part,
        dim=2,
        lat_ext=1,
        rate=rate,
        h_bound=h_bound,
        K_well=T_well,
        struc_grid=struc_grid,
        lap_kwargs=lap_kwargs,
    )
Пример #5
0
def grf(
    time,
    rad,
    storage,
    conductivity,
    dim=2,
    lat_ext=1.0,
    rate=-1e-4,
    r_well=0.0,
    r_bound=np.inf,
    h_bound=0.0,
    struc_grid=True,
    lap_kwargs=None,
):
    """
    The general radial flow (GRF) model for a pumping test.

    This solution was  presented in [Barker88]_.

    Parameters
    ----------
    time : :class:`numpy.ndarray`
        Array with all time-points where the function should be evaluated.
    rad : :class:`numpy.ndarray`
        Array with all radii where the function should be evaluated.
    storage : :class:`float`
        Storage coefficient of the aquifer.
    conductivity : :class:`float`
        Conductivity of the aquifer.
    dim : :class:`float`, optional
        Fractional dimension of the aquifer. Default: ``2.0``
    lat_ext : :class:`float`, optional
        Lateral extend of the aquifer. Default: ``1.0``
    rate : :class:`float`, optional
        Pumpingrate at the well. Default: -1e-4
    r_well : :class:`float`, optional
        Inner radius of the pumping-well. Default: ``0.0``
    r_bound : :class:`float`, optional
        Radius of the outer boundary of the aquifer. Default: ``np.inf``
    h_bound : :class:`float`, optional
        Reference head at the outer boundary, as well as initial condition.
        Default: ``0.0``
    struc_grid : :class:`bool`, optional
        If this is set to "False", the "rad" and "time" array will be merged
        and interpreted as single, r-t points. In this case they need to have
        the same shapes. Otherwise a structured r-t grid is created.
        Default: ``True``
    lap_kwargs : :class:`dict` or :any:`None` optional
        Dictionary for :any:`get_lap_inv` containing `method` and
        `method_dict`. The default is equivalent to
        ``lap_kwargs = {"method": "stehfest", "method_dict": None}``.
        Default: :any:`None`

    Returns
    -------
    head : :class:`numpy.ndarray`
        Array with all heads at the given radii and time-points.

    References
    ----------
    .. [Barker88] Barker, J.
       ''A generalized radial flow model for hydraulic tests
       in fractured rock.'',
       Water Resources Research 24.10, 1796-1804, 1988
    """
    if np.isclose(r_well, 0) and np.isposinf(r_bound) and lap_kwargs is None:
        return grf_solution(
            time=time,
            rad=rad,
            storage=storage,
            conductivity=conductivity,
            dim=dim,
            lat_ext=lat_ext,
            rate=rate,
            h_bound=h_bound,
            struc_grid=struc_grid,
        )
    return ext_grf(
        time=time,
        rad=rad,
        S_part=[storage],
        K_part=[conductivity],
        R_part=[r_well, r_bound],
        dim=dim,
        lat_ext=lat_ext,
        rate=rate,
        K_well=None,
        h_bound=h_bound,
        struc_grid=struc_grid,
        lap_kwargs=lap_kwargs,
    )