第19章 Sandbox与实验模块

Advanced Experimental

oggm/sandbox/ 目录包含了一系列实验性、面向研究且成熟度较低的模块。与核心 OGGM 包不同,sandbox 模块不受相同的 API 稳定性保证、全面测试或性能基准的约束。它们充当新物理机制、替代参数化方案、教育工具和跨模型兼容层的试验场。本章概述 sandbox 的内容,解释 sandbox 模块与核心模块的区别,并提供何时以及如何使用它们的指导。

19.1 Sandbox 的设计理念

sandbox 是 OGGM 架构中经过深思熟虑的设计选择。冰川建模是一个活跃的研究领域,新方法不断在文献中出现。OGGM 没有将每一项新技术立即集成到稳定的核心中(那样将需要无限期地维护向后兼容性),而是提供了一个 sandbox,让贡献者可以自由地进行实验。

19.1.1 核心模块 vs. Sandbox 模块:关键区别

标准核心模块Sandbox 模块
API 稳定性 语义化版本控制;移除前需要弃用周期 无稳定性保证;可能在版本间变更或消失
测试覆盖率 合并前需要单元测试;CI 门控 测试可选或极少;可能依赖手动验证
文档 Sphinx 文档字符串 + 用户指南条目 极少;通常仅有源码注释或 notebook
参数处理 params.cfg 中注册并设置默认值 可能使用硬编码值或独立配置
性能 已做性能分析;期望进行大规模优化 "在我机器上能跑"是可接受的
用途 常用建模流程 研究探索、教学、模型对比
警告 未经彻底独立验证的 sandbox 模块不应用于已发表的科学成果。OGGM 开发者明确指出,sandbox 代码可能包含已知局限、未经验证的假设或数值不稳定性。
Sandbox风险分级
等级可以怎样用发表前最低要求
教学/演示帮助理解概念或快速画图不要直接作为定量结论来源。
论文复现实验复现某篇论文或某个模块作者的实验固定OGGM版本、记录参数、复现原始案例。
方法探索开发新参数化或比较替代方案与核心工作流、观测或独立模型交叉验证。
正式区域应用不建议直接使用需要测试、敏感性分析、误差评估和清晰的方法说明。

19.2 模块:calving_fabi.py

sandbox/calving_fabi.py 实现了基于 Fabien Maussion 及其合作者研究的替代性崩解参数化方案。该模块提供的崩解速率估算在水深、应变率和锋面消融处理方面与核心 OGGM 崩解方案不同。

19.2.1 设计原理

崩解是冰川预测中最大的不确定性来源之一。核心 OGGM 模型使用简单的依赖水深的崩解率(即 "k-calving" 法则)。Fabi 参数化方案对此进行了扩展,包括:

19.2.2 关键函数

calving_rate_fabi()

def calving_rate_fabi(gdir, calving_water_level='Lmax',
                      use_beta=False, glen_a=None,
                      write=True, filesuffix=''):
    """Compute calving rate using the Fabi parameterization.

    Parameters
    ----------
    gdir : GlacierDirectory
        The glacier directory (must have inversion_output.pkl).
    calving_water_level : str or float
        Water level reference: 'Lmax' (last observed), 'L0' (bed topo),
        or a fixed elevation value.
    use_beta : bool
        If True, include strain-rate-dependent calving.
    glen_a : float, optional
        Override the default Glen A parameter for this computation.
    write : bool
        If True, save calving output to the glacier directory.
    filesuffix : str
        Suffix appended to output filenames for multi-scenario runs.

    Returns
    -------
    dict
        Dictionary containing calving_rate (m/yr), calving_flux (km3/yr),
        and per-flowline diagnostics.
    """

calving_flux_from_depth_fabi()

def calving_flux_from_depth_fabi(gdir, water_level=None,
                                    glen_a=None, write=False):
    """Compute the total frontal calving flux using the Fabi approach."""

19.2.3 使用示例

import oggm
from oggm import workflow
from oggm.sandbox import calving_fabi

# Standard OGGM preprocessing
cfg.initialize()
gdirs = workflow.init_glacier_directories(['RGI60-11.00897'])
workflow.execute_entity_task(workflow.gis_prepro_tasks, gdirs)
workflow.execute_entity_task(workflow.climate_tasks, gdirs)
workflow.execute_entity_task(workflow.inversion_tasks, gdirs)

# Apply Fabi calving with strain-rate dependence
for gdir in gdirs:
    result = calving_fabi.calving_rate_fabi(
        gdir, use_beta=True, calving_water_level='Lmax'
    )
    print(f"Calving rate: {result['calving_rate']:.1f} m/yr")
    print(f"Calving flux: {result['calving_flux']:.4f} km³/yr")

