diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index c224b9e7d..a23d17dc4 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-2022, ubuntu-20.04, macos-10.15] + os: [windows-2022, ubuntu-20.04, macos-12] requirements: [requirements-swmm.txt] include: - os: windows-2022 @@ -58,9 +58,9 @@ jobs: shell: bash working-directory: ./ci-tools/linux - - os: macos-10.15 + - os: macos-12 sys_pkgs: brew install libomp #boost - boost_platform_version: 10.15 + boost_platform_version: 12 boost_toolsit: clang build_unit_test: make.zsh -t -g "Xcode" build_reg_test: make.zsh -g "Xcode" @@ -94,7 +94,7 @@ jobs: - name: Clone ci-tools repo uses: actions/checkout@v3 with: - repository: OpenWaterAnalytics/ci-tools + repository: pyswmm/ci-tools ref: master path: ci-tools @@ -111,11 +111,11 @@ jobs: # install boost on mac and linux - name: Install required system packages on mac and linux run: ${{ matrix.sys_pkgs }} - if: ${{ runner.os == 'macOS' }} + if: ${{ runner.os == 'macOS' }} # boost takes a while to install on windows, so try to cache - name: Install boost - # if: ${{runner.os == 'Windows'}} + # if: ${{runner.os == 'Windows'}} uses: MarkusJx/install-boost@v2.4.4 id: install-boost with: @@ -123,7 +123,7 @@ jobs: # A list of supported versions can be found here: # https://github.com/MarkusJx/prebuilt-boost/blob/main/versions-manifest.json boost_version: 1.81.0 - link: shared + link: shared # OPTIONAL: Specify a custon install location # boost_install_dir: C:\some_directory # OPTIONAL: Specify a platform version @@ -143,8 +143,8 @@ jobs: - name: Before reg test env: - NRTESTS_URL: https://github.com/OpenWaterAnalytics/swmm-nrtestsuite - BENCHMARK_TAG: v3.0.1 + NRTESTS_URL: https://github.com/pyswmm/swmm-nrtestsuite + BENCHMARK_TAG: v3.1.0 run: ./${{ matrix.before_reg_test }} ${{ env.BENCHMARK_TAG }} - name: Run reg test diff --git a/CMakeLists.txt b/CMakeLists.txt index b7ebd6629..10969a2b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ endif() project(swmm-solver - VERSION 5.2.3 + VERSION 5.2.4 LANGUAGES C CXX ) diff --git a/extern/version.h.in b/extern/version.h.in index 6fcc6a895..2a0b7e622 100644 --- a/extern/version.h.in +++ b/extern/version.h.in @@ -29,6 +29,7 @@ #define COMPILER_VERSION "@CMAKE_C_COMPILER_VERSION@" #define BUILD_ID "@BUILD_ID@" +#define TOOLKIT_VERSION "1.0" static inline int get_version_legacy() { \ return VERSION_MAJOR * 10000 + VERSION_MINOR * 1000 + VERSION_PATCH; \ diff --git a/src/solver/consts.h b/src/solver/consts.h index 3cf490793..394b5e2e8 100644 --- a/src/solver/consts.h +++ b/src/solver/consts.h @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 02/12/23 (Build 5.2.3) +// Date: 07/15/23 (Build 5.2.4) // Author: L. Rossman // // Various Constants @@ -17,7 +17,7 @@ //------------------ // OWA Version string stored in version.h -// #define VERSION 52003 +// #define VERSION 52004 #define MAGICNUMBER 516114522 #define EOFMARK 0x1A // Use 0x04 for UNIX systems #define MAXTITLE 3 // Max. # title lines diff --git a/src/solver/dwflow.c b/src/solver/dwflow.c index d6484fe57..25b2b874a 100644 --- a/src/solver/dwflow.c +++ b/src/solver/dwflow.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 08/01/22 (Build 5.2.1) +// Date: 06/12/23 (Build 5.2.4) // Author: L. Rossman // M. Tryby (EPA) // R. Dickinson (CDM) @@ -26,6 +26,8 @@ // (qOld) in call to link_getLossRate. // Build 5.2.1: // - Implements the new option to skip checking for normal flow limitations. +// Build 5.2.4: +// - Arguments to function link_getLossRate changed. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -231,7 +233,7 @@ void dwflow_findConduitFlow(int j, int steps, double omega, double dt) } // --- 6. term for evap and seepage losses per unit length - dq6 = link_getLossRate(j, qLast) * 2.5 * dt * v / link_getLength(j); + dq6 = link_getLossRate(j, DW, qLast, dt) * 2.5 * dt * v / link_getLength(j); // --- combine terms to find new conduit flow denom = 1.0 + dq1 + dq5; diff --git a/src/solver/dynwave.c b/src/solver/dynwave.c index ac302e849..85968e2a9 100644 --- a/src/solver/dynwave.c +++ b/src/solver/dynwave.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 11/01/21 (Build 5.2.0) +// Date: 07/13/23 (Build 5.2.4) // Author: L. Rossman // M. Tryby (EPA) // R. Dickinson (CDM) @@ -44,6 +44,9 @@ // - Roll back the 5.1.014 change for conduit losses in updateNodeFlows(). // Build 5.2.0: // - Support added for reporting most frequent non-converging links. +// Build 5.2.4: +// - Conduit evap+seepage outflow split evenly between outflow from +// conduit's upstream and non-outfall downstream nodes. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -129,7 +132,7 @@ void dynwave_init() " Not enough memory for dynamic wave routing."); return; } - + // --- initialize node surface areas & crown elev. for (i = 0; i < Nobjects[NODE]; i++ ) { @@ -144,6 +147,7 @@ void dynwave_init() j = Link[i].node1; z = Node[j].invertElev + Link[i].offset1 + Link[i].xsect.yFull; Node[j].crownElev = MAX(Node[j].crownElev, z); + j = Link[i].node2; z = Node[j].invertElev + Link[i].offset2 + Link[i].xsect.yFull; Node[j].crownElev = MAX(Node[j].crownElev, z); @@ -534,29 +538,39 @@ void updateNodeFlows(int i) int n1 = Link[i].node1; int n2 = Link[i].node2; double q = Link[i].newFlow; - double uniformLossRate = 0.0; - - // --- compute any uniform seepage loss from a conduit - if ( Link[i].type == CONDUIT ) - { - k = Link[i].subIndex; - uniformLossRate = Conduit[k].evapLossRate + Conduit[k].seepLossRate; - barrels = Conduit[k].barrels; - uniformLossRate *= barrels; - } + double conduitLossRate = 0.0; // --- update total inflow & outflow at upstream/downstream nodes if ( q >= 0.0 ) { - Node[n1].outflow += q + uniformLossRate; + Node[n1].outflow += q; Node[n2].inflow += q; } else { Node[n1].inflow -= q; - Node[n2].outflow -= q - uniformLossRate; + Node[n2].outflow -= q; } - + + // --- add any uniform evap & seepage loss from conduit link + if ( Link[i].type == CONDUIT ) + { + k = Link[i].subIndex; + barrels = Conduit[k].barrels; + conduitLossRate = (Conduit[k].evapLossRate + Conduit[k].seepLossRate) * + barrels; + if (conduitLossRate > 0.0) + { + // --- outfall nodes do not share evap & seepage losses + if (Node[n1].type != OUTFALL && Node[n2].type != OUTFALL) + conduitLossRate /= 2.0; + if (Node[n1].type != OUTFALL) + Node[n1].outflow += conduitLossRate; + if (Node[n2].type != OUTFALL) + Node[n2].outflow += conduitLossRate; + } + } + // --- add surf. area contributions to upstream/downstream nodes Xnode[Link[i].node1].newSurfArea += Link[i].surfArea1 * barrels; Xnode[Link[i].node2].newSurfArea += Link[i].surfArea2 * barrels; @@ -585,7 +599,7 @@ int findNodeDepths(double dt) // { int i; - double yOld; // previous node depth (ft) + double yOld = 0.0; // previous node depth (ft) // --- compute outfall depths based on flow in connecting link for ( i = 0; i < Nobjects[LINK]; i++ ) link_setOutfallDepth(i); @@ -654,12 +668,11 @@ void setNodeDepth(int i, double dt) Node[i].overflow = 0.0; surfArea = Xnode[i].newSurfArea; surfArea = MAX(surfArea, MinSurfArea); - + // --- determine average net flow volume into node over the time step dQ = Node[i].inflow - Node[i].outflow; dV = 0.5 * (Node[i].oldNetInflow + dQ) * dt; - // --- determine if node is EXTRAN surcharged if (SurchargeMethod == EXTRAN) { diff --git a/src/solver/flowrout.c b/src/solver/flowrout.c index f296c3fb0..73f5f67d4 100644 --- a/src/solver/flowrout.c +++ b/src/solver/flowrout.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 05/02/22 (Build 5.2.1) +// Date: 06/12/23 (Build 5.2.4) // Author: L. Rossman // M. Tryby (EPA) // @@ -27,6 +27,8 @@ // Build 5.2.1: // - For storage routing, after convergence the reported depth is now // based on the last volume found rather than the next trial depth. +// Build 5.2.4: +// - Arguments to link_getLossRate changed. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -767,7 +769,7 @@ int steadyflow_execute(int j, double* qin, double* qout, double tStep) else { // --- adjust flow for evap and infil losses - q -= link_getLossRate(j, q); + q -= link_getLossRate(j, SF, q, tStep); // --- flow can't exceed full flow if ( q > Link[j].qFull ) diff --git a/src/solver/funcs.h b/src/solver/funcs.h index 21af0d54d..642318ebd 100644 --- a/src/solver/funcs.h +++ b/src/solver/funcs.h @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 11/01/21 (Build 5.2.0) +// Date: 06/12/23 (Build 5.2.4) // Author: L. Rossman // M. Tryby (EPA) // @@ -29,6 +29,8 @@ // - Support added for named variables & math expressions in control rules. // - Support added for tracking a gage's prior n-hour rainfall total. // - Refactored external inflow code. +// Build 5.2.4: +// - Additional arguments added to function link_getLossRate. //----------------------------------------------------------------------------- #ifndef FUNCS_H @@ -425,7 +427,7 @@ double link_getYnorm(int link, double q); double link_getVelocity(int link, double q, double y); double link_getFroude(int link, double v, double y); double link_getPower(int link); -double link_getLossRate(int link, double q); +double link_getLossRate(int link, int routeModel, double q, double tstep); char link_getFullState(double a1, double a2, double aFull); void link_getResults(int link, double wt, float x[]); diff --git a/src/solver/include/toolkit.h b/src/solver/include/toolkit.h index 339dbd09a..540fce63a 100644 --- a/src/solver/include/toolkit.h +++ b/src/solver/include/toolkit.h @@ -99,6 +99,22 @@ EXPORT_TOOLKIT int swmm_getSimulationAnalysisSetting(SM_SimOption type, int *val */ EXPORT_TOOLKIT int swmm_getSimulationParam(SM_SimSetting type, double *value); +/** + @brief Set Simulation Analysis Setting + @param type Option code (see @ref SM_SimSetting) + @param value Option value + @return Error code + */ +EXPORT_TOOLKIT int swmm_setSimulationParam(SM_SimSetting type, double value); + +/** + @brief Use/override a hotstart file before the simulation starts. + @param type The property type code (see @ref SM_HotStart) + @param hsfile The file name of the hot start file that the user would like to use. + @return Error code +*/ +EXPORT_TOOLKIT int swmm_hotstart(SM_HotStart type, const char *hsfile); + /** @brief Gets Object Count @param type Option code (see @ref SM_ObjectType) diff --git a/src/solver/include/toolkit_enums.h b/src/solver/include/toolkit_enums.h index 651743b37..89bf2ce14 100644 --- a/src/solver/include/toolkit_enums.h +++ b/src/solver/include/toolkit_enums.h @@ -89,9 +89,16 @@ typedef enum { SM_QUALERROR = 10, /**< Quality routing error */ SM_HEADTOL = 11, /**< DW routing head tolerance (ft) */ SM_SYSFLOWTOL = 12, /**< Tolerance for steady system flow */ - SM_LATFLOWTOL = 13 /**< Tolerance for steady nodal inflow */ + SM_LATFLOWTOL = 13, /**< Tolerance for steady nodal inflow */ + SM_THREADS = 14 /**< Number of Threads for this process */ } SM_SimSetting; +/// Hot Start File Manager +typedef enum { + SM_HOTSTART_USE = 0, /**< Use Hotstart File */ + SM_HOTSTART_SAVE = 1 /**< Save Hotstart File */ +} SM_HotStart; + /// Node property codes typedef enum { SM_INVERTEL = 0, /**< Invert Elevation */ diff --git a/src/solver/include/toolkit_error.h b/src/solver/include/toolkit_error.h index 3f58128ec..29ead3b3f 100644 --- a/src/solver/include/toolkit_error.h +++ b/src/solver/include/toolkit_error.h @@ -14,6 +14,7 @@ enum ToolkitErrorType { ERR_TKAPI_UNDEFINED_LID = 2010, ERR_TKAPI_MEMORY = 2011, ERR_TKAPI_NO_INLET = 2012, + ERR_TKAPI_SIM_RUNNING = 2013, TKMAXERRMSG = 3000 }; diff --git a/src/solver/include/toolkit_errors.txt b/src/solver/include/toolkit_errors.txt index 4a9dd1f8e..1349f5a4b 100644 --- a/src/solver/include/toolkit_errors.txt +++ b/src/solver/include/toolkit_errors.txt @@ -13,3 +13,4 @@ ERR(2009, "\n API Key Error: Invalid Lid Unit Index") ERR(2010, "\n API Key Error: Undefined Subcatchment Lid") ERR(2011, "\n API Key Error: No memory allocated for return value") ERR(2012, "\n API Key Error: Specified link is not assigned an inlet") +ERR(2013, "\n API Key Error: Simulation Already Started or Running.") diff --git a/src/solver/inlet.c b/src/solver/inlet.c index c44ae9fcb..f3aa180a8 100644 --- a/src/solver/inlet.c +++ b/src/solver/inlet.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 10/08/22 (Build 5.2.2) +// Date: 07/13/23 (Build 5.2.4) // Author: L. Rossman // // Street/Channel Inlet Functions @@ -18,6 +18,10 @@ // - Substitutes the constant BIG for HUGE. // Build 5.2.2: // - Additional statistics added to Street Flow Summary table. +// Build 5.2.4: +// - Fixed expression for equivalent gutter slope in getCurbInletCapture. +// - Corrected sign in equation for effective head in a curb inlet +// with an inclined throat opening in getCurbOrificeFlow. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -1444,7 +1448,7 @@ double getCurbInletCapture(double Q, double L) // Input: Q = flow rate seen by inlet (cfs) // L = length of inlet opening (ft) // Output: returns captured flow rate (cfs) -// Purpose: finds the flow captured by an on-sag inlet. +// Purpose: finds the flow captured by an on-grade curb opening inlet. // { double Se = Sx, // equivalent gutter slope @@ -1460,7 +1464,7 @@ double getCurbInletCapture(double Q, double L) { Sr = Sw / Sx; Eo = getEo(Sr, T-W, W); - Se = Sx + Sw * Eo; //HEC-22 Eq(4-24) + Se = Sx + (a/W) * Eo; //HEC-22 Eq(4-24) } // --- opening length for full capture @@ -1741,7 +1745,7 @@ double getCurbOrificeFlow(double di, double h, double L, int throatAngle) if (throatAngle == HORIZONTAL_THROAT) d = di - h / 2.0; else if (throatAngle == INCLINED_THROAT) - d = di + (h / 2.0) * 0.7071; + d = di - (h / 2.0) * 0.7071; return 0.67 * h * L * sqrt(2.0 * 32.16 * d); //HEC-22 Eq(4-31a) } diff --git a/src/solver/kinwave.c b/src/solver/kinwave.c index b137e4ce9..cafa2e346 100644 --- a/src/solver/kinwave.c +++ b/src/solver/kinwave.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 11/01/21 (Build 5.2.0) +// Date: 06/12/23 (Build 5.2.4) // Author: L. Rossman // M. Tryby (EPA) // @@ -15,6 +15,8 @@ // - Conduit inflow passed to function that computes conduit losses. // Build 5.1.014: // - Arguments to function link_getLossRate changed. +// Build 5.2.4: +// - Arguments to function link_getLossRate changed again. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -100,7 +102,7 @@ int kinwave_execute(int j, double* qinflow, double* qoutflow, double tStep) qin = (*qinflow) / Conduit[k].barrels / Qfull; // --- compute evaporation and infiltration loss rate - q3 = link_getLossRate(j, qin*Qfull) / Qfull; + q3 = link_getLossRate(j, KW, qin*Qfull, tStep) / Qfull; // --- normalize previous areas a1 = Conduit[k].a1 / Afull; diff --git a/src/solver/lid.c b/src/solver/lid.c index a6e82e16c..63de8920e 100644 --- a/src/solver/lid.c +++ b/src/solver/lid.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 02/10/23 (Build 5.2.3) +// Date: 07/13/23 (Build 5.2.4) // Author: L. Rossman // // This module handles all data processing involving LID (Low Impact @@ -70,6 +70,8 @@ // - Covered property added to RAIN_BARREL parameters // Build 5.2.3 // - Fixed double counting of initial water volume in green roof drain mat. +// Build 5.2.4 +// - Fixed test for invalid data in readDrainData function. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -786,7 +788,7 @@ int readDrainData(int j, char* toks[], int ntoks) for (i = 0; i < 6; i++) x[i] = 0.0; for (i = 2; i < 8; i++) { - if ( (ntoks > i) && (! getDouble(toks[i], &x[i-2]) || x[i-2]) < 0.0 ) + if ( (ntoks > i) && (! getDouble(toks[i], &x[i-2]) || x[i-2] < 0.0) ) return error_setInpError(ERR_NUMBER, toks[i]); } @@ -1084,6 +1086,7 @@ void validateLidProc(int j) // moved clogging factor conversion logic to readStorageData and readPavementData // in 14d2e62e9a6baad89f6cd2dc0c55907e1d2289b2 to allow multiple calls to validateLidProc // in toolkit.c + //... for certain LID types, immediate overflow of excess surface water // occurs if either the surface roughness or slope is zero LidProcs[j].surface.canOverflow = TRUE; diff --git a/src/solver/lidproc.c b/src/solver/lidproc.c index a74fd67f7..d0876fd15 100644 --- a/src/solver/lidproc.c +++ b/src/solver/lidproc.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 11/01/21 (Build 5.2.0) +// Date: 07/13/23 (Build 5.2.4) // Author: L. Rossman // // This module computes the hydrologic performance of an LID (Low Impact @@ -53,6 +53,11 @@ // - Fixed failure to account for effect of Impervious Surface Fraction on // pavement permeability for Permeable Pavement LID // - Fixed units conversion for pavement depth in detailed report file. +// Build 5.2.4: +// - Modified flux limits in biocellFluxRates, pavementFluxRates and +// trenchFluxRates. +// - Corrected head calculation in getStorageDrainRate when unit has both +// a soil and pavement layer. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -700,61 +705,64 @@ void biocellFluxRates(double x[], double f[]) SurfaceInfil = MIN(SurfaceInfil, maxRate); } - //... storage & soil layers are full - else if ( soilTheta >= soilPorosity && storageDepth >= storageThickness ) + else { - //... limiting rate is smaller of soil perc and storage outflow - maxRate = StorageExfil + StorageDrain; - if ( SoilPerc < maxRate ) + //... storage & soil layers are full + if ( soilTheta >= soilPorosity && storageDepth >= storageThickness ) { - maxRate = SoilPerc; - if ( maxRate > StorageExfil ) StorageDrain = maxRate - StorageExfil; - else + //... limiting rate is smaller of soil perc and storage outflow + maxRate = StorageExfil + StorageDrain; + if ( SoilPerc < maxRate ) { - StorageExfil = maxRate; - StorageDrain = 0.0; + maxRate = SoilPerc; + if ( maxRate > StorageExfil ) StorageDrain = maxRate - StorageExfil; + else + { + StorageExfil = maxRate; + StorageDrain = 0.0; + } } - } - else SoilPerc = maxRate; - - //... apply limiting rate to surface infil. - SurfaceInfil = MIN(SurfaceInfil, maxRate); - } + else SoilPerc = maxRate; - //... either layer not full - else if ( storageThickness > 0.0 ) - { - //... limit storage exfiltration by available storage volume - maxRate = SoilPerc - StorageEvap + storageDepth*storageVoidFrac/Tstep; - StorageExfil = MIN(StorageExfil, maxRate); - StorageExfil = MAX(StorageExfil, 0.0); + //... apply limiting rate to surface infil. + SurfaceInfil = MIN(SurfaceInfil, maxRate); + } - //... limit underdrain flow by volume above drain offset - if ( StorageDrain > 0.0 ) + //... either layer not full + else { - maxRate = -StorageExfil - StorageEvap; - if ( storageDepth >= storageThickness) maxRate += SoilPerc; - if ( theLidProc->drain.offset <= storageDepth ) + //... limit storage exfiltration by available storage volume + maxRate = SoilPerc - StorageEvap + storageDepth*storageVoidFrac/Tstep; + StorageExfil = MIN(StorageExfil, maxRate); + StorageExfil = MAX(StorageExfil, 0.0); + + //... limit underdrain flow by volume above drain offset + if ( StorageDrain > 0.0 ) { - maxRate += (storageDepth - theLidProc->drain.offset) * - storageVoidFrac/Tstep; + maxRate = -StorageExfil - StorageEvap; + if ( storageDepth >= storageThickness) maxRate += SoilPerc; + if ( theLidProc->drain.offset <= storageDepth ) + { + maxRate += (storageDepth - theLidProc->drain.offset) * + storageVoidFrac/Tstep; + } + maxRate = MAX(maxRate, 0.0); + StorageDrain = MIN(StorageDrain, maxRate); } - maxRate = MAX(maxRate, 0.0); - StorageDrain = MIN(StorageDrain, maxRate); - } - - //... limit soil perc by unused storage volume - maxRate = StorageExfil + StorageDrain + StorageEvap + - (storageThickness - storageDepth) * - storageVoidFrac/Tstep; - SoilPerc = MIN(SoilPerc, maxRate); + + //... limit soil perc by unused storage volume + maxRate = StorageExfil + StorageDrain + StorageEvap + + (storageThickness - storageDepth) * + storageVoidFrac/Tstep; + SoilPerc = MIN(SoilPerc, maxRate); - //... limit surface infil. by unused soil volume - maxRate = (soilPorosity - soilTheta) * soilThickness / Tstep + - SoilPerc + SoilEvap; - SurfaceInfil = MIN(SurfaceInfil, maxRate); + //... limit surface infil. by unused soil volume + maxRate = (soilPorosity - soilTheta) * soilThickness / Tstep + + SoilPerc + SoilEvap; + SurfaceInfil = MIN(SurfaceInfil, maxRate); + } } - + //... find surface layer outflow rate SurfaceOutflow = getSurfaceOutflowRate(surfaceDepth); @@ -849,7 +857,7 @@ void trenchFluxRates(double x[], double f[]) SurfaceOutflow = getSurfaceOutflowRate(surfaceDepth); // ... find net fluxes for each layer - f[SURF] = SurfaceInflow - SurfaceEvap - StorageInflow - SurfaceOutflow / + f[SURF] = (SurfaceInflow - SurfaceEvap - StorageInflow - SurfaceOutflow) / theLidProc->surface.voidFrac;; f[STOR] = (StorageInflow - StorageEvap - StorageExfil - StorageDrain) / theLidProc->storage.voidFrac; @@ -1012,6 +1020,7 @@ void pavementFluxRates(double x[], double f[]) StorageExfil = MIN(StorageExfil, SoilPerc); StorageDrain = SoilPerc - StorageExfil; } + PavePerc = MIN(PavePerc, SoilPerc); //... limit surface infil. by available pavement volume availVolume = (paveThickness - paveDepth) * paveVoidFrac; @@ -1027,6 +1036,8 @@ void pavementFluxRates(double x[], double f[]) PavePerc = MIN(PavePerc, SoilPerc); SoilPerc = PavePerc; SurfaceInfil = MIN(SurfaceInfil,PavePerc); + maxRate = MAX(StorageVolume / Tstep + SoilPerc - StorageEvap, 0.0); + StorageExfil = MIN(StorageExfil, maxRate); } //... no adjoining layers are full @@ -1416,7 +1427,11 @@ double getStorageDrainRate(double storageDepth, double soilTheta, // depth in layer above it if ( soilTheta >= soilPorosity ) { - if ( paveThickness > 0.0 ) head += paveDepth; + if ( paveThickness > 0.0 ) + { + head += paveDepth; + if ( paveDepth >= paveThickness ) head += surfaceDepth; + } else head += surfaceDepth; } } @@ -1424,7 +1439,7 @@ double getStorageDrainRate(double storageDepth, double soilTheta, // --- no soil layer so increase head by water level in pavement // layer and possibly surface layer - if ( paveThickness > 0.0 ) + else if ( paveThickness > 0.0 ) { head += paveDepth; if ( paveDepth >= paveThickness ) head += surfaceDepth; diff --git a/src/solver/link.c b/src/solver/link.c index 052a030b9..c8e035f4c 100644 --- a/src/solver/link.c +++ b/src/solver/link.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 10/29/22 (Build 5.2.2) +// Date: 06/12/23 (Build 5.2.4) // Author: L. Rossman // M. Tryby (EPA) // @@ -46,6 +46,8 @@ // - Warning no longer issued when conduit elevation drop < MIN_DELTA_Z. // Build 5.2.2: // - Warning for conduit elevation drop < MIN_DELTA_Z restored. +// Build 5.2.4: +// - Conduit evap+seepage loss under DW routing limited by conduit volume. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -99,7 +101,8 @@ static double conduit_getLength(int j); static double conduit_getLengthFactor(int j, int k, double roughness); static double conduit_getSlope(int j); static double conduit_getInflow(int j); -static double conduit_getLossRate(int j, double q); +static double conduit_getLossRate(int j, int routeModel, double q, + double tstep); static int pump_readParams(int j, int k, char* tok[], int ntoks); static void pump_validate(int j, int k); @@ -887,9 +890,10 @@ double link_getPower(int j) //============================================================================= -double link_getLossRate(int j, double q) +double link_getLossRate(int j, int routeModel, double q, double tstep) // // Input: j = link index +// routeModel = flow routing model type // q = flow rate (ft3/sec) // tstep = time step (sec) // Output: returns uniform loss rate in link (ft3/sec) @@ -897,7 +901,8 @@ double link_getLossRate(int j, double q) // evaporation and seepage. // { - if ( Link[j].type == CONDUIT ) return conduit_getLossRate(j, q); + if ( Link[j].type == CONDUIT ) + return conduit_getLossRate(j, routeModel, q, tstep); else return 0.0; } @@ -1326,10 +1331,12 @@ double conduit_getInflow(int j) //============================================================================= -double conduit_getLossRate(int j, double q) +double conduit_getLossRate(int j, int routeModel, double q, double tstep) // // Input: j = link index +// routeModel = type of flow routing model // q = current link flow rate (cfs) +// tstep = current routing time step (sec) // Output: returns rate of evaporation & seepage losses (ft3/sec) // Purpose: computes volumetric rate of water evaporation & seepage // from a conduit (per barrel). @@ -1338,7 +1345,7 @@ double conduit_getLossRate(int j, double q) TXsect *xsect; double depth = 0.5 * (Link[j].oldDepth + Link[j].newDepth); double length; - double topWidth; + double width, topWidth; double evapLossRate = 0.0, seepLossRate = 0.0, totalLossRate = 0.0; @@ -1359,19 +1366,25 @@ double conduit_getLossRate(int j, double q) if ( Link[j].seepRate > 0.0 ) { // limit depth to depth at max width - if ( depth >= xsect->ywMax ) depth = xsect->ywMax; + if (xsect->type == RECT_CLOSED) width = xsect->wMax; + else + { + if ( depth >= xsect->ywMax ) depth = xsect->ywMax; + width = xsect_getWofY(xsect, depth); + } // compute seepage loss rate across length of conduit - seepLossRate = Link[j].seepRate * xsect_getWofY(xsect, depth) * - length; + seepLossRate = Link[j].seepRate * width * length; seepLossRate *= Adjust.hydconFactor; } // --- compute total loss rate totalLossRate = evapLossRate + seepLossRate; - // --- total loss rate cannot exceed flow rate - q = ABS(q); + // --- limit total loss rate to current volume for DW routing + // or current link flow rate otherwise + if (routeModel == DW) q = Link[j].newVolume / tstep; + else q = ABS(q); if (totalLossRate > q) { evapLossRate = evapLossRate * q / totalLossRate; diff --git a/src/solver/project.c b/src/solver/project.c index 55a0866c8..7d65c0f9d 100644 --- a/src/solver/project.c +++ b/src/solver/project.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 11/21/22 (Build 5.2.2) +// Date: 07/17/23 (Build 5.2.4) // Author: L. Rossman // // Project management functions. @@ -52,6 +52,10 @@ // Build 5.2.2: // - Default number of threads changed from OMP max. number to 1 // to be consistent with User Manual. +// Build 5.2.4: +// - Default Inertial Damping changed from SOME to PARTIAL_DAMPING. +// - Default CourantFactor changed from 0 (fixed routing time step) +// - to 0.75 (variable time step) //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -850,12 +854,12 @@ void setDefaults() SurchargeMethod = EXTRAN; // Use EXTRAN method for surcharging CrownCutoff = 0.96; // Fractional pipe crown cutoff AllowPonding = FALSE; // No ponding at nodes - InertDamping = SOME; // Partial inertial damping + InertDamping = PARTIAL_DAMPING; // Partial inertial damping NormalFlowLtd = BOTH; // Default normal flow limitation ForceMainEqn = H_W; // Hazen-Williams eqn. for force mains LinkOffsets = DEPTH_OFFSET; // Use depth for link offsets LengtheningStep = 0; // No lengthening of conduits - CourantFactor = 0.0; // No variable time step + CourantFactor = 0.75; // Variable time step reduced to 75% MinSurfArea = 0.0; // Force use of default min. surface area MinSlope = 0.0; // No user supplied minimum conduit slope SkipSteadyState = FALSE; // Do flow routing in steady state periods diff --git a/src/solver/report.c b/src/solver/report.c index dd1a3c9d4..18c58e11d 100644 --- a/src/solver/report.c +++ b/src/solver/report.c @@ -227,9 +227,10 @@ void report_writeLogo() // // OWA manages model version differently from EPA SWMM. { + fprintf(Frpt.file, FMT08); sprintf(Msg, \ - "\n OWA STORM WATER MANAGEMENT MODEL - VERSION v%s (OWA %.10s)", - VERSION, BUILD_ID); + "\n PYSWMM TOOLKIT API - VERSION v%s (%.10s)", + TOOLKIT_VERSION, BUILD_ID); fprintf(Frpt.file, "%s", Msg); fprintf(Frpt.file, FMT09); diff --git a/src/solver/street.c b/src/solver/street.c index fd05451b7..0c55d9115 100644 --- a/src/solver/street.c +++ b/src/solver/street.c @@ -3,11 +3,14 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 11/01/21 (Build 5.2.0) +// Date: 07/13/23 (Build 5.2.4) // Author: L. Rossman // // Street Cross-Section Functions // +// Build 5.2.4: +// - Fixed incorrect index used to retrieve street backing parameters +// in street_readParams. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -106,8 +109,8 @@ int street_readParams(char* tok[], int ntoks) // --- read street backing parameters if (ntoks > 8) { - if (!getDouble(tok[8], &x[8]) || x[k] < 0.0) - return error_setInpError(ERR_NUMBER, tok[k]); + if (!getDouble(tok[8], &x[8]) || x[8] < 0.0) + return error_setInpError(ERR_NUMBER, tok[8]); if (x[8] > 0.0) { if (ntoks < 11) return error_setInpError(ERR_ITEMS, ""); diff --git a/src/solver/surfqual.c b/src/solver/surfqual.c index 858fcbee5..64593a012 100644 --- a/src/solver/surfqual.c +++ b/src/solver/surfqual.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 11/01/21 (Build 5.2.0) +// Date: 07/14/23 (Build 5.2.4) // Author: L. Rossman // // Subcatchment water quality functions. @@ -16,6 +16,10 @@ // - Support for separate accounting of LID drain flows included. // Build 5.1.014: // - Fixed bug in computing effective BMP removal by LIDs. +// Build 5.2.4: +// - Set low runoff flow concentrations to zero before computing runoff +// mass loads rather than after so that they match wet weather mass +// inflows reported for conveyance system nodes. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -255,7 +259,7 @@ void surfqual_getWashoff(int j, double runoff, double tStep) { // --- convert washoff load to a concentration cOut = 0.0; - if ( vOut1 > 0.0 ) cOut = OutflowLoad[p] / vOut1; + if ( vOut1 > 0.0 && hasOutflow ) cOut = OutflowLoad[p] / vOut1; // --- assign any difference between pre- and post-LID // subcatchment outflow loads to BMP removal @@ -281,7 +285,6 @@ void surfqual_getWashoff(int j, double runoff, double tStep) } // --- save new washoff concentration - if ( !hasOutflow ) cOut = 0.0; Subcatch[j].newQual[p] = cOut / LperFT3; // OWA Addition --- update surface buildup loads (in lbs or kg) diff --git a/src/solver/text.h b/src/solver/text.h index 353296b8e..4bb46f059 100644 --- a/src/solver/text.h +++ b/src/solver/text.h @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 12/22/22 (Build 5.2.3) +// Date: 07/15/23 (Build 5.2.4) // Author: L. Rossman // // Text strings @@ -25,7 +25,7 @@ #define FMT03 " There are errors.\n" #define FMT04 " There are warnings.\n" #define FMT08 \ - "\n EPA STORM WATER MANAGEMENT MODEL - VERSION 5.2 (Build 5.2.3)" + "\n EPA STORM WATER MANAGEMENT MODEL - VERSION 5.2 (Build 5.2.4)" #define FMT09 \ "\n ------------------------------------------------------------" #define FMT10 "\n" diff --git a/src/solver/toolkit.c b/src/solver/toolkit.c index 83571a97e..09d088672 100644 --- a/src/solver/toolkit.c +++ b/src/solver/toolkit.c @@ -24,6 +24,16 @@ #include "swmm5.h" #include "toolkit.h" +// Protect against lack of compiler support for OpenMP +#if defined(_OPENMP) +#include +int alt_omp_get_max_threads(void) +{ + return omp_get_max_threads(); +} +#else + int alt_omp_get_max_threads(void) { return 1;} +#endif // Function Declarations for API int massbal_getRoutingTotal(SM_RoutingTotals **routingTot); @@ -405,6 +415,8 @@ EXPORT_TOOLKIT int swmm_getSimulationParam(SM_SimSetting type, double *value) case SM_SYSFLOWTOL: *value = SysFlowTol; break; // Tolerance for steady nodal inflow case SM_LATFLOWTOL: *value = LatFlowTol; break; + // Number of Threads (if OpenMP enabled) + case SM_THREADS: *value = NumThreads; break; // Type not available default: error_code = ERR_TKAPI_OUTBOUNDS; break; } @@ -412,6 +424,112 @@ EXPORT_TOOLKIT int swmm_getSimulationParam(SM_SimSetting type, double *value) return error_code; } +EXPORT_TOOLKIT int swmm_setSimulationParam(SM_SimSetting type, double value) +/// +/// Input: type = SM_SimSetting +/// Simulation Parameter +/// Returns: error code +/// Purpose: Set simulation analysis parameter (limited support) +{ + int error_code = 0; + + // Check if Open + if(swmm_IsOpenFlag() == FALSE) + { + error_code = ERR_TKAPI_INPUTNOTOPEN; + } + // Check if Simulation is Running + else if(swmm_IsStartedFlag() == TRUE) + { + error_code = ERR_TKAPI_SIM_NRUNNING; + } + else + { + switch(type) + { + case SM_THREADS: + { + // --- adjust number of parallel threads to be used + if ( (int)value <= 0 ) NumThreads = 1; + else NumThreads = MIN((int)value, alt_omp_get_max_threads()); + if ( Nobjects[LINK] < 4 * NumThreads ) NumThreads = 1; + break; + } + default: error_code = ERR_TKAPI_OUTBOUNDS; break; + } + } + return error_code; +} + +EXPORT_TOOLKIT int swmm_hotstart(SM_HotStart type, const char *hsfile) +/// +/// Input: type = Hotstart option USE/SAVE (SM_HotStart) +/// hotstart = file ID name (able to overwrite) +/// Return API Error +/// Purpose: Allows selecting a HSF to use or save +{ + int error_code = 0; + // Check if Open + if(swmm_IsOpenFlag() == FALSE) + { + error_code = ERR_TKAPI_INPUTNOTOPEN; + } + // Check if Simulation is Started + else if (swmm_IsStartedFlag() == TRUE && type == SM_HOTSTART_USE) + { + error_code = ERR_TKAPI_SIM_RUNNING; + } + // Check if Simulation is NOT started + else if (swmm_IsStartedFlag() == FALSE && type == SM_HOTSTART_SAVE) + { + error_code = ERR_TKAPI_SIM_NRUNNING; + } + else + { + switch(type) + { + case SM_HOTSTART_USE: + { + // Fhotstart1 is the file to to be read + char fl_name[MAXFNAME]; + sstrncpy(fl_name, hsfile, MAXFNAME); + Fhotstart1.mode = USE_FILE; + sstrncpy(Fhotstart1.name, fl_name, MAXFNAME); + break; + } + case SM_HOTSTART_SAVE: + { + // Storing Existing INP set HSFs + TFile tmpHotstart1 = Fhotstart1; + TFile tmpHotstart2 = Fhotstart2; + int _fl1_info = Fhotstart1.mode; + int _fl2_info = Fhotstart2.mode; + // Create info for New HSF + Fhotstart1.mode = NO_FILE; + Fhotstart2.mode = SAVE_FILE; + sstrncpy(Fhotstart2.name, hsfile, MAXFNAME); + // Saving Data + if (hotstart_open()) + { + hotstart_close(); + // Replacing INP set HSFs + Fhotstart2 = tmpHotstart2; + Fhotstart1 = tmpHotstart1; + Fhotstart1.mode = _fl1_info; + Fhotstart2.mode = _fl2_info; + } + else + { + error_code = ERR_HOTSTART_FILE_OPEN; + } + break; + } + default: error_code = ERR_TKAPI_OUTBOUNDS; break; + } + } + return error_code; +} + EXPORT_TOOLKIT int swmm_countObjects(SM_ObjectType type, int *count) /// /// Input: type = object type (Based on SM_ObjectType enum) diff --git a/src/solver/transect.c b/src/solver/transect.c index 831ba017f..6ebd25558 100644 --- a/src/solver/transect.c +++ b/src/solver/transect.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 11/01/21 (Build 5.2.0) +// Date: 07/13/23 (Build 5.2.4) // Author: L. Rossman // // Geometry processing for irregular cross-section transects. @@ -12,6 +12,8 @@ // ============== // Build 5.2.0: // - Function added to create a transect for a Street cross-section. +// Build 5.2.4: +// - Corrected street transect points in transect_createStreetTransect. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -610,8 +612,8 @@ void transect_createStreetTransect(TStreet* street) w2 = street->gutterWidth; w3 = street->width; w4 = w3 - w2; - y3 = street->gutterDepression; - y1 = street->curbHeight + y3; + y3 = street->gutterDepression + street->slope * w2; + y1 = street->curbHeight + street->gutterDepression; ymax = street->backSlope * street->backWidth + y1; y4 = y3 + street->slope * w4; ymax = MAX(ymax, y4); diff --git a/tests/outfile/test_output.cpp b/tests/outfile/test_output.cpp index 1d44400ad..2494bd3c1 100644 --- a/tests/outfile/test_output.cpp +++ b/tests/outfile/test_output.cpp @@ -268,6 +268,26 @@ BOOST_FIXTURE_TEST_CASE(test_getSubcatchSeries, Fixture) { BOOST_CHECK(check_cdd_float(test_vec, ref_vec, 3)); } +BOOST_FIXTURE_TEST_CASE(test_getSystemSeries, Fixture) { + error = SMO_getSystemSeries(p_handle, SMO_runoff_flow, 0, 10, &array, + &array_dim); + BOOST_REQUIRE(error == 0); + + const int ref_dim = 10; + float ref_array[ref_dim] = { + 0.0f, 6.216825f, 13.030855f, 24.252975f, 14.172027f, 4.1949716f, + 0.322329f, 0.056010f, 0.024938f, 0.012474f}; + + std::vector ref_vec; + ref_vec.assign(ref_array, ref_array + 10); + + std::vector test_vec; + test_vec.assign(array, array + array_dim); + + BOOST_CHECK(check_cdd_float(test_vec, ref_vec, 3)); +} + + BOOST_FIXTURE_TEST_CASE(test_getSubcatchResult, Fixture) { error = SMO_getSubcatchResult(p_handle, 1, 1, &array, &array_dim); BOOST_REQUIRE(error == 0); diff --git a/tests/solver/CMakeLists.txt b/tests/solver/CMakeLists.txt index 021832fbb..0a1bdfe1a 100644 --- a/tests/solver/CMakeLists.txt +++ b/tests/solver/CMakeLists.txt @@ -38,6 +38,7 @@ set(solver_test_srcs test_solver.cpp test_stats.cpp test_inlets_and_drains.cpp + test_toolkit_hotstart.cpp # ADD NEW TEST SUITES TO EXISTING TOOLKIT TEST MODULE ) diff --git a/tests/solver/data/hotstart/Simulation1.inp b/tests/solver/data/hotstart/Simulation1.inp new file mode 100644 index 000000000..3f2639fc3 --- /dev/null +++ b/tests/solver/data/hotstart/Simulation1.inp @@ -0,0 +1,217 @@ +[TITLE] +;;Project Title/Notes +Example 1 + +[OPTIONS] +;;Option Value +FLOW_UNITS CFS +INFILTRATION HORTON +FLOW_ROUTING DYNWAVE +LINK_OFFSETS DEPTH +MIN_SLOPE 0 +ALLOW_PONDING NO +SKIP_STEADY_STATE NO + +START_DATE 01/01/1998 +START_TIME 00:00:00 +REPORT_START_DATE 01/01/1998 +REPORT_START_TIME 00:00:00 +END_DATE 01/02/1998 +END_TIME 12:00:00 +SWEEP_START 1/1 +SWEEP_END 12/31 +DRY_DAYS 5 +REPORT_STEP 01:00:00 +WET_STEP 00:15:00 +DRY_STEP 01:00:00 +ROUTING_STEP 0:01:00 + +INERTIAL_DAMPING PARTIAL +NORMAL_FLOW_LIMITED BOTH +FORCE_MAIN_EQUATION H-W +VARIABLE_STEP 0.75 +LENGTHENING_STEP 0 +MIN_SURFAREA 0 +MAX_TRIALS 0 +HEAD_TOLERANCE 0 +SYS_FLOW_TOL 5 +LAT_FLOW_TOL 5 +;MINIMUM_STEP 0.5 +THREADS 1 + +[FILES] +SAVE HOTSTART INFILE_Simulation1.hsf + +[EVAPORATION] +;;Data Source Parameters +;;-------------- ---------------- +CONSTANT 0.0 +DRY_ONLY NO + +[RAINGAGES] +;;Name Format Interval SCF Source +;;-------------- --------- ------ ------ ---------- +RG1 INTENSITY 1:00 1.0 TIMESERIES TS1 + +[SUBCATCHMENTS] +;;Name Rain Gage Outlet Area %Imperv Width %Slope CurbLen SnowPack +;;-------------- ---------------- ---------------- -------- -------- -------- -------- -------- ---------------- +1 RG1 9 10 50 500 0.01 0 +2 RG1 10 10 50 500 0.01 0 +3 RG1 13 5 50 500 0.01 0 +4 RG1 22 5 50 500 0.01 0 +5 RG1 15 15 50 500 0.01 0 +6 RG1 23 12 10 500 0.01 0 +7 RG1 19 4 10 500 0.01 0 +8 RG1 18 10 10 500 0.01 0 + +[SUBAREAS] +;;Subcatchment N-Imperv N-Perv S-Imperv S-Perv PctZero RouteTo PctRouted +;;-------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- +1 0.001 0.10 0.05 0.05 25 OUTLET +2 0.001 0.10 0.05 0.05 25 OUTLET +3 0.001 0.10 0.05 0.05 25 OUTLET +4 0.001 0.10 0.05 0.05 25 OUTLET +5 0.001 0.10 0.05 0.05 25 OUTLET +6 0.001 0.10 0.05 0.05 25 OUTLET +7 0.001 0.10 0.05 0.05 25 OUTLET +8 0.001 0.10 0.05 0.05 25 OUTLET + +[INFILTRATION] +;;Subcatchment MaxRate MinRate Decay DryTime MaxInfil +;;-------------- ---------- ---------- ---------- ---------- ---------- +1 0.35 0.25 4.14 0.50 0 +2 0.7 0.3 4.14 0.50 0 +3 0.7 0.3 4.14 0.50 0 +4 0.7 0.3 4.14 0.50 0 +5 0.7 0.3 4.14 0.50 0 +6 0.7 0.3 4.14 0.50 0 +7 0.7 0.3 4.14 0.50 0 +8 0.7 0.3 4.14 0.50 0 + +[JUNCTIONS] +;;Name Elevation MaxDepth InitDepth SurDepth Aponded +;;-------------- ---------- ---------- ---------- ---------- ---------- +9 1000 3 0 0 0 +10 995 3 0 0 0 +13 995 3 0 0 0 +14 990 3 0 0 0 +15 987 3 0 0 0 +16 985 3 0 0 0 +17 980 3 0 0 0 +19 1010 3 0 0 0 +20 1005 3 0 0 0 +21 990 3 0 0 0 +22 987 3 0 0 0 +23 990 3 0 0 0 +24 984 3 0 0 0 + +[OUTFALLS] +;;Name Elevation Type Stage Data Gated Route To +;;-------------- ---------- ---------- ---------------- -------- ---------------- +18 975 FREE NO + +[CONDUITS] +;;Name From Node To Node Length Roughness InOffset OutOffset InitFlow MaxFlow +;;-------------- ---------------- ---------------- ---------- ---------- ---------- ---------- ---------- ---------- +1 9 10 400 0.01 0 0 0 0 +4 19 20 200 0.01 0 0 0 0 +5 20 21 200 0.01 0 0 0 0 +6 10 21 400 0.01 0 1 0 0 +7 21 22 300 0.01 1 1 0 0 +8 22 16 300 0.01 0 0 0 0 +10 17 18 400 0.01 0 0 0 0 +11 13 14 400 0.01 0 0 0 0 +12 14 15 400 0.01 0 0 0 0 +13 15 16 400 0.01 0 0 0 0 +14 23 24 400 0.01 0 0 0 0 +15 16 24 100 0.01 0 0 0 0 +16 24 17 400 0.01 0 0 0 0 + +[XSECTIONS] +;;Link Shape Geom1 Geom2 Geom3 Geom4 Barrels Culvert +;;-------------- ------------ ---------------- ---------- ---------- ---------- ---------- ---------- +1 CIRCULAR 1.5 0 0 0 1 +4 CIRCULAR 1 0 0 0 1 +5 CIRCULAR 1 0 0 0 1 +6 CIRCULAR 1 0 0 0 1 +7 CIRCULAR 2 0 0 0 1 +8 CIRCULAR 2 0 0 0 1 +10 CIRCULAR 2 0 0 0 1 +11 CIRCULAR 1.5 0 0 0 1 +12 CIRCULAR 1.5 0 0 0 1 +13 CIRCULAR 1.5 0 0 0 1 +14 CIRCULAR 1 0 0 0 1 +15 CIRCULAR 2 0 0 0 1 +16 CIRCULAR 2 0 0 0 1 + +[POLLUTANTS] +;;Name Units Crain Cgw Crdii Kdecay SnowOnly Co-Pollutant Co-Frac Cdwf Cinit +;;-------------- ------ ---------- ---------- ---------- ---------- ---------- ---------------- ---------- ---------- ---------- +TSS MG/L 0.0 0.0 0 0.0 NO * 0.0 0 0 +Lead UG/L 0.0 0.0 0 0.0 NO TSS 0.2 0 0 + +[LANDUSES] +;; Sweeping Fraction Last +;;Name Interval Available Swept +;;-------------- ---------- ---------- ---------- +Residential +Undeveloped + +[COVERAGES] +;;Subcatchment Land Use Percent +;;-------------- ---------------- ---------- +1 Residential 100.00 +2 Residential 50.00 +2 Undeveloped 50.00 +3 Residential 100.00 +4 Residential 50.00 +4 Undeveloped 50.00 +5 Residential 100.00 +6 Undeveloped 100.00 +7 Undeveloped 100.00 +8 Undeveloped 100.00 + +[LOADINGS] +;;Subcatchment Pollutant Buildup +;;-------------- ---------------- ---------- + +[BUILDUP] +;;Land Use Pollutant Function Coeff1 Coeff2 Coeff3 Per Unit +;;-------------- ---------------- ---------- ---------- ---------- ---------- ---------- +Residential TSS SAT 50 0 2 AREA +Residential Lead NONE 0 0 0 AREA +Undeveloped TSS SAT 100 0 3 AREA +Undeveloped Lead NONE 0 0 0 AREA + +[WASHOFF] +;;Land Use Pollutant Function Coeff1 Coeff2 SweepRmvl BmpRmvl +;;-------------- ---------------- ---------- ---------- ---------- ---------- ---------- +Residential TSS EXP 0.1 1 0 0 +Residential Lead EMC 0 0 0 0 +Undeveloped TSS EXP 0.1 0.7 0 0 +Undeveloped Lead EMC 0 0 0 0 + +[TIMESERIES] +;;Name Date Time Value +;;-------------- ---------- ---------- ---------- +;RAINFALL +TS1 0:00 0.0 +TS1 1:00 0.25 +TS1 2:00 0.5 +TS1 3:00 0.8 +TS1 4:00 0.4 +TS1 5:00 0.1 +TS1 6:00 0.0 +TS1 27:00 0.0 +TS1 28:00 0.4 +TS1 29:00 0.2 +TS1 30:00 0.0 + +[REPORT] +;;Reporting Options +INPUT NO +CONTROLS NO +SUBCATCHMENTS ALL +NODES ALL +LINKS ALL diff --git a/tests/solver/data/hotstart/Simulation1_use_hot_start.inp b/tests/solver/data/hotstart/Simulation1_use_hot_start.inp new file mode 100644 index 000000000..d3aba0d0b --- /dev/null +++ b/tests/solver/data/hotstart/Simulation1_use_hot_start.inp @@ -0,0 +1,215 @@ +[TITLE] +;;Project Title/Notes +Example 1 + +[OPTIONS] +;;Option Value +FLOW_UNITS CFS +INFILTRATION HORTON +FLOW_ROUTING DYNWAVE +LINK_OFFSETS DEPTH +MIN_SLOPE 0 +ALLOW_PONDING NO +SKIP_STEADY_STATE NO + +START_DATE 01/01/1998 +START_TIME 00:00:00 +REPORT_START_DATE 01/01/1998 +REPORT_START_TIME 00:00:00 +END_DATE 01/02/1998 +END_TIME 12:00:00 +SWEEP_START 1/1 +SWEEP_END 12/31 +DRY_DAYS 5 +REPORT_STEP 01:00:00 +WET_STEP 00:15:00 +DRY_STEP 01:00:00 +ROUTING_STEP 0:00:01 + +INERTIAL_DAMPING PARTIAL +NORMAL_FLOW_LIMITED BOTH +FORCE_MAIN_EQUATION H-W +VARIABLE_STEP 0.75 +LENGTHENING_STEP 0 +MIN_SURFAREA 0 +MAX_TRIALS 0 +HEAD_TOLERANCE 0 +SYS_FLOW_TOL 5 +LAT_FLOW_TOL 5 +;MINIMUM_STEP 0.5 +THREADS 1 + + +[EVAPORATION] +;;Data Source Parameters +;;-------------- ---------------- +CONSTANT 0.0 +DRY_ONLY NO + +[RAINGAGES] +;;Name Format Interval SCF Source +;;-------------- --------- ------ ------ ---------- +RG1 INTENSITY 1:00 1.0 TIMESERIES TS1 + +[SUBCATCHMENTS] +;;Name Rain Gage Outlet Area %Imperv Width %Slope CurbLen SnowPack +;;-------------- ---------------- ---------------- -------- -------- -------- -------- -------- ---------------- +1 RG1 9 10 50 500 0.01 0 +2 RG1 10 10 50 500 0.01 0 +3 RG1 13 5 50 500 0.01 0 +4 RG1 22 5 50 500 0.01 0 +5 RG1 15 15 50 500 0.01 0 +6 RG1 23 12 10 500 0.01 0 +7 RG1 19 4 10 500 0.01 0 +8 RG1 18 10 10 500 0.01 0 + +[SUBAREAS] +;;Subcatchment N-Imperv N-Perv S-Imperv S-Perv PctZero RouteTo PctRouted +;;-------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- +1 0.001 0.10 0.05 0.05 25 OUTLET +2 0.001 0.10 0.05 0.05 25 OUTLET +3 0.001 0.10 0.05 0.05 25 OUTLET +4 0.001 0.10 0.05 0.05 25 OUTLET +5 0.001 0.10 0.05 0.05 25 OUTLET +6 0.001 0.10 0.05 0.05 25 OUTLET +7 0.001 0.10 0.05 0.05 25 OUTLET +8 0.001 0.10 0.05 0.05 25 OUTLET + +[INFILTRATION] +;;Subcatchment MaxRate MinRate Decay DryTime MaxInfil +;;-------------- ---------- ---------- ---------- ---------- ---------- +1 0.35 0.25 4.14 0.50 0 +2 0.7 0.3 4.14 0.50 0 +3 0.7 0.3 4.14 0.50 0 +4 0.7 0.3 4.14 0.50 0 +5 0.7 0.3 4.14 0.50 0 +6 0.7 0.3 4.14 0.50 0 +7 0.7 0.3 4.14 0.50 0 +8 0.7 0.3 4.14 0.50 0 + +[JUNCTIONS] +;;Name Elevation MaxDepth InitDepth SurDepth Aponded +;;-------------- ---------- ---------- ---------- ---------- ---------- +9 1000 3 0 0 0 +10 995 3 0 0 0 +13 995 3 0 0 0 +14 990 3 0 0 0 +15 987 3 0 0 0 +16 985 3 0 0 0 +17 980 3 0 0 0 +19 1010 3 0 0 0 +20 1005 3 0 0 0 +21 990 3 0 0 0 +22 987 3 0 0 0 +23 990 3 0 0 0 +24 984 3 0 0 0 + +[OUTFALLS] +;;Name Elevation Type Stage Data Gated Route To +;;-------------- ---------- ---------- ---------------- -------- ---------------- +18 975 FREE NO + +[CONDUITS] +;;Name From Node To Node Length Roughness InOffset OutOffset InitFlow MaxFlow +;;-------------- ---------------- ---------------- ---------- ---------- ---------- ---------- ---------- ---------- +1 9 10 400 0.01 0 0 0 0 +4 19 20 200 0.01 0 0 0 0 +5 20 21 200 0.01 0 0 0 0 +6 10 21 400 0.01 0 1 0 0 +7 21 22 300 0.01 1 1 0 0 +8 22 16 300 0.01 0 0 0 0 +10 17 18 400 0.01 0 0 0 0 +11 13 14 400 0.01 0 0 0 0 +12 14 15 400 0.01 0 0 0 0 +13 15 16 400 0.01 0 0 0 0 +14 23 24 400 0.01 0 0 0 0 +15 16 24 100 0.01 0 0 0 0 +16 24 17 400 0.01 0 0 0 0 + +[XSECTIONS] +;;Link Shape Geom1 Geom2 Geom3 Geom4 Barrels Culvert +;;-------------- ------------ ---------------- ---------- ---------- ---------- ---------- ---------- +1 CIRCULAR 1.5 0 0 0 1 +4 CIRCULAR 1 0 0 0 1 +5 CIRCULAR 1 0 0 0 1 +6 CIRCULAR 1 0 0 0 1 +7 CIRCULAR 2 0 0 0 1 +8 CIRCULAR 2 0 0 0 1 +10 CIRCULAR 2 0 0 0 1 +11 CIRCULAR 1.5 0 0 0 1 +12 CIRCULAR 1.5 0 0 0 1 +13 CIRCULAR 1.5 0 0 0 1 +14 CIRCULAR 1 0 0 0 1 +15 CIRCULAR 2 0 0 0 1 +16 CIRCULAR 2 0 0 0 1 + +[POLLUTANTS] +;;Name Units Crain Cgw Crdii Kdecay SnowOnly Co-Pollutant Co-Frac Cdwf Cinit +;;-------------- ------ ---------- ---------- ---------- ---------- ---------- ---------------- ---------- ---------- ---------- +TSS MG/L 0.0 0.0 0 0.0 NO * 0.0 0 0 +Lead UG/L 0.0 0.0 0 0.0 NO TSS 0.2 0 0 + +[LANDUSES] +;; Sweeping Fraction Last +;;Name Interval Available Swept +;;-------------- ---------- ---------- ---------- +Residential +Undeveloped + +[COVERAGES] +;;Subcatchment Land Use Percent +;;-------------- ---------------- ---------- +1 Residential 100.00 +2 Residential 50.00 +2 Undeveloped 50.00 +3 Residential 100.00 +4 Residential 50.00 +4 Undeveloped 50.00 +5 Residential 100.00 +6 Undeveloped 100.00 +7 Undeveloped 100.00 +8 Undeveloped 100.00 + +[LOADINGS] +;;Subcatchment Pollutant Buildup +;;-------------- ---------------- ---------- + +[BUILDUP] +;;Land Use Pollutant Function Coeff1 Coeff2 Coeff3 Per Unit +;;-------------- ---------------- ---------- ---------- ---------- ---------- ---------- +Residential TSS SAT 50 0 2 AREA +Residential Lead NONE 0 0 0 AREA +Undeveloped TSS SAT 100 0 3 AREA +Undeveloped Lead NONE 0 0 0 AREA + +[WASHOFF] +;;Land Use Pollutant Function Coeff1 Coeff2 SweepRmvl BmpRmvl +;;-------------- ---------------- ---------- ---------- ---------- ---------- ---------- +Residential TSS EXP 0.1 1 0 0 +Residential Lead EMC 0 0 0 0 +Undeveloped TSS EXP 0.1 0.7 0 0 +Undeveloped Lead EMC 0 0 0 0 + +[TIMESERIES] +;;Name Date Time Value +;;-------------- ---------- ---------- ---------- +;RAINFALL +TS1 0:00 0.0 +TS1 1:00 0.25 +TS1 2:00 0.5 +TS1 3:00 0.8 +TS1 4:00 0.4 +TS1 5:00 0.1 +TS1 6:00 0.0 +TS1 27:00 0.0 +TS1 28:00 0.4 +TS1 29:00 0.2 +TS1 30:00 0.0 + +[REPORT] +;;Reporting Options +INPUT NO +CONTROLS NO +SUBCATCHMENTS ALL +NODES ALL +LINKS ALL diff --git a/tests/solver/data/hotstart/Simulation2.inp b/tests/solver/data/hotstart/Simulation2.inp new file mode 100644 index 000000000..f6af08f88 --- /dev/null +++ b/tests/solver/data/hotstart/Simulation2.inp @@ -0,0 +1,217 @@ +[TITLE] +;;Project Title/Notes +Example 1 + +[OPTIONS] +;;Option Value +FLOW_UNITS CFS +INFILTRATION HORTON +FLOW_ROUTING DYNWAVE +LINK_OFFSETS DEPTH +MIN_SLOPE 0 +ALLOW_PONDING NO +SKIP_STEADY_STATE NO + +START_DATE 01/01/1998 +START_TIME 00:00:00 +REPORT_START_DATE 01/01/1998 +REPORT_START_TIME 00:00:00 +END_DATE 01/02/1998 +END_TIME 12:00:00 +SWEEP_START 1/1 +SWEEP_END 12/31 +DRY_DAYS 5 +REPORT_STEP 01:00:00 +WET_STEP 00:15:00 +DRY_STEP 01:00:00 +ROUTING_STEP 0:01:00 + +INERTIAL_DAMPING PARTIAL +NORMAL_FLOW_LIMITED BOTH +FORCE_MAIN_EQUATION H-W +VARIABLE_STEP 0.75 +LENGTHENING_STEP 0 +MIN_SURFAREA 0 +MAX_TRIALS 0 +HEAD_TOLERANCE 0 +SYS_FLOW_TOL 5 +LAT_FLOW_TOL 5 +;MINIMUM_STEP 0.5 +THREADS 1 + +[FILES] +SAVE HOTSTART INFILE_Simulation2.hsf + +[EVAPORATION] +;;Data Source Parameters +;;-------------- ---------------- +CONSTANT 0.0 +DRY_ONLY NO + +[RAINGAGES] +;;Name Format Interval SCF Source +;;-------------- --------- ------ ------ ---------- +RG1 INTENSITY 1:00 1.0 TIMESERIES TS1 + +[SUBCATCHMENTS] +;;Name Rain Gage Outlet Area %Imperv Width %Slope CurbLen SnowPack +;;-------------- ---------------- ---------------- -------- -------- -------- -------- -------- ---------------- +1 RG1 9 10 50 500 0.01 0 +2 RG1 10 10 50 500 0.01 0 +3 RG1 13 5 50 500 0.01 0 +4 RG1 22 5 50 500 0.01 0 +5 RG1 15 15 50 500 0.01 0 +6 RG1 23 12 10 500 0.01 0 +7 RG1 19 4 10 500 0.01 0 +8 RG1 18 10 10 500 0.01 0 + +[SUBAREAS] +;;Subcatchment N-Imperv N-Perv S-Imperv S-Perv PctZero RouteTo PctRouted +;;-------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- +1 0.001 0.10 0.05 0.05 25 OUTLET +2 0.001 0.10 0.05 0.05 25 OUTLET +3 0.001 0.10 0.05 0.05 25 OUTLET +4 0.001 0.10 0.05 0.05 25 OUTLET +5 0.001 0.10 0.05 0.05 25 OUTLET +6 0.001 0.10 0.05 0.05 25 OUTLET +7 0.001 0.10 0.05 0.05 25 OUTLET +8 0.001 0.10 0.05 0.05 25 OUTLET + +[INFILTRATION] +;;Subcatchment MaxRate MinRate Decay DryTime MaxInfil +;;-------------- ---------- ---------- ---------- ---------- ---------- +1 0.35 0.25 4.14 0.50 0 +2 0.7 0.3 4.14 0.50 0 +3 0.7 0.3 4.14 0.50 0 +4 0.7 0.3 4.14 0.50 0 +5 0.7 0.3 4.14 0.50 0 +6 0.7 0.3 4.14 0.50 0 +7 0.7 0.3 4.14 0.50 0 +8 0.7 0.3 4.14 0.50 0 + +[JUNCTIONS] +;;Name Elevation MaxDepth InitDepth SurDepth Aponded +;;-------------- ---------- ---------- ---------- ---------- ---------- +9 1000 3 0 0 0 +10 995 3 0 0 0 +13 995 3 0 0 0 +14 990 3 0 0 0 +15 987 3 0 0 0 +16 985 3 0 0 0 +17 980 3 0 0 0 +19 1010 3 0 0 0 +20 1005 3 0 0 0 +21 990 3 0 0 0 +22 987 3 0 0 0 +23 990 3 0 0 0 +24 984 3 0 0 0 + +[OUTFALLS] +;;Name Elevation Type Stage Data Gated Route To +;;-------------- ---------- ---------- ---------------- -------- ---------------- +18 975 FREE NO + +[CONDUITS] +;;Name From Node To Node Length Roughness InOffset OutOffset InitFlow MaxFlow +;;-------------- ---------------- ---------------- ---------- ---------- ---------- ---------- ---------- ---------- +1 9 10 400 0.01 0 0 0 0 +4 19 20 200 0.01 0 0 0 0 +5 20 21 200 0.01 0 0 0 0 +6 10 21 400 0.01 0 1 0 0 +7 21 22 300 0.01 1 1 0 0 +8 22 16 300 0.01 0 0 0 0 +10 17 18 400 0.01 0 0 0 0 +11 13 14 400 0.01 0 0 0 0 +12 14 15 400 0.01 0 0 0 0 +13 15 16 400 0.01 0 0 0 0 +14 23 24 400 0.01 0 0 0 0 +15 16 24 100 0.01 0 0 0 0 +16 24 17 400 0.01 0 0 0 0 + +[XSECTIONS] +;;Link Shape Geom1 Geom2 Geom3 Geom4 Barrels Culvert +;;-------------- ------------ ---------------- ---------- ---------- ---------- ---------- ---------- +1 CIRCULAR 1.5 0 0 0 1 +4 CIRCULAR 1 0 0 0 1 +5 CIRCULAR 1 0 0 0 1 +6 CIRCULAR 1 0 0 0 1 +7 CIRCULAR 2 0 0 0 1 +8 CIRCULAR 2 0 0 0 1 +10 CIRCULAR 2 0 0 0 1 +11 CIRCULAR 1.5 0 0 0 1 +12 CIRCULAR 1.5 0 0 0 1 +13 CIRCULAR 1.5 0 0 0 1 +14 CIRCULAR 1 0 0 0 1 +15 CIRCULAR 2 0 0 0 1 +16 CIRCULAR 2 0 0 0 1 + +[POLLUTANTS] +;;Name Units Crain Cgw Crdii Kdecay SnowOnly Co-Pollutant Co-Frac Cdwf Cinit +;;-------------- ------ ---------- ---------- ---------- ---------- ---------- ---------------- ---------- ---------- ---------- +TSS MG/L 0.0 0.0 0 0.0 NO * 0.0 0 0 +Lead UG/L 0.0 0.0 0 0.0 NO TSS 0.2 0 0 + +[LANDUSES] +;; Sweeping Fraction Last +;;Name Interval Available Swept +;;-------------- ---------- ---------- ---------- +Residential +Undeveloped + +[COVERAGES] +;;Subcatchment Land Use Percent +;;-------------- ---------------- ---------- +1 Residential 100.00 +2 Residential 50.00 +2 Undeveloped 50.00 +3 Residential 100.00 +4 Residential 50.00 +4 Undeveloped 50.00 +5 Residential 100.00 +6 Undeveloped 100.00 +7 Undeveloped 100.00 +8 Undeveloped 100.00 + +[LOADINGS] +;;Subcatchment Pollutant Buildup +;;-------------- ---------------- ---------- + +[BUILDUP] +;;Land Use Pollutant Function Coeff1 Coeff2 Coeff3 Per Unit +;;-------------- ---------------- ---------- ---------- ---------- ---------- ---------- +Residential TSS SAT 50 0 2 AREA +Residential Lead NONE 0 0 0 AREA +Undeveloped TSS SAT 100 0 3 AREA +Undeveloped Lead NONE 0 0 0 AREA + +[WASHOFF] +;;Land Use Pollutant Function Coeff1 Coeff2 SweepRmvl BmpRmvl +;;-------------- ---------------- ---------- ---------- ---------- ---------- ---------- +Residential TSS EXP 0.1 1 0 0 +Residential Lead EMC 0 0 0 0 +Undeveloped TSS EXP 0.1 0.7 0 0 +Undeveloped Lead EMC 0 0 0 0 + +[TIMESERIES] +;;Name Date Time Value +;;-------------- ---------- ---------- ---------- +;RAINFALL +TS1 0:00 0.0 +TS1 1:00 0.25 +TS1 2:00 0.5 +TS1 3:00 0.8 +TS1 4:00 0.4 +TS1 5:00 0.1 +TS1 6:00 0.0 +TS1 27:00 0.0 +TS1 28:00 0.4 +TS1 29:00 0.2 +TS1 30:00 0.0 + +[REPORT] +;;Reporting Options +INPUT NO +CONTROLS NO +SUBCATCHMENTS ALL +NODES ALL +LINKS ALL diff --git a/tests/solver/data/hotstart/Simulation3.inp b/tests/solver/data/hotstart/Simulation3.inp new file mode 100644 index 000000000..f0521e5a0 --- /dev/null +++ b/tests/solver/data/hotstart/Simulation3.inp @@ -0,0 +1,217 @@ +[TITLE] +;;Project Title/Notes +Example 1 + +[OPTIONS] +;;Option Value +FLOW_UNITS CFS +INFILTRATION HORTON +FLOW_ROUTING DYNWAVE +LINK_OFFSETS DEPTH +MIN_SLOPE 0 +ALLOW_PONDING NO +SKIP_STEADY_STATE NO + +START_DATE 01/01/1998 +START_TIME 00:00:00 +REPORT_START_DATE 01/01/1998 +REPORT_START_TIME 00:00:00 +END_DATE 01/02/1998 +END_TIME 12:00:00 +SWEEP_START 1/1 +SWEEP_END 12/31 +DRY_DAYS 5 +REPORT_STEP 01:00:00 +WET_STEP 00:15:00 +DRY_STEP 01:00:00 +ROUTING_STEP 0:00:01 + +INERTIAL_DAMPING PARTIAL +NORMAL_FLOW_LIMITED BOTH +FORCE_MAIN_EQUATION H-W +VARIABLE_STEP 0.75 +LENGTHENING_STEP 0 +MIN_SURFAREA 0 +MAX_TRIALS 0 +HEAD_TOLERANCE 0 +SYS_FLOW_TOL 5 +LAT_FLOW_TOL 5 +;MINIMUM_STEP 0.5 +THREADS 1 + +[FILES] +USE HOTSTART swmm_api_test_during_Simulation1.hsf + +[EVAPORATION] +;;Data Source Parameters +;;-------------- ---------------- +CONSTANT 0.0 +DRY_ONLY NO + +[RAINGAGES] +;;Name Format Interval SCF Source +;;-------------- --------- ------ ------ ---------- +RG1 INTENSITY 1:00 1.0 TIMESERIES TS1 + +[SUBCATCHMENTS] +;;Name Rain Gage Outlet Area %Imperv Width %Slope CurbLen SnowPack +;;-------------- ---------------- ---------------- -------- -------- -------- -------- -------- ---------------- +1 RG1 9 10 50 500 0.01 0 +2 RG1 10 10 50 500 0.01 0 +3 RG1 13 5 50 500 0.01 0 +4 RG1 22 5 50 500 0.01 0 +5 RG1 15 15 50 500 0.01 0 +6 RG1 23 12 10 500 0.01 0 +7 RG1 19 4 10 500 0.01 0 +8 RG1 18 10 10 500 0.01 0 + +[SUBAREAS] +;;Subcatchment N-Imperv N-Perv S-Imperv S-Perv PctZero RouteTo PctRouted +;;-------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- +1 0.001 0.10 0.05 0.05 25 OUTLET +2 0.001 0.10 0.05 0.05 25 OUTLET +3 0.001 0.10 0.05 0.05 25 OUTLET +4 0.001 0.10 0.05 0.05 25 OUTLET +5 0.001 0.10 0.05 0.05 25 OUTLET +6 0.001 0.10 0.05 0.05 25 OUTLET +7 0.001 0.10 0.05 0.05 25 OUTLET +8 0.001 0.10 0.05 0.05 25 OUTLET + +[INFILTRATION] +;;Subcatchment MaxRate MinRate Decay DryTime MaxInfil +;;-------------- ---------- ---------- ---------- ---------- ---------- +1 0.35 0.25 4.14 0.50 0 +2 0.7 0.3 4.14 0.50 0 +3 0.7 0.3 4.14 0.50 0 +4 0.7 0.3 4.14 0.50 0 +5 0.7 0.3 4.14 0.50 0 +6 0.7 0.3 4.14 0.50 0 +7 0.7 0.3 4.14 0.50 0 +8 0.7 0.3 4.14 0.50 0 + +[JUNCTIONS] +;;Name Elevation MaxDepth InitDepth SurDepth Aponded +;;-------------- ---------- ---------- ---------- ---------- ---------- +9 1000 3 0 0 0 +10 995 3 0 0 0 +13 995 3 0 0 0 +14 990 3 0 0 0 +15 987 3 0 0 0 +16 985 3 0 0 0 +17 980 3 0 0 0 +19 1010 3 0 0 0 +20 1005 3 0 0 0 +21 990 3 0 0 0 +22 987 3 0 0 0 +23 990 3 0 0 0 +24 984 3 0 0 0 + +[OUTFALLS] +;;Name Elevation Type Stage Data Gated Route To +;;-------------- ---------- ---------- ---------------- -------- ---------------- +18 975 FREE NO + +[CONDUITS] +;;Name From Node To Node Length Roughness InOffset OutOffset InitFlow MaxFlow +;;-------------- ---------------- ---------------- ---------- ---------- ---------- ---------- ---------- ---------- +1 9 10 400 0.01 0 0 0 0 +4 19 20 200 0.01 0 0 0 0 +5 20 21 200 0.01 0 0 0 0 +6 10 21 400 0.01 0 1 0 0 +7 21 22 300 0.01 1 1 0 0 +8 22 16 300 0.01 0 0 0 0 +10 17 18 400 0.01 0 0 0 0 +11 13 14 400 0.01 0 0 0 0 +12 14 15 400 0.01 0 0 0 0 +13 15 16 400 0.01 0 0 0 0 +14 23 24 400 0.01 0 0 0 0 +15 16 24 100 0.01 0 0 0 0 +16 24 17 400 0.01 0 0 0 0 + +[XSECTIONS] +;;Link Shape Geom1 Geom2 Geom3 Geom4 Barrels Culvert +;;-------------- ------------ ---------------- ---------- ---------- ---------- ---------- ---------- +1 CIRCULAR 1.5 0 0 0 1 +4 CIRCULAR 1 0 0 0 1 +5 CIRCULAR 1 0 0 0 1 +6 CIRCULAR 1 0 0 0 1 +7 CIRCULAR 2 0 0 0 1 +8 CIRCULAR 2 0 0 0 1 +10 CIRCULAR 2 0 0 0 1 +11 CIRCULAR 1.5 0 0 0 1 +12 CIRCULAR 1.5 0 0 0 1 +13 CIRCULAR 1.5 0 0 0 1 +14 CIRCULAR 1 0 0 0 1 +15 CIRCULAR 2 0 0 0 1 +16 CIRCULAR 2 0 0 0 1 + +[POLLUTANTS] +;;Name Units Crain Cgw Crdii Kdecay SnowOnly Co-Pollutant Co-Frac Cdwf Cinit +;;-------------- ------ ---------- ---------- ---------- ---------- ---------- ---------------- ---------- ---------- ---------- +TSS MG/L 0.0 0.0 0 0.0 NO * 0.0 0 0 +Lead UG/L 0.0 0.0 0 0.0 NO TSS 0.2 0 0 + +[LANDUSES] +;; Sweeping Fraction Last +;;Name Interval Available Swept +;;-------------- ---------- ---------- ---------- +Residential +Undeveloped + +[COVERAGES] +;;Subcatchment Land Use Percent +;;-------------- ---------------- ---------- +1 Residential 100.00 +2 Residential 50.00 +2 Undeveloped 50.00 +3 Residential 100.00 +4 Residential 50.00 +4 Undeveloped 50.00 +5 Residential 100.00 +6 Undeveloped 100.00 +7 Undeveloped 100.00 +8 Undeveloped 100.00 + +[LOADINGS] +;;Subcatchment Pollutant Buildup +;;-------------- ---------------- ---------- + +[BUILDUP] +;;Land Use Pollutant Function Coeff1 Coeff2 Coeff3 Per Unit +;;-------------- ---------------- ---------- ---------- ---------- ---------- ---------- +Residential TSS SAT 50 0 2 AREA +Residential Lead NONE 0 0 0 AREA +Undeveloped TSS SAT 100 0 3 AREA +Undeveloped Lead NONE 0 0 0 AREA + +[WASHOFF] +;;Land Use Pollutant Function Coeff1 Coeff2 SweepRmvl BmpRmvl +;;-------------- ---------------- ---------- ---------- ---------- ---------- ---------- +Residential TSS EXP 0.1 1 0 0 +Residential Lead EMC 0 0 0 0 +Undeveloped TSS EXP 0.1 0.7 0 0 +Undeveloped Lead EMC 0 0 0 0 + +[TIMESERIES] +;;Name Date Time Value +;;-------------- ---------- ---------- ---------- +;RAINFALL +TS1 0:00 0.0 +TS1 1:00 0.25 +TS1 2:00 0.5 +TS1 3:00 0.8 +TS1 4:00 0.4 +TS1 5:00 0.1 +TS1 6:00 0.0 +TS1 27:00 0.0 +TS1 28:00 0.4 +TS1 29:00 0.2 +TS1 30:00 0.0 + +[REPORT] +;;Reporting Options +INPUT NO +CONTROLS NO +SUBCATCHMENTS ALL +NODES ALL +LINKS ALL diff --git a/tests/solver/data/hotstart/use_hot_start_test.hsf b/tests/solver/data/hotstart/use_hot_start_test.hsf new file mode 100644 index 000000000..d57d38ed5 Binary files /dev/null and b/tests/solver/data/hotstart/use_hot_start_test.hsf differ diff --git a/tests/solver/test_solver.hpp b/tests/solver/test_solver.hpp index e45e477b4..6af24963c 100644 --- a/tests/solver/test_solver.hpp +++ b/tests/solver/test_solver.hpp @@ -44,6 +44,15 @@ struct FixtureOpenClose{ } }; +struct FixtureBeforeStart_TKAPI{ + FixtureBeforeStart_TKAPI() { + swmm_open(DATA_PATH_INP, DATA_PATH_RPT, DATA_PATH_OUT); + } + ~FixtureBeforeStart_TKAPI() { + swmm_close(); + } +}; + struct FixtureBeforeStep{ FixtureBeforeStep() { swmm_open(DATA_PATH_INP, DATA_PATH_RPT, DATA_PATH_OUT); diff --git a/tests/solver/test_toolkit.cpp b/tests/solver/test_toolkit.cpp index 5138c666d..b9d6db8a6 100644 --- a/tests/solver/test_toolkit.cpp +++ b/tests/solver/test_toolkit.cpp @@ -22,6 +22,7 @@ #define ERR_TKAPI_SIM_NRUNNING 2002 #define ERR_TKAPI_WRONG_TYPE 2003 #define ERR_TKAPI_OBJECT_INDEX 2004 +#define ERR_TKAPI_SIM_RUNNING 2013 using namespace std; @@ -41,6 +42,10 @@ BOOST_AUTO_TEST_CASE(model_not_open) { //Project error = swmm_getObjectIndex(SM_NODE, id, &index); BOOST_CHECK_EQUAL(error, ERR_TKAPI_INPUTNOTOPEN); + error = swmm_hotstart(SM_HOTSTART_USE, id); + BOOST_CHECK_EQUAL(error, ERR_TKAPI_INPUTNOTOPEN); + error = swmm_hotstart(SM_HOTSTART_SAVE, id); + BOOST_CHECK_EQUAL(error, ERR_TKAPI_INPUTNOTOPEN); //Gage error = swmm_getGagePrecip(0, SM_TOTALPRECIP, &val); @@ -108,10 +113,23 @@ BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE(test_toolkitapi_fixture) +// Testing for Before Simulation Start Error +BOOST_FIXTURE_TEST_CASE(sim_before_start, FixtureBeforeStart_TKAPI) { + int error; + char fakehsf[] = "FakeHSF.hsf"; + + error = swmm_hotstart(SM_HOTSTART_SAVE, fakehsf); + BOOST_CHECK_EQUAL(error, ERR_TKAPI_SIM_NRUNNING); +} + // Testing for Simulation Started Error BOOST_FIXTURE_TEST_CASE(sim_started_check, FixtureBeforeStep) { int error; + char fakehsf[] = "FakeHSF.hsf"; + //Project + error = swmm_hotstart(SM_HOTSTART_USE, fakehsf); + BOOST_CHECK_EQUAL(error, ERR_TKAPI_SIM_RUNNING); //Subcatchment error = swmm_setSubcatchParam(0, SM_WIDTH, 1); BOOST_CHECK_EQUAL(error, ERR_TKAPI_SIM_NRUNNING); @@ -419,6 +437,17 @@ BOOST_FIXTURE_TEST_CASE(project_info_metric, FixtureMetric) { error = swmm_getSimulationParam(SM_HEADTOL, &value); BOOST_REQUIRE(error == ERR_NONE); BOOST_CHECK_EQUAL(value, 0.015); + + error = swmm_getSimulationParam(SM_THREADS, &value); + BOOST_REQUIRE(error == ERR_NONE); + BOOST_CHECK_EQUAL(value, 1); + + #if defined(_OPENMP) + error = swmm_setSimulationParam(SM_THREADS, 2); + error = swmm_getSimulationParam(SM_THREADS, &value); + BOOST_REQUIRE(error == ERR_NONE); + BOOST_CHECK_EQUAL(value, 2); + #endif } diff --git a/tests/solver/test_toolkit_hotstart.cpp b/tests/solver/test_toolkit_hotstart.cpp new file mode 100644 index 000000000..617c17269 --- /dev/null +++ b/tests/solver/test_toolkit_hotstart.cpp @@ -0,0 +1,237 @@ +/* + * test_toolkitAPI_hotstart.cpp + * + * Created: 07/29/2019 + * Updated: 06/11/2023 + * Author: Bryant E. McDonnell and Jeff Sadler + * + * Unit testing mechanics for the hotstart API using Boost Test. + */ + +#include +#include "test_solver.hpp" +#include +#include + +#define HOTSTART_SWMM_SAVE_NORMAL "hotstart/INFILE_Simulation1.hsf" +#define HOTSTART_API_SAVE_DURING_SIM1 "hotstart/swmm_api_test_during_Simulation1.hsf" +#define HOTSTART_API_SAVE_AFTER_SIM1 "hotstart/swmm_api_test_after_Simulation1.hsf" +#define HOTSTART_SWMM_SAVE_SIM2 "hotstart/INFILE_Simulation2.hsf" + +#define ERR_NONE 0 +#define ERR_HOTSTART_FILE_OPEN 331 + +BOOST_AUTO_TEST_SUITE(test_hotstart) + +// Testing Run Simulation and Generate Hot Start File using Model (as normal) +// and save a hot start file using the API swmm_saveHotstart() +// +// TEST #1 - Making and Comparing Hot Start Files. +// In this test 2 simulations will be performed. One simulation will +// create hot start files at various time and the second simulation will +// end at the +// +// Start Simulation 1 +// This simulation will produce 3 hot start files: +// 1. API hotstart File at 1056 Steps into the model ~= 1998-1-1 2:59:58 +// (HSF Name: HOTSTART_API_SAVE_DURING_SIM1) +// 2. API created hotstart file at the end of the run +// (HSF Name: HOTSTART_API_SAVE_AFTER_SIM1) +// 3. Normal SWMM [FILES] Generated HSF +// (HSF Name: HOTSTART_SWMM_SAVE_NORMAL) +// +// Start Simulation 2 +// This simulation will end at 1056 Steps into a simulation. +// (HSF Name: HOTSTART_SWMM_SAVE_SIM2 +// +// The follwing comparisons will be made from these artifacts +// 1. HOTSTART_SWMM_SAVE_NORMAL Should == HOTSTART_API_SAVE +// 2. HOTSTART_API_SAVE_DURING_SIM1 Should == HOTSTART_SWMM_SAVE_SIM2 + +BOOST_AUTO_TEST_CASE(save_hotstart_file){ + int error, step_ind; + int index; + int number_of_nodes; + double elapsedTime = 0.0; + double set_val; + + // Start Simulation 1 + swmm_open((char *)"hotstart/Simulation1.inp", + (char *)"hotstart/Simulation1.rpt", + (char *)"hotstart/Simulation1.out"); + swmm_start(1); + step_ind = 0; + do + { + error = swmm_step(&elapsedTime); + step_ind += 1; + if (step_ind == 1056) + { + error = swmm_hotstart(SM_HOTSTART_SAVE, (char *) HOTSTART_API_SAVE_DURING_SIM1); + BOOST_CHECK_EQUAL(ERR_NONE, error); + } + }while (elapsedTime != 0 && !error); + BOOST_CHECK_EQUAL(ERR_NONE, error); + // Save New Hotstart File at the End of the Simulation + error = swmm_hotstart(SM_HOTSTART_SAVE, (char *) HOTSTART_API_SAVE_AFTER_SIM1); + BOOST_CHECK_EQUAL(ERR_NONE, error); + swmm_end(); + swmm_report(); + swmm_close(); + + // Start Simulation 2 + swmm_open((char *)"hotstart/Simulation2.inp", + (char *)"hotstart/Simulation2.rpt", + (char *)"hotstart/Simulation2.out"); + swmm_start(0); + step_ind = 0; + elapsedTime = 0.0; + do + { + error = swmm_step(&elapsedTime); + step_ind += 1; + }while (step_ind < 1056 && !error); + BOOST_CHECK_EQUAL(ERR_NONE, error); + swmm_end(); + swmm_close(); + + std::ifstream ifs1(HOTSTART_SWMM_SAVE_NORMAL); + std::ifstream ifs2(HOTSTART_API_SAVE_AFTER_SIM1); + std::istream_iterator b1(ifs1), e1; + std::istream_iterator b2(ifs2), e2; + //iterate over the two hotstart files and check all of them + BOOST_CHECK_EQUAL_COLLECTIONS(b1, e1, b2, e2); + + // Diff the three hot start files that come from the model. + std::ifstream ifsbench_1998(HOTSTART_SWMM_SAVE_SIM2); + std::ifstream ifs1_1998(HOTSTART_API_SAVE_DURING_SIM1); + std::istream_iterator bench_1998(ifsbench_1998), ebench_1998; + std::istream_iterator b_1998(ifs1_1998), e_1998; + // iterate over hotstart files and check all of them + BOOST_CHECK_EQUAL_COLLECTIONS(bench_1998, ebench_1998, b_1998, e_1998); + + // Testing USE the new generated hotstart file + // Start Simulation 3 + swmm_open((char *)"hotstart/Simulation3.inp", + (char *)"hotstart/Simulation3.rpt", + (char *)"hotstart/Simulation3.out"); + swmm_start(0); + error = swmm_step(&elapsedTime); + // Iterate over nodes before stepping + error = swmm_countObjects(SM_NODE, &number_of_nodes); + // Known Values + std::vector hotstart_vals {0.0046, + 3.0, + 3.0, + 0.0117, + 0.0, + 0.0, + 0.0, + 0.0105, + 0.0, + 0.1209, + 0.0, + 0.0, + 0.0484, + 0.0}; + + for (index=0; index hotstart_vals {0.0046, + 3.0, + 3.0, + 0.0117, + 0.0, + 0.0, + 0.0, + 0.0105, + 0.0, + 0.1209, + 0.0, + 0.0, + 0.0484, + 0.0}; + + for (index=0; index