usepa / stormwater-management-model Goto Github PK
View Code? Open in Web Editor NEWDynamic hydrology-hydraulic water quality simulation model
Dynamic hydrology-hydraulic water quality simulation model
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?
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.
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.
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
This is an engine error in SWMM 5.1.013 and earlier if the user has all zero R values for the RDII UH hydrolographs. The lack of ANY zero R should be an error message and trapped in the engine.
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
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?
It would be nice to have include guards on header files. Then we could work on untangling include dependencies.
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.
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;
}
Where to apply number of barrels?
uniformLossRate = (Conduit[k].evapLossRate + Conduit[k].seepLossRate)*barrels;
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):
A user was using NOAA rainfall and it seems the NOAA rainfall is not consistent. A few negative increments in the last 9 hours cause the rainfall to inflate from 3 to 90 inches. I am attaching the text file in case it helps others.
The rainfall looks like this in SWMM5
once you run the model the total rainfall is 90 inches instead of 3.2 inches and the hyetograph looks like this
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].
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.
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
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.”
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.
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;
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>>
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.
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.
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
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.
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.
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.”
In control.c executeActionList() method, the following code
if ( RptFlags.controls )
is changed to
if ( RptFlags.controls && a1->curve < 0 //(5.1.011)
&& a1->tseries < 0 && a1->attribute != r_PID ) //(5.1.011)
This change will cause curve/timeseries action not reported in the report file.
Please see attached sample input file.
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.
@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?
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.
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.
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
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
consts.h at line 16 defines macro VERSION.
#define VERSION 51000
this value is returned by swmm_getVersion function
It would be nice update to 51010 including also subversion numbering (Build 5.1.010)
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;
...
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;
}
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;
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.
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
@LRossman Actions is currently down. I'm going to make some commits to the lew-develop branch to fix it. Thanks in advance for you cooperation.
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
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);
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.
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:
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;
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
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).
InternationalFallsMN_DailyRainEvap.zip
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.
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
The Maximum Infiltration Volume feature works fine with the original Horton infiltration model (it correctly shuts off infiltration at 1-5 inches for the various subcatchments in the attached file). But it gives incorrect results when you switch to Modified Horton.
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
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
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.
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?
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;
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.