From afbb5181e19fe05e67d075b9d95968f8f6474e63 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Fri, 4 Sep 2020 14:18:07 -0400 Subject: [PATCH] Processing update swmm v5.1.15 (#61) In addition to improvements described in ReleaseNotes this PR includes: - Improvements to cmake build system - Testing scripts previously found in /tools have migrated to their own repo - Support for GitHub Actions has been added --- .github/workflows/build-and-test.yml | 71 ++ .gitignore | 15 +- Build.md | 4 +- CMakeLists.txt | 28 +- README.md | 16 +- ReleaseNotes.txt | 1307 ++++++++++++++++++++++++++ extern/boost.cmake | 35 + src/outfile/CMakeLists.txt | 9 + src/outfile/swmm_output.c | 4 +- src/run/main.c | 8 +- src/solver/CMakeLists.txt | 12 +- src/solver/consts.h | 14 +- src/solver/datetime.h | 7 + src/solver/dynwave.c | 15 +- src/solver/enums.h | 27 +- src/solver/error.c | 9 +- src/solver/error.h | 19 +- src/solver/exfil.h | 4 +- src/solver/findroot.h | 8 + src/solver/flowrout.c | 6 +- src/solver/funcs.h | 24 +- src/solver/globals.h | 16 +- src/solver/hash.h | 7 + src/solver/headers.h | 1 + src/solver/hotstart.c | 7 +- src/solver/include/swmm5.h | 12 +- src/solver/infil.c | 138 +-- src/solver/infil.h | 25 +- src/solver/inflow.c | 174 ++-- src/solver/input.c | 5 +- src/solver/keywords.h | 7 + src/solver/lid.c | 33 +- src/solver/lid.h | 16 +- src/solver/macros.h | 7 + src/solver/mathexpr.h | 7 + src/solver/mempool.h | 7 + src/solver/node.c | 15 +- src/solver/objects.h | 56 +- src/solver/odesolve.h | 7 + src/solver/project.c | 5 +- src/solver/qualrout.c | 7 +- src/solver/report.c | 42 +- src/solver/stats.c | 46 +- src/solver/statsrpt.c | 12 +- src/solver/subcatch.c | 47 +- src/solver/swmm5.c | 18 +- src/solver/text.h | 12 +- tests/CMakeLists.txt | 18 +- tests/Unit_Testing.md | 4 +- tools/Reg_Testing.md | 50 - tools/app-config.cmd | 58 -- tools/before-nrtest.cmd | 116 --- tools/make.cmd | 108 --- tools/requirements-win.txt | 22 - tools/run-nrtests.cmd | 114 --- 55 files changed, 2048 insertions(+), 813 deletions(-) create mode 100644 .github/workflows/build-and-test.yml create mode 100644 ReleaseNotes.txt create mode 100644 extern/boost.cmake delete mode 100644 tools/Reg_Testing.md delete mode 100644 tools/app-config.cmd delete mode 100644 tools/before-nrtest.cmd delete mode 100644 tools/make.cmd delete mode 100644 tools/requirements-win.txt delete mode 100644 tools/run-nrtests.cmd diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 000000000..b92ab7048 --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,71 @@ +# +# build-and-test.yml - GitHub Actions CI for swmm-solver +# +# Created: May 19, 2020 +# Updated: May 31, 2020 +# +# Author: Michael E. Tryby +# US EPA - ORD/CESER +# + +name: Build and Test + +on: + push: + branches: [ master, develop, release, codedrop ] + pull_request: + branches: [ master, develop, release, codedrop ] + +jobs: + win_build: + runs-on: windows-2016 + defaults: + run: + shell: cmd + working-directory: ci-tools/windows + + env: + OMP_NUM_THREADS: 1 + PROJECT: swmm + BUILD_HOME: build + TEST_HOME: nrtests + NRTESTS_URL: https://github.com/SWMM-Project/swmm-nrtestsuite + + steps: + - name: Checkout repo + uses: actions/checkout@v2 + + - name: Checkout submodule + uses: actions/checkout@v2 + with: + repository: michaeltryby/ci-tools + path: ci-tools + + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: '3.7' + + - name: Install requirements + run: | + python -m pip install --upgrade pip + python -m pip install -r requirements-swmm.txt + + - name: Build and unit test + run: make.cmd /t + + - name: Build for reg test + run: make.cmd + + - name: Before reg test + run: before-nrtest.cmd + + - name: Run reg test + run: run-nrtests.cmd %GITHUB_RUN_ID%_%GITHUB_RUN_NUMBER% + + - name: Upload artifacts + if: ${{ always() }} + uses: actions/upload-artifact@v2 + with: + name: nrtest-artifacts + path: upload/ diff --git a/.gitignore b/.gitignore index a441c732a..548e7a2f5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,16 @@ -# Eclipse Stuff -.metadata/ -.settings/ + + +.DS_Store + +build*/ +nrtest*/ + +*_export.h + +src/outfile/include/*_export.h +src/solver/include/*_export.h build/ nrtests/ +upload/ diff --git a/Build.md b/Build.md index b9352e45d..b0383fe78 100644 --- a/Build.md +++ b/Build.md @@ -21,12 +21,12 @@ Before the project can be built the required dependencies must be installed. - Build - Build Tools for Visual Studio 2017 - CMake 3.13 - + - ci-tools repository ### Build SWMM can be built with one simple command. ``` \> cd swmm -\swmm>tools\make.cmd +\swmm>ci-tools\windows\make.cmd ``` diff --git a/CMakeLists.txt b/CMakeLists.txt index 5918cfe51..4e4d65ae7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # CMakeLists.txt - CMake configuration file for swmm-solver # # Created: July 11, 2019 -# Modified: Nov 25, 2019 +# Updated: May 29, 2020 # # Author: Michael E. Tryby # US EPA ORD/CESER @@ -17,12 +17,12 @@ endif() project(swmm-solver - VERSION 5.1.14 + VERSION 5.1.15 LANGUAGES C CXX ) # Append local dir to module search path -list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) +# list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) # Sets the position independent code property for all targets set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -40,8 +40,7 @@ set(LIBRARY_DIST "lib") set(CONFIG_DIST "cmake") -option(BUILD_TESTS "Builds component tests (requires Boost)" OFF) -option(BUILD_DEF "Builds library with def file interface" OFF) +option(BUILD_TESTS "Build component tests (requires Boost)" OFF) # Add project subdirectories @@ -55,25 +54,6 @@ if(BUILD_TESTS) endif() -# Create target import scripts so other cmake projects can use swmm libraries -install( - EXPORT - swmm5Targets - DESTINATION - "${CONFIG_DIST}" - FILE - swmm5-config.cmake - ) - -install( - EXPORT - swmm-outputTargets - DESTINATION - "${CONFIG_DIST}" - FILE - swmm-output-config.cmake - ) - # Create install rules for vcruntime.dll, msvcp.dll, vcomp.dll etc. set(CMAKE_INSTALL_OPENMP_LIBRARIES TRUE) include(InstallRequiredSystemLibraries) diff --git a/README.md b/README.md index b84872ef1..09a0e1894 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,16 @@ Stormwater-Management-Model ORD Stormwater Management Model (aka "SWMM") -Introduction ------------- -This is the official SWMM source code repository maintained by US EPA ORD, NRMRL, Water Supply and Water Resources Division located in Cincinnati, Ohio. + +## Build Status +![Build and Test](https://github.com/USEPA/Stormwater-Management-Model/workflows/Build%20and%20Test/badge.svg) + + +## 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](http://www2.epa.gov/water-research/storm-water-management-model-swmm). + +## Find Out More +The source code distributed here is identical to the code found at the official [SWMM Website](http://www2.epa.gov/water-research/storm-water-management-model-swmm). diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt new file mode 100644 index 000000000..eb74d01bb --- /dev/null +++ b/ReleaseNotes.txt @@ -0,0 +1,1307 @@ +SWMM 5.1 Update History +======================= + +------------------------- +Build 5.1.015 (July 2020) +------------------------- + +Engine Updates: + +1. A mix of infiltration methods can now be used within a project. + +2. Monthly adjustments to depression storage are now applied only to + the pervious area of subcatchments instead of to both pervious and + impervious areas. + +3. The Status Report now includes a grouped frequency table of the + variable routing time steps used during a simulation. + +4. An error in the average summary statistics reported for projects + with a reporting start date later than the simulation start date + was fixed. + +5. A fatal error is now issued if a storage node's area curve produces + a negative volume when extrapolated to the node's full depth. + +6. A pollutant mass balance error occurring when very shallow storage + units lost all inflow to flooding was fixed. + +7. Conduit evaporation and seepage losses are now applied directly to + the conduit's flow rate instead of just to the downstream node's + inflow to reduce water quality mass balance errors. + +8. Spurious values appearing for Final Water Table and Upper Mositure + Content in the Groundwater Summary Results Table for completely + impervious subcatchments were corrected. + +GUI Updates: + +1. The mouse wheel can now be used to zoom in or out of the Study Area + Map and when pressed be used to pan the map. + +2. The Subcatchment Infiltration Dialog was modified to accept a choice + of infiltration method. + +3. The Group Editor dialog was modified to allow a choice of infiltration + method and its parameters be assigned to a group of subcatchments. + +4. The Control Curve assigned to an LID unit's drain layer was being + ignored by the input file reader. + +5. Some problems with the Graph Options dialog for the Statistics Report + plots were fixed. + +6. Better support for 4K ultra HD monitors was added. + +7. The latter update required that the three toolbars on the + main window be combined into one to avoid resizing issues. + +------------------------ +Build 5.1.014 (03/01/20) +------------------------ + +Engine Updates: + +1. Fixed a refactoring bug that produced incorrect rainfall when the same + time series was used by one rain gage assigned to a RDII Unit Hydrograph + and also by another gage assigned to a subcatchment. + +2. Fixed skipping the first rain gage in a project when checking + if two gages have the same station ID but use different data files. + +3. Fixed a program crash when running projects with LID units but no + subcatchments. + +4. Fixed having LID underdrain pollutant loads incorrectly added to the + mass balance totals. + +5. Fixed the program from hanging when an LID unit sent its outflow back + onto the pervious area of its own subcatchment. + +6. Fixed a failure to re-initialize layer volumes as each LID unit is + evaluated (which could cause incorrect results for certain + combinations of LID units). + +7. Fixed street sweeping being ignored when the sweeping period + began with a higher day of the year than the end of the period. + +8. Fixed incorrect adjustments being made for conduit evaporation and + seepage losses under dynamic wave flow routing. + +9. Fixed having soil moisture deficit recovery be ignored for Green-Ampt + exfiltration from storage units. + +10. Fixed having node/link ID names be mistaken for option keywords + in the [REPORT] section of an input file. + +11. Fixed a possible program crash when using the option to report average + values within each reporting time interval instead of point values. + + +------------------------ +Build 5.1.013 (05/10/18) +------------------------ + +Engine Updates: + +1. A subcatchment's depression storage depth, its pervious surface roughness + (Mannings n) and its hydraulic conductivity can now be adjusted on a + monthly basis by assigning monthly time patterns to these properties. + For conductivity, a subcatchment-specific adjustment pattern will + override any project-wide set of climate adjustment factors. + +2. LID controls can now treat a designated portion of a subcatchment’s + pervious area runoff (previously they could only treat impervious area + runoff). + +3. Permeable pavement LID units subjected to clogging over time can now + have their permeability only partly restored at periodic time + intervals + +4. The following options were added to control flow out of LID units + through their underdrains: + - A storage layer water depth above which a closed drain automatically + opens. + - A storage layer water depth below which an open drain automatically + closes. + - A control curve that specifies how the nominal drain flow rate is + adjusted as a function of the head seen by the drain. + +5. Pollutant removal percentages can now be assigned to LID processes that + have underdrains. The removals apply to flow leaving the unit through the + drain and not to any surface overflow from the unit. + +6. The Subcatchment Runoff Summary Report now includes both pervious and + impervious total runoff volumes (prior to any LID treatment) for each + subcatchment. + +7. A choice of method used to handle surcharging has been added to the list + of Dynamic Wave options. The EXTRAN method continues to use the traditional + Surcharge Algorithm to update the head at surcharged nodes. The new SLOT + option attaches a Preissmann Slot to closed conduits flowing more than 98.5% + full that eliminates the need to switch to the Surcharge Algorithm for + surcharged nodes. + +8. A closed vessel can now be modeled as a storage unit node that is allowed + to pressurize up to a designated Surcharge Depth value. If this depth is 0 + then the unit is modeled as before as an open vessel. + +9. A weir's discharge coefficient can now be allowed to vary with head across + the weir by assigning it a Weir Curve (see Weir Properties). Weir curves + tabulate coefficient values at specific head levels. + +10. When the upstream offset of a regulator link is below the invert of its + downstream node it is now automatically raised only for Dynamic Wave flow + routing with a warning message issued. For other flow routing choices only + the warning message is issued and no automatic offset adjustment is made. + +11. Users can now choose to set a periodic time step for control rule evaluation. + If this step is 0 then rules are tested as before at every routing time step. + +12. The option was added to have time series results for a project's nodes and + links be reported as average values computed over a reporting time step + instead of being interpolated point values at the end of the reporting time + step. + +13. The following bugs were fixed: + - Unused rain gages are no longer examined when adjusting the wet runoff + time step. + - The surface inflow rate to a permeable pavement LID unit is not allowed + to exceed the pavement’s permeability. + - The Minimum Nodal Surface Area dynamic wave routing option was being used + as surface area always available at a node instead of an amount available + only when the surface area of the node's connecting links fell below it. + - The top width of a full closed rectangular cross section shape is now set + to 0 since it can no longer supply any surface area. + - The ‘C’ parameter value for a Mitered Corrugated Metal Arch culvert was + corrected. + - An incorrect reporting of flow continuity error for systems with backflow + through outfall nodes was fixed. + +GUI Updates + +1. Various property editors and dialog forms were updated to accomodate the newly + added engine features (monthly time patterns for subcatchment properties, LID + underdrain parameters, LID pollutant removal, choice of surcharge method, + storage unit surcharge depth, weir coefficient curve, control rule time step, + and reporting of average values). + +2. A bug that failed to record the choice of number of barrels for rectangular + conduits in the Cross-Section Editor form was fixed. + +3. A bug in the GetLinkOutVal function of the Uoutput.pas unit was fixed. + + +------------------------ +Build 5.1.012 (03/14/17) +------------------------ + +Engine Updates: + +1. The direct.h header is now only #included in the swmm5.c file when + compiled for Windows. (swmm5.c) + +2. Engine Update #7 in Build 5.1.011 (internally aligning the wet time + step with the reporting time step) was redacted since it caused + problems for certain combinations of time steps. (runoff.c) + +3. A subcatchment's bottom elevation is now used instead its parent + aquifer's value when saving a water table value to the binary results + file. (subcatch.c) + +4. A bug that failed to limit surface inflitration into a saturated rain + garden LID unit was fixed. (lidproc.c) + +5. Calculation of the maximum limit on LID drain flows was modified to + produce smoother results at low depths above the drain offset. + (lidproc.c) + +6. A variable used for reporting detailed LID results is now properly + initialized. (lid.c & lid.h) + +7. The occasional writing of duplicate lines to the detailed LID results + file was fixed. (lidproc.c) + +8. The conversion from conduit seepage rate per unit area to rate per unit + of length was changed to use top width instead of wetted perimeter since + only vertical seepage is assumed to occur. (link.c) + +9. The coefficient of the evaporation/seepage term in the dynamic wave + equation for updating conduit flow was corrected (from 1.5 to 2.5). + (dwflow.c) + +10. The Engels flow equation for side flow weirs was corrected (the original + equation used in SWMM 3 & 4 was incorrect). (link.c) + +11. Crest length reductions for end contractions are no longer used for + trapezoidal weirs. (link.c) + +12. The Slope Correction Factor for culverts with mitered inlets was corrected. + (culvert.c) + +13. An entry in the table of gravel roadway weir coefficients was corrected. + (roadway.c) + +14. The user supplied minimum slope option is now initialized to 0.0 + (meaning none is provided). (project.c) + +15. NO/YES are no longer accepted as attributes for the NORMAL_FLOW_LIMITED + dynamic wave simulation option (only SLOPE/FROUDE/BOTH are valid). + (project.c) + +16. Changes were made so that the Routing Events and Skip Steady Flow + options work correctly together. (routing.c & globals.h) + +17. Steady state periods with no flow routing no longer contribute to the + routing time step statistics. (stats.c and report.c) + +18. When compiling statistics on the frequency of full conduit flow the + number of barrels is now accounted for. (stats.c) + +19. Under kinematic wave or steady flow routing, the water level in + storage nodes that have no outflow links is now updated correctly + over time. (flowrout.c) + +20. The formula for the depth at maximum width for the Modified Basket Handle + cross section was corrected. (xsect.c) + + +GUI Updates: + +1. Profile plots now correctly update the main and axis title text when + changed via the Profile Plot Options dialog. Also the downstream + offset height of non-conduit links is set to 0 on the plot. + +2. The LID Control Editor now sets the Storage Layer Thickness to 0 when + a Rain Garden is selected as the type of LID being edited. + +3. An OnChange event handler was added to each of the LID Control Editor's + data fields to record when a value is changed. + +------------------------ +Build 5.1.011 (08/22/16) +------------------------ + +Engine Updates: + +1. Detailed flow routing can now be restricted to a set of pre-defined + event periods. The event periods are listed in an [EVENTS] section + of the SWMM input file, where each line contains a start date, + start time, end date and end time for each event. + +2. New functions, swmm_getError() and swmm_getWarnings(), were added to + the API used for interfacing SWMM with other applications (see the + updated Interfacing Guide for details). + +3. The error codes returned by the API functions (swmm_open, swmm_start, + swmm_step, etc.) were corrected. + +4. The new format for precipitation amounts in rainfall files downloaded + from the NCDC's Climate Data Online service are now recognized. + +5. Monthly adjustments for hydraulic conductivity are now also + applied to the internal Green-Ampt "Lu" parameter which varies with + the square root of conductivity. + +6. A check was added to insure that subcatchment imperviousness does + not exceed 100 percent. + +7. Runoff time steps are now adjusted to stay aligned with the Report + time step (making model validation easier). + +8. A time step correction was made when computing the outflow volume + produced by an outfall that sends its outflow back onto a designated + subcatchment. + +9. The LID routines were modified so that native soil infiltration is + satisfied first when it occurs along with underdrain flow, instead + of the other way around. + +10. The allowable offset height for an LID underdrain is no longer + limited to the top of the storage layer thus allowing upturned + drains to be modelled. + +11. The detailed LID report file now lists results by both date/time + and elapsed hours and reports water level instead of moisture + content for permeable pavement. + +12. If the offset of the opening of a regulator link is below its + downstream node invert it is now raised to the invert level + and a warning message is still issued. + +13. A weir with an open rectangular shape and non-zero slope parameter + will no longer generate an input error message - the slope value is + now ignored. + +14. An illegal array index bug that could occur when checking the pump + curve type for an Ideal Pump in dynamic wave flow routing was fixed. + +15. A redundant unit conversion of max. reported depth from the Node + Depth Summary table was removed. + +16. Node surcharging is now only reported for dynamic wave flow routing + and storage nodes are never classified as surcharged. + +17. A failure to convert a storage unit's surface area curve from metric + to internal units when computing bottom exfiltration was fixed. + +18. A bug that caused a link's TIMEOPEN variable (used in control rule + conditions) to be re-set to 0 when its setting changed from one + partly opened state to another was fixed. + +19. The Status Report no longer lists control actions taken by modulated + controls since they occur continuously over time and can produce an + enormous number of actions. + +20. A failure to convert a Roadway Weir's road width that was in metric + units was fixed. + +21. A bug that caused the saved link settings read from a hot start + file to be incorrect in a model containing pollutants was fixed. + +22. Rule premises can now include SIMULATION DAYOFYEAR as a condition, + where day of year is either in month/day format or a number between + 1 and 365. + +23. A refactoring bug that affected water quality mass balance results + for Steady Flow routing was fixed. + +24. The function that decodes the fractional part of a date/time value + into hours:minutes:seconds was modified so that rounding doesn't + cause the time to exceed 24 hours. + +25. Microsoft exception handling statements are now only enabled when + the engine is compiled with the Microsoft C compiler. + +GUI Updates: + +1. A new sub-category of simulation options named Events was added along + with an Event Editor dialog to allow users to restrict detailed flow + routing calculations to specific periods of time. See the Help file + topic under Reference | Special Dialog Forms | Events Editor. + +2. When a Rain Garden is selected in the LID Control Editor, the Storage + layer tab now appears so that a bottom Seepage Rate can be specified. + This fixes the problem of having no inflitration out of a Rain Garden. + +3. After a simulation has been completed the Run Status dialog box now + indicates if any warning messages have been issued. + +4. A previously uninitialized variable (elapsed simulation time) passed + between the GUI and the engine is now assigned an initial value. + +5. The ground surface line on a Profile Plot can now be made visible or + not via the Profile Plot Options dialog, with the default being visible. + +6. An option to use thick lines to outline conduits and the ground surface + in Profile Plots was added. + + +------------------------- +Build 5.1.010 (08/05/15) +------------------------- + +Engine Updates: + +1. A modified version of Green-Ampt infiltration (MODIFIED GREEN AMPT) was + added that no longer redistributes upper zone moisture deficit during + low rainfall events. The original authors of SWMM's Green-Ampt model + have endorsed this modified version. It will produce more infiltration + for storm events that begin with low rainfall intensities, such as the + SCS design storm distributions. + +2. A new type of weir, a ROADWAY weir, has been added. It models roadway + overtopping using the FHWA HDS-5 method and would typically be used in + parallel with a culvert conduit. + +3. Rule premises can now test whether a link has been open (or closed) for + a specific period of time. See the Help file for more details. + +4. Unsaturated hydraulic conductivity ("K") was added to the list of + variables that can be used in a user-supplied groundwater flow equation. + +5. A bug introduced in update 2 of release 5.1.008 that failed to include + infiltration from LID units into the groundwater routine was fixed. + +6. A bug that failed to properly initialize the flag indicating that one or + more LID controls was initially wet was fixed. + +7. Duplicate printing of the first line of an LID detailed report file was + corrected. + +8. The Hargreaves evaporation forumla was modified to use a 7-day running + average of daily temperatures, instead of just single day values, as + recommended by the formula's authors. + +9. Daily potential evapotranspiration (PET) was added as a system output + variable. + +10. The qualrout.c module was refactored to make it more compact and easier + to follow. + +11. Storage seepage and evaporation losses are now based on the storage volume + at the end, not the start, of the prior time step. + +12. The command line used to build the engine included in the "makefile" + for the GNU C/C++ compiler was corrected to include the OpenMP libraries. + +GUI Updates: + +1. Potential evapotranspiration (PET) was added as new system-wide variable + whose time series can be viewed with a graph or table. + +2. A bug in the Number of Threads dropdown list on the Dynamic Wave Options + dialog was fixed. + +3. Additional bugs in the Cross Section Editor remaining from changes made + in release 5.1.008 were fixed. + +4. Changes were made to accommodate the new Modified Green-Ampt infiltration + option and the new Roadway weir option. + +5. The automatic scaling of plots with all y-values the same was improved. + +6. The automatic scaling of profile plots was improved and the ground surface + line was removed to improve clarity. + +7. The function that automatically converts all link depth offsets to + elevation offsets now uses the node invert elevation value rather + than *' for a zero offset. + +8. A bug in using the Macro List on the Add-In Tools Properties form to + insert a selection into the Working Directory edit box was fixed. + + +-------------------------- +Build 5.1.009 (04/30/2015) +-------------------------- + +General: + +1. A missing DLL file used to parallelize SWMM's flow routing + routine was added to the installation package. + +Engine Updates: + +1. A re-factoring bug that prevented running simulations longer + than 68 years was fixed. + +2. An input parsing error that prevented the program from + recognizing a comparison between two variables in a + control rule premise was fixed. + +3. A new warning message was added for when a control rule + premise compares two different types of variables. + +4. When implementing 5.1.008 update 12, the runon to a + subcatchment fully occupied by LIDs was not being included + in the subcatchment's Summary Report. + +5. A bug was fixed that allowed LID units to return outflow to + a subcatchment's pervious area even though LIDs occupied the + entire subcatchment. + +6. For quality routing the definition of a dry conduit/storage + node was changed to <= 1 mm of depth to avoid concentrations + from blowing up due to evaporation losses. + +7. The units label for Total Inflow Volume in the Node Inflow + Summary table of a saved report file was corrected. + +GUI Updates: + +1. A bug introduced as a result of 5.1.008 GUI Update 11 that + prevented the name of a conduit's Transect or Shape Curve + from appearing in the Cross Section Editor was fixed. + +2. A nicer default axis scaling routine is now used for time + series and scatter plots. + +3. The user-supplied custom scaling for the vertical axis of a + profile plot is now recognized. + + + +-------------------------- +Build 5.1.008 (04/02/2015) +-------------------------- + +Engine Updates: + +New Features: +============= + +1. Monthly adjustments for hydraulic conductivity used for + rainfall infiltration and for exfiltration from storage + nodes and conduits was added. + +2. LID drains can now send their outflow to a different node + or subcatchment than the parent subcatchment in which they + were placed. + +3. Conveyance system Outfall nodes now have the option to + send their outflow onto a subcatchment, to simulate + irrigation or complex LID treatment options. + +4. A new LID practice, Rooftop Disconnection, has been added. + It allows one to explicitly model roof runoff with an + optional limit on the flow capacity of their downspouts. + Disconnection is specified by setting the Return To Pervious + Area field in the [LID_USAGE] section to 1. + +5. An optional soil layer has been added to Permeable Pavement + LIDs so that a sand filter or bedding layer beneath the + pavement can be modeled. + +6. Several new built-in variable names can now be used in + custom groundwater flow equations for porosity, unsaturated + hydraulic conductivity, infiltration rate, and percolation + rate. See the Help file for more details. + +7. A Groundwater Summary table has been added that reports + several groundwater statistics for each subcatchment. + +8. A new option, the Minimum Variable Time Step, was added that + limits the smallest time step that can be computed under + variable time stepping for dynamic wave flow routing. In + previous releases it was fixed at 0.5 seconds which remains + the default. The smallest value it can now have is 0.001 sec. + +9. The dynamic wave routing procedure was parallelized to take + advantage of multiple processors, making it run several times + faster. A new option, THREADS, sets the number of parallel + threads to use, where the default is 1. + +10. A new column was added to the Node Depth Summary report table + that shows the maximum depth recorded at the Reporting Time Step + so it can be compared to the maximum depth attained over all + routing time steps also shown in the table. + +11. Control rule premises can now contain conditions that compare + the values of a node or link variable at two different locations + (e.g. IF NODE 123 HEAD > NODE 456 HEAD) and node volume was + added as a condition clause variable. + +Improvements: +============= + +12. When a subcatchment with LID controls receives runon from another + source (e.g., a subcatchment, LID drain or outfall node) the + runon is now distributed only across the non-LID area of the sub- + catchment instead of the full area. If a single LID takes up the + full subcatchment area then the runon is directed onto the LID. + +13. Storage node HRT was added to the state variables saved in the + Hot Start file. + +14. The threshold value for reporting a non-zero runoff result + was changed from 0.001 cfs to 0.001 inches/hr. + +15. The calculation of overall flow routing mass balance was + modified to account for cases where some flow streams, like + total external inflow, are negative. + +16. The "Surface Runoff" label in the Runoff Continuity Report was + replaced with "Total Runoff" since the value reported consists + of both surface runoff and LID drain flow. + +17. The "Internal Outflow" label in the Flow Routing Continuity + Report was replaced with "Flooding Losses" to improve clarity. + +18. The pollutant washoff routines were moved to a new code module + (surfqual.c) and revised to account for the reduction in + pollutant load that results from runoff flow reduction by LID + units. + +19. Initial flows for Steady Flow routing are now ignored since they + are not used in the routing calculation and the initial volume + associated with them contributed to system mass balance error. + +20. The various types of lateral inflows to conveyance system nodes + are now evaluated at the date/time for the start of the routing + time step instead of at the end of the time step. + +21. The final runoff and routing time steps are adjusted to insure + that the simulation's total duration is not exceeded. + +22. When evaluating user-supplied math expressions, any NaN (Not a + Number) result (caused by an underflow, overflow or divide by zero) + is set to 0 so that the NaN doesn't propagate through subsequent + calculations. + +Bug Fixes: +========== + +23. The evaporation rates read from a time series would only change + when a new day was reached (even though values at more frequent + intervals were present) and could cause a run to stop pre- + maturely in some rare cases. + +24. The runoff read from a Hot Start file should have been assigned + to a subcatchment's newRunoff property, not to oldRunoff. + +25. An indexing bug that caused Hot Start files with snowmelt + parameters to be read incorrectly was fixed. + +26. The setting for a non-conduit link read from a Hot Start file + was not being used to initialize the link. + +27. A bug in adjusting snowmelt for snow covered area derived from + an areal depletion curve was fixed. + +28. Snowmelt should not have been included in the total + precipitation reported for a subcatchment since the snowfall + which produced it was already accounted for. + +29. When computing a flow rate through the Drainage Mat of a Green + Roof LID unit, the mat's void ratio was being applied to the + water depth instead of to the mat's area. + +30. The state of LID controls was not being considered when + choosing to use the wet or dry runoff time step which sometimes + lead to excessive LID continuity errors. + +31. A re-factoring bug that left reporting time in minutes instead + of hours in the detailed LID results file was fixed and results + are now written to the file at each runoff time step where the + state of the LID unit changes. + +32. Failure to initialize groundwater evaporation loss to 0 was + causing problems with the reported groundwater mass balance + for subcatchments that had no pervious area. + +33. Excessive continuity errors for systems having conduits with + large seepage rates was fixed. + +34. Pollutant loss through seepage in conduits and storage nodes was + not being included in the mass balance calculations. + +35. Concentrations in conduits and storage nodes were not being + increased to account for loss of water volume when evaporation + was occurring. + +36. Premature exiting of the routine that checks for capacity limited + links whenever a non-conduit link was encountered was fixed. + +37. A bug in identifying the percent of time that a conduit has either + end full was fixed. + +38. A re-factoring bug that prevented surcharged weirs (see Update 5 + for 5.1.007) from passing any flow was fixed. + +39. A bug in evaluating recursive calls to nodal water quality treatment + functions was fixed. + + +GUI Updates: + +1. The missing July - December column labels were restored on both + the evaporation and wind speed tables in the Climatology Editor. + +2. The label "Surface Water Height (Hsw)" in the Groundwater Flow + Editor was changed to "Surface Water Depth" to make clear that + it is the depth of water at the receiving node and not the height + of water above the aquifer bottom (or Hsw as shown in the dialog's + diagram). + +3. The label "Channel Bottom Height (Hcb)" also in the Groundwater + Flow Editor was changed to "Threshold Water Table Elev." to make + clear that it is an elevation and not a height above the aquifer + bottom (as Hcb is in the dialog's diagram). + +4. A Groundwater Summary table was added to the form that displays + summary results tables. + +5. Groundwater upper zone soil moisture and node lateral inflow are + now included in the abridged Hot Start file that the GUI can + produce (using the File | Export | Hot Start File command). + +6. The column labels in the various sections of the SWMM input file + generated by the GUI were modified to better match the labels used + to describe the input file format in Appendix D of the Users Manual. + +7. A "Route To" field was added to the Outfall Node property editor to + accommodate the new option of allowing outfall nodes to discharge + onto a subcatchment. + +8. The Dynamic Wave page of the Simulation Options dialog was modified + to include the new Minimum Routing Time Step option and the new + Number of Threads option. + +9. The LID Control Editor was updated to include the new Rooftop + Disconnection LID practice and the option to add a soil layer + to the Permeable Pavement practice. + +10. A Drain Outlet field was added to the LID Usage Editor. + +11. The conduit Cross Section Editor dialog was enhanced to display + a selectable list of standard size codes and their dimensions for + elliptical and arch pipes. + +12. Custom changes made to the Map's Legends are now saved with the + rest of a project's settings in its .ini file. + +13. Word wrapping was added to the Title/Notes display in the + Project Browser to make the contents easier to read. + +14. Modal dialog message windows now appear centered over the form that + generates them instead of in the middle of the full display screen. + +15. The style of all dropdown list boxes was changed to make them more + visually appealing. + + +------------------------- +Build 5.1.007 (9/15/2014) +------------------------- + +Engine Updates: + +1. A new feature that provides monthly adjustments for + temperature, evaporation rate, and rainfall was added. + +2. Support for reading the new GHCN-Daily climate data + files available from NCDC's Climate Data Online service + was added. + +3. In addition to lateral groundwater flow, a custom + equation can now also be used for seepage flow to + a deeper groundwater aquifer. + +4. The [GW_FLOW] section of the project file was renamed + to [GWF] and its format was changed to accommodate + both lateral and deep groundwater flow equations. + +5. A new Weir parameter was added that specifies if the + weir can surcharge using an orifice equation or not. + Surcharging was the only option in SWMM 5.0 but was + switched to no surcharing in earlier 5.1 releases. + This new parameter accommodates both closed top weirs + that can surcharge and open channel weirs that cannot. + +6. The formula used to recover infiltration capacity during + dry periods for the Modified Horton method was revised. + +7. The initial cumulative infiltration into the upper soil + zone for Green-Ampt infiltration had been incorrectly + set to the maximum value instead of zero. + +8. All of the Green-Ampt infiltration functions were + re-factored to make the code easier to follow. + +9. The calculation of infiltration out of the bottom of a + Bio-Retention Cell or Permeable Pavement LID unit with a + zero-depth storage layer was corrected. + +10. Most of the LID simulation routines were modified to + provide more accurate results under flooded conditions. + +11. Results written to the detailed LID results report now + always correspond to a full reporting time step. + +12. The name of the variable used to represent the height of + the receiving channel bottom in a user-defined groundwater + flow equation was corrected to match the name displayed + in the GUI's Groundwater Editor dialog (Hcb). + +13. A problem with the program crashing when a climate file + was used to provide evaporation rates for open channels + and storage nodes when runoff was not computed (as when + there were no subcatchments in the project) was fixed. + +14. Flow and pollutant routing mass balance accounting was + modified to correctly handle negative external inflows. + +15. The procedure for computing the area available for seepage + out of a storage node that has a tabular storage curve was + corrected. + +16. Seepage from storage units can now be modeled using Green- + Ampt infiltration, which makes the seepage rate a function + of storage level. The constant seepage rate option can + still be used by setting the G-A initial moisture deficit + to 0. + +17. The function that finds depth as a function of volume from + a storage curve was corrected for the case where the depth + falls within a portion of the curve where area is constant + with depth (i.e., vertical side walls). + +GUI Updates: + +1. The Object Toolbar was restored. + +2. A new page was added to the Climatology Editor to edit + values for monthly adjustments for temperature, evaporation, + and rainfall. + +3. A field for the new weir surcharge option was added to the + Weir Property editor. + +4. A problem with the current project being closed without + asking if it should be saved first whenever a new style + theme was selected from the Program Preferences dialog + has been fixed. + +5. The default seepage rate from an LID storage layer was changed. + +6. The Infiltration Editor was restored for editing Green-Ampt + parameters for storage unit seepage loss. + +7. The Groundwater Flow Equation Editor was extended to accept + equations for deep groundwater flow. + + +------------------------- +Build 5.1.006 (5/19/2014) +------------------------- + +Engine Updates: + +1. The updating of the next time that detailed LID results + should be written to file during a simulation was modified + to avoid an off-by-one error. + +2. The number of decimal places for hourly evaporation written + to a detailed LID report was increased. + +3. The amount of soil water available for evaporation in + LID units with soil layers wasn't being limited by the + water remaining below the wilting point. + +4. The equation that computes the rate of water infiltrating + into permeable pavement LIDs had a misplaced parenthesis. + +5. There was a units conversion error in computing the + contribution of a pollutant in direct precipitation + to the water quality on a subcatchment. + +GUI Updates: + +1. As a result of the switch to Delphi XE2 some components on + the Options and Climatology dialogs were not recording that + project data had changed after edits were made. + + +------------------------- +Build 5.1.005 (4/23/2014) +------------------------- + +Engine Updates: + +1. A problem with reading hydraulic results from a hot start + file was fixed. + +GUI Updates: + +1. The appearance of the Open File Dialog with preview panel + was improved. + +2. In the property Editor for storage nodes, the Ponded Area + property was made read-only since storage nodes are not + allowed to pond water. + +3. Some issues with pop-up topic windows in the Help file + being obscured by the main Help window were fixed. + + +------------------------- +Build 5.1.004 (4/14/2014) +------------------------- + +Engine Updates: + +1. Support for the Ignore RDII analysis option was added to + the engine. + +GUI Updates: + +1. A refactoring bug that ignored any changes to numerical + precision made in the Program Preferences dialog was fixed. + +2. Another refactoring bug from 5.1.003 that caused projects + with groundwater aquifers not to run was fixed. + + +------------------------ +Build 5.1.003 (4/8/2014) +------------------------ +Engine Updates: + +1. A new property, the Upper Zone Evap. Pattern, was added to + the Aquifer object. It allows one to adjust the aquifer's + upper zone evaporation fraction by month of the year. + +2. A bug in writing/reading RDII flows to the new binary RDII + file was fixed. + +GUI Updates: + +1. A refactoring bug that prevented SWMM from working + correctly for users with non-US Windows regional settings + was fixed. + +2. A refactoring bug the prevented the Group Delete feature from + working was fixed. + +4. Issues with stay-on-top forms obscuring modal dialog forms, + with the Browser panel disappearing if its width was made too + small and with not being able to browse the Help system when a + modal form had focus were fixed (these unforseen issues were + caused by the switch to Delphi XE2 from Delphi 7). + +5. The Aquifer Editor form was updated to accept the new upper + evaporation pattern property. + + +------------------------- +Build 5.1.002 (3/31/2014) +------------------------- +Engine Updates: + +1. A bug that prevented hotstart files with the latest format + from being read was fixed. + +2. Only non-ponded surface area is saved for use in the dynamic + wave surcharge algorithm (when water depth is close to the + node's crown elevation). + +GUI Updates: + +1. Creation of auxilary forms on startup was moved from the + main form's OnActivate event to its OnCreate event, while + creation of the map form was moved tothe OnShow event. + +2. The routines for saving and reading the main form's position + and size in the swmm5 .ini file were modified. + +3. A memory leak related to copying cells from the grid editor + used in various dialogs was fixed. + + +------------------------- +Build 5.1.001 (3/24/2014) +------------------------- +Engine Updates + +New Features: +============= +1. SWMM can now read the new file format for precipitation + data retrieved online from NOAA-NCDC. + +2. A new choice of infiltration method, the Modified Horton + method, has been added. This method uses the cumulative + infiltration in excess of the minimum rate as its state + variable (instead of time along the Horton curve), + providing a more accurate infiltration estimate when + low rainfall intensities occur. + +3. RDII interface files created internally by SWMM are now + saved in a binary format to reduce storage space. The ASCII + text format for these files is still supported for users + that find it desireable to create the files outside of SWMM. + +4. Two new categories of LID controls, one for Green Roofs and + another for Rain Gardens, have been added so they no longer + have to be configured from the Bio-Retention Cell control + (although that option still remains). The Green Roof uses + a new Drainage Mat layer to store and convey the water that + percolates through the soil layer. + +5. Users can now add their own groundwater outflow equation to + a subcatchment, to be used in place of or in addition to the + standard equation. Similar to treatment functions, the equation + can be any mathematical expression that uses the same ground- + water variables that appear in the standard equation. + +6. Evaporation of water from open channels has been added. + +7. A new conduit property named Seepage Rate (in/hr or mm/hr) + has been added to model uniform seepage along the bottom + and sloped sides of a conduit. + +8. Infiltration from storage units is now referred to as + seepage, to be consistent with seepage from conduits. The + only required parameter is a seepage rate (in/hr or mm/hr). + Previous data files that supply a set of Green-Ampt + infiltration parameters will still be recognized. + +9. Separate accounting and reporting of evaporation and + seepage losses in storage units is now made. + +10. Open rectangular channels now have a new parameter that + specifies if one or both side wall surfaces should be + ignored when computing a hydraulic radius (to provide + improved support for quasi-2D modeling of wide channels + and overland flooding). + +11. New Dynamic Wave Analysis options have been added for + the maximum number of iterations and head tolerance used + at each time step. The percentage of time steps where + convergence is not achieved is also now reported. + +12. Users can now set the flow tolerances that determine if + flow routing calculations can be skipped because steady + state conditions hold. + +13. Control rules can now use a conduit's OPEN/CLOSED status + in both premise conditions and action clauses. + +14. The meaning of the link view variable "Capacity" has been + changed. For conduits it is now the fraction of the full + cross section area filled by the flow, while it is the + control setting for all other types of links (the meaning + of the control setting varies by link type -- see the Help + file or the Users Manual). + +15. The link Froude number view variable has been replaced with + the link's flow volume, the subcatchment Losses variable has + been replaced by two new variables - Evaporation and + Infiltration, and upper groundwater zone Soil Moisture has + been added as a new view variable. + +16. The Node Inflows Summary table of the Status Report now + includes a new column that lists the mass balance error + in volume units for each node. + +17. A new summary table, Link Pollutant Load, has been added + that displays the total mass load of each pollutant that + flows through each link. + +Improvements: +============= +18. Using a Drain Delay time of 0 for Rain Barrel LIDs now means + that the barrel is allowed to drain continuously, even as it + is filling during wet weather periods. + +19. The requirement that an impervious surface must be dry + (have no more than 0.05 inches of standing water) before + it could be subjected to street sweeping has been dropped. + +20. After runoff ceases and a land surface goes dry due to + evaporation, any remaining mass of pollutant originating + from direct deposition or upstream runon is assumed to be + unavailabe for future washoff (it shows up as Remaining + Buildup in the mass balance report). + +21. The way that wet weather washoff inflow loads are + interpolated across a flow routing time step was modified + to produce a better match between the reported total runoff + load and total quality routing inflow load. + +22. The method used to select a time step for processing RDII + unit hydrographs was modified to consider the case where + K (the ratio of rising limb to falling limb duration) is + below 1.0. + +23. When the moisture content of the upper groundwater zone + reaches saturation, the depth of the lower saturated zone + is now set equal to the full aquifer depth (minus a small + tolerance). + +24. Conduits with negative slopes whose absolute value is + below the Minimum Slope option will have their slope + changed to the positive minimum value, thus allowing + them to be analyzed using the Steady Flow and Kinematic + Wave routing options. + +25. The Avg. Froude Number and Avg. Flow Change columns in the + Flow Classification Summary table have been replaced with the + fraction of time steps that flow is limited to normal flow + and the fraction of time steps that flow is inlet controlled + (for culverts). + +26. An error condition now occurs if a pump's startup depth + is less than its shutoff depth. + +27. Only the upstream node for orifice and weir links is now + checked to see if its maximum depth needs to be increased + to meet the top elevation of the orifice or weir opening. + +28. Weirs are no longer allowed to operate as an orifice when + they surcharge. Instead any excess flow will flood the + upstream node. + +29. A warning message is now written to the Status Report if + the crest elevation of a regulator link is below its + downstream node's invert. + +30. When a reporting time falls in between a computational time + step during which a pump's on/off status changes, the reported + pump flow is the value at either the start or end of the time + step depending on which is closer to the reporting time (i.e., + no interpolation is used). + +31. Control rule conditions can now accept elapsed time or + time of day values as decimal hours in addition to hours: + minutes:seconds. + +32. The test for a control rule condition equaling a specified + elapsed time or time of day was modified to more accurately + capture its occurrence. + +33. If the Water Quality analysis option is disabled then the + binary results file no longer contains any pollutant values + (of 0) for all time periods. + +34. Hot Start files now contain the complete state of the watershed + and conveyance system, so that future simulations can start up + correctly where they left off. + +35. The following changes to error reporting were made: + - Error 319 was re-numbered to 320 and a new Error 319 + was added for a rainfall data file with unknown format. + - Format errors in external time series files are now + listed as Error 363 (invalid data) instead of Error + 173 (time series out of sequence). + +36. Warning messages written to the Status Report are now + single spaced instead of double spaced. See report.c. + +37. The Link Summary table in the Status Report now lists conduits + with negative slopes in their original orientation instead of + in their reversed state. + +Bug Fixes: +========== +38. A refactoring bug from 5.0.022 that prevented snowmelt + from infiltrating has been fixed. + +39. Snowmelt rate during rainfall conditions and the updating + of the antecedent temperature index were were not being + converted from the six hour time interval used in Anderson's + original NWS snowmelt model to the hourly basis used in SWMM. + +40. A refactoring bug that failed to set the maximum number of + characters high enough for a line read from a user-prepared + rainfall data file has been fixed. + +41. The optional Maximum Volume parameter for Horton + infiltration was not allowing any recovery of infiltration + capacity between storm events. + +42. Evaporation from the lower groundwater zone was being + computed from the rate remaining after surface and upper + zone evaporation was considered instead of from the + unadjusted rate (with a reduction afterwards if it exceeds + the remaining available rate). + +43. An error in applying the Vegetation Volume Fraction parameter + to swales was corrected. + +44. The time from the last rainfall used to determine when a + Rain Barrel should begin to empty wasn't being computed + correctly. + +45. An erroneous error message for Rain Barrel LIDs with a + zero Void Ratio has been fixed (the Void Ratio parameter + should be ignored for Rain Barrels). + +46. The display of extraneous infiltration results in detailed + reports for Rain Barrel LIDs has been eliminated. + +47. The check on no street sweeping for a subcatchment during + wet periods was checking rainfall over the entire study + area instead of just the subcatchment. + +48. An erroneous warning message regarding negative offsets for + pumps when elevation offsets are used has been eliminated. + +49. A possible divide by zero error for trapezoidal channels + with zero bottom width has been eliminated. + +50. A program crash that occurred when the Ignore Routing + option was selected and results were to be saved to a + Routing Interface file has been fixed. + +51. Projects that had no subcatchments or had the Ignore + Runoff switch selected were not able to evaporate water + from storage units. + +52. Weekday and weekend hourly time patterns for Dry Weather + inflows are now correctly applied in a mutually exclusive + manner. + +53. The Node Flooding Summary table in the Status Report now + correctly lists the peak depth of ponded water above the + node's maximum depth (i.e., its rim or ground elevation) + instead of above its invert elevation. + +54. Occasional problems caused by the date/time functions not + returning an hour between 0 and 23 (for hourly time patterns) + and being off by 1 second (when writing results to outflow + interface files) have been fixed. + +55. A bug introduced in release 5.0.017 that caused the + concentration after first-order decay in a storage node to + be ignored has been fixed. + +56. A bug in the Total Elapsed Time listed at the end of the + Status Report for runs taking longer than 24 hours of + computer time was fixed. + +57. A correction was made for the slope correction factor used + for mitered culvert inlets. + +58. The procedure for finding the surface area of a storage unit + given its volume was corrected for the case where the + storage curve has a section of decreasing area with depth. + +59. The procedure for finding a cross-section area given a + section factor value was corrected for the case where the + section factor table does not have its highest value as + the last entry in the table. + +60. An error in computing the hydraulic radius of the Rectangular- + Triangular conduit shape as a function of flow depth was + corrected. + +GUI Updates + +1. The entire GUI code was ported from Delphi 7 into Delphi XE2. + +2. Different color themes for the user interface can be + selected from the Program Preferences dialog. + +3. The "Data" Browser panel is now named as the "Project" + Browser. + +4. The Object Toolbar has been eliminated. Visual objects + are now added to the map in the same manner as non-visual + objects -- by selecting their category from the Project + Browser and then clicking the Browser's "+" button (or + by selecting Project | Add... on the main menu). + +5. The LID Control and LID Usage editors were re-designed to + accomodate the new LID control options. + +6. Modifications were made to accept the new engine features + mentioned above (modified Horton infiltration, seepage rate + parameter for conduits, side wall option for rectangular + channels, and the additional Dynamic Wave routing options). + +7. Modifications were made to accept the updated set of output + view variables. + +8. The summary results tables that used to appear as part of the + Status Report have been moved into a separate Summary Report + that makes it easier to view and sort them. + +9. The Time Series Plot selection dialog was modified to allow + more than one kind of object/variable pair to be plotted. + +10. The Graph Options dialog was modified to allow a vertical + axis to be inverted (as when plotting an inverted rainfall + hyetograph on the same graph as a runoff hydrograph). + +11. The option to compute evaporation using the Hargreaves + equation wasn't being saved along with the rest of a project. + +12. If pollutants are defined for a project but the Water Quality + analysis option is not selected, then after a new analysis is + made pollutants will no longer be listed as theme variables in + the Map Browser nor will they be available for graphs, tables + or statistical reports. + +13. The columns for the [XSECTIONS] section of a saved project + file now includes a heading label for "Culvert Code". diff --git a/extern/boost.cmake b/extern/boost.cmake new file mode 100644 index 000000000..4f9c10aaa --- /dev/null +++ b/extern/boost.cmake @@ -0,0 +1,35 @@ +# +# CMakeLists.txt - CMake configuration file for swmm-solver/extern +# +# Created: March 16, 2020 +# Updated: May 21, 2020 +# +# Author: Michael E. Tryby +# US EPA - ORD/CESER +# + + +if(WIN32) + set(Boost_USE_STATIC_LIBS ON) +else() + set(Boost_USE_STATIC_LIBS OFF) + add_definitions(-DBOOST_ALL_DYN_LINK) +endif() + + +# Environment variable "BOOST_ROOT_X_XX_X" points to local install location +if (DEFINED ENV{BOOST_ROOT_1_72_0}) + set(BOOST_ROOT $ENV{BOOST_ROOT_1_72_0}) + +elseif(DEFINED ENV{BOOST_ROOT_1_67_0}) + set(BOOST_ROOT $ENV{BOOST_ROOT_1_67_0}) + +endif() + + +find_package(Boost 1.67.0 + COMPONENTS + unit_test_framework + ) + +include_directories (${Boost_INCLUDE_DIRS}) diff --git a/src/outfile/CMakeLists.txt b/src/outfile/CMakeLists.txt index 5c5d2ed96..288c5d36d 100644 --- a/src/outfile/CMakeLists.txt +++ b/src/outfile/CMakeLists.txt @@ -48,6 +48,15 @@ install(TARGETS swmm-output EXPORT swmm-outputTargets FRAMEWORK DESTINATION "${TOOL_DIST}" ) +install( + EXPORT + swmm-outputTargets + DESTINATION + "${CONFIG_DIST}" + FILE + swmm-output-config.cmake + ) + install(FILES ${SWMM_OUT_PUBLIC_HEADERS} DESTINATION "${INCLUDE_DIST}") diff --git a/src/outfile/swmm_output.c b/src/outfile/swmm_output.c index dae5dc8fb..84ae6594c 100644 --- a/src/outfile/swmm_output.c +++ b/src/outfile/swmm_output.c @@ -10,6 +10,8 @@ */ +#define _CRT_SECURE_NO_DEPRECATE + #include #include #include @@ -670,7 +672,7 @@ int EXPORT_OUT_API SMO_getSystemSeries(SMO_Handle p_handle, SMO_systemAttribute errorcode = 411; else { // loop over and build time series - for (k = 0; k < length; k++) + for (k = 0; k < len; k++) temp[k] = getSystemValue(p_data, startPeriod + k, attr); *outValueArray = temp; diff --git a/src/run/main.c b/src/run/main.c index b4af1f112..0d050cf69 100644 --- a/src/run/main.c +++ b/src/run/main.c @@ -10,7 +10,9 @@ // to be run with swmm5.dll. #include +#include #include + #include "swmm5.h" int main(int argc, char *argv[]) @@ -35,7 +37,7 @@ int main(int argc, char *argv[]) int msgLen = 127; time_t start; double runTime; - + version = swmm_getVersion(); vMajor = version / 10000; vMinor = (version - 10000 * vMajor) / 1000; @@ -94,10 +96,10 @@ int main(int argc, char *argv[]) } // --- Use the code below if you need to keep the console window visible -/* +/* printf(" Press Enter to continue..."); getchar(); */ return 0; -} \ No newline at end of file +} diff --git a/src/solver/CMakeLists.txt b/src/solver/CMakeLists.txt index f109b5f49..428deb891 100644 --- a/src/solver/CMakeLists.txt +++ b/src/solver/CMakeLists.txt @@ -31,7 +31,7 @@ if(BUILD_DEF) add_library(swmm5 SHARED ${SWMM_SOURCES} - ${PROJECT_SOURCE_DIR/bindings/swmm5.def} + ${PROJECT_SOURCE_DIR}/bindings/swmm5.def ) else() @@ -78,6 +78,16 @@ install(TARGETS swmm5 EXPORT swmm5Targets FRAMEWORK DESTINATION "${TOOL_DIST}" ) +# Create target import scripts so other cmake projects can use swmm libraries +install( + EXPORT + swmm5Targets + DESTINATION + "${CONFIG_DIST}" + FILE + swmm5-config.cmake + ) + install(FILES ${SWMM_PUBLIC_HEADERS} DESTINATION "${INCLUDE_DIST}") diff --git a/src/solver/consts.h b/src/solver/consts.h index 4421dd1eb..829b089fd 100644 --- a/src/solver/consts.h +++ b/src/solver/consts.h @@ -7,16 +7,21 @@ // 08/01/16 (Build 5.1.011) // 05/10/18 (Build 5.1.013) // 03/01/20 (Build 5.1.014) +// 04/01/20 (Build 5.1.015) // Author: L. Rossman // // Various Constants //----------------------------------------------------------------------------- +#ifndef CONSTS_H +#define CONSTS_H + + //------------------ // General Constants //------------------ -#define VERSION 51014 +#define VERSION 51015 #define MAGICNUMBER 516114522 #define EOFMARK 0x1A // Use 0x04 for UNIX systems #define MAXTITLE 3 // Max. # title lines @@ -93,5 +98,8 @@ //--------------------------- // Token separator characters -//--------------------------- -#define SEPSTR " \t\n\r" +//--------------------------- +#define SEPSTR " \t\n\r" + + +#endif //CONSTS_H diff --git a/src/solver/datetime.h b/src/solver/datetime.h index 397f3180c..8c84b3b79 100644 --- a/src/solver/datetime.h +++ b/src/solver/datetime.h @@ -18,6 +18,10 @@ // - New getTimeStamp function added. //----------------------------------------------------------------------------- +#ifndef DATETIME_H +#define DATETIME_H + + typedef double DateTime; #define Y_M_D 0 @@ -61,3 +65,6 @@ void datetime_setDateFormat(int fmt); DateTime datetime_addSeconds(DateTime date1, double seconds); DateTime datetime_addDays(DateTime date1, DateTime date2); long datetime_timeDiff(DateTime date1, DateTime date2); + + +#endif //DATETIME_H diff --git a/src/solver/dynwave.c b/src/solver/dynwave.c index 294adc873..8c901057e 100644 --- a/src/solver/dynwave.c +++ b/src/solver/dynwave.c @@ -9,6 +9,8 @@ // 03/19/15 (5.1.008) // 08/01/16 (5.1.011) // 05/10/18 (5.1.013) +// 03/01/20 (5.1.014) +// 07/10/20 (5.1.015) // Author: L. Rossman (EPA) // M. Tryby (EPA) // R. Dickinson (CDM) @@ -49,6 +51,9 @@ // - updateNodeFlows() modified to subtract conduit evap. and seepage losses // from downstream node inflow instead of upstream node outflow. // +// Build 5.1.015: +// - Roll back the 5.1.014 change for conduit losses in updateNodeFlows(). +// //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -403,7 +408,7 @@ void findLinkFlows(double dt) for ( i = 0; i < Nobjects[LINK]; i++) { if ( !isTrueConduit(i) ) - { + { if ( !Link[i].bypassed ) findNonConduitFlow(i, dt); updateNodeFlows(i); } @@ -551,13 +556,13 @@ void updateNodeFlows(int i) // --- update total inflow & outflow at upstream/downstream nodes if ( q >= 0.0 ) { - Node[n1].outflow += q; //(5.1.014) - Node[n2].inflow += q - uniformLossRate; //(5.1.014) + Node[n1].outflow += q + uniformLossRate; //(5.1.015) + Node[n2].inflow += q; //(5.1.015) } else { - Node[n1].inflow -= q + uniformLossRate; //(5.1.014) - Node[n2].outflow -= q; //(5.1.014) + Node[n1].inflow -= q; //(5.1.015) + Node[n2].outflow -= q - uniformLossRate; //(5.1.015) } // --- add surf. area contributions to upstream/downstream nodes diff --git a/src/solver/enums.h b/src/solver/enums.h index e76f27519..4bc50e3f8 100644 --- a/src/solver/enums.h +++ b/src/solver/enums.h @@ -35,10 +35,14 @@ // // Build 5.1.013: // - SURCHARGE_METHOD and RULE_STEP options added. -// - WEIR_CURVE added as a curve type. +// - WEIR_CURVE added as a curve type. // //----------------------------------------------------------------------------- +#ifndef ENUMS_H +#define ENUMS_H + + //------------------------------------- // Names of major object types //------------------------------------- @@ -113,18 +117,18 @@ // Cross section shape types //------------------------------------- enum XsectType { - DUMMY, // 0 + DUMMY, // 0 CIRCULAR, // 1 closed FILLED_CIRCULAR, // 2 closed RECT_CLOSED, // 3 closed - RECT_OPEN, // 4 - TRAPEZOIDAL, // 5 - TRIANGULAR, // 6 + RECT_OPEN, // 4 + TRAPEZOIDAL, // 5 + TRIANGULAR, // 6 PARABOLIC, // 7 - POWERFUNC, // 8 - RECT_TRIANG, // 9 + POWERFUNC, // 8 + RECT_TRIANG, // 9 RECT_ROUND, // 10 - MOD_BASKET, // 11 + MOD_BASKET, // 11 HORIZ_ELLIPSE, // 12 closed VERT_ELLIPSE, // 13 closed ARCH, // 14 closed @@ -193,7 +197,7 @@ //------------------------------------- // Computed node quantities //------------------------------------- - #define MAX_NODE_RESULTS 7 + #define MAX_NODE_RESULTS 7 enum NodeResultType { NODE_DEPTH, // water depth above invert NODE_HEAD, // hydraulic head @@ -410,7 +414,7 @@ enum CompatibilityType { enum PumpCurveType { TYPE1_PUMP, // flow varies stepwise with wet well volume - TYPE2_PUMP, // flow varies stepwise with inlet depth + TYPE2_PUMP, // flow varies stepwise with inlet depth TYPE3_PUMP, // flow varies with head delivered TYPE4_PUMP, // flow varies with inlet depth IDEAL_PUMP}; // outflow equals inflow @@ -479,3 +483,6 @@ enum NoneAllType { NONE, ALL, SOME}; + + +#endif //ENUMS_H diff --git a/src/solver/error.c b/src/solver/error.c index 843823878..17c0a0ed5 100644 --- a/src/solver/error.c +++ b/src/solver/error.c @@ -6,6 +6,7 @@ // Date: 03/20/14 (Build 5.1.001) // 03/19/15 (Build 5.1.008) // 08/05/15 (Build 5.1.010) +// 04/14/20 (Build 5.1.015) // Author: L. Rossman // // Error messages @@ -16,6 +17,8 @@ // Build 5.1.010: // - Text of Error 318 for rainfall data files modified. // +// Build 5.1.015: +// - Added new Error 140 for storage nodes. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -55,6 +58,8 @@ #define ERR138 \ "\n ERROR 138: Node %s has initial depth greater than maximum depth." #define ERR139 "\n ERROR 139: Regulator %s is the outlet of a non-storage node." +#define ERR140 \ +"\n ERROR 140: Storage node %s has negative volume at full depth." //(5.1.015) #define ERR141 \ "\n ERROR 141: Outfall %s has more than 1 inlet link or an outlet link." #define ERR143 "\n ERROR 143: Regulator %s has invalid cross-section shape." @@ -197,7 +202,7 @@ char* ErrorMsgs[] = ERR327, ERR329, ERR330, ERR331, ERR333, ERR335, ERR336, ERR337, ERR338, ERR339, ERR341, ERR343, ERR345, ERR351, ERR353, ERR355, ERR357, ERR361, ERR363, ERR401, ERR402, ERR403, ERR405, ERR501, ERR502, ERR503, ERR504, - ERR505, ERR506, ERR507, ERR508, ERR509}; + ERR505, ERR506, ERR507, ERR508, ERR509, ERR140}; //(5.1.015) int ErrorCodes[] = { 0, 101, 103, 105, 107, 108, 109, 110, 111, @@ -212,7 +217,7 @@ int ErrorCodes[] = 327, 329, 330, 331, 333, 335, 336, 337, 338, 339, 341, 343, 345, 351, 353, 355, 357, 361, 363, 401, 402, 403, 405, 501, 502, 503, 504, - 505, 506, 507, 508, 509}; + 505, 506, 507, 508, 509, 140}; //(5.1.015) char ErrString[256]; diff --git a/src/solver/error.h b/src/solver/error.h index 7ffef1b7e..20737960c 100644 --- a/src/solver/error.h +++ b/src/solver/error.h @@ -4,12 +4,17 @@ // Project: EPA SWMM5 // Version: 5.1 // Date: 03/20/14 (Build 5.1.001) +// 04/14/20 (Build 5.1.015) // Author: L. Rossman // // Error codes // //----------------------------------------------------------------------------- +#ifndef ERROR_H +#define ERROR_H + + enum ErrorType { //... Runtime Errors @@ -116,7 +121,7 @@ enum ErrorType { ERR_RAIN_FILE_SCRATCH, //313 72 ERR_RAIN_FILE_OPEN, //315 73 ERR_RAIN_FILE_DATA, //317 74 - ERR_RAIN_FILE_SEQUENCE, //318 75 + ERR_RAIN_FILE_SEQUENCE, //318 75 ERR_RAIN_FILE_FORMAT, //319 76 ERR_RAIN_IFACE_FORMAT, //320 77 ERR_RAIN_FILE_GAGE, //321 78 @@ -143,7 +148,7 @@ enum ErrorType { ERR_RDII_FILE_SCRATCH, //341 91 ERR_RDII_FILE_OPEN, //343 92 ERR_RDII_FILE_FORMAT, //345 93 - + //... Routing File Errors ERR_ROUTING_FILE_OPEN, //351 94 ERR_ROUTING_FILE_FORMAT, //353 95 @@ -165,13 +170,19 @@ enum ErrorType { ERR_API_INPUTNOTOPEN, //502 105 ERR_API_SIM_NRUNNING, //503 106 ERR_API_WRONG_TYPE, //504 107 - ERR_API_OBJECT_INDEX, //505 108 + ERR_API_OBJECT_INDEX, //505 108 ERR_API_POLLUT_INDEX, //506 109 ERR_API_INFLOWTYPE, //507 110 ERR_API_TSERIES_INDEX, //508 111 ERR_API_PATTERN_INDEX, //509 112 + + //... Additional Errors + ERR_STORAGE_VOLUME, //140 113 //(5.1.015) MAXERRMSG}; - + char* error_getMsg(int i); int error_getCode(int i); int error_setInpError(int errcode, char* s); + + +#endif //ERROR_H diff --git a/src/solver/exfil.h b/src/solver/exfil.h index 6958735cc..8315c08c4 100644 --- a/src/solver/exfil.h +++ b/src/solver/exfil.h @@ -12,6 +12,7 @@ #ifndef EXFIL_H #define EXFIL_H + //---------------------------- // EXFILTRATION OBJECT //---------------------------- @@ -32,4 +33,5 @@ int exfil_readStorageParams(int k, char* tok[], int ntoks, int n); void exfil_initState(int k); double exfil_getLoss(TExfil* exfil, double tStep, double depth, double area); -#endif + +#endif //EXFIL_H diff --git a/src/solver/findroot.h b/src/solver/findroot.h index 253a4ba4e..c0ae10dff 100644 --- a/src/solver/findroot.h +++ b/src/solver/findroot.h @@ -5,8 +5,16 @@ // // Last modified on 11/19/13. //----------------------------------------------------------------------------- + +#ifndef FINDROOT_H +#define FINDROOT_H + + int findroot_Newton(double x1, double x2, double* rts, double xacc, void (*func) (double x, double* f, double* df, void* p), void* p); double findroot_Ridder(double x1, double x2, double xacc, double (*func)(double, void* p), void* p); + + +#endif //FINDROOT_H diff --git a/src/solver/flowrout.c b/src/solver/flowrout.c index b50b12787..675e39300 100644 --- a/src/solver/flowrout.c +++ b/src/solver/flowrout.c @@ -640,9 +640,9 @@ void setNewNodeState(int j, double dt) // --- update terminal storage nodes if ( Node[j].type == STORAGE ) - { - if ( Node[j].updated == FALSE ) - updateStorageState(j, Nobjects[LINK], NULL, dt); + { + if ( Node[j].updated == FALSE ) + updateStorageState(j, Nobjects[LINK], NULL, dt); return; } diff --git a/src/solver/funcs.h b/src/solver/funcs.h index bdc2a4fe0..b9da07048 100644 --- a/src/solver/funcs.h +++ b/src/solver/funcs.h @@ -32,6 +32,11 @@ // - Arguments to link_getLossRate function changed. // //----------------------------------------------------------------------------- + +#ifndef FUNCS_H +#define FUNCS_H + + void project_open(char *f1, char *f2, char *f3); void project_close(void); @@ -86,7 +91,7 @@ void report_writeSysStats(TSysStats* sysStats); void report_writeErrorMsg(int code, char* msg); void report_writeErrorCode(void); void report_writeInputErrorMsg(int k, int sect, char* line, long lineCount); -void report_writeWarningMsg(char* msg, char* id); +void report_writeWarningMsg(char* msg, char* id); void report_writeTseriesErrorMsg(int code, TTable *tseries); void inputrpt_writeInput(void); @@ -275,7 +280,7 @@ void stats_report(void); void stats_updateCriticalTimeCount(int node, int link); void stats_updateFlowStats(double tStep, DateTime aDate, int stepCount, int steadyState); -void stats_updateSubcatchStats(int subcatch, double rainVol, +void stats_updateSubcatchStats(int subcatch, double rainVol, double runonVol, double evapVol, double infilVol, double impervVol, double pervVol, double runoffVol, double runoff); //(5.1.013) void stats_updateGwaterStats(int j, double infil, double evap, @@ -356,12 +361,12 @@ void node_getResults(int node, double wt, float x[]); int inflow_readExtInflow(char* tok[], int ntoks); int inflow_readDwfInflow(char* tok[], int ntoks); int inflow_readDwfPattern(char* tok[], int ntoks); -int inflow_setExtInflow(int j, int param, int type, - int tSeries, int basePat, double cf, +int inflow_setExtInflow(int j, int param, int type, + int tSeries, int basePat, double cf, double baseline, double sf); -int inflow_validate(int param, int type, int tSeries, - int basePat, double *cf); - +int inflow_validate(int param, int type, int tSeries, + int basePat, double *cf); + void inflow_initDwfInflow(TDwfInflow* inflow); void inflow_initDwfPattern(int pattern); @@ -471,7 +476,7 @@ int shape_validate(TShape *shape, TTable *curve); int controls_create(int n); void controls_delete(void); int controls_addRuleClause(int rule, int keyword, char* Tok[], int nTokens); -int controls_evaluate(DateTime currentTime, DateTime elapsedTime, +int controls_evaluate(DateTime currentTime, DateTime elapsedTime, double tStep); //----------------------------------------------------------------------------- @@ -518,3 +523,6 @@ void writecon(char *s); // writes string to console DateTime getDateTime(double elapsedMsec); // convert elapsed time to date void getElapsedTime(DateTime aDate, // convert elapsed date int* days, int* hrs, int* mins); + + +#endif //FUNCS_H diff --git a/src/solver/globals.h b/src/solver/globals.h index 1d7c9207e..400f35b9b 100644 --- a/src/solver/globals.h +++ b/src/solver/globals.h @@ -10,6 +10,7 @@ // 08/01/16 (Build 5.1.011) // 03/14/17 (Build 5.1.012) // 05/10/18 (Build 5.1.013) +// 04/01/20 (Build 5.1.015) // Author: L. Rossman // // Global Variables @@ -26,7 +27,7 @@ // // Build 5.1.011: // - Changed WarningCode to Warnings (# warnings issued) -// - Added error message text as a variable. +// - Added error message text as a variable. // - Added elapsed simulation time (in decimal days) variable. // - Added variables associated with detailed routing events. // @@ -35,8 +36,15 @@ // // Build 5.1.013: // - CrownCutoff and RuleStep added as analysis option variables. +// +// Build 5.1.015: +// - Fixes bug in summary statistics when Report Start date > Start Date. //----------------------------------------------------------------------------- +#ifndef GLOBALS_H +#define GLOBALS_H + + EXTERN TFile Finp, // Input file Fout, // Output file @@ -52,7 +60,8 @@ EXTERN TFile EXTERN long Nperiods, // Number of reporting periods - StepCount, // Number of routing steps used + TotalStepCount, // Total routing steps used //(5.1.015) + ReportStepCount, // Reporting routing steps used //(5.1.015) NonConvergeCount; // Number of non-converging steps EXTERN char @@ -166,3 +175,6 @@ EXTERN TTable* Tseries; // Array of time series tables EXTERN TTransect* Transect; // Array of transect data EXTERN TShape* Shape; // Array of custom conduit shapes EXTERN TEvent* Event; // Array of routing events + + +#endif //GLOBALS_H diff --git a/src/solver/hash.h b/src/solver/hash.h index 26f1684fa..90ac1ca22 100644 --- a/src/solver/hash.h +++ b/src/solver/hash.h @@ -4,6 +4,10 @@ // Header file for Hash Table module hash.c. //----------------------------------------------------------------------------- +#ifndef HASH_H +#define HASH_H + + #define HTMAXSIZE 1999 #define NOTFOUND -1 @@ -21,3 +25,6 @@ int HTinsert(HTtable *, char *, int); int HTfind(HTtable *, char *); char *HTfindKey(HTtable *, char *); void HTfree(HTtable *); + + +#endif //HASH_H diff --git a/src/solver/headers.h b/src/solver/headers.h index 5f76a8a6e..eafda8a2c 100644 --- a/src/solver/headers.h +++ b/src/solver/headers.h @@ -10,6 +10,7 @@ // // DO NOT CHANGE THE ORDER OF THE #INCLUDE STATEMENTS //----------------------------------------------------------------------------- + #include #include "consts.h" #include "macros.h" diff --git a/src/solver/hotstart.c b/src/solver/hotstart.c index be81670bd..33c005e45 100644 --- a/src/solver/hotstart.c +++ b/src/solver/hotstart.c @@ -8,6 +8,7 @@ // 04/23/14 (Build 5.1.005) // 03/19/15 (Build 5.1.008) // 08/01/16 (Build 5.1.011) +// 04/01/20 (Build 5.1.015) // Author: L. Rossman (EPA) // // Hot Start file functions. @@ -37,6 +38,8 @@ // Build 5.1.011: // - Link control setting bug when reading a hot start file fixed. // +// Build 5.1.015: +// - Support added for multiple infiltration methods within a project. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -378,7 +381,7 @@ void saveRunoff(void) // Infiltration state (max. of 6 elements) for (j=0; j= 0 ) + { + m = i; + --ntoks; + } + // --- number of input tokens depends on infiltration model m - if ( m == HORTON ) n = 5; + if ( m == HORTON ) n = 5; else if ( m == MOD_HORTON ) n = 5; else if ( m == GREEN_AMPT ) n = 4; else if ( m == MOD_GREEN_AMPT ) n = 4; else if ( m == CURVE_NUMBER ) n = 4; - else return 0; - if ( ntoks < n ) return error_setInpError(ERR_ITEMS, ""); + else return 0; + if ( ntoks < n ) return error_setInpError(ERR_ITEMS, ""); + // --- parse numerical values from tokens for (i = 0; i < 5; i++) x[i] = 0.0; for (i = 1; i < n; i++) { - if ( ! getDouble(tok[i], &x[i-1]) ) + if (!getDouble(tok[i], &x[i - 1])) return error_setInpError(ERR_NUMBER, tok[i]); } @@ -183,18 +181,19 @@ int infil_readParams(int m, char* tok[], int ntoks) return error_setInpError(ERR_NUMBER, tok[n]); } - // --- assign parameter values to infil. object + // --- assign parameter values to infil, infilModel object Subcatch[j].infil = j; + Subcatch[j].infilModel = m; switch (m) { case HORTON: - case MOD_HORTON: status = horton_setParams(&HortInfil[j], x); + case MOD_HORTON: status = horton_setParams(&Infil[j].horton, x); break; case GREEN_AMPT: case MOD_GREEN_AMPT: - status = grnampt_setParams(&GAInfil[j], x); + status = grnampt_setParams(&Infil[j].grnAmpt, x); break; - case CURVE_NUMBER: status = curvenum_setParams(&CNInfil[j], x); + case CURVE_NUMBER: status = curvenum_setParams(&Infil[j].curveNum, x); break; default: status = TRUE; } @@ -204,49 +203,47 @@ int infil_readParams(int m, char* tok[], int ntoks) //============================================================================= -void infil_initState(int j, int m) +void infil_initState(int j) // // Input: j = subcatchment index -// m = infiltration method code // Output: none // Purpose: initializes state of infiltration for a subcatchment. // { - switch (m) + switch (Subcatch[j].infilModel) { case HORTON: - case MOD_HORTON: horton_initState(&HortInfil[j]); break; + case MOD_HORTON: horton_initState(&Infil[j].horton); break; case GREEN_AMPT: case MOD_GREEN_AMPT: - grnampt_initState(&GAInfil[j]); break; - case CURVE_NUMBER: curvenum_initState(&CNInfil[j]); break; + grnampt_initState(&Infil[j].grnAmpt); break; + case CURVE_NUMBER: curvenum_initState(&Infil[j].curveNum); break; } } //============================================================================= -void infil_getState(int j, int m, double x[]) +void infil_getState(int j, double x[]) // // Input: j = subcatchment index -// m = infiltration method code -// Output: none +// Output: x = subcatchment's infiltration state // Purpose: retrieves the current infiltration state for a subcatchment. // { - switch (m) + switch (Subcatch[j].infilModel) { case HORTON: - case MOD_HORTON: horton_getState(&HortInfil[j], x); break; + case MOD_HORTON: horton_getState(&Infil[j].horton, x); break; case GREEN_AMPT: case MOD_GREEN_AMPT: - grnampt_getState(&GAInfil[j],x); break; - case CURVE_NUMBER: curvenum_getState(&CNInfil[j], x); break; + grnampt_getState(&Infil[j].grnAmpt, x); break; + case CURVE_NUMBER: curvenum_getState(&Infil[j].curveNum, x); break; } } //============================================================================= -void infil_setState(int j, int m, double x[]) +void infil_setState(int j, double x[]) // // Input: j = subcatchment index // m = infiltration method code @@ -254,14 +251,14 @@ void infil_setState(int j, int m, double x[]) // Purpose: sets the current infiltration state for a subcatchment. // { - switch (m) + switch (Subcatch[j].infilModel) { case HORTON: - case MOD_HORTON: horton_setState(&HortInfil[j], x); break; + case MOD_HORTON: horton_setState(&Infil[j].horton, x); break; case GREEN_AMPT: case MOD_GREEN_AMPT: - grnampt_setState(&GAInfil[j],x); break; - case CURVE_NUMBER: curvenum_setState(&CNInfil[j], x); break; + grnampt_setState(&Infil[j].grnAmpt, x); break; + case CURVE_NUMBER: curvenum_setState(&Infil[j].curveNum, x); break; } } @@ -295,11 +292,10 @@ void infil_setInfilFactor(int j) //============================================================================= -double infil_getInfil(int j, int m, double tstep, double rainfall, +double infil_getInfil(int j, double tstep, double rainfall, double runon, double depth) // // Input: j = subcatchment index -// m = infiltration method code // tstep = runoff time step (sec) // rainfall = rainfall rate (ft/sec) // runon = runon rate from other sub-areas or subcatchments (ft/sec) @@ -308,22 +304,23 @@ double infil_getInfil(int j, int m, double tstep, double rainfall, // Purpose: computes infiltration rate depending on infiltration method. // { - switch (m) + switch (Subcatch[j].infilModel) { case HORTON: - return horton_getInfil(&HortInfil[j], tstep, rainfall+runon, depth); + return horton_getInfil(&Infil[j].horton, tstep, rainfall+runon, depth); case MOD_HORTON: - return modHorton_getInfil(&HortInfil[j], tstep, rainfall+runon, + return modHorton_getInfil(&Infil[j].horton, tstep, rainfall+runon, depth); case GREEN_AMPT: case MOD_GREEN_AMPT: - return grnampt_getInfil(&GAInfil[j], tstep, rainfall+runon, depth, m); + return grnampt_getInfil(&Infil[j].grnAmpt, tstep, rainfall+runon, depth, + Subcatch[j].infilModel); case CURVE_NUMBER: depth += runon / tstep; - return curvenum_getInfil(&CNInfil[j], tstep, rainfall, depth); + return curvenum_getInfil(&Infil[j].curveNum, tstep, rainfall, depth); default: return 0.0; @@ -341,7 +338,7 @@ int horton_setParams(THorton *infil, double p[]) // { int k; - for (k=0; k<5; k++) if ( p[k] < 0.0 ) return FALSE; + for (k = 0; k < 5; k++) if ( p[k] < 0.0 ) return FALSE; // --- max. & min. infil rates (ft/sec) infil->f0 = p[0] / UCF(RAINFALL); @@ -566,6 +563,21 @@ double modHorton_getInfil(THorton *infil, double tstep, double irate, //============================================================================= +void grnampt_getParams(int j, double p[]) +// +// Input: j = subcatchment index +// p[] = array of parameter values +// Output: none +// Purpose: retrieves Green-Ampt infiltration parameters for a subcatchment. +// +{ + p[0] = Infil[j].grnAmpt.S * UCF(RAINDEPTH); // Capillary suction head (ft) + p[1] = Infil[j].grnAmpt.Ks * UCF(RAINFALL); // Sat. hyd. conductivity (ft/sec) + p[2] = Infil[j].grnAmpt.IMDmax; // Max. init. moisture deficit +} + +//============================================================================= + int grnampt_setParams(TGrnAmpt *infil, double p[]) // // Input: infil = ptr. to Green-Ampt infiltration object diff --git a/src/solver/infil.h b/src/solver/infil.h index cf208e234..c4923e88d 100644 --- a/src/solver/infil.h +++ b/src/solver/infil.h @@ -7,6 +7,7 @@ // 09/15/14 (Build 5.1.007) // 08/05/15 (Build 5.1.010) // 05/10/18 (Build 5.1.013) +// 04/01/20 (Build 5.1.015) // Author: L. Rossman (US EPA) // // Public interface for infiltration functions. @@ -16,11 +17,15 @@ // // Build 5.1.013: // - New function infil_setInfilFactor() added. +// +// Build 5.1.015: +// - Support added for multiple infiltration methods within a project. //----------------------------------------------------------------------------- #ifndef INFIL_H #define INFIL_H + //--------------------- // Enumerated Constants //--------------------- @@ -93,19 +98,21 @@ extern TCurveNum* CNInfil; //----------------------------------------------------------------------------- // Infiltration Methods //----------------------------------------------------------------------------- -void infil_create(int subcatchCount, int model); +void infil_create(int n); void infil_delete(void); -int infil_readParams(int model, char* tok[], int ntoks); -void infil_initState(int area, int model); -void infil_getState(int j, int m, double x[]); -void infil_setState(int j, int m, double x[]); -void infil_setInfilFactor(int j); //(5.1.013) -double infil_getInfil(int area, int model, double tstep, double rainfall, - double runon, double depth); +int infil_readParams(int m, char* tok[], int ntoks); +void infil_initState(int j); +void infil_getState(int j, double x[]); +void infil_setState(int j, double x[]); +void infil_setInfilFactor(int j); +double infil_getInfil(int area, double tstep, double rainfall, double runon, + double depth); +void grnampt_getParams(int j, double p[]); int grnampt_setParams(TGrnAmpt *infil, double p[]); void grnampt_initState(TGrnAmpt *infil); double grnampt_getInfil(TGrnAmpt *infil, double tstep, double irate, double depth, int modelType); -#endif + +#endif //INFIL_H diff --git a/src/solver/inflow.c b/src/solver/inflow.c index e11e15086..42976c13e 100644 --- a/src/solver/inflow.c +++ b/src/solver/inflow.c @@ -71,11 +71,11 @@ int inflow_readExtInflow(char* tok[], int ntoks) Tseries[tseries].refersTo = EXTERNAL_INFLOW; } - // --- assign type & cf values for a FLOW inflow - if (param == -1) - { - type = FLOW_INFLOW; - } + // --- assign type & cf values for a FLOW inflow + if (param == -1) + { + type = FLOW_INFLOW; + } // --- do the same for a pollutant inflow if ( ntoks >= 4 && param > -1) @@ -115,9 +115,9 @@ int inflow_readExtInflow(char* tok[], int ntoks) basePat = project_findObject(TIMEPATTERN, tok[7]); if ( basePat < 0 ) return error_setInpError(ERR_NAME, tok[7]); } - - return(inflow_setExtInflow(j, param, type, tseries, basePat, - cf, baseline, sf)); + + return(inflow_setExtInflow(j, param, type, tseries, basePat, + cf, baseline, sf)); } int inflow_validate(int param, int type, int tseries, int basePat, double *cf) @@ -130,49 +130,49 @@ int inflow_validate(int param, int type, int tseries, int basePat, double *cf) // Output: cf = Unit Conversion // Return: returns Error Code { - int errcode = 0; - // Validate param - if (param >= Nobjects[POLLUT]) - { - errcode = ERR_API_POLLUT_INDEX; - } - // Validate Type - else if (type != FLOW_INFLOW - && type != CONCEN_INFLOW - && type != MASS_INFLOW) - { - errcode = ERR_KEYWORD; - } - // Validate Timeseries Index - else if (tseries >= Nobjects[TSERIES]) - { - errcode = ERR_API_TSERIES_INDEX; - } - // Validate Timepattern Index - else if (basePat >= Nobjects[TIMEPATTERN]) - { - errcode = ERR_API_PATTERN_INDEX; - } - else - { - // --- assign type & cf values for a FLOW inflow - if ( type == FLOW_INFLOW ) - { - *cf = 1.0/UCF(FLOW); - } - // --- include LperFT3 term in conversion factor for MASS_INFLOW - else if ( type == MASS_INFLOW ) - { - *cf /= LperFT3; - } - } - - return(errcode); + int errcode = 0; + // Validate param + if (param >= Nobjects[POLLUT]) + { + errcode = ERR_API_POLLUT_INDEX; + } + // Validate Type + else if (type != FLOW_INFLOW + && type != CONCEN_INFLOW + && type != MASS_INFLOW) + { + errcode = ERR_KEYWORD; + } + // Validate Timeseries Index + else if (tseries >= Nobjects[TSERIES]) + { + errcode = ERR_API_TSERIES_INDEX; + } + // Validate Timepattern Index + else if (basePat >= Nobjects[TIMEPATTERN]) + { + errcode = ERR_API_PATTERN_INDEX; + } + else + { + // --- assign type & cf values for a FLOW inflow + if ( type == FLOW_INFLOW ) + { + *cf = 1.0/UCF(FLOW); + } + // --- include LperFT3 term in conversion factor for MASS_INFLOW + else if ( type == MASS_INFLOW ) + { + *cf /= LperFT3; + } + } + + return(errcode); } int inflow_setExtInflow(int j, int param, int type, int tseries, int basePat, - double cf, double baseline, double sf) + double cf, double baseline, double sf) // Purpose: This function assigns property values to the inflow object // Inputs: j = Node index // param = FLOW (-1) or pollutant index @@ -185,45 +185,45 @@ int inflow_setExtInflow(int j, int param, int type, int tseries, int basePat, // Return: returns Error Code { - int errcode = 0; - - // Validate Inflow - errcode = inflow_validate(param, type, tseries, basePat, &cf); - - if (errcode == 0) - { - TExtInflow* inflow; // external inflow object - - // --- check if an external inflow object for this constituent already exists - inflow = Node[j].extInflow; - while ( inflow ) - { - if ( inflow->param == param ) break; - inflow = inflow->next; - } - - // --- if it doesn't exist, then create it - if ( inflow == NULL ) - { - inflow = (TExtInflow *) malloc(sizeof(TExtInflow)); - if ( inflow == NULL ) - { - return error_setInpError(ERR_MEMORY, ""); - } - inflow->next = Node[j].extInflow; - Node[j].extInflow = inflow; - } - - // Assigning Values to the inflow object - inflow->param = param; - inflow->type = type; - inflow->tSeries = tseries; - inflow->cFactor = cf; - inflow->sFactor = sf; - inflow->baseline = baseline; - inflow->basePat = basePat; - inflow->extIfaceInflow = 0.0; - } + int errcode = 0; + TExtInflow* inflow; // external inflow object + + // Validate Inflow + errcode = inflow_validate(param, type, tseries, basePat, &cf); + + if (errcode == 0) + { + + // --- check if an external inflow object for this constituent already exists + inflow = Node[j].extInflow; + while ( inflow ) + { + if ( inflow->param == param ) break; + inflow = inflow->next; + } + + // --- if it doesn't exist, then create it + if ( inflow == NULL ) + { + inflow = (TExtInflow *) malloc(sizeof(TExtInflow)); + if ( inflow == NULL ) + { + return error_setInpError(ERR_MEMORY, ""); + } + inflow->next = Node[j].extInflow; + Node[j].extInflow = inflow; + } + + // Assigning Values to the inflow object + inflow->param = param; + inflow->type = type; + inflow->tSeries = tseries; + inflow->cFactor = cf; + inflow->sFactor = sf; + inflow->baseline = baseline; + inflow->basePat = basePat; + inflow->extIfaceInflow = 0.0; + } return(errcode); } @@ -265,7 +265,7 @@ double inflow_getExtInflow(TExtInflow* inflow, DateTime aDate) double sf = inflow->sFactor; // scaling factor double blv = inflow->baseline; // baseline value double tsv = 0.0; // time series value - double extIfaceInflow = inflow->extIfaceInflow;// external interfacing inflow + double extIfaceInflow = inflow->extIfaceInflow;// external interfacing inflow if ( p >= 0 ) { diff --git a/src/solver/input.c b/src/solver/input.c index b36fd4289..390b6f088 100644 --- a/src/solver/input.c +++ b/src/solver/input.c @@ -6,6 +6,7 @@ // Date: 03/20/14 (Build 5.1.001) // 09/15/14 (Build 5.1.007) // 08/01/16 (Build 5.1.011) +// 04/01/20 (Build 5.1.015) // Author: L. Rossman // // Input data processing functions. @@ -16,6 +17,8 @@ // Build 5.1.011: // - Support added for reading hydraulic event dates. // +// Build 5.1.015: +// - Support added for multiple infiltration methods within a project. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -478,7 +481,7 @@ int parseLine(int sect, char *line) return subcatch_readSubareaParams(Tok, Ntokens); case s_INFIL: - return infil_readParams(InfilModel, Tok, Ntokens); + return infil_readParams(InfilModel, Tok, Ntokens); //(5.1.015) case s_AQUIFER: j = Mobjects[AQUIFER]; diff --git a/src/solver/keywords.h b/src/solver/keywords.h index 3724a0c89..af89e0d58 100644 --- a/src/solver/keywords.h +++ b/src/solver/keywords.h @@ -17,6 +17,10 @@ // - New keyword array defined for surcharge method. //----------------------------------------------------------------------------- +#ifndef KEYWORDS_H +#define KEYWORDS_H + + extern char* BuildupTypeWords[]; extern char* CurveTypeWords[]; extern char* DividerTypeWords[]; @@ -65,3 +69,6 @@ extern char* VolUnitsWords2[]; extern char* WashoffTypeWords[]; extern char* WeirTypeWords[]; extern char* XsectTypeWords[]; + + +#endif //KEYWORDS_H diff --git a/src/solver/lid.c b/src/solver/lid.c index 4dcf02a1d..57dd9c60d 100644 --- a/src/solver/lid.c +++ b/src/solver/lid.c @@ -13,6 +13,7 @@ // 03/14/17 (Build 5.1.012) // 05/10/18 (Build 5.1.013) // 03/01/20 (Build 5.1.014) +// 04/01/20 (Build 5.1.015) // Author: L. Rossman (US EPA) // // This module handles all data processing involving LID (Low Impact @@ -77,6 +78,9 @@ // Build 5.1.014: // - Fixed bug in creating LidProcs when there are no subcatchments. // - Fixed bug in adding underdrain pollutant loads to mass balances. +// +// Build 5.1.015: +// - Support added for mutiple infiltration methods within a project. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -262,7 +266,7 @@ void lid_create(int lidCount, int subcatchCount) return; } } - + //... initialize LID groups for (j = 0; j < GroupCount; j++) LidGroups[j] = NULL; @@ -761,7 +765,7 @@ int readDrainData(int j, char* toks[], int ntoks) for (i = 0; i < 6; i++) x[i] = 0.0; //(5.1.013) for (i = 2; i < 8; i++) // { - if ( ntoks > i && ! getDouble(toks[i], &x[i-2]) || x[i-2] < 0.0 ) //(5.1.013) + if ( ntoks > i && ! getDouble(toks[i], &x[i-2]) || x[i-2] < 0.0 ) //(5.1.013) return error_setInpError(ERR_NUMBER, toks[i]); } @@ -803,7 +807,7 @@ int readDrainMatData(int j, char* toks[], int ntoks) //... read numerical parameters if ( ntoks < 5 ) return error_setInpError(ERR_ITEMS, ""); - if ( LidProcs[j].lidType != GREEN_ROOF ) return 0; + if ( LidProcs[j].lidType != GREEN_ROOF ) return 0; for (i = 2; i < 5; i++) { if ( ! getDouble(toks[i], &x[i-2]) || x[i-2] < 0.0 ) @@ -1096,12 +1100,12 @@ void validateLidProc(int j) //... set storage layer parameters of a green roof if ( LidProcs[j].lidType == GREEN_ROOF ) - { - LidProcs[j].storage.thickness = LidProcs[j].drainMat.thickness; - LidProcs[j].storage.voidFrac = LidProcs[j].drainMat.voidFrac; - LidProcs[j].storage.clogFactor = 0.0; - LidProcs[j].storage.kSat = 0.0; - } + { + LidProcs[j].storage.thickness = LidProcs[j].drainMat.thickness; + LidProcs[j].storage.voidFrac = LidProcs[j].drainMat.voidFrac; + LidProcs[j].storage.clogFactor = 0.0; + LidProcs[j].storage.kSat = 0.0; + } } //============================================================================= @@ -1155,11 +1159,10 @@ void validateLidGroup(int j) //... assign vegetative swale infiltration parameters if ( LidProcs[k].lidType == VEG_SWALE ) { - if ( InfilModel == GREEN_AMPT || InfilModel == MOD_GREEN_AMPT ) + if ( Subcatch[j].infilModel == GREEN_AMPT || //(5.1.015) + Subcatch[j].infilModel == MOD_GREEN_AMPT ) //(5.1.015) { - p[0] = GAInfil[j].S * UCF(RAINDEPTH); - p[1] = GAInfil[j].Ks * UCF(RAINFALL); - p[2] = GAInfil[j].IMDmax; + grnampt_getParams(j, p); //(5.1.015) if ( grnampt_setParams(&(lidUnit->soilInfil), p) == FALSE ) { strcpy(Msg, LidProcs[k].ID); @@ -1720,10 +1723,10 @@ void findNativeInfil(int j, double tStep) //... otherwise find infil. rate for the subcatchment's rainfall + runon else { - NativeInfil = infil_getInfil(j, InfilModel, tStep, + NativeInfil = infil_getInfil(j, tStep, Subcatch[j].rainfall, Subcatch[j].runon, - getSurfaceDepth(j)); //(5.1.008) + getSurfaceDepth(j)); //(5.1.015) } //... see if there is any groundwater-imposed limit on infil. diff --git a/src/solver/lid.h b/src/solver/lid.h index 93ee2b779..146b58e2a 100644 --- a/src/solver/lid.h +++ b/src/solver/lid.h @@ -18,7 +18,7 @@ // - Detailed LID reporting modified. // // Build 5.1.011: -// - Water depth replaces moisture content for LID's pavement layer. +// - Water depth replaces moisture content for LID's pavement layer. // - Arguments for lidproc_saveResults() modified. // // Build 5.1.012: @@ -41,6 +41,7 @@ #ifndef LID_H #define LID_H + #include #include #include @@ -51,8 +52,8 @@ //----------------------------------------------------------------------------- enum LidTypes { BIO_CELL, // bio-retention cell - RAIN_GARDEN, // rain garden - GREEN_ROOF, // green roof + RAIN_GARDEN, // rain garden + GREEN_ROOF, // green roof INFIL_TRENCH, // infiltration trench POROUS_PAVEMENT, // porous pavement RAIN_BARREL, // rain barrel @@ -73,7 +74,7 @@ typedef struct { double thickness; // depression storage or berm ht. (ft) double voidFrac; // available fraction of storage volume - double roughness; // surface Mannings n + double roughness; // surface Mannings n double surfSlope; // land surface slope (fraction) double sideSlope; // swale side slope (run/rise) double alpha; // slope/roughness term in Manning eqn. @@ -184,7 +185,7 @@ typedef struct int drainNode; // node receiving drain flow TLidRptFile* rptFile; // pointer to detailed report file - TGrnAmpt soilInfil; // infil. object for biocell soil layer + TGrnAmpt soilInfil; // infil. object for biocell soil layer double surfaceDepth; // depth of ponded water on surface layer (ft) double paveDepth; // depth of water in porous pavement layer double soilMoisture; // moisture content of biocell soil layer @@ -192,7 +193,7 @@ typedef struct // net inflow - outflow from previous time step for each LID layer (ft/s) double oldFluxRates[MAX_LAYERS]; - + double dryTime; // time since last rainfall (sec) double oldDrainFlow; // previous drain flow (cfs) double newDrainFlow; // current drain flow (cfs) @@ -236,4 +237,5 @@ double lidproc_getOutflow(TLidUnit* lidUnit, TLidProc* lidProc, void lidproc_saveResults(TLidUnit* lidUnit, double ucfRainfall, double ucfRainDepth); -#endif + +#endif //LID_H diff --git a/src/solver/macros.h b/src/solver/macros.h index 998e92ac0..6f10ae464 100644 --- a/src/solver/macros.h +++ b/src/solver/macros.h @@ -7,6 +7,10 @@ // Author: L. Rossman //----------------------------------------------------------------------------- +#ifndef MACROS_H +#define MACROS_H + + //-------------------------------------------------- // Macro to test for successful allocation of memory //-------------------------------------------------- @@ -36,3 +40,6 @@ // Macro to evaluate function x with error checking //------------------------------------------------- #define CALL(x) (ErrorCode = ((ErrorCode>0) ? (ErrorCode) : (x))) + + +#endif //MACROS_H diff --git a/src/solver/mathexpr.h b/src/solver/mathexpr.h index 34d81eafd..ab56b7fba 100644 --- a/src/solver/mathexpr.h +++ b/src/solver/mathexpr.h @@ -8,6 +8,10 @@ ** LAST UPDATE: 03/20/14 ******************************************************************************/ +#ifndef MATHEXPR_H +#define MATHEXPR_H + + // Node in a tokenized math expression list struct ExprNode { @@ -27,3 +31,6 @@ double mathexpr_eval(MathExpr* expr, double (*getVal) (int)); // Deletes a tokenized math expression void mathexpr_delete(MathExpr* expr); + + +#endif //MATHEXPR_H diff --git a/src/solver/mempool.h b/src/solver/mempool.h index cc7b45cc1..864d2d6c3 100644 --- a/src/solver/mempool.h +++ b/src/solver/mempool.h @@ -7,6 +7,10 @@ // alloc pool - only the alloc routines know its structure. //----------------------------------------------------------------------------- +#ifndef MEMPOOL_H +#define MEMPOOL_H + + typedef struct { long dummy; @@ -17,3 +21,6 @@ char *Alloc(long); alloc_handle_t *AllocSetPool(alloc_handle_t *); void AllocReset(void); void AllocFreePool(void); + + +#endif //MEMPOOL_H diff --git a/src/solver/node.c b/src/solver/node.c index 4312b2d01..ac1061621 100644 --- a/src/solver/node.c +++ b/src/solver/node.c @@ -9,6 +9,7 @@ // 08/05/15 (Build 5.1.010) // 05/10/18 (Build 5.1.013) // 03/01/20 (Build 5.1.014) +// 04/14/20 (Build 5.1.015) // Author: L. Rossman // // Conveyance system node functions. @@ -31,6 +32,10 @@ // // Build 5.1.014: // - Fixed bug in storage_losses() that affected storage exfiltration. +// +// Build 5.1.015: +// - Fatal error issued if a storage node's area curve produces a negative +// volume when extrapolated to the node's full depth. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -211,6 +216,11 @@ void node_validate(int j) if ( Node[j].initDepth > Node[j].fullDepth + Node[j].surDepth ) report_writeErrorMsg(ERR_NODE_DEPTH, Node[j].ID); + // --- check for negative volume for storage node at full depth //(5.1.015) + if (Node[j].type == STORAGE) // + if (node_getVolume(j, Node[j].fullDepth) < 0.0) // + report_writeErrorMsg(ERR_STORAGE_VOLUME, Node[j].ID); // + if ( Node[j].type == DIVIDER ) divider_validate(j); // --- initialize dry weather inflows @@ -795,7 +805,7 @@ void storage_getVolDiff(double y, double* f, double* df, void* p) int k; double e, v; TStorageVol* storageVol; - + // ... cast void pointer p to a TStorageVol object storageVol = (TStorageVol *)p; k = storageVol->k; @@ -831,7 +841,7 @@ double storage_getVolume(int j, double d) // --- use table integration if area v. depth table exists if ( i >= 0 ) - return table_getArea(&Curve[i], d*UCF(LENGTH)) / UCF(VOLUME); + return table_getArea(&Curve[i], d*UCF(LENGTH)) / UCF(VOLUME); // --- otherwise use functional area v. depth relation else @@ -841,6 +851,7 @@ double storage_getVolume(int j, double d) v += Storage[k].aCoeff / (Storage[k].aExpon+1.0) * pow(d, Storage[k].aExpon+1.0); return v / UCF(VOLUME); + } } diff --git a/src/solver/objects.h b/src/solver/objects.h index 9fd738067..87716b86a 100644 --- a/src/solver/objects.h +++ b/src/solver/objects.h @@ -9,6 +9,7 @@ // 08/05/15 (Build 5.1.010) // 08/01/16 (Build 5.1.011) // 05/10/18 (Build 5.1.013) +// 04/01/20 (Build 5.1.015) // // Author: L. Rossman (EPA) // M. Tryby (EPA) @@ -54,8 +55,16 @@ // - Adjustment patterns added to TSubcatch structure. // - Members impervRunoff and pervRunoff added to TSubcatchStats structure. // - Member cdCurve (weir coeff. curve) added to TWeir structure. +// +// Build 5.1.015: +// - Support added for multiple infiltration methods within a project. +// - Support added for grouped freqency table of routing time steps. //----------------------------------------------------------------------------- +#ifndef OBJECTS_H +#define OBJECTS_H + + #include "mathexpr.h" #include "infil.h" #include "exfil.h" @@ -106,7 +115,7 @@ typedef struct typedef struct { char* ID; // raingage name - int dataSource; // data from time series or file + int dataSource; // data from time series or file int tSeries; // rainfall data time series index char fname[MAXFNAME+1]; // name of rainfall data file char staID[MAXMSG+1]; // station number @@ -130,7 +139,7 @@ typedef struct double reportRainfall; // rainfall value used for reported results int coGage; // index of gage with same rain timeseries int isUsed; // TRUE if gage used by any subcatchment - int isCurrent; // TRUE if gage's rainfall is current + int isCurrent; // TRUE if gage's rainfall is current } TGage; //------------------- @@ -138,7 +147,7 @@ typedef struct //------------------- typedef struct { - int dataSource; // data from time series or file + int dataSource; // data from time series or file int tSeries; // temperature data time series index DateTime fileStartDate; // starting date of data read from file double elev; // elev. of study area (ft) @@ -186,11 +195,11 @@ typedef struct int tSeries; // time series index double monthlyEvap[12]; // monthly evaporation values double panCoeff[12]; // monthly pan coeff. values - int recoveryPattern; // soil recovery factor pattern + int recoveryPattern; // soil recovery factor pattern int dryOnly; // true if evaporation only in dry periods //---------------------------- double rate; // current evaporation rate (ft/sec) - double recoveryFactor; // current soil recovery factor + double recoveryFactor; // current soil recovery factor } TEvap; //------------------- @@ -258,7 +267,7 @@ typedef struct //------------------------ typedef struct { - int aquifer; // index of associated gw aquifer + int aquifer; // index of associated gw aquifer int node; // index of node receiving gw flow double surfElev; // elevation of ground surface (ft) double a1, b1; // ground water outflow coeff. & exponent @@ -366,6 +375,7 @@ typedef struct int gage; // raingage index int outNode; // outlet node index int outSubcatch; // outlet subcatchment index + int infilModel; // infiltration method index //(5.1.015) int infil; // infiltration object index TSubarea subArea[3]; // sub-area data double width; // overland flow width (ft) @@ -386,7 +396,7 @@ typedef struct double lidArea; // area devoted to LIDs (ft2) double rainfall; // current rainfall (ft/sec) double evapLoss; // current evap losses (ft/sec) - double infilLoss; // current infil losses (ft/sec) + double infilLoss; // current infil losses (ft/sec) double runon; // runon from other subcatchments (cfs) double oldRunoff; // previous runoff (cfs) double newRunoff; // current runoff (cfs) @@ -538,7 +548,7 @@ typedef struct TExfil* exfil; // ptr. to exfiltration object //----------------------------- double hrt; // hydraulic residence time (sec) - double evapLoss; // evaporation loss (ft3) + double evapLoss; // evaporation loss (ft3) double exfilLoss; // exfiltration loss (ft3) } TStorage; @@ -590,10 +600,10 @@ typedef struct double aFull; // area when full (ft2) double rFull; // hyd. radius when full (ft) double wMax; // width at widest point (ft) - double ywMax; // depth at max width (ft) + double ywMax; // depth at max width (ft) double sMax; // section factor at max. flow (ft^4/3) double aMax; // area at max. flow (ft2) - double lengthFactor; // floodplain / channel length + double lengthFactor; // floodplain / channel length //-------------------------------------- double roughness; // Manning's n double areaTbl[N_TRANSECT_TBL]; // table of area v. depth @@ -610,7 +620,7 @@ typedef struct { int curve; // index of shape curve int nTbl; // size of geometry tables - double aFull; // area when full + double aFull; // area when full double rFull; // hyd. radius when full double wMax; // max. width double sMax; // max. section factor @@ -698,10 +708,10 @@ typedef struct { int type; // pump type int pumpCurve; // pump curve table index - double initSetting; // initial speed setting + double initSetting; // initial speed setting double yOn; // startup depth (ft) double yOff; // shutoff depth (ft) - double xMin; // minimum pt. on pump curve + double xMin; // minimum pt. on pump curve double xMax; // maximum pt. on pump curve } TPump; @@ -832,7 +842,7 @@ typedef struct //------------------------------- typedef struct { // All volume totals are in ft3. - double rainfall; // rainfall volume + double rainfall; // rainfall volume double evap; // evaporation loss double infil; // infiltration loss double runoff; // runoff volume @@ -900,6 +910,7 @@ typedef struct //----------------------- // SYSTEM-WIDE STATISTICS //----------------------- +#define TIMELEVELS 6 //(5.1.015) typedef struct { double minTimeStep; @@ -907,6 +918,8 @@ typedef struct double avgTimeStep; double avgStepCount; double steadyStateCount; + double timeStepIntervals[TIMELEVELS]; //(5.1.015) + int timeStepCounts[TIMELEVELS]; //(5.1.015) } TSysStats; //-------------------- @@ -931,7 +944,7 @@ typedef struct double evap; double infil; double runoff; - double maxFlow; + double maxFlow; double impervRunoff; //(5.1.013) double pervRunoff; // } TSubcatchStats; @@ -979,11 +992,11 @@ typedef struct { double avgFlow; double maxFlow; - double* totalLoad; + double* totalLoad; int totalPeriods; } TOutfallStats; -//---------------- +//---------------- // PUMP STATISTICS //---------------- typedef struct @@ -1030,15 +1043,18 @@ typedef struct int objType; // either NODE or LINK int index; // node or link index double value; // value of node or link statistic -} TMaxStats; +} TMaxStats; //------------------ // REPORT FIELD INFO //------------------ -typedef struct +typedef struct { - char Name[80]; // name of reported variable + char Name[80]; // name of reported variable char Units[80]; // units of reported variable char Enabled; // TRUE if appears in report table int Precision; // number of decimal places when reported } TRptField; + + +#endif //OBJECTS_H diff --git a/src/solver/odesolve.h b/src/solver/odesolve.h index 86fc86e67..77316452f 100644 --- a/src/solver/odesolve.h +++ b/src/solver/odesolve.h @@ -5,8 +5,15 @@ // //----------------------------------------------------------------------------- +#ifndef ODESOLVE_H +#define ODESOLVE_H + + // functions that open, close, and use the ODE solver int odesolve_open(int n); void odesolve_close(void); int odesolve_integrate(double ystart[], int n, double x1, double x2, double eps, double h1, void (*derivs)(double, double*, double*)); + + +#endif //ODESOLVE_H diff --git a/src/solver/project.c b/src/solver/project.c index 0fae207d5..db9d116c6 100644 --- a/src/solver/project.c +++ b/src/solver/project.c @@ -11,6 +11,7 @@ // 08/01/16 (Build 5.1.011) // 03/14/17 (Build 5.1.012) // 05/10/18 (Build 5.1.013) +// 04/01/20 (Build 5.1.015) // Author: L. Rossman // // Project management functions. @@ -55,6 +56,8 @@ // - More robust parsing of MinSurfarea option provided. // - Support added for new RuleStep analysis option. // +// Build 5.1.015: +// - Support added for multiple infiltration methods within a project. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -1014,7 +1017,7 @@ void createObjects() if ( ErrorCode ) return; // --- allocate memory for infiltration data - infil_create(Nobjects[SUBCATCH], InfilModel); + infil_create(Nobjects[SUBCATCH]); //(5.1.015) // --- allocate memory for water quality state variables for (j = 0; j < Nobjects[SUBCATCH]; j++) diff --git a/src/solver/qualrout.c b/src/solver/qualrout.c index 7c16e45af..3a23e4e72 100644 --- a/src/solver/qualrout.c +++ b/src/solver/qualrout.c @@ -7,6 +7,7 @@ // 04/02/15 (Build 5.1.008) // 04/30/15 (Build 5.1.009) // 08/05/15 (Build 5.1.010) +// 04/01/20 (Build 5.1.015) // Author: L. Rossman // // Water quality routing functions. @@ -22,6 +23,8 @@ // - Entire module re-written to be more compact and easier to follow. // - Neglible depth limit replaced with a negligible volume limit. // +// Build 5.1.015: +// - Fixed mass balance issue for empty storage nodes that flood. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -443,8 +446,8 @@ void findStorageQual(int j, double tStep) wIn = Node[j].newQual[p]; c2 = getMixedQual(c1, v1, wIn, qIn, tStep); - // --- set concen. to zero if remaining volume is negligible - if ( Node[j].newVolume <= ZeroVolume ) +// --- set concen. to zero if remaining volume & inflow is negligible //(5.1.015) + if (Node[j].newVolume <= ZeroVolume && qIn <= FLOW_TOL) //(5.1.015) { massbal_addToFinalStorage(p, c2 * Node[j].newVolume); c2 = 0.0; diff --git a/src/solver/report.c b/src/solver/report.c index 7a0ced556..12d73fd7c 100644 --- a/src/solver/report.c +++ b/src/solver/report.c @@ -11,6 +11,7 @@ // 03/14/17 (Build 5.1.012) // 05/10/18 (Build 5.1.013) // 03/01/20 (Build 5.1.014) +// 05/18/20 (Build 5.1.015) // Author: L. Rossman (EPA) // // Report writing functions. @@ -43,6 +44,10 @@ // // Build 5.1.014: // - Fixed bug in confusing keywords with ID names in report_readOptions(). +// +// Build 5.1.015: +// - Fixes bug in summary statistics when Report Start date > Start Date. +// - Support added for grouped freqency table of routing time steps. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -86,7 +91,7 @@ static void report_Nodes(void); static void report_NodeHeader(char *id); static void report_Links(void); static void report_LinkHeader(char *id); - +static void report_RouteStepFreq(TSysStats* sysStats); //(5.1.015) //============================================================================= @@ -1031,10 +1036,11 @@ void report_writeSysStats(TSysStats* sysStats) // { double x; - double eventStepCount = (double)StepCount - sysStats->steadyStateCount; + double eventStepCount; // Routing steps taken during reporting period //(5.1.015) - if ( Nobjects[LINK] == 0 || StepCount == 0 - || eventStepCount == 0.0 ) return; + eventStepCount = ReportStepCount - sysStats->steadyStateCount; //(5.1.015) + if ( Nobjects[LINK] == 0 || TotalStepCount == 0 + || eventStepCount == 0.0 ) return; WRITE(""); WRITE("*************************"); WRITE("Routing Time Step Summary"); @@ -1057,9 +1063,37 @@ void report_writeSysStats(TSysStats* sysStats) fprintf(Frpt.file, "\n Percent Not Converging : %7.2f", 100.0 * (double)NonConvergeCount / eventStepCount); + + // --- write grouped frequency table of variable routing time steps //(5.1.015) + if (RouteModel == DW && CourantFactor > 0.0) // + report_RouteStepFreq(sysStats); // WRITE(""); } +//============================================================================= + +//// New function added to release 5.1.015. //// //(5.1.015) +void report_RouteStepFreq(TSysStats* sysStats) +// +// Input: sysStats = simulation statistics for overall system +// Output: none +// Purpose: writes grouped frequency table of routing time steps to report file. +// +{ + double totalSteps = 0.0; + int i; + + for (i = 1; i < TIMELEVELS; i++) + totalSteps += sysStats->timeStepCounts[i]; + fprintf(Frpt.file, + "\n Time Step Frequencies :"); + for (i = 1; i < TIMELEVELS; i++) + fprintf(Frpt.file, + "\n %6.3f - %6.3f sec : %7.2f %%", + sysStats->timeStepIntervals[i-1], sysStats->timeStepIntervals[i], + 100.0 * (double)(sysStats->timeStepCounts[i]) / totalSteps); +} + //============================================================================= // SIMULATION RESULTS REPORTING diff --git a/src/solver/stats.c b/src/solver/stats.c index 7d6cb8b90..11c4ace09 100644 --- a/src/solver/stats.c +++ b/src/solver/stats.c @@ -9,6 +9,7 @@ // 08/01/16 (Build 5.1.011) // 03/14/17 (Build 5.1.012) // 05/10/18 (Build 5.1.013) +// 04/01/20 (Build 5.1.015) // Author: L. Rossman (EPA) // R. Dickinson (CDM) // @@ -36,6 +37,11 @@ // - Statistics on impervious and pervious runoff totals added. // - Storage nodes with a non-zero surcharge depth (e.g. enclosed tanks) // can now be classified as being surcharged. +// +// Build 5.1.015: +// - Fixes bug in summary statistics when Report Start date > Start Date. +// - Fixes failure to initialize all subcatchment groundwater statistics. +// - Support added for grouped freqency table of routing time steps. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -106,6 +112,9 @@ int stats_open() // { int j, k; + double timeStepDelta; //(5.1.015) + double logMaxTimeStep; //(5.1.015) + double logMinTimeStep; //(5.1.015) // --- set all pointers to NULL NodeStats = NULL; @@ -147,6 +156,8 @@ int stats_open() Subcatch[j].groundwater->stats.deepFlow = 0.0; Subcatch[j].groundwater->stats.evap = 0.0; Subcatch[j].groundwater->stats.maxFlow = 0.0; + Subcatch[j].groundwater->stats.finalUpperMoist = 0.0; //(5.1.015) + Subcatch[j].groundwater->stats.finalWaterTable = 0.0; // } } @@ -286,6 +297,20 @@ int stats_open() SysStats.avgTimeStep = 0.0; SysStats.avgStepCount = 0.0; SysStats.steadyStateCount = 0.0; + + // --- divide range between min and max routing time steps into //(5.1.015) + // equal intervals using a logarithmic scale // + logMaxTimeStep = log10(RouteStep); // + logMinTimeStep = log10(MinRouteStep); // + timeStepDelta = (logMaxTimeStep - logMinTimeStep) / (TIMELEVELS-1); // + SysStats.timeStepIntervals[0] = RouteStep; // + for (j = 1; j < TIMELEVELS; j++) // + { // + SysStats.timeStepIntervals[j] = // + pow(10., logMaxTimeStep - j * timeStepDelta); // + SysStats.timeStepCounts[j] = 0; // + } // + SysStats.timeStepIntervals[TIMELEVELS - 1] = MinRouteStep; // return 0; } @@ -446,6 +471,7 @@ void stats_updateFlowStats(double tStep, DateTime aDate, int stepCount, } // --- update count of times in steady state + ReportStepCount++; SysStats.steadyStateCount += steadyState; // --- update time step stats if not in steady state @@ -455,6 +481,15 @@ void stats_updateFlowStats(double tStep, DateTime aDate, int stepCount, if ( OldRoutingTime > 0 ) { SysStats.minTimeStep = MIN(SysStats.minTimeStep, tStep); + + // --- locate interval that logged time step falls in //(5.1.015) + // and update its count // + for (j = 1; j < TIMELEVELS; j++) // + if (tStep >= SysStats.timeStepIntervals[j]) // + { // + SysStats.timeStepCounts[j]++; // + break; // + } // } SysStats.avgTimeStep += tStep; SysStats.maxTimeStep = MAX(SysStats.maxTimeStep, tStep); @@ -703,6 +738,7 @@ void stats_findMaxStats() { int j; double x; + double stepCount = ReportStepCount - SysStats.steadyStateCount; //(5.1.015) // --- initialize max. stats arrays for (j=0; j 2 ) + if ( stepCount > 2 ) //(5.1.015) { for (j=0; j Start Date. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -337,7 +341,7 @@ void writeNodeDepths() fprintf(Frpt.file, " %-9s ", NodeTypeWords[Node[j].type]); getElapsedTime(NodeStats[j].maxDepthDate, &days, &hrs, &mins); fprintf(Frpt.file, "%7.2f %7.2f %7.2f %4d %02d:%02d %10.2f", - NodeStats[j].avgDepth / StepCount * UCF(LENGTH), + NodeStats[j].avgDepth / ReportStepCount * UCF(LENGTH), //(5.1.015) NodeStats[j].maxDepth * UCF(LENGTH), (NodeStats[j].maxDepth + Node[j].invertElev) * UCF(LENGTH), days, hrs, mins, NodeStats[j].maxRptDepth); @@ -538,7 +542,7 @@ void writeStorageVolumes() if ( Node[j].type != STORAGE ) continue; k = Node[j].subIndex; fprintf(Frpt.file, "\n %-20s", Node[j].ID); - avgVol = StorageStats[k].avgVol / StepCount; + avgVol = StorageStats[k].avgVol / (double)ReportStepCount; //(5.1.015) maxVol = StorageStats[k].maxVol; pctMaxVol = 0.0; pctAvgVol = 0.0; @@ -634,7 +638,7 @@ void writeOutfallLoads() // --- print node ID, flow freq., avg. flow, max. flow & flow vol. fprintf(Frpt.file, "\n %-20s", Node[j].ID); - x = 100.*flowCount/(double)StepCount; + x = 100.*flowCount/(double)ReportStepCount; //(5.1.015) fprintf(Frpt.file, "%7.2f", x); freqSum += x; if ( flowCount > 0 ) @@ -804,7 +808,7 @@ void writeFlowClass() for ( i=0; iinflow, subarea->depth); // --- limit infiltration rate by available void space in unsaturated @@ -1139,7 +1143,7 @@ void adjustSubareaParams(int i, int j) // Input: i = type of subarea being analyzed // j = index of current subcatchment being analyzed // Output adjusted values of module-level variables Dstore & Alpha -// Purpose: adjusts a subarea's depression storage and its pervious +// Purpose: adjusts a pervious subarea's depression storage and its //(5.1.015) // runoff coeff. by month of the year. // { @@ -1147,22 +1151,25 @@ void adjustSubareaParams(int i, int j) int m; // current month of the year double f; // adjustment factor - // --- depression storage adjustment - p = Subcatch[j].dStorePattern; - if (p >= 0 && Pattern[p].type == MONTHLY_PATTERN) - { - m = datetime_monthOfYear(getDateTime(OldRunoffTime)) - 1; - f = Pattern[p].factor[m]; - if (f >= 0.0) Dstore *= f; - } - - // --- pervious area roughness - p = Subcatch[j].nPervPattern; - if (i == PERV && p >= 0 && Pattern[p].type == MONTHLY_PATTERN) + if (i == PERV) //(5.1.015) { - m = datetime_monthOfYear(getDateTime(OldRunoffTime)) - 1; - f = Pattern[p].factor[m]; - if (f <= 0.0) Alpha = 0.0; - else Alpha /= f; - } + // --- depression storage adjustment + p = Subcatch[j].dStorePattern; + if (p >= 0 && Pattern[p].type == MONTHLY_PATTERN) + { + m = datetime_monthOfYear(getDateTime(OldRunoffTime)) - 1; + f = Pattern[p].factor[m]; + if (f >= 0.0) Dstore *= f; + } + + // --- roughness adjustment to runoff coeff. //(5.1.015) + p = Subcatch[j].nPervPattern; + if (p >= 0 && Pattern[p].type == MONTHLY_PATTERN) //(5.1.015) + { + m = datetime_monthOfYear(getDateTime(OldRunoffTime)) - 1; + f = Pattern[p].factor[m]; + if (f <= 0.0) Alpha = 0.0; + else Alpha /= f; + } + } } diff --git a/src/solver/swmm5.c b/src/solver/swmm5.c index 2917cb5e3..1ddf9f77c 100644 --- a/src/solver/swmm5.c +++ b/src/solver/swmm5.c @@ -8,6 +8,7 @@ // 08/01/16 (Build 5.1.011) // 03/14/17 (Build 5.1.012) // 05/10/18 (Build 5.1.013) +// 04/01/20 (Build 5.1.015) // Author: L. Rossman // // This is the main module of the computational engine for Version 5 of @@ -38,7 +39,9 @@ // Build 5.1.013: // - Support added for saving average results within a reporting period. // - SWMM engine now always compiled to a shared object library. -// +// +// Build 5.1.015: +// - Fixes bug in summary statistics when Report Start date > Start Date. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -306,7 +309,8 @@ int DLLEXPORT swmm_start(int saveResults) NewRunoffTime = 0.0; NewRoutingTime = 0.0; ReportTime = (double)(1000 * ReportStep); - StepCount = 0; + TotalStepCount = 0; //(5.1.015) + ReportStepCount = 0; //(5.1.015) NonConvergeCount = 0; IsStartedFlag = TRUE; @@ -440,7 +444,7 @@ int DLLEXPORT swmm_step(double* elapsedTime) #ifdef EXH // --- end of try loop; handle exception here - __except(xfilter(GetExceptionCode(), "swmm_step", ElapsedTime, StepCount)) + __except(xfilter(GetExceptionCode(), "swmm_step", ElapsedTime, TotalStepCount)) //(5.1.015) { ErrorCode = ERR_SYSTEM; } @@ -466,7 +470,7 @@ void execRouting() #endif { // --- determine when next routing time occurs - StepCount++; + TotalStepCount++; //(5.1.015) if ( !DoRouting ) routingStep = MIN(WetStep, ReportStep); else routingStep = routing_getRoutingStep(RouteModel, RouteStep); if ( routingStep <= 0.0 ) @@ -480,7 +484,7 @@ void execRouting() if ( nextRoutingTime > TotalDuration ) { routingStep = (TotalDuration - NewRoutingTime) / 1000.0; - routingStep = MAX(routingStep, 1./1000.0); + routingStep = MAX(routingStep, 1. / 1000.0); nextRoutingTime = TotalDuration; } @@ -504,7 +508,7 @@ void execRouting() #ifdef EXH // --- end of try loop; handle exception here __except(xfilter(GetExceptionCode(), "execRouting", - ElapsedTime, StepCount)) + ElapsedTime, TotalStepCount)) //(5.1.015) { ErrorCode = ERR_SYSTEM; return; @@ -816,7 +820,7 @@ void writecon(char *s) // Purpose: writes string of characters to the console. // { - fprintf(stdout,s); + fprintf(stdout,"%s",s); fflush(stdout); } diff --git a/src/solver/text.h b/src/solver/text.h index 53cc0817a..204f6d518 100644 --- a/src/solver/text.h +++ b/src/solver/text.h @@ -15,11 +15,18 @@ // 08/01/16 (Build 5.1.011) // 03/14/17 (Build 5.1.012) // 05/10/18 (Build 5.1.013) +// 03/01/20 (Build 5.1.014) +// 04/01/20 (Build 5.1.015) +// // Author: L. Rossman // // Text strings //----------------------------------------------------------------------------- +#ifndef TEXT_H +#define TEXT_H + + #define FMT01 \ "\tswmm5 \n" @@ -29,7 +36,7 @@ #define FMT06 "\n o Retrieving project data" #define FMT07 "\n o Writing output report" #define FMT08 \ - "\n EPA STORM WATER MANAGEMENT MODEL - VERSION 5.1 (Build 5.1.014)" //(5.1.014) + "\n EPA STORM WATER MANAGEMENT MODEL - VERSION 5.1 (Build 5.1.015)" //(5.1.015) #define FMT09 \ "\n --------------------------------------------------------------" #define FMT10 "\n" @@ -443,3 +450,6 @@ #define ws_GWF "[GWF" #define ws_ADJUST "[ADJUSTMENT" #define ws_EVENT "[EVENT" + + +#endif //TEXT_H diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4e5a06dbf..6849149e9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,18 +1,16 @@ # -# CMakeLists.txt - CMake configuration file for epanet/tests +# CMakeLists.txt - CMake configuration file for swmm-solver/tests +# +# Created: Mar 4, 2020 +# Updated: May 21, 2020 +# +# Author: Michael E. Tryby +# US EPA ORD/CESER # #Prep ourselves for compiling with boost -if(WIN32) - set(Boost_USE_STATIC_LIBS ON) -else() - set(Boost_USE_STATIC_LIBS OFF) - add_definitions(-DBOOST_ALL_DYN_LINK) -endif() - -find_package(Boost COMPONENTS unit_test_framework system thread filesystem) -include_directories (${Boost_INCLUDE_DIRS}) +include(../extern/boost.cmake) add_subdirectory(outfile) diff --git a/tests/Unit_Testing.md b/tests/Unit_Testing.md index 65869798d..c0b39a69a 100644 --- a/tests/Unit_Testing.md +++ b/tests/Unit_Testing.md @@ -16,10 +16,10 @@ Before the project can be built and tested the required dependencies must be installed. **Summary of Build Dependencies: Windows** - - Build - Build Tools for Visual Studio 2017 - CMake 3.13 + - ci-tools repository - Unit Test - Boost 1.67.0 (installed in default location "C:\\local") @@ -31,5 +31,5 @@ Before the project can be built and tested the required dependencies must be ins SWMM can be built and unit tests run with one simple command. ``` \> cd swmm -\swmm>tools\make.cmd /t +\swmm>ci-tools\windows\make.cmd /t ``` diff --git a/tools/Reg_Testing.md b/tools/Reg_Testing.md deleted file mode 100644 index b6d31afec..000000000 --- a/tools/Reg_Testing.md +++ /dev/null @@ -1,50 +0,0 @@ - - -## Regression Testing SWMM locally on Windows - - -### Dependencies - -Before the project can be built and tested the required dependencies must be installed. - -**Summary of Build Dependencies: Windows** - - - Build - - Build Tools for Visual Studio 2017 - - CMake 3.13 - - - Regression Test - - Python 3.6 64 bit - - curl - - git - - 7z - -Once Python is present, the following command installs the required packages for regression testing. -``` -\> cd swmm -\swmm>pip install -r tools\requirements-win.txt -``` - - -### Build - -EPANET can be built with one simple command. -``` -\swmm>tools\make.cmd -``` - - -### Regression Test - -This command runs regression tests for the local build and compares them to the latest benchmark. -``` -\swmm>tools\before-nrtest.cmd && tools\run-nrtest.cmd -``` diff --git a/tools/app-config.cmd b/tools/app-config.cmd deleted file mode 100644 index 09ce04daf..000000000 --- a/tools/app-config.cmd +++ /dev/null @@ -1,58 +0,0 @@ -:: -:: app-config.cmd - Generates nrtest app configuration file for SUT executable -:: -:: Date Created: 10/16/2019 -:: Date Modified: 10/17/2019 -:: -:: Author: Michael E. Tryby -:: US EPA - ORD/CESER -:: -:: Requires: -:: git -:: -:: Environment Variables: -:: PROJECT -:: -:: Arguments: -:: 1 - absolute path to test executable (valid path seperator for nrtest is "/") -:: 2 - (platform) -:: 3 - (build identifier for SUT) -:: - -@echo off -setlocal - - -:: check requirements -where git > nul -if %ERRORLEVEL% NEQ 0 ( echo "ERROR: git not installed" & exit /B 1 ) - -:: check environment -if not defined PROJECT ( echo "ERROR: PROJECT must be defined" & exit /B 1 ) - - -:: swmm target created by the cmake build script -set TEST_CMD=run%PROJECT%.exe - -:: remove quotes from path and convert backward to forward slash -set ABS_BUILD_PATH=%~1 -set ABS_BUILD_PATH=%ABS_BUILD_PATH:\=/% - -if [%2]==[] ( set "PLATFORM=unknown" -) else ( set "PLATFORM=%~2" ) - -if [%3]==[] ( set "BUILD_ID=unknown" -) else ( set "BUILD_ID=%~3" ) - -:: determine version -for /F "tokens=1" %%v in ( 'git rev-parse --short HEAD' ) do ( set "VERSION=%%v" ) -if not defined VERSION ( echo "ERROR: VERSION could not be determined" & exit /B 1 ) - - -echo { -echo "name" : "%PROJECT%", -echo "version" : "%VERSION%", -echo "description" : "%PLATFORM% %BUILD_ID%", -echo "setup_script" : "", -echo "exe" : "%ABS_BUILD_PATH%/%TEST_CMD%" -echo } diff --git a/tools/before-nrtest.cmd b/tools/before-nrtest.cmd deleted file mode 100644 index 6a7a36428..000000000 --- a/tools/before-nrtest.cmd +++ /dev/null @@ -1,116 +0,0 @@ -:: -:: before-test.cmd - Stages test and benchmark files for nrtest -:: -:: Date Created: 10/16/2019 -:: Date Updated: -:: -:: Author: Michael E. Tryby -:: US EPA - ORD/CESER -:: -:: Dependencies: -:: curl -:: 7z -:: -:: Environment Variables: -:: PROJECT -:: BUILD_HOME - defaults to "build" -:: PLATFORM -:: -:: Arguments: -:: 1 - (RELEASE_TAG) release tag for benchmark version (defaults to latest tag) -:: -:: Note: -:: Tests and benchmark files are stored in the project-nrtests repo. -:: This script retrieves them using a stable URL associated with a GitHub -:: release, stages the files, and sets up the environment for nrtest to run. -:: - -::@echo off - -:: set global default -set "TEST_HOME=nrtests" - -:: determine project directory -set "CUR_DIR=%CD%" -set "SCRIPT_HOME=%~dp0" -cd %SCRIPT_HOME% -cd .. - -setlocal - - -:: check that dependencies are installed -where curl > nul -if %ERRORLEVEL% neq 0 ( echo "ERROR: curl not installed" & exit /B 1 ) -where 7z > nul -if %ERRORLEVEL% neq 0 ( echo "ERROR: 7zip not installed" & exit /B 1 ) - - -:: set URL to github repo with test files -set "NRTESTS_URL=https://github.com/SWMM-Project/%PROJECT%-nrtestsuite" - - -:: if release tag isn't provided latest tag will be retrieved -if [%1] == [] (set "RELEASE_TAG=" -) else (set "RELEASE_TAG=%~1") - - -:: check env variables and apply defaults -if not defined PROJECT ( echo "ERROR: PROJECT must be defined" & exit /B 1 ) -if not defined BUILD_HOME ( echo "ERROR: BUILD_HOME must be defined" & exit /B 1 ) -if not defined PLATFORM ( echo "ERROR: PLATFORM must be defined" & exit /B 1 ) - - -echo INFO: Staging files for regression testing - - -:: determine latest tag in the tests repo -if [%RELEASE_TAG%] == [] ( - for /F delims^=^"^ tokens^=2 %%g in ('curl --silent %NRTESTS_URL%/releases/latest') do ( - set "RELEASE_TAG=%%~nxg" - ) -) - -if defined RELEASE_TAG ( - set "TESTFILES_URL=%NRTESTS_URL%/archive/%RELEASE_TAG%.zip" - set "BENCHFILES_URL=%NRTESTS_URL%/releases/download/%RELEASE_TAG%/benchmark-%PLATFORM%.zip" -) else ( echo ERROR: tag %RELEASE_TAG% is invalid & exit /B 1 ) - - -:: create a clean directory for staging regression tests -if exist %TEST_HOME% ( - rmdir /s /q %TEST_HOME% -) -mkdir %TEST_HOME% -if %ERRORLEVEL% NEQ 0 ( echo "ERROR: unable to make %TEST_HOME% dir" & exit /B 1 ) -cd %TEST_HOME% -if %ERRORLEVEL% NEQ 0 ( echo "ERROR: unable to cd %TEST_HOME% dir" & exit /B 1 ) - - -:: retrieve nrtest cases and benchmark results for regression testing -curl -fsSL -o nrtestfiles.zip %TESTFILES_URL% -curl -fsSL -o benchmark.zip %BENCHFILES_URL% - - -:: extract tests, scripts, benchmarks, and manifest -7z x nrtestfiles.zip * > nul -7z x benchmark.zip -obenchmark\ > nul -7z e benchmark.zip -o. manifest.json -r > nul - - -:: set up symlinks for tests directory -mklink /D .\tests .\%PROJECT%-nrtestsuite-%RELEASE_TAG:~1%\public > nul - - -endlocal - - -:: determine REF_BUILD_ID from manifest file -for /F delims^=^"^ tokens^=4 %%d in ( 'findstr %PLATFORM% %TEST_HOME%\manifest.json' ) do ( - for /F "tokens=2" %%r in ( 'echo %%d' ) do ( set "REF_BUILD_ID=%%r" ) -) -if not defined REF_BUILD_ID ( echo "ERROR: REF_BUILD_ID could not be determined" & exit /B 1 ) - - -:: return to users current directory -cd %CUR_DIR% diff --git a/tools/make.cmd b/tools/make.cmd deleted file mode 100644 index 3fabcc683..000000000 --- a/tools/make.cmd +++ /dev/null @@ -1,108 +0,0 @@ -:: -:: make.cmd - builds project -:: -:: Date Created: 10/15/2019 -:: Date Updated: -:: -:: Author: Michael E. Tryby -:: US EPA - ORD/CESER -:: -:: Requires: -:: Build Tools for Visual Studio download: -:: https://visualstudio.microsoft.com/downloads/ -:: -:: CMake download: -:: https://cmake.org/download/ -:: -:: Optional Arguments: -:: /g ("GENERATOR") defaults to "Visual Studio 15 2017" -:: /t builds and runs unit tests (requires Boost) -:: - - -::echo off - - -:: set global defaults -set "PROJECT=swmm" -set "BUILD_HOME=build" -set "PLATFORM=win32" - -:: determine project directory -set "CUR_DIR=%CD%" -set "SCRIPT_HOME=%~dp0" -cd %SCRIPT_HOME% -cd .. - -:: check for requirements -where cmake > nul -if %ERRORLEVEL% NEQ 0 ( echo "ERROR: cmake not installed" & exit /B 1 ) - - -setlocal EnableDelayedExpansion - - -echo INFO: Building %PROJECT% ... - - -:: set local defaults -set "GENERATOR=Visual Studio 15 2017" -set "TESTING=0" - -:: process arguments -:loop -if NOT [%1]==[] ( - if "%1"=="/g" ( - set "GENERATOR=%~2" - shift - ) - if "%1"=="/t" ( - set "TESTING=1" - ) - shift - goto :loop -) - - -:: if generator has changed delete the build folder -if exist %BUILD_HOME% ( - for /F "tokens=*" %%f in ( 'findstr CMAKE_GENERATOR:INTERNAL %BUILD_HOME%\CmakeCache.txt' ) do ( - for /F "delims=:= tokens=3" %%m in ( 'echo %%f' ) do ( - set CACHE_GEN=%%m - if not "!CACHE_GEN!" == "!GENERATOR!" ( rmdir /s /q %BUILD_HOME% & mkdir %BUILD_HOME% ) - ) - ) -) else ( - mkdir %BUILD_HOME%^ - & if %ERRORLEVEL% NEQ 0 ( echo "ERROR: unable to make %BUILD_HOME% dir" & exit /B 1 ) -) - - -:: perform the build -cd %BUILD_HOME% -if %ERRORLEVEL% NEQ 0 ( echo "ERROR: unable to cd %BUILD_HOME% dir" & exit /B 1 ) - -if %TESTING% EQU 1 ( - cmake -G"%GENERATOR%" -DBUILD_TESTS=ON -DBOOST_ROOT=C:\local\boost_1_67_0 ..^ - && cmake --build . --config Debug^ - & echo. && ctest -C Debug --output-on-failure -) else ( - cmake -G"%GENERATOR%" -DBUILD_TESTS=OFF ..^ - && cmake --build . --config Release --target install -) - - -endlocal - - -:: determine platform from CmakeCache.txt file -for /F "tokens=*" %%f in ( 'findstr CMAKE_SHARED_LINKER_FLAGS:STRING %BUILD_HOME%\CmakeCache.txt' ) do ( - for /F "delims=: tokens=3" %%m in ( 'echo %%f' ) do ( - if "%%m" == "X86" ( set "PLATFORM=win32" ) else if "%%m" == "x64" ( set "PLATFORM=win64" ) - ) -) -if not defined PLATFORM ( echo "ERROR: PLATFORM could not be determined" & exit /B 1 ) - - -:: return to users current dir -:: cd %CUR_DIR% diff --git a/tools/requirements-win.txt b/tools/requirements-win.txt deleted file mode 100644 index 0f18bb0ee..000000000 --- a/tools/requirements-win.txt +++ /dev/null @@ -1,22 +0,0 @@ -# -# requirements-win.txt - Python requirements for running nrtest on Win32/Win64 -# -# Date Created: 10/17/2019 -# Date Updated: 11/26/2019 -# -# Author: Michael E. Tryby -# US EPA ORD/CESER -# -# Useful for configuring a python environment to run nrtests on swmm. -# -# usage: -# pip install -r tools/requirements-win.txt -# - -nrtest - --f https://github.com/michaeltryby/swmm-python/releases/download/v0.3.0-dev3/swmm.output-0.4.0.dev3-cp36-cp36m-win_amd64.whl -swmm.output - --f https://github.com/michaeltryby/swmm-python/releases/download/v0.3.0-dev3/nrtest_swmm-0.5.0-py3-none-any.whl -nrtest-swmm diff --git a/tools/run-nrtests.cmd b/tools/run-nrtests.cmd deleted file mode 100644 index c51d96c80..000000000 --- a/tools/run-nrtests.cmd +++ /dev/null @@ -1,114 +0,0 @@ -:: -:: run_nrtest.cmd - Runs numerical regression test -:: -:: Date Created: 10/16/2019 -:: Date Updated: -:: -:: Author: Michael E. Tryby -:: US EPA - ORD/CESER -:: -:: Dependencies: -:: python -m pip install -r requirements.txt -:: -:: Environment Variables: -:: PROJECT -:: BUILD_HOME - relative path -:: TEST_HOME - relative path -:: PLATFORM -:: REF_BUILD_ID -:: -:: Arguments: -:: 1 - (SUT_VERSION) - optional argument -:: 2 - (SUT_BUILD_ID) - optional argument -:: - -::@echo off -setlocal EnableDelayedExpansion - - -:: Check that required environment variables are set -if not defined PROJECT ( echo "ERROR: PROJECT must be defined" & exit /B 1 ) -if not defined BUILD_HOME ( echo "ERROR: BUILD_HOME must be defined" & exit /B 1 ) -if not defined TEST_HOME ( echo "ERROR: TEST_HOME must be defined" & exit /B 1 ) -if not defined PLATFORM ( echo "ERROR: PLATFORM must be defined" & exit /B 1 ) -if not defined REF_BUILD_ID ( echo "ERROR: REF_BUILD_ID must be defined" & exit /B 1 ) - - -:: determine project directory -set "CUR_DIR=%CD%" -set "SCRIPT_HOME=%~dp0" -cd %SCRIPT_HOME% -pushd .. -set PROJ_DIR=%CD% -popd - - -cd %PROJ_DIR%\%TEST_HOME% - -:: Process optional arguments -if [%1]==[] (set "SUT_VERSION=unknown" -) else ( set "SUT_VERSION=%~1" ) - -if [%2]==[] ( set "SUT_BUILD_ID=local" -) else ( set "SUT_BUILD_ID=%~2" ) - - -:: check if app config file exists -if not exist apps\%PROJECT%-%SUT_BUILD_ID%.json ( - mkdir apps - call %SCRIPT_HOME%\app-config.cmd %PROJ_DIR%\%BUILD_HOME%\bin\Release^ - %PLATFORM% %SUT_BUILD_ID% %SUT_VERSION% > apps\%PROJECT%-%SUT_BUILD_ID%.json -) - - -:: recursively build test list -set TESTS= -for /F "tokens=*" %%T in ('dir /b /s /a:d tests') do ( - set FULL_PATH=%%T - set TESTS=!TESTS! !FULL_PATH:*%TEST_HOME%\=! -) - - -:: determine location of python Scripts folder -for /F "tokens=*" %%G in ('where python.exe') do ( - set PYTHON_DIR=%%~dpG - goto break_loop_1 -) -:break_loop_1 -set "NRTEST_SCRIPT_PATH=%PYTHON_DIR%Scripts" - - -:: build nrtest execute command -set NRTEST_EXECUTE_CMD=python.exe %NRTEST_SCRIPT_PATH%\nrtest execute -set TEST_APP_PATH=apps\%PROJECT%-%SUT_BUILD_ID%.json -set TEST_OUTPUT_PATH=benchmark\%PROJECT%-%SUT_BUILD_ID% - -:: build nrtest compare command -set NRTEST_COMPARE_CMD=python.exe %NRTEST_SCRIPT_PATH%\nrtest compare -set REF_OUTPUT_PATH=benchmark\%PROJECT%-%REF_BUILD_ID% -set RTOL_VALUE=0.01 -set ATOL_VALUE=1.E-6 - -:: change current directory to test suite -::cd %TEST_HOME% - -:: if present clean test benchmark results -if exist %TEST_OUTPUT_PATH% ( - rmdir /s /q %TEST_OUTPUT_PATH% -) - -:: perform nrtest execute -echo INFO: Creating SUT %SUT_BUILD_ID% artifacts -set NRTEST_COMMAND=%NRTEST_EXECUTE_CMD% %TEST_APP_PATH% %TESTS% -o %TEST_OUTPUT_PATH% -:: if there is an error exit the script with error value 1 -%NRTEST_COMMAND% || exit /B 1 - -echo. - -:: perform nrtest compare -echo INFO: Comparing SUT artifacts to REF %REF_BUILD_ID% -set NRTEST_COMMAND=%NRTEST_COMPARE_CMD% %TEST_OUTPUT_PATH% %REF_OUTPUT_PATH% --rtol %RTOL_VALUE% --atol %ATOL_VALUE% -o benchmark\receipt.json -%NRTEST_COMMAND% - -:: Return user to their current dir -cd %CUR_DIR%