Lemon Tiger changes
This commit is contained in:
@@ -754,7 +754,8 @@ int DLLEXPORT ENopenQ()
|
||||
OpenQflag = FALSE;
|
||||
SaveQflag = FALSE;
|
||||
if (!Openflag) return(102);
|
||||
if (!SaveHflag) return(104);
|
||||
// !LT! todo - check for SaveHflag / set sequential/step mode
|
||||
//if (!SaveHflag) return(104);
|
||||
|
||||
/* Open WQ solver */
|
||||
ERRCODE(openqual());
|
||||
@@ -1680,7 +1681,6 @@ int DLLEXPORT ENgetlinkvalue(int index, int code, float *value)
|
||||
|
||||
/*** Updated 10/25/00 ***/
|
||||
if (S[index] <= CLOSED) v = 0.0;
|
||||
|
||||
else v = Q[index]*Ucf[FLOW];
|
||||
break;
|
||||
|
||||
@@ -3143,6 +3143,8 @@ char *geterrmsg(int errcode)
|
||||
case 307: strcpy(Msg,ERR307); break;
|
||||
case 308: strcpy(Msg,ERR308); break;
|
||||
case 309: strcpy(Msg,ERR309); break;
|
||||
|
||||
case 401: strcpy(Msg,ERR401); break;
|
||||
default: strcpy(Msg,"");
|
||||
}
|
||||
return(Msg);
|
||||
@@ -3222,7 +3224,7 @@ int DLLEXPORT ENgetbasedemand(int nodeIndex, int demandIdx, float *baseDemand)
|
||||
if (nodeIndex <= 0 || nodeIndex > Nnodes) return(203);
|
||||
for(d=Node[nodeIndex].D; n<demandIdx && d != NULL; d=d->next) n++;
|
||||
if(n!=demandIdx) return(253);
|
||||
*baseDemand=d->Base*Ucf[FLOW];
|
||||
*baseDemand=(float)(d->Base*Ucf[FLOW]);
|
||||
return 0;
|
||||
}
|
||||
int DLLEXPORT ENgetdemandpattern(int nodeIndex, int demandIdx, int *pattIdx)
|
||||
|
||||
@@ -259,6 +259,9 @@ int nexthyd(long *tstep)
|
||||
else
|
||||
{
|
||||
Htime++; /* Force completion of analysis */
|
||||
if (OpenQflag) {
|
||||
Qtime++; // force completion of wq analysis too
|
||||
}
|
||||
}
|
||||
*tstep = hydstep;
|
||||
return(errcode);
|
||||
@@ -1055,8 +1058,12 @@ void tanklevels(long tstep)
|
||||
|
||||
/*** Updated 6/24/02 ***/
|
||||
/* Check if tank full/empty within next second */
|
||||
if (Tank[i].V + D[n] >= Tank[i].Vmax) Tank[i].V = Tank[i].Vmax;
|
||||
if (Tank[i].V - D[n] <= Tank[i].Vmin) Tank[i].V = Tank[i].Vmin;
|
||||
if (Tank[i].V + D[n] >= Tank[i].Vmax) {
|
||||
Tank[i].V = Tank[i].Vmax;
|
||||
}
|
||||
else if (Tank[i].V - D[n] <= Tank[i].Vmin) {
|
||||
Tank[i].V = Tank[i].Vmin;
|
||||
}
|
||||
|
||||
H[n] = tankgrade(i,Tank[i].V);
|
||||
}
|
||||
|
||||
119
src/quality.c
119
src/quality.c
@@ -106,7 +106,7 @@ int openqual()
|
||||
if (SegPool == NULL) errcode = 101; //(2.00.11 - LR)
|
||||
|
||||
/* Allocate scratch array & reaction rate array*/
|
||||
X = (double *) calloc(MAX((Nnodes+1),(Nlinks+1)),sizeof(double));
|
||||
XC = (double *) calloc(MAX((Nnodes+1),(Nlinks+1)),sizeof(double));
|
||||
R = (double *) calloc((Nlinks+1), sizeof(double));
|
||||
ERRCODE(MEMCHECK(X));
|
||||
ERRCODE(MEMCHECK(R));
|
||||
@@ -154,6 +154,9 @@ void initqual()
|
||||
for (i=1; i<=Nnodes; i++)
|
||||
if (Node[i].S != NULL) Node[i].S->Smass = 0.0;
|
||||
|
||||
QTankVolumes = calloc(Ntanks, sizeof(double)); // keep track of previous step's tank volumes.
|
||||
QLinkFlow = calloc(Nlinks, sizeof(double)); // keep track of previous step's link flows.
|
||||
|
||||
/* Set WQ parameters */
|
||||
Bucf = 1.0;
|
||||
Tucf = 1.0;
|
||||
@@ -189,7 +192,10 @@ void initqual()
|
||||
Wsource = 0.0;
|
||||
|
||||
/* Re-position hydraulics file */
|
||||
if (!OpenHflag) {
|
||||
fseek(HydFile,HydOffset,SEEK_SET);
|
||||
}
|
||||
|
||||
|
||||
/* Set elapsed times to zero */
|
||||
Htime = 0;
|
||||
@@ -221,7 +227,24 @@ int runqual(long *t)
|
||||
if (Qtime == Htime)
|
||||
{
|
||||
errcode = gethyd(&hydtime, &hydstep);
|
||||
if (!OpenHflag) { // test for sequential vs stepwise
|
||||
// sequential
|
||||
Htime = hydtime + hydstep;
|
||||
}
|
||||
else {
|
||||
// stepwise calculation
|
||||
for (int i=1; i<= Ntanks; ++i) {
|
||||
QTankVolumes[i-1] = Tank[i].V;
|
||||
}
|
||||
|
||||
for (int i=1; i<= Nlinks; ++i)
|
||||
{
|
||||
if (S[i] <= CLOSED) {
|
||||
QLinkFlow[i-1] = Q[i];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return(errcode);
|
||||
}
|
||||
@@ -243,7 +266,40 @@ int nextqual(long *tstep)
|
||||
|
||||
/* Determine time step */
|
||||
*tstep = 0;
|
||||
hydstep = Htime - Qtime;
|
||||
|
||||
// hydstep = Htime - Qtime;
|
||||
|
||||
if (Htime <= Dur) hydstep = Htime - Qtime;
|
||||
else hydstep = 0;
|
||||
|
||||
double *tankVolumes;
|
||||
|
||||
// if we're operating in stepwise mode, capture the tank levels so we can restore them later.
|
||||
if (OpenHflag) {
|
||||
tankVolumes = calloc(Ntanks, sizeof(double));
|
||||
for (int i=1; i<=Ntanks; ++i) {
|
||||
if (Tank[i].A != 0) { // skip reservoirs
|
||||
tankVolumes[i-1] = Tank[i].V;
|
||||
}
|
||||
}
|
||||
|
||||
// restore the previous step's tank volumes
|
||||
for (int i=1; i<=Ntanks; i++) {
|
||||
if (Tank[i].A != 0) { // skip reservoirs again
|
||||
int n = Tank[i].Node;
|
||||
Tank[i].V = QTankVolumes[i-1];
|
||||
H[n] = tankgrade(i,Tank[i].V);
|
||||
}
|
||||
}
|
||||
|
||||
// restore the previous step's pipe link flows
|
||||
for (int i=1; i<=Nlinks; i++) {
|
||||
if (S[i] <= CLOSED) {
|
||||
Q[i] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Perform water quality routing over this time step */
|
||||
if (Qualflag != NONE && hydstep > 0) transport(hydstep);
|
||||
@@ -255,6 +311,26 @@ int nextqual(long *tstep)
|
||||
|
||||
/* Save final output if no more time steps */
|
||||
if (!errcode && Saveflag && *tstep == 0) errcode = savefinaloutput();
|
||||
|
||||
// restore tank levels to post-runH state, if needed.
|
||||
if (OpenHflag) {
|
||||
for (int i=1; i<=Ntanks; i++) {
|
||||
if (Tank[i].A != 0) { // skip reservoirs again
|
||||
int n = Tank[i].Node;
|
||||
Tank[i].V = tankVolumes[i-1];
|
||||
H[n] = tankgrade(i,Tank[i].V);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=1; i<=Nlinks; ++i) {
|
||||
if (S[i] <= CLOSED) {
|
||||
Q[i] = QLinkFlow[i-1];
|
||||
}
|
||||
}
|
||||
|
||||
free(tankVolumes);
|
||||
}
|
||||
|
||||
return(errcode);
|
||||
}
|
||||
|
||||
@@ -321,7 +397,9 @@ int closequal()
|
||||
free(VolIn);
|
||||
free(MassIn);
|
||||
free(R);
|
||||
free(X);
|
||||
free(XC);
|
||||
free(QTankVolumes);
|
||||
free(QLinkFlow);
|
||||
return(errcode);
|
||||
}
|
||||
|
||||
@@ -344,10 +422,14 @@ int gethyd(long *hydtime, long *hydstep)
|
||||
{
|
||||
int errcode = 0;
|
||||
|
||||
// if hydraulics are not open, then we're operating in sequential mode.
|
||||
// else hydraulics are open, so use the hydraulic results in memory rather than reading from the temp file.
|
||||
if (!OpenHflag) {
|
||||
/* Read hydraulic results from file */
|
||||
if (!readhyd(hydtime)) return(307);
|
||||
if (!readhydstep(hydstep)) return(307);
|
||||
Htime = *hydtime;
|
||||
}
|
||||
|
||||
/* Save current results to output file */
|
||||
if (Htime >= Rtime)
|
||||
@@ -666,7 +748,7 @@ void accumulate(long dt)
|
||||
/* Re-set memory used to accumulate mass & volume */
|
||||
memset(VolIn,0,(Nnodes+1)*sizeof(double));
|
||||
memset(MassIn,0,(Nnodes+1)*sizeof(double));
|
||||
memset(X,0,(Nnodes+1)*sizeof(double));
|
||||
memset(XC,0,(Nnodes+1)*sizeof(double));
|
||||
|
||||
/* Compute average conc. of segments adjacent to each node */
|
||||
/* (For use if there is no transport through the node) */
|
||||
@@ -686,7 +768,7 @@ void accumulate(long dt)
|
||||
}
|
||||
}
|
||||
for (k=1; k<=Nnodes; k++)
|
||||
if (VolIn[k] > 0.0) X[k] = MassIn[k]/VolIn[k];
|
||||
if (VolIn[k] > 0.0) XC[k] = MassIn[k]/VolIn[k];
|
||||
|
||||
/* Move mass from first segment of each pipe into downstream node */
|
||||
memset(VolIn,0,(Nnodes+1)*sizeof(double));
|
||||
@@ -767,7 +849,7 @@ void updatenodes(long dt)
|
||||
** Purpose: updates concentration at all nodes to mixture of accumulated
|
||||
** inflow from connecting pipes.
|
||||
**
|
||||
** Note: Does not account for source flow effects. X[i] contains
|
||||
** Note: Does not account for source flow effects. XC[i] contains
|
||||
** average concen. of segments adjacent to node i, used in case
|
||||
** there was no inflow into i.
|
||||
**---------------------------------------------------------------------------
|
||||
@@ -780,7 +862,7 @@ void updatenodes(long dt)
|
||||
{
|
||||
if (D[i] < 0.0) VolIn[i] -= D[i]*dt;
|
||||
if (VolIn[i] > 0.0) C[i] = MassIn[i]/VolIn[i];
|
||||
else C[i] = X[i];
|
||||
else C[i] = XC[i];
|
||||
}
|
||||
|
||||
/* Update tank quality */
|
||||
@@ -809,8 +891,8 @@ void sourceinput(long dt)
|
||||
/* Establish a flow cutoff which indicates no outflow from a node */
|
||||
qcutoff = 10.0*TINY;
|
||||
|
||||
/* Zero-out the work array X */
|
||||
memset(X,0,(Nnodes+1)*sizeof(double));
|
||||
/* Zero-out the work array XC */
|
||||
memset(XC,0,(Nnodes+1)*sizeof(double));
|
||||
if (Qualflag != CHEM) return;
|
||||
|
||||
/* Consider each node */
|
||||
@@ -872,7 +954,7 @@ void sourceinput(long dt)
|
||||
}
|
||||
|
||||
/* Source concen. contribution = (mass added / outflow volume) */
|
||||
X[n] = massadded/volout;
|
||||
XC[n] = massadded/volout;
|
||||
|
||||
/* Update total mass added for time period & simulation */
|
||||
source->Smass += massadded;
|
||||
@@ -923,7 +1005,7 @@ void release(long dt)
|
||||
v = q*dt;
|
||||
|
||||
/* Include source contribution in quality released from node. */
|
||||
c = C[n] + X[n];
|
||||
c = C[n] + XC[n];
|
||||
|
||||
/* If link has a last seg, check if its quality */
|
||||
/* differs from that of the flow released from node.*/
|
||||
@@ -952,7 +1034,7 @@ void updatesourcenodes(long dt)
|
||||
** Input: dt = current WQ time step
|
||||
** Output: none
|
||||
** Purpose: updates quality at source nodes.
|
||||
** (X[n] = concen. added by source at node n)
|
||||
** (XC[n] = concen. added by source at node n)
|
||||
**---------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -968,7 +1050,7 @@ void updatesourcenodes(long dt)
|
||||
if (source == NULL) continue;
|
||||
|
||||
/* Add source to current node concen. */
|
||||
C[n] += X[n];
|
||||
C[n] += XC[n];
|
||||
|
||||
/* For tanks, node concen. = internal concen. */
|
||||
if (n > Njuncs)
|
||||
@@ -997,22 +1079,25 @@ void updatetanks(long dt)
|
||||
/* Examine each reservoir & tank */
|
||||
for (i=1; i<=Ntanks; i++)
|
||||
{
|
||||
n = Tank[i].Node;
|
||||
|
||||
/* Use initial quality for reservoirs */
|
||||
if (Tank[i].A == 0.0)
|
||||
{
|
||||
n = Tank[i].Node;
|
||||
C[n] = Node[n].C0;
|
||||
}
|
||||
|
||||
/* Update tank WQ based on mixing model */
|
||||
else switch(Tank[i].MixModel)
|
||||
else {
|
||||
switch(Tank[i].MixModel)
|
||||
{
|
||||
case MIX2: tankmix2(i,dt); break;
|
||||
case FIFO: tankmix3(i,dt); break;
|
||||
case LIFO: tankmix4(i,dt); break;
|
||||
default: tankmix1(i,dt); break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1443,7 +1528,7 @@ void ratecoeffs()
|
||||
{
|
||||
kw = Link[k].Kw;
|
||||
if (kw != 0.0) kw = piperate(k);
|
||||
Link[k].R = kw;
|
||||
Link[k].Rc = kw;
|
||||
R[k] = 0.0;
|
||||
}
|
||||
} /* End of ratecoeffs */
|
||||
@@ -1526,7 +1611,7 @@ double pipereact(int k, double c, double v, long dt)
|
||||
|
||||
/* Otherwise find bulk & wall reaction rates */
|
||||
rbulk = bulkrate(c,Link[k].Kb,BulkOrder)*Bucf;
|
||||
rwall = wallrate(c,Link[k].Diam,Link[k].Kw,Link[k].R);
|
||||
rwall = wallrate(c,Link[k].Diam,Link[k].Kw,Link[k].Rc);
|
||||
|
||||
/* Find change in concentration over timestep */
|
||||
dcbulk = rbulk*(double)dt;
|
||||
|
||||
@@ -14,6 +14,8 @@ AUTHOR: L. Rossman
|
||||
****************************************************
|
||||
*/
|
||||
/* ------------ Keyword Dictionary ---------- */
|
||||
#ifndef TEXT_H
|
||||
#define TEXT_H
|
||||
|
||||
#define w_USE "USE"
|
||||
#define w_SAVE "SAVE"
|
||||
@@ -501,6 +503,8 @@ AUTHOR: L. Rossman
|
||||
#define ERR308 "File Error 308: cannot save results to file."
|
||||
#define ERR309 "File Error 309: cannot save results to report file."
|
||||
|
||||
#define ERR401 "Sync Error 401: Qstep is not dividable by Hstep. Can't sync."
|
||||
|
||||
#define R_ERR201 "Input Error 201: syntax error in following line of "
|
||||
#define R_ERR202 "Input Error 202: illegal numeric value in following line of "
|
||||
#define R_ERR203 "Input Error 203: undefined node in following line of "
|
||||
@@ -528,3 +532,4 @@ AUTHOR: L. Rossman
|
||||
#define WARN5 "WARNING: Valves cannot deliver enough flow."
|
||||
#define WARN6 "WARNING: System has negative pressures."
|
||||
|
||||
#endif
|
||||
@@ -15,6 +15,8 @@ AUTHOR: L. Rossman
|
||||
*******************************************************************
|
||||
*/
|
||||
|
||||
#ifndef TOOLKIT_H
|
||||
#define TOOLKIT_H
|
||||
|
||||
#ifndef DLLEXPORT
|
||||
#ifdef DLL
|
||||
@@ -247,3 +249,5 @@ extern "C" {
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //TOOLKIT_H
|
||||
@@ -17,6 +17,8 @@ AUTHOR: L. Rossman
|
||||
|
||||
**********************************************************************
|
||||
*/
|
||||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
/*********************************************************/
|
||||
/* All floats have been re-declared as doubles (7/3/07). */
|
||||
@@ -206,6 +208,7 @@ typedef struct /* LINK OBJECT */
|
||||
double Kb; /* Bulk react. coeff */
|
||||
double Kw; /* Wall react. coeff */
|
||||
double R; /* Flow resistance */
|
||||
double Rc; /* Reaction cal */
|
||||
char Type; /* Link type */
|
||||
char Stat; /* Initial status */
|
||||
char Rpt; /* Reporting flag */
|
||||
@@ -451,3 +454,4 @@ enum HdrType /* Type of table heading */
|
||||
NODEHDR, /* Node Results */
|
||||
LINKHDR}; /* Link Results */
|
||||
|
||||
#endif
|
||||
14
src/vars.h
14
src/vars.h
@@ -11,7 +11,13 @@ AUTHOR: L. Rossman
|
||||
|
||||
************************************************************************
|
||||
*/
|
||||
EXTERN FILE *InFile, /* Input file pointer */
|
||||
#ifndef VARS_H
|
||||
#define VARS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "hash.h"
|
||||
|
||||
FILE *InFile, /* Input file pointer */
|
||||
*OutFile, /* Output file pointer */
|
||||
*RptFile, /* Report file pointer */
|
||||
*HydFile, /* Hydraulics file pointer */
|
||||
@@ -144,8 +150,10 @@ EXTERN double *D, /* Node actual demand */
|
||||
*K, /* Link settings */
|
||||
*Q, /* Link flows */
|
||||
*R, /* Pipe reaction rate */
|
||||
*X; /* General purpose array */
|
||||
*XC; /* General purpose array */
|
||||
EXTERN double *H; /* Node heads */
|
||||
EXTERN double *QTankVolumes;
|
||||
EXTERN double *QLinkFlow;
|
||||
EXTERN STmplist *Patlist; /* Temporary time pattern list */
|
||||
EXTERN STmplist *Curvelist; /* Temporary list of curves */
|
||||
EXTERN Spattern *Pattern; /* Time patterns */
|
||||
@@ -195,3 +203,5 @@ EXTERN int *Order, /* Node-to-row of A */
|
||||
EXTERN int *XLNZ, /* Start position of each column in NZSUB */
|
||||
*NZSUB, /* Row index of each coeff. in each column */
|
||||
*LNZ; /* Position of each coeff. in Aij array */
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user