FloodGuard — Dam Management & Early-Warning System

FloodGuard is an advanced, real-time reservoir monitoring and predictive flood-risk decision-support system. Designed for critical infrastructure management, the platform ingests live sensor telemetry, performs high-resolution divided-difference forecasts, computes dynamic safety thresholds, and provides proportional gate-release recommendations for on-site engineers—warning of hazardous states hours before they manifest.

This repository hosts the canonical PostgreSQL database schema, the core calculation engine algorithms, the Next.js integration APIs, and a graphical weather simulation suite.


Table of Contents


Team


Table of Contents

  1. Project Overview
  2. System Architecture
  3. PostgreSQL Database System Schema (3NF)
  4. Calculation Reference & Predictive Algorithm
  5. Machine Learning Integration Contract
  6. Simulation & Testing Scenarios
  7. Getting Started
  8. Links

1. Project Overview

Traditional dam safety protocols rely on static water-level thresholds. If a reservoir level crosses a fixed limit (e.g., 85%), gates are opened. However, under extreme storm conditions, the time required for physical gate configuration and downstream channel evacuation can exceed the safe response window.

FloodGuard implements a predictive, adaptive-threshold model where risk is assessed dynamically based on:

Rather than waiting for a breach, the system extrapolates historical trends forward, identifies if and when the predicted water level will cross the predicted safety threshold (the Time-To-Crossing or TTC), and triggers alarms in advance.


2. System Architecture

flowchart LR
    subgraph Field["Field Sensor & Simulation Layer"]
        S1[Water Level Sensor]
        S2[Meteorological Station Sensors]
        S3[Upstream Inflow Sensor]
        S4[Downstream Level Sensor]
        SIM[Tkinter Weather Simulator]
    end

    subgraph Pred["Prediction & Calculation Layer"]
        ALGO[Reference Mathematical Engine<br/>or Trained ML Model]
    end

    subgraph DB["PostgreSQL Database (Local)"]
        WL[(water_level_readings)]
        RF[(rainfall_readings)]
        IF[(inflow_readings)]
        DL[(downstream_level_readings)]
        CM[(calculated_metrics)]
        TC[(threshold_calculations)]
        RS[(risk_status)]
        RR[(release_recommendations)]
        DT[(deescalation_tracking)]
        AL[(alerts_log)]
    end

    subgraph FE["Frontend Dashboard"]
        DASH[SCADA Operator UI]
    end

    S1 --> WL
    S2 --> RF
    S3 --> IF
    S4 --> DL
    SIM --> WL & RF & IF & DL
    
    WL & RF & IF & DL --> ALGO
    ALGO --> CM --> TC --> RS
    RS --> RR
    RS --> DT
    RS --> AL
    
    WL & CM & TC & RS & RR & AL --> DASH

The system operates on an event-driven and polling pipeline:

  1. Sensor Ingestion: Telemetry is written to the database.
  2. Processor Loop: Evaluates new raw telemetry, computes metrics and thresholds, checks predictive crossing models, and determines risk states.
  3. Frontend Refresh: Next.js API layer serves data, refreshing the SCADA panel dynamically on a 15-second polling interval.

3. PostgreSQL Database System Schema (3NF)

The database schema is fully normalized to Third Normal Form (3NF) to support transactional integrity and clean time-series storage.

3.1 Static Configuration Tables

dams

Holds physical limits, capacities, and baseline calibration thresholds for each dam.

engineers

System user profiles for dam operator logs and alert acknowledgements.

rainfall_locations

Catchment meteorological stations associated with the dam.


3.2 Live Time-Series Sensor Tables (3NF)

water_level_readings

inflow_readings

downstream_level_readings

rainfall_readings


3.3 Backend Prediction & Calculation Tables

prediction_runs

Records metadata for each divided-difference forecast run.

predicted_values

Contains extrapolated future states across forecast horizons ($t+15$ to $t+120$ mins).

graph_crossing_results

Stores summary predictions on threshold crossings.

calculated_metrics

Intermediate calculations performed per sensor scan.

threshold_calculations

risk_status

Official alert state of the dam.

release_recommendations

Proportional gate release plans calculated for ORANGE or RED status.

deescalation_tracking

Maintains cumulative timers for de-escalation dampening.


4. Calculation Reference & Predictive Algorithm

The reference engine processes mathematical updates on every ingestion cycle (1-minute intervals during real-time telemetry, or 15-second intervals under simulator conditions).

4.1 Inflow, Level, & Runoff Inputs

The engine ingests:

Weighted Net Catchment Rainfall ($R_{net}$)

