Curvilineargrid Basics

This is the basic introduction for using meshkernel library for generating curvilinear grids.

At the very beginning, the necessary libraries have to be imported.

import matplotlib.pyplot as plt
import numpy as np

from meshkernel import (
    CurvilinearParameters,
    MakeGridParameters,
    GeometryList,
    MeshKernel,
    SplinesToCurvilinearParameters,
    OrthogonalizationParameters,
)

Define a function for creating a mesh kernel instance with a curvilinear grid generated using curvilinear_compute_transfinite_from_splines:

  • We first create the splines used for curvilinear grid generation. Each spline is separated by -999.0

  • We can set the number of m and n in a new CurvilinearParameters instance

  • We now create a new instance of the MeshKernel library

  • And used the transfinite algorithm to create a new curvilinear grid

def create_mk_instance_with_curvilinear_grid_from_transfinite_method():
    r"""A function for creating an instance of meshkernel with a curvilinear grid."""
    mk = MeshKernel()

    separator = -999.0
    splines_x = np.array(
        [
            2.0,
            4.0,
            7.0,
            separator,
            -1.0,
            1.0,
            5.0,
            separator,
            3.0,
            -2.0,
            separator,
            7.0,
            4.0,
        ],
        dtype=np.double,
    )
    splines_y = np.array(
        [
            1.0,
            3.0,
            4.0,
            separator,
            4.0,
            6.0,
            7.0,
            separator,
            1.0,
            6.0,
            separator,
            3.0,
            8.0,
        ],
        dtype=np.double,
    )
    splines = GeometryList(splines_x, splines_y)

    curvilinear_parameters = CurvilinearParameters()
    curvilinear_parameters.n_refinement = 10
    curvilinear_parameters.m_refinement = 10

    mk.curvilinear_compute_transfinite_from_splines(splines, curvilinear_parameters)

    return mk

Define a function for creating a rectangular curvilinear grid

def create_mk_instance_with_a_rectangular_curvilinear_grid(num_columns=3, num_rows=3):
    r"""A local function for creating an instance of meshkernel with a rectangular curvilinear grid."""
    mk = MeshKernel()

    # Create an instance of MakeGridParameters and set the values
    make_grid_parameters = MakeGridParameters()
    make_grid_parameters.num_columns = num_columns
    make_grid_parameters.num_rows = num_rows
    make_grid_parameters.angle = 0.0
    make_grid_parameters.origin_x = 0.0
    make_grid_parameters.origin_y = 0.0
    make_grid_parameters.block_size_x = 10.0
    make_grid_parameters.block_size_y = 10.0

    mk.curvilinear_compute_rectangular_grid(make_grid_parameters)

    return mk

Generate a curvilinear grid using the transfinite interpolation method

curvilinear_grid_transfinite = (
    create_mk_instance_with_curvilinear_grid_from_transfinite_method().curvilineargrid_get()
)

Plot the result

fig, ax = plt.subplots()
curvilinear_grid_transfinite.plot_edges(ax)
../_images/1086d09a8077ac63a4a730da8afd2298d3c6430fd26d757c3fd8ed27a6df42eb.png

Generate a curvilinear grid using the advancing front method

Define a function for creating a mesh kernel instance with a curvilinear grid generated using curvilinear_compute_orthogonal_from_splines:

  • We first create the splines for curvilinear grid generation. Each spline is separated by -999.0

  • We can set the number of m and n in a new CurvilinearParameters instance

  • For this algorithm we also need to set the additional parameters required for generating a curvilinear grid from splines

  • We can now use the advancing front algorithm to create a new curvilinear grid

mk = MeshKernel()

separator = -999.0
splines_x = np.array([-1.0, 2.0, 6.0, separator, 3.0, -2.0, separator], dtype=np.double)
splines_y = np.array([2.0, 5.0, 6.0, separator, 1.0, 6.0, separator], dtype=np.double)

splines_values = np.zeros_like(splines_x)
splines = GeometryList(splines_x, splines_y, splines_values)

