Source code for wolfgpu.simplesimu.boundary_conditions

import logging
from enum import Enum
import numpy as np

# FIXME This should be imported from WolfHECE
[docs] class BoundaryConditionsTypes(Enum): """The boundary conditions types. Note: The values match the numbers in Wolf's simulations parameters. """
[docs] H = 1
""" Weak boundary condition over :math:`h+b`, the water free surface height (that is, height of water plus bathymetry level). """
[docs] QX = 2
""" Weak boundary condition over :math:`q_x`, the discharge over the x-axis. """
[docs] QY = 3
""" Weak boundary condition over :math:`q_y`, the discharge over the x-axis. """
[docs] NONE = 4
""" This is used to represent the absence of boundary condition. """
[docs] QBX = 5
""" Not used. """
[docs] QBY = 6
""" Not used. """
[docs] HMOD = 7
""" Weak boundary condition over :math:`h`, the water free surface height. """
[docs] FROUDE_NORMAL = 8
""" Weak boundary condition for Froude limited height. Water height becomes :math:`\\min(h, \\frac{u^2}{g \\times \\text{Fr}^2})` where :math:`\\text{Fr}` is given. """
[docs] class Direction(Enum):
[docs] LEFT = 1
[docs] BOTTOM = 2
[docs] X = 1
[docs] Y = 2
[docs] class BoundaryConditionIndices(Enum): """ The column indices of each supported boundary conditions in the boundary conditions table. This also covers cell parameters. IMPORTANT: These values are tied to data representation in the shader. Don't change them! These are separate from the `BoundaryConditionsTypes` because they don't serve the same purpose. These are for data representation in wolfgpu whereas `BoundaryConditionsTypes` are for CPU Wolf compatibility. `BoundaryConditionsTypes` and `CellParameterType` must all be converted to this enum when loading the sim in the gpu. """
[docs] BC_TABLE_INDEX_FOR_H_ON_LEFT = 1
[docs] BC_TABLE_INDEX_FOR_HMOD_ON_LEFT = 2
[docs] BC_TABLE_INDEX_FOR_QX_ON_LEFT = 0
[docs] BC_TABLE_INDEX_FOR_QY_ON_LEFT = 3 # Qy on a Y horizontal border
[docs] BC_TABLE_INDEX_FOR_FROUDE_NORMAL_ON_LEFT = 8
[docs] BC_TABLE_INDEX_FOR_H_ON_BOTTOM = 4
[docs] BC_TABLE_INDEX_FOR_HMOD_ON_BOTTOM = 5
[docs] BC_TABLE_INDEX_FOR_QX_ON_BOTTOM = 6 # Qx applied to a bottom border
[docs] BC_TABLE_INDEX_FOR_QY_ON_BOTTOM = 7 # Qy applied to a bottom border
[docs] BC_TABLE_INDEX_FOR_FROUDE_NORMAL_ON_BOTTOM = 9
[docs] BC_TABLE_INDEX_FOR_BRIDGE_DECK_ELEVATION = 10
[docs] BC_TABLE_INDEX_FOR_BRIDGE_ROOF_ELEVATION = 11
@classmethod
[docs] def index_for_bc_type(kls, param_type: BoundaryConditionsTypes, direction: Direction) -> "BoundaryConditionIndices": """ Find the column index in the BC table for a given BC type and direction. :param param_type: The type of parameter to set. See `BoundaryConditionIndices` enum for possible values. :param direction: The direction of the boundary condition. :return: The column index in the BC table. """ assert isinstance(param_type, BoundaryConditionsTypes), "param_type must be a BoundaryConditionsTypes enum value" assert isinstance(direction, Direction), "direction must be a Direction enum value" if param_type == BoundaryConditionsTypes.H: if direction in [Direction.X, Direction.LEFT]: return BoundaryConditionIndices.BC_TABLE_INDEX_FOR_H_ON_LEFT else: return BoundaryConditionIndices.BC_TABLE_INDEX_FOR_H_ON_BOTTOM elif param_type == BoundaryConditionsTypes.QX: if direction in [Direction.X, Direction.LEFT]: return BoundaryConditionIndices.BC_TABLE_INDEX_FOR_QX_ON_LEFT else: return BoundaryConditionIndices.BC_TABLE_INDEX_FOR_QX_ON_BOTTOM elif param_type == BoundaryConditionsTypes.QY: if direction in [Direction.X, Direction.LEFT]: return BoundaryConditionIndices.BC_TABLE_INDEX_FOR_QY_ON_LEFT else: return BoundaryConditionIndices.BC_TABLE_INDEX_FOR_QY_ON_BOTTOM elif param_type == BoundaryConditionsTypes.FROUDE_NORMAL: if direction in [Direction.X, Direction.LEFT]: return BoundaryConditionIndices.BC_TABLE_INDEX_FOR_FROUDE_NORMAL_ON_LEFT else: return BoundaryConditionIndices.BC_TABLE_INDEX_FOR_FROUDE_NORMAL_ON_BOTTOM elif param_type == BoundaryConditionsTypes.HMOD: if direction in [Direction.X, Direction.LEFT]: return BoundaryConditionIndices.BC_TABLE_INDEX_FOR_HMOD_ON_LEFT else: return BoundaryConditionIndices.BC_TABLE_INDEX_FOR_HMOD_ON_BOTTOM else: raise RuntimeError(f"Unsupported boundary condition parameter type: {param_type}")
[docs] BC_ON_LEFT = [BoundaryConditionIndices.BC_TABLE_INDEX_FOR_H_ON_LEFT, BoundaryConditionIndices.BC_TABLE_INDEX_FOR_HMOD_ON_LEFT, BoundaryConditionIndices.BC_TABLE_INDEX_FOR_QX_ON_LEFT, BoundaryConditionIndices.BC_TABLE_INDEX_FOR_QY_ON_LEFT, BoundaryConditionIndices.BC_TABLE_INDEX_FOR_FROUDE_NORMAL_ON_LEFT]
[docs] BC_ON_BOTTOM = [BoundaryConditionIndices.BC_TABLE_INDEX_FOR_H_ON_BOTTOM, BoundaryConditionIndices.BC_TABLE_INDEX_FOR_HMOD_ON_BOTTOM, BoundaryConditionIndices.BC_TABLE_INDEX_FOR_QX_ON_BOTTOM, BoundaryConditionIndices.BC_TABLE_INDEX_FOR_QY_ON_BOTTOM, BoundaryConditionIndices.BC_TABLE_INDEX_FOR_FROUDE_NORMAL_ON_BOTTOM]
# FIXME This *MUST* be imported from WolfHECE
[docs] class boundary_condition_2D: ''' Type des CL générales, faibles et fortes @author Pierre Archambeau ''' def __init__(self, i: int, j: int, ntype: BoundaryConditionsTypes, val: float, direction: Direction) -> None: from wolfhece.mesh2d.cst_2D_boundary_conditions import BCType_2D_GPU, Direction as hece_Direction INTEGER_TYPES=set([int, np.int16, np.int32, np.int64]) if not type(i) in INTEGER_TYPES: raise TypeError(f"The type of 'i' is not integral. You gave a '{type(i)}', I support {INTEGER_TYPES}") if not type(j) in INTEGER_TYPES: raise TypeError(f"The type of 'j' is not integral. You gave a '{type(j)}', I support {INTEGER_TYPES}") if not isinstance(ntype, BoundaryConditionsTypes | BCType_2D_GPU): raise TypeError(f"{ntype} should be BoundaryConditionsTypes. You gave {type(ntype)}") if not isinstance(direction, Direction | hece_Direction): raise TypeError(f"{direction} should be of type Direction. You gave {type(ntype)}") if i < 1: raise ValueError(f"The boundary conditions indices start at 1. You gave: {i} for the i index.") if j < 1: raise ValueError(f"The boundary conditions indices start at 1. You gave: {j} for the j index.") # I cast to "int" because these values will be marshalled to JSON. # However I use the default behaviour of JSON which only handles 'int' # and not numpy's int types if type(i) != int or type(j) != int: logging.warning("You have given i,j values for which the type is not 'int'. I will cast them to int.")
[docs] self.i = int(i) # indice de colonne dans le plus petit maillage
[docs] self.j = int(j) # indice de ligne dans le plus petit maillage
[docs] self.ntype = ntype # type de cl (h=1,qx=2,qy=3,rien=4,qbx=5,qby=6,hmod=7,fr=8)
[docs] self.val = val # valeur à imposer
[docs] self.direction = direction
[docs] def to_dict(self): return { "i" : self.i, "j" : self.j, "type": self.ntype.name, "val" : float(self.val), # float makes sure the load and save to JSON has same format ("xxx.yyy") event when passing int's. "direction": self.direction.name, }
@classmethod
[docs] def from_dict(kls, js): return boundary_condition_2D(js["i"], js["j"], BoundaryConditionsTypes[js["type"]], float(js["val"]), Direction[js["direction"]])
[docs] BC_BLANK_VALUE=np.float32(-9_999_999) # Exactly represented by float32
[docs] NB_BC_TYPES = len(BoundaryConditionIndices)