To account for geographic delays, rainfall runoff is modeled by looking back at station delay offsets ($\tau_i$). If a station has missing telemetry, weights are scaled dynamically:

\[R_{net}(t) = \frac{\sum w_i R_i(t - \tau_i)}{\sum w_{active}}\]

4.2 Rise Rate & Acceleration

Short-term Rise Rate ($RR_{short}$)

Measures water level rate of change over the last 15 minutes, scaled to an hourly rate:

\[RR_{short}(t) = [L(t) - L(t - 15)] \times 4 \quad (\%/hour)\]

Long-term Rise Rate ($RR_{long}$)

Measures change over the last 60 minutes:

\[RR_{long}(t) = [L(t) - L(t - 60)] \times 1 \quad (\%/hour)\]

Rise Rate Acceleration ($ACC$)

Measures the change in long-term rise rate over the preceding hour:

\[ACC(t) = RR_{long}(t) - RR_{long}(t - 60) \quad (\%/hour^2)\]

Rolling Average ($RA$) & Deviation Score ($DEV$)

Calculates the 3-hour moving average of the long-term rise rate and compares it to the short-term spike rate to identify flash surge anomalies:

\[RA(t) = \text{Average}(RR_{long}) \text{ over last 3 hours}\] \[DEV(t) = RR_{short}(t) - RA(t)\]

4.3 Severity Classifications (Bands)

Telemetry states are classified into four rise-rate severity bands. The worst individual parameter match determines the band.

Severity Band Long-Term Rise Rate Short-Term Rise Rate Acceleration
NORMAL $< 1.0\,\%/h$ AND $< 2.0\,\%/h$ AND $\le 0.5\,\%/h^2$
ELEVATED $1.0\text{–}2.5\,\%/h$ OR $2.0\text{–}4.0\,\%/h$ OR $0.5\text{–}1.5\,\%/h^2$
HIGH $2.5\text{–}4.0\,\%/h$ OR $4.0\text{–}7.0\,\%/h$ OR $1.5\text{–}3.0\,\%/h^2$
CRITICAL $> 4.0\,\%/h$ OR $> 7.0\,\%/h$ OR $> 3.0\,\%/h^2$ (or $DEV > 5.0$)

4.4 Adaptive Safety Threshold ($AT$)

The safety threshold shifts downwards from BASE (75%) depending on hydrological stresses, clamped at a minimum FLOOR (30%).

\[AT(t) = \text{Clamp}( L_{base} - rr_{adj} - rf_{adj} - if_{adj} - dl_{adj},\; L_{floor},\; L_{base} )\]

Individual Penalties

  1. Rise Rate Adjustment ($rr_{adj}$):
    • NORMAL: 0% ELEVATED: 8% HIGH: 18% CRITICAL: 30%
  2. Rainfall Adjustment ($rf_{adj}$):
    • $R_{net} < 10$: 0% $10\text{–}25$: 3% $25\text{–}50$: 7% $> 50\,\text{mm/h}$: 12%
  3. Inflow Adjustment ($if_{adj}$): (relative to baseline inflow $IF_{base}$)
    • $IF(t) < 1.5 \times IF_{base}$: 0% $1.5\text{–}2.5 \times$: 4% $2.5\text{–}4 \times$: 8% $> 4 \times IF_{base}$: 13%
  4. Downstream level Adjustment ($dl_{adj}$):
    • $DL < 50\%$: 0% $50\text{–}70\%$: 3% $70\text{–}85\%$: 8% $> 85\%$: 15%

4.5 Newton Divided-Difference Extrapolation

For prediction cycles, the engine fits a polynomial through recent historical readings to extrapolate water levels ($L_{pred}(t+h)$) and inflow rates ($IF_{pred}(t+h)$) for horizons $h \in {15, 30, 45, 60, 90, 120}$ minutes.

To avoid high-degree oscillations (Runge’s phenomenon), the engine selects a low-degree fit (linear or quadratic) using the last 3-4 historical data points spaced over a rolling 6-hour window.

Divided-Difference Table

Given nodes $(x_0, y_0), (x_1, y_1), \dots, (x_k, y_k)$, divided differences are defined recursively:

\[f[x_i] = y_i\] \[f[x_i, x_{i+1}, \dots, x_{i+j}] = \frac{f[x_{i+1}, \dots, x_{i+j}] - f[x_i, \dots, x_{i+j-1}]}{x_{i+j} - x_i}\]

The interpolating polynomial is:

\[P(x) = f[x_0] + \sum_{i=1}^k f[x_0, \dots, x_i] \prod_{j=0}^{i-1} (x - x_j)\]

4.6 Graph Crossing Analysis & Time-To-Crossing ($TTC$)