curvilinearParameters = CurvilinearParameters()
curvilinearParameters.n_refinement = 10
curvilinearParameters.m_refinement = 10

splinesToCurvilinearParameters = SplinesToCurvilinearParameters()
splinesToCurvilinearParameters.aspect_ratio = 1.0
splinesToCurvilinearParameters.aspect_ratio_grow_factor = 1.0
splinesToCurvilinearParameters.average_width = 0.2
splinesToCurvilinearParameters.nodes_on_top_of_each_other_tolerance = 1e-4
splinesToCurvilinearParameters.min_cosine_crossing_angles = 0.95
splinesToCurvilinearParameters.check_front_collisions = 0
splinesToCurvilinearParameters.curvature_adapted_grid_spacing = 1
splinesToCurvilinearParameters.remove_skinny_triangles = 1

mk.curvilinear_compute_orthogonal_from_splines(
    splines, curvilinearParameters, splinesToCurvilinearParameters
)

curvilinear_grid_orthogonal = mk.curvilineargrid_get()

Plot the result

fig, ax = plt.subplots()
curvilinear_grid_orthogonal.plot_edges(ax)
../_images/f6812a32aad87070c58f39002ba02cbaac2cbbf2c81ab09993336baa4ce0fca5.png

Refine/derefine a curvilinear mesh

Before refinement

mk = create_mk_instance_with_curvilinear_grid_from_transfinite_method()
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/1086d09a8077ac63a4a730da8afd2298d3c6430fd26d757c3fd8ed27a6df42eb.png

Refine by adding two horizontal grid lines for each row within two selected points and plot the results

mk.curvilinear_refine(2.299, 4.612, 3.074, 3.684, 2)
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/0406a0df53482c78917e356986f0789509fbe477ce2d56f1e0fcf26fd400626f.png

Derefine by removing the grid lines on the same rows

mk.curvilinear_derefine(2.299, 4.612, 3.074, 3.684)
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/ac659c1d9366a4685dc4f6add30c8084621cd6f55788582e81d45e1ba51cc9d7.png

Make a rectangular grid

mk = create_mk_instance_with_a_rectangular_curvilinear_grid()
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/6ce9b9532440ec36a34acbcd76d24340e0fc64407b7c426519dafad6f0bcd070.png

A rectangular grid can be also generated from a polygon. The polygon must be closed

node_x = np.array([2.5, 5.5, 3.5, 0.5, 2.5], dtype=np.double)
node_y = np.array([0.5, 3.0, 5.0, 2.5, 0.5], dtype=np.double)
geometry_list = GeometryList(node_x, node_y)
make_grid_parameters = MakeGridParameters()
make_grid_parameters.num_columns = 10
make_grid_parameters.num_rows = 10
make_grid_parameters.angle = 0.0
make_grid_parameters.origin_x = 0.0
make_grid_parameters.origin_y = 0.0
make_grid_parameters.block_size_x = 0.2
make_grid_parameters.block_size_y = 0.2
mk.curvilinear_compute_rectangular_grid_from_polygon(
    make_grid_parameters, geometry_list
)
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/e6753139d32324dadf66bd8b06e9b6fd156b53005ba844093de1ce90f95c327b.png

Generate a curvilinear grid using the nodes at the polygons’s perimeter

Define the polygon and generate the curvilinear grid

node_x = np.array([2, 4, 6, 7, 8, 8, 8, 8, 7, 5, 3, 2, 2, 2, 2], dtype=np.double)
node_y = np.array([1, 1, 1, 1, 1, 1.2, 4, 6, 6, 6, 6, 6, 5, 3, 1], dtype=np.double)
geometry_list = GeometryList(node_x, node_y)
mk = MeshKernel()
mk.curvilinear_compute_transfinite_from_polygon(geometry_list, 0, 4, 7, False)
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/82fd2ee952697ac2dea75941cdc3da1aeff9fc6e8764c2d7680765badf595e03.png

Perform curvilinear grid orthogonalization

Move a node to make the grid non orthogonal and plot the result

