Connectivity Rule Domain Codes for Water Distribution Networks

A connectivity rule in a water-distribution utility network is only as reliable as the coded values behind it. Every rule is expressed in terms of an asset group, an asset type (subtype), a terminal, and the association it permits — and each of those is a domain code that must match exactly, or the rule silently fails to fire. When a service lateral carries the wrong subtype code, or a gate valve is loaded with a terminal count of one, the network will happily accept geometry that connects a hydrant directly to a transmission main, and no trace will complain until an isolation analysis returns a boundary that leaves customers energized who should be shut off. This reference collects the domain codes, terminal configurations, and permitted associations for a representative water-distribution network into a single table so engineers can validate features against a known baseline before they enable tracing. It is the code-level companion to the configuring connectivity rules for pipe and cable workflow, sits within the broader topology and tracing workflows discipline, and supplies the subtype and terminal facts that both valve and isolator mapping strategies and the containment model in asset hierarchy design for water and electric depend on.

Environment Prerequisites

The codes below are a baseline to validate against, not a substitute for reading your own deployed domains. Confirm the following before you trust them:

  • ArcGIS Pro 3.2+ with a Standard or Advanced license and arcpy importable from Python 3.11, so you can export the network’s actual coded-value domains with arcpy.da.ListDomains and compare them against this reference.
  • The deployed asset package — the codes in the table follow the conventions of a typical water-distribution data model, but every organization renumbers subtypes during configuration. Treat the exported domain as authoritative and this table as the shape it should take.
  • A validated Utility Network topology with terminal configurations already assigned to every device asset type; terminal counts drive the association rules and cannot be inferred from geometry.
  • networkx 3.x and geopandas 1.x pinned in an isolated environment for the validation helper, with feature data exported from a reconciled, unversioned snapshot rather than an open edit session.
  • Read access to the published connectivity rules so you can confirm the permitted junction-edge and edge-junction associations in the table match the rules actually enforced by the network.

Schema Validation Protocol — Run Before You Trust the Codes

Domain-code errors are quiet: the feature saves, the map draws, and only a trace exposes the fault. Work this ordered protocol first; the earliest item is the most common source of a wrong association.

  1. Confirm the subtype code exists in the deployed domain. Export the coded-value domain and check that every asset type in your data maps to a code present in this reference’s shape. A subtype value with no matching domain entry is unclassified and connects under no rule at all.
  2. Verify terminal counts match the device class. A line valve is a two-terminal device; a coupling is two-terminal; a tee is three-terminal; a cross is four-terminal. A device loaded with the wrong terminal count either over-connects or refuses valid associations.
  3. Check that permitted associations are directional-correct. A junction-edge rule (device-to-line) and an edge-junction rule (line-to-device) are distinct; a rule authored in only one direction leaves the reverse association unpermitted and breaks continuity.
  4. Reconcile structural containment against connectivity. A valve housed in a vault is structurally attached, not topologically connected through the vault; conflating the two, exactly the hazard described for valve and isolator mapping, fractures isolation boundaries.
  5. Validate before you trace. Never evaluate the table against a dirty-area backlog — run topology validation first so the codes you check reflect a consistent network state.

The Domain-Code Reference Table

The table maps each water-distribution asset group and asset type to its representative subtype domain code, terminal configuration, and the associations the connectivity rules should permit. Junction-edge associations describe which line assets a device or junction may connect to; edge-junction associations describe which devices or junctions a line may terminate against. Codes are grouped by feature class — mains and laterals (line), valves and hydrants and meters (device), and fittings and service points (junction).

