Skip to content

Add node_id validation#2983

Draft
visr wants to merge 2 commits intomainfrom
val-id
Draft

Add node_id validation#2983
visr wants to merge 2 commits intomainfrom
val-id

Conversation

@visr
Copy link
Member

@visr visr commented Mar 17, 2026

Fixes #1780
Fixes #905

As a draft since I still need to review, this is written by Claude.

Plan: Node-ID Consistency Validation via Schema Metadata

Add a node_id_relation trait to Julia schema table types, auto-generate it into Python schema classes, and implement validation in NodeModel that checks node_id consistency across tables.


Classification

Relation Meaning
"equal" Table's node_ids must exactly match the NodeModel's node_ids (default)
"subset" Table's node_ids must be a subset
"partition" All partition tables must be pairwise disjoint, union must equal all node_ids

Partition (static + time pairs): Pump, Outlet, PidControl, LevelBoundary, FlowBoundary, FlowDemand, LevelDemand, UserDemand, TabulatedRatingCurve, Basin

Equal (default): Basin profile/state/concentration/concentration_external/concentration_state, LevelBoundary/FlowBoundary/UserDemand concentration, DiscreteControl variable/condition/logic, ContinuousControl variable/function, ManningResistance static, LinearResistance static

Subset: Basin subgrid/subgrid_time/area, FlowBoundary area, Observation time

Changes Made

Julia — Single Source of Truth (config.jl)

  • Added node_id_relation(::Type{<:Table}) function with a default of :equal
  • Defined :partition overloads for all Static/Time pairs (Pump, Outlet, LevelBoundary, FlowBoundary, TabulatedRatingCurve, PidControl, UserDemand, LevelDemand, FlowDemand)
  • Defined :subset overloads for Basin.Static, Basin.Time (Basin forcing is optional per-node), Basin.Subgrid, Basin.SubgridTime, and Observation.Time
  • Exported node_id_relation

Codegen (gen_python.jl, schemas.py.jinja)

  • get_models() now includes node_id_relation per table type
  • Template emits _node_id_relation: str = "..." class variable on each schema class

Generated (schemas.py)

  • All 30+ schema classes now have _node_id_relation with correct values

Non-codegen schemas (area.py)

  • Added _node_id_relation = "subset" to BasinAreaSchema and FlowBoundaryAreaSchema

Validation logic (node.py)

  • Added _validate_node_ids() method to NodeModel that:
    • Checks "equal" tables: node_ids must match exactly
    • Checks "subset" tables: node_ids must be a subset
    • Checks "partition" tables: must be pairwise disjoint and their union must equal the full set

Wired into model validation (model.py)

  • _validate_model() now calls _validate_node_ids() on each node model

Tests (test_validation.py)

  • test_node_id_validation_valid — valid model passes
  • test_node_id_partition_overlap — node_id in both static and time raises
  • test_node_id_partition_missing — incomplete partition raises
  • test_node_id_equal_mismatch — missing node_id in equal table raises

Design Note

Basin.Static/Time are :subset rather than :partition because Basin forcing is optional per-node (Julia uses is_complete=false, defaulting to NaN). The disjointness between Basin static and time is still validated by Julia core at runtime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Validate data table node_ids against Node Check node ID in both Basin / static and Basin / time

1 participant