Fluctuation Field Generation#

DRDMannTurb provides generic methods for generating fluctuation fields from specified spectra models. Please refer to the UML diagram to see the class hierarchy.

class drdmannturb.GenerateFluctuationField(friction_velocity: float, reference_height: float, grid_dimensions: ndarray, grid_levels: ndarray, model: str, length_scale: float | None = None, time_scale: float | None = None, energy_spectrum_scale: float | None = None, path_to_parameters: str | PathLike | None = None, seed: int | None = None, blend_num=10)[source]#

Class for generating a fluctuation field either from a Mann model or a pre-fit DRD model that generates the field spectra.

Turbulent fluctuations can be formally written as a convolution of a covariance kernel with Gaussian noise \(\boldsymbol{\xi}\) in the physical domain:

\[\mathbf{u}=\mathcal{F}^{-1} \mathcal{G} \widehat{\boldsymbol{\xi}}=\mathcal{F}^{-1} \mathcal{G} \mathcal{F} \boldsymbol{\xi},\]

where \(\mathcal{F}\) is the Fourier transform and the operator \(\mathcal{G}\) is the point-wise multiplication by \(G(\boldsymbol{k})\), which is any positive-definite “square-root” of the spectral tensor and satisfies \(G(\boldsymbol{k}) G^*(\boldsymbol{k})=\Phi(\boldsymbol{k})\).

This is determined by which \(\Phi(\boldsymbol{k}, \tau(\boldsymbol{k}))\) is used. The following are provided:

  1. Mann, which utilizes the Mann eddy lifetime function

    \[\tau^{\mathrm{IEC}}(k)=\frac{T B^{-1}(k L)^{-\frac{2}{3}}}{\sqrt{{ }_2 F_1\left(1 / 3,17 / 6 ; 4 / 3 ;-(k L)^{-2}\right)}}\]
and the full spectral tensor can be found in the following reference:
  1. Mann, “The spatial structure of neutral atmospheric surfacelayer turbulence,” Journal of fluid mechanics 273, 141-168 (1994)

  1. DRD model, which utilizes a learned eddy lifetime function and requires a pre-trained DRD model. The eddy lifetime function is given by

    \[\tau(\boldsymbol{k})=\frac{T|\boldsymbol{a}|^{\nu-\frac{2}{3}}}{\left(1+|\boldsymbol{a}|^2\right)^{\nu / 2}}, \quad \boldsymbol{a}=\boldsymbol{a}(\boldsymbol{k})\]
  2. Von Karman model,

    \[\Phi_{i j}^{\mathrm{VK}}(\boldsymbol{k})=\frac{E(k)}{4 \pi k^2}\left(\delta_{i j}-\frac{k_i k_j}{k^2}\right)\]

    which utilizes the energy spectrum function

    \[E(k)=c_0^2 \varepsilon^{2 / 3} k^{-5 / 3}\left(\frac{k L}{\left(1+(k L)^2\right)^{1 / 2}}\right)^{17 / 3},\]

    where \(\varepsilon\) is the viscous dissipation of the turbulent kinetic energy, \(L\) is the length scale parameter and \(c_0^2 \approx 1.7\) is an empirical constant.

Parameters:
  • friction_velocity (float) – The reference wind friction velocity \(u_*\)

  • reference_height (float) – Reference height \(L\)

  • grid_dimensions (np.ndarray) – Numpy array denoting the grid size; the real dimensions of the domain of interest.

  • grid_levels (np.ndarray) – Numpy array denoting the grid levels; number of discretization points used in each dimension, which evaluates as 2^k for each dimension for FFT-based sampling methods.

  • model (str) – One of "DRD", "VK", or "Mann" denoting “Neural Network,” “Von Karman,” and “Mann model”.

  • length_scale (Optional[float]) – The length scale \(L:\), used only if non-DRD model is used. By default, None.

  • time_scale (Optional[float]) – The time scale \(T\), used only if non-DRD model is used. By default, None.

  • energy_spectrum_scale (Optional[float]) – Scaling of energy spectrum, used only if non-DRD model is used. By default, None.

  • path_to_parameters (Union[str, PathLike]) – File path (string or Pathlib.Path())

  • seed (int, optional) – Pseudo-random number generator seed, by default None. See np.random.RandomState.

  • blend_num (int, optional) – Number of grid points in the y-z plane to use as buffer regions between successive blocks of fluctuation; see figures 7 and 8 of the original DRD paper, by default 10. Note that at the boundary of each block, points are often correlated, so if the resulting field has undesirably high correlation, increasing this number may mitigate some of these effects.