Asset Group Asset Type (subtype) Domain code Terminal config Permitted junction–edge / edge–junction associations
Distribution Pipe (Line) Distribution Main 1 linear (no terminals) Gate Valve, Butterfly Valve, Hydrant Lateral, Tee, Cross, Reducer, Service Tap
Distribution Pipe (Line) Transmission Main 2 linear (no terminals) Gate Valve, Butterfly Valve, Air Release Valve, Tee, Cross, Reducer
Distribution Pipe (Line) Pressurized Lateral 3 linear (no terminals) Curb Stop, Meter, Tee, Coupling, Service Point
Service Pipe (Line) Service Lateral 41 linear (no terminals) Curb Stop, Water Meter, Service Point, Coupling
Service Pipe (Line) Hydrant Lateral 42 linear (no terminals) Hydrant, Gate Valve (auxiliary), Tee
Service Pipe (Line) Fire Service Lateral 43 linear (no terminals) Detector Check Valve, Water Meter, Service Point
Distribution Device (Junction) Gate Valve 101 2 (inlet / outlet) Distribution Main, Transmission Main, Hydrant Lateral
Distribution Device (Junction) Butterfly Valve 102 2 (inlet / outlet) Distribution Main, Transmission Main
Distribution Device (Junction) Check Valve 103 2 (inlet / outlet) Distribution Main, Pressurized Lateral
Distribution Device (Junction) Pressure Reducing Valve 104 2 (high / low side) Transmission Main, Distribution Main
Distribution Device (Junction) Air Release Valve 105 1 (inlet) Transmission Main, Distribution Main
Distribution Device (Junction) Curb Stop 106 2 (inlet / outlet) Service Lateral, Pressurized Lateral
Distribution Device (Junction) Detector Check Valve 107 2 (inlet / outlet) Fire Service Lateral
Hydrant (Device) Dry-Barrel Hydrant 121 1 (inlet) Hydrant Lateral
Hydrant (Device) Wet-Barrel Hydrant 122 1 (inlet) Hydrant Lateral
Hydrant (Device) Flush Hydrant 123 1 (inlet) Distribution Main, Hydrant Lateral
Water Meter (Device) Positive-Displacement Meter 141 2 (inlet / outlet) Service Lateral, Pressurized Lateral
Water Meter (Device) Turbine Meter 142 2 (inlet / outlet) Service Lateral, Fire Service Lateral
Water Meter (Device) Compound Meter 143 2 (inlet / outlet) Fire Service Lateral
Fitting (Junction) Tee 161 3 (branch) Distribution Main, Transmission Main, Service Lateral
Fitting (Junction) Cross 162 4 (branch) Distribution Main, Transmission Main
Fitting (Junction) Reducer 163 2 (large / small) Distribution Main, Transmission Main
Fitting (Junction) Coupling 164 2 (inline) Distribution Main, Service Lateral, Pressurized Lateral
Fitting (Junction) Cap / End 165 1 (inline) Distribution Main, Service Lateral
Service Point (Junction) Metered Service Point 181 1 (connection) Service Lateral, Pressurized Lateral
Service Point (Junction) Fire Service Point 182 1 (connection) Fire Service Lateral
Network Structure (Junction) Valve Vault 201 structural (containment only) none — structural attachment, not connectivity
Anatomy of a connectivity rule domain entry A connectivity rule is assembled left to right from four coded facts: the asset group names the feature class, the asset type resolves to a subtype domain code, the terminal configuration fixes how many terminals the device carries, and together these produce a permitted association — a junction-edge or edge-junction rule the trace engine enforces. A worked example runs beneath: Gate Valve, subtype code 101, two terminals, permitted to connect to a Distribution Main. Asset group feature class Asset type subtype code Terminal config terminal count Permitted association rule Worked example Gate Valve code 101 2 terminals → Distribution Main

Two reading rules make the table safe to apply. First, a device asset type may associate only with the line asset types listed in its row; a gate valve that connects a service lateral to a transmission main violates its permitted set even though the geometry snaps cleanly. Second, terminal count is a hard constraint on association arity — a one-terminal air release valve or hydrant terminates a single edge, so it can never sit inline splitting a main, while a tee’s three terminals are exactly what let it branch a lateral off a distribution main. The valve vault at the bottom of the table is the deliberate exception: it carries no connectivity terminals at all, because it participates through structural containment, and any rule that treats it as a connective junction is a defect.

The helper below encodes the reference as a lookup and validates a feature’s asset group, subtype code, terminal count, and proposed association against it. It returns a structured verdict suitable for a build gate rather than raising on the first mismatch:

from dataclasses import dataclass, field
import logging

logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")


@dataclass(frozen=True)
class RuleEntry:
    """One row of the water-distribution connectivity-rule reference."""
    asset_group: str
    asset_type: str
    terminals: int
    permitted: frozenset[str] = field(default_factory=frozenset)


