Repository: pyswmm/Stormwater-Management-Model (language: python)

Issue:
add initial inlet control api functions
This PR adds some basic api functionality for inlets of street links in SWMM 5.2.3. 

3 new api functions:

* `swmm_getInletParam`: get parameters assigned to inlets of a given street link. The parameters are only those assigned to the inlets of a given street, NOT the inlets designs upon which they are based.
* `swmm_setInletParam`: set parameters assigned to inlets of a given street link. Currently only clog factor and flow limit are supported and can be set during a simulation to approximate progressive inlet clogging.
* `swmm_getInletResult`: result data associated with inlets that are otherwise only internal to the SWMM model. These may or may not be useful for modelers......TBD
    * flow capture: the captured flow rate by the inlet
    * back flow: the back flow rate from the capture node of an inlet
    * back flow ratio: `inlet backflow / capture node overflow`
Add Building page to Wiki



Discussion / hints:

@bemcdonnell maybe a BUILD.md file on the the repo root?

Fix patch:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d73d30e59..b7ebd6629 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.3
     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..3cf490793 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:    02/12/23  (Build 5.2.3)
 //   Author:  L. Rossman
 //
 //   Various Constants
@@ -17,7 +17,7 @@
 //------------------
 
 // OWA Version string stored in version.h
-// #define   VERSION            52001
+// #define   VERSION            52003
 #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..21af0d54d 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);
@@ -270,7 +270,7 @@ void    massbal_addSeepageLoss(int pollut, double seepLoss);
 void    massbal_addToFinalStorage(int pollut, double mass);
 double  massbal_getStepFlowError(void);
 double  massbal_getRunoffError(void);
-double  massbal_getFlowError(void);
+double  massbal_getFlowError(char isFinalStorage); // OWA EDIT - added isFinalStorage param to allow running flow error calcs
 
 //-----------------------------------------------------------------------------
 //   Simulation Statistics Methods
@@ -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/include/toolkit.h b/src/solver/include/toolkit.h
index ad2bdcdeb..339dbd09a 100644
--- a/src/solver/include/toolkit.h
+++ b/src/solver/include/toolkit.h
@@ -25,6 +25,7 @@
 #include "../enums.h"
 #include "../datetime.h"
 #include "../lid.h"
+#include "../inlet.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -312,6 +313,24 @@ EXPORT_TOOLKIT int swmm_getLinkParam(int index, SM_LinkProperty param, double *v
 */
 EXPORT_TOOLKIT int swmm_setLinkParam(int index, SM_LinkProperty param, double value);
 
+/**
+ @brief Get a property value for the inlets of a specified link.
+ @param index The index of a link
+ @param Param The property type code (See @ref SM_InletProperty)
+ @param[out] value The value of the inlet's property
+ @return Error code
+*/
+EXPORT_TOOLKIT int swmm_getInletParam(int index, SM_InletProperty param, double *value);
+
+/**
+ @brief Set a property value for the inlets of a specified link.
+ @param index The index of a link
+ @param Param The property type code (See @ref SM_InletProperty)
+ @param value The new value of the inlet's property
+ @return Error code
+*/
+EXPORT_TOOLKIT int swmm_setInletParam(int index, SM_InletProperty param, double value);
+
 /**
  @brief Get a property value for specified subcatchment.
  @param index The index of a subcatchment
@@ -421,6 +440,17 @@ EXPORT_TOOLKIT int swmm_setLinkPollut(int index, SM_LinkPollut type, int polluta
 */
 EXPORT_TOOLKIT int swmm_getLinkResult(int index, SM_LinkResult type, double *result);
 
+/**
+ @brief Gets results for the inlets of a specified link.
+ @param index The index of a link with inlets
+ @param type The result type code (See @ref SM_InletResult)
+ @param result Pollutant index to set
+ @param[out] result The result of the inlet's property
+ @return Error code
+*/
+EXPORT_TOOLKIT int swmm_getInletResult(int index, SM_InletResult type, double *result);
+
+
 /**
  @brief Gets pollutant values for a specified link.
  @param index The index of a link
diff --git a/src/solver/include/toolkit_enums.h b/src/solver/include/toolkit_enums.h
index 9b54f7b2d..651743b37 100644
--- a/src/solver/include/toolkit_enums.h
+++ b/src/solver/include/toolkit_enums.h
@@ -275,5 +275,21 @@ typedef enum {
     SM_STORAGEDRAIN = 29, /**< Underdrain flow rate layer */
 } SM_LidResult;
 
+typedef enum {
+    SM_INLETNUMINLETS = 0, 
+    SM_INLETCLOGFACTOR = 1, 
+    SM_INLETFLOWLIMIT  = 2,
+    SM_INLETLOCALDEPRESS = 3,
+    SM_INLETLOCALWIDTH = 4
+} SM_InletProperty;
+
+typedef enum {
+    SM_INLETFLOWFACTOR = 0,
+    SM_INLETFLOWCAPTURE = 1, 
+    SM_INLETBACKFLOW  = 2,
+    SM_INLETBACKFLOWRATIO = 3,
+
+} SM_InletResult;
+
 
 #endif /* TOOLKIT_ENUMS_H_ */
diff --git a/src/solver/include/toolkit_error.h b/src/solver/include/toolkit_error.h
index 2081edefd..3f58128ec 100644
--- a/src/solver/include/toolkit_error.h
+++ b/src/solver/include/toolkit_error.h
@@ -13,6 +13,7 @@ enum  ToolkitErrorType {
     ERR_TKAPI_LIDUNIT_INDEX      = 2009,
     ERR_TKAPI_UNDEFINED_LID      = 2010,
     ERR_TKAPI_MEMORY             = 2011,
+    ERR_TKAPI_NO_INLET           = 2012,
 
     TKMAXERRMSG                  = 3000
 };
diff --git a/src/solver/include/toolkit_errors.txt b/src/solver/include/toolkit_errors.txt
index 3a5b9782e..4a9dd1f8e 100644
--- a/src/solver/include/toolkit_errors.txt
+++ b/src/solver/include/toolkit_errors.txt
@@ -12,3 +12,4 @@ ERR(2008, "\n API Key Error: Invalid Pattern Index")
 ERR(2009, "\n API Key Error: Invalid Lid Unit Index")
 ERR(2010, "\n API Key Error: Undefined Subcatchment Lid")
 ERR(2011, "\n API Key Error: No memory allocated for return value")
+ERR(2012, "\n API Key Error: Specified link is not assigned an inlet")
diff --git a/src/solver/inlet.c b/src/solver/inlet.c
index 1ec914c4d..c44ae9fcb 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
 
@@ -68,38 +70,7 @@ typedef struct
 } TInletDesign;
 
 
