216 lines
5.7 KiB
Markdown
216 lines
5.7 KiB
Markdown
# 二维网格基础
|
|
|
|
本教程介绍 `meshkernel` 库的基本用法。
|
|
|
|
`meshkernel` 可以创建和操作多种网格。
|
|
|
|
最常见的应用涉及二维非结构网格,因此本教程重点介绍这类网格。
|
|
|
|
[返回示例目录](index.md)
|
|
|
|
以下保留原笔记本的代码和已保存输出;转换过程中未重新执行代码。
|
|
|
|
首先导入所需的库。
|
|
|
|
```python
|
|
import matplotlib.pyplot as plt
|
|
import numpy as np
|
|
|
|
from meshkernel import GeometryList, MakeGridParameters, MeshKernel, ProjectionType
|
|
```
|
|
|
|
`meshkernel` 提供了一组便捷方法,用于创建常见网格。
|
|
|
|
这里使用 `curvilinear_compute_rectangular_grid` 方法创建一个简单的曲线网格。该方法的完整参数请参阅相应文档。
|
|
|
|
```python
|
|
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`。
|
|
|
|
```python
|
|
mk.curvilinear_convert_to_mesh2d()
|
|
```
|
|
|
|
```python
|
|
mesh2d_input = mk.mesh2d_get()
|
|
```
|
|
|
|
`Mesh2D` 有三个必需属性,仅凭它们就可以完整描述任意非结构网格。
|
|
|
|
前两个属性是 `node_x` 和 `node_y`,它们是一维 `double` 数组,用来描述节点的位置,如下图所示。
|
|
|
|
```python
|
|
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 等索引对分别表示一条边。
|
|
|
|
```python
|
|
mesh2d_input.edge_nodes
|
|
```
|
|
|
|
```text
|
|
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)
|
|
```
|
|
|
|
结合这三个参数即可绘制网格。
|
|
|
|
```python
|
|
fig, ax = plt.subplots()
|
|
mesh2d_input.plot_edges(ax, color="blue")
|
|
```
|
|
|
|

|
|
|
|
要与 `meshkernel` 库交互,首先创建一个 `MeshKernel` 类实例。
|
|
|
|
构造函数的 `projection` 参数用于指定网格采用笛卡尔坐标(`ProjectionType.CARTESIAN`)还是球面坐标(`ProjectionType.SPHERICAL`)。
|
|
|
|
```python
|
|
mk = MeshKernel(projection=ProjectionType.CARTESIAN)
|
|
```
|
|
|
|
每个实例都维护各自的状态,可以通过对应的获取和设置方法访问这些状态。
|
|
|
|
```python
|
|
mk.mesh2d_set(mesh2d_input)
|
|
```
|
|
|
|
```python
|
|
mesh2d_output_0 = mk.mesh2d_get()
|
|
```
|
|
|
|
刚才设置了 `mesh2d`,随后立即将它取出,期间没有要求 `meshkernel` 执行其他操作。
|
|
|
|
设置 `mesh2d` 后,`meshkernel` 已计算出网格面数据和边的坐标。
|
|
|
|
```python
|
|
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` 类中。
|
|
|
|
```python
|
|
fig, ax = plt.subplots()
|
|
ax.plot(mesh2d_output_0.edge_x, mesh2d_output_0.edge_y, ".");
|
|
```
|
|
|
|

|
|
|
|
目前网格看起来仍然是结构化的。接下来添加几个节点,改变它的结构。
|
|
|
|
```python
|
|
node_index_0 = mk.mesh2d_insert_node(4.0, 1.5)
|
|
node_index_1 = mk.mesh2d_insert_node(4.0, 2.5)
|
|
```
|
|
|
|
还需要将新增节点连接起来,否则 `meshkernel` 会将未连接的节点清理掉。
|
|
|
|
```python
|
|
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)
|
|
```
|
|
|
|
获取更新后的状态。
|
|
|
|
```python
|
|
mesh2d_output_1 = mk.mesh2d_get()
|
|
```
|
|
|
|
绘制输出网格,可以看到 `meshkernel` 已立即识别出一个新的网格面。
|
|
|
|
```python
|
|
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)
|
|
```
|
|
|
|

|
|
|
|
也可以删除节点。
|
|
|
|
```python
|
|
mk.mesh2d_delete_node(node_index_1)
|
|
mesh2d_output_2 = mk.mesh2d_get()
|
|
```
|
|
|
|
网格重新变成六个面,但仍留有一条悬挂边。
|
|
|
|
```python
|
|
fig, ax = plt.subplots()
|
|
mesh2d_output_2.plot_edges(ax, color="blue")
|
|
```
|
|
|
|

|
|
|
|
悬挂边通常是不需要的,因此 `meshkernel` 提供了处理它们的方法。首先,可以统计悬挂边的数量。
|
|
|
|
```python
|
|
hanging_edges = mk.mesh2d_get_hanging_edges()
|
|
assert hanging_edges.size == 1
|
|
```
|
|
|
|
`meshkernel` 还可以查找并删除悬挂边。
|
|
|
|
```python
|
|
mk.mesh2d_delete_hanging_edges()
|
|
mesh2d_output_3 = mk.mesh2d_get()
|
|
```
|
|
|
|
删除悬挂边后,网格恢复到最初的状态。
|
|
|
|
```python
|
|
fig, ax = plt.subplots()
|
|
mesh2d_output_3.plot_edges(ax, color="blue")
|
|
```
|
|
|
|

|