# Representative subtype domain codes -> reference entries.
DOMAIN_CODES: dict[int, RuleEntry] = {
    1: RuleEntry("Distribution Pipe", "Distribution Main", 0,
                 frozenset({"Gate Valve", "Butterfly Valve", "Tee", "Cross", "Reducer"})),
    101: RuleEntry("Distribution Device", "Gate Valve", 2,
                   frozenset({"Distribution Main", "Transmission Main", "Hydrant Lateral"})),
    121: RuleEntry("Hydrant", "Dry-Barrel Hydrant", 1,
                   frozenset({"Hydrant Lateral"})),
    161: RuleEntry("Fitting", "Tee", 3,
                   frozenset({"Distribution Main", "Transmission Main", "Service Lateral"})),
    181: RuleEntry("Service Point", "Metered Service Point", 1,
                   frozenset({"Service Lateral", "Pressurized Lateral"})),
    201: RuleEntry("Network Structure", "Valve Vault", 0, frozenset()),
}


def validate_domain_code(code: int, terminals: int, associate_to: str) -> dict:
    """Validate a feature's subtype code, terminal count, and proposed association.

    Returns a structured verdict: whether the code is known, the terminal count
    matches the reference, and the proposed association is permitted.
    """
    entry = DOMAIN_CODES.get(code)
    if entry is None:
        logging.warning("Unknown subtype code %s — feature is unclassified", code)
        return {"code": code, "known": False, "ok": False,
                "reason": "subtype code not in reference domain"}

    terminal_ok = terminals == entry.terminals
    assoc_ok = associate_to in entry.permitted
    ok = terminal_ok and assoc_ok
    if not terminal_ok:
        logging.error("Code %s (%s): terminal count %d != expected %d",
                      code, entry.asset_type, terminals, entry.terminals)
    if not assoc_ok:
        logging.error("Code %s (%s): association to %r not permitted",
                      code, entry.asset_type, associate_to)

    return {
        "code": code,
        "asset_type": entry.asset_type,
        "known": True,
        "terminal_ok": terminal_ok,
        "association_ok": assoc_ok,
        "ok": ok,
    }


if __name__ == "__main__":
    print(validate_domain_code(101, terminals=2, associate_to="Distribution Main"))
    print(validate_domain_code(121, terminals=1, associate_to="Distribution Main"))

The second example fails deliberately: a hydrant coded 121 with a single terminal cannot associate directly to a distribution main, because its permitted set contains only the hydrant lateral. That is exactly the class of error the reference is meant to catch before it reaches a trace.

Production Deployment Pattern

Turn the reference from documentation into an enforced control:

  1. Export and diff the live domain. On every schema change, export the deployed coded-value domains with arcpy.da.ListDomains and diff them against this reference’s shape, so a renumbered or dropped subtype is caught at configuration time rather than during an outage.
  2. Wire the validator into CI. Run validate_domain_code over a sample of committed features from a build agent, and fail the pipeline when an unknown code, a terminal mismatch, or an unpermitted association appears — the same gating discipline detailed in automating connectivity rule validation in CI pipelines.
  3. Reconcile against a snapshot, not the live edit version. Read features from a reconciled, unversioned snapshot so the codes you validate reflect committed geometry and never contend with editor locks.
  4. Persist an audit trail. Append each validation run’s unknown-code count, terminal mismatches, and unpermitted associations to a timestamped, version-controlled log, along with the exported domain hash, so a reliability or AWWA G400 review can confirm the network was configured against a known baseline.
  5. Keep the reference under version control. Treat the domain-code table as code: any change to a subtype code or permitted association is a reviewed commit, so the network’s connectivity contract has a history rather than a memory.

Conclusion

Connectivity rules live or die on their domain codes, and in a water-distribution network those codes are the difference between a trace that isolates the right section and one that leaves a main energized. Validating each feature’s asset group, subtype code, terminal configuration, and permitted associations against a known reference — before tracing is ever enabled — turns a silent configuration error into a caught defect. Use the table as the shape your exported domains should take, enforce it with the validator on every commit, and keep the reference itself under version control so the connectivity contract is auditable rather than assumed. Correct codes are the quiet foundation every downstream isolation and impact trace inherits.

For authoritative reference, consult the ArcGIS Pro utility network connectivity documentation and the AWWA standards program.