{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Creation of a 2D modeling via script\n", "\n", "In order to create a 2D simulation, it is necessary to:\n", "\n", "- Create an instance \"prev_sim2d\" by going into argument the full access path and the generic name of the simulation\n", "- Define a vector/polygon contour delimiting the work area\n", "-(optional) Define a \"magnetic grid\" used to catch vertices of polygons -> allows to align between different models for example.\n", "- Define the spatial resolution of the mesh on which the data (topo, rubbing, unknown ...) will be provided initially\n", "- Define block contours/polygons and their respective spatial resolution\n", "- Call the mesher (call to the Fortran code)\n", "- Create the mandatory matrices and fill them with the desired values ​​(via script (s) or GUI)\n", "- Create the potential edges for boundary conditions (.aux, .suy)\n", "- Impose the necessary limits (info: nothing = impermeable)\n", "- Configure the problem\n", "- Execute the calculation\n", "- Treat the results\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Import modules" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from wolfhece.mesh2d.wolf2dprev import prev_sim2D\n", "from wolfhece.PyVertexvectors import zone, Zones, vector, wolfvertex\n", "from wolfhece.wolf_array import WolfArray, WolfArrayMB, header_wolf\n", "from wolfhece.wolfresults_2D import Wolfresults_2D\n", "from wolfhece.mesh2d.cst_2D_boundary_conditions import BCType_2D, Direction, revert_bc_type\n", "\n", "from tempfile import TemporaryDirectory\n", "from pathlib import Path\n", "import numpy as np\n", "from datetime import datetime as dt\n", "from datetime import timezone as tz\n", "from datetime import timedelta as td\n", "from typing import Literal, Union\n", "import logging" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Definition of the work directory" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test\n" ] } ], "source": [ "outdir = Path(r'test')\n", "outdir.mkdir(exist_ok=True) # Création du dossier de sortie\n", "print(outdir.name)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Verification of the presence of the solver code\n", "\n", "Returns the full access path to the code" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Code found : D:\\ProgrammationGitLab\\HECEPython\\wolfhece\\libs\\wolfcli.exe\n" ] } ], "source": [ "wolfcli = prev_sim2D.check_wolfcli() # méthode de classe, il n'est donc pas nécessaire d'instancier la classe pour l'appeler\n", "\n", "if wolfcli:\n", " print('Code found : ', wolfcli)\n", "else:\n", " print('Code not found !')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Creation of a 2D simulation object" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:root:No infiltration file found\n" ] } ], "source": [ "# Passing the working directory to which we added the generic name of the simulation.\n", "# \"Clear\" allows you to delete files from the previous simulation.\n", "newsim = prev_sim2D(fname=str(outdir / 'test'), clear=True)\n", "\n", "# A \"logging.info\" message is issued because no file has been found. This is normal!\n", "# If a file is found, it is loaded." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Geometry of the problem\n", "\n", "Square domain of total size 1.0 m x 1.0 m.\n", "\n", "## Definition mode\n", "\n", "It is necessary to define an external polygon/outline of the domain to model.\n", "\n", "There are six ways of working:\n", "1. Create a \"Vector\" object and encode its contact details - via a \"Vector\" class - see [wolfhece.pyvertexverters] (https://wolf.hece.hece.uliege.be/Autoapi/wolfhece/pyvertexvecotors/index.html)\n", "1. Define the desired spatial terminals\n", "1. Define the origin, the size of the mesh and the number of stitches in each direction\n", "1. Provide a header object\n", "1. On the basis of an existing matrix - Total grip\n", "1. On the basis of an existing matrix - outline generated on the basis of its mask\n", "\n", "Internally, these 6 procedures will always come back to define a vector contour/polygon, only given accepted by the Fortran code." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Steps of implementation\n", "\n", "It is necessary to define an external polygon/outline of the domain to model." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Nombre de vertices : 5\n", "5 vertices car la polygone est fermé et le dernier point est aux mêmes coordonnées que le premier.\n", "Meshing done !\n" ] } ], "source": [ "# Magnetic grid - DX and DY are the steps of the grid [m], origx and origy are the coordinates of the first point of the grid.\n", "# The coordinates will be aligned on the magnetic grid by the routine align2grid -- https://wolf.hece.uliege.be/autoapi/wolfhece/wolf_array/index.html#wolfhece.wolf_array.header_wolf.align2grid\n", "newsim.set_magnetic_grid(dx=1., dy=1., origx=0., origy=0.)\n", "\n", "# ***** CHOICE *****\n", "\n", "# Choisir 1 des 6 options suivantes pour définir le contour externe de la simulation\n", "# ----------------------------------------------------------------------------------\n", "\n", "choices = [(1, 'set_external_border_vector'),\n", " (2, 'set_external_border_xy'),\n", " (3, 'set_external_border_nxny'),\n", " (4, 'set_external_border_header'),\n", " (5, 'set_external_border_wolfarray - mode emprise'),\n", " (6, 'set_external_border_wolfarray - mode contour')]\n", "\n", "choice = 1\n", "\n", "if choice not in [c[0] for c in choices]:\n", "\n", " logging.error('Invalid choice !')\n", "\n", "elif choice == 1:\n", "\n", " # Define the extrenal contour\n", " extern = vector()\n", " extern.add_vertex(wolfvertex(0., 0.))\n", " extern.add_vertex(wolfvertex(1., 0.))\n", " extern.add_vertex(wolfvertex(1., 1.))\n", " extern.add_vertex(wolfvertex(0., 1.))\n", " extern.close_force()\n", "\n", " print('Nombre de vertices : ', extern.nbvertices)\n", " print('5 vertices car la polygone est fermé et le dernier point est aux mêmes coordonnées que le premier.')\n", "\n", " # Transfert du polygone comme contour externe de simulation.\n", " # Le contour externe est la limite de maillage.\n", " # Ensemble, les polygones de blocs doivent entourer complètement le contour externe.\n", " newsim.set_external_border_vector(extern)\n", "\n", "elif choice == 2:\n", "\n", " # via des bornes\n", " newsim.set_external_border_xy(xmin= 0., xmax= 1., ymin= 0., ymax= 1.)\n", "\n", "elif choice == 3:\n", "\n", " # encore via une description de la matrice\n", " # ATTENTION : ici dx et dy ne sont pas nécessairement les mêmes que ceux du maillage fin.\n", "\n", " newsim.set_external_border_nxny(xmin= 0, ymin=0., nbx= 10, nby= 10, dx= 0.1, dy= 0.1)\n", "\n", "elif choice == 4:\n", "\n", " # Ici rien de bien intéressant vis-à-vis du choix précédent mais il est possible\n", " # d'obtenir un header depuis n'importe quelle matrice\n", "\n", " header = header_wolf()\n", " header.origx = 0.\n", " header.origy = 0.\n", " header.dx = 0.1\n", " header.dy = 0.1\n", " header.nbx = 10\n", " header.nby = 10\n", "\n", " newsim.set_external_border_header(header)\n", "\n", "elif choice == 5:\n", " # On peut aussi choisir de définir le contour externe à partir\n", " # d'une matrice de donnée de type WolfArray\n", "\n", " # Mode emprise/header\n", "\n", " # Comme on n'a pas de données chargées, on crée une matrice de toute pièce.\n", "\n", " header = header_wolf()\n", " header.origx = 0.\n", " header.origy = 0.\n", " header.dx = 1.\n", " header.dy = 1.\n", " header.nbx = 1\n", " header.nby = 1\n", "\n", " src_array = WolfArray(srcheader=header)\n", "\n", " newsim.set_external_border_wolfarray(src_array, mode='header', abs=True)\n", "\n", " # L'emprise n'a pas besoin que la matrice soit masquée, mais c'est possible.\n", " # Dans ce dernier cas, le masque est ignoré lors de la création de l'emprise.\n", "\n", "elif choice == 6:\n", " # On peut aussi choisir de définir le contour externe à partir\n", " # d'une matrice de données de type WolfArray\n", "\n", " # Mode contour/masque\n", "\n", " # Comme on n'a pas de données chargées, on crée une matrice de toute pièce.\n", " #\n", " # ATTENTIOn : la recherche d'un contour demande que la matrice soit bornée par des valeurs masquées.\n", "\n", " header = header_wolf()\n", " header.origx = -1.\n", " header.origy = -1.\n", " header.dx = 1.\n", " header.dy = 1.\n", " header.nbx = 3\n", " header.nby = 3\n", "\n", " src_array = WolfArray(srcheader=header)\n", "\n", "\n", " # complete way\n", " src_array.array[0,:] = 0.\n", " src_array.array[-1,:] = 0.\n", " src_array.array[:,0] = 0.\n", " src_array.array[:,-1] = 0.\n", " src_array.mask_data(src_array.nullvalue)\n", "\n", " # or more simply\n", " #src_array.nullify_border(width=1)\n", "\n", " newsim.set_external_border_wolfarray(src_array, mode='contour', abs=True)\n", "\n", "# ***** End of choice *****\n", "\n", "# By default, the polygon coordinates will be translated for the point (Xmin, Ymin) or in (0, 0).\n", "# Translation info in the '.trl' file\n", "# To avoid translation, we can modify the property \"translate_origin2zero\".\n", "newsim.translate_origin2zero = True\n", "\n", "# Choice of fine mesh spatial steps [M].\n", "newsim.set_mesh_fine_size(dx=0.1, dy=0.1)\n", "\n", "# Addition of a block with its specific space step [M].\n", "\n", "# We can define a particular outline or reuse the external outline.\n", "\n", "extern = newsim.external_border\n", "\n", "newsim.add_block(extern, dx=0.2, dy=0.2)\n", "\n", "# (optional) Addition of other blocks ...\n", "\n", "# Meal of the problem\n", "# - Creation of a file without extension (empty) - Useful for retrocompatibility with the previous versions of Wolf.\n", "# - Writing on disk of the mesh description file (. Block)\n", "# - Calculation of the \"fine\" grip (can only be done once all the blocks defined because depends on the maximum spatial resolution of the blocks)\n", "# - Call for Fortran code (mesh phase only) - wolfcli must be defined - command \"Run_wolf2d_Prev\" with argument \"Genfile = '/path/to/file'\"\n", "# - The Fortran will create the files:\n", "# - \".Mnap\" Block mesh and relationships between blocks\n", "# - \".nfo\" Screen outputs from the Fortran code\n", "# - \".xy\" external outline of the mesh (for graphical interface)\n", "# - \".blx\" and \". Bly\" free edges of the MB mesh (useful only for Fortran developers)\n", "# - \".cmd\" Interaction file with Fortran code under calculation\n", "# - Creation of the file \".napbin\" by the Python code (fine grip on which the data must be provided) - will serve as \"mask\" for data matrices\n", "if newsim.mesh():\n", " print('Meshing done !')\n", "else:\n", " print('Meshing failed !')\n", "\n", "# Creation of Data Matrices - Fine grip - Binary format [NP.FLOAT32] - Shape (NBX, NBY)\n", "# - \".top\" Topography file [m]\n", "# - \".hbin\" Initial water height condition [m]\n", "# - \".Qxbin\" Initial specific debit condition according to x [m²/s]\n", "# - \".Qybin\" Initial condition of specific flow according to Y [m²/s]\n", "# - \".frot\" friction coefficient (default law: manning - \"n\" units [s/m^(1/3) - reverse of the 'K' de Strickler]) - Default value: 0.04\n", "# - \".Inf\" infiltration zoning - not to be confused with the \".fil\" file which will contain the values ​​of infiltration flow rates [m³/s]\n", "\n", "# If \"with_Tubulence\" is true, the files \".kbin\" and \".pops\" will be created in addition and will contain turbulent kinetic energy.\n", "newsim.create_fine_arrays(default_frot=0.04, with_tubulence=False)\n", "\n", "\n", "# Research on the edges with potential limits on the basis of the matrix \".napbin\" and writing of files \".sux\" and \".suy\"\n", "# - Research mode: edge separating a masked value of an unseated value - Succesive clogging according to x and y\n", "# -\".Sux\" enumeration of the clues [i, j] of the fine mesh located on the right of an edge oriented according to Y -> [i, j] relating to the edge [I -1/2, j]\n", "#-\".Suy\" list of clues [i, j] of the fine mesh located above an edge oriented according to x-> [i, j] relating to the edge [i, j-1/2]\n", "newsim.create_sux_suy()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Summary of the spatial grip\n", "\n", "It is possible to display information from the fine or MB mesh via \"Get_header\" and/or \"Get_header_mb\"\n", "\n", "https://wolf.hece.uliege.be/autoapi/wolfhece/mesh2d/wolf2dprev/index.html#wolfhece.mesh2d.wolf2dprev.prev_sim2D.get_header\n", "\n", "https://wolf.hece.uliege.be/autoapi/wolfhece/mesh2d/wolf2dprev/index.html#wolfhece.mesh2d.wolf2dprev.prev_sim2D.get_header_MB\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this specific case, shape == (18, 18) because the fine mesh is resolved (0.1, 0.1) and the maximum block size is (0.2, 0.2)\n", "\n", "Or (10x10) for the square domain of (1.0, 1.0) to a resolution of (0.1, 0.1) to which we add a fringe corresponding to (dx_max + 2 * dx_fin) on either side.\n", "\n", "**This fringe is necessary to ensure that there is enough space to store the neighborhood relationships between blocks in the matrices and to keep at least one masked fringe all around.**\n", "\n", "So (10 + 2 * (0.2 + 2 * 0.1) / 0.1, 10 + 2 * (0.2 + 2 * 0.1) / 0.1) = (18, 18)\n", "\n", "The fringe width is also which explains the values ​​of the origin (-0.4, -0.4). This in order to keep (0.0, 0.0) to (xmin, ymin) of the mesh outdoor polygon." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Shape : 18 x 18 \n", "Resolution : 0.1 x 0.1 \n", "Spatial extent : \n", " - Origin : (-0.4 ; -0.4) \n", " - End : (1.4 ; 1.4) \n", " - Widht x Height : 1.8 x 1.8 \n", " - Translation : (0.0 ; 0.0)\n", "Null value : 0.0\n", "\n", "\n" ] } ], "source": [ "print(newsim.get_header())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The same type of information is available in MB." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Shape : 18 x 18 \n", "Resolution : 0.1 x 0.1 \n", "Spatial extent : \n", " - Origin : (-0.4 ; -0.4) \n", " - End : (1.4 ; 1.4) \n", " - Widht x Height : 1.8 x 1.8 \n", " - Translation : (0.0 ; 0.0)\n", "Null value : 0.0\n", "\n", "Number of blocks : 1\n", "\n", "Block block1 : \n", "\n", "Shape : 11 x 11 \n", "Resolution : 0.2 x 0.2 \n", "Spatial extent : \n", " - Origin : (-0.19999999999999996 ; -0.19999999999999996) \n", " - End : (2.0 ; 2.0) \n", " - Widht x Height : 2.2 x 2.2 \n", " - Translation : (-0.4 ; -0.4)\n", "Null value : 0.0\n", "\n", "\n" ] } ], "source": [ "print(newsim.get_header_MB())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A little help on the files, their content and the type of storage" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Text files\n", "----------\n", "Infiltration hydrographs [m³/s] : .fil\n", "Resulting mesh [-] : .mnap\n", "Translation to real world [m] : .trl\n", "\n", "\n", "Fine array - monoblock\n", "----------------------\n", "Mask [-] : .napbin [int16]\n", "Bed Elevation [m] : .top [float32]\n", "Bed Elevation - computed [m] : .topini_fine [float32]\n", "Roughness coefficient [law dependent] : .frot [float32]\n", "Infiltration zone [-] : .inf [int32]\n", "Initial water depth [m] : .hbin [float32]\n", "Initial discharge along X [m^2/s] : .qxbin [float32]\n", "Initial discharge along Y [m^2/s] : .qybin [float32]\n", "Rate of dissipation [m²/s³] : .epsbin [float32]\n", "Turbulent kinetic energy [m²/s²] : .kbin [float32]\n", "Z level under the deck of the bridge [m] : .bridge [float32]\n", "\n", "\n", "Multiblock arrays\n", "-----------------\n", "MB - Bed elevation [m] : .topini [float32]\n", "MB - Water depth [m] : .hbinb [float32]\n", "MB - Discharge X [m²/s] : .qxbinb [float32]\n", "MB - Discharge Y [m²/s] : .qybinb [float32]\n", "MB - Roughness coeff : .frotini [float32]\n", "MB - Rate of dissipation [m²/s³] : .epsbinb [float32]\n", "MB - Turbulent kinetic energy [m²/s²] : .kbinb [float32]\n", "\n" ] } ], "source": [ "print(newsim.help_files())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setting\n", "\n", "When initializing the simulation, default parameter values ​​are defined. They are identical to those imposed by the VB6 code (for retrocompatibility).\n", "\n", "These values ​​are commonly used to obtain a stationary state in pure water. The default temporal diagram is a Runge -Kutta 21 - weights (0.7; 0.3).\n", "\n", "All settings are of course customizable by the user.\n", "\n", "In an attempt to simplify access to values, they are separated between \"active\" values ​​and \"default\" values.\n", "\n", "When active values ​​are accessed, the returned dictionary only contains the parameters whose value differs from default values.\n", "\n", "**This does not mean that the values ​​of other parameters are 0**\n", "\n", "The parameters are split into 2 main categories:\n", "\n", "- global simulation parameters (shared by all blocks)\n", "- specific block parameters\n", "\n", "In the VB6 interface, a separation is made in \"general\" and \"debug\" parameter. This distinction does not exist more facial in python even if the organization of files is in no way changed.\n", "\n", "It will therefore always be possible to operate the VB6 and/or Python interface for the same simulation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Groups\n", "\n", "The different parameters are grouped by theme.\n", "\n", "It is possible to obtain the name of these groups via \"Get_parameters_Groups\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Nombre de groupes de paramètres : 34\n", "Groupe B : 3 ['Boundary conditions', 'Bridge', 'Buildings']\n", "Groupe C : 2 ['Collapsible buildings', 'Computation domain']\n", "Groupe D : 2 ['Danger map', 'Duration of simulation']\n", "Groupe F : 3 ['Forcing', 'Friction', 'Frictional fluid']\n", "Groupe G : 1 ['Geometry']\n", "Groupe I : 5 ['Infiltration', 'Infiltration weir poly3', 'Infiltration weirs', 'Initial condition', 'Initial conditions']\n", "Groupe M : 3 ['Mesher', 'Mobile contour', 'Mobile forcing']\n", "Groupe N : 1 ['Numerical options']\n", "Groupe O : 1 ['Options']\n", "Groupe P : 1 ['Problem']\n", "Groupe R : 2 ['Reconstruction', 'Results']\n", "Groupe S : 4 ['Sediment', 'Spatial scheme', 'Splitting', 'Stopping criteria']\n", "Groupe T : 2 ['Temporal scheme', 'Turbulence']\n", "Groupe U : 1 ['Unsteady topo-bathymetry']\n", "Groupe V : 3 ['VAM5 - Turbulence', 'Variable infiltration', 'Variable infiltration 2']\n" ] } ], "source": [ "groups = newsim.get_parameters_groups() # List of parameter groups - Str - sorted in alphabetical order\n", "\n", "print('Number of parameter groups: ', len(groups))\n", "\n", "# First letter display\n", "\n", "for letter in 'abcdefghijklmnopqrstuvwxyz':\n", "\n", " group = [g for g in groups if g[0].lower() == letter]\n", "\n", " if group:\n", " print(f'Groupe {letter.upper()} : {len(group)}', group)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Settings\n", "\n", "The set of parameters can be obtained via \"Get_parameters_Groups_and_names\" which returns a list of **TUPLES (Group, Param)**.\n", "\n", "It is also possible to list the parameters of a group via \"get_parameters_in_group\".\n", "\n", "The values ​​of the parameters are numeric (int or float). However, it is possible, via Gui, to choose the configuration via more explicit keywords.\n", "\n", "Aid on the parameters can also be obtained via \"help_parameter\" and/or \"help_values_parameter\". The aid is present in the form of a short and potentially long/explicit chain. The first value returned by the \"help_parameter\" function indicates whether the scope is global or on a block." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[('Boundary conditions', 'Nb strong BC (not editable)'), ('Boundary conditions', 'Nb weak BC X (not editable)'), ('Boundary conditions', 'Nb weak BC Y (not editable)'), ('Boundary conditions', 'Unsteady BC'), ('Bridge', 'Activate'), ('Buildings', 'Collapsable'), ('Collapsible buildings', 'H max'), ('Collapsible buildings', 'V max'), ('Collapsible buildings', 'Q max'), ('Computation domain', 'Using tags'), ('Computation domain', 'Strip width for extension'), ('Computation domain', 'Delete unconnected cells every'), ('Danger map', 'Compute'), ('Danger map', 'Minimal water depth'), ('Duration of simulation', 'Total steps'), ('Duration of simulation', 'Time step'), ('Forcing', 'Activate'), ('Friction', 'Global friction coefficient'), ('Friction', 'Lateral Manning coefficient'), ('Friction', 'Surface computation method'), ('Frictional fluid', 'Density of the fluid'), ('Frictional fluid', 'Saturated height'), ('Frictional fluid', 'Consolidation coefficient'), ('Frictional fluid', 'Interstitial pressure (t=0)'), ('Geometry', 'Dx'), ('Geometry', 'Dy'), ('Geometry', 'Nx'), ('Geometry', 'Ny'), ('Geometry', 'Origin X'), ('Geometry', 'Origin Y'), ('Infiltration', 'Forced correction ux'), ('Infiltration', 'Forced correction vy'), ('Infiltration weir poly3', 'a'), ('Infiltration weir poly3', 'b'), ('Infiltration weir poly3', 'c'), ('Infiltration weir poly3', 'd'), ('Infiltration weirs', 'Cd'), ('Infiltration weirs', 'Z'), ('Infiltration weirs', 'L'), ('Initial condition', 'To egalize'), ('Initial condition', 'Water level to egalize'), ('Initial conditions', 'Reading mode'), ('Mesher', 'Mesh only'), ('Mesher', 'Remeshing mode'), ('Mesher', 'Number of blocks (not editable)'), ('Mobile contour', 'Active'), ('Mobile forcing', 'Activate'), ('Numerical options', 'Water depth min for division'), ('Numerical options', 'Water depth min'), ('Numerical options', 'Water depth min to compute'), ('Numerical options', 'Exponent Q null on borders'), ('Numerical options', 'Reconstruction slope mode'), ('Numerical options', 'H computation mode (deprecated)'), ('Numerical options', 'Latitude position'), ('Numerical options', 'Troncature (deprecated)'), ('Numerical options', 'Smoothing mode (deprecated)'), ('Options', 'Topography'), ('Options', 'Friction slope'), ('Options', 'Modified infiltration'), ('Options', 'Reference water level for infiltration'), ('Options', 'Inclined axes'), ('Options', 'Variable topography'), ('Problem', 'Number of unknowns'), ('Problem', 'Number of equations'), ('Problem', 'Unequal speed distribution'), ('Problem', 'Conflict resolution'), ('Problem', 'Fixed/Evolutive domain'), ('Reconstruction', 'Reconstruction method'), ('Reconstruction', 'Interblocks reconstruction method'), ('Reconstruction', 'Free border reconstruction method'), ('Reconstruction', 'Number of neighbors'), ('Reconstruction', 'Limit water depth or water level'), ('Reconstruction', 'Frontier'), ('Reconstruction', 'Froude maximum'), ('Results', 'Writing interval'), ('Results', 'Writing interval mode'), ('Results', 'Writing mode'), ('Results', 'Only one result'), ('Sediment', 'Porosity'), ('Sediment', 'Mean diameter'), ('Sediment', 'Relative density'), ('Sediment', 'Theta critical velocity'), ('Sediment', 'Drifting model'), ('Sediment', 'Convergence criteria - bottom'), ('Sediment', 'Convergence criteria - sediment'), ('Sediment', 'Model type'), ('Sediment', 'Active infiltration'), ('Sediment', 'Write topography'), ('Sediment', 'Hmin for computation'), ('Sediment', 'With gravity discharge'), ('Sediment', 'Critical slope'), ('Sediment', 'Natural slope'), ('Sediment', 'Reduction slope'), ('Sediment', 'D30'), ('Sediment', 'D90'), ('Spatial scheme', 'Limiter type'), ('Spatial scheme', 'Venkatakrishnan k'), ('Spatial scheme', 'Wetting-Drying mode'), ('Spatial scheme', 'Non-erodible area'), ('Splitting', 'Splitting type'), ('Stopping criteria', 'Stop computation on'), ('Stopping criteria', 'Epsilon'), ('Temporal scheme', 'Runge-Kutta'), ('Temporal scheme', 'Courant number'), ('Temporal scheme', 'Factor for verification'), ('Temporal scheme', 'Optimized time step'), ('Temporal scheme', 'Mac Cormack (deprecated)'), ('Temporal scheme', 'Local time step factor'), ('Turbulence', 'Model type'), ('Turbulence', 'alpha coefficient'), ('Turbulence', 'Kinematic viscosity'), ('Turbulence', 'Maximum value of the turbulent viscosity'), ('Turbulence', 'C3E coefficient'), ('Turbulence', 'CLK coefficient'), ('Turbulence', 'CLE coefficient'), ('Unsteady topo-bathymetry', 'Model type'), ('VAM5 - Turbulence', 'Vertical viscosity'), ('VAM5 - Turbulence', 'Model type'), ('Variable infiltration', 'a'), ('Variable infiltration', 'b'), ('Variable infiltration', 'c'), ('Variable infiltration 2', 'd'), ('Variable infiltration 2', 'e')]\n" ] } ], "source": [ "all_params = newsim.get_parameters_groups_and_names() # List of parameter groups and parameters - sorted in alphabetical order\n", "\n", "print(all_params)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['Global friction coefficient', 'Lateral Manning coefficient', 'Surface computation method']\n" ] } ], "source": [ "params = newsim.get_parameters_in_group('Friction') # List of group 'friction' parameters\n", "\n", "print(params)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Examples of help on:\n", "\n", "- A block parameter\n", "- A global parameter" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "ERROR:root:Group duration or parameter total steps not found\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Global or Block : Block\n", "Aide courte :\t Number of unknowns (integer) - default = 4\n", "Aide complète :\t If a turbulence model is selected, the number of unknowns will be increased by the computation code accordingly to the number of additional equations\n", "\n", "Global or Block : -\n", "Aide courte :\t -\n", "Aide complète :\t -\n" ] } ], "source": [ "target, comment, full_comment = newsim.help_parameter('problem', 'Number of unknowns')\n", "\n", "print('Global or Block : ', target)\n", "print('Aide courte :\\t', comment)\n", "print('Aide complète :\\t', full_comment)\n", "\n", "print()\n", "\n", "target, comment, full_comment = newsim.help_parameter('duration', 'total steps')\n", "\n", "print('Global or Block : ', target)\n", "print('Aide courte :\\t', comment)\n", "print('Aide complète :\\t', full_comment)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Valeurs possibles : \n", "\n", "Horizontal 0\n", "Modified surface corrected 2D (HECE) 6\n", "Modified surface corrected 2D + Lateral external borders (HECE) 7\n", "Horizontal and Lateral external borders 1\n", "Modified surface (slope) 2\n", "Modified surface (slope) + Lateral external borders 3\n", "Horizontal and Lateral external borders (HECE) 4\n", "Modified surface (slope) + Lateral external borders (HECE) 5\n", "Horizontal -- Bathurst -2\n", "Horizontal -- Bathurst-Colebrook -5\n", "Horizontal -- Chezy -1\n", "Horizontal -- Colebrook -3\n", "Horizontal -- Barr -4\n", "Horizontal -- Bingham -6\n", "Horizontal -- Frictional fluid -61\n", "Horizontal and Lateral external borders (Colebrook) -34\n", "Horizontal and Lateral external borders (Barr) -44\n" ] } ], "source": [ "vals = newsim.help_values_parameter('friction', 'Surface computation method')\n", "\n", "if vals is not None:\n", " print('Valeurs possibles : \\n')\n", " for key, vals in vals.items():\n", " print(key, vals)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Tolerance to the failure of breakage**\n", "\n", "A certain tolerance is authorized in writing groups and parameters.\n", "\n", "A function \"sanitize_group_name\" allows you to try to find the information encoded.\n", "\n", "It is recommended to use it to check your script." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "ERROR:root:Group friTION or parameter SurFAce computation methOD not found\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Cet exemple va fonctionner car seule une erreur de casses est corrigée.\n", "\n", "Group : Friction\n", "Name : Surface computation method\n", "\n", "Cet exemple ne va pas fonctionner car une erreur de frappe est présente dans le groupe.\n", "\n", "Group : None\n", "Name : Surface computation method\n" ] } ], "source": [ "# OK\n", "print('This example will work because only a breakage error is corrected.\\n')\n", "\n", "group1, name1 = newsim.sanitize_group_name('fricTION', 'SurFAce computation methOD')\n", "\n", "assert group1 == 'Friction'\n", "assert name1 == 'Surface computation method'\n", "\n", "print('Group : ', group1)\n", "print('Name : ', name1)\n", "\n", "# KO\n", "print('\\nThis example will not work because a striking error is present in the group.\\n')\n", "\n", "group2, name2 = newsim.sanitize_group_name('friTION', 'SurFAce computation methOD')\n", "\n", "assert group2 is None\n", "assert name2 == 'Surface computation method'\n", "\n", "print('Group : ', group2)\n", "print('Name : ', name2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### List of active settings" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'Geometry': {'Dx': 0.1,\n", " 'Dy': 0.1,\n", " 'Nx': 18,\n", " 'Ny': 18,\n", " 'Origin X': -0.4,\n", " 'Origin Y': -0.4},\n", " 'Block 0': {}}" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Recovery of a dictionnaiore with all the active parameters of the simulation, that is to say those which are different from the default values\n", "newsim.get_active_parameters_extended() # -- Extended to also obtain all block settings" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### List of all settings" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Nombre de groupes de paramètres : 11\n", "Nombre de paramètres : 57\n" ] } ], "source": [ "all = newsim.get_all_parameters()\n", "\n", "print('Number of parameter groups : ', len(all))\n", "print('Number of parameters : ', sum([len(p) for p in all.values()]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Imposing a parameter\n", "\n", "The modification of the value of an individual parameter can be done via \"set_parameter\" which takes as arguments:\n", "\n", "- The name of the group\n", "- The name of the parameter\n", "- The value (int or float)\n", "-The block index (1-based) if it is a block parameter-a value of **-1** or **'all'** will impose the same parameter value on all **current blocks** present in the simulation" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3\n", "--\n", "Tous les paramètres :\n", "3\n" ] } ], "source": [ "\n", "group, name = newsim.sanitize_group_name('friction', 'Surface computation method')\n", "newsim.set_parameter(group, name, value = 3, block = 1)\n", "\n", "active = newsim.get_active_parameters_block(1) # dictionnaire des paramètres actifs du bloc 1\n", "\n", "if group not in active:\n", " print('Le groupe n\\'est pas dans les paramètres actifs.')\n", "else:\n", " if name not in active[group]:\n", " print('Le groupe existe mais Le paramètre a sa valeur par défaut')\n", " else:\n", " print(active[group][name])\n", "\n", "print('--')\n", "\n", "all = newsim.get_all_parameters_block(1) # dictionnaire de tous les paramètres du bloc 1\n", "\n", "print('Tous les paramètres :')\n", "print(all[group][name])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For regulars of the VB6 code, specialists and nostalgic, it is also possible to work on the basis of lists of \"general\" and \"debug\" parameters.\n", "\n", "To do this, you must use \"Get_parameters_from_List\" and \"Set_parameters_from_list\"." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Nombre de paramètres Globaux/Généraux: 36\n", "Nombre de paramètres Globaux/Debug: 60\n", "Nombre de paramètres de Bloc/Généraux: 23\n", "Nombre de paramètres de Bloc/Debug: 60\n" ] } ], "source": [ "glob_gen = newsim.get_parameters_from_list('Global', 'General')\n", "glob_dbg = newsim.get_parameters_from_list('Global', 'Debug')\n", "\n", "print('Number of global/general parameters: ', len(glob_gen))\n", "print('Number of global parameters/debug: ', len(glob_dbg))\n", "\n", "block_gen = newsim.get_parameters_from_list('Block', 'General', 1)\n", "block_dbg = newsim.get_parameters_from_list('Block', 'Debug', 1)\n", "\n", "print('Number of block/general parameters: ', len(block_gen))\n", "print('Number of Block/Debug settings: ', len(block_dbg))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The association with group names and parameters is obtained via \"Get_Group_Name_from_List\"." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Groupe \"Duration of simulation\" : Param \"Total steps\"\n" ] } ], "source": [ "glob_gen_key = newsim.get_group_name_from_list('Global', 'General')\n", "glob_dbg_ket = newsim.get_group_name_from_list('Global', 'Debug')\n", "block_gen_key = newsim.get_group_name_from_list('Block', 'General')\n", "block_dbg_key = newsim.get_group_name_from_list('Block', 'Debug')\n", "\n", "def print_group_param(target:Literal['Global', 'Block'],\n", " which:Literal['General', 'Debug'],\n", " idx:int):\n", "\n", " if target == 'Global':\n", " if which == 'General':\n", " print(f'Groupe \"{glob_gen_key[idx-1][0]}\" : Param \"{glob_gen_key[idx-1][1]}\"')\n", " else:\n", " print(f'Groupe \"{glob_dbg_ket[idx-1][0]}\" : Param \"{glob_dbg_ket[idx-1][1]}\"')\n", " else:\n", " if which == 'General':\n", " print(f'Groupe \"{block_gen_key[idx-1][0]}\" : Param \"{block_gen_key[idx-1][1]}\"')\n", " else:\n", " print(f'Groupe \"{block_dbg_key[idx-1][0]}\" : Param \"{block_dbg_key[idx-1][1]}\"')\n", "\n", "print_group_param('Global', 'General', 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Typage of the settings\n", "\n", "The parameters are whole or floating.\n", "\n", "The expected type is specified in the help/comment associated with each paameter.\n", "\n", "During the imposition of value, a conversion is forced into the right type.\n", "\n", "If an error occurs, first check your code before shouting at WOLF. ;-)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Settings (very) frequently used/defined\n", "\n", "A list of the most frequent parameters are available via \"Get_Frequent_parameters\"." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " Renvoi des paramètres de simulation fréquents\n", "\n", " Les valeurs retournées sont :\n", " - les groupes et noms des paramètres globaux\n", " - les groupes et noms des paramètres de blocs\n", " - les indices des paramètres globaux (generaux et debug) et de blocs (generaux et debug)\n", "\n", " \n", "Paramètres globaux/généraux fréquents : [('Duration of simulation', 'Total steps'), ('Results', 'Writing interval'), ('Results', 'Writing interval mode'), ('Initial conditions', 'Reading mode'), ('Temporal scheme', 'Runge-Kutta'), ('Temporal scheme', 'Courant number'), ('Spatial scheme', 'Wetting-Drying mode'), ('Computation domain', 'Delete unconnected cells every')]\n", "Paramètres de bloc fréquents : [('Reconstruction', 'Froude maximum'), ('Problem', 'Conflict resolution'), ('Problem', 'Fixed/Evolutive domain'), ('Options', 'Friction slope'), ('Options', 'Modified infiltration'), ('Options', 'Reference water level for infiltration'), ('Turbulence', 'Model type'), ('Turbulence', 'alpha coefficient'), ('Turbulence', 'Kinematic viscosity'), ('Not used', '4'), ('Variable infiltration', 'a'), ('Variable infiltration', 'b'), ('Variable infiltration', 'c'), ('Friction', 'Lateral Manning coefficient'), ('Friction', 'Surface computation method'), ('Danger map', 'Compute'), ('Danger map', 'Minimal water depth'), ('Bridge', 'Activate'), ('Infiltration weirs', 'Cd'), ('Infiltration weirs', 'Z'), ('Variable infiltration 2', 'd'), ('Variable infiltration 2', 'e'), ('Infiltration weirs', 'L'), ('Turbulence', 'Maximum value of the turbulent viscosity'), ('Infiltration weir poly3', 'a'), ('Infiltration weir poly3', 'b'), ('Infiltration weir poly3', 'c'), ('Infiltration weir poly3', 'd'), ('Turbulence', 'C3E coefficient'), ('Turbulence', 'CLK coefficient'), ('Turbulence', 'CLE coefficient')]\n" ] } ], "source": [ "print(newsim.get_frequent_parameters.__doc__)\n", "\n", "freq_glob, freq_block, (idx_glog_gen, idx_glob_dbg, idx_bl_gen, idx_bl_dbg) = newsim.get_frequent_parameters()\n", "\n", "print('Paramètres globaux/généraux fréquents : ', freq_glob)\n", "print('Paramètres de bloc fréquents : ', freq_block)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### To look more ..." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " Useful functions/routines for parameters manipulation\n", "\n", " :return (ret, dict) : ret is a string with the description of the function, dict is a dictionary with the function names sorted by category (Global, Block) and type (set, get, reset, check)\n", "\n", " \n", "Useful functions can be found to set, get, reset and check parameters.\n", "\n", "Here is a list of implemented functions :\n", "\n", "Setter in global parameters\n", "***************************\n", "\n", " set_params_geometry\n", " set_params_time_iterations\n", " set_params_temporal_scheme\n", " set_params_collapsible_building\n", "\n", "Getter in global parameters\n", "***************************\n", "\n", " get_params_time_iterations\n", " get_params_temporal_scheme\n", " get_params_collapsible_building\n", "\n", "Setter in block parameters\n", "**************************\n", "\n", " set_params_topography_operator\n", " set_params_reconstruction_type\n", " set_params_flux_type\n", " set_params_froud_max\n", " set_params_conflict_resolution\n", " set_params_sediment\n", " set_params_gravity_discharge\n", " set_params_steady_sediment\n", " set_params_unsteady_topo_bathymetry\n", " set_params_collapse_building\n", " set_params_mobile_contour\n", " set_params_mobile_forcing\n", " set_params_bridges\n", " set_params_danger_map\n", " set_params_surface_friction\n", " set_params_turbulence\n", " set_params_vam5_turbulence\n", " set_params_infiltration_momentum_correction\n", " set_params_infiltration_bridge\n", " set_params_infiltration_weir\n", " set_params_infiltration_weir_poly3\n", " set_params_infiltration_polynomial2\n", " set_params_infiltration_power\n", " set_params_bingham_model\n", " set_params_frictional_model\n", "\n", "Getter in block parameters\n", "\n", "**************************\n", "\n", " get_params_topography_operator\n", " get_params_reconstruction_type\n", " get_params_flux_type\n", " get_params_froud_max\n", " get_params_conflict_resolution\n", " get_params_sediment\n", " get_params_gravity_discharge\n", " get_params_steady_sediment\n", " get_params_unsteady_topo_bathymetry\n", " get_params_collapse_building\n", " get_params_mobile_contour\n", " get_params_bridges\n", " get_params_danger_maps\n", " get_params_surface_friction\n", " get_params_turbulence\n", " get_params_vam5_turbulence\n", " get_params_infiltration\n", " get_params_infiltration_momentum_correction\n", " get_params_frictional\n", "\n", "Resetter in global parameters\n", "\n", "*****************************\n", "\n", " reset_params_time_iterations\n", " reset_params_temporal_scheme\n", "\n", "Resetter in block parameters\n", "\n", "****************************\n", "\n", " reset_params_topography_operator\n", " reset_params_reconstruction_type\n", " reset_params_flux_type\n", " reset_params_froud_max\n", " reset_params_conflict_resolution\n", " reset_params_sediment\n", " reset_params_gravity_discharge\n", " reset_params_steady_sediment\n", " reset_params_unsteady_topo_bathymetry\n", " reset_params_collapse_building\n", " reset_params_mobile_contour\n", " reset_params_mobile_forcing\n", " reset_params_bridges\n", " reset_params_danger_map\n", " reset_params_surface_friction\n", " reset_params_turbulence\n", " reset_params_vam5_turbulence\n", " reset_params_infiltration_momentum_correction\n", " reset_params_infiltration_bridges\n", " reset_params_infiltration_weir\n", " reset_params_infiltration_weir_poly3\n", " reset_params_infiltration_polynomial2\n", " reset_params_infiltration_power\n", " reset_params_bingham_model\n", " reset_params_frictional_model\n", "\n", "Checker in global parameters\n", "\n", "****************************\n", "\n", " check_params_time_iterations\n", " check_params_temporal_scheme\n", " check_params_collapsible_building\n", "\n", "Checker in block parameters\n", "\n", "***************************\n", "\n", " check_params_topography_operator\n", " check_params_reconstruction_type\n", " check_params_flux_type\n", " check_params_froud_max\n", " check_params_conflict_resolution\n", " check_params_sediment\n", " check_params_gravity_discharge\n", " check_params_steady_sediment\n", " check_params_unsteady_topo_bathymetry\n", " check_params_collapse_building\n", " check_params_mobile_contour\n", " check_params_mobile_forcing\n", " check_params_forcing\n", " check_params_bridges\n", " check_params_danger_map\n", " check_params_turbulence\n", " check_params_infiltration\n", "\n" ] } ], "source": [ "print(newsim.help_useful_fct.__doc__)\n", "print(newsim.help_useful_fct()[0])" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dict_keys(['Global', 'Block'])\n", "dict_keys(['set', 'get', 'reset', 'check'])\n", "['set_params_topography_operator', 'set_params_reconstruction_type', 'set_params_flux_type', 'set_params_froud_max', 'set_params_conflict_resolution', 'set_params_sediment', 'set_params_gravity_discharge', 'set_params_steady_sediment', 'set_params_unsteady_topo_bathymetry', 'set_params_collapse_building', 'set_params_mobile_contour', 'set_params_mobile_forcing', 'set_params_bridges', 'set_params_danger_map', 'set_params_surface_friction', 'set_params_turbulence', 'set_params_vam5_turbulence', 'set_params_infiltration_momentum_correction', 'set_params_infiltration_bridge', 'set_params_infiltration_weir', 'set_params_infiltration_weir_poly3', 'set_params_infiltration_polynomial2', 'set_params_infiltration_power', 'set_params_bingham_model', 'set_params_frictional_model']\n" ] } ], "source": [ "fct_names = newsim.help_useful_fct()[1]\n", "\n", "print(fct_names.keys())\n", "print(fct_names['Global'].keys())\n", "print(fct_names['Block']['set'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"Global\" functions can be called via the simulation body and the \"parameter\" attribute.\n", "\n", "The block functions can be called via the simulation instance and the attribute \"Parameters.Blocks [i]\" where **I** is the block key **(0-based, as it is a Python list)**." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " Set the mesher only flag\n", "\n", " When launched, the Fortran program will only generate the mesh and stop.\n", "\n", " \n" ] } ], "source": [ "# Example of using a \"global\" set function\n", "\n", "print(newsim.parameters.set_mesh_only.__doc__)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " Définit le Froude maximum\n", "\n", " Si, localement, le Froude maximum est dépassé, le code limitera\n", " les inconnues de débit spécifique à la valeur du Froude maximum\n", " en conservant inchangée la hauteur d'eau.\n", "\n", " Valeur par défaut : 20.\n", "\n", " \n", "\n", " Définit le Froude maximum\n", "\n", " Si, localement, le Froude maximum est dépassé, le code limitera\n", " les inconnues de débit spécifique à la valeur du Froude maximum\n", " en conservant inchangée la hauteur d'eau.\n", "\n", " Valeur par défaut : 20.\n", "\n", " \n", "Old value : 20.0\n", "New value : 1.5\n" ] } ], "source": [ "# Example of using a \"block\" set function from the object \"prev_sim2d\" and its attribute \"parameters\"\n", "print(newsim.parameters.blocks[0].set_params_froud_max.__doc__)\n", "\n", "# Example of using a \"block\" set function directly from the object \"prev_sim2d\" -- remark (1-based)\n", "print(newsim[1].set_params_froud_max.__doc__)\n", "\n", "# Closure on the blocks - Use of the class iterator \"PREV_SIM2D\"\n", "for curblock in newsim:\n", " print('Old value : ', curblock.get_params_froud_max())\n", " curblock.set_params_froud_max(1.5)\n", " print('New value : ', curblock.get_params_froud_max())\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### for the simulation to be implemented ..." ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "newsim.parameters.set_params_time_iterations(nb_timesteps= 1000, optimize_timestep=True, writing_frequency=1, writing_mode='Iterations', initial_cond_reading_mode='Binary', writing_type='Binary compressed')\n", "newsim.parameters.set_params_temporal_scheme(RungeKutta='RK21', CourantNumber=0.35)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'RungeKutta': 0.3, 'CourantNumber': 0.35, 'dt_factor': 100.0}" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "newsim.parameters.get_params_temporal_scheme()" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'nb_timesteps': 1000,\n", " 'optimize_timestep': 1,\n", " 'first_timestep_duration': 0.1,\n", " 'writing_frequency': 1,\n", " 'writing_mode': 'Iterations',\n", " 'writing_type': 'Binary compressed',\n", " 'initial_cond_reading_mode': 'Binary',\n", " 'writing_force_onlyonestep': 0}" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "newsim.parameters.get_params_time_iterations()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Checks" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n" ] } ], "source": [ "# Set bad RK value for testing purpose -- If you want, you can decomment the following line\n", "# newsim.set_parameter('Temporal scheme', 'Runge-Kutta', value = -.5)\n", "\n", "# Plusieurs niveaux de vebrosité sont disponibles:\n", "# - 0 : Erreurs uniquement\n", "# - 1 : Erreurs et Warnings\n", "# - 2 : Erreurs, Warnings et Informations\n", "# - 3 : 2 + en-têtes de sections\n", "print(newsim.check_all(verbosity= 0))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Using a graphical interface from the jupyter\n", "\n", "It is possible to operate WX widgets from a jupyter notebook. To do this, you must first add a WX event management loop to the notebook via \"%Gui WX\". Without this, events (click mouse, ...) will not be captured." ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [], "source": [ "%gui wx" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can then ask the simulation object to display the properties window:\n", "- global\n", "- for a specific block\n", "\n", "The active parameters will only be displayed if their value is different from the default value ** or ** if the option \"show_in_active_if_default\" is in True." ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": [ "newsim.parameters.show() # == newsim[0].show()\n", "newsim[1].show(show_in_active_if_default = True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Manipulation of parameters can be done indistinctly from the notebook or graphical interface.\n", "\n", "A modification from the notebook will force the update of the graphic window and vice versa (after clicking on \"apply changes\")." ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "ERROR:root:Group duration or parameter total steps not found\n", "ERROR:root:Parameter duration - total steps not found\n", "ERROR:root:Group not found in parameters\n" ] } ], "source": [ "newsim.get_parameter('duration', 'total steps')" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "ERROR:root:Group duration or parameter time step not found\n", "ERROR:root:Parameter duration - time step not found\n" ] } ], "source": [ "newsim.set_parameter('duration', 'time step',.2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Boundary conditions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Types of Boundary conditions available in the code" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Types of boundary conditions\n", "---------------------------\n", "Key : H - Associacted value : 1 - Water level [m]\n", "Key : QX - Associacted value : 2 - Flow rate along X [m²/s]\n", "Key : QY - Associacted value : 3 - Flow rate along Y [m²/s]\n", "Key : NONE - Associacted value : 4 - None\n", "Key : QBX - Associacted value : 5 - Sediment flow rate along X [m²/s]\n", "Key : QBY - Associacted value : 6 - Sediment flow rate along Y [m²/s]\n", "Key : HMOD - Associacted value : 7 - Water level [m] / impervious if entry point\n", "Key : FROUDE_NORMAL - Associacted value : 8 - Froude normal to the border [-]\n", "Key : ALT1 - Associacted value : 9 - to check\n", "Key : ALT2 - Associacted value : 10 - to check\n", "Key : ALT3 - Associacted value : 11 - to check\n", "Key : DOMAINE_BAS_GAUCHE - Associacted value : 12 - to check\n", "Key : DOMAINE_DROITE_HAUT - Associacted value : 13 - to check\n", "Key : SPEED_X - Associacted value : 14 - Speed along X [m/s]\n", "Key : SPEED_Y - Associacted value : 15 - Speed along Y [m/s]\n", "Key : FROUDE_ABSOLUTE - Associacted value : 16 - norm of Froude in the cell [-]\n", "\n" ] } ], "source": [ "print(newsim.help_bc_type())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Listing\n", "\n", "The list of boundary conditions can be obtained via \"list_pot_bc_x\" and \"list_pot_bc_y\"\n", "\n", "The return of these routines consist of a list of 2 numpy vectors [np.int32]. It is therefore quite easy to perform sorts or other action to select certain edges.\n", "\n", "- ret[0] = indices i\n", "- ret[1] = indices j\n", "\n", "**These edges are numbered according to the Fortran Convention, namely 1-based**" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "bcx = newsim.list_pot_bc_x()\n", "bcy = newsim.list_pot_bc_y()" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Liste des indices i (1-based) - bord X : [ 5 5 5 5 5 5 5 5 5 5 15 15 15 15 15 15 15 15 15 15]\n", "Liste des indices j (1-based) - bord X : [ 5 6 7 8 9 10 11 12 13 14 5 6 7 8 9 10 11 12 13 14]\n", "Liste des indices i (1-based) - bord Y : [ 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14]\n", "Liste des indices j (1-based) - bord Y : [ 5 15 5 15 5 15 5 15 5 15 5 15 5 15 5 15 5 15 5 15]\n" ] } ], "source": [ "print('Liste des indices i (1-based) - bord X :', bcx[0])\n", "print('Liste des indices j (1-based) - bord X :', bcx[1])\n", "print('Liste des indices i (1-based) - bord Y :', bcy[0])\n", "print('Liste des indices j (1-based) - bord Y :', bcy[1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A small visualization with Matplotlib ...\n", "\n", "Please note: Matplotlib and WX are not necessarily the best friends in a notebook. The following 2 blocks are commented to avoid conflicts." ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [], "source": [ "# # %matplotlib widget\n", "# %matplotlib inline\n", "\n", "# fig, ax = newsim.plot_borders(xy_or_ij='xy', xcolor='b', ycolor='r')\n", "# ax.set_xticks(np.arange(newsim.origx, newsim.endx, newsim.dx))\n", "# ax.set_yticks(np.arange(newsim.origy, newsim.endy, newsim.dy))\n", "# ax.grid()\n" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "# fig, ax = newsim.plot_borders(xy_or_ij='ij', xcolor='black', ycolor='orange')\n", "# ax.set_xticks(np.arange(0.5, newsim.nbx+1.5, 1))\n", "# ax.set_yticks(np.arange(0.5, newsim.nby+1.5, 1))\n", "# ax.grid()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Imposition d'une condition faible\n", "\n", "Il est possible d'imposer une condition faible via les routines \"add_weak_bc_x\" et\"add_weak_bc_y\".\n", "\n", "Il faut préciser en argument :\n", " - les indices (i,j) tels que disponibles dans les listes précédentes\n", " - le type de BC\n", " - la valeur (peu importe cette valeur pour NONE à l'exception de 99999. qui est l'équivalent d'une valeur nulle dans les versions précédentes)\n" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "# une valeur à la fois\n", "# newsim.add_weak_bc_x(i = 15, j = 5, ntype = BCType_2D.H, value = 1.0)\n", "\n", "# ou via des boucles, tout est possible !\n", "for j in range(5,15):\n", " newsim.add_weak_bc_x(i = 15, j = j, ntype = BCType_2D.H, value = 1.0)\n", "\n", "for j in range(5,15):\n", " newsim.add_weak_bc_x(i = 5, j = j, ntype = BCType_2D.QX, value = 1.0)\n", " newsim.add_weak_bc_x(i = 5, j = j, ntype = BCType_2D.QY, value = 0.0)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Autre fonction ...\n", "\n", "Il est possible d'utiliser une autre syntexe plus proche de ce qui est disponible dans le code GPU.\n", "\n", "Cette routine n'est cependant rien d'autre d'une redirection vers les routines précédentes." ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "newsim.reset_all_boundary_conditions()\n", "\n", "# ou via des boucles, tout est possible !\n", "for j in range(5,15):\n", " newsim.add_boundary_condition(i = 15, j = j, bc_type = BCType_2D.H, bc_value = 1.0, border=Direction.X)\n", "\n", "for j in range(5,15):\n", " newsim.add_boundary_condition(i = 5, j = j, bc_type = BCType_2D.QX, bc_value = 1.0, border=Direction.X)\n", " newsim.add_boundary_condition(i = 5, j = j, bc_type = BCType_2D.QY, bc_value = 0.0, border=Direction.X)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Listing of CL according to each axis:\n", "\n", "- CL name\n", "- List the clues\n", "- Get a list of objects \"Boundary_Condition_2d\" - https://wolf.hece.uliege.be/autoapi/wolfgpu/simple_simulation/index.html#wolfgpu.simple_simulation.boundary_condition_2d\n", "- Check the existence or not\n", "- Change the value and/or the type\n", "- Remove a condition imposed previously" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Nb CL selon X : 30\n", "Nb CL selon Y : 0\n" ] } ], "source": [ "print('Nb CL selon X : ', newsim.nb_weak_bc_x)\n", "print('Nb CL selon Y : ', newsim.nb_weak_bc_y)" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "i : [15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]\n", "j : [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14]\n" ] } ], "source": [ "i,j = newsim.list_bc_x_ij()\n", "print('i : ', i)\n", "print('j : ', j)" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "i : [15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]\n", "j : [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14]\n" ] } ], "source": [ "# Même chose que précédemment mais selon une autre approche\n", "\n", "all_bc = newsim.list_bc()\n", "\n", "# all_bc[0] # bc along X\n", "# all_bc[1] # bc along Y\n", "\n", "i = [curbc.i for curbc in all_bc[0]]\n", "j = [curbc.j for curbc in all_bc[0]]\n", "print('i : ', i)\n", "print('j : ', j)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vérification de l'existence en un bord spécifique\n", "\n", "Décommenter les blocs ci-dessous au besoin" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [], "source": [ "# print('Test en (15,5) : ', newsim.exists_weak_bc_x(i = 15, j = 5))\n", "# print('Test en (16,5) : ', newsim.exists_weak_bc_x(i = 16, j = 5))\n", "# print('Test en (5,5) : ', newsim.exists_weak_bc_x(i = 5, j = 5))\n", "\n", "# if newsim.exists_weak_bc_x(i = 15, j = 5):\n", "# # Même si la valeur renvoyée est un entier (le nombre de BC existante à cet indice), il est possible de l'utiliser dans un test\n", "# newsim.remove_weak_bc_x(i = 15, j = 5)\n", "# assert newsim.exists_weak_bc_x(i = 15, j = 5) ==0, 'Erreur de suppression'" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [], "source": [ "# # remove enlève toutes les CL sur un bord\n", "# print('Nb total avant remove : ', newsim.nb_weak_bc_x)\n", "# assert newsim.nb_weak_bc_x ==29, 'Erreur de comptage - relancer le code ?'\n", "\n", "# print('Nb selon X avant remove : ', len(newsim.get_bc_x(5,5)))\n", "# newsim.remove_weak_bc_x(i = 5, j = 5)\n", "\n", "# assert newsim.exists_weak_bc_x(i = 5, j = 5) ==0, 'Erreur de suppression'\n", "# print('Nb selon X après remove : ', newsim.exists_weak_bc_x(5,5))\n" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [], "source": [ "# bc = newsim.get_bc_x(i = 15, j = 5)\n", "\n", "# print('Nombre de BC : ', len(bc))\n", "# for curbc in bc:\n", "# print('Type : ', curbc.ntype)\n", "# print('Type : ', revert_bc_type(BCType_2D, curbc.ntype))\n", "# print('Value : ', curbc.val)\n", "\n", "\n", "# bc = newsim.get_bc_x(i = 5, j = 5)\n", "\n", "# print()\n", "# print('Nombre de BC : ', len(bc))\n", "# for curbc in bc:\n", "# print('Type : ', curbc.ntype)\n", "# print('Type : ', revert_bc_type(BCType_2D, curbc.ntype))\n", "# print('Value : ', curbc.val)\n" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [], "source": [ "# print('Test 1')\n", "# i,j = 5,6\n", "# if newsim.exists_weak_bc_x(i,j) == 1 :\n", "\n", "# print('Ancienne valeur : ', newsim.get_bc_x(i,j)[0].val)\n", "# newsim.change_weak_bc_x(i = i, j = j, ntype = BCType_2D.QX, value = 2.0)\n", "# print('Nouvelle valeur : ', newsim.get_bc_x(i,j)[0].val)\n", "\n", "# else:\n", "# print(\"Impossible de changer une valeur car plus d'une condition sur le même bord\")\n", "# print('Suppression des conditions')\n", "\n", "# newsim.remove_weak_bc_x(i = i, j = j)\n", "\n", "# print('\\nTest 2')\n", "# i,j = 15,6\n", "# if newsim.exists_weak_bc_x(i,j) == 1 :\n", "\n", "# print('Ancienne valeur : ', newsim.get_bc_x(i,j)[0].val)\n", "# newsim.change_weak_bc_x(i = i, j = j, ntype = BCType_2D.H, value = 2.0)\n", "# print('Nouvelle valeur : ', newsim.get_bc_x(i,j)[0].val)\n", "\n", "# else:\n", "# print(\"Impossible de changer une valeur car plus d'une condition sur le même bord\")\n", "# print('Suppreesion des conditions')\n", "\n", "# newsim.remove_weak_bc_x(i = i, j = j)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Backup on disk\n", "\n", "The parameters and boundary conditions can be saved on disk in the file \".par\" via the \"Save\" method.\n", "\n", "Writing on disk can therefore only be valid **after** having defined both the useful parameters and the BCs of the problem." ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:root:No infiltration data to write\n" ] } ], "source": [ "newsim.save()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Conditions initiales / Données" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is possible to easily read data via \"Read_fine_array\" or \"Read_mb_array\" by passing it in argument the extension of the file.\n", "\n", "THE '.' extension is optional but advised more readability. ;-)\n", "\n", "The return is in WolfArray or WolfArrayMB. https://wolf.hece.uliege.be/autoapi/wolfhece/wolf_array/index.html" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Comparaison des caractéristiques de matrice : True\n", "Comparaison des valeurs : True\n", "Comparaison des masques : True\n" ] } ], "source": [ "# exemple de lecture de la matrice napbin\n", "nap = newsim.read_fine_array('.napbin')\n", "nap2 = newsim.read_fine_array('napbin')\n", "\n", "print('Comparaison des caractéristiques de matrice : ', nap2.is_like(nap))\n", "print('Comparaison des valeurs : ', np.all(nap2.array.data == nap.array.data))\n", "print('Comparaison des masques : ', np.all(nap2.array.mask == nap.array.mask))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Topography" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Topo min : 0.0\n", "Topo max : 0.0\n", "Heure de modification (UTC) : 2024-06-21 13:15:38.011223+00:00\n", "Heure de modification (GMT+1) : 2024-06-21 14:15:38.011223+01:00\n", "Heure de modification (GMT+2) : 2024-06-21 15:15:38.011223+02:00\n" ] } ], "source": [ "top = newsim.read_fine_array('.top')\n", "\n", "# mise à zéro de la topographie\n", "top.array[:,:] = 0.0\n", "\n", "print('Topo min : ', top.array.min())\n", "print('Topo max : ', top.array.max())\n", "\n", "top.write_all()\n", "\n", "# vérification de la date de modification du fichier\n", "print('Heure de modification (UTC) : ', newsim.last_modification_date('.top', tz.utc)) # date en UTC (paramètre par défaut)\n", "print('Heure de modification (GMT+1) : ', newsim.last_modification_date('.top', tz(td(hours=1)))) # date en GMT+1/UTC+1 (heure d'hiver sur Bruxelles)\n", "print('Heure de modification (GMT+2) : ', newsim.last_modification_date('.top', tz(td(hours=2)))) # date en GMT+2/UTC+2 (heure d'été sur Bruxelles)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Initial water height" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hauteur min : 1.0\n", "Hauteur max : 1.0\n" ] }, { "data": { "text/plain": [ "datetime.datetime(2024, 6, 21, 13, 15, 38, 41143, tzinfo=datetime.timezone.utc)" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h = newsim.read_fine_array('.hbin')\n", "\n", "# Comme la topo est plate, on peut facilement éditer la matrice de hauteur d'eau\n", "h.array[:,:] = 1.0\n", "\n", "print('Hauteur min : ', h.array.min())\n", "print('Hauteur max : ', h.array.max())\n", "\n", "h.write_all()\n", "\n", "# Vérification de la date de modification du fichier\n", "newsim.last_modification_date('.hbin')" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hauteur min : 2.0\n", "Hauteur max : 2.0\n" ] }, { "data": { "text/plain": [ "datetime.datetime(2024, 6, 21, 13, 15, 38, 73059, tzinfo=datetime.timezone.utc)" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Dans un cas plus complexe, on pourrait travailler en terme de surface libre et de topographie pour obtenir la hauteur d'eau.\n", "z = WolfArray(mold=top)\n", "z.array[:,:] = 2.0\n", "\n", "h = z - top # dans ce cas l'objet h n'est plus celui chargé plus haut, mais une nouvelle instance de WolfArray'\n", "\n", "print('Hauteur min : ', h.array.min())\n", "print('Hauteur max : ', h.array.max())\n", "\n", "h.write_all(newsim.filename + '.hbin') # Il faut donc nommer le fichier à écrire\n", "\n", "# verification de la date de modification du fichier\n", "newsim.last_modification_date('.hbin')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Débits selon X et Y" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [], "source": [ "qx = newsim.read_fine_array('.qxbin')\n", "qy = newsim.read_fine_array('.qybin')\n", "\n", "qx.array[:,:] = 0.\n", "qy.array[:,:] = 0.\n", "\n", "qx.write_all()\n", "qy.write_all()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Frottement" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Valeur par défaut : 0.04\n" ] } ], "source": [ "nManning = newsim.read_fine_array('.frot')\n", "\n", "print('Valeur par défaut : ', nManning.array.max())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Autre façon d'accéder aux données\n", "\n", "Les matrices de données sont également accessibles via des propriétés de l'objet de simulation.\n", "\n", "Propriétés disponibles :\n", "- hbin\n", "- qxbin\n", "- qybin\n", "- top\n", "- frot\n", "- inf\n", "- kbin (si calcul avec turbulence)\n", "- epsbin (si calcul avec turbulence)\n", "\n", "Les matrices seront lues sur disque si elles n'existent pas.\n", "\n", "Par contre, si elles ont déjà été appelées, il faudra d'abord forcer le déchargement \"force_unload\" avant de pouvoir relire la fichier ou alors le forcer manuellement." ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test\\test.top\n" ] } ], "source": [ "top = newsim.top\n", "\n", "assert top is newsim.top, 'Erreur de référence -- Ceci n\\'est pas un alias/pointeur'\n", "print(top.filename)" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [], "source": [ "newsim.force_unload()" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [], "source": [ "# Récupération de la topographie après déchargement\n", "top2 = newsim.top\n", "\n", "# Vérification que les 2 objets sont distincts\n", "assert top is not top2, 'Erreur de référence -- Les deux objets ne sont pas distincts'\n", "\n", "# Il faut donc être prudent lors de l'utilisation de pointeurs et préférer l'appel aux propriétés de l'objet" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Calcul\n", "\n", "Une fois que tous les fichiers sont écrits sur disque, il est temps de lancer le calcul.\n", "\n", "Pour cela, soit utiliser \"run_wolfcli\" ou alors exécuter la commande \"wolfcli run_wolf2d_prev genfile=pathtosim' dans une fenêtre de commande, pour autant que wolfcli y soit accessible (via le PATH par ex.)." ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [], "source": [ "newsim.run_wolfcli()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Soyez patient !! \n", "\n", "Le calcul est en cours... du moins si une fenêtre de commande apparaît et que des informations de calcul s'affichent.\n", "\n", "Le temps de calcul total est impossible à prédire." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Analyse de résultats" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si le calcul s'est déroulé comme prévu, des fichiers supplémentaires sont présents dans votre répertoire de simulation.\n", "\n", "Il s'agit de :\n", " - .RH : résultats de hauteur d'eau sur les mailles calculées (binaire - float32)\n", " - .RUH : résultats de débit spécifique selon X (binaire - float32)\n", " - .RVH : résultats de débit spécifique selon Y (binaire - float32)\n", " - .RCSR : numérotation des mailles selon le standard Compressed Sparse Row ((binaire - int32))\n", " - .HEAD : header contenant toutes les informations de position dans les fichiers précédents (binaire - mix)\n", " - .RZB : résultat de l'altitude du fond (calcul sédimentaire)\n", "\n", "Des fichiers supplémentaires seront présents en cas de calcul avec turbulebnce, en fonction du modèle choisi.\n", "\n", "Il est recommandé d'accéder aux résultats via la classe \"Wolfresults_2D\" - https://wolf.hece.uliege.be/autoapi/wolfhece/wolfresults_2D/index.html" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [], "source": [ "# Instanciation d'un objet résultat\n", "res = Wolfresults_2D(newsim.filename)" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1001" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Récupération du nombre de résultats\n", "res.get_nbresults()\n", "\n", "# 1001 car 1000 itérations + 1 état initial" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [], "source": [ "# Récupération des résultats d'un pas spécifique (0-based) -- \"-1\" pour le dernier pas\n", "res.read_oneresult(-1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les résultats sont stockés sous la forme de blocs, accessible via un dictionnaire. La clé de ce dictionnaire est générée par la fonction \"getkeyblock\" du module wolf_array, https://wolf.hece.uliege.be/autoapi/wolfhece/wolf_array/index.html#wolfhece.wolf_array.getkeyblock.\n", "\n", "Chaque bloc contient les résultats pour les différentes inconnues et, le cas échéant, des valeurs combinées.\n", "\n", "Il est possible de choisir ces valeurs combinées via l'Enum \"views_2D\" -- https://wolf.hece.uliege.be/autoapi/wolfhece/wolfresults_2D/index.html#wolfhece.wolfresults_2D.views_2D\n", "\n", "La \"vue courante\" d'un objet de résultat est choisie via " ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [], "source": [ "from wolfhece.wolfresults_2D import views_2D, getkeyblock\n", "\n", "res.set_current(views_2D.FROUDE) # Calcul du Froude" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La matrice de chaque bloc peut être obtenue facilement." ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Typage : \n" ] } ], "source": [ "fr1 = res[0] # Récupération de la matrice de résultats du bloc n°1 en passant un entier\n", "fr2 = res[getkeyblock(1, addone=False)] # Récupération de la matrice de résultats du bloc n°1 en passant une clé générée par getkeyblock\n", "fr3 = res[getkeyblock(0)] # Récupération de la matrice de résultats du bloc n°0 en passant une clé générée par getkeyblock\n", "\n", "#Les trois lignes précédentes renvoient le même résultat.\n", "\n", "assert fr1 == fr2\n", "assert fr2 == fr3\n", "\n", "print('Typage : ', type(fr1)) # Le format renvoyé est du type \"WolfArray\"" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Typage : \n" ] } ], "source": [ "fr_MB = res.as_WolfArray() # Récupération de la matrice de résultats en tant qu'objet \"WolfArray_MB\" si plusieurs blocs, \"WolfArray\" sinon\n", "\n", "print('Typage : ', type(fr_MB)) # Le format renvoyé ici est du type \"WolfArray\" car il n'y a qu'un seul bloc de calcul" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [], "source": [ "fr_mono = res.as_WolfArray().as_WolfArray() # En cas de matrice MB, il est possible de récupérer une matrice monobloc en appelant deux fois la méthode \"as_WolfArray\" (première fois pour passer de résultat à MB, deuxième fois pour passer de MB à mono)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## et la suite...\n", "\n", "Pour la suite, tout dépend de ce que vous voulez faire.\n", "\n", "## A retenir\n", "\n", "Il faut retenir de ce tuto que :\n", "\n", "1. il faut définir une emprise de simulation par un contour général polygonal et un/plusieurs contour(s) de bloc\n", "1. on peut définir une grille magnétique pour caler les contours\n", "1. il faut définir la taille de maillage fin sur lequel les données devront être fournies\n", "1. il faut définir la taille de maillage de chaque bloc\n", "1. il faut paramétrer le modèle (plusieurs fonctions proposées pour simplifier la procédure)\n", "1. il faut lui ajouter des conditions aux limites\n", "1. lancer le calcul...\n", "1. analyser les résultats\n", "\n", "Les résultats sont accessibles progressivement en cours de calcul. Il n'est donc pas nécessaire d'attendre la fin.\n", "\n", "Le fichier de paramétrage sera inaccessible pendant toute la durée du calcul (pointeur ouvert par le Fortran)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Affichage Matplotlib simple du dernier pas" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [], "source": [ "res.read_oneresult(-1)\n", "res.set_current(views_2D.WATERDEPTH) # Calcul de la hauteur d'eau\n" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Minimum 1.0003558\n", "Maximum 1.0017345\n" ] }, { "data": { "image/png": "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nStb9kZ3lh07dtg7BJmCggJ7hyBz5MgRe4cgs/hl614MqLRZ3fbYOwRJsr0DINVjhUc5qqrwKCUpKQnl5eXSduLECXuHRERERLeRqio8Sr2bQ6fT3XEvTCMiotaJ1RllqKrCc7vezUFERESti6IJT0VFhfTCL+C/7+aoezx1UlISRo0aJbWfOHEifvnlF0ybNg3Hjh3Dhx9+iPXr12PKlClSm8TERHz88cf45JNPcPToUbzwwgv13s1BREREdCNFh7Ts9W4OIiKiOxEnLStH0YRn4MCBTd70hp6iPHDgQBw4cKDJfl966SW89NJLLQ2PiIiIWglVTVomIiJqzVjhUY6qJi0TERERKYEJDxERETk8DmkRERGpBIe0lMMKDxERETk8VniIiIhUghUe5bDCQ0RERA6PFR4iIiKVYIVHOazwEBERkcNjwkNEREQOj0NaREREKsEhLeWwwkNEREQOjxUeIiIilWCFRzms8BAREZHDY4WHiIhIJVjhUQ4rPEREROTwmPAQERGRw+OQFhERkUpwSEs5rPAQERGRw2OFh4iISCVY4VEOKzxERETk8JjwEBERkcPjkBYREZFKcEhLOazwEBERkcNjhYeIiEglWOFRDis8RERE5PBY4SEiIlIJVniUwwoPEREROTxWeIiIiFSCFR7lsMJDREREDo8JDxERETk8DmkRERGpBIe0lMMKDxERETk8VniIiIhUghUe5She4UlNTUVAQABcXFwQERGBvXv3Ntp24MCB0Gg09ba4uDipzejRo+t9HxMTo/RlEBEROaydO3diyJAh8PX1hUajwcaNG296TE5ODvr16wedTofu3bsjPT29Xpub5QBLly7FwIEDodfrodFoUFZWJvv+119/xdixYxEYGAhXV1d069YNycnJqK6utvoaFU141q1bh8TERCQnJ2P//v0ICQmB0WjEmTNnGmz/5ZdfoqSkRNoOHToEZ2dnPPPMM7J2MTExsnZr1qxR8jKIiIgcWmVlJUJCQpCamtqs9kVFRYiLi0NUVBTy8/MxefJkjBs3Dlu2bJHaNCcHuHz5MmJiYvD66683eJ5jx47BYrHgH//4Bw4fPoyFCxciLS2t0fZNUXRIa8GCBRg/fjwSEhIAAGlpacjIyMCKFSswY8aMeu09PT1ln9euXQs3N7d6CY9Op4PBYFAucCIiIjuw15BWbGwsYmNj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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "\n", "print('Minimum ', res[0].array.min())\n", "print('Maximum ', res[0].array.max())\n", "\n", "fig,ax = res[0].plot_matplotlib()\n", "fig.suptitle('Hauteur d\\'eau')\n", "fig.colorbar(ax.images[0], ax=ax)\n", "fig.tight_layout()\n" ] } ], "metadata": { "kernelspec": { "display_name": "python3.10", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.11" } }, "nbformat": 4, "nbformat_minor": 2 }