Raises:

ValueError – If model doesn’t match one of the 3 available models: DRD, VK and Mann.

evaluate_divergence(spacing: tuple | ndarray, field: ndarray | None = None) ndarray[source]#

Evaluates the point-wise divergence of a generated fluctuation vector (!) field on a given grid. The underlying method is numpy’s gradient function, which is computed with second-order central difference methods.

Note

If the generated field has been normalized with .normalize(), it must be passed into this method as the field argument. The default evaluation of this method is on the total_fluctuation attribute of this object.

This method will approximate

\[\operatorname{div} \boldsymbol{F} = \frac{\partial \boldsymbol{F}_x}{\partial x} + \frac{\partial \boldsymbol{F}_y}{\partial y} + \frac{\partial \boldsymbol{F}_z}{\partial z}.\]

Note that the vector field is assumed to be 3D.

Parameters:
  • spacing (Union[tuple, np.ndarray]) – The spacing of the grid on which the fluctuation field has been generated. This is necessary for derivatives to be computed properly.

  • field (Optional[np.ndarray], optional) – The fluctuation field containing all field components, of the shape \((x, y, z, 3)\), by default None, which evaluates the divergence of the non-normalized field stored in total_fluctuation.

Returns:

np.ndarray – Point-wise divergence of the vector field, this will be of shape (x, y, z). To gather further information about the divergence, consider using .max(), .sum() or .mean() to determine the maximum, total, or average point-wise divergence of the generated field.

Raises:
  • ValueError – Spacing must contain 3 scalars determining the spacing of evaluation points of the field for each dimension.

  • ValueError – Last dimension of vector field must be 3, consider reshaping your vector field.

Return type:

ndarray

generate(num_blocks: int, zref: float, uref: float, z0: float, windprofiletype: str, plexp: float | None = None) ndarray[source]#

Generates the full fluctuation field in blocks. The resulting field is stored as the total_fluctuation field of this object, allowing for all metadata of the object to be stored safely with the fluctuation field, and also reducing data duplication for post-processing; all operations can be performed on this public variable.

Warning

If this method is called twice in the same object, additional fluctuation field blocks will be appended to the field generated from the first call. If this is undesirable behavior, instantiate a new object.

Parameters:
  • num_blocks (int) – Number of blocks to use in fluctuation field generation.

  • zref (float) – Reference height.

  • uref (float) – Reference velocity.

  • z0 (float) – Roughness height.

  • windprofiletype (str) –

    Type of wind profile by which to normalize, either "LOG" for logarithmic scaling or "PL" for power law scaling: for "LOG",

    \[\left\langle U_1(z)\right\rangle=\frac{u_*}{\kappa} \ln \left(\frac{z}{z_0}+1\right)\]

    or for "PL",

    \[\left\langle U_1(z)\right\rangle= u_* \left( \frac{z}{z_{\text{ref}}} \right)^\alpha\]

    where \(u_*\) is the friction velocity and \(z_{\text{ref}}\) is the reference height.

  • plexp (Optional[float], optional) – Power law exponent \(\alpha\), by default None.

Returns:

np.ndarray – The full fluctuation field, which is also stored as the total_fluctuation field.

Return type:

ndarray

save_to_vtk(filepath: str | Path = './')[source]#