-// Inlet performance statistics
-typedef struct
-{
-    int       flowPeriods;        // # periods with approach flow
-    int       capturePeriods;     // # periods with captured flow
-    int       backflowPeriods;    // # periods with backflow
-    double    peakFlow;           // peak flow seen by inlet (cfs)
-    double    peakFlowCapture;    // capture efficiency at peak flow
-    double    avgFlowCapture;     // average capture efficiency
-    double    bypassFreq;         // frequency of bypass flow
-} TInletStats;
-
-// Inlet list object
-struct TInlet
-{
-    int         linkIndex;        // index of conduit link with the inlet
-    int         designIndex;      // index of inlet's design
-    int         nodeIndex;        // index of node receiving captured flow
-    int         numInlets;        // # inlets on each side of street or in channel
-    int         placement;        // whether inlet is on-grade or on-sag
-    double      clogFactor;       // fractional degree of inlet clogging
-    double      flowLimit;        // inlet flow restriction (cfs)
-    double      localDepress;     // local gutter depression (ft)
-    double      localWidth;       // local depression width (ft)
-
-    double      flowFactor;       // flow = flowFactor * (flow spread)^2.67
-    double      flowCapture;      // captured flow rate (cfs)
-    double      backflow;         // backflow from capture node (cfs)
-    double      backflowRatio;    // inlet backflow / capture node overflow
-    TInletStats stats;            // inlet performance statistics
-    TInlet *    nextInlet;        // next inlet in list
-};
+// OWA EDIT - TInlet and TInletStats struct defs moved to inlet.h to be shared by toolkit.c
 
 // Shared inlet variables
 TInletDesign * InletDesigns;      // array of available inlet designs
@@ -1030,17 +1001,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 +1067,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/inlet.h b/src/solver/inlet.h
index ca7830725..52b6dcb54 100644
--- a/src/solver/inlet.h
+++ b/src/solver/inlet.h
@@ -27,4 +27,39 @@ void   inlet_adjustQualOutflows();
 void   inlet_writeStatsReport();
 double inlet_capturedFlow(int link);
 
+// OWA EDIT ##################################################################################
+// TInlet and TInletStats struct defs moved to inlet.h to be shared by toolkit.c
+typedef struct
+{
+    int       flowPeriods;        // # periods with approach flow
+    int       capturePeriods;     // # periods with captured flow
+    int       backflowPeriods;    // # periods with backflow
+    double    peakFlow;           // peak flow seen by inlet (cfs)
+    double    peakFlowCapture;    // capture efficiency at peak flow
+    double    avgFlowCapture;     // average capture efficiency
+    double    bypassFreq;         // frequency of bypass flow
+} TInletStats;
+
+// Inlet list object
+struct TInlet
+{
+    int         linkIndex;        // index of conduit link with the inlet
+    int         designIndex;      // index of inlet's design
+    int         nodeIndex;        // index of node receiving captured flow
+    int         numInlets;        // # inlets on each side of street or in channel
+    int         placement;        // whether inlet is on-grade or on-sag
+    double      clogFactor;       // fractional degree of inlet clogging
+    double      flowLimit;        // inlet flow restriction (cfs)
+    double      localDepress;     // local gutter depression (ft)
+    double      localWidth;       // local depression width (ft)
+
+    double      flowFactor;       // flow = flowFactor * (flow spread)^2.67
+    double      flowCapture;      // captured flow rate (cfs)
+    double      backflow;         // backflow from capture node (cfs)
+    double      backflowRatio;    // inlet backflow / capture node overflow
+    TInletStats stats;            // inlet performance statistics
+    TInlet *    nextInlet;        // next inlet in list
+};
+// ###########################################################################################
+
 #endif
diff --git a/src/solver/lid.c b/src/solver/lid.c
index d9a0c7e78..a6e82e16c 100644
--- a/src/solver/lid.c
+++ b/src/solver/lid.c
@@ -3,7 +3,7 @@
 //
 //   Project:  EPA SWMM5
 //   Version:  5.2
-//   Date:     11/01/21   (Build 5.2.0)
+//   Date:     02/10/23   (Build 5.2.3)
 //   Author:   L. Rossman
 //
 //   This module handles all data processing involving LID (Low Impact
@@ -57,7 +57,7 @@
 //   - Redefined initialization of wasDry for LID reporting.
 //   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.
@@ -68,6 +68,8 @@
 //   - Support added for mutiple infiltration methods within a project.
 //   Build 5.2.0:
 //   - Covered property added to RAIN_BARREL parameters
+//   Build 5.2.3
+//   - Fixed double counting of initial water volume in green roof drain mat.
 //-----------------------------------------------------------------------------
 #define _CRT_SECURE_NO_DEPRECATE
 
@@ -97,7 +99,7 @@ enum LidLayerTypes {
     REMOVALS};               // pollutant removals
 
 //// 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",
@@ -134,7 +136,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
@@ -249,7 +251,7 @@ void lid_create(int lidCount, int subcatchCount)
 
     //... 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));
@@ -543,7 +545,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;
@@ -554,7 +556,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;
@@ -569,7 +571,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
@@ -587,7 +589,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);
@@ -604,7 +606,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
@@ -672,7 +674,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
@@ -706,7 +708,7 @@ 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
@@ -760,14 +762,14 @@ int readStorageData(int j, char* toks[], int ntoks)
     LidProcs[j].storage.covered     = covered;
     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
@@ -805,14 +807,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
@@ -846,7 +848,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
@@ -895,7 +897,7 @@ void lid_writeSummary()
     TLidUnit*  lidUnit;
     TLidList*  lidList;
     TLidGroup  lidGroup;
-
+ 
     fprintf(Frpt.file, "\n");
     fprintf(Frpt.file, "\n");
     fprintf(Frpt.file, "\n  *******************");
@@ -935,7 +937,7 @@ void lid_writeSummary()
 void lid_validate()
 //
 //  Purpose: validates LID process and group parameters.
-//  Input:   none
+//  Input:   none 
 //  Output:  none
 //
 {
@@ -949,7 +951,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
 //
 {
@@ -970,7 +972,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:
@@ -989,8 +991,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 )
@@ -1005,7 +1007,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
@@ -1029,9 +1031,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;
     }
@@ -1048,7 +1050,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
            )
@@ -1057,7 +1059,7 @@ void validateLidProc(int j)
             sstrcat(Msg, ERR_SWALE_SURF, MAXMSG);
             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;
     }
@@ -1104,7 +1106,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;
@@ -1119,7 +1121,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
 //
 {
@@ -1161,7 +1163,7 @@ void validateLidGroup(int j)
                 report_writeErrorMsg(ERR_LID_PARAMS, Msg);
             }
         }
