You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -94,7 +95,7 @@ Component definitions consist primarily of a name, zero or more block definition
94
95
-`blocks`: block definitions
95
96
-`parent`: parent component(s)
96
97
-`schema_version`: DFN schema version
97
-
-`derived_dims`: dimensions computed from other dimensions
98
+
-`dims`: named dimensions (field-backed or derived) available for use in array shapes
98
99
99
100
Components may refer to, i.e. be constrained by, other components. Cross-component constraints include parent-child relations, solution compatibility, and format variants.
100
101
@@ -334,10 +335,6 @@ Type `integer`.
334
335
335
336
`[integer] | null`. Permitted values (enumeration constraint). Empty list is treated as absent.
336
337
337
-
###### `dimension`
338
-
339
-
`"record" | "component" | "model" | "simulation" | true | false | null (default: null)`. Declares this field as a dimension source and specifies its scope. See [Scope and resolution](#scope-and-resolution). A `true` value indicates `"component"` scope; `false` and `null` are equivalent.
340
-
341
338
###### `time_series`
342
339
343
340
`boolean (default: false)`. Marks fields where the parser accepts either a numeric literal or a time-series name (referencing a `utl-ts` object). Not inferable from structural type. Also appears on array fields (where it references a `utl-tas` object instead). Note that `utl-tas` currently only works with layered arrays, not full-grid arrays, though generalizing has been considered.
@@ -416,12 +413,6 @@ Each declared shape expression is either a global dimension name (explicit or de
416
413
417
414
`string | null (default: null)`. Names the field (within the same component) whose runtime length determines how many times this field is read sequentially within an array block, with each reading appended to an accumulated sequence. See `repeat` section below.
418
415
419
-
###### `dimension`
420
-
421
-
`"component" | "model" | "simulation" | null (default: null)`. Marks this self-sizing array as a dimension source at the given scope: the array's name may appear in other arrays' `shape` expressions to mean "one value per element of this array." Valid only on self-sizing arrays (`shape` must be empty); a schema error on arrays with a declared shape.
422
-
423
-
Because a self-sizing array is read inline and dynamically sized, the parser knows its element count immediately after reading the line — no separate integer field is needed to declare the size in advance. That count is what other arrays reference when they name this array in their `shape`. The dtype of the dimension-source array is not constrained: a string array whose elements are named identifiers (e.g. auxiliary variable names) and a numeric array whose elements happen to fix a count both provide the same thing to the shape system — a dynamic integer size. `"record"` scope is not valid for arrays.
424
-
425
416
#### Record
426
417
427
418
Type `record`. Product type. In MF6 input files, records appear on a single line. Record subfields may or may not be `tagged`. While blocks can be considered product types also, in the DFN specification only records are considered fields; blocks are considered named collections of related fields.
@@ -458,15 +449,33 @@ Type `list`. Collection type. Unlimited but for one rule: a list may not contain
458
449
459
450
### Array dimensions
460
451
461
-
A field defined in one component can be referenced by name in the `shape` expression of an array field in the same or another component. Two field types may serve as dimension sources:
452
+
Dimensions are declared at the component level via the `dims` map, not on individual fields. Each entry in `dims` is a `DimDef`:
453
+
454
+
```yaml
455
+
dims:
456
+
nlay:
457
+
field: nlay # backed by an integer field named 'nlay' in this component
458
+
scope: model
459
+
nodes:
460
+
expr: "nlay * nrow * ncol"# derived from other dims
461
+
scope: model
462
+
nper:
463
+
field: nper
464
+
scope: simulation
465
+
```
466
+
467
+
A `DimDef` has exactly one of:
468
+
- `field`: the name of an `integer` field in this component that provides the dimension value
469
+
- `expr`: a Python arithmetic expression that derives the dimension from other known dims
462
470
463
-
-`integer` fields with `dimension: true`
464
-
-`array` fields with `dtype: "string"` and `dimension: true` — the array's name becomes a valid shape dim meaning "one value per element of this string array"
471
+
And a `scope` (see [Scope and resolution](#scope-and-resolution)) that controls which other components can see it.
472
+
473
+
Self-sizing `array` fields (those with `shape: []`) may also serve as dimension sources: any such array's name may appear in a `shape` expression to mean "one element per item in this array." These are registered in `dims` with `field` pointing to the array name.
465
474
466
475
Shape expressions for non-string arrays may use one of three structural forms. All three may additionally carry a bound annotation:
467
476
468
477
- **Dim reference** (`^[A-Za-z_]\w*$`): a plain identifier resolved via the scope chain (explicit → derived → inherited dims). When the array is a subfield of a record and the identifier does not resolve globally, resolution falls back to intra-record sibling scope (see below).
469
-
-**Intra-record sibling reference**: a dim reference that names a sibling `integer`or `dimension: true``array`in the same enclosing record. Makes the record a variadic tuple whose width varies per row. Valid only when the array is a subfield of a record. See below.
478
+
- **Intra-record sibling reference**: a dim reference that names a sibling `integer` in the same enclosing record. Makes the record a variadic tuple whose width varies per row. Valid only when the array is a subfield of a record. See below.
470
479
- **Row-level column lookup** (`block.column(fk_field)`): a cross-list per-row quantity, valid only for array subfields of records. See below.
471
480
472
481
Any dim reference (either of the first two forms) may carry a **bound annotation** prefix (`<`, `>`, `<=`, or `>=`). The dim portion validates normally; the bound is advisory and is not enforced by the MF6 parser.
@@ -475,29 +484,37 @@ A shape expression that does not match one of these forms is a schema validation
475
484
476
485
#### Derived dimensions
477
486
478
-
The optional component attribute `derived_dims` maps dimension names to expressions with which to evaluate the dimension size. Expressions use Python arithmetic syntax. Operands may be:
487
+
A `DimDef` with an `expr` rather than a `field` is a derived dimension. Its expression uses Python arithmetic syntax. Operands may be:
479
488
480
-
- Explicit dimensions: any `dimension: true`fieldin this component
481
-
-Derived dimensions: another derived dimension; circular dependencies are a schema error
489
+
- Explicit dimensions: any field-backed dim in this component's `dims`
490
+
- Other derived dims: another derived dim in this component; circular dependencies are a schema error
482
491
- Functions of columns in a tabular list block: `sum(block.list.column)`sums the integer values of `column` across all rows of list field `list` in block `block`. When the list field shares its name with its containing block — the MF6 convention — the block qualifier may be omitted: `sum(list.column)`.
483
492
493
+
Derived dims carry the same `scope` as field-backed dims and are visible to other components under the same rules.
494
+
484
495
Canonical examples:
485
496
486
497
```yaml
487
-
# gwf-dis: nodes is derived; ncpl is also derived to give packages a uniform
488
-
# per-layer cell count dim regardless of discretization type (DISV has ncpl
489
-
# as an explicit dim; DIS derives it from nrow * ncol)
A record may also be a variadic tuple without any FK-linked list. If a record contains an `integer` field (or a string-dim `array`) followed by an `array` whose shape names that preceding field, the record is self-describing: it carries its own count. The `array`'s shape element is a plain identifier that resolves to the sibling field, not to a global dim.
577
+
A record may also be a variadic tuple without any FK-linked list. If a record contains an `integer` field followed by an `array` whose shape names that field, the record is self-describing: it carries its own count. The `array`'s shape element is a plain identifier that resolves to the sibling field, not to a global dim.
561
578
562
579
```yaml
563
580
connectiondata:
@@ -580,7 +597,7 @@ connectiondata:
580
597
581
598
Validation rules:
582
599
- Valid only when the array is a subfield of a record (not a top-level block field).
583
-
- The sibling field must be an `integer` with `dimension: "record"`. The `"record"` scope annotation makes the role explicit and prevents accidental resolution of unrelated integer fields.
600
+
- The sibling field must be an `integer`. No special annotation is required on the sibling.
584
601
- Resolution order: the scope chain is tried first; sibling resolution is only the fallback when the identifier does not resolve globally.
585
602
586
603
#### Bound-annotated shape expressions
@@ -598,28 +615,29 @@ sfacval:
598
615
599
616
Dim references (plain identifiers) resolve in this order:
600
617
601
-
1. Local explicit dims: `integer`fields with `dimension` set and self-sizing `array` fields (i.e. `shape: []`) with `dimension` set, in this component
602
-
2. Local derived dims: entries in this component's `derived_dims`, resolved in dependency order
603
-
3. Inherited dims: explicit dims from other components in the spec (filtered by scope — `"model"` dims available to packages in the same model, `"simulation"` dims available to all)
604
-
4. Intra-record siblings with `dimension: "record"`: a sibling `integer` in the same enclosing record that has been explicitly marked as a per-row inline count — fallback when steps 1–3 all fail and the array is inside a record.
618
+
1. **Local dims**: entries in this component's `dims` map — both field-backed and derived — resolved in dependency order.
619
+
2. **Inherited dims**: dims from other components in the spec, filtered by their `scope` and the requesting component's `parent` attribute (see below).
620
+
3. **Intra-record sibling**: a sibling `integer` in the same enclosing record — fallback when steps 1–2 fail and the array is inside a record.
605
621
606
622
Row-level column lookups and bound annotations (`<dim` etc.) are not resolved via this scope chain. Row-level lookups are evaluated per row at parse time using the FK relationship. Bound annotations are advisory only.
607
623
608
-
#### Explicit dimension scope
624
+
#### Dimension scope
609
625
610
-
The `dimension` attribute is categorical, not binary. Valid values differ by field type:
626
+
Each `DimDef` carries a `scope: "component"| "model" | "simulation"` that determines which other components can inherit it:
- For `array` (self-sizing only, i.e. `shape: []`): `"component" | "model" | "simulation" | null`
628
+
- **`"component"`**: only visible within this component (or to subpackages that list this component as their explicit parent).
629
+
- **`"model"`**: visible to any component that can share the same model instance, determined dynamically from `parent` attributes. A dim defined in component A (with `scope: "model"`) is visible to component B when:
630
+
- A's `parent` contains a concrete model-name entry (e.g. `"gwf-nam"`, `"chf-nam"`) — meaning A is model-attached, and
631
+
- B's `parent` contains either that same model-name entry, or a generic type (`"model"`, `"package"`, `"*"`) — meaning B can belong to the same model.
632
+
633
+
This means `"model"` scope is not tied to any specific model type. A package that can attach to any model (e.g. a utility with `parent: "package"`) inherits model-scoped dims from whichever grid discretization is in its model.
614
634
615
-
Meanings:
616
-
- `null` (default): not a dimension source.
617
-
- `"record"`: intra-record scope. The integer field is an inline count on the same record row. Valid only on `integer`. Makes the sibling-resolution fallback (scope level 4) explicit and annotated.
618
-
- `"component"`: available within this component.
619
-
- `"model"`: exported to model scope; available to all packages whose parent is the same model. Example: `nrow`, `ncol`, `nlay` in `gwf-dis` are model-scoped — accessible to `gwf-chd`, `gwf-wel`, and all other packages in the same GWF model.
620
-
- `"simulation"`: exported to simulation scope; available to all components. Example: `nper` in `sim-tdis`.
635
+
- **`"simulation"`**: always visible to all components.
621
636
622
-
Dimension `true` is equivalent to `"component"`, `false` to `null`.
637
+
Examples:
638
+
- `nrow`, `ncol`, `nlay` in `gwf-dis` — `scope: "model"` — accessible to `gwf-chd`, `gwf-wel`, `utl-spca` (which has `parent: "package"`), and any other component attached to the same GWF model.
639
+
- `nper` in `sim-tdis` — `scope: "simulation"` — accessible everywhere.
640
+
- `total_lake_connections` in `gwf-lak` — `scope: "component"` — private to that component.
0 commit comments