Source code for pyrtid.utils.random_field

"""
utility to generate random field in 1, 2 and 3D.

@author: acollet
"""

from typing import Any, Dict, List, Optional, Union

import gstools as gs
import numpy as np

from pyrtid.utils.types import NDArrayFloat

# pylint: disable=C0103  # Do not conform to snake_case naming style
# pylint: disable=R0913  # Too many arguments

# Use the optional dependency GSTools-Core, which is a re-implementation of the main
# algorithms used in GSTools. The new package uses the language Rust and it should be
# faster (in some cases by orders of magnitude), safer, and it will potentially
# completely replace the current standard implementation in Cython.
# gs.config.USE_RUST = True


[docs]def gen_random_ensemble( model: gs.covmodel.CovModel, n_ensemble: int, var: float, len_scale: Union[float, List[float], NDArrayFloat], mean: float, nx: int, ny: int = 1, nz: int = 1, seed: int = 20170519, normalizer: Optional[gs.normalizer.Normalizer] = None, model_kwargs: Optional[Dict[str, Any]] = None, ) -> NDArrayFloat: r""" Generate a (ne, nx, ny, nz) ensemble of 3D random fields. Parameters ---------- model: CovModel Covariance Model class object related to the field. n_ensemble : int Number of members in the ensemble. var : float Variance of the model (the nugget is not included in “this” variance). len_scale : Union[float, List[float], NDArrayFloat] Length scale of the model. If a single value is given, the same length-scale will be used for every direction. If multiple values (for main and transversal directions) are given, anis will be recalculated accordingly. If only two values are given in 3D, the latter one will be used for both transversal directions. mean: float Mean of the field. nx : int x size of the members. ny : int, optional y size of the members (if members are 2D). The default is 1 (if members are 1D). nz : int, optional z size of the members (if members are 3D). The default is 1 (if members are 1D). seed : int, optional Specifying a seed, we make sure to create reproducible results. The default is 20170519. normalizer: Optional[Normalized] Normalizer to be applied to the field. The default is None. model_kwargs: Dict[str, Any] additional parameters for the model. Returns ------- ens : np.ndarray Ensemble members. Dimensions are (ne, nx, ny, nz) """ if model_kwargs is None: model_kwargs = {} # model = gs.Gaussian(dim=3, var=var, len_scale=len_scale) srf = gs.SRF( model(dim=3, var=var, len_scale=len_scale, **model_kwargs), mean=mean, normalizer=normalizer, ) srf.set_pos([range(nx), range(ny), range(nz)], "structured") ens = np.zeros((n_ensemble, nx, ny, nz)) _seed = gs.random.MasterRNG(seed) for i in range(n_ensemble): srf(seed=_seed(), store=f"better_field{i}") for i in range(n_ensemble): ens[i] = srf[i] return ens
[docs]def get_normalized_mean_from_lognormal_params(mean: float, std: float) -> float: r""" Get the mean of the normalized log-normal distribution. Let $X$ be log-normally distributed. Denote $\mu_{X}$ and $\sigma_{X}$ as the mean and standard deviation of $X$. The mean $\mu$ of $\log{X}$ is given by: .. math:: \mu = \ln\left(\frac{\mu_X^2}{\sqrt{\mu_X^2+\sigma_X^2}}\right) See: https://en.wikipedia.org/wiki/Log-normal_distribution#Generation_and_parameters Parameters ---------- mean : float The mean of the log-normal distribution. std : float The standard deviation of the log-normal distribution. Returns ------- float The mean of the normalized distribution. """ return np.log(mean**2 / np.sqrt(mean**2 + std**2))
[docs]def get_log_normalized_mean_from_normal_params(mean: float, std: float) -> float: r""" Get the mean of the log-normalized normal distribution. Let $Z$ be normally distributed. Denote $\mu_{Z}$ and $\sigma_{Z}$ as the mean and standard deviation of $Z$. The mean $\mu$ of $e_{Z}$ is given by: .. math:: \mu = e^{\mu_{Z} + \tfrac{1}{2}\sigma_{Z}^2} See: https://en.wikipedia.org/wiki/Log-normal_distribution#Arithmetic_moments Parameters ---------- mean : float The mean of the normal distribution. std : float The standard deviation of the normal distribution. Returns ------- float The mean of the log-noramlized distribution. """ return float(np.exp(mean + 1 / 2 * std**2))
[docs]def get_normalized_std_from_lognormal_params(mean: float, std: float) -> float: r""" Get the standard deviation of the normalized log-normal distribution. Let $X$ be log-normally distributed. Denote $\mu_{X}$ and $\sigma_{X}$ as the mean and standard deviation of $X$. The standard deviation $\sigma$ of $\log{X}$ is given by: .. math:: \sigma = \sqrt{\ln \left(1+{\frac {\sigma _{X}^{2}}{\mu _{X}^{2}}}\right)} See: https://en.wikipedia.org/wiki/Log-normal_distribution#Generation_and_parameters Parameters ---------- mean : float The mean of the log-normal distribution. std : float The standard deviation of the log-normal distribution. Returns ------- float The standard deviation of the normalized distribution. """ return np.sqrt(np.log(1 + std**2 / mean**2))
[docs]def get_log_normalized_std_from_normal_params(mean: float, std: float) -> float: r""" Get the mean of the log-normalized normal distribution. Let $Z$ be normally distributed. Denote $\mu_{Z}$ and $\sigma_{Z}$ as the mean and standard deviation of $Z$. The standard deviation $\sigma$ of $e_{Z}$ is given by: .. math:: \sigma = e^{\mu + \tfrac{1}{2}\sigma^2}\sqrt{e^{\sigma^2} - 1} See: https://en.wikipedia.org/wiki/Log-normal_distribution#Arithmetic_moments Parameters ---------- mean : float The mean of the normal distribution. std : float The standard deviation of the normal distribution. Returns ------- float The standard deviation of the log-normalized distribution. """ return np.exp(mean + 1 / 2 * std**2) * np.sqrt(np.exp(std**2) - 1)