-
+        
         //... assign vegetative swale infiltration parameters
         if ( LidProcs[k].lidType == VEG_SWALE )
         {
@@ -1217,7 +1219,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
 //
 {
@@ -1258,7 +1260,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;
@@ -1269,12 +1271,6 @@ void lid_initState()
                     LidProcs[k].storage.thickness;
                 initVol += lidUnit->storageDepth * LidProcs[k].storage.voidFrac;
             }
-            if ( LidProcs[k].drainMat.thickness > 0.0 )
-            {
-                lidUnit->storageDepth = lidUnit->initSat *
-                    LidProcs[k].drainMat.thickness;
-                initVol += lidUnit->storageDepth * LidProcs[k].drainMat.voidFrac;
-            }
             if ( lidUnit->initSat > 0.0 ) HasWetLids = TRUE;
 
             //... initialize water balance totals
@@ -1298,7 +1294,7 @@ void lid_initState()
 
             //... set previous flux rates to 0
             for (i = 0; i < MAX_LAYERS; i++)
-            {
+            {    
                 lidUnit->oldFluxRates[i] = 0.0;
             }
 
@@ -1319,7 +1315,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
 //
 {
@@ -1343,7 +1339,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
 //
 {
@@ -1357,7 +1353,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)
 //
 {
@@ -1413,9 +1409,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)
 //
 {
@@ -1442,7 +1438,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.
 {
@@ -1468,11 +1464,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];
@@ -1483,11 +1479,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++)
             {
@@ -1514,7 +1510,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.
 //
@@ -1525,8 +1521,8 @@ void lid_addDrainRunon(int j)
     double q;                // drain flow rate (cfs)
     double w;                // mass of polllutant from drain flow
     TLidUnit*  lidUnit;
-    TLidList*  lidList;
-    TLidGroup  lidGroup;
+    TLidList*  lidList; 
+    TLidGroup  lidGroup; 
 
     //... check if LID group exists
     lidGroup = LidGroups[j];
@@ -1565,7 +1561,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.
@@ -1602,12 +1598,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;
@@ -1626,7 +1622,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.
@@ -1641,7 +1637,7 @@ void lid_getRunoff(int j, double tStep)
     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];
@@ -1659,7 +1655,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);
     }
@@ -1692,7 +1688,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);
         }
@@ -1704,7 +1700,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;
 }
@@ -1852,7 +1848,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;
 