A crossing is predicted if the gap margin at any horizon $h$ falls to or below zero:

\[Gap(t+h) = AT_{pred}(t+h) - L_{pred}(t+h) \le 0\] \[\Delta Gap = Gap(t+h) - Gap(t+h-15)\]

4.7 Risk Status Classification Rules

Risk statuses are evaluated in order of severity. First match wins.

Risk Status Trigger Conditions
🔴 Red $L(t) \ge AT(t)$ (Current level exceeds safety threshold)
OR $TTC \le 15$ minutes (Crossing imminent)
OR $RR_{band} = \text{CRITICAL}$
🟠 Orange $L(t) \ge AT(t) + 3\%$ (Within 3% of threshold)
OR ($TTC \le 60$ minutes)
OR ($RR_{band} = \text{HIGH}$ AND Gap Trend = decreasing)
🟡 Yellow $L(t) \ge AT(t) + 10\%$ (Within 10% of threshold)
OR ($TTC > 60$ minutes)
OR ($RR_{band} = \text{ELEVATED}$)
OR ($TTC = \text{Null}$ AND Gap Trend = decreasing)
🟢 Green All other conditions

4.8 Proportional Release Recommendations

Calculated when risk status reaches ORANGE or RED.

  1. Calculate Volumetrically Desired Discharge ($Q_{desired}$): Calculates the release rate required to bring the reservoir down to the threshold level over the next hour:

    \[Q_{desired}(t) = IF(t) - \frac{(AT(t) - L(t)) \times \text{Capacity}_{reservoir}}{3600 \times 100} \quad (m^3/s)\]
  2. Downstream Safety Limit ($Q_{down_avail}$): Calculates the remaining capacity of the downstream channel:

    \[Q_{down\_avail}(t) = \text{Capacity}_{downstream} \times \left(1 - \frac{DL(t)}{100}\right) \quad (m^3/s)\]
  3. Apply Safety Overrides:

    \[Q_{release}(t) = \text{Min}\left(Q_{desired}(t),\; Q_{down\_avail}(t),\; \text{Capacity}_{max\_gate}\right)\]

    If $Q_{desired} > Q_{down_avail}$, a CONFLICT WARNING is flagged to inform operators that the downstream channel is constrained.

  4. Proportional Gate Opening:

    \[\text{GateOpening}\% = \left(\frac{Q_{release}(t)}{\text{Capacity}_{max\_gate}}\right) \times 100\]

    Rounded to the nearest 5% for operator configuration.

  5. Estimated Discharge Duration ($t_{duration}$): Calculates the duration (minutes) needed to lower the level to a target buffer level ($AT(t) - 10\%$):

    \[t_{duration} = \frac{L(t) - (AT(t) - 10.0)}{\left(\frac{Q_{release} - IF(t)}{\text{Capacity}_{reservoir}}\right) \times 100 \times 60} \quad \text{minutes}\]

4.9 Sustained De-escalation Timers

Status downgrades are delayed to prevent rapid toggling due to noise. The system must meet de-escalation rules continuously:


5. Machine Learning Integration Contract

The prediction layer is model-agnostic. The deterministic reference algorithm can be swapped for a trained ML model by satisfying this integration contract.

+------------------+       Reads telemetry       +------------------+
|   PostgreSQL     | --------------------------> |  Trained Model   |
|   Database       | <-------------------------- |  (Python Script) |
+------------------+    Writes predictions &     +------------------+
                            risk status

5.1 Inputs

The model must query live and historical time-series data directly from:

5.2 Outputs

The model must write its calculated predictions into the database tables:

  1. calculated_metrics: Populate rise rates, acceleration, rolling average, deviation, and rise rate band.
  2. threshold_calculations: Populate the calculated dynamic safety threshold and adjustments.
  3. risk_status: Set the calculated risk status.
  4. release_recommendations: Generate proportional gate openings and safe release rates.

6. Simulation & Testing Scenarios

The Tkinter weather simulator generates real-time telemetry to test system responses.


7. Getting Started

7.1 Database Initialization

Create your local PostgreSQL database and load the schema:

# Create local database
createdb dam_management

# Apply schema migrations
psql -U postgres -d dam_management -f ./code/database/dam_management_schema.sql

7.2 Service Execution

  1. Copy .env.example to .env and fill in your PostgreSQL credentials:
    cp .env.example .env
    
  2. Install Python dependencies:
    pip install -r requirements.txt
    
  3. Launch backend services (launches the Tkinter GUI and calculation loops):
    python code/main.py
    
  4. Start the frontend Next.js server:
    cd code/frontend
    npm install
    npm run dev
    

    Open http://localhost:3000 to view the SCADA control panel.