5.7 KiB
二维网格基础
本教程介绍 meshkernel 库的基本用法。
meshkernel 可以创建和操作多种网格。
最常见的应用涉及二维非结构网格,因此本教程重点介绍这类网格。
以下保留原笔记本的代码和已保存输出;转换过程中未重新执行代码。
首先导入所需的库。
import matplotlib.pyplot as plt
import numpy as np
from meshkernel import GeometryList, MakeGridParameters, MeshKernel, ProjectionType
meshkernel 提供了一组便捷方法,用于创建常见网格。
这里使用 curvilinear_compute_rectangular_grid 方法创建一个简单的曲线网格。该方法的完整参数请参阅相应文档。
mk = MeshKernel()
make_grid_parameters = MakeGridParameters()
make_grid_parameters.num_columns = 3
make_grid_parameters.num_rows = 2
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 = 1.0
make_grid_parameters.block_size_y = 1.0
mk.curvilinear_compute_rectangular_grid(make_grid_parameters)
将曲线网格转换为非结构网格,并获取生成的 mesh2d。
mk.curvilinear_convert_to_mesh2d()
mesh2d_input = mk.mesh2d_get()
Mesh2D 有三个必需属性,仅凭它们就可以完整描述任意非结构网格。
前两个属性是 node_x 和 node_y,它们是一维 double 数组,用来描述节点的位置,如下图所示。
fig, ax = plt.subplots()
# 绘制白色点,仅用于调整图的显示范围
ax.plot(mesh2d_input.node_x, mesh2d_input.node_y, "ow")
# 为节点编号
for i in range(mesh2d_input.node_x.size):
ax.annotate(
int(i),
xy=(mesh2d_input.node_x[i], mesh2d_input.node_y[i]),
ha="center",
va="center",
fontsize=12,
color="blue",
)
第三个必需属性是 edge_nodes,它描述组成各条边的节点索引。
每两个索引表示一条边。因此,在本例中,0–4、1–5、2–6 等索引对分别表示一条边。
mesh2d_input.edge_nodes
array([ 0, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 0,
1, 1, 2, 2, 3, 4, 5, 5, 6, 6, 7, 8, 9, 9, 10, 10, 11],
dtype=int32)
结合这三个参数即可绘制网格。
fig, ax = plt.subplots()
mesh2d_input.plot_edges(ax, color="blue")
要与 meshkernel 库交互,首先创建一个 MeshKernel 类实例。
构造函数的 projection 参数用于指定网格采用笛卡尔坐标(ProjectionType.CARTESIAN)还是球面坐标(ProjectionType.SPHERICAL)。
mk = MeshKernel(projection=ProjectionType.CARTESIAN)
每个实例都维护各自的状态,可以通过对应的获取和设置方法访问这些状态。
mk.mesh2d_set(mesh2d_input)
mesh2d_output_0 = mk.mesh2d_get()
刚才设置了 mesh2d,随后立即将它取出,期间没有要求 meshkernel 执行其他操作。
设置 mesh2d 后,meshkernel 已计算出网格面数据和边的坐标。
fig, ax = plt.subplots()
mesh2d_output_0.plot_faces(ax)
# 在网格面中心标注面索引
for face_index, (face_x, face_y) in enumerate(
zip(mesh2d_output_0.face_x, mesh2d_output_0.face_y)
):
ax.text(face_x, face_y, face_index, ha="center", va="center", fontsize=22)
meshkernel 还会查找边的中点,并将其作为属性添加到 Mesh2D 类中。
fig, ax = plt.subplots()
ax.plot(mesh2d_output_0.edge_x, mesh2d_output_0.edge_y, ".");
目前网格看起来仍然是结构化的。接下来添加几个节点,改变它的结构。
node_index_0 = mk.mesh2d_insert_node(4.0, 1.5)
node_index_1 = mk.mesh2d_insert_node(4.0, 2.5)
还需要将新增节点连接起来,否则 meshkernel 会将未连接的节点清理掉。
edge_index_0 = mk.mesh2d_insert_edge(7, node_index_0)
edge_index_1 = mk.mesh2d_insert_edge(node_index_0, node_index_1)
edge_index_3 = mk.mesh2d_insert_edge(node_index_1, 11)
获取更新后的状态。
mesh2d_output_1 = mk.mesh2d_get()
绘制输出网格,可以看到 meshkernel 已立即识别出一个新的网格面。
fig, ax = plt.subplots()
mesh2d_output_1.plot_faces(ax)
# 在网格面中心标注面索引
for face_index, (face_x, face_y) in enumerate(
zip(mesh2d_output_1.face_x, mesh2d_output_1.face_y)
):
ax.text(face_x, face_y, face_index, ha="center", va="center", fontsize=22)
也可以删除节点。
mk.mesh2d_delete_node(node_index_1)
mesh2d_output_2 = mk.mesh2d_get()
网格重新变成六个面,但仍留有一条悬挂边。
fig, ax = plt.subplots()
mesh2d_output_2.plot_edges(ax, color="blue")
悬挂边通常是不需要的,因此 meshkernel 提供了处理它们的方法。首先,可以统计悬挂边的数量。
hanging_edges = mk.mesh2d_get_hanging_edges()
assert hanging_edges.size == 1
meshkernel 还可以查找并删除悬挂边。
mk.mesh2d_delete_hanging_edges()
mesh2d_output_3 = mk.mesh2d_get()
删除悬挂边后,网格恢复到最初的状态。
fig, ax = plt.subplots()
mesh2d_output_3.plot_edges(ax, color="blue")






