You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flopy中为MF6 DISV网格创建SFR输入?基于Shapefile/Shapely LineString的实现方案咨询

处理MF6 DISV网格的SFR输入:从Shapefile到Flopy的实操方案

我刚好有过在MF6 DISV网格上搭建SFR模型的实操经验,针对你遇到的Shapefile/Shapely LineString转SFR输入的问题,分享几个可行的思路和具体实现方法:

一、Flopy中DISV网格创建SFR的通用逻辑

和结构化网格(DISU/DIS)不同,DISV的SFR是基于不规则单元格来定义河段(reach)的,核心逻辑是:

  1. 确定河流路径穿过的所有DISV单元格,把河流拆分成每个单元格内的子河段(每个子河段对应一个SFR reach);
  2. 为每个reach配置必要的水文地质属性(河床高程、水力传导系数、河流宽度等);
  3. 根据河流流向,建立reach之间的上下游连接关系;
  4. 用Flopy的ModflowGwfSfr类组装这些数据,生成MF6的SFR输入文件。

二、从Shapefile/Shapely LineString生成SFR输入的Python实现

下面是用geopandas、shapely和flopy组合实现的具体步骤:

步骤1:读取网格与河流数据

首先读取DISV单元格的多边形数据(可以从已有的Shapefile读取,或者直接从Flopy的DISV对象中提取),以及河流的Shapefile:

import geopandas as gpd
import shapely
import flopy

# 读取DISV单元格多边形(假设已导出为shapefile)
disv_cells = gpd.read_file("disv_cells.shp")
# 读取河流shapefile(确保是LineString类型)
river_lines = gpd.read_file("river_network.shp")

如果是从Flopy模型中提取单元格多边形,可以用以下方式生成:

# 假设gwf是已创建的MF6 GWF模型对象
disv = gwf.disv
cell_polygons = []
for cell_idx in range(disv.ncpl.get_data()):
    # 获取单元格的顶点坐标
    vertices = disv.vertices.get_data()[disv.cell2vert.get_data()[cell_idx]]
    polygon = shapely.Polygon(vertices)
    cell_polygons.append({"cellid": cell_idx, "geometry": polygon})
disv_cells = gpd.GeoDataFrame(cell_polygons, crs="EPSG:4326")  # 替换为你的坐标系

步骤2:匹配河流与单元格,拆分河段

对每条河流LineString,找到它相交的所有单元格,再把河流拆分成每个单元格内的子线段(每个子线段对应一个SFR reach):

from shapely.ops import split

all_reaches = []
current_reach_id = 1

# 遍历每条河流
for _, river in river_lines.iterrows():
    river_line = river.geometry
    # 筛选出与河流相交的单元格
    intersecting_cells = disv_cells[disv_cells.intersects(river_line)]
    
    # 用单元格边界分割河流线段,得到每个单元格内的子河段
    cell_boundaries = shapely.MultiPolygon(intersecting_cells.geometry.tolist()).boundary
    split_segments = split(river_line, cell_boundaries)
    
    # 为每个子河段关联对应的单元格和属性
    for seg in split_segments.geoms:
        # 通过子河段的质心找到所属单元格
        cell = intersecting_cells[intersecting_cells.contains(seg.centroid)].iloc[0]
        # 构建reach字典(属性根据你的Shapefile字段调整)
        reach = {
            "reachid": current_reach_id,
            "cellid": cell["cellid"],
            "length": seg.length,
            "strtop": river.get("river_elev", 100),  # 河流顶部高程,可从Shapefile取或设默认值
            "strbot": river.get("river_bed_elev", 95),  # 河床底部高程
            "strhc1": river.get("bed_k", 1e-4),  # 河床水力传导系数
            "width1": river.get("river_width", 10),  # 河流宽度
            "mannings": river.get("mannings", 0.03)  # 曼宁糙率系数
        }
        all_reaches.append(reach)
        current_reach_id += 1

步骤3:建立Reach上下游连接

根据河流的流向(拆分后的子线段顺序就是河流的流向),为每个reach设置上下游关联:

# 按河流分组处理连接(如果有多条河流,需要先按河流分组)
# 这里假设all_reaches是按单条河流的顺序排列的,若有多条河流需先分组
for i in range(len(all_reaches)):
    if i == 0:
        all_reaches[i]["upstream"] = 0  # 首段无上游
    else:
        all_reaches[i]["upstream"] = all_reaches[i-1]["reachid"]
    if i == len(all_reaches)-1:
        all_reaches[i]["downstream"] = 0  # 末段无下游
    else:
        all_reaches[i]["downstream"] = all_reaches[i+1]["reachid"]

步骤4:用Flopy创建SFR包

把整理好的reach数据转换成Flopy要求的格式,然后创建SFR包:

# 假设gwf是已初始化的MF6 GWF模型对象
# 整理reach_data:按MF6 SFR的参数顺序排列
reach_data = []
for r in all_reaches:
    reach_data.append((
        r["reachid"], r["cellid"], r["length"], r["strtop"], r["strbot"],
        r["strhc1"], r["width1"], r["mannings"], r["upstream"], r["downstream"]
    ))

# 创建SFR包
sfr = flopy.mf6.ModflowGwfSfr(
    gwf,
    nreaches=len(all_reaches),
    reach_data=reach_data,
    # 设置packagedata:定义SFR的整体配置,比如下游边界类型
    packagedata=[(0, "downstream", "free")],
    # 如果需要设置初始流量,可添加period_data
    period_data=[[(0, "flow", 100.0)]]  # 示例:所有reach初始流量100 m³/d
)

# 写入SFR输入文件
sfr.write_file()

三、注意事项与优化建议

  • 空间匹配精度:如果河流线段和单元格边界的匹配有误差,可以给河流线段加微小的buffer(比如river_line.buffer(0.1)),确保能正确匹配到单元格;
  • 属性补全:如果Shapefile缺少部分属性(比如河床高程),可以用DEM数据插值获取,或者参考区域水文地质资料设置合理默认值;
  • 参数验证:MF6的SFR参数较多,建议对照官方文档确认每个参数的含义和格式,避免参数顺序或类型错误;
  • 参考SFRmaker源码:虽然SFRmaker对DISV支持不完善,但可以参考它的空间匹配逻辑(比如线段拆分、单元格关联),修改后适配DISV网格。

内容的提问来源于stack exchange,提问作者nikobenho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 16:19:06