Saves generated fluctuation field in VTK format to specified filepath.

Parameters:

filepath (Union[str, Path]) – Filepath to which to save generated fluctuation field.

Plotting Utilities#

drdmannturb.fluctuation_generation.wind_plot.plot_velocity_magnitude(spacing: tuple[float, float, float], wind_field: ndarray, surf_count=75, reshape=True, transparent=False) Figure[source]#

Produces a 3D plot of the wind velocity magnitude in a specified domain. This returns a Plotly figure for use of downstream visualization.

Parameters:
  • spacing (tuple[float, float, float]) – Spacing array that determines the spacing of points to be used in each dimension of the 3D field. Typically, of the form grid_dimensions (a 3x1 vector representing the dimensions of the domain) divided by the grid_levels, which determine the resolution of the wind field in each respective dimension.

  • wind_field (np.ndarray) – 3D wind field, typically of shape (Nx, Ny, Nz, 3) (not C-layout, to be reshaped).

  • surf_count (int, optional) – Number of surfaces to be used, by default 75

  • reshape (bool, optional) – Whether to re-format the given wind field into C-order, typically the desirable choice to match the order of entries of the wind field and the provided spacing, by default True

  • transparent (bool, optional) – Whether to set the background of the plot to a transparent background, which renders the same on different backgrounds on which this Figure could be embedded.

Returns:

go.Figure – Plotly Figure object to be used in visualization.

Return type:

Figure

drdmannturb.fluctuation_generation.wind_plot.plot_velocity_components(spacing: tuple[float, float, float], wind_field: ndarray, surface_count=25, reshape=True) Figure[source]#

Plots x, y, z components of given wind field over provided spacing. Note that the same spacing is used for all 3 velocity components.

Parameters:
  • spacing (tuple[float, float, float]) – Spacing array that determines the spacing of points to be used in each dimension of the 3D field. Typically, of the form grid_dimensions (a 3x1 vector representing the dimensions of the domain) divided by the grid_levels, which determine the resolution of the wind field in each respective dimension.

  • wind_field (np.ndarray) – 3D wind field, typically of shape (Nx, Ny, Nz, 3) (not C-layout, to be reshaped).

  • surface_count (int, optional) – Number of surfaces to be used for each velocity component, by default 25

  • reshape (bool, optional) – Whether to re-format the given wind field into C-order, typically the desirable choice to match the order of entries of the wind field and the provided spacing, by default True

Returns:

go.Figure – Plotly Figure object to be used in visualization.

Return type:

Figure

drdmannturb.fluctuation_generation.wind_plot.format_wind_field(wind_field: ndarray) tuple[ndarray, ndarray, ndarray][source]#

Creates a copy of the given wind-field that has a C-layout; this is a wrapper around np.copy.

Parameters:

wind_field (np.ndarray) – 3D wind field, typically of shape \((Nx, Ny, Nz, 3)\) (not C-layout, to be reshaped).

Returns:

tuple[np.ndarray, np.ndarray, np.ndarray] – Triple consisting of wind field values in each x, y, z directions.

Return type:

tuple[ndarray, ndarray, ndarray]

drdmannturb.fluctuation_generation.wind_plot.create_grid(spacing: tuple[float, float, float], shape: tuple[int, int, int]) ndarray[source]#

Creates a 3D grid (meshgrid) from given spacing between grid points and desired shape (which should match the shape of the generated wind field, for example).

Parameters:
  • spacing (tuple[float, float, float]) – Spacing array that determines the spacing of points to be used in each dimension of the 3D field. Typically, of the form grid_dimensions (a 3x1 vector representing the dimensions of the domain) divided by the grid_levels, which determine the resolution of the wind field in each respective dimension.

  • shape (tuple[int, int, int]) – Number of points in each dimension.

Returns:

np.ndarray – np.meshgrid object consisting of points at the provided spacing and with the specified counts in each dimension. This is ‘ij’ indexed (not Cartesian!).

Return type:

ndarray