mk = create_mk_instance_with_a_rectangular_curvilinear_grid()
mk.curvilinear_move_node(10.0, 20.0, 18.0, 12.0)
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/6c809b8208dce8706e70684067c39518c6b6048a1c7542e92bca18926a1a8f38.png

Orthogonalize

# Assert a nodal position before orthogonalization
orthogonalization_parameters = OrthogonalizationParameters()
orthogonalization_parameters.outer_iterations = 1
orthogonalization_parameters.boundary_iterations = 25
orthogonalization_parameters.inner_iterations = 25
orthogonalization_parameters.orthogonalization_to_smoothing_factor = 0.95

# Initialize the curvilinear grid orthogonalization algorithm
mk.curvilinear_initialize_orthogonalize(orthogonalization_parameters)

# Sets the block to orthogonalize (in this case the lower left and upper right corners of the grid)
mk.curvilinear_set_block_orthogonalize(0.0, 0.0, 30.0, 30.0)

# Orthogonalize
mk.curvilinear_orthogonalize()

Plot the results after orthogonalization

curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/e2aba06433a70f4f686aa06f558b61f035308cef068061ace4d74401422df5bb.png

Perform curvilinear grid orthogonalization with a frozen line

mk = create_mk_instance_with_a_rectangular_curvilinear_grid()
mk.curvilinear_move_node(10.0, 20.0, 18.0, 12.0)
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/6c809b8208dce8706e70684067c39518c6b6048a1c7542e92bca18926a1a8f38.png

Orthogonalize, but freeze the vertical grid line where the moved node is

# Assert a nodal position before orthogonalization
orthogonalization_parameters = OrthogonalizationParameters()
orthogonalization_parameters.outer_iterations = 1
orthogonalization_parameters.boundary_iterations = 25
orthogonalization_parameters.inner_iterations = 25
orthogonalization_parameters.orthogonalization_to_smoothing_factor = 0.95

# Initialize the curvilinear grid orthogonalization algorithm
mk.curvilinear_initialize_orthogonalize(orthogonalization_parameters)

# Sets the block to orthogonalize (in this case the lower left and upper right corners of the grid)
mk.curvilinear_set_block_orthogonalize(0.0, 0.0, 30.0, 30.0)

# Freeze the vertical grid line where the moved node is
mk.curvilinear_set_frozen_lines_orthogonalize(10.0, 0.0, 10.0, 30.0)

# Orthogonalize
mk.curvilinear_orthogonalize()

Plot the results after orthogonalization

curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/22fb0b031048f56c2bf89c1639e2c168d43981ef0ed12926a3f3202d3aa5635e.png

Perform curvilinear grid smoothing

Move a node to make the grid non-smooth and plot the result

mk = create_mk_instance_with_a_rectangular_curvilinear_grid()
mk.curvilinear_move_node(10.0, 20.0, 18.0, 12.0)
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/6c809b8208dce8706e70684067c39518c6b6048a1c7542e92bca18926a1a8f38.png

Smoothing

mk.curvilinear_smoothing(10, 0.0, 0.0, 30.0, 30.0)

Plot the results after smoothing

curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/e50b7e2ab4d91e4802049c119e96af6422f40d9dc61bc805358e5406a02578bc.png

Perform curvilinear directional curvilinear grid smoothing

Move a node to make the grid non-smooth and plot the result

mk = create_mk_instance_with_a_rectangular_curvilinear_grid()
mk.curvilinear_move_node(10.0, 20.0, 18.0, 12.0)
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/6c809b8208dce8706e70684067c39518c6b6048a1c7542e92bca18926a1a8f38.png

Directional smoothing

mk.curvilinear_smoothing_directional(
    10,  # the number of smoothing iterations
    10.0,
    0.0,
    10.0,
    30.0,  # the grid line coordinates defining the smoothing direction
    0.0,
    0.0,
    30.0,
    30.0,
)  # the corner points of the block to smooth

Plot the results after directional smoothing

curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/9303cb6c4c54511e36ea05e57bebf3441dc24b071ffb4ca77f0e3b69178214a5.png

