agentsclimarketplace

Run2 glm lake mendota setup

Skill cxcscmu/SkillLearnBench/skills/b3-teacher-feedback-claude-sonnet-4-6/temperature-simulation/run2_glm_lake_mendota_setup

Use this skill to understand the GLM (General Lake Model) configuration for Lake Mendota, including how to read and modify the glm3.nml file, what parameters are allowed to change, and how the model is structured. Apply this before running or calibrating GLM.From its SKILL.md

Install
npx -y skills add cxcscmu/SkillLearnBench --skill run2_glm_lake_mendota_setup

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

SKILL.md

3.3 KB, 866 tokens by cl100k_base, as published. Nobody here has run it

GLM Lake Mendota Setup

Allowed Calibration Parameters

Only these five parameters may be modified in /root/glm3.nml:

  • Kw — light extinction coefficient, range [0.1, 0.5]
  • coef_mix_hyp — hypolimnetic mixing coefficient, range [0.3, 0.7]
  • wind_factor — wind scaling factor, range [0.7, 1.3]
  • lw_factor — longwave radiation scaling, range [0.7, 1.3]
  • ch — bulk aerodynamic heat transfer coefficient, range [0.0005, 0.002]

Do NOT change: sw_factor, cd, ce, the_depths, the_temps, the_sals, or any other settings.

Reading and Modifying glm3.nml

import re

def read_nml_param(nml_path, param_name):
    """Read a single parameter value from the NML file."""
    with open(nml_path, 'r') as f:
        content = f.read()
    pattern = rf'^\s*{param_name}\s*=\s*([^\n,!]+)'
    match = re.search(pattern, content, re.MULTILINE)
    if match:
        return float(match.group(1).strip())
    raise ValueError(f"Parameter {param_name} not found in {nml_path}")

def write_nml_param(nml_path, param_name, value):
    """Write a single parameter value to the NML file."""
    with open(nml_path, 'r') as f:
        content = f.read()
    pattern = rf'(^\s*{param_name}\s*=\s*)([^\n,!]+)'
    replacement = rf'\g<1>{value}'
    new_content = re.sub(pattern, replacement, content, flags=re.MULTILINE)
    if new_content == content:
        raise ValueError(f"Parameter {param_name} not found or not replaced in {nml_path}")
    with open(nml_path, 'w') as f:
        f.write(new_content)

def get_lake_depth_from_nml(nml_path):
    """Get the fixed lake depth (crest_elev - base_elev) from morphometry block."""
    with open(nml_path, 'r') as f:
        content = f.read()
    # Try lake_depth first
    m = re.search(r'^\s*lake_depth\s*=\s*([^\n,!]+)', content, re.MULTILINE)
    if m:
        return float(m.group(1).strip())
    # Fallback: crest_elev - bsn_bot or lake_depth from morphometry
    ce = re.search(r'^\s*crest_elev\s*=\s*([^\n,!]+)', content, re.MULTILINE)
    be = re.search(r'^\s*bsn_bot\s*=\s*([^\n,!]+)', content, re.MULTILINE)
    if ce and be:
        return float(ce.group(1).strip()) - float(be.group(1).strip())
    raise ValueError("Cannot determine lake_depth from NML file")

Running GLM

import subprocess
import os

def run_glm(glm_dir='/root'):
    """Run GLM from the given directory. Returns (returncode, stdout, stderr)."""
    result = subprocess.run(
        ['glm'],
        cwd=glm_dir,
        capture_output=True,
        text=True
    )
    return result.returncode, result.stdout, result.stderr

def glm_ran_successfully(glm_dir='/root'):
    """Check that GLM ran and produced output."""
    output_path = os.path.join(glm_dir, 'output', 'output.nc')
    rc, stdout, stderr = run_glm(glm_dir)
    if rc != 0:
        print("GLM STDERR:", stderr[-2000:])
        return False
    if not os.path.exists(output_path):
        print("Output file not found:", output_path)
        return False
    return True

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.