Skip to main content

NetworkManager Architecture

Component: NetworkManager (EPANET INP Parser & Database Importer) Date: October 2025 Status: Production Ready Purpose: Parse EPANET input files and import water distribution networks to database


Table of Contents

  1. Overview
  2. Architecture
  3. Parsing System
  4. Property Processing
  5. Default Value Strategy
  6. Seeding System
  7. V&V Mode
  8. Technical Details

1. Overview

1.1 Purpose

NetworkManager is a .NET executable library that:

  • Parses EPANET input files (.inp)
  • Imports water distribution network models to PostgreSQL database
  • Seeds configuration data (entity types, metrics, units)
  • Validates and verifies network data
  • Supports multiple operational modes

1.2 Key Capabilities

EPANET Parsing:

  • Complete support for all EPANET sections
  • Node processing (Junctions, Tanks, Reservoirs)
  • Link processing (Pipes, Pumps, Valves)
  • Patterns, Curves, Controls, Rules
  • Options, Time Parameters, Energy, Reactions

Database Import:

  • Entity Framework Core integration
  • PostgreSQL connectivity
  • Relationship management
  • Property table handling

Configuration Seeding:

  • Entity type definitions
  • Metric configurations
  • Visualization settings
  • Measurement units
  • System constants

Operational Modes:

  • Full parse and import
  • V&V-only mode (validation without re-parsing)
  • Export mode
  • Various debugging modes

2. Architecture

2.1 Component Structure

NetworkManager/
├── Builders/
│ ├── NetworkBuilder.cs # Main orchestrator
│ ├── EN2NodeBuilder.cs # Node parsing
│ ├── EN2LinkBuilder.cs # Link parsing
│ ├── EN2PatternBuilder.cs # Pattern parsing
│ └── EN2CurveBuilder.cs # Curve parsing
├── Parsers/
│ ├── JunctionsSectionParser.cs # [JUNCTIONS] section
│ ├── PipesSectionParser.cs # [PIPES] section
│ ├── OptionsSectionParser.cs # [OPTIONS] section
│ ├── ControlsSectionParser.cs # [CONTROLS] section
│ ├── RulesSectionParser.cs # [RULES] section
│ └── [20+ section parsers]
├── Services/
│ ├── NetworkConfigurationService.cs # DB config access
│ ├── NetworkConfigurationSeedingService.cs # Config seeding
│ └── EpanetPropertyDefaults.cs # Default value lookup
└── Models/
├── entity-types.json # Entity definitions
├── metrics.json # Metric configurations
├── visualization-config.json # Viz settings
├── model-units.json # Unit definitions
└── constants.json # System constants

2.2 Data Flow

EPANET INP File

EpanetWrapper (Native DLL)

