Code Monkey home page Code Monkey logo

stormwater-management-model's Introduction

ORD Stormwater-Management-Model Solver

Stormwater Management Model (aka "SWMM") solver only

Build Status

Build and Test

Disclaimer

The United States Environmental Protection Agency (EPA) GitHub project code is provided on an "as is" basis and the user assumes responsibility for its use. EPA has relinquished control of the information and no longer has responsibility to protect the integrity, confidentiality, or availability of the information. Any reference to specific commercial products, processes, or services by service mark, trademark, manufacturer, or otherwise, does not constitute or imply their endorsement, recommendation or favoring by EPA. The EPA seal and logo shall not be used in any manner to imply endorsement of any commercial product or activity by EPA or the United States Government.

Introduction

This is the official SWMM source code repository maintained by US EPA Office of Research and Development, Center For Environmental Solutions & Emergency Response, Water Infrastructure Division located in Cincinnati, Ohio.

SWMM is a dynamic hydrology-hydraulic water quality simulation model. It is used for single event or long-term (continuous) simulation of runoff quantity and quality from primarily urban areas. SWMM source code is written in the C Programming Language and released in the Public Domain.

Find Out More

The source code distributed here is identical to the code found at the official SWMM Website.

stormwater-management-model's People

Contributors

andychase avatar cbuahin avatar jaorquina avatar lrossman avatar michaeltryby avatar michelleannesimon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stormwater-management-model's Issues

No recovery of soil moisture deficit for exfiltration from storage units

There is a bug in the storage_getlosses() function of node.c. The code only applies the Green-Ampt function for exfiltration when the storage unit’s volume is greater than FUDGE. That means that after the unit drains down completely the G-A function is not called and no recovery of soil moisture deficit can occur. The affected section of the code is shown below with the necessary corrections:

////// --- if node has some stored volume   DELETE
////if ( Node[j].newVolume > FUDGE )        DELETE
////{                                       DELETE
        // --- get node's evap. rate (ft/s) &  exfiltration object
        k = Node[j].subIndex;
        evapRate = Evap.rate * Storage[k].fEvap;
        exfil = Storage[k].exfil;
 
        // --- if either of these apply
        if ( evapRate > 0.0 || exfil != NULL) 
        {
            // --- obtain storage depth & surface area 
            depth = Node[j].newDepth;
            area = storage_getSurfArea(j, depth);
 
            // --- compute evap rate over this area (cfs)
            if (Node[j].newVolume > FUDGE) evapRate = area * evapRate;
 
            // --- find exfiltration rate (cfs) through bottom and side banks
            if ( exfil != NULL )
            {
                exfilRate = exfil_getLoss(exfil, tStep, depth, area);
            }
 
            // --- total loss over time step cannot exceed stored volume
            totalLoss = (evapRate + exfilRate) * tStep;
            if ( totalLoss > Node[j].newVolume )
            {
                lossRatio = Node[j].newVolume / totalLoss;
                evapRate *= lossRatio;
                exfilRate *= lossRatio; 
            }
        }
////}   DELETE

Missing system rainfall when simulating RDII

In gage_validate() method, new function was added to ignore unused gage. This will exclude gages for RDII which use flag is set in a later step. As a result, the gage.coGage is not set correctly which will advance time series table pointer accidentally.

    // --- no validation for an unused gage
    if ( !Gage[j].isUsed ) return;

Here is a sample project for the issue:

Rainfall.zip

Report entities not read correctly if name starts with keywords

For the following [REPORT] section, output file does not contain results for the first eight links (which name starts with "ALL"):

[REPORT]
INPUT YES
CONTROLS NO
SUBCATCHMENTS NONE
NODES NONE
LINKS ALLE_00740.1 ALLE_01570.1 ALLE_01640.1 ALLE_02370.2
LINKS ALLE_02740.2 ALLE_03430.1 FRIS_00010.1 FRIS_00070.1
LINKS FRIS_00120.1 MCKI_00870.1 NTMW_05460.1 NTMW_06810.1
LINKS NTMW_07280.1 PLAN_00030.1 PLAN_00470.1

Update affiliation for Master page and readme file and indicate that it is SWMM 5.1.014

Please update affiliation in the Readme file, Introduction, and elsewhere for the Master link as well: Also indicate that the master and develop are from SWMM 5.1.014.

“This is the official SWMM source code repository maintained by US EPA ORD, NRMRL, Water Supply and Water Resources Division located in Cincinnati, Ohio.”

To “This is the official SWMM source code repository maintained by US EPA Office of Research and Development, Center For Environmental Solutions & Emergency Response, Water Infrastructure Division located in Cincinnati, Ohio.”

NetCDF Output Format

Would there be any interest in using the NetCDF as the output file format for SWMM? It is self documenting, portable, and is able to scale well.