19.3 模块:calving_jan.py

sandbox/calving_jan.py 提供了另一种崩解参数化方案,由 Jan-Hendrik Malles 开发。该方法强调水下融化和峡湾环流在驱动海洋终止型冰川崩解中的作用。

19.3.1 概念模型

Jan 崩解方案将崩解视为以下因素的产物:

  1. 水下融化掏蚀:海洋热通量侵蚀末端的淹没部分,形成突出的悬垂冰体,最终发生力学破坏。
  2. 热刻槽破坏:当融化导致的刻槽深度超过冰厚的临界比例时,水上冰崖发生崩塌。
  3. 崩解率-融化率比值:崩解率被参数化为水下融化率的函数,采用经验推导的比例常数。

19.3.2 关键函数

def calving_rate_from_depth_jan(gdir, melt_f=None, water_level=0,
                                 write=True, filesuffix=''):
    """Calving rate based on submarine melt undercutting.

    The calving rate C is computed as:
        C = k_m * m_dot * (d / H)
    where k_m is an empirical constant, m_dot is the submarine melt rate,
    d is water depth, and H is terminus ice thickness.

    Parameters
    ----------
    gdir : GlacierDirectory
    melt_f : float, optional
        Submarine melt factor. If None, uses cfg.PARAMS['melt_f'].
    water_level : float
        Reference water level elevation (m a.s.l.).
    write : bool
    filesuffix : str

    Returns
    -------
    dict with 'calving_rate' and 'calving_flux' keys.
    """

19.3.3 崩解方法的比较

特性核心 k-calvingFabi (calving_fabi)Jan (calving_jan)
主要驱动水深水深 + 应变率水下融化
参数calving_kcalving_k, glen_a, betamelt_f, k_m
峡湾几何宽度效应(可选)
计算成本
验证程度多区域有限区域单一峡湾

19.4 模块:distribute_2d.py

sandbox/distribute_2d.py 解决了流线模型的一个根本性局限:如何从一维流线反演结果重建二维冰厚场。这是将 OGGM 与区域气候模型耦合或在完整二维网格上可视化冰川几何形态的关键步骤。

19.4.1 分布问题

OGGM 沿一维流线运行其质量守恒反演。结果是沿每条流线的厚度剖面。要获得网格化产品,必须将厚度横向"分布"到整个冰川集水区。这是一个欠定问题:无限多个二维场可以投影到同一个一维剖面上。

19.4.2 算法

distribute_thickness_per_altitude()

def distribute_thickness_per_altitude(gdir, varname='distributed_thickness',
                                       add_slope=True,
                                       smooth_radius=None):
    """Distribute flowline thickness to each grid point.

    Algorithm:
    1. Compute distance-to-flowline for every grid cell.
    2. At each altitude band, assign the flowline thickness value.
    3. Optionally add a slope-dependent correction (thicker in concave areas).
    4. Optionally smooth the result with a Gaussian filter.

    Parameters
    ----------
    gdir : GlacierDirectory
    varname : str
        Name of output grid variable.
    add_slope : bool
        Include slope-dependent thickness correction.
    smooth_radius : float, optional
        Smoothing kernel radius in meters.
    """

distribute_thickness_interp()

def distribute_thickness_interp(gdir, add_slope=True,
                                 smooth_radius=None):
    """Alternative interpolation-based distribution method.

    Uses inverse-distance-weighted interpolation from the flowline
    centerline outward, rather than altitude-band assignment.
    """

19.4.3 使用示例

from oggm.sandbox import distribute_2d

# After running inversion...
for gdir in gdirs:
    distribute_2d.distribute_thickness_per_altitude(
        gdir, add_slope=True, smooth_radius=200
    )
    # Now gdir.gridded_data has 'distributed_thickness' variable
提示:验证 二维分布厚度可以通过将其投影回流线并与原始一维反演进行比较来验证。一维和二维表示之间总冰体积的守恒也是一个有用的诊断指标。

19.5 模块:edu.py

sandbox/edu.py 是一个专为冰川动力学教学而设计的教育模块。它实现了简化的、解析可解的冰川模型,可以在 Jupyter notebook 中交互运行,无需完整的 OGGM 预处理流程。

19.5.1 教育模型

IdealisedBedrock

class IdealisedBedrock:
    """A simple, analytically-defined bedrock profile.

    Supports:
    - Linear beds: z_b(x) = z_max - slope * x
    - Parabolic beds: z_b(x) = z_max - (z_max - z_min) * (x/L)²
    - Custom polynomial beds

    Parameters
    ----------
    top_z : float
        Elevation at the head (m).
    bottom_z : float
        Elevation at the terminus (m).
    width : float
        Constant glacier width (m).
    length_km : float
        Glacier length (km).
    """

