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.
"""
""" Weak boundary condition over :math:`h+b`, the water free surface height
(that is, height of water plus bathymetry level).
"""
""" Weak boundary condition over :math:`q_x`, the discharge over the x-axis.
"""
""" Weak boundary condition over :math:`q_y`, the discharge over the x-axis.
"""
""" This is used to represent the absence of boundary condition.
"""
""" Not used.
"""
""" Not used.
"""
""" Weak boundary condition over :math:`h`, the water free surface height.
"""
""" 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 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)