Section Parsers (C# layer)

Entity Builders (Model creation)

Database (PostgreSQL via EF Core)

3. Parsing System

3.1 EPANET Input File Sections

Complete Coverage:

SectionStatusParserDatabase Model
[JUNCTIONS]JunctionsSectionParserJunction
[RESERVOIRS]ReservoirsSectionParserReservoir
[TANKS]TanksSectionParserTank
[PIPES]PipesSectionParserPipe
[PUMPS]PumpsSectionParserPump (via LinkProperty)
[VALVES]ValvesSectionParserValve
[PATTERNS]PatternsSectionParserDataPattern
[CURVES]CurvesSectionParserDataCurve
[CONTROLS]ControlsSectionParserSimpleControl
[RULES]RulesSectionParserRuleBasedControl
[OPTIONS]OptionsSectionParserOptions
[TIMES]TimesSectionParserTimeParameters
[ENERGY]EnergySectionParserEnergy
[REACTIONS]ReactionsSectionParserReaction
[QUALITY]QualitySectionParserNodeProperty
[STATUS]StatusSectionParserLinkProperty
[MIXING]MixingSectionParserTankMixing
[EMITTERS]EmittersSectionParserNodeProperty
[COORDINATES]CoordinatesSectionParserNode XY coords
[VERTICES]VerticesSectionParserLinkVertice

3.2 Parsing Architecture

Two-Stage Process:

Stage 1: EPANET Toolkit Reading

// Use EPANET's native parser to load and validate
int result = epanetWrapper.EN_open(inpFilePath, reportPath, "");
if (result != 0) throw new Exception("Invalid INP file");

Stage 2: Data Extraction

// Extract data using EPANET API
int count = epanetWrapper.EN_getcount(EN_JUNCCOUNT);
for (int i = 1; i <= count; i++)
{
var junction = GetJunctionByIndex(epanetWrapper, i);
junctions.Add(junction);
}

Benefits:

  • ✅ Leverages EPANET's robust parsing
  • ✅ Automatic validation
  • ✅ Handles all EPANET format variations
  • ✅ Type-safe data extraction

4. Property Processing

4.1 Property Tables

NetworkManager uses two tables for flexible property storage:

LinkProperty Table:

  • Stores non-standard link properties
  • Pump settings (curves, energy, patterns)
  • Valve settings
  • Custom properties (KWall, leak parameters)

NodeProperty Table:

  • Stores non-standard node properties
  • Emitter coefficients
  • Initial quality
  • Tank bulk reaction coefficients

4.2 Standard Processing Pattern

public static List<LinkProperty> GetPumpProperties(EpanetWrapper wrapper, int i)
{
var linkId = wrapper.GetLinkId(i);
var properties = new List<LinkProperty>();

// Get property value from EPANET
var value = wrapper.GetLinkProperty(EN_LinkProperty.EN_PUMP_HCURVE, i);

// Only add if NOT default
if (!EpanetPropertyDefaults.IsDefaultLinkValue((int)EN_LinkProperty.EN_PUMP_HCURVE, value))
{
properties.Add(new LinkProperty(linkId, (int)EN_LinkProperty.EN_PUMP_HCURVE, value));
}

return properties;
}

Key Principle: Only insert non-default values to prevent database bloat


5. Default Value Strategy

5.1 Problem Solved

Issue: Without knowing default values, the system stored ALL property values, causing:

  • 90%+ database entries were defaults (zeros and ones)
  • Confusion about explicit vs default values
  • Database bloat and performance overhead

Solution: EpanetPropertyDefaults service class

5.2 Default Value Repository

File: Services/EpanetPropertyDefaults.cs

Link Property Defaults:

public static readonly Dictionary<int, double> LinkDefaults = new()
{
{ (int)EN_LinkProperty.EN_KWALL, 0.0 }, // Wall reaction
{ (int)EN_LinkProperty.EN_LEAK_AREA, 0.0 }, // Leakage area
{ (int)EN_LinkProperty.EN_INITSTATUS, 1.0 }, // Initial status (OPEN)
{ (int)EN_LinkProperty.EN_PUMP_HCURVE, 0.0 }, // No head curve
{ (int)EN_LinkProperty.EN_PUMP_ECOST, 0.0 }, // No energy cost
// ... complete lookup table
};

Node Property Defaults:

public static readonly Dictionary<int, double> NodeDefaults = new()
{
{ (int)EN_NodeProperty.EN_EMITTER, 0.0 }, // No emitter
{ (int)EN_NodeProperty.EN_INITQUAL, 0.0 }, // Initial quality
{ (int)EN_NodeProperty.EN_TANK_KBULK, 0.0 }, // Tank bulk reaction
};

5.3 Usage Pattern

if (!EpanetPropertyDefaults.IsDefaultLinkValue(propertyId, value))
{
// Only insert non-default values
properties.Add(new LinkProperty(linkId, propertyId, value));
}

Result:

  • ✅ 90% reduction in LinkProperty/NodeProperty entries
  • ✅ Clear distinction between explicit and default values
  • ✅ Better database performance
  • ✅ Cleaner data model

5.4 Critical Distinction: EN_STATUS vs EN_INITSTATUS

EN_INITSTATUS (PropertyId = 4) ✅ STORE THIS

  • User-configurable initial status
  • Set before simulation
  • Static configuration value
  • Store in database

EN_STATUS (PropertyId = 11) ❌ DO NOT STORE

  • Computed during simulation
  • Dynamic simulation result
  • Changes during hydraulic solving
  • Never store in database

Why this matters:

  • Storing EN_STATUS would save meaningless runtime values
  • EN_INITSTATUS is the actual configuration
  • Confusion between these caused bugs (now fixed)

6. Seeding System

6.1 Configuration Seeding Architecture

Single Source of Truth:

  • All seeding logic centralized in NetworkManager
  • All seed data stored in NetworkManager/Models
  • Clear separation of concerns

Seeding Components:

  1. NetworkConfigurationSeedingService - Database seeding
  2. NetworkConfigurationService - Database access
  3. ConfigurationDataService (in EN2PostgresContext) - File-based access
  4. JSON seed files - Data definitions

6.2 Seeding Process

// Orchestrated by NetworkBuilder
private static async Task PopulateNetworkConfiguration()
{
var seedingService = new NetworkConfigurationSeedingService(enContext, logger);
await seedingService.SeedAllConfigurationDataAsync();
}

Seeds:

  • Entity type configurations
  • Metric definitions
  • Visualization configurations
  • Measurement units
  • System constants

6.3 Data-Driven Configuration

Benefits:

  • Configuration changes without code deployment
  • Frontend uses same data as backend
  • Single source of truth
  • Easy to maintain and extend

7. V&V Mode

7.1 Validation & Verification Only Mode

Purpose: Validate existing database data without re-parsing input files

Use Cases:

  • Quick validation of existing data
  • Regression testing after changes
  • Data quality assessment
  • Troubleshooting data issues

7.2 Configuration

Enable V&V Mode:

{
"V&V": {
"EnableV&VOnlyMode": true,
"V&VOnlyMode": {
"SkipParsing": true,
"SkipDatabaseInserts": true,
"ValidateExistingData": true,
"GenerateDetailedReport": true
}
}
}

Features:

  • ✅ Comprehensive validation
  • ✅ Detailed reporting
  • ✅ Performance metrics
  • ✅ No database modifications
  • ✅ Quick execution

8. Technical Details

8.1 EPANET API Integration

Wrapper Usage:

// Get counts
int junctionCount = wrapper.EN_getcount(EN_JUNCCOUNT);
int pipeCount = wrapper.EN_getcount(EN_LINKCOUNT);

// Get node data
string nodeId = wrapper.GetNodeId(index);
double elevation = wrapper.GetNodeValue(EN_ELEVATION, index);

// Get link data
string linkId = wrapper.GetLinkId(index);
double diameter = wrapper.GetLinkValue(EN_DIAMETER, index);

8.2 Database Schema Integration

Entity Framework Core:

  • DbContext: EN2PostgresContext
  • Models: HTModels project
  • Migrations: Handled externally
  • Relationships: Properly configured

8.3 Performance Considerations

Optimization Strategies:

  • Bulk insert operations
  • Filtered property insertion (defaults excluded)
  • Efficient querying
  • Index usage
  • Connection pooling

Typical Performance:

  • Small network (< 1,000 elements): < 10 seconds
  • Medium network (1,000-10,000): < 60 seconds
  • Large network (> 10,000): < 5 minutes

Summary

Complete EPANET Parsing:

  • All 20+ INP file sections supported
  • Robust parsing using EPANET toolkit
  • Type-safe data extraction
  • Complete property coverage

Smart Property Handling:

  • Default value filtering prevents bloat
  • Critical EN_STATUS vs EN_INITSTATUS distinction
  • Only non-default values stored
  • 90% reduction in property entries

Configuration Management:

  • Centralized seeding system
  • JSON-based seed data
  • Single source of truth
  • Data-driven architecture

Quality Assurance:

  • V&V-only mode for validation
  • Comprehensive reporting
  • Data quality checks
  • Regression testing support

Production Ready:

  • Stable and tested
  • Performance optimized
  • Well documented
  • Maintainable codebase

Related Documentation:

  • Design Specs: NetworkManager-design-specs.md
  • Functional Specs: NetworkManager-functional-specs.md
  • Component Overview: NetworkManager-summary.md
  • Parsing Analysis: See detailed section coverage above

Status: ✅ Production Ready Last Updated: October 2025