Update swmm to recognize relative paths to auxiliary data files

Sometimes when running swmm on an input file that references auxiliary data (such as rainfall data), the simulation fails because it is unable to open the auxiliary file (ERROR 317). This is because auxiliary files either have to be referenced using an absolute path or the input and auxiliary files must reside in the current working directory. This can be inconvenient in many situations.

It would be more user friendly if auxiliary data files could also be referenced using paths relative to the location of the input file itself. This way absolute paths in the input file could be avoided and the user would have the flexibility to choose a working directory that suites the task they are performing. For example, batch processing input files for optimization, uncertainty analysis, or testing purposes.

Constants precision nits

Very minor stuff: a few constants are applied inconsistently and/or could easily be resolved to higher precision. The gravity adjustment is less than 0.1%; the Manning's N coefficient adjustment is close to 0.3%

//consts.h
#define GRAVITY 32.2 // add precision to 32.174
#define SI_GRAVITY 9.81 // never used
#define PHI 1.486 // resolve to 1.4859 or exact representation as 0.3048^(-1/3)

//lid.c
LidProcs[j].surface.alpha =1.49 * sqrt(LidProcs[j].surface.surfSlope) / LidProcs[j].surface.roughness; // use PHI

  LidProcs[j].surface.alpha = 1.49 / LidProcs[j].surface.roughness * sqrt(LidProcs[j].surface.surfSlope);           // use PHI

  LidProcs[j].drainMat.alpha = 1.49 / LidProcs[j].drainMat.roughness * sqrt(LidProcs[j].surface.surfSlope);     // use PHI

//statsrpt.c
if (UnitSystem == US) Vcf = 7.48 / 1.0e6; // resolve to 7.4805

//subcatch.c
const double MCOEFF = 1.49; // use PHI

//transect.c
else Transect[j].hradTbl[i] = pow(qSum * Nchannel / 1.49 / aSum, 1.5); // use PHI

//link.c
aa = Conduit[k].beta / sqrt(32.2) * pow(Link[j].xsect.yFull, 0.1666667) * 0.3; // use GRAVITY

Possible race condition in dynwave.c

There is a possible race condition in the multi-threaded portion of the findNodeDepths function in dynwave.c. The variable converged, defined outside of the parallel loop, can be changed within the loop. The fix is to remove converged from the parallel loop and set its value later by checking each Xnode[i].converged value until the first FALSE value is found.

Routing Error Calculation (with initial snowpack on LIDs)

It doesn’t look like the initial snowpack on an LID is properly accounted in the Routing Error calculation. Attached ZIP features a single catchment with an LID and no rainfall, the only runoff is generated by snowmelt. There are two files: one represents the initial snowpack depth of 220mm (minus 1mm free water) and the other with 210 mm of precipitation at the beginning of simulation (and snowpack depth of 0mm). The Snow Depth hydrographs match, however the routing error for the initial snowpack scenario is 64% compared to 0% for the initial snowfall scenario.
SnowFallingOnLIDs.zip

Context for the table Most Frequent Nonconverging Nodes in SWMM 5.2

The table Most Frequent Nonconverging Nodes is a great addition as it helps user identifuy problem simulation areas of the network but it lacks context. If a node does not converge 10 percent of the time how many times is is not converging. I suggest adding the number of time steps to the summary time step routing table so the user can get some context. It tells you the number or report steps, the number actual steps per report step and the total time steps.

Here is an example


Most Frequent Nonconverging Nodes


Node 10208 (35.59%)
Node 82309 (32.86%)
Node 80608 (12.74%)
Node 80408 (10.31%)
Node 81009 (9.00%)


Routing Time Step Summary


Minimum Time Step : 19.13 sec
Average Time Step : 29.12 sec
Maximum Time Step : 60.00 sec
% of Time in Steady State : 0.00
Average Iterations per Step : 5.10
% of Steps Not Converging : 35.59
% Number of Report Steps : 989
% Total TS / Report TS : 29.12
% Total Time Steps (TS) : 28799

Time Step Frequencies :
60.000 - 23.031 sec : 42.81 %
23.031 - 8.841 sec : 57.19 %
8.841 - 3.393 sec : 0.00 %
3.393 - 1.303 sec : 0.00 %
1.303 - 0.500 sec : 0.00 %

Here is the code for report.c - just adding three lines to the Routing Time Step Summary using known information.

