Declarations and preparation
After opening an input file, swmmrs allows selected model inputs to be changed
programmatically. These changes are declarations: they state the scenario the
caller wants the next run to use. This is not yet a general-purpose editor for
every SWMM input section. The API reference identifies editable properties;
curves, time series, patterns, land uses, pollutants, controls, and several other
definition families currently remain read-only.
A declaration is not always copied directly into the active solver. Many SWMM
values depend on other objects or require unit conversion, normalization, or
geometry calculations. swmmrs therefore separates accepting requested inputs
from preparing one internally consistent solver model.
Requested and effective values
Consider a requested routing step, thread count, node invert, or conduit geometry:
- Your edit records the requested public value.
- The simulation becomes dirty if dependent solver values need rebuilding.
start()checks the complete requested model and calculates its effective, solver-ready values.- Only a completely successful preparation replaces the prior prepared model.
flowchart LR
EDIT["Requested edit"]
DIRTY["Dirty<br/>request retained"]
PREP["start()<br/>whole-model preparation"]
CLEAN["Clean<br/>requested and prepared agree"]
RUN["Running"]
REPAIR["Diagnostics<br/>repair requested values"]
EDIT --> DIRTY --> PREP
PREP --> CLEAN --> RUN
PREP --> REPAIR --> DIRTY
A read of a declaration-backed property continues to show what you requested,
even before preparation and after a failed preparation. A specifically named
effective or prepared property reports what the solver actually selected
or derived. For example, requested_threads is an input request, while
effective_threads is known after startup.
Clean and dirty do not mean valid and invalid
| Status | Meaning | What to do |
|---|---|---|
| Clean | The accepted declarations agree with the prepared solver values. | Start or rerun normally. |
| Dirty | At least one accepted declaration requires preparation before routing. | Finish the edits, then call start(). |
| Dirty after failed preparation | Requested values conflict at the whole-model level; the previous prepared model was not partially replaced. | Inspect diagnostics, repair declarations, and retry start(). |
Dirty is an engineering workflow state, not a quality judgment. It intentionally allows temporary inconsistencies while a multi-object scenario is assembled. For example, you can change related elevations in separate calls and resolve the relationship before starting.
Two levels of checking
At assignment time, swmmrs checks facts that can be judged from the value
itself: type, finiteness, representable units, intrinsic range, and applicable
object subtype.
At start time, preparation checks relationships that require the prospective model as a whole: dates and steps, topology, elevations, geometry, selected patterns, LID relationships, and other cross-object constraints.
A start-time ConfigurationError contains ordered diagnostics. It does not
mean that half of the dependent geometry was updated. The requested values stay
available for inspection and repair.
What atomic means
An operation is atomic when it has an all-or-nothing effect.
- A grouped declaration update either accepts the complete candidate or leaves the prior declaration unchanged.
- Configuration preparation either installs the complete solver-ready model or retains the previous prepared model.
- A rejected candidate does not leave a mixture of old and new fields.
Atomicity is especially important for schedules, options, and object definitions
whose fields are meaningful only together. Prefer grouped update(...) methods
when changing related properties.
Atomic does not mean that every logically related object must be edited in one
call. Cross-object edits can be made in stages while dirty; they become one
prepared model only after successful start().
What idempotent means here
Preparation derives solver values from the authoritative requested declarations, not by repeatedly modifying the last derived result. Repeating preparation with the same declarations is intended to produce the same prepared model rather than compound conversions, offsets, or geometry changes. Empty or unchanged updates are no-ops where the declaration API supports them.
This matters for parameter sweeps and reruns: a value expressed in project units should not be converted again merely because a model was prepared more than once. Idempotence does not mean rerunning the hydraulic simulation produces no work, nor does it make two different floating-point execution paths identical.
Not every write is a declaration
Choose the operation by meaning, not only by the object being changed:
| Operation | Example | Effect |
|---|---|---|
| Stable declaration | Pipe geometry, node initial depth, dates, options | May mark configuration dirty; prepared at start(). |
| Metadata or reporting edit | Tag or isolated report selection | Usually does not require hydraulic preparation. |
| Persistent forcing | Measured inflow, forecast rain, boundary stage | Kept separately and reapplied according to its lifecycle contract. |
| Runtime control | Gate target during routing | Changes a future routing operation, not stable model geometry. |
| Result read | Current depth or copied statistics | Observes state; does not configure it. |
After a completed run
A preparation-dependent declaration accepted after end() returns the owner to
OPEN and resets completed-run clock and report-period bookkeeping for the next
run. Copy required final statistics and write the report before beginning the
next scenario.
For methods and diagnostic examples, see Configure a model. Continue with Solver lifecycle to place preparation in the complete run sequence.