diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 41e7c5020..f48647079 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -24,7 +24,7 @@ jobs: requirements: [requirements-swmm.txt] include: - os: windows-2022 - sys_pkgs: choco install boost-msvc-14.1 + sys_pkgs: choco install boost-msvc-14.3 build_unit_test: make.cmd /g "Visual Studio 17 2022" /A "x64" /t build_reg_test: make.cmd /g "Visual Studio 17 2022" /A "x64" before_reg_test: before-nrtest.cmd @@ -83,17 +83,17 @@ jobs: steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Clone ci-tools repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: OpenWaterAnalytics/ci-tools ref: master path: ci-tools - name: Setup python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: "3.7" @@ -114,7 +114,7 @@ jobs: - name: Before reg test env: NRTESTS_URL: https://github.com/OpenWaterAnalytics/swmm-nrtestsuite - BENCHMARK_TAG: v2.0.1 + BENCHMARK_TAG: v2.0.2 run: ./${{ matrix.before_reg_test }} ${{ env.BENCHMARK_TAG }} - name: Run reg test @@ -122,7 +122,7 @@ jobs: - name: Upload artifacts if: ${{ always() }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: build-test-artifacts path: upload/*.* diff --git a/.gitignore b/.gitignore index fec94365b..54fd8cba7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ - # Eclipse Stuff .metadata/ .settings/ @@ -7,6 +6,17 @@ .pydevproject +.DS_Store + +build*/ +nrtest*/ + +*_export.h + +src/outfile/include/*_export.h +src/solver/include/*_export.h + + # Mac Stuff .DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index 087455567..a2409aa80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ endif() project(swmm-solver - VERSION 5.1.14 + VERSION 5.1.15 LANGUAGES C CXX ) diff --git a/extern/boost.cmake b/extern/boost.cmake index 839df22ec..4f9eb1792 100644 --- a/extern/boost.cmake +++ b/extern/boost.cmake @@ -7,10 +7,10 @@ # Author: Michael E. Tryby # US EPA - ORD/CESER # -# Usage: -# Create environment variable with the following pattern -- "BOOST_ROOT_X_XX_X" +# Usage: +# Create environment variable with the following pattern -- "BOOST_ROOT_X_XX_X" # where Xs are the Boost version -- pointing to install location. -# +# if(WIN32) diff --git a/src/outfile/CMakeLists.txt b/src/outfile/CMakeLists.txt index 11b7e5ce8..6732b9027 100644 --- a/src/outfile/CMakeLists.txt +++ b/src/outfile/CMakeLists.txt @@ -6,7 +6,7 @@ # # Author: Michael E. Tryby # US EPA ORD/CESER -# +# # # configure file groups @@ -18,7 +18,7 @@ set(SWMM_OUT_PUBLIC_HEADERS # the binary output file API -add_library(swmm-output +add_library(swmm-output swmm_output.c errormanager.c ) diff --git a/src/outfile/swmm_output.c b/src/outfile/swmm_output.c index 57fa847d6..11a0c57b4 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 diff --git a/src/run/main.c b/src/run/main.c index dee6418d2..ac1d2a018 100644 --- a/src/run/main.c +++ b/src/run/main.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -124,7 +125,7 @@ int main(int argc, char *argv[]) else if (strcmp(arg1, "--version") == 0 || strcmp(arg1, "-v") == 0) { printf("\nVersion:\n"); - printf("\tOWA-SWMM v%s (Build %.10s)\n\n", swmm_getSemVersion(), + printf("\tOWA-SWMM v%s (Build %.10s)\n\n", swmm_getSemVersion(), swmm_getBuildId()); } @@ -139,4 +140,4 @@ int main(int argc, char *argv[]) } return 0; -} \ No newline at end of file +} diff --git a/src/solver/CMakeLists.txt b/src/solver/CMakeLists.txt index e10fa4a9a..0741ffe3d 100644 --- a/src/solver/CMakeLists.txt +++ b/src/solver/CMakeLists.txt @@ -38,7 +38,7 @@ if(BUILD_DEF) PROPERTIES_HEADER_FILE_ONLY TRUE ) - add_library(swmm5 + add_library(swmm5 ${SWMM_SOURCES} ${PROJECT_SOURCE_DIR/bindings/swmm5.def} $ @@ -46,7 +46,7 @@ if(BUILD_DEF) else() # Performs standard library build - add_library(swmm5 + add_library(swmm5 ${SWMM_SOURCES} $ ) @@ -90,7 +90,7 @@ target_include_directories(swmm5 include(GenerateExportHeader) generate_export_header(swmm5 - BASE_NAME toolkit + BASE_NAME toolkit EXPORT_MACRO_NAME EXPORT_TOOLKIT EXPORT_FILE_NAME toolkit_export.h STATIC_DEFINE SHARED_EXPORTS_BUILT_AS_STATIC @@ -118,6 +118,7 @@ install(TARGETS swmm5 EXPORT swmm5Targets FRAMEWORK DESTINATION "${TOOL_DIST}" ) +# Create target import scripts so other cmake projects can use swmm libraries install( EXPORT swmm5Targets @@ -125,14 +126,9 @@ install( "${CONFIG_DIST}" FILE swmm5-config.cmake -) + ) -install( - FILES - ${SWMM_PUBLIC_HEADERS} - DESTINATION - "${INCLUDE_DIST}" -) +install(FILES ${SWMM_PUBLIC_HEADERS} DESTINATION "${INCLUDE_DIST}") # copy swmm5 to build tree for testing diff --git a/src/solver/consts.h b/src/solver/consts.h index 62bf52747..b1697c368 100644 --- a/src/solver/consts.h +++ b/src/solver/consts.h @@ -7,11 +7,16 @@ // 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 //------------------ @@ -93,3 +98,6 @@ // Token separator characters //--------------------------- #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 7d2ab42e4..1ee7b0bea 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 //------------------------------------- @@ -114,18 +118,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 @@ -194,7 +198,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 @@ -411,7 +415,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 @@ -480,3 +484,6 @@ enum NoneAllType { NONE, ALL, SOME}; + + +#endif //ENUMS_H diff --git a/src/solver/error.c b/src/solver/error.c index dfd0998ae..f0d40f62b 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." @@ -200,7 +205,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, ERR510, ERR511, ERR512}; + ERR505, ERR506, ERR507, ERR508, ERR509, ERR510, ERR511, ERR512, ERR140}; int ErrorCodes[] = { 0, 101, 103, 105, 107, 108, 109, 110, 111, @@ -215,7 +220,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, 510, 511, 512}; + 505, 506, 507, 508, 509, 510, 511, 512, 140}; char ErrString[256]; diff --git a/src/solver/error.h b/src/solver/error.h index 80e7c0d83..3697cc129 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 @@ -173,9 +178,14 @@ enum ErrorType { ERR_API_LIDUNIT_INDEX, //510 113 ERR_API_UNDEFINED_LID, //511 114 ERR_API_MEMORY, //512 115 + //... Additional Errors + ERR_STORAGE_VOLUME, //140 116 //(5.1.015) MAXERRMSG}; char* error_getMsg(int i); int error_getCode(int i); int error_getErrorIndex(int ErrorCode); 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 4199e54c3..09a2db4fc 100644 --- a/src/solver/funcs.h +++ b/src/solver/funcs.h @@ -33,6 +33,10 @@ // //----------------------------------------------------------------------------- +#ifndef FUNCS_H +#define FUNCS_H + + void project_open(char *f1, char *f2, char *f3); void project_close(void); @@ -360,10 +364,10 @@ 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, - double baseline, double sf); + int tSeries, int basePat, double cf, + double baseline, double sf); int inflow_validate(int param, int type, int tSeries, - int basePat, double *cf); + int basePat, double *cf); void inflow_initDwfInflow(TDwfInflow* inflow); void inflow_initDwfPattern(int pattern); @@ -521,3 +525,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 b3d2ca403..93c11f2d7 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 @@ -167,3 +176,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 88cd95e4b..016f5445c 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 e7f6ef82d..45cb020f1 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 @@ -69,7 +70,7 @@ // // Build 5.1.013: // - Support added for LID units treating pervious area runoff. -// - Support added for open/closed head levels and multiplier v. head +// - Support added for open/closed head levels and multiplier v. head // control curve for underdrain flow. // - Support added for unclogging permeable pavement at fixed intervals. // - Support added for pollutant removal in underdrain flow. @@ -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 @@ -106,7 +110,7 @@ enum LidLayerTypes { REMOVALS}; // pollutant removals //(5.1.013) //// Note: DRAINMAT must be placed before DRAIN so the two keywords can -/// be distinguished from one another when parsing a line of input. +/// be distinguished from one another when parsing a line of input. char* LidLayerWords[] = {"SURFACE", "SOIL", "STORAGE", "PAVEMENT", "DRAINMAT", "DRAIN", @@ -143,7 +147,7 @@ static double MaxNativeInfil; // native soil infil. rate limit (ft/s) //----------------------------------------------------------------------------- // Imported Variables (from SUBCATCH.C) //----------------------------------------------------------------------------- -// Volumes (ft3) for a subcatchment over a time step +// Volumes (ft3) for a subcatchment over a time step extern double Vevap; // evaporation extern double Vpevap; // pervious area evaporation extern double Vinfil; // non-LID infiltration @@ -251,10 +255,10 @@ void lid_create(int lidCount, int subcatchCount) return; } } - + //... initialize LID groups for (j = 0; j < GroupCount; j++) LidGroups[j] = NULL; - + //... create LID objects if ( LidCount == 0 ) return; LidProcs = (TLidProc *) calloc(LidCount, sizeof(TLidProc)); @@ -287,7 +291,7 @@ void lid_create(int lidCount, int subcatchCount) { // ErrorCode = ERR_MEMORY; // return; // - } // + } // } } @@ -548,7 +552,7 @@ int addLidUnit(int j, int k, int n, double x[], char* fname, //... open report file if it was supplied if ( fname != NULL ) { - if ( !createLidRptFile(lidUnit, fname) ) + if ( !createLidRptFile(lidUnit, fname) ) return error_setInpError(ERR_RPT_FILE, fname); } return 0; @@ -559,7 +563,7 @@ int addLidUnit(int j, int k, int n, double x[], char* fname, int createLidRptFile(TLidUnit* lidUnit, char* fname) { TLidRptFile* rptFile; - + rptFile = (TLidRptFile *) malloc(sizeof(TLidRptFile)); if ( rptFile == NULL ) return 0; lidUnit->rptFile = rptFile; @@ -574,7 +578,7 @@ int readSurfaceData(int j, char* toks[], int ntoks) // // Purpose: reads surface layer data for a LID process from line of input // data file -// Input: j = LID process index +// Input: j = LID process index // toks = array of string tokens // ntoks = number of tokens // Output: returns error code @@ -592,7 +596,7 @@ int readSurfaceData(int j, char* toks[], int ntoks) if ( ! getDouble(toks[i], &x[i-2]) || x[i-2] < 0.0 ) return error_setInpError(ERR_NUMBER, toks[i]); } - if ( x[1] >= 1.0 ) return error_setInpError(ERR_NUMBER, toks[3]); + if ( x[1] >= 1.0 ) return error_setInpError(ERR_NUMBER, toks[3]); if ( x[0] == 0.0 ) x[1] = 0.0; LidProcs[j].surface.thickness = x[0] / UCF(RAINDEPTH); @@ -609,7 +613,7 @@ int readPavementData(int j, char* toks[], int ntoks) // // Purpose: reads pavement layer data for a LID process from line of input // data file -// Input: j = LID process index +// Input: j = LID process index // toks = array of string tokens // ntoks = number of tokens // Output: returns error code @@ -654,7 +658,7 @@ int readPavementData(int j, char* toks[], int ntoks) if (LidProcs[j].pavement.thickness > 0.0) { LidProcs[j].pavement.clogFactor = x[4] * - LidProcs[j].pavement.thickness * + LidProcs[j].pavement.thickness * LidProcs[j].pavement.voidFrac * (1.0 - LidProcs[j].pavement.impervFrac); } @@ -673,7 +677,7 @@ int readSoilData(int j, char* toks[], int ntoks) // // Purpose: reads soil layer data for a LID process from line of input // data file -// Input: j = LID process index +// Input: j = LID process index // toks = array of string tokens // ntoks = number of tokens // Output: returns error code @@ -707,13 +711,13 @@ int readStorageData(int j, char* toks[], int ntoks) // // Purpose: reads drainage layer data for a LID process from line of input // data file -// Input: j = LID process index +// Input: j = LID process index // toks = array of string tokens // ntoks = number of tokens // Output: returns error code // // Format of data is: -// LID_ID STORAGE Thickness VoidRatio Ksat ClogFactor +// LID_ID STORAGE Thickness VoidRatio Ksat ClogFactor // { int i; @@ -737,25 +741,25 @@ int readStorageData(int j, char* toks[], int ntoks) if (LidProcs[j].storage.thickness > 0.0) { - LidProcs[j].storage.clogFactor = x[3] * - LidProcs[j].storage.thickness * + LidProcs[j].storage.clogFactor = x[3] * + LidProcs[j].storage.thickness * LidProcs[j].storage.voidFrac; } - else + else { LidProcs[j].storage.clogFactor = 0.0; } return 0; } - + //============================================================================= int readDrainData(int j, char* toks[], int ntoks) // // Purpose: reads underdrain data for a LID process from line of input // data file -// Input: j = LID process index +// Input: j = LID process index // toks = array of string tokens // ntoks = number of tokens // Output: returns error code @@ -772,7 +776,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]); } @@ -793,14 +797,14 @@ int readDrainData(int j, char* toks[], int ntoks) LidProcs[j].drain.qCurve = i; // return 0; } - + //============================================================================= int readDrainMatData(int j, char* toks[], int ntoks) // // Purpose: reads drainage mat data for a LID process from line of input // data file -// Input: j = LID process index +// Input: j = LID process index // toks = array of string tokens // ntoks = number of tokens // Output: returns error code @@ -836,7 +840,7 @@ int readRemovalsData(int j, char* toks[], int ntoks) // // Purpose: reads pollutant removal data for a LID process from line of input // data file -// Input: j = LID process index +// Input: j = LID process index // toks = array of string tokens // ntoks = number of tokens // Output: returns error code @@ -885,7 +889,7 @@ void lid_writeSummary() TLidUnit* lidUnit; TLidList* lidList; TLidGroup lidGroup; - + fprintf(Frpt.file, "\n"); fprintf(Frpt.file, "\n"); fprintf(Frpt.file, "\n *******************"); @@ -925,7 +929,7 @@ void lid_writeSummary() void lid_validate() // // Purpose: validates LID process and group parameters. -// Input: none +// Input: none // Output: none // { @@ -939,7 +943,7 @@ void lid_validate() void validateLidProc(int j) // // Purpose: validates LID process parameters. -// Input: j = LID process index +// Input: j = LID process index // Output: none // { @@ -960,7 +964,7 @@ void validateLidProc(int j) if ( LidProcs[j].soil.thickness <= 0.0 ) layerMissing = TRUE; break; case GREEN_ROOF: - if ( LidProcs[j].soil.thickness <= 0.0 ) layerMissing = TRUE; + if ( LidProcs[j].soil.thickness <= 0.0 ) layerMissing = TRUE; if ( LidProcs[j].drainMat.thickness <= 0.0) layerMissing = TRUE; break; case POROUS_PAVEMENT: @@ -979,8 +983,8 @@ void validateLidProc(int j) //... check pavement layer parameters if ( LidProcs[j].lidType == POROUS_PAVEMENT ) { - if ( LidProcs[j].pavement.thickness <= 0.0 - || LidProcs[j].pavement.kSat <= 0.0 + if ( LidProcs[j].pavement.thickness <= 0.0 + || LidProcs[j].pavement.kSat <= 0.0 || LidProcs[j].pavement.voidFrac <= 0.0 || LidProcs[j].pavement.voidFrac > 1.0 || LidProcs[j].pavement.impervFrac > 1.0 ) @@ -995,7 +999,7 @@ void validateLidProc(int j) //... check soil layer parameters if ( LidProcs[j].soil.thickness > 0.0 ) { - if ( LidProcs[j].soil.porosity <= 0.0 + if ( LidProcs[j].soil.porosity <= 0.0 || LidProcs[j].soil.fieldCap >= LidProcs[j].soil.porosity || LidProcs[j].soil.wiltPoint >= LidProcs[j].soil.fieldCap || LidProcs[j].soil.kSat <= 0.0 @@ -1019,9 +1023,9 @@ void validateLidProc(int j) } } - //... if no storage layer adjust void fraction and drain offset + //... if no storage layer adjust void fraction and drain offset else - { + { LidProcs[j].storage.voidFrac = 1.0; LidProcs[j].drain.offset = 0.0; } @@ -1038,7 +1042,7 @@ void validateLidProc(int j) //... compute the surface layer's overland flow constant (alpha) if ( LidProcs[j].lidType == VEG_SWALE ) { - if ( LidProcs[j].surface.roughness * + if ( LidProcs[j].surface.roughness * LidProcs[j].surface.surfSlope <= 0.0 || LidProcs[j].surface.thickness == 0.0 ) @@ -1047,7 +1051,7 @@ void validateLidProc(int j) strcat(Msg, ERR_SWALE_SURF); report_writeErrorMsg(ERR_LID_PARAMS, Msg); } - else LidProcs[j].surface.alpha = + else LidProcs[j].surface.alpha = 1.49 * sqrt(LidProcs[j].surface.surfSlope) / LidProcs[j].surface.roughness; } @@ -1090,7 +1094,7 @@ void validateLidProc(int j) LidProcs[j].storage.kSat = 0.0; } - //... set storage layer parameters of a green roof + //... set storage layer parameters of a green roof if ( LidProcs[j].lidType == GREEN_ROOF ) { LidProcs[j].storage.thickness = LidProcs[j].drainMat.thickness; @@ -1105,7 +1109,7 @@ void validateLidProc(int j) void validateLidGroup(int j) // // Purpose: validates properties of LID units grouped in a subcatchment. -// Input: j = subcatchment index +// Input: j = subcatchment index // Output: returns 1 if data are valid, 0 if not // { @@ -1147,15 +1151,14 @@ void validateLidGroup(int j) report_writeErrorMsg(ERR_LID_PARAMS, Msg); } } - + //... 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); @@ -1204,7 +1207,7 @@ void validateLidGroup(int j) void lid_initState() // // Purpose: initializes the internal state of each LID in a subcatchment. -// Input: none +// Input: none // Output: none // { @@ -1245,7 +1248,7 @@ void lid_initState() initVol = 0.0; if ( LidProcs[k].soil.thickness > 0.0 ) { - lidUnit->soilMoisture = LidProcs[k].soil.wiltPoint + + lidUnit->soilMoisture = LidProcs[k].soil.wiltPoint + lidUnit->initSat * (LidProcs[k].soil.porosity - LidProcs[k].soil.wiltPoint); initVol += lidUnit->soilMoisture * LidProcs[k].soil.thickness; @@ -1266,7 +1269,7 @@ void lid_initState() //... initialize water balance totals lidproc_initWaterBalance(lidUnit, initVol); - //... initialize water rate + //... initialize water rate lidproc_initWaterRate(lidUnit); lidUnit->volTreated = 0.0; @@ -1282,7 +1285,7 @@ void lid_initState() //... set previous flux rates to 0 for (i = 0; i < MAX_LAYERS; i++) - { + { lidUnit->oldFluxRates[i] = 0.0; } @@ -1303,7 +1306,7 @@ void lid_initState() void lid_setOldGroupState(int j) // // Purpose: saves the current drain flow rate for the LIDs in a subcatchment. -// Input: j = subcatchment index +// Input: j = subcatchment index // Output: none // { @@ -1327,7 +1330,7 @@ void lid_setOldGroupState(int j) int isLidPervious(int k) // // Purpose: determines if a LID process allows infiltration or not. -// Input: k = LID process index +// Input: k = LID process index // Output: returns 1 if process is pervious or 0 if not // { @@ -1341,7 +1344,7 @@ double getSurfaceDepth(int j) // // Purpose: computes the depth (volume per unit area) of ponded water on the // surface of all LIDs within a subcatchment. -// Input: j = subcatchment index +// Input: j = subcatchment index // Output: returns volumetric depth of ponded water (ft) // { @@ -1397,9 +1400,9 @@ double lid_getFlowToPerv(int j) double lid_getStoredVolume(int j) // -// Purpose: computes stored volume of water for all LIDs +// Purpose: computes stored volume of water for all LIDs // grouped within a subcatchment. -// Input: j = subcatchment index +// Input: j = subcatchment index // Output: returns stored volume of water (ft3) // { @@ -1426,7 +1429,7 @@ double lid_getDrainFlow(int j, int timePeriod) // // Purpose: returns flow from all of a subcatchment's LID drains for // a designated time period -// Input: j = subcatchment index +// Input: j = subcatchment index // timePeriod = either PREVIOUS or CURRENT // Output: total drain flow (cfs) from the subcatchment. { @@ -1454,11 +1457,11 @@ void lid_addDrainLoads(int j, double c[], double tStep) { int isRunoffLoad; // true if drain becomes external runoff load int p; // pollutant index - double r; // pollutant fractional removal + double r; // pollutant fractional removal double w; // pollutant mass load (lb or kg) TLidUnit* lidUnit; - TLidList* lidList; - TLidGroup lidGroup; + TLidList* lidList; + TLidGroup lidGroup; //... check if LID group exists lidGroup = LidGroups[j]; @@ -1469,11 +1472,11 @@ void lid_addDrainLoads(int j, double c[], double tStep) while ( lidList ) { lidUnit = lidList->lidUnit; - + //... see if unit's drain flow becomes external runoff isRunoffLoad = (lidUnit->drainNode >= 0 || lidUnit->drainSubcatch == j); - + //... for each pollutant not routed back on to subcatchment surface if (!lidUnit->toPerv) for (p = 0; p < Nobjects[POLLUT]; p++) { @@ -1500,7 +1503,7 @@ void lid_addDrainLoads(int j, double c[], double tStep) void lid_addDrainRunon(int j) // // Purpose: adds drain flows from LIDs in a given subcatchment to the -// subcatchments that were designated to receive them +// subcatchments that were designated to receive them // Input: j = index of subcatchment contributing underdrain flows // Output: none. // @@ -1511,8 +1514,8 @@ void lid_addDrainRunon(int j) double q; // drain flow rate (cfs) double w; // mass of polllutant from drain flow //(5.1.013) TLidUnit* lidUnit; - TLidList* lidList; - TLidGroup lidGroup; + TLidList* lidList; + TLidGroup lidGroup; //... check if LID group exists lidGroup = LidGroups[j]; @@ -1551,7 +1554,7 @@ void lid_addDrainRunon(int j) void lid_addDrainInflow(int j, double f) // -// Purpose: adds LID drain flow to conveyance system nodes +// Purpose: adds LID drain flow to conveyance system nodes // Input: j = subcatchment index // f = time interval weighting factor // Output: none. @@ -1588,12 +1591,12 @@ void lid_addDrainInflow(int j, double f) Node[k].newLatFlow += q; massbal_addInflowFlow(WET_WEATHER_INFLOW, q); - //... add pollutant load, based on parent subcatchment quality + //... add pollutant load, based on parent subcatchment quality for (p = 0; p < Nobjects[POLLUT]; p++) { //... get previous & current drain loads w1 = lidUnit->oldDrainFlow * Subcatch[j].oldQual[p]; - w2 = lidUnit->newDrainFlow * Subcatch[j].newQual[p]; + w2 = lidUnit->newDrainFlow * Subcatch[j].newQual[p]; //... add interpolated load to node's wet weather loading w = (1.0 - f) * w1 + f * w2; @@ -1612,7 +1615,7 @@ void lid_addDrainInflow(int j, double f) void lid_getRunoff(int j, double tStep) // // Purpose: computes runoff and drain flows from the LIDs in a subcatchment. -// Input: j = subcatchment index +// Input: j = subcatchment index // tStep = time step (sec) // Output: updates following global quantities after LID treatment applied: // Vevap, Vpevap, VlidInfil, VlidIn, VlidOut, VlidDrain. @@ -1624,10 +1627,10 @@ void lid_getRunoff(int j, double tStep) double lidArea; // area of an LID unit double qImperv = 0.0; // runoff from impervious areas (cfs) double qPerv = 0.0; // runoff from pervious areas (cfs) //(5.1.013) - double lidInflow = 0.0; // inflow to an LID unit (ft/s) + double lidInflow = 0.0; // inflow to an LID unit (ft/s) double qRunoff = 0.0; // surface runoff from all LID units (cfs) double qDrain = 0.0; // drain flow from all LID units (cfs) - double qReturn = 0.0; // LID outflow returned to pervious area (cfs) + double qReturn = 0.0; // LID outflow returned to pervious area (cfs) //... return if there are no LID's theLidGroup = LidGroups[j]; @@ -1645,7 +1648,7 @@ void lid_getRunoff(int j, double tStep) //... get impervious and pervious area runoff from non-LID // portion of subcatchment (cfs) if ( Subcatch[j].area > Subcatch[j].lidArea ) - { + { qImperv = getImpervAreaRunoff(j); qPerv = getPervAreaRunoff(j); //(5.1.013) } @@ -1678,7 +1681,7 @@ void lid_getRunoff(int j, double tStep) //... evaluate the LID unit's performance, updating the LID group's // total surface runoff, drain flow, and flow returned to - // pervious area + // pervious area evalLidUnit(j, lidUnit, lidArea, lidInflow, tStep, &qRunoff, &qDrain, &qReturn); } @@ -1690,7 +1693,7 @@ void lid_getRunoff(int j, double tStep) theLidGroup->flowToPerv = qReturn; //... save the LID group's total surface, drain and return flow volumes - VlidOut = qRunoff * tStep; + VlidOut = qRunoff * tStep; VlidDrain = qDrain * tStep; VlidReturn = qReturn * tStep; } @@ -1718,10 +1721,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. @@ -1823,7 +1826,7 @@ void evalLidUnit(int j, TLidUnit* lidUnit, double lidArea, double lidInflow, lidRunoff = lidproc_getOutflow(lidUnit, lidProc, lidInflow, EvapRate, NativeInfil, MaxNativeInfil, tStep, &lidEvap, &lidInfil, &lidDrain) * lidArea; - + //... convert drain flow to CFS lidDrain *= lidArea; @@ -1842,7 +1845,7 @@ void evalLidUnit(int j, TLidUnit* lidUnit, double lidArea, double lidInflow, lidDrain = 0.0; } } - + //... update system flow balance if drain flow goes to a // conveyance system node if ( lidUnit->drainNode >= 0 ) @@ -1910,7 +1913,7 @@ void lid_writeWaterBalance() "\n --------------------------------------------------------------------------------------------------------------------" "\n Total Evap Infil Surface Drain Initial Final Continuity" "\n Inflow Loss Loss Outflow Outflow Storage Storage Error"); - if ( UnitSystem == US ) fprintf(Frpt.file, + if ( UnitSystem == US ) fprintf(Frpt.file, "\n Subcatchment LID Control in in in in in in in %%"); else fprintf(Frpt.file, "\n Subcatchment LID Control mm mm mm mm mm mm mm %%"); @@ -1940,7 +1943,7 @@ void lid_writeWaterBalance() lidUnit->waterBalance.finalVol*ucf); //... compute flow balance error - inflow = lidUnit->waterBalance.initVol + + inflow = lidUnit->waterBalance.initVol + lidUnit->waterBalance.inflow; outflow = lidUnit->waterBalance.finalVol + lidUnit->waterBalance.evap + @@ -2018,8 +2021,8 @@ void initLidRptFile(char* title, char* lidID, char* subcatchID, TLidUnit* lidUni int lid_getLidUnitCount(int index) -// Input: index = Index of desired subcatchment -// Output: int = number of lid units for subcatchment +// Input: index = Index of desired subcatchment +// Output: int = number of lid units for subcatchment // Return: number of lid units for subcatchment // Purpose: count number of lid units for subcatchment { @@ -2028,7 +2031,7 @@ int lid_getLidUnitCount(int index) TLidGroup lidGroup; lidGroup = LidGroups[index]; - + if (lidGroup) { lidList = lidGroup->lidList; @@ -2045,13 +2048,13 @@ int lid_getLidUnitCount(int index) TLidUnit* lid_getLidUnit(int index, int lidIndex, int* errcode) // -// Input: index = Index of desired subcatchment +// Input: index = Index of desired subcatchment // lidIndex = Index of desired lid control (subcatchment allow for multiple lids) // errcode = ptr to errcode -// Output: TLidUnit = TLidUnit ptr -// Return: TLidUnit ptr +// Output: TLidUnit = TLidUnit ptr +// Return: TLidUnit ptr // Purpose: Gets lid unit (TLidUnit) ptr -{ +{ int currLidIndex = 0; int unitCount = 1; TLidUnit* lidUnit = NULL; @@ -2063,16 +2066,16 @@ TLidUnit* lid_getLidUnit(int index, int lidIndex, int* errcode) { *errcode = ERR_API_UNDEFINED_LID; } - else + else { lidList = lidGroup->lidList; // Patch solution for now // Realized the lid units are stored in reverse order of // how they are defined in the [LID USAGE] - // For now, I will just count the number of Lid Units in Lid List + // For now, I will just count the number of Lid Units in Lid List unitCount = lid_getLidUnitCount(index); - + if (lidIndex > (unitCount - 1)) { *errcode = ERR_API_LIDUNIT_INDEX; @@ -2082,7 +2085,7 @@ TLidUnit* lid_getLidUnit(int index, int lidIndex, int* errcode) { // update lidIndex due to reverse order lidIndex = unitCount - lidIndex - 1; - + // Traverse through lid list to find lid unit while ((lidList) && (currLidIndex <= lidIndex)) { @@ -2090,7 +2093,7 @@ TLidUnit* lid_getLidUnit(int index, int lidIndex, int* errcode) currLidIndex += 1; lidList = lidList->nextLidUnit; } - + // Verify that the lid unit found matches the one specified by the user if (!((currLidIndex - 1) == lidIndex)) { @@ -2106,8 +2109,8 @@ TLidUnit* lid_getLidUnit(int index, int lidIndex, int* errcode) TLidProc* lid_getLidProc(int index) // // Input: index = Index of desired lid control -// Output: ptr = TLidProc ptr -// Return: TLidProc ptr +// Output: ptr = TLidProc ptr +// Return: TLidProc ptr // Purpose: Gets lid process (TLidProc) ptr { TLidProc* ptr; @@ -2118,8 +2121,8 @@ TLidProc* lid_getLidProc(int index) TLidGroup lid_getLidGroup(int index) // -// Input: index = index of desired subcatchment -// Output: result = result data desired +// Input: index = index of desired subcatchment +// Output: result = result data desired // Return: TLidGroup ptr // Purpose: Gets lid group (TLidGroup) ptr { @@ -2131,7 +2134,7 @@ TLidGroup lid_getLidGroup(int index) void lid_validateLidProc(int index) // // Purpose: hook to lid internal function to validate LID process parameters. -// Input: index = Index of desired subcatchment +// Input: index = Index of desired subcatchment // Output: none { validateLidProc(index); @@ -2141,7 +2144,7 @@ void lid_validateLidProc(int index) void lid_validateLidGroup(int index) // // Purpose: hook to lid internal function to validate LID process parameters. -// Input: index = Index of desired subcatchment +// Input: index = Index of desired subcatchment // Output: none { validateLidGroup(index); @@ -2160,14 +2163,14 @@ void lid_updateLidUnit(TLidUnit* lidUnit, int subIndex) lid_validateLidGroup(subIndex); if (LidProcs[lidIndex].soil.thickness > 0.0) { - lidUnit->soilMoisture = LidProcs[lidIndex].soil.wiltPoint + - lidUnit->initSat * (LidProcs[lidIndex].soil.porosity - + lidUnit->soilMoisture = LidProcs[lidIndex].soil.wiltPoint + + lidUnit->initSat * (LidProcs[lidIndex].soil.porosity - LidProcs[lidIndex].soil.wiltPoint); } if (LidProcs[lidIndex].storage.thickness > 0.0) { - lidUnit->storageDepth = lidUnit->initSat * + lidUnit->storageDepth = lidUnit->initSat * LidProcs[lidIndex].storage.thickness; } @@ -2227,7 +2230,7 @@ void lid_updateLidGroup(int index) if (area > 0.0 && Subcatch[index].subArea[i].N > 0.0) { - Subcatch[index].subArea[i].alpha = 1.49 * Subcatch[index].width / area * + Subcatch[index].subArea[i].alpha = 1.49 * Subcatch[index].width / area * sqrt(Subcatch[index].slope) / Subcatch[index].subArea[i].N; } } @@ -2248,7 +2251,7 @@ void lid_updateLidGroup(int index) void lid_updateAllLidUnit(int lidIndex) { -// +// // Purpose: update all lid unit parameters due to change in lid control parameters // Input: lidIndex = Index of desired lid control (subcatchment allow for multiple lids) // Output: none @@ -2279,4 +2282,4 @@ void lid_updateAllLidUnit(int lidIndex) } } -} \ No newline at end of file +} diff --git a/src/solver/lid.h b/src/solver/lid.h index abd5bfb48..d36ecda72 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. @@ -160,7 +161,7 @@ typedef struct double finalVol; // final stored volume (ft) } TWaterBalance; -// +// typedef struct { double evap; // evaporation rate (ft/s) @@ -203,7 +204,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 @@ -211,7 +212,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) @@ -268,7 +269,7 @@ void lid_writeWaterBalance(void); int lid_getLidUnitCount(int index); TLidUnit* lid_getLidUnit(int index, int lidIndex, int* errcode); TLidProc* lid_getLidProc(int index); -TLidGroup lid_getLidGroup(int index); +TLidGroup lid_getLidGroup(int index); void lid_validateLidProc(int index); void lid_validateLidGroup(int index); void lid_updateLidUnit(TLidUnit* lidUnit, int subIndex); @@ -284,4 +285,6 @@ 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 b74909d8c..f2445097d 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 96e09e158..265d0409f 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" @@ -109,8 +118,8 @@ typedef struct typedef struct { char* ID; // raingage name - double externalRain; // rainfall-rate injected RAIN API - int dataSource; // data from time series or file + double externalRain; // rainfall-rate injected RAIN API + 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 @@ -134,7 +143,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; //------------------- @@ -142,7 +151,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) @@ -190,11 +199,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; //------------------- @@ -262,7 +271,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 @@ -370,6 +379,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) @@ -390,7 +400,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) @@ -516,7 +526,7 @@ typedef struct double* newQual; // current quality state double* extQual; // external quality state double* inQual; // inflow quality state - double* reactorQual; // concentration in the mixed reactor + double* reactorQual; // concentration in the mixed reactor double oldFlowInflow; // previous flow inflow double oldNetInflow; // previous net inflow } TNode; @@ -549,7 +559,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; @@ -601,10 +611,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 @@ -621,7 +631,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 @@ -670,8 +680,8 @@ typedef struct double* oldQual; // previous quality state double* newQual; // current quality state double* totalLoad; // total quality mass loading - double* extQual; // external quality state - double* reactorQual; // concentration in the mixed reactor + double* extQual; // external quality state + double* reactorQual; // concentration in the mixed reactor int flowClass; // flow classification double dqdh; // change in flow w.r.t. head (ft2/sec) signed char direction; // flow direction flag @@ -712,10 +722,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; @@ -846,7 +856,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 @@ -918,6 +928,7 @@ typedef SM_RoutingTotals TRoutingTotals; //----------------------- // SYSTEM-WIDE STATISTICS //----------------------- +#define TIMELEVELS 6 //(5.1.015) typedef struct { double minTimeStep; @@ -925,6 +936,8 @@ typedef struct double avgTimeStep; double avgStepCount; double steadyStateCount; + double timeStepIntervals[TIMELEVELS]; //(5.1.015) + int timeStepCounts[TIMELEVELS]; //(5.1.015) } TSysStats; //-------------------- @@ -949,7 +962,7 @@ typedef struct // double evap; // double infil; // double runoff; -// double maxFlow; +// double maxFlow; // double impervRunoff; //(5.1.013) // double pervRunoff; // // } TSubcatchStats; @@ -1003,13 +1016,13 @@ typedef SM_StorageStats TStorageStats; // { // double avgFlow; // double maxFlow; -// double* totalLoad; +// double* totalLoad; // int totalPeriods; // } TOutfallStats; typedef SM_OutfallStats TOutfallStats; -//---------------- +//---------------- // PUMP STATISTICS //---------------- // typedef struct @@ -1060,15 +1073,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 70b5a8c56..7f092ca2d 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 @@ -1019,7 +1022,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 fd94ccd60..d8a933beb 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 @@ -466,8 +469,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 07598b98a..07c6bd968 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 @@ -89,7 +94,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) //============================================================================= @@ -1038,10 +1043,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"); @@ -1064,9 +1070,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 cd571c537..b23d015c1 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; javgDepth *= (UCF(LENGTH) / (double)StepCount); + (*nodeStats)->avgDepth *= (UCF(LENGTH) / (double)ReportStepCount); // Current Maximum Depth (*nodeStats)->maxDepth *= UCF(LENGTH); // Current Maximum Lateral Inflow @@ -841,12 +877,12 @@ int stats_getStorageStat(int index, TStorageStats **storageStats) int k = Node[index].subIndex; // Copy Structure memcpy(*storageStats, &StorageStats[k], sizeof(TStorageStats)); - + // Convert units // Initial Volume (*storageStats)->initVol *= UCF(VOLUME); // Current Average Volume - (*storageStats)->avgVol *= (UCF(VOLUME) / (double)StepCount); + (*storageStats)->avgVol *= (UCF(VOLUME) / (double)ReportStepCount); // Current Maximum Volume (*storageStats)->maxVol *= UCF(VOLUME); // Current Maximum Flow @@ -872,7 +908,7 @@ int stats_getOutfallStat(int index, TOutfallStats **outfallStats) // fetch sub index k = Node[index].subIndex; - + // Copy Structure temp = (*outfallStats)->totalLoad; memcpy(*outfallStats, &(OutfallStats[k]), sizeof(TOutfallStats)); @@ -937,7 +973,7 @@ int stats_getLinkStat(int index, TLinkStats **linkStats) (*linkStats)->timeCapacityLimited /= 3600.0; // Cumulative Time Courant Critical Flow (*linkStats)->timeCourantCritical /= 3600.0; - + return 0; } diff --git a/src/solver/statsrpt.c b/src/solver/statsrpt.c index 4c5d90b76..b08851abf 100644 --- a/src/solver/statsrpt.c +++ b/src/solver/statsrpt.c @@ -9,6 +9,7 @@ // 04/30/15 (Build 5.1.009) // 08/01/16 (Build 5.1.011) // 05/10/18 (Build 5.1.013) +// 04/01/20 (Build 5.1.015) // Author: L. Rossman // // Report writing functions for summary statistics. @@ -26,6 +27,9 @@ // // Build 5.1.013: // - Pervious and impervious runoff added to Subcatchment Runoff Summary. +// +// Build 5.1.015: +// - Fixes bug in summary statistics when Report Start date > 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 @@ -1161,7 +1165,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. // { @@ -1169,22 +1173,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 517436d62..9051da5fc 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 @@ -39,6 +40,8 @@ // - 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 @@ -287,7 +290,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; @@ -424,7 +428,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; } @@ -450,7 +454,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 ) @@ -464,7 +468,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; } @@ -488,7 +492,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; @@ -799,7 +803,7 @@ void writecon(char *s) // Purpose: writes string of characters to the console. // { - fprintf(stdout,"%s", s); + fprintf(stdout,"%s",s); fflush(stdout); } diff --git a/src/solver/text.h b/src/solver/text.h index f8224a77c..204f6d518 100644 --- a/src/solver/text.h +++ b/src/solver/text.h @@ -15,23 +15,28 @@ // 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 //----------------------------------------------------------------------------- -//#include "consts.h" +#ifndef TEXT_H +#define TEXT_H + -//#define FMT01 \ -// "\tswmm5 \n" +#define FMT01 \ + "\tswmm5 \n" #define FMT03 " There are errors.\n" #define FMT04 " There are warnings.\n" #define FMT05 "\n" #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 "SEMVERSION_MAJOR"."SEMVERSION_MINOR"."SEMVERSION_PATCH")" //(5.1.014) +#define FMT08 \ + "\n EPA STORM WATER MANAGEMENT MODEL - VERSION 5.1 (Build 5.1.015)" //(5.1.015) #define FMT09 \ "\n --------------------------------------------------------------" #define FMT10 "\n" @@ -445,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 17f17d546..ebb0f397b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,7 +9,6 @@ # - #Prep ourselves for compiling with boost include(../extern/boost.cmake)