@@ -1871,7 +1867,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 )
@@ -1939,7 +1935,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           %%");
@@ -1969,7 +1965,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 +
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/massbal.c b/src/solver/massbal.c
index 893cf36d6..f6443ffef 100644
--- a/src/solver/massbal.c
+++ b/src/solver/massbal.c
@@ -298,7 +298,7 @@ void massbal_report()
 
     if ( Nobjects[NODE] > 0 && !IgnoreRouting )
     {
-        if ( massbal_getFlowError() > MAX_FLOW_BALANCE_ERR ||
+        if ( massbal_getFlowError(TRUE) > MAX_FLOW_BALANCE_ERR ||       // OWA EDIT - added isFinalStorage param to massbal_getFlowError
              RptFlags.continuity == TRUE
            ) report_writeFlowError(&FlowTotals);
     
@@ -855,9 +855,9 @@ double massbal_getGwaterError()
 
 //=============================================================================
 
-double massbal_getFlowError()
+double massbal_getFlowError(char isFinalStorage)   // OWA EDIT - added isFinalStorage param to allow running flow error calcs
 //
-//  Input:   none
+//  Input:   isFinalStorage = TRUE if at final time period
 //  Output:  none
 //  Purpose: computes flow routing mass balance error.
 //
@@ -866,7 +866,7 @@ double massbal_getFlowError()
     double totalOutflow;
 
     // --- get final volume of nodes and links
-    FlowTotals.finalStorage = massbal_getStorage(TRUE);
+    FlowTotals.finalStorage = massbal_getStorage(isFinalStorage);   // OWA EDIT - added isFinalStorage param to allow running flow error calcs
 
     // --- add contributions to total inflow and outflow that are always positive
     totalInflow = FlowTotals.initStorage + FlowTotals.wwInflow  + FlowTotals.iiInflow;
@@ -1052,10 +1052,11 @@ int massbal_getRoutingTotal(TRoutingTotals **routingTotal)
 //
 // Input:    element = element to return
 // Return:   value
-// Purpose:  Gets the routing total for toolkitAPI
+// Purpose:  Gets the routing total for toolkitAPI in volume units (ft^3 or m^3)
 //
-{
-	memcpy(*routingTotal, &FlowTotals, sizeof(TRoutingTotals));
+{   
+    double error = massbal_getFlowError(FALSE);
+    memcpy(*routingTotal, &FlowTotals, sizeof(TRoutingTotals));
 
     // Cumulative Dry Weather Inflow Volume
     (*routingTotal)->dwInflow *= UCF(VOLUME);
@@ -1076,33 +1077,33 @@ int massbal_getRoutingTotal(TRoutingTotals **routingTotal)
     // Cumulative Seepage Loss
     (*routingTotal)->seepLoss *= UCF(VOLUME);
     // Continuity Error
-    (*routingTotal)->pctError *= 100;
+    (*routingTotal)->pctError;
 
-	return 0;
+    return 0;
 }
 
 int massbal_getRunoffTotal(TRunoffTotals **runoffTotal)
 //
 // Input:    element = element to return
 // Return:   value
-// Purpose:  Gets the runoff total for toolkitAPI
+// Purpose:  Gets the runoff total for toolkitAPI in depth units (in or mm)
 //
 {
-	
-	memcpy(*runoffTotal, &RunoffTotals, sizeof(TRunoffTotals));
-	
+    double error = massbal_getRunoffError();
+    memcpy(*runoffTotal, &RunoffTotals, sizeof(TRunoffTotals));
+
     // Cumulative Rainfall Depth
     (*runoffTotal)->rainfall *= (UCF(RAINDEPTH) / TotalArea);
     // Cumulative Evaporation Volume
-    (*runoffTotal)->evap *= UCF(VOLUME);
+    (*runoffTotal)->evap *= (UCF(RAINDEPTH) / TotalArea);
     // Cumulative Infiltration Volume
-    (*runoffTotal)->infil *= UCF(VOLUME);
+    (*runoffTotal)->infil *= (UCF(RAINDEPTH) / TotalArea);
     // Cumulative Runoff Volume
-    (*runoffTotal)->runoff *= UCF(VOLUME);
+    (*runoffTotal)->runoff *= (UCF(RAINDEPTH) / TotalArea);
     // Cumulative Runon Volume
-    (*runoffTotal)->runon *= UCF(VOLUME);
+    (*runoffTotal)->runon *= (UCF(RAINDEPTH) / TotalArea);
     // Cumulative Drain Volume
-    (*runoffTotal)->drains *= UCF(VOLUME);
+    (*runoffTotal)->drains *= (UCF(RAINDEPTH) / TotalArea);
     // Cumulative Snow Removed Volume
     (*runoffTotal)->snowRemoved *= (UCF(RAINDEPTH) / TotalArea);
     // Initial Storage Volume
@@ -1114,9 +1115,9 @@ int massbal_getRunoffTotal(TRunoffTotals **runoffTotal)
     // Final Snow Cover Volume
     (*runoffTotal)->finalSnowCover *= (UCF(RAINDEPTH) / TotalArea);
     // Continuity Error
-    (*runoffTotal)->pctError *= 100;
+    (*runoffTotal)->pctError;
 
-	return 0;
+    return 0;
 }
 
 
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/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..2e49e27f4 100644
--- a/src/solver/swmm5.c
+++ b/src/solver/swmm5.c
@@ -350,7 +350,7 @@ int DLLEXPORT swmm_open(const char *f1, const char *f2, const char *f3)
 
 int DLLEXPORT swmm_start(int saveResults)
 //
-//  Input:   saveResults = TRUE if simulation results saved to binary file
+//  Input:   saveResults = TRUE if simulation results saved to binary file 
 //  Output:  returns an error code
 //  Purpose: starts a SWMM simulation.
 //
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..353296b8e 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:    12/22/22  (Build 5.2.3)
 //   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.3)"
 #define FMT09 \
   "\n  ------------------------------------------------------------"
 #define FMT10 "\n"
diff --git a/src/solver/toolkit.c b/src/solver/toolkit.c
index fff5f4998..83571a97e 100644
--- a/src/solver/toolkit.c
+++ b/src/solver/toolkit.c
@@ -806,6 +806,148 @@ EXPORT_TOOLKIT int swmm_setLinkParam(int index, SM_LinkProperty param, double va
     return error_code;
 }
 
+EXPORT_TOOLKIT int swmm_getInletParam(int index, SM_InletProperty param, double *value)
+///
+/// Input:   index = Index of the link with desired inlet
+///          param = Parameter desired (Based on enum SM_InletProperty)
+/// Output:  value = value to be output
+/// Return:  API Error
+/// Purpose: Gets Link Parameter
+{
+    int error_code = 0;
+    *value = 0;
+    TInlet* inlet;
+
+    // Check if Open
+    if(swmm_IsOpenFlag() == FALSE)
+    {
+        error_code = ERR_TKAPI_INPUTNOTOPEN;
+    }
+    // Check if object index is within bounds
+    else if (index < 0 || index >= Nobjects[LINK])
+    {
+        error_code = ERR_TKAPI_OBJECT_INDEX;
+    }
+    else
+    {
+        inlet = Link[index].inlet;
+        if (inlet)
+        {
+            switch(param)
+            {
+                case SM_INLETNUMINLETS:
+                    *value = (double)inlet->numInlets; break;
+                case SM_INLETCLOGFACTOR:
+                    *value = (1 - inlet->clogFactor) * 100; break;
+                case SM_INLETFLOWLIMIT:
+                    *value = inlet->flowLimit * UCF(FLOW); break;
+                case SM_INLETLOCALDEPRESS:
+                    *value = inlet->localDepress * UCF(LENGTH); break;
+                case SM_INLETLOCALWIDTH:
+                    *value = inlet->localWidth * UCF(LENGTH); break;
+                default: error_code = ERR_TKAPI_OUTBOUNDS; break;
+            }
+        }
+
+        else
+        {
+            error_code = ERR_TKAPI_NO_INLET;
+        }
+    }
+    return error_code;
+};
+
+EXPORT_TOOLKIT int swmm_setInletParam(int index, SM_InletProperty param, double value)
+///
+/// Input:   index = Index of link with desired inlets
+///          param = Parameter desired (Based on enum SM_InletProperty)
+///          value = value to be assigned
+/// Return:  API Error
+/// Purpose: Sets Inlet Parameter
+{
+    int error_code = 0;
+    TInlet* inlet;
+    // Check if Open
+    if(swmm_IsOpenFlag() == FALSE)
+    {
+        error_code = ERR_TKAPI_INPUTNOTOPEN;
+    }
+    // Check if object index is within bounds
+    else if (index < 0 || index >= Nobjects[LINK])
+    {
+        error_code = ERR_TKAPI_OBJECT_INDEX;
+    }
+    else
+    {
+        inlet = Link[index].inlet;
+        if (inlet)
+        {
+            switch(param)
+            {
+                case SM_INLETCLOGFACTOR:
+                    inlet->clogFactor = 1.0 - (value / 100.); break;
+                case SM_INLETFLOWLIMIT:
+                    inlet->flowLimit = value / UCF(FLOW); break;
+                default: error_code = ERR_TKAPI_OUTBOUNDS; break;
+            }
+        }
+
+        else
+        {
+            error_code = ERR_TKAPI_NO_INLET;
+        }
+    }
+    return error_code;
+}
+
+EXPORT_TOOLKIT int swmm_getInletResult(int index, SM_InletResult type, double *result)
+///
+/// Input:   index = Index of the link with desired inlet
+///          param = Parameter desired (Based on enum SM_InletProperty)
+/// Output:  value = value to be output
+/// Return:  API Error
+/// Purpose: Gets Link Parameter
+{
+    int error_code = 0;
+    *result = 0;
+    TInlet* inlet;
+
+    // Check if Open
+    if(swmm_IsOpenFlag() == FALSE)
+    {
+        error_code = ERR_TKAPI_INPUTNOTOPEN;
+    }
+    // Check if object index is within bounds
+    else if (index < 0 || index >= Nobjects[LINK])
+    {
+        error_code = ERR_TKAPI_OBJECT_INDEX;
+    }
+    else
+    {
+        inlet = Link[index].inlet;
+        if (inlet)
+        {
+            switch(type)
+            {
+                case SM_INLETFLOWFACTOR:
+                    *result = inlet->flowFactor; break;
+                case SM_INLETFLOWCAPTURE:
+                    *result = inlet->flowCapture * UCF(FLOW); break;
+                case SM_INLETBACKFLOW:
+                    *result = inlet->backflow * UCF(FLOW); break;
+                case SM_INLETBACKFLOWRATIO:
+                    *result = inlet->backflowRatio; break;
+                default: error_code = ERR_TKAPI_OUTBOUNDS; break;
+            }
+        }
+
+        else
+        {
+            error_code = ERR_TKAPI_NO_INLET;
+        }
+    }
+    return error_code;
+};
 
 EXPORT_TOOLKIT int swmm_getSubcatchParam(int index, SM_SubcProperty param, double *value)
 ///
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.


Test patch:
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/tests/solver/CMakeLists.txt b/tests/solver/CMakeLists.txt
index da8a5d375..021832fbb 100644
--- a/tests/solver/CMakeLists.txt
+++ b/tests/solver/CMakeLists.txt
@@ -37,6 +37,7 @@ set(solver_test_srcs
     test_toolkit.cpp
     test_solver.cpp
     test_stats.cpp
+    test_inlets_and_drains.cpp
     # ADD NEW TEST SUITES TO EXISTING TOOLKIT TEST MODULE
 )
 
diff --git a/tests/solver/data/test_inlet_drains.inp b/tests/solver/data/test_inlet_drains.inp
new file mode 100644
index 000000000..a60d798aa
--- /dev/null
+++ b/tests/solver/data/test_inlet_drains.inp
@@ -0,0 +1,502 @@
+[TITLE]
+;;Project Title/Notes
+A dual drainage model with street inlets.
+See Inlet_Drains_Model.txt for more details.
+
+[OPTIONS]
+;;Option             Value
+FLOW_UNITS           CFS
+INFILTRATION         HORTON
+FLOW_ROUTING         DYNWAVE
+LINK_OFFSETS         DEPTH
+MIN_SLOPE            0
+ALLOW_PONDING        NO
+SKIP_STEADY_STATE    NO
+
+START_DATE           01/01/2007
+START_TIME           00:00:00
+REPORT_START_DATE    01/01/2007
+REPORT_START_TIME    00:00:00
+END_DATE             01/01/2007
+END_TIME             06:00:00
+SWEEP_START          01/01
+SWEEP_END            12/31
+DRY_DAYS             0
+REPORT_STEP          00:01:00
+WET_STEP             00:01:00
+DRY_STEP             01:00:00
+ROUTING_STEP         0:00:15 
+RULE_STEP            00:00:00
+
+INERTIAL_DAMPING     PARTIAL
+NORMAL_FLOW_LIMITED  SLOPE
+FORCE_MAIN_EQUATION  H-W
+VARIABLE_STEP        0.75
+LENGTHENING_STEP     0
+MIN_SURFAREA         12.566
+MAX_TRIALS           8
+HEAD_TOLERANCE       0.005
+SYS_FLOW_TOL         5
+LAT_FLOW_TOL         5
+MINIMUM_STEP         0.5
+THREADS              1
+
+[EVAPORATION]
+;;Data Source    Parameters
+;;-------------- ----------------
+CONSTANT         0.0
+DRY_ONLY         NO
+
+[RAINGAGES]
+;;Name           Format    Interval SCF      Source    
+;;-------------- --------- ------ ------ ----------
+RainGage         INTENSITY 0:05     1.0      TIMESERIES 2-yr            
+
+[SUBCATCHMENTS]
+;;Name           Rain Gage        Outlet           Area     %Imperv  Width    %Slope   CurbLen  SnowPack        
+;;-------------- ---------------- ---------------- -------- -------- -------- -------- -------- ----------------
+S1               RainGage         Aux1             4.55     56.8     1587     2        0                        
+S2               RainGage         Aux4             4.74     63.0     1653     2        0                        
+S3               RainGage         Aux3             3.74     39.5     1456     3.1      0                        
+S4               RainGage         J7               6.79     49.9     2331     3.1      0                        
+S5               RainGage         J10              4.79     87.7     1670     2        0                        
+S6               RainGage         J11              1.98     95.0     690      2        0                        
+S7               RainGage         J10              2.33     0.0      907      3.1      0                        
+
+[SUBAREAS]
+;;Subcatchment   N-Imperv   N-Perv     S-Imperv   S-Perv     PctZero    RouteTo    PctRouted 
+;;-------------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
+S1               0.015      0.24       0.06       0.3        25         OUTLET    
+S2               0.015      0.24       0.06       0.3        25         OUTLET    
+S3               0.015      0.24       0.06       0.3        25         OUTLET    
+S4               0.015      0.24       0.06       0.3        25         OUTLET    
+S5               0.015      0.24       0.06       0.3        25         OUTLET    
+S6               0.015      0.24       0.06       0.3        25         OUTLET    
+S7               0.015      0.24       0.06       0.3        25         OUTLET    
+
+[INFILTRATION]
+;;Subcatchment   Param1     Param2     Param3     Param4     Param5    
+;;-------------- ---------- ---------- ---------- ---------- ----------
+S1               4.5        0.2        6.5        7          0         
+S2               4.5        0.2        6.5        7          0         
+S3               4.5        0.2        6.5        7          0         
+S4               4.5        0.2        6.5        7          0         
+S5               4.5        0.2        6.5        7          0         
+S6               4.5        0.2        6.5        7          0         
+S7               4.5        0.2        6.5        7          0         
+
+[JUNCTIONS]
+;;Name           Elevation  MaxDepth   InitDepth  SurDepth   Aponded   
+;;-------------- ---------- ---------- ---------- ---------- ----------
+Aux1             4975       0          0          0          0         
+Aux2             4973       0          0          0          0         
+Aux3             4968.5     0          0          0          0         
+Aux4             4971.8     0          0          0          0         
+Aux5             4970.7     0          0          0          0         
+Aux6             4969       0          0          0          0         
+Aux7             4963       0          0          0          0         
+J1               4969       4          0          0          0         
+J10              4957.8     0          0          0          0         
+J11              4957       0          0          0          0         
+J2               4965       4          0          0          0         
+J2a              4966.7     4          0          0          0         
+J3               4973       0          0          0          0         
+J4               4965       0          0          0          0         
+J5               4965.8     0          0          0          0         
+J6               4969       0          0          0          0         
+J7               4963.5     0          0          0          0         
+J8               4966.5     0          0          0          0         
+J9               4964.8     0          0          0          0         
+
+[OUTFALLS]
+;;Name           Elevation  Type       Stage Data       Gated    Route To        
+;;-------------- ---------- ---------- ---------------- -------- ----------------
+O1               4956       FREE                        NO                       
+
+[CONDUITS]
+;;Name           From Node        To Node          Length     Roughness  InOffset   OutOffset  InitFlow   MaxFlow   
+;;-------------- ---------------- ---------------- ---------- ---------- ---------- ---------- ---------- ----------
+Street1          Aux1             Aux2             377.31     0.016      0          0          0          0         
+Street2          Aux2             Aux4             286.06     0.016      0          0          0          0         
+Street3          Aux4             Aux5             239.41     0.016      0          0          0          0         
+Street4          Aux5             Aux6             157.48     0.016      0          0          0          0         
+Street5          Aux6             Aux7             526.0      0.016      0          0          0          0         
+C3               J3               J4               109.0      0.016      0          6          0          0         
+C4               J4               J5               133.0      0.05       6          4          0          0         
+C5               J5               J6               207.0      0.05       4          0          0          0         
+C6               J7               J6               140.0      0.05       8          0          0          0         
+C7               J6               J8               95.0       0.016      0          0          0          0         
+C8               J8               J9               166.0      0.05       0          0          0          0         
+C9               J9               J10              320.0      0.05       0          6          0          0         
+C10              J10              J11              145.0      0.05       6          6          0          0         
+C11              J11              O1               89.0       0.016      0          0          0          0         
+C_Aux3           Aux3             J3               444.75     0.05       6          0          0          0         
+P1               J1               J5               185.39     0.016      0          0          0          0         
+P2               J2a              J2               157.48     0.016      0          0          0          0         
+P3               J2               J11              529.22     0.016      0          0          0          0         
+P4               Aux3             J4               567.19     0.016      0          0          0          0         
+P5               J5               J4               125.98     0.016      0          0          0          0         
+P6               J4               J7               360.39     0.016      0          0          0          0         
+P7               J7               J10              507.76     0.016      0          0          0          0         
+P8               J10              J11              144.50     0.016      0          0          0          0         
+
+[XSECTIONS]
+;;Link           Shape        Geom1            Geom2      Geom3      Geom4      Barrels    Culvert   
+;;-------------- ------------ ---------------- ---------- ---------- ---------- ---------- ----------
+Street1          STREET       FullStreet      
+Street2          STREET       FullStreet      
+Street3          STREET       FullStreet      
+Street4          STREET       HalfStreet      
+Street5          STREET       HalfStreet      
+C3               CIRCULAR     2.25             0          0          0          1                    
+C4               TRAPEZOIDAL  3                5          5          5          1                    
+C5               TRAPEZOIDAL  3                5          5          5          1                    
+C6               TRAPEZOIDAL  3                5          5          5          1                    
+C7               CIRCULAR     3.5              0          0          0          1                    
+C8               TRAPEZOIDAL  3                5          5          5          1                    
+C9               TRAPEZOIDAL  3                5          5          5          1                    
+C10              TRAPEZOIDAL  3                5          5          5          1                    
+C11              CIRCULAR     4.75             0          0          0          1                    
+C_Aux3           TRAPEZOIDAL  3                5          5          5          1                    
+P1               CIRCULAR     0.5              0          0          0          1                    
+P2               CIRCULAR     1.5              0          0          0          1                    
+P3               CIRCULAR     1.5              0          0          0          1                    
+P4               CIRCULAR     1.67             0          0          0          1                    
+P5               CIRCULAR     1.83             0          0          0          1                    
+P6               CIRCULAR     2                0          0          0          1                    
+P7               CIRCULAR     2                0          0          0          1                    
+P8               CIRCULAR     3.17             0          0          0          1                    
+
+[STREETS]
+;;Name           Tcrown   Hcurb    Sx       nRoad    a        W        Sides    Tback    Sback    nBack   
+;;-------------- -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
+HalfStreet       20       0.5      4        0.016    0        0        1        20       4        0.016   
+FullStreet       20       0.5      4        0.016    0        0        2        20       4        0.016   
+
+[INLETS]
+;;Name           Type             Parameters:
+;;-------------- ---------------- -----------
+ComboInlet       GRATE            2        2        P_BAR-50        
+ComboInlet       CURB             2        0.5      HORIZONTAL
+
+[INLET_USAGE]
+;;Conduit        Inlet            Node             Number    %Clogged  Qmax      aLocal    wLocal    Placement
+;;-------------- ---------------- ---------------- --------- --------- --------- --------- --------- --------- ---------
+Street1          ComboInlet       J1               1         50        2.2       0.5       2        
+Street3          ComboInlet       J2a              1         0         0         0         0        
+Street4          ComboInlet       J2               1         0         0         0         0        
+Street5          ComboInlet       J11              2         0         0         0         0        
+
+[TIMESERIES]
+;;Name           Date       Time       Value     
+;;-------------- ---------- ---------- ----------
+2-yr                        0:00       0.29      
+2-yr                        0:05       0.33      
+2-yr                        0:10       0.38      
+2-yr                        0:15       0.64      
+2-yr                        0:20       0.81      
+2-yr                        0:25       1.57      
+2-yr                        0:30       2.85      
+2-yr                        0:35       1.18      
+2-yr                        0:40       0.71      
+2-yr                        0:45       0.42      
+2-yr                        0:50       0.35      
+2-yr                        0:55       0.3       
+2-yr                        1:00       0.2       
+2-yr                        1:05       0.19      
+2-yr                        1:10       0.18      
+2-yr                        1:15       0.17      
+2-yr                        1:20       0.17      
+2-yr                        1:25       0.16      
+2-yr                        1:30       0.15      
+2-yr                        1:35       0.15      
+2-yr                        1:40       0.14      
+2-yr                        1:45       0.14      
+2-yr                        1:50       0.13      
+2-yr                        1:55       0.13      
+;
+10-yr                       0:00       0.49      
+10-yr                       0:05       0.56      
+10-yr                       0:10       0.65      
+10-yr                       0:15       1.09      
+10-yr                       0:20       1.39      
+10-yr                       0:25       2.69      
+10-yr                       0:30       4.87      
+10-yr                       0:35       2.02      
+10-yr                       0:40       1.21      
+10-yr                       0:45       0.71      
+10-yr                       0:50       0.6       
+10-yr                       0:55       0.52      
+10-yr                       1:00       0.39      
+10-yr                       1:05       0.37      
+10-yr                       1:10       0.35      
+10-yr                       1:15       0.34      
+10-yr                       1:20       0.32      
+10-yr                       1:25       0.31      
+10-yr                       1:30       0.3       
+10-yr                       1:35       0.29      
+10-yr                       1:40       0.28      
+10-yr                       1:45       0.27      
+10-yr                       1:50       0.26      
+10-yr                       1:55       0.25      
+
+[REPORT]
+;;Reporting Options
+INPUT      YES
+SUBCATCHMENTS ALL
+NODES ALL
+LINKS ALL
+
+[TAGS]
+Link       Street1          Full_Street     
+Link       Street2          Full_Street     
+Link       Street3          Full_Street     
+Link       Street4          Half_Street     
+Link       Street5          Half_Street     
+Link       C3               Culvert         
+Link       C4               Swale           
+Link       C5               Swale           
+Link       C6               Swale           
+Link       C7               Culvert         
+Link       C8               Swale           
+Link       C9               Swale           
+Link       C10              Swale           
+Link       C11              Culvert         
+Link       C_Aux3           Swale           
+
+[MAP]
+DIMENSIONS -255.206 -70.199 1490.833 1514.231
+Units      Feet
+
+[COORDINATES]
+;;Node           X-Coord            Y-Coord           
+;;-------------- ------------------ ------------------
+Aux1             293.152            1161.023          
+Aux2             653.046            1052.180          
+Aux3             122.363            696.959           
+Aux4             914.142            1058.025          
+Aux5             1175.238           1120.376          
+Aux6             1260.972           956.704           
+Aux7             1381.777           514.399           
+J1               647.200            1022.952          
+J10              1254.058           640.029           
+J11              1270.714           491.017           
+J2               1218.105           950.859           
+J2a              1159.651           1069.716          
+J3               405.287            905.702           
+J4               505.345            862.573           
+J5               631.281            859.123           
+J6               803.079            869.022           
+J7               831.398            709.035           
+J8               915.930            840.146           
+J9               1072.918           867.749           
+O1               1411.468           477.401           
+
+[VERTICES]
+;;Link           X-Coord            Y-Coord           
+;;-------------- ------------------ ------------------
+Street1          382.860            1112.719          
+Street1          514.703            1061.922          
+Street2          806.976            1042.437          
+Street3          1062.227           1091.149          
+Street4          1210.311           1061.922          
+Street5          1338.911           781.341           
+Street5          1387.623           662.483           
+Street5          1393.468           586.493           
+C4               559.710            846.393           
+C5               672.684            850.497           
+C5               712.363            829.795           
+C5               743.415            805.643           
+C5               768.006            833.950           
+C6               791.719            734.912           
+C6               798.620            784.942           
+C8               965.959            838.421           
+C8               995.287            831.520           
+C8               1038.415           850.497           
+C9               1102.246           867.749           
+C9               1131.573           852.222           
+C9               1147.099           829.795           
+C9               1162.626           809.094           
+C9               1198.854           779.766           
+C9               1219.556           757.339           
+C9               1233.357           721.111           
+C9               1238.532           715.936           
+C9               1235.082           674.532           
+C9               1247.158           646.930           
+C_Aux3           163.003            699.992           
+C_Aux3           208.620            726.287           
+C_Aux3           239.673            793.567           
+C_Aux3           251.749            876.374           
+C_Aux3           291.427            912.602           
+C_Aux3           355.257            929.854           
+P3               1331.117           691.711           
+P3               1329.168           590.390           
+P4               275.901            572.749           
+P4               472.567            824.620           
+P7               886.602            800.468           
+
+[Polygons]
+;;Subcatchment   X-Coord            Y-Coord           
+;;-------------- ------------------ ------------------
+S1               282.657            1334.810          
+S1               111.700            1101.604          
+S1               172.525            1062.743          
+S1               231.660            1027.262          
+S1               306.002            990.092           
+S1               370.206            959.679           
+S1               409.066            946.163           
+S1               444.547            936.025           
+S1               493.545            924.198           
+S1               532.405            915.750           
+S1               569.576            907.302           
+S1               610.125            897.165           
+S1               655.744            897.165           
+S1               684.338            1318.700          
+S1               651.043            1321.922          
+S1               596.269            1332.662          
+S1               551.160            1346.624          
+S1               495.312            1367.030          
+S1               455.573            1384.214          
+S1               410.465            1409.991          
+S1               386.836            1427.175          
+S1               363.208            1442.211          
+S2               678.967            1238.149          
+S2               673.584            1152.903          
+S2               655.744            897.165           
+S2               758.808            893.786           
+S2               817.943            895.475           
+S2               880.458            898.855           
+S2               921.007            905.613           
+S2               978.453            920.819           
+S2               1042.657           937.715           
+S2               1103.482           959.679           
+S2               1159.238           985.023           
+S2               1225.131           1010.367          
+S2               1109.646           1274.665          
+S2               1052.723           1400.325          
+S2               985.061            1370.252          
+S2               924.916            1348.772          
+S2               861.549            1331.588          
+S2               815.367            1325.144          
+S2               762.740            1319.774          
+S2               719.780            1316.552          
+S2               684.338            1317.626          
+S3               109.199            1103.258          
+S3               141.754            1081.555          
+S3               190.586            1051.713          
+S3               247.557            1019.158          
+S3               304.528            989.317           
+S3               354.716            964.900           
+S3               398.123            949.980           
+S3               490.166            922.509           
+S3               477.743            883.275           
+S3               501.993            816.065           
+S3               556.059            778.895           
+S3               488.476            679.210           
+S3               422.582            729.897           
+S3               282.348            557.560           
+S3               179.734            633.927           
+S3               153.962            651.561           
+S3               107.843            693.610           
+S3               71.218             742.443           
+S3               48.159             785.849           
+S3               31.881             837.394           
+S3               29.168             886.226           
+S3               31.881             933.702           
+S3               38.664             967.613           
+S3               50.872             1001.525          
+S3               65.793             1035.436          
+S3               87.496             1070.704          
+S3               109.199            1103.258          
+S4               282.348            559.250           
+S4               420.893            729.897           
+S4               488.476            680.899           
+S4               556.828            779.067           
+S4               501.213            814.335           
+S4               479.468            885.000           
+S4               491.718            922.851           
+S4               616.511            898.434           
+S4               668.056            897.078           
+S4               783.355            895.722           
+S4               815.909            898.434           
+S4               857.959            899.791           
+S4               890.595            897.165           
+S4               968.316            915.750           
+S4               1042.657           937.715           
+S4               1074.759           849.857           
+S4               1054.484           773.826           
+S4               1020.692           702.864           
+S4               963.247            623.454           
+S4               689.536            256.816           
+S5               1301.482           474.258           
+S5               1271.677           445.380           
+S5               1232.340           393.835           
+S5               1241.835           384.340           
+S5               1222.844           366.706           
+S5               1233.696           355.854           
+S5               1026.159           66.931            
+S5               1008.525           56.079            
+S5               708.750            275.824           
+S5               1023.446           704.462           
+S5               1150.644           618.812           
+S5               1251.203           640.809           
+S5               1328.193           519.824           
+S6               1334.478           519.824           
+S6               1306.266           488.956           
+S6               1293.380           474.205           
+S6               1232.340           393.835           
+S6               1241.835           381.627           
+S6               1222.844           365.350           
+S6               1232.340           353.142           
+S6               1027.516           65.574            
+S6               1012.595           56.079            
+S6               707.393            273.111           
+S6               688.403            254.121           
+S6               739.948            218.853           
+S6               788.780            159.169           
+S6               806.414            106.268           
+S6               813.197            1.821             
+S6               994.961            12.673            
+S6               1228.270           27.594            
+S6               1222.844           115.763           
+S6               1228.270           167.308           
+S6               1241.835           229.705           
+S6               1255.399           254.121           
+S6               1279.815           302.953           
+S6               1309.657           354.498           
+S6               1335.430           401.974           
+S6               1359.846           448.093           
+S6               1370.616           475.830           
+S6               1381.615           491.542           
+S7               1122.467           968.970           
+S7               1174.012           987.282           
+S7               1225.557           1005.594          
+S7               1377.480           675.977           
+S7               1391.044           642.065           
+S7               1396.470           598.659           
+S7               1381.615           491.542           
+S7               1331.336           519.824           
+S7               1249.632           640.809           
+S7               1150.644           617.241           
+S7               1020.733           704.462           
+S7               1054.645           772.285           
+S7               1076.796           848.212           
+S7               1056.370           900.062           
+S7               1040.658           937.772           
+
+[SYMBOLS]
+;;Gage           X-Coord            Y-Coord           
+;;-------------- ------------------ ------------------
+RainGage         -175.841           1212.778          
+
+[LABELS]
+;;X-Coord          Y-Coord            Label           
+145.274            1129.896           "S1" "" "Arial" 14 0 0
+758.404            969.723            "S2" "" "Arial" 14 0 0
+247.369            666.226            "S3" "" "Arial" 14 0 0
+628.971            458.688            "S4" "" "Arial" 14 0 0
+952.552            257.845            "S5" "" "Arial" 14 0 0
+827.947            56.930             "S6" "" "Arial" 14 0 0
+1073.058           780.037            "S7" "" "Arial" 14 0 0
+1385.481           454.225            "Outfall" "" "Arial" 10 1 0
+
diff --git a/tests/solver/test_inlets_and_drains.cpp b/tests/solver/test_inlets_and_drains.cpp
new file mode 100644
index 000000000..466140c46
--- /dev/null
+++ b/tests/solver/test_inlets_and_drains.cpp
@@ -0,0 +1,120 @@
+/*
+ ******************************************************************************
+ Project:      OWA SWMM
+ Version:      5.2.3
+ Module:       test_inlets_and_drains.cpp
+ Description:  tests for SWMM inlets and drains API functions
+ Authors:      see AUTHORS
+ Copyright:    see AUTHORS
+ License:      see LICENSE
+ Last Updated: 3/27/2023
+ ******************************************************************************
+*/
+
+ #include <boost/test/unit_test.hpp>
+
+ #include "test_solver.hpp"
+
+
+#define ERR_NONE 0
+
+BOOST_AUTO_TEST_SUITE(test_toolkitapi_inlets_and_drains)
+
+
+BOOST_FIXTURE_TEST_CASE(getset_inlet_params, FixtureBeforeStep_Inlets){
+    int error, link_ind;
+    double value;
+    char id[] = "Street1";
+
+    error = swmm_getObjectIndex(SM_LINK, id, &link_ind);
+    BOOST_REQUIRE(error == ERR_NONE);
+
+    // test num inlets getter
+    error = swmm_getInletParam(link_ind, SM_INLETNUMINLETS, &value);
+    BOOST_REQUIRE(error == ERR_NONE);
+    BOOST_CHECK_SMALL(value - 1.0, 0.0001);
+    
+    // test clogging factor getter
+    error = swmm_getInletParam(link_ind, SM_INLETCLOGFACTOR, &value);
+    BOOST_REQUIRE(error == ERR_NONE);
+    BOOST_CHECK_SMALL(value - 50.0, 0.0001);
+
+    // test clogging factor setter
+    error = swmm_setInletParam(link_ind, SM_INLETCLOGFACTOR, 78.0);
+    BOOST_REQUIRE(error == ERR_NONE);
+    error = swmm_getInletParam(link_ind, SM_INLETCLOGFACTOR, &value);
+    BOOST_REQUIRE(error == ERR_NONE);
+    BOOST_CHECK_SMALL(value - 78.0, 0.0001);
+
+     // test flow limit getter
+    error = swmm_getInletParam(link_ind, SM_INLETFLOWLIMIT, &value);
+    BOOST_REQUIRE(error == ERR_NONE);
+    BOOST_CHECK_SMALL(value - 2.2, 0.0001);
+
+    // test flow limit setter
+    error = swmm_setInletParam(link_ind, SM_INLETFLOWLIMIT, 5.8);
+    BOOST_REQUIRE(error == ERR_NONE);
+    error = swmm_getInletParam(link_ind, SM_INLETFLOWLIMIT, &value);
+    BOOST_REQUIRE(error == ERR_NONE);
+    BOOST_CHECK_SMALL(value - 5.8, 0.0001);
+
+    // test local depression height getter
+    error = swmm_getInletParam(link_ind, SM_INLETLOCALDEPRESS, &value);
+    BOOST_REQUIRE(error == ERR_NONE);
+    BOOST_CHECK_SMALL(value - 0.5, 0.0001);
+    
+    // test local depression width getter
+    error = swmm_getInletParam(link_ind, SM_INLETLOCALWIDTH, &value);
+    BOOST_REQUIRE(error == ERR_NONE);
+    BOOST_CHECK_SMALL(value - 2.0, 0.0001);
+
+}
+
+BOOST_FIXTURE_TEST_CASE(get_result_during_sim, FixtureBeforeStep_Inlets){
+    int error, step_ind;
+    int lnk_ind;
+    double val;
+    double elapsedTime = 0.0;
+
+    char lnkid[] = "Street1";
+
+    error = swmm_getObjectIndex(SM_LINK, lnkid, &lnk_ind);
+    BOOST_REQUIRE(error == ERR_NONE);
+     
+    step_ind = 0;
+
+    do
+    {
+        error = swmm_step(&elapsedTime);
+
+        if (step_ind == 250) // peak flow in Street1
+        {
+            // test inlet flow factor getter
+            error = swmm_getInletResult(lnk_ind, SM_INLETFLOWFACTOR, &val);
+            BOOST_REQUIRE(error == ERR_NONE);
+            BOOST_CHECK_SMALL(val - 0.0118, 0.0001);
+
+            // test inlet flow capture getter
+            error = swmm_getInletResult(lnk_ind, SM_INLETFLOWCAPTURE, &val);
+            BOOST_REQUIRE(error == ERR_NONE);
+            BOOST_CHECK_SMALL(val - 3.3864, 0.0001);
+
+            // test inlet backflow getter
+            error = swmm_getInletResult(lnk_ind, SM_INLETBACKFLOW, &val);
+            BOOST_REQUIRE(error == ERR_NONE);
+            BOOST_CHECK_SMALL(val - 2.5670, 0.0001);
+
+            // test inlet backflow ratio getter
+            error = swmm_getInletResult(lnk_ind, SM_INLETBACKFLOWRATIO, &val);
+            BOOST_REQUIRE(error == ERR_NONE);
+            BOOST_CHECK_SMALL(val - 1.0, 0.0001);
+        }
+        
+        step_ind+=1;
+    }while (elapsedTime != 0 && !error);
+    // BOOST_REQUIRE(error == 1);
+    swmm_end();
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file
diff --git a/tests/solver/test_solver.hpp b/tests/solver/test_solver.hpp
index c2617ae9b..e45e477b4 100644
--- a/tests/solver/test_solver.hpp
+++ b/tests/solver/test_solver.hpp
@@ -24,6 +24,7 @@ extern "C" {
 #define DATA_PATH_INP_POLLUT_NODE "node_constantinflow_constanteffluent.inp"
 #define DATA_PATH_INP_POLLUT_LINK "link_constantinflow.inp"
 #define DATA_PATH_INP_LINK_DIR "link_flow_dir.inp"
+#define DATA_PATH_INP_INLETS_AND_DRAINS "test_inlet_drains.inp"
 #define DATA_PATH_RPT "tmp.rpt"
 #define DATA_PATH_OUT "tmp.out"
 
@@ -103,6 +104,18 @@ struct FixtureBeforeStep_Flow_Dir{
 };
 
 
+struct FixtureBeforeStep_Inlets{
+    FixtureBeforeStep_Inlets() {
+        swmm_open(DATA_PATH_INP_INLETS_AND_DRAINS, DATA_PATH_RPT, DATA_PATH_OUT);
+        swmm_start(0);
+    }
+    ~FixtureBeforeStep_Inlets() {
+        swmm_close();
+    }
+};
+
+
+
 // Declare shared test predicates here
 boost::test_tools::predicate_result check_cdd_double(std::vector<double>& test,
     std::vector<double>& ref, long cdd_tol);