.. Watlab documentation file, created by Pierre-Yves Gousenbourger on Wed Aug 2, 2023. .. _create-mesh: Create a mesh ============= In ``example 1``, you run the file ``Mesh.py`` with python. In this tutorial, we will dig into this file to understand how it is created. To run a numerical hydraulic model using Watlab, it is necessary to generate a **mesh** of the study zone. The mesh is made of **points**, **lines** and **areas**. Those are then converted to **nodes** and **cells**, to which one can impose boundary conditions, initial conditions, and so on (this is the :doc:`modeling ` part). GMSH, the meshing software, in a nutshell ----------------------------------------- The mesh is generated by `GMSH `_, an open source software dedicated to that. It comes with a user interface **and** with a Python API. The former is handy if you do not like to code or if your study zone is a bit messy. The latter is super powerful and let you use the latest functionnalities. A GMSH mesh is made of **points**, **lines**, **curve loops**, **plane surfaces** and **physical elements**. Check the `documentation `_ of GMSH for more information. Two physical elements are important here: the **Boundaries** and the **Regions** : - **Boundaries** are the limits where one specifies **boundary conditions** in the model; - **Regions** are areas where one specifies **initial conditions**. **Regions** are assigned to **plane surfaces** and plane surfaces are recognized by the **lines** surrounding them. Furthermore, **lines** are defined by their two end-**points**. Therefore to add a physical plane you need to first define points that define a curve loop to which a plane surface is attributed and finally, the region can be assigned to this plane surface. .. mermaid:: flowchart LR A[Points] --> B[Lines] --> C[Curve loops] --> D[Plane surfaces] --> E([Regions]) B --> F([Boundaries]) In a nutshell, here are the main functions to use : - add a point: ``gmsh.model.geo.addPoint(x, y, z, lc, tag)`` : - ``(x,y,z)`` are the coordinates of the point; - ``lc`` determines the mesh size required at that point; - ``tag`` stands for the number you give to a point (by default, it is incremented). - create a line: ``gmsh.model.geo.addLine(start_point_tag, end_point_tag, line_tag)`` - create a curve loop: ``gmsh.model.geo.addCurveLoop([line_tag_1, line_tag_2, ...], curve_loop_tag)`` - create a plane surface: ``gmsh.model.geo.addPlaneSurface([curve_loop_tag], plane_surface_tag)`` - create a physical group: ``gmsh.model.addPhysicalGroup(dim, [line_tag_1, line_tag_2,...], name="physical_group_name")`` - ``dim`` determines the dimension of the group! - A **Region** (an area) is a group of ``dim=2`` - A **Boundary** is a group of ``dim=1`` The final physical surfaces may not have the same number as the plane surfaces so you need to be careful if you want to recall them by their number somewhere else. Check also this `GMSH tutorial `_ for more details. Good practices for mesh creation -------------------------------- A suited GMSH-mesh is super important in order to run your Watlab simulation. Here is a list of good practices that we recommend to observe: - Always name your regions (resp. boundaries) with a unique easy-to-remember name (example: "reservoir", "upstream bank", "minor bed", "input boundary", etc.); - Separate your mesh in subregions (resp. sub-boundaries) where initial conditions (resp. boundary conditions) are different; - Better create too many regions (resp. boundaries) than too few; - Avoid overlays. Except if justified, never place a cell (resp. an edge) in two different regions (resp. boundaries); - Add every cell in one region. On the contrary, not every edge is a boundary! - Respect the anti-clockwise direction when setting up the curve loops: it ensures that the mesh outputed by GMSH will be well-oriented for Watlab. A good tool to create suited GMSH-meshes is `SeaMSH `_. A good program for visualizing and mesh generation is `QGIS `_ and its `GSMH module `_. In this example, we show how to create a mesh associated to a rectangular domain composed of two physical surfaces. It is represented on the picture hereunder. The numbers (resp. labels) are corresponding to the tags (resp. labels) of the different elements: .. image:: ../pics/hydroflow_example01.jpg :width: 700 :alt: Mesh example 01 We will inspect the mesh creation file and comment it line by line (or somehow). .. code-block:: python import gmsh import sys gmsh.initialize() gmsh.model.add("Example_Mesh") Those lines are important! The first is importation package: ``gmsh`` is the core module that you need to install in your environment (already included in ``hydroflow``). Then, ``gmsh`` must be initialized in order to properly function, and a name must be given to the new model created. .. code-block:: python lc = 0.01 gmsh.model.geo.addPoint(0, 0, 0, lc, 1) gmsh.model.geo.addPoint(0.5, 0, 0, lc, 2) gmsh.model.geo.addPoint(1, 0, 0, lc, 3) gmsh.model.geo.addPoint(0, 0.4, 0, lc, 4) gmsh.model.geo.addPoint(0.5, 0.4, 0, lc, 5) gmsh.model.geo.addPoint(1,0.4, 0, lc, 6) Here, six points are declared : one at each corner, and two to separate the rectangle in two parts. Here, we want the mesh size to be the same everywhere, so this is why ``lc`` is declared at the beginning. .. code-block:: python gmsh.model.geo.addLine(1, 2, 1) gmsh.model.geo.addLine(2, 3, 2) gmsh.model.geo.addLine(1, 4, 3) gmsh.model.geo.addLine(2, 5, 4) gmsh.model.geo.addLine(3, 6, 5) gmsh.model.geo.addLine(4, 5, 6) gmsh.model.geo.addLine(5, 6, 7) Now we declare lines. There are seven lines in our model: three limit the left area, three other limit the right area, and one makes the boundary between the two, in the middle. The nodes defining the lines are identified by their tags. .. code-block:: python gmsh.model.geo.addCurveLoop([1, 4, -6, -3], 1) gmsh.model.geo.addCurveLoop([2, 5, -7, -4], 2) Before creating a surface, one creates the curve loops (i.e., the actual limit of the physical surface, composed of straight lines put together). It is important to respect the direction of each line: use a minus (``-``) if the line was defined in the opposite direction than the one needed. Warning: all curve loops are oriented with anti-clockwise direction. .. code-block:: python gmsh.model.geo.addPlaneSurface([1], 1) gmsh.model.geo.addPlaneSurface([2], 2) gmsh.model.geo.synchronize() Finally, one can create the plane surface to complete the geometry. Two areas are created. At this point the **geometrical work** is finished. It remains to give them a physical name. Note that each surface can be constituted from multiple curve loops. It is necessary to synchronise those informations with the Gmsh model, creating the relevant data structure. The following will identify each surface and each curve loop as a physical element, allowing Watlab to assign initial conditions and boundary conditions later on. As mentioned, there are two kinds of physical groups: boundaries and regions. We build them as follows: .. code-block:: python # Creation of boundaries gmsh.model.addPhysicalGroup(1, [1,2],name="Boundaries down") gmsh.model.addPhysicalGroup(1, [5],name="Boundaries right") gmsh.model.addPhysicalGroup(1, [6,7],name="Boundaries up") gmsh.model.addPhysicalGroup(1, [3],name="Boundaries left") # Creation of regions gmsh.model.addPhysicalGroup(2, [1],name="Filled area") gmsh.model.addPhysicalGroup(2, [2],name="Empty area") Note that, compared to the geometrical entities, we can here give the physical elements a **real name** (with a string !). This will be handy later on while running the :doc:`model `. Finally, generate and save the mesh (as ``Example_Mesh.msh``, for instance): .. code-block:: python gmsh.model.mesh.generate(2) gmsh.model.mesh.optimize('Laplace2D') gmsh.write("Example_Mesh.msh") if '-nopopup' not in sys.argv: gmsh.fltk.run() # Do not forget to finalize your gmsh session ! gmsh.finalize() If you run the script, the Gmsh window will pop-up and should look like this: .. image:: ../pics/tuto_example01_gmsh.png :width: 700 :alt: GMSH tutorial output popup.