void report_writeTimeStepStats(TTimeStepStats* timeStepStats)
//
// Input: timeStepStats = routing time step statistics
// Output: none
// Purpose: writes routing time step statistics to report file.
//
{
double timeStepCount = timeStepStats->timeStepCount;
double totalRoutingTime; // time taken for all flow routing steps
double fSteadyState = 0.0; // fraction of reporting time in steady state

if ( Nobjects[LINK] == 0 || timeStepStats->timeStepCount == 0.0 )
    return;

totalRoutingTime = timeStepStats->steadyStateTime + timeStepStats->routingTime;
if (totalRoutingTime > 0.0)
    fSteadyState = 100.0 * timeStepStats->steadyStateTime / totalRoutingTime;

WRITE("");
WRITE("*************************");
WRITE("Routing Time Step Summary");
WRITE("*************************");
fprintf(Frpt.file,
    "\n  Minimum Time Step           :  %7.2f sec",
    timeStepStats->minTimeStep);
fprintf(Frpt.file,
    "\n  Average Time Step           :  %7.2f sec",
    timeStepStats->routingTime / timeStepCount);
fprintf(Frpt.file,
    "\n  Maximum Time Step           :  %7.2f sec",
    timeStepStats->maxTimeStep);
fprintf(Frpt.file,
    "\n  %% of Time in Steady State   :  %7.2f", MIN(fSteadyState, 100.0));
fprintf(Frpt.file,
    "\n  Average Iterations per Step :  %7.2f",
    timeStepStats->trialsCount / timeStepCount);
fprintf(Frpt.file,
    "\n  %% of Steps Not Converging   :  %7.2f",
    100.0 * (double)NonConvergeCount / timeStepCount);
fprintf(Frpt.file,
    "\n  %% Number of Report Steps    :%9.0f",  timeStepCount);   // RED_2022
fprintf(Frpt.file,
    "\n  %% Total TS / Report TS      :  %7.2f", timeStepStats->routingTime/ timeStepCount); // RED_2022
fprintf(Frpt.file,
    "\n  %% Total Time Steps (TS)     :%9.0f", timeStepStats->routingTime);   // RED_2022

#define SOL /* Compile as a shared object library */

I have not been able to compile swmm5 as a shared object file, on a linux (fedora) system. I have been able to compile it as an executable, by commenting out the references to Windows in swmm5.c and uncommenting #define CLE. However, if I try the same thing with #define SOL I get the following error:

/usr/lib/gcc/x86_64-redhat-linux/7/../../../../lib64/crt1.o: In function _start': (.text+0x20): undefined reference to main'
collect2: error: ld returned 1 exit status
make: *** [Makefile:12: swmm5] Error 1

There are no reference to SOL further down in swmm5.c. What do I have to do to get this option to work?

Thanks
Jim

Unit Hydrograph ALL months functionality

The user should be warned that a unit hydrograph entry for ALL months overrides prior values entered for a specific month. E.g. if hydrographs are specified in the order Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, All, Oct, Nov, Dec, ALL would override the prior entries, with only Oct, Nov, and Dec ending up with the values specified by the user. While this behavior is reasonable, it should be identified in the User Manual and flagged as a warning in the status report from the routine rdii_readUnitHydParams in rdii.C. More generally, a warning could be triggered any time a user specifies more than one set of values for a month.

Community Contributions

@michaeltryby, I'd like to explore and strategize the best pathways forward to bring in contributions from the community into the next (or a future) release of SWMM. Do you have any initial thoughts on this?

Units conversion issue in Curve number infiltration

In infile.c infil_getInfil() method:

  case CURVE_NUMBER:
    depth += runon / tstep;
    return curvenum_getInfil(&CNInfil[j], tstep, rainfall, depth);

runon is in ft/sec. To convert it to depth, it should be depth+=runon*tstep.

Make corrections in Readme and Introduction and elsewhere

Please update affiliation in the Readme file, Introduction, and elsewhere:

“This is the official SWMM source code repository maintained by US EPA ORD, NRMRL, Water Supply and Water Resources Division located in Cincinnati, Ohio.”

To “This is the official SWMM source code repository maintained by US EPA Office of Research and Development, Center For Environmental Solutions & Emergency Response, Water Infrastructure Division located in Cincinnati, Ohio.”

Inconsistent reporting of "Time of Max Occurrence" time stamp

Under some conditions the time of peak flow is being reported differently causing an apparent shift in time (minutes column of a report table). This can occur when changing compiler versions or going from 32 bit to 64 bit compilation.

The 32 bit and 64 bit results are in agreement to approximately 12 decimal places. The results of stats update computations are different due to numerical noise beyond the 12 decimal place.

Furthermore this numerical noise is biasing the reported "Time of Max Occurrence" to be later than it otherwise would be. Filtering out numerical noise results in a shift towards earlier times of occurrence and brings the times being reported for 32 bit and 64 bit builds into agreement.

High continuity error, critical elements, and flow instability tables display

The Highest Continuity Errors, Time-Step Critical Elements, and Highest Flow Instability Index tables are presently printed in the .RPT file after the flow continuity error with the top five locations. For a large model with convergence/stability issues, the modeler would prefer to see a more comprehensive list.

It would be simple to change MAX_STATS in stats.c to a user-specified variable via the [OPTIONS] section.

Alternatively or additionally, these listings could be appended to the Link Flow and Node Inflow summary tables.

These changes would assist users in debugging convergence and timestep issues in complex models.

Rainfall plot and event statistics

The rainfall plot and event statistics are incorrect when the reporting step is greater than the recording interval. See attached file, which features a bunch of 1-minute pulses of rain, each is 0.2” (12 in/hr) and irregularly spaced in time. MillDistrictMN_Oct2011.inp <<saved as *.txt file>>

MillDistrictMN_Oct2011.txt

With a 15-min reporting step, the Total Precip. in the Summary Results table is correctly reported as 3.20 in, however the graph only plots the first and last pulse (these are the only two pulses that begin exactly on the 15-min reporting period). Likewise, the event statistics are incorrectly calculated: only two events are detected, and the Event Total assumes that the 12 in/hr intensity lasts for a duration of 15 min (i.e., 3” in each pulse). When you change the reporting step to 1 min (same as the rainfall recording interval), all rainfall pulses are correctly plotted and event statistics correctly calculated.

I could live with the graphical error when plotting such timeseries, but not the errors in event statistics. As it becomes more common to use 1-min ASOS rainfall data, it is still practical to go with a larger reporting step of 15-min or more to limit the output file size. So, this error will become more persistent – but the error is not evident unless you deliberately go hunting for it. This is a concern.

Rain file conflict not checked for the first gage

I think we found a bug in rainFileConflict() method in rain.c. Loop variable j should start at 0 instead of 1, in which case, the first gage won't be checked.

From rain.c:

int rainFileConflict(int i)
//
// Input: i = rain gage index
// Output: returns 1 if file conflict found, 0 if not
// Purpose: checks if a rain gage's station ID matches another gage's
// station ID but the two use different rain data files.
//
{
int j;
char* staID = Gage[i].staID;
char* fname = Gage[i].fname;
for (j = 1; j < i; j++)
{
if ( strcomp(Gage[j].staID, staID) && !strcomp(Gage[j].fname, fname) )
{
report_writeErrorMsg(ERR_RAIN_FILE_CONFLICT, Gage[i].ID);
return 1;
}
}
return 0;
}

LID "Return all outflow to pervious area" dead loop

there is a dead loop when using the LID Usage option “Return all outflow to pervious area”. It looks like the read line in the lid_addDrainLoads() method is at fault:

while ( lidList )
       {
            lidUnit = lidList->lidUnit;

            //... skip LID unit if it sends its drain flow onto
            //    its subcatchment's pervious area
            if (lidUnit->toPerv) continue;

One solution might be:

If(lidUnit->toPerv)
{
       // process next LID unit in the group
       lidList = lidList->nextLidUnit;
continue;
}

Linux compilation

I am having trouble compiling the SWMM shared object library on linux. The Makefile distributed with the source on the EPA website is shown below.

The issued the make command in the terminal but get the following error:
/usr/bin/ld: swmm5.o: relocation R_X86_64_PC32 against symbol `ErrorCode' can not be used when making a shared object; recompile with -fPIC

I tried adding the -fPIC flag to the cc command in the Makefile, but get the same error. Not sure where to go from here.

# Makefile for SWMM5

objs = swmm5.o climate.o controls.o culvert.o datetime.o dwflow.o dynwave.o error.o \
       exfil.o findroot.o flowrout.o forcmain.o gage.o gwater.o hash.o hotstart.o iface.o \
       infil.o inflow.o input.o inputrpt.o keywords.o kinwave.o landuse.o lid.o \
       lidproc.o link.o massbal.o mathexpr.o mempool.o node.o odesolve.o output.o \
       project.o qualrout.o rain.o rdii.o report.o roadway.o routing.o runoff.o shape.o snow.o \
       stats.o statsrpt.o subcatch.o surfqual.o table.o toposort.o transect.o treatmnt.o xsect.o


swmm5 : $(objs)
	cc -o libswmm5.so $(objs) -fopenmp -lm -lpthread -shared 

swmm5.o       : consts.h macros.h enums.h error.h datetime.h objects.h funcs.h text.h globals.h swmm5.h
climate.o     : headers.h
controls.o    : headers.h
culvert.o     : headers.h
datetime.o    : datetime.h
dwflow.o      : headers.h
dynwave.o     : headers.h
error.o       : error.h
exfil.o       : headers.h infil.h exfil.h
findroot.o    : findroot.h
flowrout.o    : headers.h
forcmain.o    : headers.h
gage.o        : headers.h
gwater.o      : headers.h odesolve.h
hash.o        : hash.h
hotstart      : headers.h
iface.o       : headers.h
infil.o       : headers.h infil.h
inflow.o      : headers.h
input.o       : headers.h lid.h
inputrpt.o    : headers.h lid.h
keywords.o    : text.h
kinwave.o     : headers.h findroot.h
landuse.o     : headers.h
lid.o         : headers.h infil.h lid.h
lidproc.o     : headers.h lid.h
link.o        : headers.h
massbal.o     : headers.h
mathexpr.o    : mathexpr.h
mempool.o     : mempool.h
node.o        : headers.h findroot.h
odesolve.o    : odesolve.h
output.o      : headers.h
project.o     : headers.h hash.h lid.h mempool.h
qualrout.o    : headers.h
rain.o        : headers.h
rdii.o        : headers.h
report.o      : headers.h
roadway.o     : headers.h
routing.o     : headers.h
runoff.o      : headers.h odesolve.h
shape.o       : headers.h
snow.o        : headers.h
stats.o       : headers.h
statsrpt.o    : headers.h lid.h
subcatch.o    : headers.h lid.h odesolve.h
surfqual.o    : headers.h lid.h
table.o       : headers.h
toposort.o    : headers.h
transect.o    : headers.h
treatmnt.o    : headers.h
xsect.o       : headers.h findroot.h

Compiling issue on OS X

Compiling on OS X using gcc via cmake failed due to errors in output.c

Left: fix that works, right: original

changes_to_output

String concatenation in the report file.

If a node has very large total inflow, the value will be concatenated with the previous value and make it hard for other application to parse the line (see example below). It will be better if a space was added between the values.

*******************
Node Inflow Summary
*******************

-------------------------------------------------------------------------------------------------
Maximum Maximum Lateral Total Flow
Lateral Total Time of Max Inflow Inflow Balance
Inflow Inflow Occurrence Volume Volume Error
Node Type CMS CMS days hr:min 10^6 ltr 10^6 ltr Percent
-------------------------------------------------------------------------------------------------
J10 JUNCTION 0.000169677.750 0 01:20 0 1.49e+06 -0.001

LID Models Hang in SWMM 5.1.013 but works fine in SWMM 5.1.02

A little history on this particular model. It stared live as a USGS Nurp Study in Dade County, Florida. I made a SWMM4 file for it and it has been the subject of many thesis. It was converted to SWMM5 many years ago and i use it a lot in InfoSWMM for water quality with hydrology. This model works in InfoSWMM, all SWMM 5 versions before and including SWMM 5.1.012 but hangs with no error message in SWMM 5.1.013. I have tried to find the issue but cannot.
Note: the file had to be changed to .txt from .inp for Github roles. Further note - this will work in SWMM 5.1.103 if you delete the LID Usage Tables. LID Controls do not have to deleted.

2015_Simple_Yet_Interesting_Network_InfoSWMM_13.txt

In the new SWMM 5.1.013 code there is a new parameter (extIfaceInflow;) in struct ExtInflow that does not get used

In the new SWMM 5.1.013 code there is a new parameter (extIfaceInflow;) in struct ExtInflow that does not get used or is always set to 0. Is this for a future or deprecated change?

//------------------------------
// DIRECT EXTERNAL INFLOW OBJECT
//------------------------------
struct ExtInflow
{
int param; // pollutant index (flow = -1)
int type; // CONCEN or MASS
int tSeries; // index of inflow time series
int basePat; // baseline time pattern
double cFactor; // units conversion factor for mass inflow
double baseline; // constant baseline value
double sFactor; // time series scaling factor
double extIfaceInflow;// external interfacing inflow ??? Set to zero and never updated
struct ExtInflow* next; // pointer to next inflow data object
};
typedef struct ExtInflow TExtInflow;

Possible bad area approximation for shallow water depths in egg shaped conduits?

Until now, my assumption was that the Phillips Standard Egg shape SWMM uses and the German egg profile according to DIN4263 are equivalent. At least in the case of full filling, the assumption seems to be correct.

However, in the case of very shallow water depths (< 0.1 * shape height), they seem to behave differently. I tracked this down to the second and third value in A_Egg from xsect.dat. Compared to my german reference book, those two values overestimate the area at depth / full depth = 0.04 and 0.08 by about 30% (relative). For higher fill levels, the deviation is around 0. This deviation propagates to the calculation of the velocity, where I observed it first.

static const double A_Egg[N_A_Egg] =
{.0000,.0150,.0400,.0550,.0850,.1200,.1555,.1900,.2250,.2750,
 .3200,.3700,.4200,.4700,.5150,.5700,.6200,.6800,.7300,.7800, 
 .8350,.8850,.9250,.9550,.9800,1.000};

My table says:


+--------------------+---------------------------+------------------------------+------+
| depth / full depth | area / full area SWMM egg | area / full area DIN4263 egg |  Δ%  |
+--------------------+---------------------------+------------------------------+------+
|               0,04 |                     0,015 |                       0,0116 | 29,3 |
|               0,08 |                      0,04 |                       0,0316 | 26,6 |
|               0,12 |                     0,055 |                       0,0562 | -2,1 |
|               0,16 |                     0,085 |                       0,0849 |  0,1 |
|                0,2 |                      0,12 |                       0,1173 |  2,3 |
|               0,24 |                    0,1555 |                       0,1531 |  1,6 |
|               0,28 |                      0,19 |                       0,1917 | -0,9 |
|               0,32 |                     0,225 |                       0,2331 | -3,5 |
|               0,36 |                     0,275 |                       0,2767 | -0,6 |
|                0,4 |                      0,32 |                       0,3223 | -0,7 |
|               0,44 |                      0,37 |                       0,3697 |  0,1 |
|               0,48 |                      0,42 |                       0,4186 |  0,3 |
|               0,52 |                      0,47 |                       0,4686 |  0,3 |
|               0,56 |                     0,515 |                       0,5196 | -0,9 |
|                0,6 |                      0,57 |                       0,5712 | -0,2 |
|               0,64 |                      0,62 |                       0,6233 | -0,5 |
|               0,68 |                      0,68 |                       0,6755 |  0,7 |
|               0,72 |                      0,73 |                       0,7274 |  0,4 |
|               0,76 |                      0,78 |                       0,7784 |  0,2 |
|                0,8 |                     0,835 |                       0,8275 |  0,9 |
|               0,84 |                     0,885 |                       0,8738 |  1,3 |
|               0,88 |                     0,925 |                       0,9163 |  0,9 |
|               0,92 |                     0,955 |                       0,9535 |  0,2 |
|               0,96 |                      0,98 |                       0,9833 | -0,3 |
+--------------------+---------------------------+------------------------------+------+


(from: Hydraulik der Abwasserkanäle in der Praxis (Pecher/Schmidt/Pecher, 1991)

Could you give me a hint where I can find information on how Phillips Standard Egg shapes are geometrically constructed and where those values in the lookup tables might come frome, so I might check my assumption?

Compiling SWMM v5.2 on Ubuntu 20.04

So far, two errors when building SWMM v5.2 on Ubuntu 20.04

(i) File: inlet.c
Lines 1570 & 1898: qMax = HUGE
Solution: change to qMax = BIG

(ii) File: output.c
Lines 37ff: #elif // Other platforms
and multiple error messages associated with F_OFF

Thanks for any suggestions to solve (ii) errors:
'#elif with no expression', and
'unknown type name ‘F_OFF’

+++++++++++++++++++++++++++++++++++++++++++++++++++++++

For example:

[ 60%] Building C object src/solver/CMakeFiles/swmm5.dir/output.c.o

.../Stormwater-Management-Model-develop/src/solver/output.c:36:37: error: #elif with no expression
36 | #elif // Other platforms
^
.../Stormwater-Management-Model-develop/src/solver/output.c:62:8: error: unknown type name ‘F_OFF’
62 | static F_OFF IDStartPos; // starting file position of ID names

.../Stormwater-Management-Model-develop/src/solver/output.c:63:8: error: unknown type name ‘F_OFF’
63 | static F_OFF InputStartPos; // starting file position of input data
| ^~~~~

etc, etc

*.rpt Link Flow Summary wrong column for weir results in GUI

This is possible bug in the EPA SWMM 5.1 GUI.
After running the model below, go to "Report->Summary->Topic: Link Flow"
model_full_features.inp

For the weir "C3" the last value 0.47 should be the last column. Instead it is displayed as max. vel.

A review of the *.rpt file showed that, for weir, the values of "max. vel" and "max. full flow" were omitted in the the line. A quick check the of "Tokenize" procedure in "Uutils.pas line 889 showed that the routine doesn't consider such situation, it assumes no values are omitted.

  ********************
  Link Flow Summary
  ********************
  
  -----------------------------------------------------------------------------
                                 Maximum  Time of Max   Maximum    Max/    Max/
                                  |Flow|   Occurrence   |Veloc|    Full    Full
  Link                 Type          CFS  days hr:min    ft/sec    Flow   Depth
  -----------------------------------------------------------------------------
  C1:C2                CONDUIT      7.22     2  09:59     18.36    0.90    0.50
  C2                   PUMP         9.41     0  10:00                          
  C3                   WEIR        12.12     0  10:00                      0.47

ImportError: libswmm-output not found.

When I use the package swmm_reader in tools, it raises the import error about libswmm-output. I wonder what is the libswmm-output, and where I can get it?

Access violation in module swmm_open

Access violation exception occurs when there are LID controls, but no subcatchments in the model.

LidProcs is not initialized in lid_create() method if number of subcatchments is zero:

void lid_create(int lidCount, int subcatchCount)
{
LidProcs = NULL;
LidGroups = NULL;
LidCount = lidCount;

//... create LID groups
GroupCount = subcatchCount;
if ( GroupCount == 0 ) return;
...

File open issue

If a model contains more than 508 time series that have external files, the engine will throw "ERROR 361" even these files are all valid. This seems to be a limitation in C run time. According to Microsoft Docs:

C run-time I/O now supports up to 8,192 files open simultaneously at the low I/O level. This level includes files opened and accessed using the _open, _read, and _write family of I/O functions. By default, up to 512 files can be open simultaneously at the stream I/O level. This level includes files opened and accessed using the fopen, fgetc, and fputc family of functions. The limit of 512 open files at the stream I/O level can be increased to a maximum of 8,192 by use of the _setmaxstdio function.

if I add _setmaxstdio(8192); before project_open(), the model will run:

_setmaxstdio(8192);

    // --- open a SWMM project
    project_open(f1, f2, f3);

Conduit loss calculation

In dynamic wave routing, the conduit loss calculation seems to have some issues. The loss should apply the flow-to node, not the flow-from node. Otherwise, the routing continuity error will increase.

  1. From updateNodeFlows() in dynwave.c (SWMM5.1.013)

    // --- update total inflow & outflow at upstream/downstream nodes
    if ( q >= 0.0 )
    {
    Node[n1].outflow += q + uniformLossRate;
    Node[n2].inflow += q;
    }
    else
    {
    Node[n1].inflow -= q;
    Node[n2].outflow -= q - uniformLossRate;
    }

The above code should be:

if ( q >= 0.0 )
{
Node[n1].outflow += q;
Node[n2].inflow += q - uniformLossRate;
}
else
{
Node[n1].inflow -= q + uniformLossRate;
Node[n2].outflow -= q;
}

  1. Where to apply number of barrels?
    uniformLossRate = (Conduit[k].evapLossRate + Conduit[k].seepLossRate)*barrels;

  2. Loss should be cleared when the conduit is dry in dwflow_findConduitFlow():
    if ( Link[j].flowClass == DRY ||
    Link[j].flowClass == UP_DRY ||
    Link[j].flowClass == DN_DRY ||
    isClosed ||
    aMid <= FUDGE )
    {
    Conduit[k].a1 = 0.5 * (a1 + a2);
    Conduit[k].q1 = 0.0;;
    Conduit[k].q2 = 0.0;

    Conduit[k].evapLossRate = 0;
    Conduit[k].seepLossRate = 0;

     Link[j].dqdh  = GRAVITY * dt * aMid / length * barrels;
     Link[j].froude = 0.0;
     Link[j].newDepth = MIN(yMid, Link[j].xsect.yFull);
     Link[j].newVolume = Conduit[k].a1 * link_getLength(j) * barrels;
     Link[j].newFlow = 0.0;
     return;
    

    }

Please see the following input file for example (rename it to .inp file):

Evaporation.txt

Transect roughness issue

If a transect has its right bank not defined, i.e. Xrightbank = 0, the engine still use its roughness in the flow calculation in transect.c getFlow() method:

if ( findFlow )
{
// --- find value of Manning's n to use
n = Nchannel;
if ( Station[k-1] < Xleftbank ) n = Nleft;
if ( Station[k] > Xrightbank ) n = Nright;

    // --- compute flow through flow area
    return PHI / n * a * pow(a/wp, 2./3.);
}

I think Xrightbank > 0 or Xrightbank > Xleftbank should also be evaluated as well.

Where to Post Bug Fixes

I have updated the v5.1.013 source files to fix all of the bugs identified to date. They appear in the attached zip file along with a set of examples for each bug fix. It appears that this repo is strictly archival and doesn't allow branches cloned off of the master to be published. Is the OWA-SWMM repo the place to push these bug fixes? If so, will they find their way into an official EPA-SWMM release anytime soon?
swmm5.1.013_Bug_Fixes.zip

Allow user-defined Section words

Input.c (input_readData) only accepts section words used by the computational engine or the Delphi GUI (COORDINATE, VERTICES, POLYGON, LABEL, SYMBOL, BACKDROP, TAG, PROFILE, and MAP). The program would be more flexible for working with custom engines and GUIs if it ignored or triggered warnings upon encountering unknown section headers.

High runoff continuity error caused by LID

SoilVolume is not initialized for roof disconnection LID, so SoilVolume from other LID could be added to roof disconnection LID thus causes high runoff continuity error.

void roofFluxRates(double x[], double f[])
{
......
SurfaceVolume = surfaceDepth;
SoilVolume = 0; // This line should be added to reset SoilVolume
SurfaceInfil = 0.0;
......
}

This simple model below illustrates the issue. Run it directly, the runoff error is around -24% and Final Storage at roof disconnection LID is 88.01 mm (much large than its depth at 1). Delete the other LID usage and run again, the runoff continuity error will drop down to normal value.

test.txt

I also discovered total volume comprises four parts (lidproc_saveResults() method):
totalVolume = SurfaceVolume + PaveVolume + SoilVolume + StorageVolume;

The PaveVolume is only initialized in pavementFluxRates() method, which could potentially used for other LID unit. How about initialize the four variables in lidproc_getOutflow() method:

//... initialize layer flux rates and moisture limits

SurfaceVolume = 0.0;
PaveVolume = 0.0;
SoilVolume =0.0;
StorageVolume = 0.0;

SurfaceInflow = inflow;
SurfaceInfil = 0.0;

Allow multiple outfalls to be listed in a single timeseries file

I'm working on a model that has over 100 outfalls. Rather than requiring a unique file for each outfall, it would be more elegant to expand the timeseries file format to allow an optional ID (e.g. following the value field) and thus allow the user to use a single boundary conditions file. No GUI change would be needed.

Alternatively, the file format could follow the structure of calibration files in the EPA GUI, where the location ID is listed on a header line and datetime/value pairs follow.

EPA SWMM has at least five timeseries formats: internal timeseries (ID m/d/y h:m value), timeseries file (m/d/y h:m value), GUI calibration file timeseries (same as external timeseries but with ID header), routing interface file (header followed by ID y m d h m s value), and rain gage (like routing interface but without header or seconds). Despite all these options, it does not accommodate y/m/d and d/m/y formats and does not allow a multi-location outfall file as I've suggested here.

Temperature calculations for Hargreaves evaporation

I’m getting PET values that are about half of what I expect and I think it’s because SWMM5 is using the wrong temperature values. See attached files in “InternationalFallsMN_DailyRainEvap.zip”. The GHCN-Daily climate summary file “InternationalFallsMN_DailyGHCN_1907-2020.txt” has TMIN and TMAX values that range between -55 and 103 deg-F. However, when I plot the System Temperature, it shows a range between 24-50 deg-F (the average daily temp should be between -30 and 83 deg-F).
image
InternationalFallsMN_DailyRainEvap.zip

Missing 0 in Version Folder Names

My apologies if this is a silly request but can the folders named such as 5.1.10 be renamed 5.1.010? to fill in the missing 0 in the release name?

Exception in reporting average results

If the "Report average results" option is chosen and the number of links does not equal to the number of nodes in the model, an "Access violation in module swmm_step at step 62, hour 0 --- execution halted." exception will happen.

In output_saveAvgResults() method:

for (i = 0; i < **Nobjects[NODE]**; i++)
{
	SysResults[SYS_STORAGE] += (REAL4)(Link[i].newVolume * UCF(VOLUME));
}

Nobjects[NODE] should be Nobjects[LINK].

Time step averaging issue

When the SWMM engine announced that we will be able to get time series results for a project's nodes and links reported as average values computed over a reporting time step instead of being interpolated point values at the end of the reporting time step.

While we were testing the latest SWMM engine so that we can switch our engines; we potentially found a bug in the averaging of reported values for pipes. This bug may not impact systems that do not experience frequent flow reversals.

Here is the brief description of the issue.
While averaging the values the absolute values of the flow are used for averaging instead of the flows with the associated flow direction (negative value for flow reversal). After the flow is averaged, the last timesteps flow direction is assumed to the flow direction for the whole averaged period. If the flow changes direction from upstream to downstream and from downstream to upstream, during the averaging period, then the averaging will overestimate the flow and potentially the effective flow direction; this will also lead to issues with volume calculations.

https://www.openswmm.org/SWMM51015/output-c/output_updateAvgResults
swmm

While we are on the topic we would like to take the opportunity to mention an item on the wish list. Would it be possible for the user to define how the averaging is being performed the three options that we can think of are the following.

  1. Centralized average: The values on both sides (before and after the reported timestep) of reported timestep are equally averaged. (averaged and assigned to the middle timestep)
  2. Left averaging: Values after(in time) the reported timestep are averaged and assigned. (averaged and assigned to the first timestep)
  3. Right averaging: Values before(in time) the reported timestep are averaged and assigned. (averaged and assigned to the last timestep)

We've posted this issue to the SWMM listserv as well. As always we are thankful for the development team in supporting SWMM and releasing updated engines frequently.

No street sweeping when end day/month before start day/month

I think this is a holdover bug for SWMM 4 but street sweeping does not work if you have an ending day/month before the starting day/month of street sweeping. The dialog needs a year to function correctly or just sweep 12 months a year…

From Runoff.C

    // --- see if street sweeping can occur on current date
    day = datetime_dayOfYear(currentDate);
    if ( day >= SweepStart && day <= SweepEnd ) canSweep = TRUE;
    else canSweep = FALSE;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.