diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 2e2d3ee1f..c224b9e7d 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -144,7 +144,7 @@ jobs: - name: Before reg test env: NRTESTS_URL: https://github.com/OpenWaterAnalytics/swmm-nrtestsuite - BENCHMARK_TAG: v3.0.0 + BENCHMARK_TAG: v3.0.1 run: ./${{ matrix.before_reg_test }} ${{ env.BENCHMARK_TAG }} - name: Run reg test diff --git a/CMakeLists.txt b/CMakeLists.txt index d73d30e59..ae4b46e40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # CMakeLists.txt - CMake configuration file for swmm-solver # # Created: July 11, 2019 -# Updated: May 19, 2021 +# Modified: Aug 16, 2022 # # Authors: Michael E. Tryby # US EPA ORD/CESER @@ -22,7 +22,7 @@ endif() project(swmm-solver - VERSION 5.2.1 + VERSION 5.2.2 LANGUAGES C CXX ) diff --git a/README.md b/README.md index e5c747a1b..8ec778bbd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Stormwater-Management-Model -ORD Stormwater Management Model (aka "SWMM") +Stormwater Management Model (aka "SWMM") solver only ## Introduction This is the open source SWMM source code repository maintained by the Open diff --git a/src/solver/consts.h b/src/solver/consts.h index 23000bbdb..ec465336d 100644 --- a/src/solver/consts.h +++ b/src/solver/consts.h @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 06/01/22 (Build 5.2.1) +// Date: 10/18/22 (Build 5.2.2) // Author: L. Rossman // // Various Constants @@ -17,7 +17,7 @@ //------------------ // OWA Version string stored in version.h -// #define VERSION 52001 +// #define VERSION 52002 #define MAGICNUMBER 516114522 #define EOFMARK 0x1A // Use 0x04 for UNIX systems #define MAXTITLE 3 // Max. # title lines diff --git a/src/solver/controls.c b/src/solver/controls.c index 34e3612cc..b46054006 100644 --- a/src/solver/controls.c +++ b/src/solver/controls.c @@ -1198,8 +1198,8 @@ void updateActionList(struct TAction* a) listItem->next = ActionList; ActionList = listItem; } - listItem->action = a; - } + listItem->action = a; +} //============================================================================= diff --git a/src/solver/enums.h b/src/solver/enums.h index 22b514274..b1946778c 100644 --- a/src/solver/enums.h +++ b/src/solver/enums.h @@ -116,18 +116,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 @@ -197,7 +197,7 @@ //------------------------------------- // Computed node quantities //------------------------------------- - #define MAX_NODE_RESULTS 7 + #define MAX_NODE_RESULTS 7 enum NodeResultType { NODE_DEPTH, // water depth above invert NODE_HEAD, // hydraulic head @@ -418,7 +418,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 TYPE5_PUMP, // variable speed version of TYPE3 pump diff --git a/src/solver/funcs.h b/src/solver/funcs.h index aad84fc04..15f272ffa 100644 --- a/src/solver/funcs.h +++ b/src/solver/funcs.h @@ -93,7 +93,7 @@ void report_writeTimeStepStats(TTimeStepStats* timeStepStats); void report_writeErrorMsg(int code, char* msg); void report_writeErrorCode(void); void report_writeInputErrorMsg(int k, int sect, char* line, long lineCount); -void report_writeWarningMsg(char* msg, char* id); +void report_writeWarningMsg(char* msg, char* id); void report_writeTseriesErrorMsg(int code, TTable *tseries); void inputrpt_writeInput(void); @@ -496,7 +496,7 @@ void controls_addToCount(char* s); int controls_addVariable(char* tok[], int ntoks); int controls_addExpression(char* tok[], int ntoks); int controls_addRuleClause(int rule, int keyword, char* Tok[], int nTokens); -int controls_evaluate(DateTime currentTime, DateTime elapsedTime, +int controls_evaluate(DateTime currentTime, DateTime elapsedTime, double tStep); //----------------------------------------------------------------------------- diff --git a/src/solver/gage.c b/src/solver/gage.c index 84e0af2da..d8e4e2b4f 100644 --- a/src/solver/gage.c +++ b/src/solver/gage.c @@ -406,7 +406,7 @@ void gage_setState(int j, DateTime t) // --- otherwise update next rainfall interval date Gage[j].startDate = Gage[j].nextDate; Gage[j].endDate = datetime_addSeconds(Gage[j].startDate, - Gage[j].rainInterval); + Gage[j].rainInterval); Gage[j].rainfall = Gage[j].nextRainfall; if ( !getNextRainfall(j) ) Gage[j].nextDate = NO_DATE; } @@ -670,11 +670,11 @@ int getNextRainfall(int j) { if ( Frain.file && Gage[j].currentFilePos < Gage[j].endFilePos ) { - fseek(Frain.file, Gage[j].currentFilePos, SEEK_SET); - fread(&Gage[j].nextDate, sizeof(DateTime), 1, Frain.file); - fread(&vNext, sizeof(float), 1, Frain.file); - Gage[j].currentFilePos = ftell(Frain.file); - rNext = convertRainfall(j, (double)vNext); + fseek(Frain.file, Gage[j].currentFilePos, SEEK_SET); + fread(&Gage[j].nextDate, sizeof(DateTime), 1, Frain.file); + fread(&vNext, sizeof(float), 1, Frain.file); + Gage[j].currentFilePos = ftell(Frain.file); + rNext = convertRainfall(j, (double)vNext); } else return 0; } @@ -684,9 +684,9 @@ int getNextRainfall(int j) k = Gage[j].tSeries; if ( k >= 0 ) { - if ( !table_getNextEntry(&Tseries[k], - &Gage[j].nextDate, &rNext) ) return 0; - rNext = convertRainfall(j, rNext); + if ( !table_getNextEntry(&Tseries[k], + &Gage[j].nextDate, &rNext) ) return 0; + rNext = convertRainfall(j, rNext); } else return 0; } diff --git a/src/solver/globals.h b/src/solver/globals.h index 193903697..cdc04eac3 100644 --- a/src/solver/globals.h +++ b/src/solver/globals.h @@ -19,7 +19,7 @@ // - Minimum dynamic wave routing variable time step added. // 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. // Build 5.1.012: diff --git a/src/solver/inlet.c b/src/solver/inlet.c index 1ec914c4d..4defe127e 100644 --- a/src/solver/inlet.c +++ b/src/solver/inlet.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 06/01/22 (Build 5.2.1) +// Date: 10/08/22 (Build 5.2.2) // Author: L. Rossman // // Street/Channel Inlet Functions @@ -16,6 +16,8 @@ // // Build 5.2.1: // - Substitutes the constant BIG for HUGE. +// Build 5.2.2: +// - Additional statistics added to Street Flow Summary table. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -1030,17 +1032,18 @@ void writeStreetStatsHeader() report_writeLine("*******************"); report_writeLine(""); fprintf(Frpt.file, -"\n ----------------------------------------------------------------------------------------------------------------------" -"\n Peak Maximum Maximum Peak Flow Average Bypass BackFlow" -"\n Flow Spread Depth Inlet Inlet Capture Capture Frequency Frequency"); +"\n ---------------------------------------------------------------------------------------------------------------------------------------" +"\n Peak Avg. Bypass Back Peak Peak" +"\n Peak Maximum Maximum Flow Flow Flow Flow Capture Bypass" +"\n Flow Spread Depth Inlet Inlet Inlet Capture Capture Freq Freq / Inlet Flow"); if (UnitSystem == US) fprintf(Frpt.file, -"\n Street Conduit %3s ft ft Design Location %% %% %% %%", - FlowUnitWords[FlowUnits]); +"\n Street Conduit %3s ft ft Design Location Count Pcnt Pcnt Pcnt Pcnt %3s %3s", + FlowUnitWords[FlowUnits], FlowUnitWords[FlowUnits], FlowUnitWords[FlowUnits]); else fprintf(Frpt.file, -"\n Street Conduit %3s m m Design Location %% %% %% %%", - FlowUnitWords[FlowUnits]); +"\n Street Conduit %3s m m Design Location Pcnt Pcnt Pcnt Pcnt %3s %3s", + FlowUnitWords[FlowUnits], FlowUnitWords[FlowUnits], FlowUnitWords[FlowUnits]); fprintf(Frpt.file, -"\n ----------------------------------------------------------------------------------------------------------------------"); +"\n ---------------------------------------------------------------------------------------------------------------------------------------"); } //============================================================================= @@ -1095,19 +1098,24 @@ void writeStreetStats(int link) fprintf(Frpt.file, " ON-GRADE"); else fprintf(Frpt.file, " ON-SAG "); + fprintf(Frpt.file, " %5d", inlet->numInlets); fp = inlet->stats.flowPeriods / 100.0; if (fp > 0.0) { cp = inlet->stats.capturePeriods / 100.0; - fprintf(Frpt.file, " %9.2f", inlet->stats.peakFlowCapture); + fprintf(Frpt.file, " %7.2f", inlet->stats.peakFlowCapture); if (cp > 0.0) { afc = inlet->stats.avgFlowCapture / cp; bpf = inlet->stats.bypassFreq / cp; } - fprintf(Frpt.file, " %9.2f", afc); - fprintf(Frpt.file, " %9.2f", bpf); - fprintf(Frpt.file, " %9.2f", inlet->stats.backflowPeriods / fp); + fprintf(Frpt.file, " %7.2f", afc); + fprintf(Frpt.file, " %7.2f", bpf); + fprintf(Frpt.file, " %7.2f", inlet->stats.backflowPeriods / fp); + fprintf(Frpt.file, " %7.2f", (maxFlow / Street[t].sides) * UCF(FLOW) * + 0.01 * inlet->stats.peakFlowCapture / inlet->numInlets); + fprintf(Frpt.file, " %7.2f", maxFlow * UCF(FLOW) * 0.01 * + (100.0 - inlet->stats.peakFlowCapture)); } } } diff --git a/src/solver/lid.c b/src/solver/lid.c index d9a0c7e78..e471e2941 100644 --- a/src/solver/lid.c +++ b/src/solver/lid.c @@ -356,7 +356,7 @@ int lid_readProcParams(char* toks[], int ntoks) // LID_ID STORAGE // LID_ID DRAIN // LID_ID DRAINMAT -// LID_ID REMOVALS +// LID_ID REMOVALS // { int j, m; @@ -712,7 +712,7 @@ int readStorageData(int j, char* toks[], int ntoks) // Output: returns error code // // Format of data is: -// LID_ID STORAGE Thickness VoidRatio Ksat ClogFactor (YES/NO) +// LID_ID STORAGE Thickness VoidRatio Ksat ClogFactor (YES/NO) // { int i; @@ -1638,7 +1638,7 @@ 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) - 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) diff --git a/src/solver/lid.h b/src/solver/lid.h index c3ff11592..565cdb0b4 100644 --- a/src/solver/lid.h +++ b/src/solver/lid.h @@ -15,7 +15,7 @@ // - Support added for separate routing of LID drain flows. // - 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: // - Redefined meaning of wasDry in TLidRptFile structure. @@ -47,8 +47,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 @@ -69,7 +69,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. @@ -204,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 @@ -212,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) diff --git a/src/solver/link.c b/src/solver/link.c index b93cdfbaa..052a030b9 100644 --- a/src/solver/link.c +++ b/src/solver/link.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 06/01/22 (Build 5.2.1) +// Date: 10/29/22 (Build 5.2.2) // Author: L. Rossman // M. Tryby (EPA) // @@ -44,6 +44,8 @@ // - Support added for variable speed pumps. // Build 5.2.1 // - Warning no longer issued when conduit elevation drop < MIN_DELTA_Z. +// Build 5.2.2: +// - Warning for conduit elevation drop < MIN_DELTA_Z restored. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -1264,9 +1266,7 @@ double conduit_getSlope(int j) delta = fabs(elev1 - elev2); if ( delta < MIN_DELTA_Z ) { - /* Deprecated as of v.5.2.1 report_writeWarningMsg(WARN04, Link[j].ID); - */ delta = MIN_DELTA_Z; } diff --git a/src/solver/mathexpr.c b/src/solver/mathexpr.c index 2ce4d423d..c39dff7e1 100644 --- a/src/solver/mathexpr.c +++ b/src/solver/mathexpr.c @@ -6,9 +6,9 @@ ** operators. ** AUTHORS: L. Rossman, US EPA - NRMRL ** F. Shang, University of Cincinnati -** VERSION: 5.2.0 -** LAST UPDATE: 11/01/21 -** BUG FIXES: Problems related to '^' operator (L.Rossman, 11/01/21) +** VERSION: 5.2.2 +** LAST UPDATE: 09/02/2022 +** BUG FIXES: Problems related to '^' operator (F. Shang, 09/02/2022) ******************************************************************************/ /* ** Operand codes: @@ -34,12 +34,12 @@ ** 20 = acos ** 21 = atan ** 22 = acot -** 23 = sinh +** 23 = sinh ** 24 = cosh ** 25 = tanh ** 26 = coth ** 27 = log10 -** 28 = step (x<=0 ? 0 : 1) +** 28 = step (x<=0 ? 0 : 1) ** 31 = ^ ******************************************************************************/ #define _CRT_SECURE_NO_DEPRECATE @@ -190,6 +190,7 @@ double getNumber() char c[] = " "; char sNumber[255]; int errflag = 0; + int decimalCount = 0; /* --- get whole number portion of number */ sNumber[0] = '\0'; @@ -205,6 +206,8 @@ double getNumber() { if (S[Pos] == '.') { + decimalCount++; + if (decimalCount > 1) Err = 1; strcat(sNumber, "."); Pos++; while (Pos < Len && isDigit(S[Pos])) @@ -257,7 +260,7 @@ int getOperand() case '-': code = 4; if (Pos < Len-1 && isDigit(S[Pos+1]) && - (CurLex == 0 || CurLex == 1)) + (CurLex <= 6 || CurLex == 31)) { Pos++; Fvalue = -getNumber(); @@ -294,7 +297,7 @@ int getLex() n = getMathFunc(); if ( n == 0 ) n = getVariable(); } - else if ( isDigit(S[Pos]) ) + else if ( S[Pos] == '.' || isDigit(S[Pos]) ) { n = 7; Fvalue = getNumber(); @@ -330,6 +333,7 @@ ExprTree * getSingleOp(int *lex) { int opcode; ExprTree *left; + ExprTree *node; /* --- open parenthesis, so continue to grow the tree */ if ( *lex == 1 ) @@ -374,6 +378,17 @@ ExprTree * getSingleOp(int *lex) } } *lex = getLex(); + + /* --- exponentiation */ + if (*lex == 31) + { + node = newNode(); + node->left = left; + node->opcode = *lex; + *lex = getLex(); + node->right = getSingleOp(lex); + left = node; + } return left; } @@ -398,7 +413,7 @@ ExprTree * getOp(int *lex) else if ( *lex == 3) *lex = getLex(); } left = getSingleOp(lex); - while ( *lex == 5 || *lex == 6 || *lex == 31) + while ( *lex == 5 || *lex == 6) { opcode = *lex; *lex = getLex(); @@ -518,88 +533,88 @@ double mathexpr_eval(MathExpr *expr, double (*getVariableValue) (int)) case 3: r1 = ExprStack[stackindex]; stackindex--; - if (stackindex < 0) break; + if (stackindex < 0) break; r2 = ExprStack[stackindex]; ExprStack[stackindex] = r2 + r1; break; - case 4: - r1 = ExprStack[stackindex]; + case 4: + r1 = ExprStack[stackindex]; stackindex--; - if (stackindex < 0) break; + if (stackindex < 0) break; r2 = ExprStack[stackindex]; ExprStack[stackindex] = r2 - r1; break; - case 5: - r1 = ExprStack[stackindex]; + case 5: + r1 = ExprStack[stackindex]; stackindex--; - if (stackindex < 0) break; + if (stackindex < 0) break; r2 = ExprStack[stackindex]; ExprStack[stackindex] = r2 * r1; break; - case 6: + case 6: r1 = ExprStack[stackindex]; stackindex--; - if (stackindex < 0) break; - r2 = ExprStack[stackindex]; + if (stackindex < 0) break; + r2 = ExprStack[stackindex]; ExprStack[stackindex] = r2 / r1; break; - case 7: + case 7: stackindex++; - if (stackindex >= MAX_STACK_SIZE) break; + if (stackindex >= MAX_STACK_SIZE) break; ExprStack[stackindex] = node->fvalue; break; - case 8: - if (getVariableValue != NULL) - { - r1 = getVariableValue(node->ivar); - } - else r1 = 0.0; + case 8: + if (getVariableValue != NULL) + { + r1 = getVariableValue(node->ivar); + } + else r1 = 0.0; stackindex++; - if (stackindex >= MAX_STACK_SIZE) break; - ExprStack[stackindex] = r1; + if (stackindex >= MAX_STACK_SIZE) break; + ExprStack[stackindex] = r1; break; - case 9: + case 9: ExprStack[stackindex] = -ExprStack[stackindex]; break; - case 10: + case 10: r1 = ExprStack[stackindex]; r2 = cos(r1); ExprStack[stackindex] = r2; break; - case 11: + case 11: r1 = ExprStack[stackindex]; r2 = sin(r1); ExprStack[stackindex] = r2; break; - case 12: + case 12: r1 = ExprStack[stackindex]; r2 = tan(r1); ExprStack[stackindex] = r2; break; - case 13: + case 13: r1 = ExprStack[stackindex]; if (r1 == 0.0) r2 = 0.0; else r2 = 1.0/tan( r1 ); ExprStack[stackindex] = r2; break; - case 14: + case 14: r1 = ExprStack[stackindex]; r2 = fabs( r1 ); ExprStack[stackindex] = r2; break; - case 15: + case 15: r1 = ExprStack[stackindex]; if (r1 < 0.0) r2 = -1.0; else if (r1 > 0.0) r2 = 1.0; @@ -607,93 +622,93 @@ double mathexpr_eval(MathExpr *expr, double (*getVariableValue) (int)) ExprStack[stackindex] = r2; break; - case 16: + case 16: r1 = ExprStack[stackindex]; if (r1 < 0.0) r2 = 0.0; else r2 = sqrt( r1 ); ExprStack[stackindex] = r2; break; - case 17: + case 17: r1 = ExprStack[stackindex]; if (r1 <= 0) r2 = 0.0; else r2 = log(r1); ExprStack[stackindex] = r2; break; - case 18: + case 18: r1 = ExprStack[stackindex]; r2 = exp(r1); ExprStack[stackindex] = r2; break; - case 19: + case 19: r1 = ExprStack[stackindex]; r2 = asin( r1 ); ExprStack[stackindex] = r2; break; - case 20: + case 20: r1 = ExprStack[stackindex]; r2 = acos( r1 ); ExprStack[stackindex] = r2; break; - case 21: + case 21: r1 = ExprStack[stackindex]; r2 = atan( r1 ); ExprStack[stackindex] = r2; break; - case 22: + case 22: r1 = ExprStack[stackindex]; r2 = 1.57079632679489661923 - atan(r1); ExprStack[stackindex] = r2; break; - case 23: + case 23: r1 = ExprStack[stackindex]; r2 = (exp(r1)-exp(-r1))/2.0; ExprStack[stackindex] = r2; break; - case 24: + case 24: r1 = ExprStack[stackindex]; r2 = (exp(r1)+exp(-r1))/2.0; ExprStack[stackindex] = r2; break; - case 25: + case 25: r1 = ExprStack[stackindex]; r2 = (exp(r1)-exp(-r1))/(exp(r1)+exp(-r1)); ExprStack[stackindex] = r2; break; - case 26: + case 26: r1 = ExprStack[stackindex]; r2 = (exp(r1)+exp(-r1))/(exp(r1)-exp(-r1)); ExprStack[stackindex] = r2; break; - case 27: + case 27: r1 = ExprStack[stackindex]; if (r1 == 0.0) r2 = 0.0; else r2 = log10( r1 ); ExprStack[stackindex] = r2; break; - case 28: + case 28: r1 = ExprStack[stackindex]; if (r1 <= 0.0) r2 = 0.0; else r2 = 1.0; ExprStack[stackindex] = r2; break; - case 31: + case 31: r1 = ExprStack[stackindex]; - stackindex--; - if (stackindex < 0) break; - r2 = ExprStack[stackindex]; + stackindex--; + if (stackindex < 0) break; + r2 = ExprStack[stackindex]; if (r2 <= 0.0) r2 = 0.0; else r2 = pow(r2, r1); ExprStack[stackindex] = r2; @@ -741,9 +756,9 @@ MathExpr * mathexpr_create(char *formula, int (*getVar) (char *)) tree = getTree(); if (Bc == 0 && Err == 0) { - traverseTree(tree, &expr); - while (expr) - { + traverseTree(tree, &expr); + while (expr) + { result = expr; expr = expr->prev; } diff --git a/src/solver/node.c b/src/solver/node.c index c3ad97aad..2c8fa2501 100644 --- a/src/solver/node.c +++ b/src/solver/node.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 06/01/22 (Build 5.2.1) +// Date: 10/29/22 (Build 5.2.2) // Author: L. Rossman // // Conveyance system node functions. @@ -34,6 +34,9 @@ // - Warning no longer issued when node full depth is increased to match // crown of highest connecting link. // - a2 term for paraboloid shaped storage units was corrected +// Build 5.2.2: +// - Warning restored for node full depth being increased to crown of highest +// connecting link. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -204,12 +207,11 @@ void node_validate(int j) TDwfInflow* inflow; // --- see if full depth was increased to accommodate conduit crown -/* Deprecated as of v.5.2.1 if ( Node[j].fullDepth > Node[j].oldDepth && Node[j].oldDepth > 0.0 ) { report_writeWarningMsg(WARN02, Node[j].ID); } -*/ + // --- check that initial depth does not exceed max. depth if ( Node[j].initDepth > Node[j].fullDepth + Node[j].surDepth ) report_writeErrorMsg(ERR_NODE_DEPTH, Node[j].ID); @@ -1096,7 +1098,7 @@ double storage_getLosses(int j, double tStep) exfilRate *= lossRatio; } } - + // --- save evap & infil losses at the node Storage[Node[j].subIndex].evapLoss = evapRate * tStep; Storage[Node[j].subIndex].exfilLoss = exfilRate * tStep; diff --git a/src/solver/objects.h b/src/solver/objects.h index 2e5146444..07f5129fd 100644 --- a/src/solver/objects.h +++ b/src/solver/objects.h @@ -147,7 +147,7 @@ typedef struct int pastInterval; // seconds since pastRain last updated 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; //------------------- @@ -203,11 +203,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; //------------------- @@ -404,7 +404,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) @@ -568,7 +568,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; @@ -620,10 +620,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 @@ -751,10 +751,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; @@ -1115,14 +1115,14 @@ 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 diff --git a/src/solver/project.c b/src/solver/project.c index a9bc162a3..55a0866c8 100644 --- a/src/solver/project.c +++ b/src/solver/project.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 11/01/21 (Build 5.2.0) +// Date: 11/21/22 (Build 5.2.2) // Author: L. Rossman // // Project management functions. @@ -49,6 +49,9 @@ // - Support added for Streets and Inlets. // - Support added for RptFlags.disabled option. // - Object's rptFlag changed to record its index in output file. +// Build 5.2.2: +// - Default number of threads changed from OMP max. number to 1 +// to be consistent with User Manual. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -64,7 +67,7 @@ #endif #include "headers.h" -#include "lid.h" +#include "lid.h" #include "hash.h" #include "mempool.h" @@ -72,7 +75,7 @@ // Shared variables //----------------------------------------------------------------------------- static HTtable* Htable[MAX_OBJ_TYPES]; // Hash tables for object ID names -static char MemPoolAllocated; // TRUE if memory pool allocated +static char MemPoolAllocated; // TRUE if memory pool allocated //----------------------------------------------------------------------------- // External Functions (declared in funcs.h) @@ -290,7 +293,7 @@ int project_init(void) // Input: none // Output: returns an error code // Purpose: initializes the internal state of all objects. -// +// { int j, k; climate_initState(); @@ -508,7 +511,7 @@ int project_readOption(char* s1, char* s2) // --- simulation ending date case END_DATE: - if ( !datetime_strToDate(s2, &EndDate) ) + if ( !datetime_strToDate(s2, &EndDate) ) { return error_setInpError(ERR_DATETIME, s2); } @@ -626,8 +629,8 @@ int project_readOption(char* s1, char* s2) } break; - case NORMAL_FLOW_LTD: - m = findmatch(s2, NormalFlowWords); + case NORMAL_FLOW_LTD: + m = findmatch(s2, NormalFlowWords); if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2); NormalFlowLtd = m; break; @@ -704,7 +707,7 @@ int project_readOption(char* s1, char* s2) break; // --- minimum surface area (ft2 or sq. meters) associated with nodes - // under dynamic wave flow routing + // under dynamic wave flow routing case MIN_SURFAREA: if (!getDouble(s2, &MinSurfArea)) return error_setInpError(ERR_NUMBER, s2); @@ -821,7 +824,7 @@ void setDefaults() // Interface files Frain.mode = SCRATCH_FILE; // Use scratch rainfall file - Fclimate.mode = NO_FILE; + Fclimate.mode = NO_FILE; Frunoff.mode = NO_FILE; Frdii.mode = NO_FILE; Fhotstart1.mode = NO_FILE; @@ -852,14 +855,14 @@ void setDefaults() 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.0; // No variable time step 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 + SkipSteadyState = FALSE; // Do flow routing in steady state periods IgnoreRainfall = FALSE; // Analyze rainfall/runoff IgnoreRDII = FALSE; // Analyze RDII - IgnoreSnowmelt = FALSE; // Analyze snowmelt - IgnoreGwater = FALSE; // Analyze groundwater + IgnoreSnowmelt = FALSE; // Analyze snowmelt + IgnoreGwater = FALSE; // Analyze groundwater IgnoreRouting = FALSE; // Analyze flow routing IgnoreQuality = FALSE; // Analyze water quality WetStep = 300; // Runoff wet time step (secs) @@ -869,15 +872,15 @@ void setDefaults() MinRouteStep = 0.5; // Minimum variable time step (sec) ReportStep = 900; // Reporting time step (secs) StartDryDays = 0.0; // Antecedent dry days - MaxTrials = 0; // Force use of default max. trials + MaxTrials = 0; // Force use of default max. trials HeadTol = 0.0; // Force use of default head tolerance SysFlowTol = 0.05; // System flow tolerance for steady state LatFlowTol = 0.05; // Lateral flow tolerance for steady state - NumThreads = 0; // Number of parallel threads to use + NumThreads = 1; // Number of parallel threads to use NumEvents = 0; // Number of detailed routing events // Deprecated options - SlopeWeighting = TRUE; // Use slope weighting + SlopeWeighting = TRUE; // Use slope weighting Compatibility = SWMM4; // Use SWMM 4 up/dn weighting method // Starting & ending date/time @@ -934,7 +937,7 @@ void setDefaults() Evap.panCoeff[i] = 1.0; } Evap.recoveryPattern = -1; - Evap.recoveryFactor = 1.0; + Evap.recoveryFactor = 1.0; Evap.tSeries = -1; Evap.dryOnly = FALSE; diff --git a/src/solver/qualrout.c b/src/solver/qualrout.c index d535d9a25..d9c640f79 100644 --- a/src/solver/qualrout.c +++ b/src/solver/qualrout.c @@ -107,7 +107,7 @@ void qualrout_execute(double tStep) { int i, j; double qIn, vAvg; - + // --- find mass flow each link contributes to its downstream node for ( i = 0; i < Nobjects[LINK]; i++ ) findLinkMassFlow(i, tStep); @@ -125,7 +125,7 @@ void qualrout_execute(double tStep) if ( qIn < ZERO ) qIn = 0.0; treatmnt_setInflow(qIn, Node[j].newQual); } - + // --- find new quality at the node if ( Node[j].type == STORAGE || Node[j].oldVolume > ZeroVolume ) { @@ -330,7 +330,7 @@ void findLinkQual(int i, double tStep) // --- start with concen. at start of time step c1 = Link[i].oldQual[p]; - // --- update mass balance accounting for seepage loss + // --- update mass balance accounting for seepage loss massbal_addSeepageLoss(p, qSeep*c1); // --- increase concen. by evaporation factor diff --git a/src/solver/runoff.c b/src/solver/runoff.c index b8f9fb72b..080674fbb 100644 --- a/src/solver/runoff.c +++ b/src/solver/runoff.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 11/01/21 (Build 5.2.0) +// Date: 10/17/22 (Build 5.2.2) // Author: L. Rossman // M. Tryby // @@ -27,7 +27,9 @@ // Build 5.1.014: // - Fixed street sweeping bug. // Build 5.2.0: -// - Support added for saving rainfall amounts in previous 48 hours. +// - Support added for saving rainfall amounts in previous 48 hours. +// Build 5.2.2: +// - Fixed possible use of canSweep in runoff_execute() with no assigned value. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -204,12 +206,12 @@ void runoff_execute() // --- see if street sweeping can occur on current date day = datetime_dayOfYear(currentDate); + canSweep = FALSE; if ( SweepStart <= SweepEnd ) { if ( day >= SweepStart && day <= SweepEnd ) canSweep = TRUE; } else if ( day <= SweepEnd || day >= SweepStart ) canSweep = TRUE; - else canSweep = FALSE; // --- get runoff time step (in seconds) runoffStep = runoff_getTimeStep(currentDate); diff --git a/src/solver/stats.c b/src/solver/stats.c index 2e4d2f7fc..be05e73d4 100644 --- a/src/solver/stats.c +++ b/src/solver/stats.c @@ -592,7 +592,7 @@ void stats_updateNodeStats(int j, double tStep, DateTime aDate) k = Node[j].subIndex; StorageStats[k].avgVol += newVolume; StorageStats[k].evapLosses += - Storage[Node[j].subIndex].evapLoss; + Storage[Node[j].subIndex].evapLoss; StorageStats[k].exfilLosses += Storage[Node[j].subIndex].exfilLoss; diff --git a/src/solver/statsrpt.c b/src/solver/statsrpt.c index f76ef7a48..baa3a40d8 100644 --- a/src/solver/statsrpt.c +++ b/src/solver/statsrpt.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 06/01/22 (Build 5.2.1) +// Date: 11/19/22 (Build 5.2.2) // Author: L. Rossman // // Report writing functions for summary statistics. @@ -27,6 +27,9 @@ // - Fixes value used for total reporting time. // Build 5.2.1: // - Replaces the "3" in "ft3" and "m3" with ANSI superscript (\xB3). +// Build 5.2.2 +// - Calculation of % Evaporation and % Exfiltration losses for storage +// units was corrected. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -512,7 +515,7 @@ void writeStorageVolumes() { int j, k, days, hrs, mins; double avgVol, maxVol, pctAvgVol, pctMaxVol; - double addedVol, pctEvapLoss, pctSeepLoss; + double pctEvapLoss, pctSeepLoss; if ( Nnodes[STORAGE] > 0 ) { @@ -524,16 +527,16 @@ void writeStorageVolumes() // OWA EDIT - write unicode super script 3 (\xC2\xB3) instead of extended ascii (\xB3) fprintf(Frpt.file, -"\n --------------------------------------------------------------------------------------------------" -"\n Average Avg Evap Exfil Maximum Max Time of Max Maximum" -"\n Volume Pcnt Pcnt Pcnt Volume Pcnt Occurrence Outflow"); +"\n ------------------------------------------------------------------------------------------------" +"\n Average Avg Evap Exfil Maximum Max Time of Max Maximum" +"\n Volume Pcnt Pcnt Pcnt Volume Pcnt Occurrence Outflow"); if ( UnitSystem == US ) fprintf(Frpt.file, -"\n Storage Unit 1000 ft\xC2\xB3 Full Loss Loss 1000 ft\xC2\xB3 Full days hr:min "); +"\n Storage Unit 1000 ft\xC2\xB3 Full Loss Loss 1000 ft\xC2\xB3 Full days hr:min "); else fprintf(Frpt.file, -"\n Storage Unit 1000 m\xC2\xB3 Full Loss Loss 1000 m\xC2\xB3 Full days hr:min "); +"\n Storage Unit 1000 m\xC2\xB3 Full Loss Loss 1000 m\xC2\xB3 Full days hr:min "); fprintf(Frpt.file, "%3s", FlowUnitWords[FlowUnits]); fprintf(Frpt.file, -"\n --------------------------------------------------------------------------------------------------"); +"\n ------------------------------------------------------------------------------------------------"); for ( j = 0; j < Nobjects[NODE]; j++ ) { @@ -551,14 +554,13 @@ void writeStorageVolumes() } pctEvapLoss = 0.0; pctSeepLoss = 0.0; - addedVol = NodeInflow[j] + StorageStats[k].initVol; - if ( addedVol > 0.0 ) + if ( NodeInflow[j] > 0.0 ) { - pctEvapLoss = StorageStats[k].evapLosses / addedVol * 100.0; - pctSeepLoss = StorageStats[k].exfilLosses / addedVol * 100.0; + pctEvapLoss = StorageStats[k].evapLosses / NodeInflow[j] * 100.0; + pctSeepLoss = StorageStats[k].exfilLosses / NodeInflow[j] * 100.0; } - fprintf(Frpt.file, "%10.3f %4.0f %4.0f %4.0f %10.3f %4.0f", + fprintf(Frpt.file, "%10.3f %5.1f %5.1f %5.1f %10.3f %5.1f", avgVol*UCF(VOLUME)/1000.0, pctAvgVol, pctEvapLoss, pctSeepLoss, maxVol*UCF(VOLUME)/1000.0, pctMaxVol); diff --git a/src/solver/swmm5.c b/src/solver/swmm5.c index 3ef3f6fc7..bf3b63b4a 100644 --- a/src/solver/swmm5.c +++ b/src/solver/swmm5.c @@ -17,7 +17,7 @@ // ============== // Build 5.1.008: // - Support added for the MinGW compiler. -// - Reporting of project options moved to swmm_start. +// - Reporting of project options moved to swmm_start. // - Hot start file now read before routing system opened. // - Final routing step adjusted so that total duration not exceeded. // Build 5.1.011: @@ -126,7 +126,7 @@ //----------------------------------------------------------------------------- // Unit conversion factors //----------------------------------------------------------------------------- -const double Ucf[10][2] = +const double Ucf[10][2] = {// US SI {43200.0, 1097280.0 }, // RAINFALL (in/hr, mm/hr --> ft/sec) {12.0, 304.8 }, // RAINDEPTH (in, mm --> ft) @@ -431,9 +431,9 @@ int DLLEXPORT swmm_start(int saveResults) massbal_open(); stats_open(); - // --- write heading for control actions listing - if (!RptFlags.disabled && RptFlags.controls) - report_writeControlActionsHeading(); + // --- write heading for control actions listing + if (!RptFlags.disabled && RptFlags.controls) + report_writeControlActionsHeading(); } #ifdef EXH @@ -457,7 +457,7 @@ int DLLEXPORT swmm_step(double *elapsedTime) { // --- check that simulation can proceed *elapsedTime = 0.0; - if ( ErrorCode ) + if ( ErrorCode ) return ErrorCode; if ( !IsOpenFlag ) return (ErrorCode = ERR_API_NOT_OPEN); @@ -594,7 +594,7 @@ void execRouting() // --- if no runoff analysis, update climate state (for evaporation) else climate_setState(getDateTime(NewRoutingTime)); - + // --- route flows & pollutants through drainage system // (while updating NewRoutingTime) if ( DoRouting ) @@ -883,7 +883,7 @@ double DLLEXPORT swmm_getValue(int property, int index) // // Input: property = an object's property code // index = the object's index in the array of like objects -// +// // Output: returns the property's current value // Purpose: retrieves the value of an object's property. { @@ -925,7 +925,7 @@ void DLLEXPORT swmm_setValue(int property, int index, double value) case swmm_SUBCATCH_RPTFLAG: if (!IsStartedFlag && index >= 0 && index < Nobjects[SUBCATCH]) Subcatch[index].rptFlag = (value > 0.0); - return; + return; case swmm_NODE_LATFLOW: setNodeLatFlow(index, value); return; @@ -935,20 +935,20 @@ void DLLEXPORT swmm_setValue(int property, int index, double value) case swmm_NODE_RPTFLAG: if (!IsStartedFlag && index >= 0 && index < Nobjects[NODE]) Node[index].rptFlag = (value > 0.0); - return; + return; case swmm_LINK_SETTING: setLinkSetting(index, value); return; case swmm_LINK_RPTFLAG: if (!IsStartedFlag && index >= 0 && index < Nobjects[LINK]) Link[index].rptFlag = (value > 0.0); - return; + return; case swmm_ROUTESTEP: setRoutingStep(value); return; case swmm_REPORTSTEP: if (!IsStartedFlag && value > 0) - ReportStep = (int)value; + ReportStep = (int)value; return; case swmm_NOREPORT: if (!IsStartedFlag) @@ -963,8 +963,8 @@ double DLLEXPORT swmm_getSavedValue(int property, int index, int period) // // Input: property = an object's property code // index = the object's index in the array of like objects -// period = a reporting time period (starting from 1) -// Output: returns the property's saved value +// period = a reporting time period (starting from 1) +// Output: returns the property's saved value // Purpose: retrieves an object's computed value at a specific reporting time period. { if (!IsOpenFlag) @@ -1078,7 +1078,7 @@ double getNodeValue(int property, int index) case swmm_NODE_DEPTH: return node->newDepth * UCF(LENGTH); case swmm_NODE_HEAD: - return (node->newDepth + node->invertElev) * UCF(LENGTH); + return (node->newDepth + node->invertElev) * UCF(LENGTH); case swmm_NODE_VOLUME: return node->newVolume * UCF(VOLUME); case swmm_NODE_LATFLOW: @@ -1258,7 +1258,7 @@ double getSavedDate(int period) // // Input: period = a reporting period (starting at 1) // Output: returns the date/time of the reporting period in decimal days -// Purpose: retrieves the date/time of a reporting period. +// Purpose: retrieves the date/time of a reporting period. { double days; output_readDateTime(period, &days); diff --git a/src/solver/table.c b/src/solver/table.c index aced49e13..f5917cacb 100644 --- a/src/solver/table.c +++ b/src/solver/table.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 11/01/21 (Build 5.2.0) +// Date: 10/17/22 (Build 5.2.2) // Author: L. Rossman // // Table (curve and time series) functions. @@ -28,6 +28,8 @@ // - The table_getInverseArea function was renamed table_getStorageDepth and // was refactored. // - Support added for relative file names. +// Build 5.2.2: +// - Prevent re-reading a time series file from start once end is reached. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -759,6 +761,13 @@ double table_tseriesLookup(TTable *table, double x, char extend) && table->x2 >= x && table->x1 != table->x2 ) return table_interpolate(x, table->x1, table->y1, table->x2, table->y2); + + // --- end of external time series file has been reached + if ( table->file.mode == USE_FILE && feof(table->file.file) ) + { + if (extend == TRUE) return table->y1; + else return 0; + } // --- x lies before current time bracket: // move to start of time series diff --git a/src/solver/text.h b/src/solver/text.h index 70bfc1f50..8448978c4 100644 --- a/src/solver/text.h +++ b/src/solver/text.h @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 06/01/22 (Build 5.2.1) +// Date: 10/18/22 (Build 5.2.2) // 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.1)" + "\n EPA STORM WATER MANAGEMENT MODEL - VERSION 5.2 (Build 5.2.2)" #define FMT09 \ "\n ------------------------------------------------------------" #define FMT10 "\n" diff --git a/src/solver/xsect.c b/src/solver/xsect.c index 5ebab53c0..1a53d36e2 100644 --- a/src/solver/xsect.c +++ b/src/solver/xsect.c @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 11/01/21 (Build 5.2.0) +// Date: 10/17/22 (Build 5.2.2) // Author: L. Rossman // M. Tryby (EPA) // @@ -32,6 +32,8 @@ // - Width at full height set to 0 for closed rectangular shape. // Build 5.2.0: // - Support added for Street cross sections. +// Build 5.2.2: +// - Feasibility check added to Mod. Baskethandle & Rect.-Round shapes. //----------------------------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE @@ -430,6 +432,7 @@ int xsect_setParams(TXsect *xsect, int type, double p[], double ucf) // --- depth of circular bottom xsect->yBot = xsect->rBot * (1.0 - cos(theta/2.0)); + if (xsect->yBot > xsect->yFull) return FALSE; xsect->ywMax = xsect->yFull; xsect->aFull = xsect->wMax * (xsect->yFull - xsect->yBot) + xsect->aBot; @@ -455,6 +458,7 @@ int xsect_setParams(TXsect *xsect, int type, double p[], double ucf) // --- height of circular arc xsect->yBot = xsect->rBot * (1.0 - cos(theta/2.0)); + if (xsect->yBot > xsect->yFull) return FALSE; xsect->ywMax = xsect->yFull - xsect->yBot; // --- area of circular arc diff --git a/src/solver/xsect.dat b/src/solver/xsect.dat index 10b10ed33..fbecb58ac 100644 --- a/src/solver/xsect.dat +++ b/src/solver/xsect.dat @@ -3,7 +3,7 @@ // // Project: EPA SWMM5 // Version: 5.2 -// Date: 06/01/22 (Build 5.2.1) +// Date: 08/01/22 (Build 5.2.1) // Author: L. Rossman // // Tables of relative geometric properties for rounded cross-sections.