Add more analysis options to the API (issue #425)

This commit is contained in:
Lew Rossman
2019-04-03 21:17:28 -04:00
parent f63df92e52
commit 3e733f5a2a
5 changed files with 140 additions and 20 deletions

View File

@@ -140,7 +140,7 @@ Public Const EN_CMD = 9
Public Const EN_DDA = 0 ' Demand driven analysis Public Const EN_DDA = 0 ' Demand driven analysis
Public Const EN_PDA = 1 ' Pressure driven analysis Public Const EN_PDA = 1 ' Pressure driven analysis
Public Const EN_TRIALS = 0 ' Hydraulic options Public Const EN_TRIALS = 0 ' Simulation options
Public Const EN_ACCURACY = 1 Public Const EN_ACCURACY = 1
Public Const EN_TOLERANCE = 2 Public Const EN_TOLERANCE = 2
Public Const EN_EMITEXPON = 3 Public Const EN_EMITEXPON = 3
@@ -152,6 +152,17 @@ Public Const EN_GLOBALEFFIC = 8
Public Const EN_GLOBALPRICE = 9 Public Const EN_GLOBALPRICE = 9
Public Const EN_GLOBALPATTERN = 10 Public Const EN_GLOBALPATTERN = 10
Public Const EN_DEMANDCHARGE = 11 Public Const EN_DEMANDCHARGE = 11
Public Const EN_SP_GRAVITY = 12
Public Const EN_SP_VISCOS = 13
Public Const EN_UNBALANCED = 14
Public Const EN_CHECKFREQ = 15
Public Const EN_MAXCHECK = 16
Public Const EN_DAMPLIMIT = 17
Public Const EN_SP_DIFFUS = 18
Public Const EN_BULKORDER = 19
Public Const EN_WALLORDER = 20
Public Const EN_TANKORDER = 21
Public Const EN_CONCENLIMIT = 22
Public Const EN_LOWLEVEL = 0 ' Control types Public Const EN_LOWLEVEL = 0 ' Control types
Public Const EN_HILEVEL = 1 Public Const EN_HILEVEL = 1

View File

@@ -145,7 +145,7 @@ Public Const EN_CMD = 9
Public Const EN_DDA = 0 ' Demand driven analysis Public Const EN_DDA = 0 ' Demand driven analysis
Public Const EN_PDA = 1 ' Pressure driven analysis Public Const EN_PDA = 1 ' Pressure driven analysis
Public Const EN_TRIALS = 0 ' Hydraulic options Public Const EN_TRIALS = 0 ' Simulation options
Public Const EN_ACCURACY = 1 Public Const EN_ACCURACY = 1
Public Const EN_TOLERANCE = 2 Public Const EN_TOLERANCE = 2
Public Const EN_EMITEXPON = 3 Public Const EN_EMITEXPON = 3
@@ -157,6 +157,17 @@ Public Const EN_GLOBALEFFIC = 8
Public Const EN_GLOBALPRICE = 9 Public Const EN_GLOBALPRICE = 9
Public Const EN_GLOBALPATTERN = 10 Public Const EN_GLOBALPATTERN = 10
Public Const EN_DEMANDCHARGE = 11 Public Const EN_DEMANDCHARGE = 11
Public Const EN_SP_GRAVITY = 12
Public Const EN_SP_VISCOS = 13
Public Const EN_UNBALANCED = 14
Public Const EN_CHECKFREQ = 15
Public Const EN_MAXCHECK = 16
Public Const EN_DAMPLIMIT = 17
Public Const EN_SP_DIFFUS = 18
Public Const EN_BULKORDER = 19
Public Const EN_WALLORDER = 20
Public Const EN_TANKORDER = 21
Public Const EN_CONCENLIMIT = 22
Public Const EN_LOWLEVEL = 0 ' Control types Public Const EN_LOWLEVEL = 0 ' Control types
Public Const EN_HILEVEL = 1 Public Const EN_HILEVEL = 1

View File

@@ -282,13 +282,13 @@ typedef enum {
/// Simulation options /// Simulation options
/** /**
These options specify hydraulic convergence criteria, choice of head loss formula, and These constants identify the hydraulic and water quality simulation options
several other parameters applied on a network-wide basis. They are accessed using the that are applied on a network-wide basis. They are accessed using the
@ref EN_getoption and @ref EN_setoption functions. @ref EN_getoption and @ref EN_setoption functions.
*/ */
typedef enum { typedef enum {
EN_TRIALS = 0, //!< Maximum hydraulic trials allowed EN_TRIALS = 0, //!< Maximum hydraulic trials allowed for hydraulic convergence
EN_ACCURACY = 1, //!< Maximum total relative flow change for hydraulic convergence EN_ACCURACY = 1, //!< Total normalized flow change for hydraulic convergence
EN_TOLERANCE = 2, //!< Water quality tolerance EN_TOLERANCE = 2, //!< Water quality tolerance
EN_EMITEXPON = 3, //!< Exponent in emitter discharge formula EN_EMITEXPON = 3, //!< Exponent in emitter discharge formula
EN_DEMANDMULT = 4, //!< Global demand multiplier EN_DEMANDMULT = 4, //!< Global demand multiplier
@@ -299,6 +299,17 @@ typedef enum {
EN_GLOBALPRICE = 9, //!< Global energy price per KWH EN_GLOBALPRICE = 9, //!< Global energy price per KWH
EN_GLOBALPATTERN = 10, //!< Index of a global energy price pattern EN_GLOBALPATTERN = 10, //!< Index of a global energy price pattern
EN_DEMANDCHARGE = 11 //!< Energy charge per max. KW usage EN_DEMANDCHARGE = 11 //!< Energy charge per max. KW usage
EN_SP_GRAVITY = 12, //!< Specific gravity
EN_SP_VISCOS = 13, //!< Specific viscosity (relative to water at 20 deg C)
EN_UNBALANCED = 14, //!< Extra trials allowed if hydraulics don't converge
EN_CHECKFREQ = 15, //!< Frequency of hydraulic status checks
EN_MAXCHECK = 16, //!< Maximum trials for status checking
EN_DAMPLIMIT = 17, //!< Accuracy level where solution damping begins
EN_SP_DIFFUS = 18, //!< Specific diffusivity (relative to chlorine at 20 deg C)
EN_BULKORDER = 19, //!< Bulk water reaction order for pipes
EN_WALLORDER = 20, //!< Wall reaction order for pipes (either 0 or 1)
EN_TANKORDER = 21, //!< Bulk water reaction order for tanks
EN_CONCENLIMIT = 22 //!< Limiting concentration for growth reactions
} EN_Option; } EN_Option;
/// Types of simple controls /// Types of simple controls

View File

@@ -1108,8 +1108,7 @@ int DLLEXPORT EN_getoption(EN_Project p, int option, double *value)
v = qual->Ctol * Ucf[QUALITY]; v = qual->Ctol * Ucf[QUALITY];
break; break;
case EN_EMITEXPON: case EN_EMITEXPON:
if (hyd->Qexp > 0.0) if (hyd->Qexp > 0.0) v = 1.0 / hyd->Qexp;
v = 1.0 / hyd->Qexp;
break; break;
case EN_DEMANDMULT: case EN_DEMANDMULT:
v = hyd->Dmult; v = hyd->Dmult;
@@ -1135,6 +1134,39 @@ int DLLEXPORT EN_getoption(EN_Project p, int option, double *value)
case EN_DEMANDCHARGE: case EN_DEMANDCHARGE:
v = hyd->Dcost; v = hyd->Dcost;
break; break;
case EN_SP_GRAVITY:
v = hyd->SpGrav;
break;
case EN_SP_VISCOS:
v = hyd->Viscos / VISCOS;
break;
case EN_UNBALANCED:
v = hyd->ExtraIter;
break;
case EN_CHECKFREQ:
v = hyd->CheckFreq;
break;
case EN_MAXCHECK:
v = hyd->MaxCheck;
break;
case EN_DAMPLIMIT:
v = hyd->DampLimit;
break;
case EN_SP_DIFFUS:
v = qual->Diffus / DIFFUS;
break;
case EN_BULKORDER:
v = qual->BulkOrder;
break;
case EN_WALLORDER:
v = qual->WallOrder;
break;
case EN_TANKORDER:
v = qual->TankOrder;
break;
case EN_CONCENLIMIT:
v = qual->Climit * p->Ucf[QUALITY];
break;
default: default:
return 251; return 251;
@@ -1163,6 +1195,22 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
double Ke, n, ucf; double Ke, n, ucf;
if (!p->Openflag) return 102; if (!p->Openflag) return 102;
// The EN_UNBALANCED option can be < 0 indicating that the simulation
// should be halted if no convergence is reached in EN_TRIALS. Other
// values set the number of additional trials to use with no more
// link status changes to achieve convergence.
if (option == EN_UNBALANCED)
{
hyd->ExtraIter = (int)value;
if (hyd->ExtraIter < 0) hyd->ExtraIter = -1;
return 0;
}
// All other option values must be non-negative
if (value < 0.0) return 213;
// Process the speficied option
switch (option) switch (option)
{ {
case EN_TRIALS: case EN_TRIALS:
@@ -1171,12 +1219,11 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
break; break;
case EN_ACCURACY: case EN_ACCURACY:
if (value < 1.e-5 || value > 1.e-1) return 213; if (value < 1.e-8 || value > 1.e-1) return 213;
hyd->Hacc = value; hyd->Hacc = value;
break; break;
case EN_TOLERANCE: case EN_TOLERANCE:
if (value < 0.0) return 213;
qual->Ctol = value / Ucf[QUALITY]; qual->Ctol = value / Ucf[QUALITY];
break; break;
@@ -1193,17 +1240,14 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
break; break;
case EN_DEMANDMULT: case EN_DEMANDMULT:
if (value <= 0.0) return 213;
hyd->Dmult = value; hyd->Dmult = value;
break; break;
case EN_HEADERROR: case EN_HEADERROR:
if (value < 0.0) return 213;
hyd->HeadErrorLimit = value / Ucf[HEAD]; hyd->HeadErrorLimit = value / Ucf[HEAD];
break; break;
case EN_FLOWCHANGE: case EN_FLOWCHANGE:
if (value < 0.0) return 213;
hyd->FlowChangeLimit = value / Ucf[FLOW]; hyd->FlowChangeLimit = value / Ucf[FLOW];
break; break;
@@ -1218,12 +1262,11 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
break; break;
case EN_GLOBALEFFIC: case EN_GLOBALEFFIC:
if (value <= 0.0 || value > 100.0) return 213; if (value <= 1.0 || value > 100.0) return 213;
hyd->Epump = value; hyd->Epump = value;
break; break;
case EN_GLOBALPRICE: case EN_GLOBALPRICE:
if (value < 0.0) return 213;
hyd->Ecost = value; hyd->Ecost = value;
break; break;
@@ -1234,10 +1277,53 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
break; break;
case EN_DEMANDCHARGE: case EN_DEMANDCHARGE:
if (value < 0.0) return 213;
hyd->Dcost = value; hyd->Dcost = value;
break; break;
case EN_SP_GRAVITY:
if (value <= 0.0) return 213;
Ucf[PRESSURE] *= (value / hyd->SpGrav);
hyd->SpGrav = value;
break;
case EN_SP_VISCOS:
if (value <= 0.0) return 213;
hyd->Viscos = value * VISCOS;
break;
case EN_CHECKFREQ:
hyd->CheckFreq = (int)value;
break;
case EN_MAXCHECK:
hyd->MaxCheck = (int)value;
break;
case EN_DAMPLIMIT:
hyd->DampLimit = value;
break;
case EN_SP_DIFFUS:
qual->Diffus = value * DIFFUS;
break;
case EN_BULKORDER:
qual->BulkOrder = value;
break;
case EN_WALLORDER:
if (value == 0.0 || value == 1.0) qual->WallOrder = value;
else return 213;
break;
case EN_TANKORDER:
qual->TankOrder = value;
break;
case EN_CONCENLIMIT:
qual->Climit = value / p->Ucf[QUALITY];
break;
default: default:
return 251; return 251;
} }

View File

@@ -23,10 +23,11 @@ BOOST_FIXTURE_TEST_CASE(test_anlys_getoption, FixtureOpenClose)
{ {
int i; int i;
std::vector<double> test(12); std::vector<double> test(23);
double *array = test.data(); double *array = test.data();
std::vector<double> ref = {40.0, 0.001, 0.01, 0.5, 1.0, 0.0, 0.0, 0.0, 75.0, 0.0, 0.0, 0.0}; std::vector<double> ref = {40.0, 0.001, 0.01, 0.5, 1.0, 0.0, 0.0, 0.0, 75.0, 0.0, 0.0, 0.0,
1.0, 1.0, 10.0, 2.0, 10.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0};
error = EN_solveH(ph); error = EN_solveH(ph);
BOOST_REQUIRE(error == 0); BOOST_REQUIRE(error == 0);
@@ -35,7 +36,7 @@ BOOST_FIXTURE_TEST_CASE(test_anlys_getoption, FixtureOpenClose)
BOOST_REQUIRE(error == 0); BOOST_REQUIRE(error == 0);
for (i=EN_TRIALS; i<=EN_DEMANDCHARGE; i++) { for (i=EN_TRIALS; i<=EN_CONCENLIMIT; i++) {
error = EN_getoption(ph, i, array++); error = EN_getoption(ph, i, array++);
BOOST_REQUIRE(error == 0); BOOST_REQUIRE(error == 0);
} }
@@ -43,7 +44,7 @@ BOOST_FIXTURE_TEST_CASE(test_anlys_getoption, FixtureOpenClose)
BOOST_CHECK_EQUAL_COLLECTIONS(ref.begin(), ref.end(), test.begin(), test.end()); BOOST_CHECK_EQUAL_COLLECTIONS(ref.begin(), ref.end(), test.begin(), test.end());
double temp; double temp;
error = EN_getoption(ph, 18, &temp); error = EN_getoption(ph, 25, &temp);
BOOST_CHECK(error == 251); BOOST_CHECK(error == 251);
} }