Perform curvilinear grid line shifting

mk = create_mk_instance_with_a_rectangular_curvilinear_grid(5, 5)
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/e3b5c006184ff6adf515036100960ccd42001e82c7c290e9c0ba8a0652beb25d.png

Initialize line shifting and set the line to shift

mk.curvilinear_initialize_line_shift()
mk.curvilinear_set_line_line_shift(0.0, 0.0, 0.0, 50.0)

Set the grid block where to distribute the line shift

mk.curvilinear_set_block_line_shift(0.0, 0.0, 20.0, 50.0)

Move all nodes on the left side of the curvilinear grid to the left

mk.curvilinear_move_node_line_shift(0.0, 0.0, -50.0, 0.0)
mk.curvilinear_move_node_line_shift(0.0, 10.0, -50.0, 10.0)
mk.curvilinear_move_node_line_shift(0.0, 20.0, -50.0, 20.0)
mk.curvilinear_move_node_line_shift(0.0, 30.0, -50.0, 30.0)
mk.curvilinear_move_node_line_shift(0.0, 40.0, -50.0, 40.0)
mk.curvilinear_move_node_line_shift(0.0, 50.0, -50.0, 50.0)

Performs the line shift. Nodes not in the block specified above will not be shifted

mk.curvilinear_line_shift()
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/9cfe64096afc18579f88d5996ce6e91c8d1897873451322c051dceb4cb0d228e.png

Perform curvilinear insert a face

mk = create_mk_instance_with_a_rectangular_curvilinear_grid(5, 5)
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/e3b5c006184ff6adf515036100960ccd42001e82c7c290e9c0ba8a0652beb25d.png

Insert two faces

mk.curvilinear_insert_face(-10.0, 5.0)
mk.curvilinear_insert_face(-5.0, 10.0)
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/fe1d3e2ac3f1e05bc6eb28f01bcb4e5104394fb237dc20b5d7c3ec4130f8d894.png

Perform curvilinear delete a node

mk = create_mk_instance_with_a_rectangular_curvilinear_grid(5, 5)
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/e3b5c006184ff6adf515036100960ccd42001e82c7c290e9c0ba8a0652beb25d.png

Delete the corner node

mk.curvilinear_delete_node(0.0, 0.0)
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/1a7e3dfe8c6aff7dd62169c3d84a6a64f20ac151f3b2858c8a6a78e69c2c12c0.png

Perform curvilinear line attraction/repulsion

Attracts the nodes within a block towards a defined line

mk = create_mk_instance_with_a_rectangular_curvilinear_grid(5, 5)
mk.curvilinear_line_attraction_repulsion(
    1.0,  # positive repels lines, here by 1 times the column width
    30.0,
    0.0,
    30.0,
    50.0,  # The line coordinate
    10.0,
    0.0,
    50.0,
    50.0,
)  # The affected block
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/1bbf0c9656f483b6d031c90da987cdae07d283f596f361cda93f2e35cc58b1dd.png
mk = create_mk_instance_with_a_rectangular_curvilinear_grid(5, 5)
mk.curvilinear_line_attraction_repulsion(
    -1.0,  # negative attracts lines, here by 0.5 times the column width
    30.0,
    0.0,
    30.0,
    50.0,  # The line coordinate
    10.0,
    0.0,
    50.0,
    50.0,
)  # The affected block
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/74850b43f16fb006d5f2bf7f766bc39c6b9db27fb66f34a3770e6e97e1dcdbb9.png

Perform curvilinear line mirror

Mirrow the left gridline by 2 times the column width

mk = create_mk_instance_with_a_rectangular_curvilinear_grid(5, 5)
mk.curvilinear_line_mirror(
    2.0, 0.0, 0.0, 0.0, 50.0  # the mirroring factor
)  # the gridline to mirrow
curvilinear_grid = mk.curvilineargrid_get()
fig, ax = plt.subplots()
curvilinear_grid.plot_edges(ax)
../_images/236b0c7496847e4db58322a1976dbf819a516175e1ac8bf7bc7d71f5b1ac7de0.png