Source code for pheromone_dispersion.geom

import numpy as np

"""
Module containing the geometry of the domain ,
the mesh and the time window.
"""


[docs] class MeshRect2D: r""" Class containing the geometry of a 2D rectangular domain :math:`\Omega = [x_0;x_0+L_x]\times [y_0;y_0+L_y]` with a cartesian mesh with constant space steps :math:`\Delta x` and :math:`\Delta y`, and a time window :math:`[0;T]` discretized with constant time step :math:`\Delta t`. Attributes ---------- L_x : float Length of the domain along the :math:`x`-axis :math:`L_x`. L_y : float Length of the domain along the :math:`y`-axis :math:`L_y`. dx : float Space step of the mesh along the :math:`x`-axis :math:`\Delta x`. dy : float Space step of the mesh along the :math:`y`-axis :math:`\Delta y`. x : ~numpy.ndarray Array of the :math:`x`-coordinates of the center of the cells of the mesh. y : ~numpy.ndarray Array of the :math:`y`-coordinates of the center of the cells of the mesh. x_vertical_interface : ~numpy.ndarray Array of the :math:`x`-coordinates of the vertical interfaces between the cells of the mesh. y_horizontal_interface : ~numpy.ndarray Array of the :math:`y`-coordinates of the horizontal interfaces between the cells of the mesh. mass_cell : float The volume of mesh cells :math:`\Delta x\times \Delta y`. t : float The current time :math:`t` of the modelling, initialized to :math:`t=0s`. T_final : float The final time :math:`T` of the modeling time window. dt : float The time step :math:`\Delta t`. Initialized to `None` and to be computed using the methods :func:`calc_dt_explicit_solver` or :func:`calc_dt_implicit_solver`. t_array : ~numpy.ndarray The time array. Initialized to `None` and to be computed from the attribute :attr:`dt` using the methods :func:`calc_dt_explicit_solver` or :func:`calc_dt_implicit_solver`. X_0 : tuple of float Coordinates of the origin of the mesh :math:`(x_0, y_0)`. By default set to :math:`(x_0, y_0)=(0, 0)`. """
[docs] def __init__(self, L_x, L_y, dx, dy, T_final, X_0=None): r""" Constructor method. Parameters ---------- L_x : float Length of the domain along the :math:`x`-axis :math:`L_x`. L_y : float Length of the domain along the :math:`y`-axis :math:`L_y`. dx : float Space step of the mesh along the :math:`x`-axis :math:`\Delta x`. dy : float Space step of the mesh along the :math:`y`-axis :math:`\Delta y`. T_final : float The final time :math:`T` of the modeling time window. X_0 : tuple of float, default: None Coordinates of the origin of the mesh :math:`(x_0, y_0)`. If `None`, set to :math:`(x_0, y_0)=(0, 0)`. """ # To do: # Add exceptions to ensure all inputs are float. self.L_x = L_x self.L_y = L_y self.dx = dx self.dy = dy nx = L_x // dx ny = L_y // dy if dx - 1e-12 < L_x % dx: nx += 1 if dy - 1e-12 < L_y % dy: ny += 1 if X_0 is None: X_0 = (0.0, 0.0) self.x_vertical_interface = np.arange(0, (nx + 0.5) * dx, dx) + X_0[0] self.x = 0.5 * (self.x_vertical_interface[:-1] + self.x_vertical_interface[1:]) self.y_horizontal_interface = np.arange(0, (ny + 0.5) * dy, dy) + X_0[1] self.y = 0.5 * (self.y_horizontal_interface[:-1] + self.y_horizontal_interface[1:]) self.mass_cell = dx * dy self.t = 0 self.T_final = T_final self.dt = None self.t_array = None
[docs] def calc_dt_explicit_solver(self, U, dt_max=0.1): r""" Compute the time step :math:`\Delta t` such as it satisfies the CFL condition :math:`\Delta t<\left(\frac{max(u)}{\Delta x}+\frac{max(v)}{\Delta y}\right)^{-1}` for a given wind field :math:`\vec{u}=(u,v)`. To be used with an explicit or semi-implicit numerical scheme. Parameters ---------- U: ~pheromone_dispersion.velocity.Velocity The wind field :math:`\vec{u}(x,y,t)`. dt_max: float, optional, default: 0.1 The maximal time step :math:`\Delta t_{max}` imposing that :math:`\Delta t<\Delta t_{max}` to ensure a certain accuracy Notes ----- Compute a time step :math:`\Delta t`, store it in the attribute :attr:`dt` and compute the attribute :attr:`t_array` accordingly. """ # To do: # add exceptions to make sure that all the inputs are float self.dt = np.min([1.0 / (1.2 * U.max_horizontal_U / self.dx + 1.2 * U.max_vertical_U / self.dy), dt_max]) self.t_array = np.arange(0, self.T_final + self.dt, self.dt) self.T_final = self.t_array[-1]
[docs] def calc_dt_implicit_solver(self, dt): r""" Store the provided time step :math:`\Delta t` in the attribute :attr:`dt` and compute the attribute :attr:`t_array` accordingly. To be used with an implicit numerical scheme. Parameters ---------- dt : float The provided time step :math:`\Delta t`. """ # To do: # add exceptions to make sure that all the inputs are float self.dt = dt self.t_array = np.arange(0, self.T_final + self.dt, self.dt) self.T_final = self.t_array[-1]