The MeshMaker class#

What it does#

Based on the gmsh API, the MeshMaker class is used to construct finite element meshes from vector data such as shapefiles or GeoDataFrames. It automates mesh generation by converting geospatial information into Gmsh geometry and mesh files.

Documentation#

class watlab.utils.MeshMaker(shapefile: str | GeoDataFrame | ShapeFileParser, type='shp')#

Based on the gmsh API, the MeshMaker class generate 2D computational meshes from shapefiles, GeoDataFrames or ShapeFileParser object. The resulting mesh can then be used to define computational domains and regions for hydrodynamic or sediment transport simulations within the Watlab suite.

Parameters:
  • shapefile (str | geopandas.GeoDataFrame | watlab.shapefile_parser.ShapeFileParser) –

    Input geometry data — can be a path to a shapefile, a GeoDataFrame, or a ShapeFileParser object.

    The shapefile ‘data.shp’ must be placed in the same folder as the associated files ‘data.cpg’, ‘data.dbf’, ‘data.prj’, and ‘data.shx’.

  • type (str, optional) – Type of input file if shapefile is a path. “shp” for Shapefile (default), or “csv” for CSV input.

Example

from watlab.utils.mesh_maker import MeshMaker

# Example 1 — From a shapefile
mesh = MeshMaker("data/boundaries.shp")
mesh.make_mesh("output_mesh")

# Example 2 — From a ShapeFileParser
from watlab.utils.shapefile_parser import ShapeFileParser
shp_parser = ShapeFileParser("data/boundaries.shp")
mesh = MeshMaker(shp_parser)
mesh.make_mesh("river_mesh.msh")

Notes

  • The shapefile must contain all necessary associated files (.shp, .dbf, .prj, .shx, .cpg).

  • Each zone should form a valid, closed polygon (or curveloop).

  • Gmsh must be correctly installed and accessible in your environment.

create_boundaries(boundaries: dict) None#

Creates physical groups for boundaries in Gmsh.

Each boundary is defined as a set of lines and assigned a name. This allows boundary conditions to be applied to specific edges in the mesh.

Parameters:

boundaries (dict) – Dictionary where keys are boundary names and values are lists of line tags that define each boundary.

Returns:

None. Physical groups for boundaries are added directly to the Gmsh model.

Example

boundaries = {
    "inlet": [1, 2, 3],
    "outlet": [4, 5]
}
mesh_maker.create_boundaries(boundaries)
create_curveloops(curveloops: dict, lines: dict = None, points: list = None) None#

Creates curveloops and corresponding plane surfaces in Gmsh.

Each curveloop defines a closed boundary using line indices. Nested curveloops (holes) are automatically detected and handled, so the resulting plane surfaces correctly account for inner voids.

Parameters:
  • curveloops (dict) – Dictionary of curveloops where keys are zone names and values are lists of line indices forming each curveloop.

  • lines (dict, optional) – Dictionary of line definitions (key: line tag, value: tuple of point indices). Defaults to self.data.lines if None.

  • points (list, optional) – List of point coordinates corresponding to the lines. Defaults to self.data.points if None.

Returns:

None. Curveloops and plane surfaces are added directly to the Gmsh model.

Example

mesh_maker.create_curveloops(curveloops)
create_lines(lines: dict) None#

Creates lines in the Gmsh model from a dictionary of lines.

Each line is defined by its start and end points and assigned a unique tag. These lines can then be used to form curves, surfaces, and loops in Gmsh.

Parameters:

lines (dict) – Dictionary of lines where the key is the line tag and the value is a list or tuple containing the start and end point indices.

Example

lines = {
    1: [1, 2],
    2: [2, 3],
    3: [3, 1]
}
mesh_maker.create_lines(lines)
create_points(points: list, resolutions: list) None#

Creates points in the Gmsh model. Each point is added with a specific resolution, which controls the local mesh size.

Parameters:
  • points (list of tuples or lists) – List of point coordinates. Each point can be 2D (x, y) or 3D (x, y, z).

  • resolutions (list of float) – List of resolution values for each point. Must have the same length as points.

Notes - The points are added to the Gmsh model with tags starting from 1 and incremented sequentially.

create_regions(zone_names: list, regions: dict) None#

Creates physical groups for regions composed of multiple zones in Gmsh.

Each region is defined as a 2D physical group that may contain multiple zones. Zones with names ending with ‘*’ are ignored when assigning them to regions.

Parameters:
  • zone_names (list) – List of all zone names corresponding to plane surfaces.

  • regions (dict) – Dictionary mapping region names to lists of zone names included in the region.

Returns:

None. Physical groups for regions are added directly to the Gmsh model.

Example

zone_names = ["zone1", "zone2", "zone3"]
regions = {"regionA": ["zone1", "zone2"], "regionB": ["zone3"]}
mesh_maker.create_regions(zone_names, regions)
create_zones(zone_names: list) None#

Creates physical groups for zones (plane surfaces) in Gmsh.

Each zone is assigned a name and added as a 2D physical group. This allows assigning properties or performing operations on specific zones in the mesh.

