wolfgpu.simple_simulation ========================= .. py:module:: wolfgpu.simple_simulation .. autoapi-nested-parse:: Author: HECE - University of Liege, Stéphane Champailler, Pierre Archambeau Date: 2024 Copyright (c) 2024 University of Liege. All rights reserved. This script and its content are protected by copyright law. Unauthorized copying or distribution of this file, via any medium, is strictly prohibited. Module Contents --------------- .. py:class:: CellParameterType(*args, **kwds) Bases: :py:obj:`enum.Enum` .. autoapi-inheritance-diagram:: wolfgpu.simple_simulation.CellParameterType :parts: 1 :private-bases: Represents the type of a cell parameter. .. py:attribute:: BRIDGE_DECK_ELEVATION :value: 1 .. py:attribute:: BRIDGE_ROOF_ELEVATION :value: 2 .. py:class:: BoundaryConditionsTypes(*args, **kwds) Bases: :py:obj:`enum.Enum` .. autoapi-inheritance-diagram:: wolfgpu.simple_simulation.BoundaryConditionsTypes :parts: 1 :private-bases: The boundary conditions types. Note: The values match the numbers in Wolf's simulations parameters. .. py:attribute:: H :value: 1 Weak boundary condition over :math:`h+b`, the water free surface height (that is, height of water plus bathymetry level). .. py:attribute:: QX :value: 2 Weak boundary condition over :math:`q_x`, the discharge over the x-axis. .. py:attribute:: QY :value: 3 Weak boundary condition over :math:`q_y`, the discharge over the x-axis. .. py:attribute:: NONE :value: 4 This is used to represent the absence of boundary condition. .. py:attribute:: QBX :value: 5 Not used. .. py:attribute:: QBY :value: 6 Not used. .. py:attribute:: HMOD :value: 7 Weak boundary condition over :math:`h`, the water free surface height. .. py:attribute:: FROUDE_NORMAL :value: 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. .. py:class:: Direction(*args, **kwds) Bases: :py:obj:`enum.Enum` .. autoapi-inheritance-diagram:: wolfgpu.simple_simulation.Direction :parts: 1 :private-bases: Create a collection of name/value pairs. Example enumeration: >>> class Color(Enum): ... RED = 1 ... BLUE = 2 ... GREEN = 3 Access them by: - attribute access:: >>> Color.RED - value lookup: >>> Color(1) - name lookup: >>> Color['RED'] Enumerations can be iterated over, and know how many members they have: >>> len(Color) 3 >>> list(Color) [, , ] Methods can be added to enumerations, and members can have their own attributes -- see the documentation for details. .. py:attribute:: LEFT :value: 1 .. py:attribute:: BOTTOM :value: 2 .. py:attribute:: X :value: 1 .. py:attribute:: Y :value: 2 .. py:class:: SimpleSimulation(nx: int = 0, ny: int = 0) A simple simulation scenario. IMPORTANT: although we use numpy arrays to represent various matrices, be careful: we use shapes as (nb of columns, nb of rows). This is transposed compared to regular numpy ! .. py:attribute:: path :type: pathlib.Path Directory where the simulation was loaded or will be saved. .. py:attribute:: creation_date :type: datetime.datetime Creation or last save date. .. py:attribute:: comment :type: str A free text comment, no formatting supported. .. py:attribute:: param_froude_max :type: float Froude limit .. py:attribute:: _param_froude_bc_limit_tolerance :type: float When Froude BC applies and needs to push up the water height, it will push it up to current_water_height * tolerance. .. py:attribute:: param_runge_kutta :type: float Runge-Kutta ponderation. The value is the ponderation of the estimator. Thus 1-ponderation is applied to the corrector. None means no RK but simple Euler step. .. py:attribute:: _param_dx :type: float Size of a single mesh along x axis, in meters. .. py:attribute:: _param_dy :type: float Size of a single mesh along y axis, in meters. .. py:attribute:: _param_nbx :type: int Size of the computation domain along the x axis, in number of meshes. .. py:attribute:: _param_nby :type: int Size of the computation domain along the y axis, in number of meshes. .. py:attribute:: param_base_coord_ll_x :type: float The computation domain coordinates are relative to "base" coordinates. This parameter is the x component of the base coordinates. The basis of the coordinates system is located, by convention, on the lower left corner of the domain (i.e. at (0,0) in the local coordinates system). .. py:attribute:: param_base_coord_ll_y :type: float The computation domain coordinates are relative to "base" coordinates. This parameter is the y component of the base coordinates. The basis of the coordinates system is located, by convention, on the lower left corner of the domain (i.e. at (0,0) in the local coordinates system). .. py:attribute:: _param_timestep_strategy :type: wolfgpu.simplesimu.durations.TimeStepStrategy Strategy used to compute the time step at each iteration. .. py:attribute:: _param_timestep :type: float In case of a constant time step strategy, this is the duration of the time step. It will be ignored in other cases. .. py:attribute:: _param_infiltration_lerp :type: wolfgpu.simplesimu.infiltrations.InfiltrationInterpolation constant values, linear interpolation,... :type: Type of infiltration interpolation .. py:attribute:: _param_duration :type: wolfgpu.simplesimu.durations.SimulationDuration Duration of the simulation, either in steps or in simulation time (seconds) .. py:attribute:: _param_report_period :type: wolfgpu.simplesimu.durations.SimulationDuration Duration of the period for reporting, either in steps or in simulation time (seconds) .. py:attribute:: _h :type: numpy.typing.NDArray[numpy.float32] Matrix of water height, in meters. .. py:attribute:: _qx :type: numpy.typing.NDArray[numpy.float32] Matrix of quantity of movement along x axis, in m²/s. .. py:attribute:: _qy :type: numpy.typing.NDArray[numpy.float32] Matrix of quantity of movement along y axis, in m²/s. .. py:attribute:: _bathymetry :type: numpy.typing.NDArray[numpy.float32] Bathymetry, in meters. .. py:attribute:: _manning :type: numpy.typing.NDArray[numpy.float32] Manning coefficients. .. py:attribute:: _infiltration_zones :type: numpy.typing.NDArray[numpy.int32] Infiltration zones indices. Indices are numbered from one. 0 means no infiltration in the mesh. .. py:attribute:: _nap :type: numpy.typing.NDArray[numpy.uint8] Matrix representing which mesh are part of the computation domain or not. 1 means a mesh is part of the computation domain, 0 means it's not. .. py:attribute:: _bridge_roof_elevation :type: numpy.typing.NDArray[numpy.float32] Elevation of the bridge roof. .. py:attribute:: _wp :type: wolfhece.PyParams.Wolf_Param Attributes of the simulation as Wolf_Param instance. .. py:attribute:: _boundary_conditions :type: list[boundary_condition_2D] :value: [] .. py:attribute:: _cell_parameters :type: list[CellParameter] :value: [] .. py:attribute:: _infiltrations_chronology :value: [] .. py:attribute:: _infiltrations_timings_as_gpu_array_cache :value: None .. py:attribute:: _wrapped_injectors :type: dict[str, wolfgpu.injector_wrapper.InjectorWrapper] .. py:attribute:: param_courant :value: 0.5 .. py:method:: _check_np_array_type(a: numpy.array, dtype=np.float32, check_size=True) .. py:method:: _interior_cell(bc: boundary_condition_2D, zero_based=True) Given a boundary condition, return the cell which touches the boundary condition border *and* which is inside the simulation domain. This works only if the boundary condition's coordinates are correct. .. py:method:: force_Euler_scheme() Force the simulation to use a simple Euler scheme. .. py:property:: param_dx dx is the x-dimension of a mesh (expressed in meters). .. py:property:: param_dy dy is the y-dimension of a mesh (expressed in meters) .. py:property:: h :type: numpy.typing.NDArray[numpy.float32] An array representing the water height (expressed in meters above the bathymetry). .. py:property:: qx :type: numpy.typing.NDArray[numpy.float32] An array representing the water discharge along x-axis (expressed in m/s²). .. py:property:: qy :type: numpy.typing.NDArray[numpy.float32] An array representing the water discharge along y-axis (expressed in m/s²). .. py:property:: manning :type: numpy.typing.NDArray[numpy.float32] An array representing the Manning coefficient for each mesh. .. py:property:: infiltration_zones :type: numpy.typing.NDArray[numpy.int32] An array representing the infiltration zones for each mesh. .. py:property:: nap :type: numpy.typing.NDArray[numpy.uint8] An array representing the meshes that are part of the computation domain. .. py:property:: bathymetry :type: numpy.typing.NDArray[numpy.float32] An array representing the bathymetry each mesh (expressed in meters). .. py:property:: param_nx :type: int Dimension of the computation domain on the x axis. .. py:property:: param_ny :type: int Dimension of the computation domain on the y axis. .. py:property:: param_froude_bc_limit_tolerance When Froude BC applies and needs to push up the water height, it will push it up to current_water_height * tolerance. .. py:property:: shape :type: tuple[int, int] The shape of the various arrays representing data in the computation domain. This is equal to `(param_nx, param_ny)`. .. py:property:: param_duration :type: wolfgpu.simplesimu.durations.SimulationDuration Duration of the simulation, either in steps or in simulation time (seconds). The duration is represented by an object of class `SimulationDuration`. .. py:property:: param_report_period :type: wolfgpu.simplesimu.durations.SimulationDuration Duration of the period for reporting, either in steps or in simulation time (seconds). The duration is represented by an object of class `SimulationDuration`. .. py:property:: param_timestep :type: float In case of a constant timestep strategy, this is the duration of a step, expressed in seconds. .. py:property:: param_timestep_strategy :type: wolfgpu.simplesimu.durations.TimeStepStrategy Strategy used to compute the time step at each iteration. The strategy is represented by an object of class `TimeStepStrategy`. .. py:property:: param_infiltration_lerp :type: wolfgpu.simplesimu.infiltrations.InfiltrationInterpolation constant values, linear interpolation,... The interpolation type is represented by an object of class `InfiltrationInterpolation`. :type: Type of infiltration interpolation .. py:method:: add_boundary_condition(i: int, j: int, bc_type: BoundaryConditionsTypes, bc_value: float, border: Direction) Add a boundary condition to the model. :param i, j: position of the boundary condition (1-based) :param bc_type: type of boundary condition :param bc_value: value/parameter of the boundary condition :param border: mesh's border on which the boundary condtion applies .. py:method:: header_wolf() -> wolfhece.wolf_array.header_wolf .. py:method:: number_of_bc_along_X() .. py:method:: number_of_bc_along_Y() .. py:method:: add_cell_parameter(i: int, j: int, bc_type: CellParameterType, bc_value: float) Add a cell parameter to the model. :param i: i position of the boundary condition (1-based) :param j: j position of the boundary condition (1-based) :param bc_type: type of cell parameter :param bc_value: value/parameter of the boundary condition :param border: mesh's border on which the boundary condtion applies .. py:method:: get_cell_parameter(i: int, j: int, bc_type: CellParameterType) -> float Get the value of a cell parameter at a given position. :param i, j: position of the boundary condition (1-based) :param bc_type: type of cell parameter .. py:method:: get_all_cell_parameters(bc_type: CellParameterType) -> List[CellParameter] Get all the cell parameters of a given type. :param bc_type: type of cell parameter .. py:method:: clear_cell_parameters(bc_type: CellParameterType = None) Clears all the cell parameters. Useful if one wants to build a new simulation starting with an existing one. :param bc_type: if given, only the cell parameters of this type will be cleared. .. py:method:: clear_boundary_conditions() Clears all the boundary conditions. Useful if one wants to build a new simulation starting with an existing one. .. py:method:: get_injector(identifier: str) -> wolfgpu.injector_wrapper.InjectorWrapper Get an injector by its identifier. The identifier must be present in the simulation. .. py:method:: add_injector(identifier: str, injector: wolfgpu.injector.SimulationInjector, active_zone: wolfhece.wolf_array.header_wolf, time_to_first_injection: wolfgpu.simplesimu.durations.SimulationDuration, replace=False) At this point only the active zone is handled by the simulator itself. The rest of the parameters of an injector (such as the starting time) will be handled by the injector's class. :param identifier: A unique identifier for the injector, used in various places (but not for display). :param active_zone: The zone over which the injector can act. These zones are handled by the simulator because it needs to make sure no two zones overlap. :param time_to_first_injection: Time to first injection, how much time the simulator will wait before calling this injector. :param replace: In case an identifier with the same `name` exists, it will be replaced. .. py:method:: delete_injector(identifier: str) Delete an injector by its identifier. :param identifier: The identifier of the injector to delete. .. py:method:: get_injector_base_params(identifier: str) -> tuple[wolfhece.wolf_array.header_wolf, wolfgpu.simplesimu.durations.SimulationDuration] .. py:method:: set_injector_base_params(identifier: str, active_zone: wolfhece.wolf_array.header_wolf, time_to_first_injection: wolfgpu.simplesimu.durations.SimulationDuration) .. py:method:: _injector_wrappers() -> dict[str, wolfgpu.injector_wrapper.InjectorWrapper] .. py:method:: add_infiltration(time_start: float, zones_values: list[float]) Add an infiltration point in the infiltration chronology. :param time_start: start time of the infiltration (in seconds) :param zones_values: an array representing the quantity of water per second to add to each infiltration zones, starting at time_start. The first item corrsesponds to the zone 1, second item corresponds to zone 2 and so on. .. py:method:: clear_infiltration_chronology() Clear the infiltration chronology. Useful if one wants to build a new simulation starting with an existing one. .. py:property:: boundary_condition :type: list[boundary_condition_2D] .. py:property:: infiltrations_chronology :type: list[float, list[float]] Returns the chronology of infiltration. This is a list. Each entry of the list is: `[start_time, [list of values for each infiltration zone]]` The start_time is when the infiltration should start. The list of value is the quantity of water falling on each mesh of each infitlation zones (the n-th entry of the list corresponds to the n-th infiltration zone). .. py:method:: _infiltrations_timings_as_gpu_array() Compute the infiltration timing array in a form suitable for the GPU processing. .. py:method:: _check_infiltrations_warnings(infiltration_zones: numpy.ndarray, nap: numpy.ndarray, bathymetry: numpy.ndarray) -> list[str] Check if the infiltration data is consistent. .. py:method:: _check_infiltrations(infiltration_zones: numpy.ndarray, infiltration_timings, interp_infiltration: wolfgpu.simplesimu.infiltrations.InfiltrationInterpolation, nap: numpy.ndarray, bathymetry: numpy.ndarray) -> list[str] Check if the infiltration data is consistent. .. py:method:: plot_infiltration(figax=None, toshow: bool = True) Plot the infiltration chronology. :param figax: a tuple (fig, ax) of matplotlib objects. If None, a new figure is created. :param toshow: if True, the figure is shown. :return: the figure and the axis. .. py:method:: check_warnings() -> Union[None, list[str]] Check if the model currently set in this object is valid. A number of tests are made, they are not exhaustive. Returns None if no problem was found. Returns a list of warnings messages else. .. py:method:: check_errors() -> Union[None, list[str]] Check if the model currently set in this object is valid. A number of tests are made, they are not exhaustive. These tests are performed after the creation of the simulation (or part of it), because sometimes we need several data to do the test (for example, we need both the NAP matrix and the boundary conditions to check they are coherent) Returns None if no problem was found. Returns a list of error messages else. .. py:method:: _fail_if_invalid() .. py:attribute:: _injector_classes_registry :type: set[type] The injector registry is here to allow the simple simulation class to know about the injector classes. It is useful when loading a simulation from the disk: with it one can quickly check if the injector class in the loaded simulation is supported. .. py:method:: register_injector_class(injector_class: Type[wolfgpu.injector.SimulationInjector]) :classmethod: .. py:method:: unregister_injector_class(injector_class: Type[wolfgpu.injector.SimulationInjector]) :classmethod: .. py:method:: get_registered_injector_classes() -> set[type] :classmethod: .. py:method:: unregister_all_injector_classes() :classmethod: .. py:method:: unregister_injector_class_by_name(injector_cls_name: str) :classmethod: .. py:method:: register_injector_class_from_file(injector_cls_name: str, path: pathlib.Path) -> type :classmethod: .. py:method:: load(simulation_dir: pathlib.Path | str) :classmethod: Load a simulation. :param store_dir: where the simulation model is stored (a directory). :type store_dir: Path .. py:method:: _json_to_header_wolf(d) -> wolfhece.wolf_array.header_wolf Construct a header_wolf object from a JSON-like dictionary. :param d: Dictionary with keys 'dx', 'dy', 'origx', 'origy', 'nbx', 'nby' :return: header_wolf instance .. py:method:: copy() -> SimpleSimulation Create a new simulation from an existing one. .. py:method:: save(store_dir: pathlib.Path = None) Save the model to a directory. If `store_dir` is None, the path used to load the model is used. If the model was not loaded from a directory, an exception is raised. .. py:method:: _save_json() -> dict Save the parameters to a json file. .. py:method:: _save_injectors_to_json() -> dict .. py:method:: to_wolfparam() -> wolfhece.PyParams.Wolf_Param Return a Wolf_Param object that represents the parameters of the simulation. .. py:method:: add_to_wolfparam(dest: wolfhece.PyParams.Wolf_Param) -> wolfhece.PyParams.Wolf_Param Return a Wolf_Param object that represents the parameters of the simulation. .. py:method:: from_wolfparam(wp: wolfhece.PyParams.Wolf_Param) Callback called when the Wolf_Param object is modified and apply routine is called. .. py:method:: write_initial_condition_from_record(recpath: pathlib.Path = None, id_rec: int = None, destpath: pathlib.Path = None) -> int Define the initial condition of the simulation from a previous record. :param recpath: the path to the records. if None, the default path is used and 'simul_gpu_results' as result directory. :param id_rec: the index of the record you want to start from. :param destpath: the path where to save the initial condition. If None, the current path is used. :return: 0 if everything went well, -1 if the record doesn't exist, -2 if the record path doesn't exist. .. py:method:: copy_ic_from_simulation(source: SimpleSimulation) Copy the initial condition from a simulation to the current simulation. .. py:method:: copy_ic_from_record(source: pathlib.Path, id_rec: int = None) Copy the initial condition from a record to the current simulation. .. py:method:: has_infiltration() .. py:method:: mask_nap_contour(nb_cells: int = 1) Mask the contour of the NAP array. .. py:method:: make_void_arrays() Create void arrays from (nx, ny) shape. Arrays : - nap - h - qx - qy - manning - bathymetry .. py:method:: make_void_infiltration_zones() Create a void infiltration zones array. .. py:property:: bridge_roof :type: numpy.ndarray Return the bridge roof. .. py:method:: has_bridge() -> bool Return True if the simulation has a bridge roof. .. py:method:: make_void_bridge_roof() Create a void bridge roof array. .. py:method:: convert_roof_array2params(roof_array: numpy.ndarray = None) Convert a roof array to a list of parameters. It will remove all the existing bridge roof parameters before add the new ones. .. py:method:: _params_have_duplicated_values() -> str Check if the parameters are not duplicated. .. py:method:: ensure_nullvalue_outside_nap(nodata=99999.0) Force the nodata where nap is 0 for: - topo/bathymetry - manning Force zero value for initial conditions where nap is 0: - h - qx - qy