Source code for src.utils
import logging
import numpy as np
import scipy.fft as fft
[docs]
def compute_wind_fields(u_rot, wind_dir):
"""
Computes the zonal (u) and meridional (v) wind components from a rotated
wind speed and direction.
Parameters:
u_rot (float): Rotated wind speed.
wind_dir (float): Wind direction in degrees (clockwise from north).
Returns:
tuple: A tuple (u, v) where:
- u (float): Zonal wind component (east-west).
- v (float): Meridional wind component (north-south).
"""
wind_dir = np.deg2rad(wind_dir)
u = u_rot * np.sin(wind_dir)
v = u_rot * np.cos(wind_dir)
return u, v
[docs]
def point_source(nxy, domain, src_pt):
"""
Generates a point source field in Fourier space and transforms it back
to the spatial domain.
Parameters:
nxy (tuple): Number of grid points in the x and y directions (nx, ny).
domain (tuple): Physical dimensions of the domain (xmax, ymax).
src_pt (tuple): Coordinates of the source point (xs, ys).
Returns:
numpy.ndarray: A 2D array representing the point source field in the spatial domain.
"""
nx, ny = nxy
xmx, ymx = domain
xs, ys = src_pt
dx, dy = xmx / nx, ymx / ny
# Fourier summation index
ilx = fft.fftfreq(nx, d=1.0 / nx)
ily = fft.fftfreq(ny, d=1.0 / ny)
# define zonal and meridional wavenumbers
lx = 2.0 * np.pi / dx / nx * ilx
ly = 2.0 * np.pi / dy / ny * ily
Lx, Ly = np.meshgrid(lx, ly)
fftq0 = np.ones((ny, nx), dtype=complex)
# shift to source point in Fourier space
fftq0 = fftq0 * np.exp(-1j * (Lx * xs + Ly * ys)) / nx / ny
# normalize
fftq0 = fftq0 / dx / dy
return fft.ifft2(fftq0, norm="forward").real
[docs]
def ideal_source(nxy, domain, shape="diamond"):
"""
Creates a synthetic source field in the shape of a circle or diamond.
Useful for testing purposes.
Parameters:
nxy (tuple): Number of grid points in the x and y directions (nx, ny).
domain (tuple): Physical dimensions of the domain (xmax, ymax).
shape (str): Shape of the source field. Options are "circle" or "diamond". Default is "diamond".
Returns:
numpy.ndarray: A 2D array representing the source field.
"""
nx, ny = nxy
xmx, ymx = domain
x = np.linspace(0.0, xmx, nx)
y = np.linspace(0.0, ymx, ny)
X, Y = np.meshgrid(x, y)
q0 = np.zeros([ny, nx])
# Circular source
# R = np.sqrt((X-xmx/2)**2 + (Y-ymx/2)**2)
# Diamond source
R = np.abs(X - xmx / 4) + np.abs(Y - ymx / 4)
R0 = xmx / 12
q0 = np.where(R < R0, 1.0, 0.0)
return q0
[docs]
def point_measurement(f, g):
"""
Computes the convolution of two 2D arrays evaluated at a specific point.
Parameters:
f (numpy.ndarray): First 2D array.
g (numpy.ndarray): Second 2D array.
Returns:
float: The result of the convolution at the specified point.
"""
return np.sum(f * g)
[docs]
def setup_logging():
"""Set up logging configuration."""
logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)