Saturday, December 28, 2024

SWMM5 gage.c Summary

 Below is a step‐by‐step explanation of gage.c, which implements rain gage functions in EPA SWMM5. A rain gage in SWMM is an object that provides rainfall data (either from a time series or external file) for one or more subcatchments. This file tracks:

  1. Gage parameters (data source, units, data intervals).
  2. Recorded rainfall (both current and historical).
  3. Updates to rainfall at each time step.

1. Purpose and Context

//   gage.c
//   Rain gage functions.
//
//   Update History ...
  • This file is part of the runoff or global modules, providing the interface for reading and storing rainfall data from either:

    • A time series (in .inp file or from external time series definitions), or
    • A rainfall interface file (binary data file).
  • The main public functions declared in headers.h and defined here are:

    1. gage_readParams: parse input line for a gage.
    2. gage_validate: checks correctness.
    3. gage_initState: initializes gage states.
    4. gage_setState: sets current rainfall at a certain time.
    5. gage_getPrecip: returns the rainfall (and whether it's rain or snow).
    6. gage_getNextRainDate: next date/time with non-zero rainfall.
    7. gage_updatePastRain: maintains an array of previous hours' rainfall totals.
    8. gage_getPastRain: retrieves the N-hour rainfall total.
    9. gage_setReportRainfall: sets the gage’s rainfall specifically for reporting.

2. Data Flow

  • Each Gage[j] object has fields like:
    • dataSource: RAIN_TSERIES or RAIN_FILE.
    • rainType: RAINFALL_INTENSITY, RAINFALL_VOLUME, or CUMULATIVE_RAINFALL.
    • rainInterval: recording interval (seconds).
    • rainfall: the current rainfall intensity (in/hr or mm/hr).
    • apiRainfall: rainfall that might have been directly set via an API call (bypasses default reading).
    • startDate, endDate: the start and end times of the current rainfall record.
    • nextDate, nextRainfall: the next rainfall record after the current interval, etc.

3. Reading Gage Parameters

3.1 gage_readParams(j, tok, ntoks)

int gage_readParams(int j, char* tok[], int ntoks)
  • Parses a line from the SWMM input file describing a gage’s configuration, storing the values in Gage[j].

  • The data format can be:

    1. Time Series:
      GageID  RainType  RecdFreq  SCF  TIMESERIES  TSeriesName
      
    2. File:
      GageID  RainType  RecdFreq  SCF  FILE  FileName  Station  Units  StartDate
      
  • The function delegates to either:

    • readGageSeriesFormat(...) (for TIMESERIES lines),
    • readGageFileFormat(...) (for FILE lines).

Key fields:

  • rainType can be:
    • RAINFALL_INTENSITY,
    • RAINFALL_VOLUME, or
    • CUMULATIVE_RAINFALL.
  • rainInterval = how often data is recorded (seconds).
  • snowFactor = an adjustment factor for snowfall catch deficiency.
  • rainUnits = US or SI units for file-based gages.

3.2 readGageSeriesFormat(tok, ntoks, x[])

static int readGageSeriesFormat(char* tok[], int ntoks, double x[])
  • Handles time series format lines.
  • Looks up the type of rainfall from RainTypeWords.
  • Converts the user’s input of RecdFreq into seconds.
  • Finds the time series index for the name tok[5].

3.3 readGageFileFormat(tok, ntoks, x[])

static int readGageFileFormat(char* tok[], int ntoks, double x[])
  • For lines referencing an external Rainfall file.
  • Also sets start/end date for the file if provided.
  • The user can supply:
    • Station ID,
    • Units (like “IN” or “MM”),
    • StartDate (the earliest date to read from file).

4. Validation: gage_validate(j)

  • For a gage that’s not used by any subcatchment (isUsed == FALSE), no checks are done.
  • If it uses a time series that’s also used by another gage, we set coGage so they share the same data.
  • If intervals mismatch or are bigger than time series intervals, we produce warnings/errors.

5. Initialization: gage_initState(j)

void gage_initState(int j)
  • Called at simulation start:
    1. If IgnoreRainfall = TRUE, sets rainfall=0.0.
    2. If RAIN_FILE, sets file pointer to the start of record, sets unitsFactor if needed, etc.
    3. getFirstRainfall(j): obtains the first date & rainfall record from the time series or file.
    4. If the first record starts after StartDateTime, adjusts accordingly.
    5. Calls initPastRain(j) to reset the past hour accumulation array.

6. Updating Rainfall: gage_setState(j, t)

void gage_setState(int j, DateTime t)
  • Called each step to update the gage’s rainfall at time t.
  • If coGage >= 0, just copy that gage’s rainfall.
  • If the user’s code set apiRainfall, use that.
  • Otherwise, we compare t to the current interval [startDate, endDate].
    • If t < startDate => 0.0 rainfall,
    • If startDate <= t < endDate => same rainfall,
    • If t >= endDate => shift to the next interval by calling getNextRainfall(j), etc.

7. Past Hourly Rainfall: gage_updatePastRain & gage_getPastRain

  • gage_updatePastRain(j, tStep):

    • The current rainfall intensity is Gage[j].rainfall / 3600. ( ft or mm per second).
    • It accumulates partial amounts in pastRain[] array, each entry representing an hour’s total.
    • If pastInterval has reached 3600 seconds, shift the array by 1 hour.
  • gage_getPastRain(j, n):

    • Returns sum of the past n hours of rainfall from the pastRain[] array.

This supports logic like control rules that might require “past 6-hour rainfall total.”


8. Next Rain Date: gage_getNextRainDate(j, aDate)

DateTime gage_getNextRainDate(int j, DateTime aDate)
  • Returns the date/time after aDate when the next rainfall interval starts.
  • If coGage >= 0, the co-gage’s next date is used.

9. Retrieving Actual or Reported Rain

  1. gage_getPrecip(j, &rainfall, &snowfall):

    • Distinguishes rain vs. snow. If Temp.ta <= Snow.snotmp, we treat it as snow times snowFactor; else it’s rain.
    • The total precipitation is (rainfall + snowfall) in ft/sec or mm/sec.
  2. gage_setReportRainfall(j, reportDate):

    • For writing results. If coGage >= 0, again copy. If we are exactly on the boundary between intervals, we might use the “next” rainfall.
    • Or if the user set an API rainfall, that’s used.

10. Internal Routines

10.1 initPastRain(j)

  • Zeros out the Gage[j].pastRain[] array and sets pastInterval=0.

10.2 getFirstRainfall(j) & getNextRainfall(j)

  • For the first/next record from:
    • A file: read DateTime and float volume from Frain.file. Convert to in/hr or mm/hr.
    • A time series: from Tseries[k].
  • Skips zero rainfall records (for getNextRainfall) so we can keep distinct intervals for real wet/dry transitions.

10.3 convertRainfall(j, r)

  • Switches on rainType:
    • RAINFALL_INTENSITY => no transformation.
    • RAINFALL_VOLUME => convert total volume to intensity = (volume / interval) * 3600.
    • CUMULATIVE_RAINFALL => difference from last accumulation is the new volume.
  • Multiplies by unitsFactor if in metric and also a global Adjust.rainFactor.

11. Summary

gage.c handles:

  1. Reading gage definitions from the SWMM input file (time series or external file).
  2. Initialization and per-step updates of rainfall states.
  3. Distinguishing rain vs. snow.
  4. Managing past hourly rainfall accumulation arrays.

It ensures each subcatchment referencing a gage sees the correct rainfall for that step, optionally referencing the same time series or file as other gages.

No comments:

A comprehensive explanation of how minimum travel distance relates to link length in InfoSewer

In hydraulic modeling of sewer networks, the minimum travel distance is a fundamental parameter that affects how accurately the model can si...