Parameters:

zone_names (list) – List of zone names corresponding to plane surfaces. Zones with names ending with ‘*’ are ignored.

Returns:

None. Physical groups for zones are added directly to the Gmsh model.

Example

zone_names = ["river", "floodplain"]
mesh_maker.create_zones(zone_names)
embed_internal_boundaries(points: list, lines: dict, internal_boundaries: dict, curveloops: dict)#

Embeds internal boundaries into their corresponding 2D surfaces in the Gmsh model.

Each internal boundary is reconstructed as a LineString and tested against zone polygons to determine which zone contains it. If the zone covers the boundary, the corresponding line tags are embedded into that surface using gmsh.model.mesh.embed.

Parameters:
  • points (list) – List of point coordinates.

  • lines (dict) – Mapping of line tags to pairs of point indices.

  • internal_boundaries (dict) – Mapping of boundary names to ordered line-tag lists.

  • curveloops (dict) – Mapping of zone names to line-tag lists forming each zone boundary.

Returns:

None

Return type:

None. Internal Boundaries are embedded directly to the surfaces of Gmsh model.

Raises:

Warning – If a boundary does not lie inside any zone.

make_curveloop_from_zone(zone: list, lines: dict | list = None, points: list = None)#

Constructs a curveloop from an unordered set of line tags defining a zone.

A curveloop is an ordered list of lines that form a closed polygonal boundary. Each line connects two consecutive points, and its sign indicates the traversal direction: - A positive tag means the line is traversed from its first point to its second. - A negative tag means the line is traversed in reverse order.

This method ensures that: - All lines in the given zone are ordered so that they form a closed loop. - The loop orientation is counterclockwise (positive normal). - The closure and orientation validity are verified.

Parameters:
  • zone (list) – List of line indexes defining the zone.

  • lines (dict | list, optional) – Dictionary or list of line definitions where each line is a tuple (start_point, end_point). Defaults to self.data.lines.

  • points (list, optional) – List of point coordinates used to determine the geometric orientation. Defaults to self.data.points.

Raises:
  • Exception – If the curveloop cannot be closed or the shapefile contains inconsistencies.

  • ValueError – If the zone has no proper orientation (orientation equals zero).

Returns:

Ordered list of signed line tags forming a closed, properly oriented curveloop.

Return type:

list

Example

zone = [1, 2, 3, 4]
lines = {
    1: (1, 2),
    2: (2, 3),
    3: (3, 4),
    4: (4, 1)
}
points = [(0,0), (1,0), (1,1), (0,1)]

curveloop = meshmaker.make_curveloop_from_zone(zone, lines, points)
print(curveloop)
# Output: [1, 2, 3, 4]  → properly ordered and counterclockwise
make_mesh(name: str, verbosity=5, display_ui=False)#

Generates a 2D mesh using Gmsh from the provided points, lines, curveloops, and physical groups.

This method performs the complete mesh creation workflow:

  1. Initializes Gmsh if necessary.

  2. Adds points and lines to the geometry.

  3. Creates curveloops and associated plane surfaces.

  4. Synchronizes the geometric model.

  5. Creates boundaries, zones, and regions as physical groups.

  6. Generates and optionally optimizes the mesh.

  7. Exports the mesh to a .msh file.

  8. Optionally opens the Gmsh GUI for visualization.

Parameters:
  • name (str) – Name of the output mesh file. If the extension is not provided, ‘.msh’ will be appended.

  • verbosity (int, optional) –

    Level of messages printed by Gmsh:

    • 0: silent except for fatal errors

    • 1: errors

    • 2: warnings

    • 3: direct messages

    • 4: information

    • 5: status (default)

    • 99: debug

  • display_ui (bool, optional) – If True, opens the Gmsh GUI for visualization. Defaults to False.

Returns:

None. The mesh is written to a .msh file and added to the Gmsh model.

Example

mesh_maker = MeshMaker("my_shapefile.shp")
mesh_maker.make_mesh("output_mesh", verbosity=5, display_ui=False)
verify_curveloop_closure(curveloop: list, lines: dict | list)#

Verifies that a given curveloop is properly closed.

A curveloop is a list of line tags that form a continuous polygonal boundary. This method checks whether the starting point of the first line and the ending point of the last line are identical, ensuring that the loop is closed.

Parameters:
  • curveloop (list) – List of line tags composing the curveloop. Each line tag can be positive or negative, indicating its direction.

  • lines (dict | list) – Dictionary or list mapping each line tag to a tuple of point indices (start, end).

Returns:

True if the curveloop is closed, False otherwise.

Return type:

bool

Example

curveloop = [1, 2, 3]
lines = {
    1: (1, 2),
    2: (2, 3),
    3: (3, 1)
}

is_closed = meshmaker.verify_curveloop_closure(curveloop, lines)
print(is_closed)  # True → the loop is closed

Notes

  • A negative line tag (e.g. -2) means that the line is traversed in reverse order.

  • This method only checks topological closure (connectivity of start and end points), not geometric continuity.