BumpedBedrock(前身为 IdealisedGlacier)

class BumpedBedrock(IdealisedBedrock):
    """Adds a Gaussian bump to the bedrock for more realistic geometry."""

ShallowIceApproximationModel

class ShallowIceApproximationModel:
    """A didactic implementation of the SIA glacier model.

    This model explicitly shows the physics without the optimization
    complexity of the production FluxBasedModel. Students can read
    the source code and understand every line.

    The model solves:
      ∂H/∂t = -∂(u_bar * H * w)/∂x / w + b_dot
    where u_bar is the depth-averaged velocity from the SIA.
    """

19.5.2 面向教学的设计

edu.py 的主要教育特性:

19.5.3 示例:运行教育模拟

from oggm.sandbox.edu import BumpedBedrock, ShallowIceApproximationModel
import numpy as np

# Create an idealized glacier geometry
bed = BumpedBedrock(
    top_z=3600, bottom_z=1200, width=300, length_km=10,
    bump_amplitude=100, bump_position=0.4
)

# Initialize the SIA model
model = ShallowIceApproximationModel(
    bed=bed, nx=200, glen_a=2.4e-24,
    mb_model='seasonal', ela=2800
)

# Run to equilibrium
model.run_to_equilibrium(rtol=1e-3, max_years=500)

# Plot the profile
model.plot(title="Equilibrium Glacier Profile")

# Inspect mass budget
print(f"Total volume: {model.volume_km3:.3f} km³")
print(f"Max thickness: {model.thickness.max():.1f} m")
print(f"ELA: {model.ela:.0f} m a.s.l.")

19.6 模块:pygem_compat.py

sandbox/pygem_compat.py 提供了 OGGM 与 PyGEM(Python Glacier Evolution Model,由 David Rounce 及其合作者开发)之间的兼容层。PyGEM 是一个独立的冰川模型,常用于全球尺度的预测,在模型对比研究中经常与 OGGM 一起被引用。

19.6.1 目的

该兼容层支持以下功能:

19.6.2 关键函数

convert_oggm_to_pygem()

def convert_oggm_to_pygem(gdir, output_dir=None):
    """Convert OGGM GlacierDirectory into PyGEM input format.

    Extracts: RGI metadata, hypsometry, climate timeseries,
    and ice thickness (if available).

    Parameters
    ----------
    gdir : GlacierDirectory
    output_dir : str, optional
        Directory for PyGEM input files.

    Returns
    -------
    dict
        PyGEM-compatible glacier dictionary.
    """

run_pygem_from_oggm()

def run_pygem_from_oggm(gdir, pygem_params=None,
                         n_years=None, output_dir=None):
    """Run PyGEM model from an OGGM glacier directory.

    Handles all data conversion internally and returns results
    in a standardized format for comparison.
    """

compare_oggm_pygem()

def compare_oggm_pygem(gdir, oggm_run_output=None,
                       pygem_run_output=None):
    """Generate a diagnostic comparison between OGGM and PyGEM runs.

    Returns a DataFrame with annual values of:
    - Specific mass balance
    - Volume change
    - Area change
    for both models.
    """

19.7 其他 Sandbox 模块

除上述主要模块外,sandbox 还包含若干较小的工具:

sandbox/gmd_paper_mbcrossval.py

实现了 OGGM GMD 论文中描述的物质平衡交叉验证方法。该模块系统地测试校准后的物质平衡参数对不同校准周期、参考数据集和冰川子集的敏感性。

sandbox/grindelwald_demo.py

一个演示 notebook 配套文件,对 Grosser Aletschgletscher 及其他瑞士冰川的历史演变进行建模。展示了如何为具有长期物质平衡和长度变化记录的、观测充分的冰川设置 OGGM。

sandbox/idealisepy_glaciers.py(遗留)

edu.py 的前身,保留以兼容引用旧类名的 notebook。

19.8 何时使用 Sandbox 模块

使用场景推荐模块注意事项
格陵兰研究的替代崩解方案 calving_fabi.py 需先用观测数据验证
水下融化驱动崩解(阿拉斯加) calving_jan.py 融化速率参数约束较差
用于区域气候模型的二维厚度图 distribute_2d.py 分布过程增加不确定性;需量化
向学生教授冰川动力学 edu.py 不适合定量预测
与 PyGEM 的跨模型对比 pygem_compat.py 需要安装 PyGEM

19.9 为 Sandbox 贡献代码

OGGM 欢迎 sandbox 贡献。sandbox 的纳入门槛比核心模块低:

第20章 扩展OGGM →