Ecological Landscape Modeling: Models Pages |
#include "globals.h"
Go to the source code of this file.
Data Structures | |
struct | Chan_segm |
struct | Chan |
struct | Cells |
struct | Structure |
Water control structure attributes. More... | |
struct | Schedule |
struct | Points |
struct | HistData |
Defines | |
#define | STEP(x) ( ((x)>=0) ? 1.0 : 0.0 ) |
#define | MAX_H_STRUCT 180 |
#define | LEFT 1 |
#define | RIGHT -1 |
#define | NONE 0 |
#define | EAST 1 |
#define | SOUTH 2 |
#define | ALL 3 |
Functions | |
void | CanalReInit () |
Re-initialize the depths and concentrations in canals under the Positional Analysis mode. | |
void | Canal_Network_Init (float baseDatum, float *elev) |
Initialize the water managment network topology. | |
void | Run_Canal_Network (float *SWH, float *ElevMap, float *MC, float *GWV, float *poros, float *GWcond, double *NA, double *PA, double *SA, double *GNA, double *GPA, double *GSA, float *Unsat, float *sp_yield) |
Runs the water management network. | |
void | ReadStructures (char *name, float BASE_DATUM) |
Read attribute data on water control structures. | |
void | ReadStructFlow_PtSer (char *name) |
Read time series data of flow at water control structures. | |
void | ReadStructTP_PtSer (char *name) |
Read time series data of TP concentration at water control structures. | |
void | ReadStructTS_PtSer (char *name) |
Read time series data of TS (salt/tracer) concentration at water control structures. | |
void | Channel_configure (float *ElevMap, struct Chan *channel_first) |
Configure attributes of grid cells interacting with canal vectors. | |
void | getCanalElev (int chan_n) |
Assign elevation to canal using slope & distance from start point . | |
void | FluxChannel (int chan_n, float *SWH, float *ElevMap, float *MC, float *GWH, float *poros, float *GWcond, double *NA, double *PA, double *SA, double *GNA, double *GPA, double *GSA, float *Unsat, float *sp_yield) |
Runs the iterative algorithm over the network of canals. | |
void | Flows_in_Structures (float *SWH, float *GW, float *poros, float *Elev, double *NA, double *PA, double *SA) |
Calling function to functions that determine flows through water control structures. | |
void | flowData_CanCan (struct Structure *structs, struct Structure *struct_hist_start, float *SWH, double *NA, double *PA, double *SA) |
Canal-to-Canal water control structure flows: Data-driven (historical/sfwmm). | |
void | flowData_CelCel (struct Structure *structs, float *SWH, double *NA, double *PA, double *SA) |
Cell-to-Cell water control structure flows: Data-driven (historical/sfwmm). | |
void | flowData_CanCel (struct Structure *structs, struct Structure *struct_hist_start, float *SWH, double *NA, double *PA, double *SA) |
Canal-to-Cell water control structure flows: Data-driven (historical/sfwmm). | |
void | flowData_CelCan (struct Structure *structs, float *SWH, double *NA, double *PA, double *SA) |
Cell-to-Canal water control structure flows: Data-driven (historical/sfwmm). | |
void | flowCalc_CanCan (struct Structure *structs, float *SWH, float *GW, float *poros, float *Elev, double *NA, double *PA, double *SA) |
Canal-to-Canal water control structure flows: Calculated. | |
void | flowCalc_CelCel (struct Structure *structs, float *SWH, float *Elev, double *NA, double *PA, double *SA) |
Cell-to-Cell water control structure flows: Calculated (rule-based). | |
void | flowCalc_CanCel (struct Structure *structs, float *SWH, float *GW, float *poros, float *Elev, double *NA, double *PA, double *SA) |
Canal-to-Cell water control structure flows: Calculated (rule-based). | |
void | flowCalc_CelCan (struct Structure *structs, float *SWH, float *GW, float *poros, float *Elev, double *NA, double *PA, double *SA) |
Cell-to-Canal water water control structure flows: Calculated (rule-based). | |
float | f_Manning (float delta, float SWater, float SW_coef) |
Surface water exchange between cell and canal. | |
float | f_Ground (float dh, float height, float GW_coef, float l_Length) |
Subsurface ground water exchange between cell and canal. | |
float | GetGraph (struct Schedule *graph, float x) |
Graph to read the time dependent schedules. | |
struct Chan * | ReadChanStruct (char *filename) |
Reads the information about canal reaches from data file. | |
struct Cells * | MarkCell (int x, int y, int index, float length, struct Cells *cell, int ch_number, int levee, int xm, int ym, int c_num, int *marked, float distTot) |
Mark cell function. | |
struct Schedule * | Read_schedule (char *sched_name, char *filename, float BASE_DATUM) |
Read target stage schedule as a recurring time-series graph. | |
int | Wrdcmp (char *s, char *t) |
Compare two words. | |
float | UTM2kmx (double UTM) |
Converter from meters in UTM to grid cell row location (zero origin). | |
float | UTM2kmy (double UTM) |
Converter from meters in UTM to grid cell column location (zero origin). | |
double | julday (int mon, int day, int year, int h, int mi, double se) |
Determine the Julian calendar day from a Gregorian date. | |
void | init_pvar (VOIDP Map, UCHAR *mask, unsigned char Mtype, float iv) |
Initialize a variable to a value. | |
VOIDP | nalloc (unsigned mem_size, const char var_name[]) |
Allocate memory for a variable. | |
char * | Scip (char *s, char SYM) |
Skip ahead in a string until next field. | |
int | isInteger (char *target_str) |
Determine if an integer is present in string. | |
int | isFloat (char *target_str) |
Determine if a float is present in string. | |
float | FMOD (float x, float y) |
Modulus of a pair of (double) arguments. | |
int | Round (float x) |
truncate (not rounding) to an integer | |
float | Flux_SWcells (int i0, int i1, int j0, int j1, float *SWater, float *Elevation, float *MC) |
Surface water flux calculations. | |
void | Flux_SWstuff (int i0, int i1, int j0, int j1, float Flux, float *SURFACE_WAT, double *STUF1, double *STUF2, double *STUF3, float *SfWat_vel_day) |
Flux of surface water constituents. | |
Variables | |
FILE * | schedFile |
FILE * | ChanInFile |
FILE * | CanalOutFile |
FILE * | CanalOutFile_P |
FILE * | CanalOutFile_S |
FILE * | WstructOutFile |
FILE * | WstructOutFile_P |
FILE * | WstructOutFile_S |
FILE * | canDebugFile |
FILE * | CanalCellInteractDebug |
FILE * | F_struct_wat |
FILE * | F_struct_TP |
FILE * | F_struct_TS |
int | CHo |
int | CHANNEL_MAX_ITER |
int | UTM_EOrigin |
int | UTM_NOrigin |
int | printchan = 0 |
int | N_c_iter = 0 |
int | num_cell = 0 |
int | C_Mark = 0 |
float | C_F |
float | F_ERROR |
float | MINDEPTH |
int | num_chan |
int | num_struct_hist |
int | numTPser |
int | numTSser |
int | disAggNum |
int | IDhist [MAX_H_STRUCT] |
float * | MCopen |
char | modelFileName [300] |
struct Chan ** | Chan_list |
struct Cells * | cell_last |
struct Cells * | cell |
struct Structure * | struct_first |
struct Structure * | structs |
struct HistData | Hist_data [MAX_H_STRUCT] |
int | NumScheds = 0 |
char * | ModelPath |
char * | OutputPath |
char * | ProjName |
char | modelName [20] |
char | modelVers [10] |
char | SimAlt [20] |
char | SimModif [20] |
double | Jdate_init |
double | Jdate_end |
int | PORnumday |
float | can_Intvl |
int | canPrint |
unsigned char * | HAB |
int * | basn |
float | GP_DetentZ |
float | GP_MinCheck |
float | GP_SLRise |
float | GP_mannDepthPow |
float | GP_mannHeadPow |
float | GP_calibGWat |
int | numBasn |
basnDef ** | basn_list |
basnDef * | basins |
double * | TOT_VOL_CAN |
double * | VOL_IN_STR |
double * | VOL_IN_OVL |
double * | VOL_IN_SPG |
double * | VOL_IN_GW |
double * | VOL_OUT_STR |
double * | VOL_OUT_OVL |
double * | VOL_OUT_SPG |
double * | VOL_OUT_GW |
double * | TOT_P_CAN |
double * | P_IN_STR |
double * | P_IN_OVL |
double * | P_IN_SPG |
double * | P_IN_GW |
double * | P_OUT_STR |
double * | P_OUT_OVL |
double * | P_OUT_SPG |
double * | P_OUT_GW |
double * | TOT_S_CAN |
double * | S_IN_STR |
double * | S_IN_OVL |
double * | S_IN_SPG |
double * | S_IN_GW |
double * | S_OUT_STR |
double * | S_OUT_OVL |
double * | S_OUT_SPG |
double * | S_OUT_GW |
This defines or declares variables & functions that are global to WatMgmt.c.
Note: documented with Doxygen, which expects specific syntax within special comments.
The Everglades Landscape Model (ELM).
last updated: Mar 2008
Definition in file watmgmt.h.
#define STEP | ( | x | ) | ( ((x)>=0) ? 1.0 : 0.0 ) |
#define MAX_H_STRUCT 180 |
maximum number of water control structures that have historical or other data as input
Definition at line 33 of file watmgmt.h.
Referenced by ReadStructures().
#define LEFT 1 |
#define RIGHT -1 |
#define NONE 0 |
#define EAST 1 |
#define SOUTH 2 |
#define ALL 3 |
void CanalReInit | ( | ) |
Re-initialize the depths and concentrations in canals under the Positional Analysis mode.
Definition at line 292 of file WatMgmt.c.
Referenced by reinitCanals().
00293 { 00294 int i; 00295 for( i = 0; i < num_chan; i++ ) 00296 00297 { 00298 Chan_list[i]->wat_depth = Chan_list[i]->ic_depth; 00299 Chan_list[i]->P = Chan_list[i]->ic_P_con * Chan_list[i]->area * Chan_list[i]->ic_depth; /* kg/m3 * m2 * m */ 00300 Chan_list[i]->N = Chan_list[i]->ic_N_con * Chan_list[i]->area * Chan_list[i]->ic_depth; /* kg/m3 * m2 * m */ 00301 Chan_list[i]->S = Chan_list[i]->ic_S_con * Chan_list[i]->area * Chan_list[i]->ic_depth; /* kg/m3 * m2 * m */ 00302 00303 } 00304 }
void Canal_Network_Init | ( | float | baseDatum, | |
float * | elev | |||
) |
Initialize the water managment network topology.
Initialize/configure the network of canals/levees and and water control structures. The canal information stored in the global array Chan_list
baseDatum | GP_DATUM_DISTANCE | |
elev | SED_ELEV |
Definition at line 96 of file WatMgmt.c.
Referenced by init_canals().
00098 { struct Structure *structs; 00099 int i,j; 00100 char filename[30]; 00101 00102 sprintf(filename,"CanalData"); 00103 00104 /* Input the canals geometry file, return pointer to first vector */ 00105 /* Configure the canals, marking the cells that interact with them */ 00106 /* and storing the pointers to the cells for each of the canals in Chan_list array */ 00107 Channel_configure(elev, ReadChanStruct (filename)); 00108 00109 for( i = 0; i < num_chan; i++ ) 00110 { 00111 Chan_list[i]->P = Chan_list[i]->ic_P_con * Chan_list[i]->area * Chan_list[i]->ic_depth; /* kg/m3 * m2 * m */ 00112 Chan_list[i]->N = Chan_list[i]->ic_N_con * Chan_list[i]->area * Chan_list[i]->ic_depth; /* kg/m3 * m2 * m */ 00113 Chan_list[i]->S = Chan_list[i]->ic_S_con * Chan_list[i]->area * Chan_list[i]->ic_depth; /* kg/m3 * m2 * m */ 00114 } 00115 00116 usrErr ("\tCanal geometry configured OK"); 00117 00118 /* Read data on the water control structures, return pointer to the first structure */ 00119 ReadStructures (filename, baseDatum); 00120 00121 ON_MAP[T(2,2)] = 0; 00122 00123 MCopen = (float *) nalloc(sizeof(float)*(s0+2)*(s1+2),"MCopen"); /* open-water manning's coef, used in structure cell-cell bridge flow */ 00124 init_pvar(MCopen,NULL,'f',0.05); /* this is a hard-wired parameter (value set to last argument, 0.05) - but do not do anything much with it now for the bridge flows */ 00125 00126 00127 if ( debug > 0 ) /* Output the canal/levee modifications to ON_MAP */ 00128 { 00129 sprintf( modelFileName, "%s/%s/Output/Debug/ON_MAP_CANAL.txt", OutputPath, ProjName ); 00130 00131 00132 if ( ( ChanInFile = fopen( modelFileName, "w" ) ) == NULL ) 00133 { 00134 printf( "Can't open the %s canal/levee debug file!\n", modelFileName ); 00135 exit(-1) ; 00136 } 00137 fprintf ( ChanInFile, "ROWS=%d\nCOLUMNS=%d\nFORMAT=text\nINFO=\"Debug data: Overland flow restrictions due to levees. \"\nMISSING=0\n", s0, s1 ); 00138 00139 for ( i = 1; i <= s0 ; i++ ) 00140 { for ( j = 1 ; j <= s1 ; j++ ) 00141 fprintf( ChanInFile, "%4d\t", ON_MAP[T(i,j)]) ; 00142 fprintf ( ChanInFile, "\n" ); 00143 } 00144 fclose( ChanInFile ) ; 00145 } 00146 00147 00148 /* Open file for writing structure flows */ 00149 { if(H_OPSYS==UNIX) 00150 sprintf( modelFileName, "%s/%s/Output/Canal/structsOut", OutputPath, ProjName ); 00151 else sprintf( modelFileName, "%s%s:Output:structsOut", OutputPath, ProjName ); 00152 } 00153 00154 /* Open file to print structure flows to */ 00155 if ( ( WstructOutFile = fopen( modelFileName, "w" ) ) == NULL ) 00156 { 00157 printf( "Can't open %s file!\n", modelFileName ); 00158 exit(-1) ; 00159 } 00160 /* Print The Header Line For This File */ 00161 fprintf ( WstructOutFile, 00162 "%s %s %s %s scenario: Sum of water flows at structures (ft^3/sec)\n Date\t", &modelName, &modelVers, &SimAlt, &SimModif ); 00163 structs = struct_first; 00164 while ( structs != NULL ) 00165 { fprintf( WstructOutFile, "%7s\t", structs->S_nam); 00166 structs = structs->next_in_list; 00167 } 00168 00169 /* Open file for writing structure P concs */ 00170 { if(H_OPSYS==UNIX) 00171 sprintf( modelFileName, "%s/%s/Output/Canal/structsOut_P", OutputPath, ProjName ); 00172 else sprintf( modelFileName, "%s%s:Output:structsOut_P", OutputPath, ProjName ); 00173 } 00174 00175 /* Open file to print structure flows to */ 00176 if ( ( WstructOutFile_P = fopen( modelFileName, "w" ) ) == NULL ) 00177 { 00178 printf( "Can't open %s file!\n", modelFileName ); 00179 exit(-1) ; 00180 } 00181 /* Print The Header Line For This File */ 00182 fprintf ( WstructOutFile_P, 00183 "%s %s %s %s scenario: Flow weighted mean TP conc at structures ( mg/L) \n Date\t", &modelName, &modelVers, &SimAlt, &SimModif ); 00184 structs = struct_first; 00185 while ( structs != NULL ) 00186 { fprintf( WstructOutFile_P, "%7s\t", structs->S_nam); 00187 structs = structs->next_in_list; 00188 } 00189 00190 /* Open file for writing structure Salin concs */ 00191 { if(H_OPSYS==UNIX) 00192 sprintf( modelFileName, "%s/%s/Output/Canal/structsOut_S", OutputPath, ProjName ); 00193 else sprintf( modelFileName, "%s%s:Output:structsOut_S", OutputPath, ProjName ); 00194 } 00195 00196 /* Open file to print structure flows to */ 00197 if ( ( WstructOutFile_S = fopen( modelFileName, "w" ) ) == NULL ) 00198 { 00199 printf( "Can't open %s file!\n", modelFileName ); 00200 exit(-1) ; 00201 } 00202 /* Print The Header Line For This File */ 00203 fprintf ( WstructOutFile_S, 00204 "%s %s %s %s scenario: Flow weighted mean tracer concentration at structures ( g/L) \n Date\t", &modelName, &modelVers, &SimAlt, &SimModif ); 00205 structs = struct_first; 00206 while ( structs != NULL ) 00207 { fprintf( WstructOutFile_S, "%7s\t", structs->S_nam); 00208 structs = structs->next_in_list; 00209 } 00210 00211 /****/ 00212 00213 /* Open file to print canal stage info to */ 00214 { if(H_OPSYS==UNIX) 00215 sprintf( modelFileName, "%s/%s/Output/Canal/CanalOut", OutputPath, ProjName ); 00216 else sprintf( modelFileName, "%s%s:Output:CanalOut", OutputPath, ProjName ); 00217 } 00218 00219 if ( ( CanalOutFile = fopen( modelFileName, "w" ) ) == NULL ) 00220 { 00221 printf( "Can't open %s file!\n", modelFileName ); 00222 exit(-1) ; 00223 } 00224 00225 fprintf ( CanalOutFile, "%s %s %s %s scenario: Instantaneous water depth (meters, from bottom of canal) in canal Reaches\n Date\t", &modelName, &modelVers, &SimAlt, &SimModif ); /* print the header line for this file */ 00226 /* channels with negative widths are reserved for new canals */ 00227 /* v2.2 put a "R_" prefix in front of the canal ID# */ 00228 for( i = 0; i < num_chan; i++ ) {if (Chan_list[i]->width > 0) fprintf ( CanalOutFile, "R_%d\t",Chan_list[i]->number);} 00229 00230 00231 /* Open file to print canal phosph info to */ 00232 { if(H_OPSYS==UNIX) 00233 sprintf( modelFileName, "%s/%s/Output/Canal/CanalOut_P", OutputPath, ProjName ); 00234 else sprintf( modelFileName, "%s%s:Output:CanalOut_P", OutputPath, ProjName ); 00235 } 00236 00237 if ( ( CanalOutFile_P = fopen( modelFileName, "w" ) ) == NULL ) 00238 { 00239 printf( "Can't open %s file!\n", modelFileName ); 00240 exit(-1) ; 00241 } 00242 00243 fprintf ( CanalOutFile_P, "%s %s %s %s scenario: Instantaneous TP conc (mg/L) in canal Reaches\n Date\t", &modelName, &modelVers, &SimAlt, &SimModif ); /* print the header line for this file */ 00244 /* v2.2 put a "R_" prefix in front of the canal ID# */ 00245 for( i = 0; i < num_chan; i++ ) {if (Chan_list[i]->width > 0) fprintf ( CanalOutFile_P, "R_%d\t",Chan_list[i]->number);} 00246 00247 /* Open file to print canal salinity/tracer info to */ 00248 { if(H_OPSYS==UNIX) 00249 sprintf( modelFileName, "%s/%s/Output/Canal/CanalOut_S", OutputPath, ProjName ); 00250 else sprintf( modelFileName, "%s%s:Output:CanalOut_S", OutputPath, ProjName ); 00251 } 00252 00253 if ( ( CanalOutFile_S = fopen( modelFileName, "w" ) ) == NULL ) 00254 { 00255 printf( "Can't open %s file!\n", modelFileName ); 00256 exit(-1) ; 00257 } 00258 00259 fprintf ( CanalOutFile_S, "%s %s %s %s scenario: Instantaneous tracer conc (g/L) in canal Reaches\n Date\t", &modelName, &modelVers, &SimAlt, &SimModif ); /* print the header line for this file */ 00260 /* v2.2 put a "R_" prefix in front of the canal ID# */ 00261 for( i = 0; i < num_chan; i++ ) {if (Chan_list[i]->width > 0) fprintf ( CanalOutFile_S, "R_%d\t",Chan_list[i]->number);} 00262 00263 00264 00265 /* Open file for canal-cell flux debugging purposes */ 00266 if( debug > 0 ) 00267 { 00268 if(H_OPSYS==UNIX) 00269 sprintf( modelFileName, "%s/%s/Output/Debug/Can_debug", OutputPath, ProjName ); 00270 else sprintf( modelFileName, "%s%s:Output:Can_debug", OutputPath, ProjName ); 00271 00272 00273 /* Open file for debugging and error/warnings on canal-cell flows, structure flows */ 00274 if ( ( canDebugFile = fopen( modelFileName, "w" ) ) == NULL ) 00275 { 00276 printf( "Can't open %s file!\n", modelFileName ); 00277 exit(-1) ; 00278 } 00279 00280 fprintf ( canDebugFile, "Depending on level of the debug requested, printed here are data on canal-cell flows and excessive demands on data-driven structure flows. \n" ); /* v2.5 made use of this file pointer */ 00281 fflush(canDebugFile); 00282 00283 } 00284 00285 return; 00286 00287 }
void Run_Canal_Network | ( | float * | SWH, | |
float * | Elevation, | |||
float * | MC, | |||
float * | GW, | |||
float * | poros, | |||
float * | GWcond, | |||
double * | NA, | |||
double * | PA, | |||
double * | SA, | |||
double * | GNA, | |||
double * | GPA, | |||
double * | GSA, | |||
float * | Unsat, | |||
float * | sp_yield | |||
) |
Runs the water management network.
Invoke the calls to water control structure flows and the canal-cell interactions.
SWH | SURFACE_WAT | |
Elevation | SED_ELEV | |
MC | HYD_MANNINGS_N | |
GW | SAT_WATER | |
poros | HP_HYD_POROSITY | |
GWcond | HYD_RCCONDUCT | |
NA | DINdummy | |
PA | TP_SF_WT | |
SA | SALT_SURF_WT | |
GNA | DINdummy | |
GPA | TP_SED_WT | |
GSA | SALT_SED_WT | |
Unsat | UNSAT_WATER | |
sp_yield | HP_HYD_SPEC_YIELD |
Definition at line 330 of file WatMgmt.c.
Referenced by horizFlow().
00334 { int i; 00335 float CH_vol; 00336 00337 if ( canPrint && (( N_c_iter++ % hyd_iter ) == 0.0) ) { 00338 if (SensiOn) { 00339 printchan = (SimTime.IsSimulationEnd) ? (1) : (0); /* flag to indicate to print canal/struct data */ 00340 } 00341 else printchan = 1; 00342 } 00343 else printchan = 0; 00344 00345 if (printchan == 1) { 00346 00347 fprintf( WstructOutFile, "\n%d/%d/%d\t",SimTime.yr[0],SimTime.mo[0],SimTime.da[0] ); 00348 fprintf( WstructOutFile_P, "\n%d/%d/%d\t",SimTime.yr[0],SimTime.mo[0],SimTime.da[0] ); 00349 /* fprintf( WstructOutFile_N, "\n%d/%d/%d\t",SimTime.yr[0],SimTime.mo[0],SimTime.da[0] ); */ 00350 fprintf( WstructOutFile_S, "\n%d/%d/%d\t",SimTime.yr[0],SimTime.mo[0],SimTime.da[0] ); 00351 00352 fprintf (CanalOutFile, "\n%d/%d/%d\t",SimTime.yr[0],SimTime.mo[0],SimTime.da[0] ); 00353 fprintf (CanalOutFile_P, "\n%d/%d/%d\t",SimTime.yr[0],SimTime.mo[0],SimTime.da[0] ); 00354 /* fprintf (CanalOutFile_N, "\n%d/%d/%d\t",SimTime.yr[0],SimTime.mo[0],SimTime.da[0] ); */ 00355 fprintf (CanalOutFile_S, "\n%d/%d/%d\t",SimTime.yr[0],SimTime.mo[0],SimTime.da[0] ); 00356 } 00357 00358 00359 for ( i = 0; i < num_chan; i++ ) 00360 { /* set the sum of historical (or other-model) and Rule-based flows to/from a canal per iteration to 0 */ 00361 Chan_list[i]->sumHistIn = Chan_list[i]->sumHistOut = 0.0; 00362 Chan_list[i]->sumRuleIn = Chan_list[i]->sumRuleOut = 0.0; 00363 } 00364 00365 /* calculate flows through water control structures */ 00366 Flows_in_Structures ( SWH, GW, poros, Elevation, NA, PA, SA ); 00367 00368 /* output header for canal-cell flux output canal debug file, at relatively high debug levels (writes a LOT of stuff) */ 00369 if( debug > 3 ) 00370 { 00371 fprintf( canDebugFile, "N%3d WatDepth Pconc Sconc flux_S flux_G flux_L Qin Qout #_iter Area error \n", N_c_iter ); 00372 00373 } 00374 00375 /* Flux the water along a canal using the relaxation procedure */ 00376 00377 for( i = 0; i < num_chan; i++ ) 00378 if (Chan_list[i]->width > 0) /* a neg width canal is skipped */ 00379 00380 { 00381 FluxChannel ( i, SWH, Elevation, MC, GW, poros, GWcond, NA, PA, SA, GNA, GPA, GSA, Unsat, sp_yield ); 00382 /* calculate total canal volume after canal fluxes */ 00383 CH_vol = Chan_list[i]->area*Chan_list[i]->wat_depth; 00384 00385 /* sum the storages on iteration that performs budget checks */ 00386 if ( !( FMOD(N_c_iter,(1/canstep) )) && (SimTime.IsBudgEnd ) ) { 00387 TOT_VOL_CAN[Chan_list[i]->basin] += CH_vol; 00388 TOT_VOL_CAN[0] += CH_vol; 00389 TOT_P_CAN[Chan_list[i]->basin] += Chan_list[i]->P; 00390 TOT_P_CAN[0] += Chan_list[i]->P; 00391 TOT_S_CAN[Chan_list[i]->basin] += Chan_list[i]->S; 00392 TOT_S_CAN[0] += Chan_list[i]->S; 00393 } 00394 00395 00396 if ( printchan ) 00397 { 00398 /* report N&P concentration in mg/L (kg/m3==g/L * 1000 = mg/L) */ 00399 Chan_list[i]->P_con = (CH_vol > 0) ? (Chan_list[i]->P/CH_vol*1000.0) : 0.0; 00400 /* Chan_list[i]->N_con = (CH_vol > 0) ? (Chan_list[i]->N/CH_vol*1000.0) : 0.0; */ 00401 Chan_list[i]->S_con = (CH_vol > 0) ? (Chan_list[i]->S/CH_vol ) : 0.0; 00402 00403 /* v2.2 increased decimal places in output (from 6.3f to 7.4f) */ 00404 fprintf( CanalOutFile, "%6.2f\t", Chan_list[i]->wat_depth ); 00405 fprintf( CanalOutFile_P, "%7.4f\t", Chan_list[i]->P_con ); 00406 /* fprintf( CanalOutFile_N, "%7.4f\t", Chan_list[i]->N_con ); */ 00407 fprintf( CanalOutFile_S, "%7.4f\t", Chan_list[i]->S_con ); 00408 } 00409 } 00410 if ( printchan ) 00411 { 00412 fflush(CanalOutFile); 00413 fflush(CanalOutFile_P); 00414 /* fflush(CanalOutFile_N); */ 00415 fflush(CanalOutFile_S); 00416 } 00417 00418 return; 00419 }
void ReadStructures | ( | char * | filename, | |
float | BASE_DATUM | |||
) |
Read attribute data on water control structures.
filename | Water control structures attributes file name | |
BASE_DATUM | GP_DATUM_DISTANCE |
Definition at line 611 of file WatMgmt.c.
References Structure::canal_fr, Structure::canal_to, Structure::cell_HW, Structure::cell_i_fr, Structure::cell_i_HW, Structure::cell_i_to, Structure::cell_i_TW, Structure::cell_j_fr, Structure::cell_j_HW, Structure::cell_j_to, Structure::cell_j_TW, Structure::cell_TW, Chan_list, ChanInFile, CHo, disAggNum, HistData::flag, Structure::flag, Structure::flagHWsched, Structure::flagHWtide, Structure::flagTWsched, Structure::flagTWtide, H_OPSYS, Hist_data, Structure::histID, Structure::HW_graph, Structure::HW_stage, IDhist, isFloat(), isInteger(), MAX_H_STRUCT, modelFileName, modelName, ModelPath, msgStr, Structure::next_in_list, num_chan, num_struct_hist, NumScheds, numTPser, numTSser, ON_MAP, ProjName, Read_schedule(), ReadStructFlow_PtSer(), ReadStructTP_PtSer(), ReadStructTS_PtSer(), s0, s1, HistData::S_nam, Structure::S_nam, Scip(), SimAlt, SimModif, Structure::SrcDest, Structure::str_cell_i, Structure::str_cell_j, struct_first, structs, Structure::Sum_N, Structure::Sum_P, Structure::Sum_S, Structure::SumFlow, T, TAB, Structure::TN, Structure::TNser, Structure::TP, Structure::TPser, Structure::TS, Structure::TSser, Structure::TW_graph, Structure::TW_stage, UNIX, usrErr(), Structure::w_coef, Chan::width, and WriteMsg().
Referenced by Canal_Network_Init().
00612 { 00622 struct Structure *structs, *struct_next, *struct_last; 00623 00624 char ss[622], *s; 00625 char sched_name[20]; 00626 int i, j, k; 00627 int IDhist[MAX_H_STRUCT]; 00628 int lincnt; 00629 double Jdate_read; 00630 char lline[2001], *line; 00631 int yyyy, mm, dd; 00632 char structName[20]; 00633 char scenario[20], s_modname[20]; 00634 char histTP[5]; 00635 char histTS[5]; 00636 char srcType[5], destType[5]; /* v2.8 */ 00637 char prefixTide[]="tid_"; /* v2.8 - the Headwater and Tailwater schedules have the 'tid_' prefix (in CanalData.graph) if they are tidally based, this will be used to check for such a schedule */ 00638 00639 num_struct_hist = 0; 00640 numTPser = numTSser = disAggNum = 0; /* v2.6 */ 00641 00642 { if(H_OPSYS==UNIX) 00643 sprintf( modelFileName, "%s/%s/Data/%s.struct", ModelPath, ProjName, filename ); 00644 else sprintf( modelFileName, "%s%s:Data:%s.struct", ModelPath, ProjName, filename ); 00645 } 00646 00647 /* Open file with structures data */ 00648 if ( ( ChanInFile = fopen( modelFileName, "r" ) ) == NULL ) 00649 { 00650 printf( "Can't open %s file!\n", modelFileName ) ; 00651 exit(-1) ; 00652 } 00653 00654 /* Allocate memory for structures */ 00655 if ( (structs = (struct Structure *) malloc( (size_t) sizeof( struct Structure ))) == NULL ) 00656 { 00657 printf( "No memory for first structure\n " ) ; 00658 exit( -2 ) ; 00659 } 00660 struct_first = structs; 00661 00662 fgets( ss, 620, ChanInFile ); 00663 sscanf(ss, "%s\t%s\t%s\t%s",&scenario,&scenario,&s_modname,&scenario); /* 2 junk strings followed by the model name and actual scenario ID */ 00664 if (strcmp(scenario,SimAlt) != 0) { 00665 sprintf(msgStr, "The scenario (%s) found in the %s file doesn't match the one (%s) you asked for in Driver.parm!", 00666 scenario, modelFileName, SimAlt); usrErr(msgStr); 00667 exit(-1); 00668 } 00669 if (strcmp(s_modname,modelName) != 0) { 00670 sprintf(msgStr, "The model name (%s) found in the %s file doesn't match the one (%s) in the canal data file!", 00671 s_modname, modelFileName, modelName); usrErr(msgStr); 00672 exit(-1); 00673 } 00674 00675 /* Skip 2'nd header line */ 00676 fgets( ss, 620, ChanInFile ); 00677 00678 00679 /* Read structure descriptors until none left */ 00680 while ( fgets( ss, 620, ChanInFile ) != NULL && !feof( ChanInFile ) ) 00681 { 00682 s = ss; 00683 00684 00685 sscanf( s, "%d", &structs->flag ); 00686 /* structure flag: <0 - skip structure info, structure not operating; */ 00687 /* >0 - historical/other-data data array, flag=1 normally in this case, but is >1 for aggregated SFWMM structures; */ 00688 /* 0 - rule-based structure */ 00689 if ( structs->flag < 0 ) continue; 00690 if ( structs->flag > 0 && structs->flag <10 ) { 00691 structs->histID = ++num_struct_hist; 00692 Hist_data[structs->histID-1].flag = structs->flag; 00693 } 00694 00695 00696 /* assign integer to the historical data ID, and increment the counter for structures with historical/other-data data to be read from datafile. */ 00697 /* flags >= 20 represent structures (such as the S-11s) that were aggregated in SFWMM output */ 00698 /* and need to be assigned disaggregated flows for separate ELM structures */ 00699 /* Ex: SFWMM structure name S11 may have flag = 2 in CanalData.struct. That S11 flow holds the sum of S-11A-C flows. */ 00700 /* The flags on S-11A, S-11B, and S-11C would all have been assigned 20, 20, and 20 in the CanalData.struct file */ 00701 00702 /* NO LONGER NECESSARY (old note, kept here in v2.2+): as a temporary measure until the SFWMM output .dss file is fixed, the structures that have calculated "other" partitions */ 00703 /* (S140,S7,S8) are assigned historical flags of 9 (they are in the dss file read by a SAS routine, the flag */ 00704 /* of 9 allows them to remain in the file, but the structure is turned off because it has flag >1) */ 00705 00706 00707 s = Scip( s, TAB ); 00708 00709 if ( *s != TAB ) { 00710 sscanf ( s, "%s", &structs->S_nam ); 00711 if ( structs->flag >0 && structs->flag <10) 00712 sscanf ( s, "%s", &Hist_data[structs->histID-1].S_nam ); 00713 00714 /* for solute concentration of flows thru structures, */ 00715 /* data use flag XXser: -1== simulated, 0==static historical, 1= time-varying historical */ 00716 s = Scip( s, TAB ); 00717 if ( *s == TAB ) structs->TPser = -1; 00718 else { 00719 sscanf ( s, "%s", &histTP ); /* read the field that either has TP conc (ug/L=ppb) that is constant across time 00720 or has (any) string to indicate the use of TimeSeries data from a datafile (read later)*/ 00721 if (isInteger(histTP) ) { 00722 structs->TPser = 0; 00723 structs->TP = atof(histTP)*1.0e-6; /* conc (ug/L=>g/L) that is constant across time */ 00724 } 00725 else { structs->TPser = 1; numTPser++;} /* otherwise, we will be reading time series data later */ 00726 } 00727 00728 s = Scip( s, TAB ); 00729 if ( *s == TAB ) structs->TNser = -1; /* value to indicate use of simulated, not historical, data */ 00730 else { 00731 sscanf ( s, "%f", &structs->TN ); 00732 structs->TNser = 0; 00733 structs->TN *= 1.0e-6;/* read the TN conc (ug/L=>g/L) that is constant across time */ 00734 } 00735 00736 00737 s = Scip( s, TAB ); 00738 if ( *s == TAB ) structs->TSser = -1; /* value to indicate use of simulated, not historical, data */ 00739 /* v2.2 added code to allow use of TimeSeries input data in addition to old method of a constant concentration */ 00740 else { 00741 sscanf ( s, "%s", &histTS ); /* read the field that either has TS (salt) conc (g/L=ppt) that is constant across time 00742 or has (any) string to indicate the use of TimeSeries data from a datafile (read later)*/ 00743 if (isFloat(histTS) ) { 00744 structs->TSser = 0; 00745 structs->TS = atof(histTS)*1.0; /* conc (no conversion, g/L) that is constant across time */ 00746 } 00747 else { structs->TSser = 1; numTSser++;} /* otherwise, we will be reading time series data later */ 00748 00749 } 00750 00751 s = Scip( s, TAB ); 00752 if ( *s == TAB ) structs->str_cell_i = 0; /* non 0 if elevation at the structure location is desired */ 00753 else { 00754 sscanf( s, "%d", &structs->str_cell_i ); 00755 structs->str_cell_i++; /* this converts the data map coords to model coords (map+1) */ 00756 } 00757 00758 s = Scip( s, TAB ); 00759 00760 if ( *s == TAB ) structs->str_cell_j = 0; /* non 0 if elevation at the structure location is desired */ 00761 else { 00762 sscanf( s, "%d", &structs->str_cell_j ); 00763 structs->str_cell_j++; 00764 } 00765 00766 if ( structs->str_cell_i != 0 && !ON_MAP[T(structs->str_cell_i, structs->str_cell_j)] ) 00767 { printf ( "Location of water control structure %s is off-map.\n", structs->S_nam ); 00768 exit (-2); /*check that cells obtained are within on-map boundaries */ 00769 } 00770 00771 00772 } 00773 00774 s = Scip( s, TAB ); 00775 00776 if ( *s == TAB ) structs->canal_fr = 0; /* non 0 if the structure involves a donor canal */ 00777 else sscanf( s, "%d", &structs->canal_fr ); 00778 s = Scip( s, TAB ); 00779 if ( *s == TAB) structs->canal_to = 0; /* non 0 if the structure involves a receiving canal */ 00780 else sscanf( s, "%d", &structs->canal_to ); 00781 s = Scip( s, TAB ); 00782 00783 if ( structs->canal_fr - CHo >= num_chan || structs->canal_to - CHo >= num_chan ) 00784 { printf ( "Canal from/to doesn't exist for water control structure %s\n", structs->S_nam ); 00785 exit (-2); /* check that canals read are consistent with canals data */ 00786 } 00787 /* check to ensure canals associated with structures are valid */ 00788 if ( structs->canal_fr != 0 && Chan_list[structs->canal_fr- CHo]->width <= 0.1 ) 00789 { printf ( "The donor canal %d has been turned off for water control structure %s\n", structs->canal_fr, structs->S_nam ); 00790 exit (-2); 00791 } 00792 if ( structs->canal_to != 0 && Chan_list[structs->canal_to- CHo]->width <= 0.1 ) 00793 { printf ( "The recipient canal %d has been turned off for water control structure %s\n", structs->canal_to, structs->S_nam ); 00794 exit (-2); 00795 } 00796 00797 if (*s == TAB) structs->cell_i_fr = 0; /* non 0 if the structure involves a donor cell */ 00798 else 00799 { sscanf( s, "%d", &structs->cell_i_fr ); 00800 structs->cell_i_fr++; 00801 } 00802 s = Scip( s, TAB ); 00803 if (*s == TAB) structs->cell_j_fr = 0; 00804 else 00805 { sscanf( s, "%d", &structs->cell_j_fr ); 00806 structs->cell_j_fr++; 00807 } 00808 s = Scip( s, TAB ); 00809 00810 00811 if ( structs->cell_i_fr > 2 && !ON_MAP[T(structs->cell_i_fr, structs->cell_j_fr)] ) 00812 { printf ( "Donor cell for water control structure %s is off-map.\n", structs->S_nam ); 00813 exit (-2); /*check that cells obtained are within on-map boundaries */ 00814 } 00815 00816 /* if valid donor cell, mark it on ON_MAP */ 00817 if ( structs->cell_j_fr ) ON_MAP[T(structs->cell_i_fr, structs->cell_j_fr)] += 100; 00818 00819 if (*s == TAB) structs->cell_i_to = 0; /* non 0 if the structure involves a recipient cell */ 00820 else 00821 { sscanf( s, "%d", &structs->cell_i_to ); 00822 structs->cell_i_to++; 00823 } 00824 00825 s = Scip( s, TAB ); 00826 if (*s == TAB) structs->cell_j_to = 0; 00827 else 00828 { sscanf( s, "%d", &structs->cell_j_to ); 00829 structs->cell_j_to++; 00830 } 00831 00832 00833 if ( structs->cell_i_to > 2 && !ON_MAP[T(structs->cell_i_to, structs->cell_j_to)] ) 00834 { printf ( "Recipient cell for water control structure %s is off-map.\n", structs->S_nam ); 00835 exit (-2); /*check that cells obtained are within on-map boundaries */ 00836 } 00837 00838 /* if valid recieving cell, mark it on ON_MAP */ 00839 /* this used to check for cell_j_to > 2, not putting recipient LEC cells ON_MAP */ 00840 if ( structs->cell_j_to ) ON_MAP[T(structs->cell_i_to, structs->cell_j_to)] += 100; 00841 00842 /* the following seven field of data are for rule-based water management */ 00843 00844 /* read the targeted HeadWater stage info */ 00845 s = Scip( s, TAB ); 00846 if (*s == TAB) { 00847 structs->flagHWsched = -1; /* v2.8 */ 00848 } 00849 else if ( isalpha (*s) ) { /* if there is a graph for the schedule */ 00850 sscanf( s, "%s", sched_name ); 00851 structs->HW_graph = Read_schedule ( sched_name, filename, BASE_DATUM ); 00852 structs->flagHWsched = 1; /* v2.8 this is a time-varying target */ 00853 structs->flagHWtide = ( strncmp(sched_name, prefixTide ,4) == 0) ? (1) : (0); /* true if this is a tidally-based target */ 00854 } 00855 else { sscanf( s, "%f", &structs->HW_stage ); 00856 structs->HW_stage += BASE_DATUM; 00857 structs->flagHWsched = 0; /* v2.8 this is a constant target TODO - this should not be available as an option */ 00858 } 00859 00860 00861 00862 /* read the targeted TailWater stage info */ 00863 s = Scip( s, TAB ); 00864 if (*s == TAB) { 00865 structs->flagTWsched = -1; /* v2.8 */ 00866 } 00867 else if ( isalpha (*s) ) { /* if there is a graph for the schedule */ 00868 sscanf( s, "%s", sched_name ); 00869 structs->TW_graph = Read_schedule ( sched_name, filename, BASE_DATUM ); 00870 structs->flagTWsched = 1; /* v2.8 this is a time-varying target */ 00871 structs->flagTWtide = ( strncmp(sched_name, prefixTide ,4) == 0) ? (1) : (0); /* true if this is a tidally-based target */ 00872 } 00873 else { sscanf( s, "%f", &structs->TW_stage ); 00874 structs->TW_stage += BASE_DATUM; /* prior to v2.8, the input data was designed to be negative values in the dbase for tailwater - this is NOT the case any longer */ 00875 structs->flagTWsched = 0; /* v2.8 this is a constant target TODO - this should not be available as an option */ 00876 } 00877 00878 /* read the northing (row) coordinate of the location where the HeadWater stage will be checked */ 00879 s = Scip( s, TAB ); 00880 if (*s == TAB) structs->cell_i_HW = 0; 00881 else 00882 { sscanf( s, "%d", &structs->cell_i_HW ); 00883 structs->cell_i_HW++; 00884 } 00885 00886 /* read the easting (col) coordinate of the location where the HeadWater stage will be checked */ 00887 s = Scip( s, TAB ); 00888 if (*s == TAB) structs->cell_j_HW = 0; 00889 else 00890 { sscanf( s, "%d", &structs->cell_j_HW ); 00891 structs->cell_j_HW++; 00892 } 00893 00894 if ( structs->cell_i_HW > s0 || structs->cell_j_HW > s1 ) 00895 { printf ( "Error in definition of HW location of water control structure %s", structs->S_nam ); 00896 exit (-2); /*check that cell obtained is within array boundaries */ 00897 } 00898 else 00899 { (structs->cell_i_HW != 0) ? (structs->cell_HW = T(structs->cell_i_HW, structs->cell_j_HW) ) : (0); /* v2.8 determine this location now, instead of during dynamic calcs */ 00900 } 00901 00902 // if ( ( structs->cell_HW != 0) && (structs->flagHWsched < 0) ) /* v2.8 TODO will need to clean up the dbase to remove HW and TW cell locations, for structures that have such fields filled in but are data-driven */ 00903 // { printf ( "Error: lacking target stage or stage sched for HW location of water control structure %s", structs->S_nam ); 00904 // exit (-2); 00905 // } 00906 00907 00908 /* read the northing (row) coordinate of the location where the TailWater stage will be checked */ 00909 s = Scip( s, TAB ); 00910 if (*s == TAB) structs->cell_i_TW = 0; 00911 else 00912 { sscanf( s, "%d", &structs->cell_i_TW ); 00913 structs->cell_i_TW++; 00914 } 00915 00916 /* read the easting (col) coordinate of the location where the TailWater stage will be checked */ 00917 s = Scip( s, TAB ); 00918 if (*s == TAB) structs->cell_j_TW = 0; 00919 else 00920 { sscanf( s, "%d", &structs->cell_j_TW ); 00921 structs->cell_j_TW++; 00922 } 00923 00924 if ( structs->cell_i_TW > s0 || structs->cell_j_TW > s1 ) 00925 { printf ( "Error in definition of TW location of water control structure %s", structs->S_nam ); 00926 exit (-2); /*check that cell obtained is within array boundaries */ 00927 } 00928 else 00929 { (structs->cell_i_TW != 0) ? (structs->cell_TW = T(structs->cell_i_TW, structs->cell_j_TW) ) : (0); /* v2.8 determine this location now, instead of during dynamic calcs */ 00930 } 00931 00932 // if ( ( structs->cell_TW != 0) && (structs->flagTWsched < 0) ) /* v2.8 TODO will need to clean up the dbase to remove HW and TW cell locations, for structures that have such fields filled in but are data-driven */ 00933 // { printf ( "Error: lacking target stage or stage sched for TW location of water control structure %s", structs->S_nam ); 00934 // exit (-2); 00935 // } 00936 00937 /* read the flow coefficient, that was derived in dbase to allow flow calcs via a simple weir-flow eqn */ 00938 s = Scip( s, TAB ); 00939 if (*s == TAB || *s == '?') structs->w_coef = 0; 00940 else sscanf( s, "%f", &structs->w_coef ); 00941 00942 struct_last = structs; 00943 00944 /* Allocate memory for next structure */ 00945 if ( (struct_next = (struct Structure *) malloc( (size_t) sizeof( struct Structure ))) == NULL ) 00946 { 00947 printf( "Failed to allocate memory for next structure (%s)\n ", structs->S_nam ) ; 00948 exit( -2 ) ; 00949 }; 00950 00951 /* v2.8 redesign of structure flow choices */ 00952 /* assemble the attribute of the Source and Destination raster-vector type ('Can'al or 'Cel'l) */ 00953 if ( structs->canal_fr != 0 ) sprintf( srcType, "Can"); 00954 if ( structs->canal_to != 0 ) sprintf( destType, "Can"); 00955 if ( structs->cell_i_fr != 0 && structs->cell_j_fr != 0 ) sprintf( srcType, "Cel"); 00956 if ( structs->cell_i_to != 0 && structs->cell_j_to != 0 ) sprintf( destType, "Cel"); 00957 sprintf( structs->SrcDest, "%s%s", srcType, destType ); 00958 00959 00960 /* initialize the sum of structure flows and constit solute in flows */ 00961 structs->SumFlow = 0.0; 00962 structs->Sum_P = 0.0; 00963 structs->Sum_N = 0.0; 00964 structs->Sum_S = 0.0; 00965 00966 structs->next_in_list = struct_next; 00967 structs = struct_next; 00968 } 00969 00970 struct_last->next_in_list = NULL; 00971 free ((char *)structs); 00972 fclose (ChanInFile); 00973 00974 00975 sprintf(msgStr,"\tUsing %d target stage schedules for rule-based flows", NumScheds); usrErr(msgStr); 00976 usrErr( "\tWater control structure locs/attributes read OK" ); 00977 00978 /* v2.6 - encoded the reading of these data into separate functions - no change in data or results */ 00979 if (num_struct_hist>0) ReadStructFlow_PtSer(filename); 00980 if (numTPser>0) ReadStructTP_PtSer(filename); 00981 if (numTSser>0) ReadStructTS_PtSer(filename); 00982 00983 sprintf(msgStr, "\t**** Evaluate scenario: %s %s ****", &SimAlt, &SimModif ); usrErr(msgStr); WriteMsg(msgStr,1); 00984 00985 return; 00986 }
void ReadStructFlow_PtSer | ( | char * | filename | ) |
Read time series data of flow at water control structures.
v2.6 - made this a separate function instead of the old nested if - then statements
Definition at line 994 of file WatMgmt.c.
References HistData::aggCnt, HistData::aggID, HistData::arrayN, HistData::arrayP, HistData::arrayS, HistData::arrayWat, disAggNum, F_struct_wat, HistData::flag, Structure::flag, H_OPSYS, Hist_data, Structure::histID, Jdate_end, Jdate_init, julday(), modelFileName, ModelPath, msgStr, nalloc(), Structure::next_in_list, num_struct_hist, PORnumday, ProjName, Structure::S_nam, Scip(), SimAlt, struct_first, structs, TAB, UNIX, usrErr(), and usrErr0().
Referenced by ReadStructures().
00995 { 00996 char lline[2001], *line; 00997 char scenario[20]; 00998 int i, k; 00999 int lincnt; 01000 char structName[20]; 01001 int yyyy, mm, dd; 01002 double Jdate_read; 01003 usrErr0 ( "\tControl structures' water flow time series..."); 01004 if(H_OPSYS==UNIX) 01005 sprintf( modelFileName, "%s/%s/Data/%s.struct_wat", ModelPath, ProjName, filename ); 01006 else sprintf( modelFileName, "%s%s:Data:%s.struct_wat", ModelPath, ProjName, filename ); 01007 01008 01009 /* Open file with structure flow data */ 01010 if ( ( F_struct_wat = fopen( modelFileName, "r" ) ) == NULL ) 01011 { 01012 printf( "Can't open %s file!\n", modelFileName ) ; 01013 exit(-1) ; 01014 } 01015 01016 fgets(lline, 2000, F_struct_wat); /* first header line with the alternative's name */ 01017 line=lline; 01018 sscanf(line, "%s",&scenario); 01019 if (strcmp(scenario,SimAlt) != 0) { 01020 sprintf(msgStr, "The scenario (%s) found in the %s file doesn't match the one (%s) you asked for in Driver.parm!", scenario, modelFileName, SimAlt); usrErr(msgStr); 01021 exit(-1); 01022 } 01023 01024 fgets(lline, 2000, F_struct_wat); /* read 2'nd header line with column names */ 01025 line=lline; 01026 line = Scip( line, TAB ); 01027 line = Scip( line, TAB ); 01028 line = Scip( line, TAB ); /*read past the three date columns, ready to read the variable names */ 01029 01030 01031 /* loop through all the control structure columns */ 01032 for ( i = 0; i < num_struct_hist; i++ ) { 01033 01034 Hist_data[i].arrayWat = (float*) nalloc( ( (PORnumday+2)*sizeof(float) ), "timeseries temp" ); 01035 Hist_data[i].arrayP = (float*) nalloc( ( (PORnumday+2)*sizeof(float) ), "timeseries temp" ); 01036 Hist_data[i].arrayN = (float*) nalloc( ( (PORnumday+2)*sizeof(float) ), "timeseries temp" ); 01037 Hist_data[i].arrayS = (float*) nalloc( ( (PORnumday+2)*sizeof(float) ), "timeseries temp" ); 01038 01039 /* allocate memory for dissaggregated structures and provide a couple of attributes */ 01040 if ( Hist_data[i].flag > 1 ) { 01041 structs = struct_first; /* go through all structures to pull out the disaggregated ones */ 01042 while ( structs != NULL ) 01043 { 01044 /* Ex: the SFWMM aggregated S10's flag is 2, S10AB&C's flags are 20 */ 01045 if ( structs->flag == 10 * Hist_data[i].flag ) 01046 { 01047 /* disAggNum counts the total number of disaggregated structures for simulation */ 01048 disAggNum++; 01049 Hist_data[num_struct_hist+disAggNum-1].arrayWat = 01050 (float*) nalloc( ( (PORnumday+2)*sizeof(float) ), "timeseries temp" ); 01051 Hist_data[num_struct_hist+disAggNum-1].arrayP = 01052 (float*) nalloc( ( (PORnumday+2)*sizeof(float) ), "timeseries temp" ); 01053 Hist_data[num_struct_hist+disAggNum-1].arrayN = 01054 (float*) nalloc( ( (PORnumday+2)*sizeof(float) ), "timeseries temp" ); 01055 Hist_data[num_struct_hist+disAggNum-1].arrayS = 01056 (float*) nalloc( ( (PORnumday+2)*sizeof(float) ), "timeseries temp" ); 01057 01058 Hist_data[num_struct_hist+disAggNum-1].aggID = i; /* the aggregated structure ID is attached to the dissagregated one */ 01059 strcpy( Hist_data[num_struct_hist+disAggNum-1].S_nam, structs->S_nam ); /* the disaggregated structure's name is put into the HistData structure */ 01060 Hist_data[i].aggCnt++; /* increment a count of the number of disagg structs associated w/ each agg struct */ 01061 structs->flag = 1; /* set the disagg struct's processing flag to 1, the only flag used for simulation structure flows (new input style) */ 01062 structs->histID = num_struct_hist+disAggNum; /* store the historical ID value for the disagg structures */ 01063 01064 } 01065 01066 structs = structs->next_in_list; 01067 } 01068 } 01069 01070 sscanf ( line,"%s\t",&structName); /* read the structure names in the header */ 01071 if (strcmp(Hist_data[i].S_nam , structName) != 0) { 01072 printf( "variable name %s in input file does not match order of CanalData.structs.\n", structName); 01073 exit(-1); 01074 } 01075 line = Scip( line, TAB ); 01076 } 01077 01078 01079 lincnt = 0; /* historical/other-data data input file record # starting at the point where the model reads values */ 01080 while ( fgets(lline, 2000, F_struct_wat) != NULL && !feof( F_struct_wat ) ) 01081 { 01082 line = lline; 01083 sscanf( line, "%d %d %d",&yyyy,&mm,&dd); /* read the date of the current record */ 01084 01085 /* julian day, returns a double (args = mon, day, year, hours, minutes, seconds) */ 01086 Jdate_read = julday( mm,dd,yyyy,0,0,0.0 ); 01087 if ((lincnt == 0) && (Jdate_read > Jdate_init) ) { 01088 printf (" \n***Error\nStructure flow data (%s) init date > simulation start date\n", modelFileName); exit (-1); 01089 } 01090 if ((Jdate_read >= Jdate_init) && (Jdate_read <= Jdate_end)) 01091 { 01092 line = Scip( line, TAB ); 01093 line = Scip( line, TAB ); 01094 01095 for ( i = 0; i < num_struct_hist; i++ ) { /* loop through all the control structure columns in the input file */ 01096 line = Scip( line, TAB ); 01097 if (*line == TAB) Hist_data[i].arrayWat[((int)(lincnt))] = 0; 01098 else sscanf( line, "%f", &Hist_data[i].arrayWat[((int)(lincnt))] ); 01099 Hist_data[i].arrayWat[((int)(lincnt))] *= 2446.848; /* cfs => m^3/d (0.02832*60*60*24) */ 01100 } 01101 01102 for (i = num_struct_hist; i < num_struct_hist+disAggNum; i++) { /* dissaggregate all agg structs */ 01103 k = Hist_data[i].aggID; /* use the aggregated historical data WCstructure */ 01104 Hist_data[i].arrayWat[((int)(lincnt))] = 01105 Hist_data[k].arrayWat[((int)(lincnt))] / (Hist_data[k].aggCnt) ; 01106 01107 } 01108 01109 01110 lincnt++; /* increment the number of daily data records */ 01111 } 01112 01113 } /* end of reading structure flow records */ 01114 01115 if (lincnt == 0) { 01116 printf (" \n***Error\nStructure flow data (%s) has date problem (0 records read)\n", modelFileName); exit (-1); 01117 } 01118 else if (lincnt != PORnumday ) { 01119 printf (" \n***Error\nStructure flow data (%s) has problem (%d records read, %d expected)\n", modelFileName, lincnt, PORnumday); exit (-1); 01120 } 01121 01122 sprintf (msgStr, "done, found %d records.",lincnt); usrErr(msgStr); 01123 fclose (F_struct_wat); 01124 } /* end of function for flow record input */
void ReadStructTP_PtSer | ( | char * | filename | ) |
Read time series data of TP concentration at water control structures.
v2.6 - made this a separate function instead of the old nested if - then statements
Definition at line 1132 of file WatMgmt.c.
References HistData::arrayP, disAggNum, F_struct_TP, H_OPSYS, Hist_data, IDhist, Jdate_end, Jdate_init, julday(), modelFileName, ModelPath, msgStr, num_struct_hist, numTPser, PORnumday, ProjName, Structure::S_nam, Scip(), SimAlt, TAB, UNIX, usrErr(), and usrErr0().
Referenced by ReadStructures().
01133 { 01134 char lline[2001], *line; 01135 char scenario[20]; 01136 int i, j, k; 01137 int lincnt; 01138 /* int IDhist[MAX_H_STRUCT]; */ 01139 char structName[20]; 01140 int yyyy, mm, dd; 01141 double Jdate_read; 01142 01143 usrErr0 ( "\tControl structures' TP concen. time series..."); 01144 01145 { if(H_OPSYS==UNIX) 01146 sprintf( modelFileName, "%s/%s/Data/%s.struct_TP", ModelPath, ProjName, filename ); 01147 else sprintf( modelFileName, "%s%s:Data:%s.struct_TP", ModelPath, ProjName, filename ); 01148 } 01149 01150 /* Open file with structure concentration data */ 01151 if ( ( F_struct_TP = fopen( modelFileName, "r" ) ) == NULL ) 01152 { 01153 printf( "Can't open %s file!\n", modelFileName ) ; 01154 exit(-1) ; 01155 } 01156 01157 fgets(lline, 2000, F_struct_TP); /* first header line with the alternative's name */ 01158 line=lline; 01159 sscanf(line, "%s",&scenario); 01160 if (strcmp(scenario,SimAlt) != 0) { 01161 sprintf(msgStr, "The scenario (%s) found in the %s file doesn't match the one (%s) you asked for in Driver.parm!", scenario, modelFileName, SimAlt); usrErr(msgStr); 01162 exit(-1); 01163 } 01164 fgets(lline, 2000, F_struct_TP); /* read 2'nd header line with column names */ 01165 line=lline; 01166 line = Scip( line, TAB ); 01167 line = Scip( line, TAB ); 01168 line = Scip( line, TAB ); 01169 01170 /* now we're past the three date columns, ready to read the variable names */ 01171 for ( j = 0; j < numTPser; j++ ) { /* loop through all the data columns */ 01172 IDhist[j] = -1; 01173 strcpy(structName,"NULL"); /* a string structName read previously is retained - this NULL assignment will take care of case 01174 where nothing was found/read in the time series file, and thus cause an error */ 01175 sscanf ( line,"%s\t",&structName); /* read the structure names in the header */ 01176 for ( i = 0; i < num_struct_hist+disAggNum; i++ ) { 01177 if (strcmp(Hist_data[i].S_nam , structName) == 0) { 01178 IDhist[j] = i; 01179 line = Scip( line, TAB ); 01180 } 01181 } 01182 if (IDhist[j] == -1 ) { printf( "variable name %s in %s not found in CanalData.structs. (if 'NULL', a variable in CanalData.structs defined as having a time series column was not found in %s)\n", structName, modelFileName, modelFileName); 01183 exit(-1); 01184 } 01185 } 01186 01187 lincnt = 0; /* input file record # starting at the point where the model reads values */ 01188 01189 while ( fgets(lline, 2000, F_struct_TP) != NULL && !feof( F_struct_TP ) ) 01190 { 01191 line = lline; 01192 sscanf( line, "%d %d %d",&yyyy,&mm,&dd); /* read the date of the current record */ 01193 01194 /* julian day, returns a double (args = mon, day, year, hours, minutes, seconds) */ 01195 Jdate_read = julday( mm,dd,yyyy,0,0,0.0 ); 01196 if ((lincnt == 0) && (Jdate_read > Jdate_init) ) { 01197 printf (" \n***Error\nStructure TP data (%s) init date > simulation start date\n", modelFileName); exit (-1); 01198 } 01199 if ((Jdate_read >= Jdate_init) && (Jdate_read <= Jdate_end)) 01200 { 01201 line = Scip( line, TAB ); 01202 line = Scip( line, TAB ); 01203 for ( j = 0; j < numTPser; j++ ) { /* loop through all the control structure columns in the input file */ 01204 line = Scip( line, TAB ); 01205 if (*line == TAB) Hist_data[IDhist[j]].arrayP[((int)(lincnt))] = 0; 01206 else sscanf( line, "%f", &Hist_data[IDhist[j]].arrayP[((int)(lincnt))] ); 01207 Hist_data[IDhist[j]].arrayP[((int)(lincnt))] *= 1.0E-6; /* data read in ug/L, convert to g/L=kg/m3 */ 01208 01209 } 01210 01211 lincnt++; /* increment the number of daily data records */ 01212 } 01213 01214 } /* end of reading TP conc data records */ 01215 01216 if (lincnt == 0 ) { 01217 printf (" \n***Error\nTP Time series data (%s) has date problem (0 records read)\n", modelFileName); exit (-1); 01218 } 01219 else if (lincnt != PORnumday ) { 01220 printf (" \n***Error\nTP Time series data (%s) has problem (%d records read, %d expected)\n", modelFileName, lincnt, PORnumday); exit (-1); 01221 } 01222 sprintf (msgStr, "done, found %d records.",lincnt); usrErr(msgStr); 01223 01224 fclose (F_struct_TP); 01225 } /* end of reading TP time series data (if needed) */
void ReadStructTS_PtSer | ( | char * | filename | ) |
Read time series data of TS (salt/tracer) concentration at water control structures.
v2.6 - made this a separate function instead of the old nested if - then statements
Definition at line 1234 of file WatMgmt.c.
References HistData::arrayS, disAggNum, F_struct_TS, H_OPSYS, Hist_data, IDhist, Jdate_end, Jdate_init, julday(), modelFileName, ModelPath, msgStr, num_struct_hist, numTSser, PORnumday, ProjName, Structure::S_nam, Scip(), SimAlt, TAB, UNIX, usrErr(), and usrErr0().
Referenced by ReadStructures().
01235 { 01236 char lline[2001], *line; 01237 char scenario[20]; 01238 int i, j, k; 01239 int lincnt; 01240 /* int IDhist[MAX_H_STRUCT]; */ 01241 char structName[20]; 01242 int yyyy, mm, dd; 01243 double Jdate_read; 01244 01245 usrErr0 ( "\tControl structures' Tracer concen. time series..."); 01246 01247 { if(H_OPSYS==UNIX) 01248 sprintf( modelFileName, "%s/%s/Data/%s.struct_TS", ModelPath, ProjName, filename ); 01249 else sprintf( modelFileName, "%s%s:Data:%s.struct_TS", ModelPath, ProjName, filename ); 01250 } 01251 01252 /* Open file with structure concentration data */ 01253 if ( ( F_struct_TS = fopen( modelFileName, "r" ) ) == NULL ) 01254 { 01255 printf( "Can't open %s file!\n", modelFileName ) ; 01256 exit(-1) ; 01257 } 01258 01259 fgets(lline, 2000, F_struct_TS); /* first header line with the alternative's name */ 01260 line=lline; 01261 sscanf(line, "%s",&scenario); 01262 if (strcmp(scenario,SimAlt) != 0) { 01263 sprintf(msgStr, "The scenario (%s) found in the %s file doesn't match the one (%s) you asked for in Driver.parm!", scenario, modelFileName, SimAlt); usrErr(msgStr); 01264 exit(-1); 01265 } 01266 fgets(lline, 2000, F_struct_TS); /* read 2'nd header line with column names */ 01267 line=lline; 01268 line = Scip( line, TAB ); 01269 line = Scip( line, TAB ); 01270 line = Scip( line, TAB ); 01271 01272 /* now we're past the three date columns, ready to read the variable names */ 01273 for ( j = 0; j < numTSser; j++ ) { /* loop through all the data columns */ 01274 IDhist[j] = -1; 01275 strcpy(structName,"NULL"); /* a string structName read previously is retained - this NULL assignment will take care of case 01276 where nothing was found/read in the time series file, and thus cause an error */ 01277 sscanf ( line,"%s\t",&structName); /* read the structure names in the header */ 01278 for ( i = 0; i < num_struct_hist+disAggNum; i++ ) { 01279 if (strcmp(Hist_data[i].S_nam , structName) == 0) { 01280 IDhist[j] = i; 01281 line = Scip( line, TAB ); 01282 } 01283 } 01284 if (IDhist[j] == -1 ) { printf( "variable name %s in %s not found in CanalData.structs. (if 'NULL', a variable in CanalData.structs defined as having a time series column was not found in %s)\n", structName, modelFileName, modelFileName); 01285 exit(-1); 01286 } 01287 } 01288 01289 lincnt = 0; /* input file record # starting at the point where the model reads values */ 01290 01291 while ( fgets(lline, 2000, F_struct_TS) != NULL && !feof( F_struct_TS ) ) 01292 { 01293 line = lline; 01294 sscanf( line, "%d %d %d",&yyyy,&mm,&dd); /* read the date of the current record */ 01295 01296 /* julian day, returns a double (args = mon, day, year, hours, minutes, seconds) */ 01297 Jdate_read = julday( mm,dd,yyyy,0,0,0.0 ); 01298 if ((lincnt == 0) && (Jdate_read > Jdate_init) ) { 01299 printf (" \n***Error\nStructure Tracer data (%s) init date > simulation start date\n", modelFileName); exit (-1); 01300 } 01301 if ((Jdate_read >= Jdate_init) && (Jdate_read <= Jdate_end)) 01302 { 01303 line = Scip( line, TAB ); 01304 line = Scip( line, TAB ); 01305 for ( j = 0; j < numTSser; j++ ) { /* loop through all the control structure columns in the input file */ 01306 line = Scip( line, TAB ); 01307 if (*line == TAB) Hist_data[IDhist[j]].arrayS[((int)(lincnt))] = 0; 01308 else sscanf( line, "%f", &Hist_data[IDhist[j]].arrayS[((int)(lincnt))] ); 01309 Hist_data[IDhist[j]].arrayS[((int)(lincnt))] *= 1.0; /* data read in g/L=kg/m3, no conversion*/ 01310 01311 } 01312 01313 lincnt++; /* increment the number of daily data records */ 01314 } 01315 01316 } /* end of reading tracer (salt) conc data records */ 01317 01318 if (lincnt == 0 ) { 01319 printf (" \n***Error\nTracer Time series data (%s) has date problem (0 records read)\n", modelFileName); exit (-1); 01320 } 01321 else if (lincnt != PORnumday ) { 01322 printf (" \n***Error\nTracer Time series data (%s) has problem (%d records read, %d expected)\n", modelFileName, lincnt, PORnumday); exit (-1); 01323 } 01324 sprintf (msgStr, "done, found %d records.",lincnt); usrErr(msgStr); 01325 01326 fclose (F_struct_TS); 01327 } /* end of function for reading tracer (salt) time series data (if needed) */
void Channel_configure | ( | float * | ElevMap, | |
struct Chan * | channel_first | |||
) |
Configure attributes of grid cells interacting with canal vectors.
Identifies the cells that are crossed by the canal, calculates the length of canal within each cell and marks the cells directly interacting with the canal. Store the pointers to the adjacent cell arrays.
ElevMap | SED_ELEV | |
channel_first | Pointer to first canal data structure |
Definition at line 1441 of file WatMgmt.c.
References Abs, ALL, Chan::area, C_F, C_Mark, CanalCellInteractDebug, cell, cell_last, Chan::cells, celWid, Chan_list, CHo, Chan::cond, EAST, Chan::elev_drop, Chan::elev_end, Chan::elev_slope, Chan::elev_start, getCanalElev(), GP_calibGWat, init_pvar(), LEFT, Chan::length, Chan::levee, MarkCell(), MINDEPTH, Chan::minVol, modelFileName, nalloc(), Cells::next_cell, Chan::next_in_list, Chan_segm::next_segm, NONE, num_cell, num_chan, Chan::num_of_cells, Chan::number, ON_MAP, OutputPath, ProjName, RIGHT, Chan::roil, Chan::roir, Round(), s0, s1, sec_per_day, Chan::seg_len, Chan::segments, SOUTH, Chan::SPG_flow_coef, STEP, Chan::SW_flow_coef, T, Chan::width, Chan_segm::x0, Chan_segm::x1, Chan_segm::y0, and Chan_segm::y1.
Referenced by Canal_Network_Init().
01442 { int i, j; /*coord. of current cell crossed by the canal */ 01443 int cellLoc, cellLoc_i, cellLoc_j; 01444 int HV, k, L_range, R_range; 01445 float T_length; /* length of a straight segment of a canal reach (m) */ 01446 float C_length; /* total length of all of the segments of a canal reach (m) */ 01447 float distTot; /* cumulative (along grid cells) distance along a canal reach, from the starting point (m) */ 01448 float A1, B1, A2, B2; /* parameters of the canal equation */ 01449 float L, p_middle, m, i45, x, y, x1, y1, length, RoIL, RoIR; 01450 float cell_step = 1.0; 01451 01452 float a0, b0, a1, b1; 01453 int c_num, z; 01454 struct Cells *cell; /* addresses for adjacent cell structures */ 01455 struct Chan *channel; 01456 struct Chan_segm *Segm; 01457 01458 int numChek; /* placeholder for debugging cell elev along canals */ 01459 01460 01461 int *marked; /* a "temporary" fix used to determine if a cell belonging to a canal has already been marked */ 01462 marked = (int *) nalloc(sizeof(int)*(s0+2)*(s1+2),"marked"); 01463 init_pvar(marked,NULL,'d',0); 01464 01465 /* Open file to print canal-cell interaction info to */ 01466 sprintf( modelFileName, "%s/%s/Output/Debug/CanalCells_interaction.txt", OutputPath, ProjName ); 01467 if ( ( CanalCellInteractDebug = fopen( modelFileName, "w" ) ) == NULL ) 01468 { 01469 printf( "Can't open %s file!\n", modelFileName ) ; 01470 exit(-1) ; 01471 } 01472 01473 /* allocate memory for array of pointers to Chan structs */ 01474 if ( (Chan_list = 01475 (struct Chan **) malloc( (size_t) sizeof( struct Chan *) * num_chan)) == NULL ) 01476 { 01477 printf( "Failed to allocate memory for next canal (%d)\n ", channel->number ) ; 01478 exit( -2 ) ; 01479 }; 01480 01481 /* allocate memory for first cell structure */ 01482 if ( (cell = (struct Cells *) malloc( (size_t) sizeof( struct Cells ))) == NULL ) 01483 { 01484 printf( "Failed to allocate memory for cell structure\n " ) ; 01485 exit( -2 ) ; 01486 } 01487 01488 /* store the pointer to first cell in the array */ 01489 channel = channel_first; 01490 01491 /* loop over all the canal reaches (== channel, defined as an individual canal reach with an ID number) */ 01492 while (channel != NULL) 01493 { 01494 Segm = channel->segments; 01495 c_num = channel->number; 01496 z = channel->levee; 01497 RoIL = channel->roil; 01498 RoIR = channel->roir; 01499 01500 Chan_list[c_num - CHo] = channel; 01501 01502 channel->cells = cell; 01503 distTot = 0; 01504 C_length = 0; 01505 C_Mark = 0; 01506 01507 /* a negative-width canal is skipped, going to SKIPCHAN line that is located (almost) at the end of this function */ 01508 if (channel->width < 0) goto SKIPCHAN; 01509 01510 fprintf ( CanalCellInteractDebug, "N = %d levee = %d\n", c_num, z ); 01511 01512 /* get the elevation at the starting reach segment (may be up or down stream) of the canal */ 01513 cellLoc_i=(int)(Segm->x0+1); 01514 cellLoc_j=(int)(Segm->y0+1); 01515 cellLoc = T(cellLoc_i,cellLoc_j ); 01516 Chan_list[c_num - CHo]->elev_start = ElevMap[cellLoc]; 01517 if ( !ON_MAP[cellLoc] ) { 01518 printf( "Starting elevation of Reach %d is out of the active domain. Fix the reach location.\n",c_num); 01519 exit(-2); 01520 } 01521 fprintf ( CanalCellInteractDebug, " %d, %d, StartElev = %f\n", cellLoc_i,cellLoc_j, Chan_list[c_num - CHo]->elev_start ); 01522 01523 01524 while (Segm != NULL) /* loop through canal reach segments */ 01525 { 01526 a0 = Segm->x0; 01527 b0 = Segm->y0; 01528 a1 = Segm->x1; 01529 b1 = Segm->y1; 01530 01531 x1 = 0; y1 = 0; 01532 01533 T_length = sqrt( (b1 - b0)*(b1 - b0) + (a1 - a0)*(a1 - a0) ); /* total reach segment length */ 01534 C_length += T_length; /* total canal reach length */ 01535 01536 if ( a1 != a0 && b1 != b0 ) 01537 { 01538 A1 = (b1 - b0)/(a1 - a0); /* define the equation: y = A1x + B1 */ 01539 B1 = b0 - A1*a0; 01540 A2 = 1/A1; B2 = - B1/A1; /* define the equation: x = A2y + B2 */ 01541 } 01542 01543 x = a0; y = b0; 01544 i = Round (x); j = Round (y); 01545 01546 /* loop along cells of the canal reach segment */ 01547 while ( x1 != a1 || y1 != b1 ) 01548 { 01549 if ( a1 == a0 ) /* if goes straight horizontally */ 01550 { x1 = a0; 01551 y1 = (j == Round (b1) ) ? b1 : j + STEP(b1 - b0)*cell_step; 01552 length = y1 - y; 01553 } 01554 01555 else if ( b1 == b0 ) /* if goes straight vertically */ 01556 { x1 = (i == Round (a1) ) ? a1 : i + STEP(a1 - a0)*cell_step; 01557 y1 = b0; 01558 length = x1 - x; 01559 } 01560 01561 else if ( i == Round (a1) && j == Round (b1) ) 01562 { x1 = a1; y1 = b1; /* if last cell */ 01563 length = T_length * (y1 - y)/(b1 - b0); 01564 C_Mark = 0; 01565 } 01566 01567 else 01568 { y1 = A1*(i + STEP(a1 - a0)*cell_step) + B1; length = T_length * (y1 - y)/(b1 - b0); 01569 x1 = A2*(j + STEP(b1 - b0)*cell_step) + B2; L = T_length * (x1 - x)/(a1 - a0); 01570 01571 if ( length < L ) /* define the end coordinates and length */ 01572 x1 = i + STEP(a1 - a0)*cell_step; /* (the next coordinate is the closest)*/ 01573 else 01574 { y1 = j + STEP(b1 - b0)*cell_step; length = L; 01575 } 01576 } 01577 01578 if ( Abs (a1 - a0) < Abs (b1 - b0) ) 01579 /* define the direction of canal reach and */ 01580 { p_middle = (x1 + x)/2; /* calculate the middle point on the canal reach in cell */ 01581 m = i + cell_step/2; /* m - the center of the cell */ 01582 HV = 1; /* to indicate that the canal reach goes closer to the horizontal direction */ 01583 } 01584 else 01585 { p_middle = (y1 + y)/2; 01586 m = j + cell_step/2; 01587 HV = 0; 01588 } 01589 01590 distTot = distTot + length*celWid; /* cumulative (along grid cells) distance along a canal reach, from the starting point (m) */ 01591 01592 /* mark cells depending on where the center of canal reach is rel. to the cell center*/ 01593 01594 if ( Round (a1) == Round (a0) ) /* if the canal reach goes within the range of one */ 01595 /*cell horizontally, mark the two vertical cells */ 01596 { if (b0 < b1) /* if going from left to right */ 01597 { /* if the middle point of the canal reach is lower than the */ 01598 /* cell center, mark the cell as LEFT else as RIGHT */ 01599 if ( p_middle > m ) 01600 { cell = MarkCell ( i, j, LEFT, length, cell, EAST, z, i, j, c_num, marked, distTot ); 01601 L_range = (int)(RoIL - 1); R_range = (int)RoIR; 01602 } 01603 else 01604 { cell = MarkCell ( i, j, RIGHT, length, cell, EAST, z, i - 1, j, c_num, marked, distTot ); 01605 L_range = (int) RoIL; R_range = (int)(RoIR - 1); 01606 } 01607 for ( k = 0; k < L_range; k++ ) 01608 cell = MarkCell ( i - k - 1, j, LEFT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01609 for ( k = 0; k < R_range; k++ ) 01610 cell = MarkCell ( i + k + 1, j, RIGHT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01611 } 01612 else /* vice versa if we go from right to left */ 01613 { /* if the middle point of the canal reach is lower than the */ 01614 /* cell center, mark the cell as RIGHT else as LEFT */ 01615 if ( p_middle > m ) 01616 { cell = MarkCell ( i, j, RIGHT, length, cell, EAST, z, i, j, c_num, marked, distTot ); 01617 L_range = (int)RoIL; R_range = (int)(RoIR - 1); 01618 } 01619 else 01620 { cell = MarkCell ( i, j, LEFT, length, cell, EAST, z, i - 1, j, c_num, marked, distTot ); 01621 L_range = (int)(RoIL - 1); R_range = (int)RoIR; 01622 } 01623 for ( k = 0; k < L_range; k++ ) 01624 cell = MarkCell ( i + k + 1, j, LEFT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01625 for ( k = 0; k < R_range; k++ ) 01626 cell = MarkCell ( i - k - 1, j, RIGHT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01627 } 01628 } 01629 else if ( Round (b1) == Round (b0) ) /* if the canal reach goes vertically */ 01630 { if (a0 < a1) /* if going from top to bottom */ 01631 { /* if the middle point of the canal reach is further to the right than the */ 01632 /* cell center, mark the cell as RIGHT else as LEFT */ 01633 if ( p_middle > m ) 01634 { cell = MarkCell ( i, j, RIGHT, length, cell, SOUTH, z, i, j, c_num, marked, distTot ); 01635 L_range = (int)RoIL; R_range = (int)(RoIR -1); 01636 } 01637 else 01638 { cell = MarkCell ( i, j, LEFT, length, cell, SOUTH, z, i, j - 1, c_num, marked, distTot ); 01639 L_range = (int)(RoIL - 1); R_range = (int)RoIR; 01640 } 01641 for ( k = 0; k < L_range; k++ ) 01642 cell = MarkCell ( i, j + k + 1, LEFT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01643 for ( k = 0; k < R_range; k++ ) 01644 cell = MarkCell ( i, j - k - 1, RIGHT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01645 } 01646 else /* vice versa if we go from bottom to top */ 01647 { /* if the middle point of the canal reach is further to the left than the */ 01648 /* cell center, mark the cell as LEFT else as RIGHT */ 01649 if ( p_middle > m ) 01650 { cell = MarkCell ( i, j, LEFT, length, cell, SOUTH, z, i, j, c_num, marked, distTot ); 01651 L_range = (int)(RoIL - 1); R_range = (int)RoIR; 01652 } 01653 else 01654 { cell = MarkCell ( i, j, RIGHT, length, cell, SOUTH, z, i, j - 1, c_num, marked, distTot ); 01655 L_range = (int)RoIL; R_range = (int)(RoIR - 1); 01656 } 01657 for ( k = 0; k < L_range; k++ ) 01658 cell = MarkCell ( i, j - k - 1, LEFT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01659 for ( k = 0; k < R_range; k++ ) 01660 cell = MarkCell ( i, j + k + 1, RIGHT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01661 } 01662 } 01663 else 01664 /* if the canal reach crosses more than one cell (in both dimensions), mark diagonal cells */ 01665 { if ( A1>0 ) /* this is an extremely confusing check, but in this */ 01666 i45 = ( HV ) ? p_middle - m : m - p_middle; /*form it seems to be working OK */ 01667 else 01668 i45 = p_middle - m; 01669 /* b0>b1, a0>a1 \/ b0<b1, a0>a1 */ 01670 /* b0>b1, a0<a1 /\ b0<b1, a0<a1 */ 01671 if ( b0 < b1 ) 01672 { if ( a0 < a1 ) /* when a0<a1 the canal reach goes down in the \ direction */ 01673 { if ( i45 > 0 ) 01674 { cell = MarkCell ( i, j, LEFT, length, cell, EAST, z, i, j, c_num, marked, distTot ); 01675 cell = MarkCell ( i + 1, j - 1, RIGHT, length, cell, SOUTH, z, i + 1, j - 1, c_num, marked, distTot ); 01676 } 01677 else 01678 { cell = MarkCell ( i, j, RIGHT, length, cell, SOUTH, z, i, j, c_num, marked, distTot ); 01679 cell = MarkCell ( i - 1, j + 1, LEFT, length, cell, EAST, z, i - 1, j + 1, c_num, marked, distTot ); 01680 } 01681 for ( k = 0; k < RoIR-1; k++ ) 01682 cell = MarkCell ( i + k + 1, j - k - 1, RIGHT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01683 for ( k = 0; k < RoIL-1; k++ ) 01684 cell = MarkCell ( i - k - 1, j + k + 1, LEFT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01685 } 01686 else /* in this case the canal reach goes up in the / direction */ 01687 { if ( i45 > 0 ) 01688 { cell = MarkCell ( i, j, LEFT, length, cell, NONE, z, i, j, c_num, marked, distTot ); 01689 cell = MarkCell ( i + 1, j + 1, RIGHT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01690 } 01691 else 01692 { cell = MarkCell ( i, j, RIGHT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01693 cell = MarkCell ( i - 1, j - 1, LEFT, length, cell, NONE, z, i - 1, j - 1, c_num, marked, distTot ); 01694 } 01695 for ( k = 0; k < RoIR-1; k++ ) 01696 cell = MarkCell ( i + k + 1, j + k + 1, RIGHT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01697 for ( k = 0; k < RoIL-1; k++ ) 01698 cell = MarkCell ( i - k - 1, j - k - 1, LEFT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01699 } 01700 } 01701 /* if going in the opposite direction change left and right */ 01702 else 01703 { if ( a0 > a1 ) /* when a0<a1 the canal reach goes up in the \ direction */ 01704 { if ( i45 < 0 ) 01705 { cell = MarkCell ( i, j, LEFT, length, cell, SOUTH, z, i, j, c_num, marked, distTot ); 01706 cell = MarkCell ( i - 1, j + 1, RIGHT, length, cell, EAST, z, i - 1, j + 1, c_num, marked, distTot ); 01707 } 01708 else 01709 { cell = MarkCell ( i, j, RIGHT, length, cell, EAST, z, i, j, c_num, marked, distTot ); 01710 cell = MarkCell ( i + 1, j - 1, LEFT, length, cell, SOUTH, z, i + 1, j - 1, c_num, marked, distTot ); 01711 } 01712 01713 for ( k = 0; k < RoIL-1; k++ ) 01714 cell = MarkCell ( i + k + 1, j - k - 1, LEFT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01715 for ( k = 0; k < RoIR-1; k++ ) 01716 cell = MarkCell ( i - k - 1, j + k + 1, RIGHT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01717 } 01718 else /* in this case the canal reach goes down in the / direction */ 01719 { if ( i45 < 0 ) 01720 { cell = MarkCell ( i, j, LEFT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01721 cell = MarkCell ( i - 1, j - 1, RIGHT, length, cell, NONE, z, i - 1, j - 1, c_num, marked, distTot ); 01722 } 01723 else 01724 { cell = MarkCell ( i, j, RIGHT, length, cell, NONE, z, i, j, c_num, marked, distTot ); 01725 cell = MarkCell ( i + 1, j + 1, LEFT, length, cell, ALL, z, i + 1, j + 1, c_num, marked, distTot ); 01726 } 01727 01728 for ( k = 0; k < (int)(RoIL-1); k++ ) 01729 cell = MarkCell ( i + k + 1, j + k + 1, LEFT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01730 for ( k = 0; k < (int)(RoIR-1); k++ ) 01731 cell = MarkCell ( i - k - 1, j - k - 1, RIGHT, length, cell, ALL, z, i, j, c_num, marked, distTot ); 01732 } 01733 } 01734 } 01735 01736 num_cell++; /*at this point we're counting the cells only once thinking that all 01737 cells have the same length of interaction irrelevant of their distance from the canal 01738 and that this length will be equal to the canal length / number of cells it crosses */ 01739 01740 /* prepare for the next step in cycle */ 01741 x = x1; y = y1; 01742 i = Round (x); if ( a1 < a0 && i == x ) i--; /* if we're going upwards, we */ 01743 /* need to change the rule of Rounding so that we move ahead along cells */ 01744 j = Round (y); if ( b1 < b0 && j == y ) j--; 01745 C_Mark = 1; 01746 01747 01748 } /* end loop along cells of the canal reach segment */ 01749 01750 Segm = Segm->next_segm; 01751 } /* end loop over all reach segments of a canal */ 01752 01753 /* get the elevation at the ending reach segment (may be up or down stream) of the canal */ 01754 cellLoc_i=(int)(a1+1); 01755 cellLoc_j=(int)(b1+1); 01756 cellLoc = T(cellLoc_i,cellLoc_j ); 01757 Chan_list[c_num - CHo]->elev_end = ElevMap[cellLoc]; 01758 01759 Chan_list[c_num - CHo]->num_of_cells = num_cell; 01760 num_cell = 0; 01761 /* store the canal attributes of: 01762 length of entire canal, 01763 area of entire canal, 01764 minimum volume allowed in canal, 01765 avg length of cell along reach segment, 01766 overland flow coefficient (not incl. dynamic manning's n, C_F is for sensitivity experiments only (normally=1) ), 01767 seepage flow coefficient (including GP_calibGWat groundwater flow calibration coef), 01768 land surface elevation difference between starting and ending points of canal 01769 slope of the elevation gradient from start to end points */ 01770 Chan_list[c_num - CHo]->length = C_length*celWid; 01771 Chan_list[c_num - CHo]->area = Chan_list[c_num - CHo]->width*Chan_list[c_num - CHo]->length; 01772 Chan_list[c_num - CHo]->minVol = Chan_list[c_num - CHo]->area*MINDEPTH; 01773 Chan_list[c_num - CHo]->seg_len = Chan_list[c_num - CHo]->length/Chan_list[c_num - CHo]->num_of_cells; 01774 Chan_list[c_num - CHo]->SW_flow_coef = sqrt(Chan_list[c_num - CHo]->seg_len) * sec_per_day * C_F; 01775 Chan_list[c_num - CHo]->SPG_flow_coef = Chan_list[c_num - CHo]->cond * GP_calibGWat; 01776 Chan_list[c_num - CHo]->elev_drop = Chan_list[c_num - CHo]->elev_start - Chan_list[c_num - CHo]->elev_end; 01777 Chan_list[c_num - CHo]->elev_slope = Chan_list[c_num - CHo]->elev_drop / Chan_list[c_num - CHo]->length ; /* v2.5 calculated slope */ 01778 01779 if ( !ON_MAP[cellLoc] ) { 01780 printf( "Ending elevation of Reach %d is out of the active domain. Fix the reach location.\n",c_num); 01781 exit(-2); 01782 } 01783 fprintf ( CanalCellInteractDebug, " %d, %d, EndingElev = %f, ElevSlope= %f, ReachLength= %f\n", cellLoc_i,cellLoc_j, 01784 Chan_list[c_num - CHo]->elev_end, Chan_list[c_num - CHo]->elev_slope, Chan_list[c_num - CHo]->length ); 01785 01786 getCanalElev(c_num - CHo); /* v2.5 */ 01787 01788 SKIPCHAN: /* a single goto comes here, skipping a canal with negative width */ 01789 channel = channel->next_in_list; 01790 01791 cell_last->next_cell = NULL; /* close the cell list */ 01792 01793 } /* end loop loop over all the canal reaches */ 01794 01795 fclose ( CanalCellInteractDebug ); 01796 01797 return; 01798 }
void getCanalElev | ( | int | chan_n | ) |
Assign elevation to canal using slope & distance from start point
.
This function does two things:
1. For each grid cell along a canal, we determine the elevation (relative to model base datum) of the top of the canal bank, using the slope of the canal and the distance from the beginning point of the canal. (function new in v2.5)
2. Calculate the mean elevation for a reach.
chan_n | Canal reach number (adjusted for the beginning ID number) |
Definition at line 1812 of file WatMgmt.c.
References CanalCellInteractDebug, cell, Chan::cells, Chan_list, CHo, Chan::elev_avg, Chan::elev_slope, Chan::elev_start, Exit(), Cells::next_cell, Cells::reachDistDown, Cells::reachElev, T, Cells::x, and Cells::y.
Referenced by Channel_configure().
01813 { 01814 int i, celcount=0; 01815 Chan_list[chan_n]->elev_avg = 0.0 ; /* v2.8 calculating an avg elevation for reach */ 01816 /* cycle along canal cells */ 01817 cell = Chan_list[chan_n]->cells; 01818 i = T(cell->x, cell->y); 01819 01820 while ( cell != NULL ) 01821 { 01822 celcount++; 01823 cell->reachElev = Chan_list[chan_n]->elev_start - cell->reachDistDown * Chan_list[chan_n]->elev_slope; 01824 Chan_list[chan_n]->elev_avg = Chan_list[chan_n]->elev_avg + cell->reachElev; 01825 fprintf ( CanalCellInteractDebug, " Reach= %d, Cell (%d, %d), ReachElev= %f\n", chan_n+CHo, cell->x, cell->y, cell->reachElev ); 01826 cell = cell->next_cell; 01827 } 01828 if (celcount == 0) { printf(" Error in getting cells along canal for elevation avg\n"); Exit(-1); } 01829 Chan_list[chan_n]->elev_avg = Chan_list[chan_n]->elev_avg/celcount; 01830 }
void FluxChannel | ( | int | chan_n, | |
float * | SWH, | |||
float * | ElevMap, | |||
float * | MC, | |||
float * | GWH, | |||
float * | poros, | |||
float * | GWcond, | |||
double * | NA, | |||
double * | PA, | |||
double * | SA, | |||
double * | GNA, | |||
double * | GPA, | |||
double * | GSA, | |||
float * | Unsat, | |||
float * | sp_yield | |||
) |
Runs the iterative algorithm over the network of canals.
The iterative relaxation routine calculates the new head in the canal and the water exchange with the adjacent cells, including constituent fluxes.
chan_n | Canal ID number | |
SWH | SURFACE_WAT | |
ElevMap | SED_ELEV | |
MC | HYD_MANNINGS_N | |
GWH | SAT_WATER | |
poros | HP_HYD_POROSITY | |
GWcond | HYD_RCCONDUCT | |
NA | DINdummy | |
PA | TP_SF_WT | |
SA | SALT_SURF_WT | |
GNA | DINdummy | |
GPA | TP_SED_WT | |
GSA | SALT_SED_WT | |
Unsat | UNSAT_WATER | |
sp_yield | HP_HYD_SPEC_YIELD |
Definition at line 1935 of file WatMgmt.c.
References Abs, Chan::area, Chan::basin, basn, basn_list, Structure::canal_fr, Structure::canal_to, canDebugFile, cell, CELL_SIZE, Chan::cells, Chan_list, CHANNEL_MAX_ITER, CHo, debug, Chan::depth, dynERRORnum, Chan::edgeMann, F_ERROR, f_Ground(), f_Manning(), basndef::family, Chan::family, Structure::flow, GP_DetentZ, GP_MinCheck, HAB, Cells::ind, Max, Min, MINDEPTH, Chan::minVol, msgStr, Chan::N, Cells::next_cell, Structure::next_in_list, Chan::number, ON_MAP, Chan::P, P, Chan::P_con, P_IN_GW, P_IN_OVL, P_IN_SPG, P_OUT_GW, P_OUT_OVL, P_OUT_SPG, ramp, Cells::reachElev, Chan::S, Chan::S_con, S_IN_GW, S_IN_OVL, S_IN_SPG, S_OUT_GW, S_OUT_OVL, S_OUT_SPG, Chan::seg_len, sgn, SimTime, Chan::SPG_flow_coef, struct_first, structs, T, simTime::TIME, True, VOL_IN_GW, VOL_IN_OVL, VOL_IN_SPG, VOL_OUT_GW, VOL_OUT_OVL, VOL_OUT_SPG, Chan::wat_depth, Chan::width, WriteMsg(), Cells::x, and Cells::y.
Referenced by Run_Canal_Network().
01939 { 01940 01972 int converged = 0; 01973 float error = 1.0; 01974 float prev_error = 1.0; 01975 int iter = 0; 01976 int max_iter = CHANNEL_MAX_ITER; 01977 float init_factor = 0.5; 01978 float factor = init_factor; 01979 01980 int i; 01981 int attempt=0; 01982 double CanWatDep = Chan_list[chan_n]->wat_depth; 01983 double T_flux_S, T_flux_G, T_flux_L; 01984 double fluxO, fluxCk; 01985 double fluxS, fluxG, fluxL; 01986 double SW_coef, SPG_coef, GW_coef; 01987 double N_fl, P_fl, S_fl; 01988 /* double SNfl, GNfl, SPfl, GPfl, SSfl, GSfl; UNUSED */ 01989 double I_Length; 01990 double seg_area; 01991 double MIN_VOL; 01992 double GW_head; 01993 double h_GWflow, h_SPflow; 01994 double dh; 01995 double Qin, Qout, Qout1; 01996 double SWater; 01997 double tot_head; 01998 double CH_vol; 01999 double CH_vol_R; 02000 double CH_bottElev; 02001 double H_rad_ch, H_rad_cell; 02002 double can_cell_M, can_cell_A; 02003 float errorConv; 02004 02005 /* UNUSED below, unimplemented gwater/sfwater integration vars */ 02006 int equilib, revers=1; 02007 float H_pot_don, H_pot_rec; 02008 02009 float fluxTOunsat_don, fluxHoriz; /* vertical and horiz components of the calculated total groundwater Flux */ 02010 float UnsatZ_don, UnsatCap_don, UnsatPot_don, Sat_vs_unsat; /* unsaturated zone capacities, potentials, in the donor cell */ 02011 float UnsatZ_rec, UnsatCap_rec, UnsatPot_rec; /* unsaturated zone capacities, potentials, in the recipient cell */ 02012 float sfTOsat_don, unsatTOsat_don, unsatTOsat_rec, satTOsf_rec, horizTOsat_rec; /* fluxes for vertical integration */ 02013 02014 float sedwat_don, sedwat_rec; 02015 float sed_stuf1fl_rec, sed_stuf2fl_rec, sed_stuf3fl_rec; /* vertical flux of solutes */ 02016 float sf_stuf1fl_don, sf_stuf2fl_don, sf_stuf3fl_don; /* vertical flux of solutes */ 02017 float sed_stuf1fl_horz, sed_stuf2fl_horz, sed_stuf3fl_horz; /* horiz flux of solutes */ 02018 /* UNUSED above, unimplemented gwater/sfwater integration vars */ 02019 02020 02021 /* look at all the structures connected to the canal and add/subtract flow from/to them */ 02022 Qin = 0; Qout = 0; 02023 structs = struct_first; 02024 while ( structs != NULL ) 02025 { 02026 02027 if ( structs->canal_fr == chan_n+CHo ) 02028 { 02029 if ( structs->flow > 0 ) Qout += structs->flow; 02030 else Qin -= structs->flow; 02031 } 02032 if ( structs->canal_to == chan_n+CHo ) 02033 { 02034 if ( structs->flow > 0 ) Qin += structs->flow; 02035 else Qout -= structs->flow; 02036 } 02037 02038 structs = structs->next_in_list; 02039 } 02040 02041 CH_vol_R = Chan_list[chan_n]->area * CanWatDep; /* total canal volume prior to relaxation procedure */ 02042 MIN_VOL = Chan_list[chan_n]->minVol; /* minimum canal volume allowed */ 02043 SPG_coef = Chan_list[chan_n]->SPG_flow_coef; /* GP_calibGWat already in this */ 02044 02045 I_Length = Chan_list[chan_n]->seg_len; /* avg length of cell along reach segment */ 02046 seg_area = I_Length * Chan_list[chan_n]->width; /* avg area of reach segment */ 02047 can_cell_M = Chan_list[chan_n]->area*CELL_SIZE; /* used in reducing excess flows between canal<->cell */ 02048 can_cell_A = Chan_list[chan_n]->area+CELL_SIZE; /* used in reducing excess flows between canal<->cell */ 02049 02050 02051 02052 /* start relaxation procedure */ 02053 do 02054 { 02055 if ( Abs( error) < F_ERROR ) 02056 { 02057 converged = 1; /* when we've converged, we'll go through the cell list one more time w/o modifying the depth estimate */ 02058 /* occasionally, we get a modified total flux value, and diff error, a second time with the same depth estimate! */ 02059 errorConv=error; 02060 factor = 0; 02061 } 02062 else if ( iter >= (max_iter-1) ) 02063 { 02064 if (attempt == 4) { 02065 converged = 1; /* haven't actually converged, but stop now */ 02066 sprintf(msgStr,"Day %6.1f: ERROR - couldn't converge on Canal %d, HALTING the iterative relaxation after 4 tries, error = %f.", 02067 SimTime.TIME, Chan_list[chan_n]->number, error); 02068 WriteMsg( msgStr,True ); dynERRORnum++; 02069 } 02070 else { 02071 if (debug > 3) { sprintf(msgStr,"Day %6.1f: Warning - couldn't converge on Canal %d, redoing the iterative relaxation, error = %f.", 02072 SimTime.TIME, Chan_list[chan_n]->number, error); 02073 WriteMsg( msgStr,True ); } 02074 02075 attempt++; /* the attempt counter increment */ 02076 iter = 0; /* reset iterations to 0, and double factor & max # iterations on first try */ 02077 if (attempt == 1) { factor = init_factor*2.0; max_iter = CHANNEL_MAX_ITER * 2; } 02078 else if (attempt == 2) { factor = init_factor*0.5; max_iter = CHANNEL_MAX_ITER * 2; } 02079 else if (attempt == 3) { factor = init_factor*4.0; max_iter = CHANNEL_MAX_ITER * 4; } 02080 else if (attempt == 4) { factor = init_factor*0.05; max_iter = CHANNEL_MAX_ITER * 4; } 02081 } 02082 } 02083 02084 else 02085 { 02086 /* if error changed sign, we have overshot the target, therefore reverse direction */ 02087 if (error * prev_error < 0 && iter != 1) 02088 factor = - sgn(error) * Abs( factor ) * 0.5; /* and reduce the step */ 02089 02090 /* if error contiues to grow after first iter.(#0), reverse direction */ 02091 if (iter == 1 && error > 0) factor = - factor; 02092 02093 } 02094 02095 if (iter != 0 && !converged ) 02096 { 02097 CanWatDep += factor; 02098 prev_error = error; 02099 if ( CanWatDep < MINDEPTH ) 02100 { 02101 if (debug > 3) { sprintf(msgStr,"Day %6.1f: Warning - estimate is below minimum depth, revising estimate. (Canal %d, depth %f)", 02102 SimTime.TIME, Chan_list[chan_n]->number,CanWatDep); 02103 WriteMsg( msgStr,True ); } 02104 02105 CanWatDep = MINDEPTH; 02106 /* converged = 1; */ 02107 factor = -factor*0.1; /* reverse the direction and decrease for next estimate*/ 02108 } 02109 } 02110 02111 T_flux_G = T_flux_S = T_flux_L = 0.0; /* at each convergence iter, set the sum flows to 0 */ 02112 CH_vol = Chan_list[chan_n]->area * CanWatDep; /* volume of canal at the estimated water depth */ 02113 02114 /* cycle along canal cells */ 02115 cell = Chan_list[chan_n]->cells; 02116 02117 while ( cell != NULL ) 02118 { 02119 i = T(cell->x, cell->y); 02120 if ( !ON_MAP[i] ) /* check that cell is ON_MAP, else we do nothing */ 02121 /* return to beginning of do loop */ 02122 { cell = cell->next_cell; continue; 02123 } 02124 if (basn[i] == 0) { 02125 sprintf(msgStr,"ERROR - Cell (%d, %d) is out-of-system.", cell->x, cell->y); 02126 WriteMsg( msgStr,True ); dynERRORnum++; } 02127 02128 fluxS = 0.; fluxG = 0.; fluxL = 0.; /* overland, subsurface, and seepage cell-canal fluxes set to 0 */ 02129 /* v2.5 In the case of some canal reaches, there is a lip or berm, and often associated vegetation, that is 02130 along the edge of a canal, decreasing flow rates between canal & marsh. If user provides a non-zero roughness 02131 parameter in the CanalData.chan input file, the the mean roughness of this berm and the cell is used for 02132 surface exchanges */ 02133 SW_coef = ( MC[i] == 0.0 ) ? 0 : Chan_list[chan_n]->SW_flow_coef / ( (Chan_list[chan_n]->edgeMann > 0.0) ? (MC[i] + Chan_list[chan_n]->edgeMann)/2 : MC[i] ); 02134 GW_coef = GWcond[i] * poros[HAB[i]]; 02135 SWater = SWH[i]; 02136 02137 if (debug>0 && (SWater < -GP_MinCheck) ) { 02138 sprintf(msgStr,"Day %6.1f: capacityERR - neg sfwater along canal %d, candepth %f, cell (%d, %d), celldepth %f", 02139 SimTime.TIME,Chan_list[chan_n]->number,CanWatDep, cell->x, cell->y, SWater); 02140 WriteMsg( msgStr,True ); dynERRORnum++; } 02141 02142 GW_head = Min( GWH[i]/poros[HAB[i]], ElevMap[i]); /* v2.8, eqn modified */ 02143 tot_head = ramp(SWater) + GW_head; /* v2.8, eqn modified */ 02144 CH_bottElev = cell->reachElev - Chan_list[chan_n]->depth; /* elev of bottom of canal at cell location (v2.5+: this is from fixed vector slope instead of actual grid cell elev) */ 02145 02146 dh = ( CH_bottElev + CanWatDep ) - tot_head; 02147 02148 /* hydraulic radius of canal for overland flow out of canal */ 02149 H_rad_ch = Max ( ( seg_area * ramp(CanWatDep - Chan_list[chan_n]->depth) + 02150 SWater * (CELL_SIZE-seg_area) ) / CELL_SIZE, 0.0); 02151 /* hydraulic radius of cell for overland flow into canal (same eqn right now) */ 02152 H_rad_cell = Max ( ( seg_area * ramp(CanWatDep - Chan_list[chan_n]->depth) + 02153 SWater * (CELL_SIZE-seg_area) ) / CELL_SIZE, 0.0); 02154 02155 /* determine the heights of the water cross sections associated with the subsurf and seep flows */ 02156 if (dh > 0.0) { /* from canal */ 02157 h_GWflow = Min(Chan_list[chan_n]->depth, CanWatDep ); 02158 h_SPflow = Max(CH_bottElev + CanWatDep - ElevMap[i], 0.0); 02159 } 02160 else if (dh < 0.0) { /* from cell */ 02161 h_GWflow = Max(GW_head-CH_bottElev, 0.0); 02162 h_SPflow = Max(tot_head-ElevMap[i], 0.0); 02163 } 02164 else { 02165 h_GWflow = 0.0; 02166 h_SPflow = 0.0; 02167 } 02168 02169 02170 02171 switch( Chan_list[chan_n]->levee ) 02172 { 02173 02174 case 2: /* if levees are on both sides of the canal */ 02175 /*seepage and subsurface flow on both sides */ 02176 fluxL = (h_SPflow > 0.0) ? (f_Ground ( dh, h_SPflow, SPG_coef, I_Length) ) : (0.0); 02177 fluxG = (h_GWflow > 0.0) ? (f_Ground ( dh, h_GWflow, GW_coef, I_Length) ) : (0.0); 02178 break; 02179 case 0: /* if there are no levees */ 02180 /*overland flow either side */ 02181 if ( dh > 0 ) { 02182 /* flux from canal to cell */ 02183 fluxS = f_Manning ( dh, H_rad_ch, SW_coef); 02184 } 02185 else if (SWater>GP_DetentZ) { 02186 fluxS = f_Manning ( dh, H_rad_cell, SW_coef) ; 02187 if (-fluxS > (SWater-GP_DetentZ) *CELL_SIZE ) 02188 fluxS = -(SWater-GP_DetentZ)*CELL_SIZE; 02189 } 02190 02191 /* subsurface groundwater flow both sides */ 02192 fluxG = (h_GWflow > 0.0) ? (f_Ground ( dh, h_GWflow, GW_coef, I_Length) ) : (0.0); 02193 break; 02194 case 1: /* if levee is on the left */ 02195 if ( cell->ind < 0 ) 02196 { /*overland flow */ 02197 if ( dh > 0 ) { 02198 /* flux from canal to cell */ 02199 fluxS = f_Manning ( dh, H_rad_ch, SW_coef); 02200 } 02201 else if (SWater>GP_DetentZ) { 02202 fluxS = f_Manning ( dh, H_rad_cell, SW_coef) ; 02203 if (-fluxS > (SWater-GP_DetentZ) *CELL_SIZE ) 02204 fluxS = -(SWater-GP_DetentZ)*CELL_SIZE; 02205 } 02206 02207 } 02208 else 02209 /*seepage on the levee side */ 02210 fluxL = (h_SPflow > 0.0) ? (f_Ground ( dh, h_SPflow, SPG_coef, I_Length) ) : (0.0); 02211 02212 /* subsurface groundwater flow both sides */ 02213 fluxG = (h_GWflow > 0.0) ? (f_Ground ( dh, h_GWflow, GW_coef, I_Length) ) : (0.0); 02214 break; 02215 case -1: /* if levee is on the right */ 02216 if ( cell->ind > 0 ) 02217 { /*overland flow */ 02218 if ( dh > 0 ) { 02219 /* flux from canal to cell */ 02220 fluxS = f_Manning( dh, H_rad_ch, SW_coef); 02221 } 02222 else if (SWater>GP_DetentZ) { 02223 fluxS = f_Manning ( dh, H_rad_cell, SW_coef); 02224 if (-fluxS > (SWater-GP_DetentZ) *CELL_SIZE ) 02225 fluxS = -(SWater-GP_DetentZ)*CELL_SIZE; 02226 } 02227 } 02228 else 02229 /*seepage on the levee side */ 02230 fluxL = (h_SPflow > 0.0) ? (f_Ground ( dh, h_SPflow, SPG_coef, I_Length) ) : (0.0); 02231 02232 /* subsurface groundwater flow both sides */ 02233 fluxG = (h_GWflow > 0.0) ? (f_Ground ( dh, h_GWflow, GW_coef, I_Length) ) : (0.0); 02234 break; 02235 default: 02236 printf ("Error in levee location: Channel N %d", chan_n+CHo ); 02237 exit (-1); 02238 break; 02239 } /*end switch */ 02240 02241 02242 02243 /* can_cell_M and can_cell_A are the areas of the canal and the cell multiplied (M) and added (A) together, respectively */ 02244 /* the flux eqn is similar to the simple weir eqn for virtual structures, equilibrating the heads across two unequal area regions */ 02245 02246 /* Surface flows: making sure that the cell head is not higher than the canal head */ 02247 if (fluxS>0 && ( (fluxCk = tot_head + fluxS/CELL_SIZE - (CH_bottElev + CanWatDep - fluxS/Chan_list[chan_n]->area) ) > 0.0 ) ) { 02248 fluxS = (can_cell_M*(CH_bottElev + CanWatDep)/can_cell_A - can_cell_M*tot_head/can_cell_A ); 02249 fluxCk = tot_head + fluxS/CELL_SIZE - (CH_bottElev + CanWatDep - fluxS/Chan_list[chan_n]->area); 02250 if (fluxCk > F_ERROR && debug>3) { 02251 sprintf(msgStr,"Day %6.1f: Warning - excessive head in cell after flux from Canal %d (%f m diff)", 02252 SimTime.TIME, Chan_list[chan_n]->number,fluxCk); 02253 WriteMsg( msgStr,True ); 02254 } 02255 } 02256 02257 /* Surface flows: making sure that the canal water level is not flooded much higher than the water level in the cell */ 02258 if ( fluxS<0 && ( (fluxCk = (CH_bottElev + CanWatDep - fluxS/Chan_list[chan_n]->area) - (tot_head + fluxS/CELL_SIZE) ) > 0.0 ) ) { 02259 fluxS = (can_cell_M*(CH_bottElev + CanWatDep)/can_cell_A - can_cell_M*tot_head/can_cell_A ); 02260 fluxCk = (CH_bottElev + CanWatDep - fluxS/Chan_list[chan_n]->area) - (tot_head + fluxS/CELL_SIZE); 02261 if (fluxCk > F_ERROR && debug>3) { 02262 sprintf(msgStr,"Day %6.1f: Warning - excessive head in Canal %d after flux from cell (%f m diff)", 02263 SimTime.TIME, Chan_list[chan_n]->number,fluxCk); 02264 WriteMsg( msgStr,True ); 02265 } 02266 } 02267 02268 /* now ensure the canal is not drained below its minimum level */ 02269 if ( fluxS > 0 || fluxG > 0 || fluxL > 0) /* check gw, seep, and sfwat */ 02270 { 02271 fluxO = (fluxS > 0) ? fluxS : 0; 02272 fluxO += (fluxG > 0) ? fluxG : 0; 02273 fluxO += (fluxL > 0) ? fluxL : 0; 02274 02275 /* using vol associated with new estimate (before subtracting losses) */ 02276 if ( (fluxCk = CH_vol - MIN_VOL - fluxS - fluxG - fluxL) < 0.0 ) 02277 { fluxCk = (fluxO>0) ? ( ( fluxO + fluxCk )/fluxO) : (0.0); /* v2.5 removed a divide by zero, but shouldn't be needed */ 02278 if (fluxS>0) fluxS *= fluxCk; /* reduce all pos outflows by this proportion */ 02279 if (fluxG>0) fluxG *= fluxCk; 02280 if (fluxL>0) fluxL *= fluxCk; 02281 if ( (fluxCk = (CH_vol - MIN_VOL - fluxS - fluxG - fluxL)/Chan_list[chan_n]->area) < -GP_MinCheck ) { 02282 sprintf(msgStr,"Day %6.1f: capacityERR - excessive draining from Canal %d (%f m below min)", SimTime.TIME,Chan_list[chan_n]->number,fluxCk); 02283 WriteMsg( msgStr,True ); dynERRORnum++; } 02284 } 02285 } 02286 02287 /******** Below is UNUSED *********************/ 02288 if (debug>99 && fluxG != 0.0) do { 02289 /* This is a part of the routine used to integrate surface/groundwater 02290 fluxes in the cell-cell Fluxes.c. It only modifies the allocations if 02291 a cell is a recipient of groundwater flux (does not deal with cells as 02292 donor, which is handled in Fluxes.c). 02293 NOTE:****This routine is NOT fully integrated into the canal iterative solution, 02294 and thus is NOT used for now - get to it some day if it is determined to be needed. */ 02295 fluxHoriz = fluxG; 02296 02297 02298 /**** recipient cell's **pre-flux** capacities */ 02299 UnsatZ_rec = (fluxG>0) ? ( ElevMap[i] - GWH[i] / poros[HAB[i]] ) : (0.0) ; /* unsat zone depth */ 02300 if (debug>2 && (UnsatZ_rec < -0.001 ) ) { 02301 sprintf(msgStr,"Day %6.1f: capacityERR - neg unsat depth (%f m) in recipient cell (%d,%d) in canal-cell gw fluxes!", 02302 SimTime.TIME, UnsatZ_rec, cell->x, cell->y ); WriteMsg( msgStr,True ); dynERRORnum++; } 02303 02304 UnsatCap_rec = (fluxG>0) ? (UnsatZ_rec * poros[HAB[i]]) : (0.0); /* maximum pore space capacity (UnsatCap) 02305 in the depth (UnsatZ) of new unsaturated zone */ 02306 UnsatPot_rec = (fluxG>0) ? (UnsatCap_rec - Unsat[i] ) : (0.0); /* (height of) the volume of pore space (soil "removed") 02307 that is unoccupied in the unsat zone */ 02308 /* sf-unsat-sat fluxes */ 02309 horizTOsat_rec = (fluxG>0) ? (fluxHoriz) : (0.0); /* lateral inflow to soil into saturated storage */ 02310 satTOsf_rec = (fluxG>0) ? (Max(fluxHoriz - UnsatPot_rec, 0.0) ) : (0.0); /* upwelling beyond soil capacity */ 02311 if (fluxG>0) unsatTOsat_rec = (UnsatZ_rec > 0.0) ? /* incorporation of unsat moisture into sat storage with 02312 rising water table due to horiz inflow */ 02313 ( ((horizTOsat_rec-satTOsf_rec)/poros[HAB[i]] ) / UnsatZ_rec * Unsat[i] ) : 02314 (0.0); 02315 else 02316 unsatTOsat_rec = 0.0; 02317 02318 /**** potential new head in recipient cell will be ... */ 02319 if (fluxG>0) H_pot_rec = (GWH[i] + horizTOsat_rec + unsatTOsat_rec - satTOsf_rec) 02320 / poros[HAB[i]] + (SWater + satTOsf_rec); 02321 02322 02323 equilib = 1; 02324 02325 } while (!equilib); /* end of ***incomplete** routine for integrating groundwater-surface water and preventing head reversals */ 02326 /******** Above is UNUSED *********************/ 02327 02328 /* if (fluxG>0) fluxG=fluxHoriz; */ /* unused, part of unimplemented sf/gwater routine */ 02329 02330 CH_vol -= ( fluxS + fluxG + fluxL); /* subtract flows (pos == loss) from volume associated with new estimate */ 02331 02332 if ( converged ) 02333 { /* the nutrient mass fluxes (pre-flux volumes) (mass=kg, vol=m3)*/ 02334 /* remember pos flux is from canal */ 02335 /* (CH_vol_R is vol prior to in/out fluxes) */ 02336 /* surface water canal-cell flux */ 02337 if ( fluxS != 0 ) { 02338 if ( fluxS > 0 ) /* surface water flux from canal to cell */ 02339 { 02340 /* this is where Disp_Calc comes in */ /* hcf TEST to see about reducing dispersion, halfing the flux of salt (i.e., ca. 500m grid dispersion) */ 02341 N_fl = (CH_vol_R > 0) ? (Chan_list[chan_n]->N/CH_vol_R*fluxS) : (0.0); 02342 P_fl = (CH_vol_R > 0) ? (Chan_list[chan_n]->P/CH_vol_R*fluxS) : (0.0); 02343 S_fl = (CH_vol_R > 0) ? (Chan_list[chan_n]->S/CH_vol_R*fluxS) : (0.0); 02344 02345 if (Chan_list[chan_n]->basin != basn[i] && debug > -999 ) { 02346 if ( (Chan_list[chan_n]->family != basn_list[basn[i]]->family) && (debug > 0) ) { /* if the flow is not within the family... */ 02347 sprintf(msgStr,"Day %6.1f: ERROR - no basin-basin canal-cell overland flow! (Reach %d, basn %d, with cell %d,%d, basin %d)", 02348 SimTime.TIME,Chan_list[chan_n]->number, Chan_list[chan_n]->basin, cell->x, cell->y, basn[i]); 02349 WriteMsg( msgStr,True ); dynERRORnum++; 02350 } 02351 else { /* if it's flow within a family, just keep 02352 track of what the children do among themselves */ 02353 if ( !Chan_list[chan_n]->parent ) { 02354 /* then find out about the flow for the family's sake */ 02355 VOL_OUT_OVL[Chan_list[chan_n]->basin] += fluxS; 02356 P_OUT_OVL[Chan_list[chan_n]->basin] += P_fl; 02357 S_OUT_OVL[Chan_list[chan_n]->basin] += S_fl; 02358 } 02359 if ( !basn_list[basn[i]]->parent ) { 02360 /* then find out about the flow for the family's sake */ 02361 VOL_IN_OVL[basn[i]] += fluxS; 02362 P_IN_OVL[basn[i]] += P_fl; 02363 S_IN_OVL[basn[i]] += S_fl; 02364 } 02365 } 02366 } 02367 } 02368 else /* surface water flux from cell to canal */ 02369 { 02370 /* this is where Disp_Calc comes in */ 02371 N_fl = ( SWH[i] > 0 ) ? NA[i]*fluxS/CELL_SIZE/SWH[i] : 0.; 02372 P_fl = ( SWH[i] > 0 ) ? PA[i]*fluxS/CELL_SIZE/SWH[i] : 0.; 02373 S_fl = ( SWH[i] > 0 ) ? SA[i]*fluxS/CELL_SIZE/SWH[i] : 0.; 02374 if (Chan_list[chan_n]->basin != basn[i] && debug > -999 ) { 02375 02376 if ( (Chan_list[chan_n]->family != basn_list[basn[i]]->family) && (debug > 0) ) { /* if the flow is not within the family... */ 02377 sprintf(msgStr,"Day %6.1f: ERROR - no basin-basin canal-cell overland flow! (Reach %d, basn %d, with cell %d,%d, basin %d)", 02378 SimTime.TIME,Chan_list[chan_n]->number, Chan_list[chan_n]->basin, cell->x, cell->y, basn[i]); 02379 WriteMsg( msgStr,True ); dynERRORnum++; 02380 } 02381 else { /* if it's flow within a family, just keep 02382 track of what the children do among themselves */ 02383 if ( !basn_list[basn[i]]->parent ) { 02384 /* then find out about the flow for the family's sake */ 02385 VOL_OUT_OVL[basn[i]] -= fluxS; 02386 P_OUT_OVL[basn[i]] -= P_fl; 02387 S_OUT_OVL[basn[i]] -= S_fl; 02388 } 02389 if ( !Chan_list[chan_n]->parent ) { 02390 /* then find out about the flow for the family's sake */ 02391 VOL_IN_OVL[Chan_list[chan_n]->basin] -= fluxS; 02392 P_IN_OVL[Chan_list[chan_n]->basin] -= P_fl; 02393 S_IN_OVL[Chan_list[chan_n]->basin] -= S_fl; 02394 } 02395 } 02396 } 02397 02398 02399 } 02400 /* now pass that mass flux to/from the cell/canal */ 02401 NA[i] += N_fl; 02402 PA[i] += P_fl; 02403 SA[i] += S_fl; 02404 Chan_list[chan_n]->N -= N_fl; 02405 Chan_list[chan_n]->P -= P_fl; 02406 Chan_list[chan_n]->S -= S_fl; 02407 } 02408 02409 /* groundwater canal-cell flux */ 02410 if ( fluxG != 0 ) { 02411 if ( fluxG > 0 ) /* ground water flux from canal to cell */ 02412 { 02413 N_fl = (CH_vol_R > 0) ? (Chan_list[chan_n]->N/CH_vol_R*fluxG) : (0.0); 02414 P_fl = (CH_vol_R > 0) ? (Chan_list[chan_n]->P/CH_vol_R*fluxG) : (0.0); 02415 S_fl = (CH_vol_R > 0) ? (Chan_list[chan_n]->S/CH_vol_R*fluxG) : (0.0); 02416 02417 if (Chan_list[chan_n]->basin != basn[i] && debug > -999 ) { 02418 if (Chan_list[chan_n]->family != 02419 basn_list[basn[i]]->family ) { /* if the flow is not within the family... */ 02420 if ( !Chan_list[chan_n]->parent ) { /* and if the donor or recipient is a child... */ 02421 /* then find out about the flow for the family's sake */ 02422 VOL_OUT_GW[Chan_list[chan_n]->family] += fluxG; 02423 P_OUT_GW[Chan_list[chan_n]->family] += P_fl; 02424 S_OUT_GW[Chan_list[chan_n]->family] += S_fl; 02425 } 02426 if ( !basn_list[basn[i]]->parent ) { 02427 /* then find out about the flow for the family's sake */ 02428 VOL_IN_GW[basn_list[basn[i]]->family] += fluxG; 02429 P_IN_GW[basn_list[basn[i]]->family] += P_fl; 02430 S_IN_GW[basn_list[basn[i]]->family] += S_fl; 02431 } 02432 VOL_OUT_GW[Chan_list[chan_n]->basin] += fluxG; 02433 VOL_IN_GW[basn[i]] += fluxG; 02434 P_OUT_GW[Chan_list[chan_n]->basin] += P_fl; 02435 P_IN_GW[basn[i]] += P_fl; 02436 S_OUT_GW[Chan_list[chan_n]->basin] += S_fl; 02437 S_IN_GW[basn[i]] += S_fl; 02438 } 02439 else { /* if it's flow within a family, just keep 02440 track of what the children do among themselves */ 02441 if ( !Chan_list[chan_n]->parent ) { 02442 /* then find out about the flow for the family's sake */ 02443 VOL_OUT_GW[Chan_list[chan_n]->basin] += fluxG; 02444 P_OUT_GW[Chan_list[chan_n]->basin] += P_fl; 02445 S_OUT_GW[Chan_list[chan_n]->basin] += S_fl; 02446 } 02447 if ( !basn_list[basn[i]]->parent ) { 02448 /* then find out about the flow for the family's sake */ 02449 VOL_IN_GW[basn[i]] += fluxG; 02450 P_IN_GW[basn[i]] += P_fl; 02451 S_IN_GW[basn[i]] += S_fl; 02452 } 02453 } 02454 } 02455 } /* end of positive flow evaluations */ 02456 02457 02458 else /* ground water flux from cell to canal */ 02459 { 02460 N_fl = ( GWH[i] > 0 ) ? GNA[i]*fluxG/CELL_SIZE/GWH[i] : 0.; 02461 P_fl = ( GWH[i] > 0 ) ? GPA[i]*fluxG/CELL_SIZE/GWH[i] : 0.; 02462 S_fl = ( GWH[i] > 0 ) ? GSA[i]*fluxG/CELL_SIZE/GWH[i] : 0.; 02463 if (Chan_list[chan_n]->basin != basn[i] && debug > -999) { 02464 if (Chan_list[chan_n]->family != 02465 basn_list[basn[i]]->family ) { /* if the flow is not within the family... */ 02466 if ( !basn_list[basn[i]]->parent ) { /* and if the donor or recipient is a child... */ 02467 /* then find out about the flow for the family's sake */ 02468 VOL_OUT_GW[basn_list[basn[i]]->family] -= fluxG; 02469 P_OUT_GW[basn_list[basn[i]]->family] -= P_fl; 02470 S_OUT_GW[basn_list[basn[i]]->family] -= S_fl; 02471 } 02472 if ( !Chan_list[chan_n]->parent ) { 02473 /* then find out about the flow for the family's sake */ 02474 VOL_IN_GW[Chan_list[chan_n]->family] -= fluxG; 02475 P_IN_GW[Chan_list[chan_n]->family] -= P_fl; 02476 S_IN_GW[Chan_list[chan_n]->family] -= S_fl; 02477 } 02478 VOL_IN_GW[Chan_list[chan_n]->basin] -= fluxG; 02479 VOL_OUT_GW[basn[i]] -= fluxG; 02480 P_IN_GW[Chan_list[chan_n]->basin] -= P_fl; 02481 P_OUT_GW[basn[i]] -= P_fl; 02482 S_IN_GW[Chan_list[chan_n]->basin] -= S_fl; 02483 S_OUT_GW[basn[i]] -= S_fl; 02484 } 02485 else { /* if it's flow within a family, just keep 02486 track of what the children do among themselves */ 02487 if ( !basn_list[basn[i]]->parent ) { 02488 /* then find out about the flow for the family's sake */ 02489 VOL_OUT_GW[basn[i]] -= fluxG; 02490 P_OUT_GW[basn[i]] -= P_fl; 02491 S_OUT_GW[basn[i]] -= S_fl; 02492 } 02493 if ( !Chan_list[chan_n]->parent ) { 02494 /* then find out about the flow for the family's sake */ 02495 VOL_IN_GW[Chan_list[chan_n]->basin] -= fluxG; 02496 P_IN_GW[Chan_list[chan_n]->basin] -= P_fl; 02497 S_IN_GW[Chan_list[chan_n]->basin] -= S_fl; 02498 } 02499 } 02500 } 02501 } 02502 /* now pass that mass flux to/from the cell/canal 02503 this includes allocating nuts to surface water thru upflow (unimplemented) */ 02504 /* unused, part of unimplemented sf/gwater routine */ 02505 /* SNfl = Chan_list[chan_n]->N/CH_vol_R*satTOsf_rec ; */ 02506 /* GNfl = N_fl - SNfl; */ 02507 /* SPfl = Chan_list[chan_n]->P/CH_vol_R*satTOsf_rec ; */ 02508 /* GPfl = P_fl - SPfl; */ 02509 /* SSfl = Chan_list[chan_n]->S/CH_vol_R*satTOsf_rec ; */ 02510 /* GSfl = S_fl - SSfl; */ 02511 /* GNA[i] += GNfl; */ 02512 /* GPA[i] += GPfl; */ 02513 /* GSA[i] += GSfl; */ 02514 GNA[i] += N_fl; 02515 GPA[i] += P_fl; 02516 GSA[i] += S_fl; 02517 Chan_list[chan_n]->N -= N_fl; 02518 Chan_list[chan_n]->P -= P_fl; 02519 Chan_list[chan_n]->S -= S_fl; 02520 /* upflow into surface water nuts (this is actually canal conc., but what the heck) */ 02521 /* unused, part of unimplemented sf/gwater routine */ 02522 /* NA[i] += SNfl; */ 02523 /* PA[i] += SPfl; */ 02524 /* SA[i] += SSfl; */ 02525 } 02526 02527 /* seepage canal-cell flux */ 02528 if ( fluxL != 0 ) { 02529 if ( fluxL > 0 ) /* seepage flux from canal to cell */ 02530 { 02531 N_fl = (CH_vol_R > 0) ? (Chan_list[chan_n]->N/CH_vol_R*fluxL) : (0.0); 02532 P_fl = (CH_vol_R > 0) ? (Chan_list[chan_n]->P/CH_vol_R*fluxL) : (0.0); 02533 S_fl = (CH_vol_R > 0) ? (Chan_list[chan_n]->S/CH_vol_R*fluxL) : (0.0); 02534 if (Chan_list[chan_n]->basin != basn[i] && debug > -999 ) { 02535 if (Chan_list[chan_n]->family != 02536 basn_list[basn[i]]->family ) { /* if the flow is not within the family... */ 02537 if ( !Chan_list[chan_n]->parent ) { /* and if the donor or recipient is a child... */ 02538 /* then find out about the flow for the family's sake */ 02539 VOL_OUT_SPG[Chan_list[chan_n]->family] += fluxL; 02540 P_OUT_SPG[Chan_list[chan_n]->family] += P_fl; 02541 S_OUT_SPG[Chan_list[chan_n]->family] += S_fl; 02542 } 02543 if ( !basn_list[basn[i]]->parent ) { 02544 /* then find out about the flow for the family's sake */ 02545 VOL_IN_SPG[basn_list[basn[i]]->family] += fluxL; 02546 P_IN_SPG[basn_list[basn[i]]->family] += P_fl; 02547 S_IN_SPG[basn_list[basn[i]]->family] += S_fl; 02548 } 02549 VOL_OUT_SPG[Chan_list[chan_n]->basin] += fluxL; 02550 VOL_IN_SPG[basn[i]] += fluxL; 02551 P_OUT_SPG[Chan_list[chan_n]->basin] += P_fl; 02552 P_IN_SPG[basn[i]] += P_fl; 02553 S_OUT_SPG[Chan_list[chan_n]->basin] += S_fl; 02554 S_IN_SPG[basn[i]] += S_fl; 02555 } 02556 else { /* if it's flow within a family, just keep 02557 track of what the children do among themselves */ 02558 if ( !Chan_list[chan_n]->parent ) { 02559 /* then find out about the flow for the family's sake */ 02560 VOL_OUT_SPG[Chan_list[chan_n]->basin] += fluxL; 02561 P_OUT_SPG[Chan_list[chan_n]->basin] += P_fl; 02562 S_OUT_SPG[Chan_list[chan_n]->basin] += S_fl; 02563 } 02564 if ( !basn_list[basn[i]]->parent ) { 02565 /* then find out about the flow for the family's sake */ 02566 VOL_IN_SPG[basn[i]] += fluxL; 02567 P_IN_SPG[basn[i]] += P_fl; 02568 S_IN_SPG[basn[i]] += S_fl; 02569 } 02570 } 02571 } 02572 if ( tot_head > GW_head ) { /* to cell surface water */ 02573 NA[i] += N_fl; 02574 PA[i] += P_fl; 02575 SA[i] += S_fl; 02576 } 02577 else { /* to cell groundwater */ 02578 GNA[i] += N_fl; 02579 GPA[i] += P_fl; 02580 GSA[i] += S_fl; 02581 } 02582 } 02583 else if (fluxL < 0) /* seepage flux from cell to canal */ 02584 { 02585 if ( tot_head > GW_head ) { /* cell's tot head > its groundwater head */ 02586 N_fl = ( SWH[i] > 0 ) ? NA[i]*fluxL/CELL_SIZE/SWH[i] : 0.; 02587 P_fl = ( SWH[i] > 0 ) ? PA[i]*fluxL/CELL_SIZE/SWH[i] : 0.; 02588 S_fl = ( SWH[i] > 0 ) ? SA[i]*fluxL/CELL_SIZE/SWH[i] : 0.; 02589 NA[i] += N_fl; 02590 PA[i] += P_fl; 02591 SA[i] += S_fl; 02592 } 02593 else { 02594 N_fl = ( GWH[i] > 0 ) ? GNA[i]*fluxL/CELL_SIZE/GWH[i] : 0.; 02595 P_fl = ( GWH[i] > 0 ) ? GPA[i]*fluxL/CELL_SIZE/GWH[i] : 0.; 02596 S_fl = ( GWH[i] > 0 ) ? GSA[i]*fluxL/CELL_SIZE/GWH[i] : 0.; 02597 GNA[i] += N_fl; 02598 GPA[i] += P_fl; 02599 GSA[i] += S_fl; 02600 } 02601 if (Chan_list[chan_n]->basin != basn[i] && debug > -999) { 02602 if (Chan_list[chan_n]->family != 02603 basn_list[basn[i]]->family ) { /* if the flow is not within the family... */ 02604 if ( !basn_list[basn[i]]->parent ) { /* and if the donor or recipient is a child... */ 02605 /* then find out about the flow for the family's sake */ 02606 VOL_OUT_SPG[basn_list[basn[i]]->family] -= fluxL; 02607 P_OUT_SPG[basn_list[basn[i]]->family] -= P_fl; 02608 S_OUT_SPG[basn_list[basn[i]]->family] -= S_fl; 02609 } 02610 if ( !Chan_list[chan_n]->parent ) { 02611 /* then find out about the flow for the family's sake */ 02612 VOL_IN_SPG[Chan_list[chan_n]->family] -= fluxL; 02613 P_IN_SPG[Chan_list[chan_n]->family] -= P_fl; 02614 S_IN_SPG[Chan_list[chan_n]->family] -= S_fl; 02615 } 02616 VOL_IN_SPG[Chan_list[chan_n]->basin] -= fluxL; 02617 VOL_OUT_SPG[basn[i]] -= fluxL; 02618 P_IN_SPG[Chan_list[chan_n]->basin] -= P_fl; 02619 P_OUT_SPG[basn[i]] -= P_fl; 02620 S_IN_SPG[Chan_list[chan_n]->basin] -= S_fl; 02621 S_OUT_SPG[basn[i]] -= S_fl; 02622 } 02623 else { /* if it's flow within a family, just keep 02624 track of what the children do among themselves */ 02625 if ( !basn_list[basn[i]]->parent ) { 02626 /* then find out about the flow for the family's sake */ 02627 VOL_OUT_SPG[basn[i]] -= fluxL; 02628 P_OUT_SPG[basn[i]] -= P_fl; 02629 S_OUT_SPG[basn[i]] -= S_fl; 02630 } 02631 if ( !Chan_list[chan_n]->parent ) { 02632 /* then find out about the flow for the family's sake */ 02633 VOL_IN_SPG[Chan_list[chan_n]->basin] -= fluxL; 02634 P_IN_SPG[Chan_list[chan_n]->basin] -= P_fl; 02635 S_IN_SPG[Chan_list[chan_n]->basin] -= S_fl; 02636 } 02637 } 02638 } 02639 } 02640 /* now pass that mass flux to/from the canal */ 02641 Chan_list[chan_n]->N -= N_fl; 02642 Chan_list[chan_n]->P -= P_fl; 02643 Chan_list[chan_n]->S -= S_fl; 02644 } 02645 /* now we recalculate the depths of SFWater and Gwater in cell */ 02646 /* SWH[i] += (fluxS+satTOsf_rec)/CELL_SIZE; */ 02647 /* GWH[i] += (fluxG-satTOsf_rec)/CELL_SIZE; */ 02648 SWH[i] += (fluxS)/CELL_SIZE; 02649 GWH[i] += (fluxG)/CELL_SIZE; 02650 if ( tot_head > GW_head ) SWH[i] += fluxL/CELL_SIZE; /* whether to add seepage to surface or */ 02651 else GWH[i] += fluxL/CELL_SIZE; /* groundwater is not critical, as vertical updates will follow */ 02652 02653 02654 } /* that's all we do when finally converged */ 02655 02656 T_flux_S += fluxS; 02657 T_flux_G += fluxG; 02658 T_flux_L += fluxL; 02659 02660 cell = cell->next_cell; 02661 } /*end cycle along canal cells */ 02662 02663 02664 error = (CanWatDep - Chan_list[chan_n]->wat_depth) - (Qin - Qout - T_flux_S - T_flux_G - T_flux_L)/ Chan_list[chan_n]->area; 02665 if (converged && error != errorConv ) { 02666 /* error the second time around should be close to that of the first */ 02667 if (fabs(error-errorConv)>F_ERROR ) { 02668 sprintf(msgStr,"Day %6.1f: ERROR - converg error != to error after cell-canal fluxes (Chan %d, est= %5.3f, last depth= %5.3f m)", 02669 SimTime.TIME, Chan_list[chan_n]->number, CanWatDep, Chan_list[chan_n]->wat_depth); 02670 WriteMsg( msgStr,True ); dynERRORnum++; 02671 } 02672 02673 if (CanWatDep>Chan_list[chan_n]->depth*3.0 || CanWatDep < 0.0) { 02674 CanWatDep = MINDEPTH; /* lost the mass balance, but let it go for now */ 02675 sprintf(msgStr," Reset Chan %d depth to minimum allowed (%5.3f m)", 02676 Chan_list[chan_n]->number, MINDEPTH); 02677 WriteMsg( msgStr,True ); } 02678 02679 /*errorConv is the error upon first reaching convergence criteria; */ 02680 /* we then recalc the fluxes in the same loop thru cells (w/ same depth est.), */ 02681 /* and should have the same fluxes and error as before */ 02682 if (debug>4) { /* this here to halt program with high debug */ 02683 printf("\nDay %6.1f: ERROR - converg error != to error after cell-canal fluxes (Chan %d, est= %5.3f m)\n", 02684 SimTime.TIME, Chan_list[chan_n]->number, CanWatDep); 02685 exit (-1); 02686 02687 } 02688 02689 } 02690 02691 ++iter; 02692 02693 } while (!converged ); /* end relaxation procedure */ 02694 02695 if ( factor != 0 && Qout > 0) /* if relaxation was abnormally stopped because of hitting the bottom */ 02696 { 02697 sprintf(msgStr,"Day %6.1f: ERROR - hit bottom of Canal %d, stopped the iterative relaxation", SimTime.TIME, Chan_list[chan_n]->number); 02698 WriteMsg( msgStr,True ); 02699 dynERRORnum++; 02700 /*#######*******######## this old code should not be reached 02701 the code is questionable - an ERROR message printed 02702 to file will indicate signif problem due to entrance to this */ 02703 Qout1 = (Chan_list[chan_n]->wat_depth - CanWatDep)*Chan_list[chan_n]->area + Qin - T_flux_S - T_flux_G - T_flux_L; 02704 structs = struct_first; 02705 while ( structs != NULL ) /* recalculate the outflow in the data for possible use in the next canal inflow */ 02706 { 02707 if ( structs->canal_fr == chan_n+CHo ) structs->flow *= Qout1/Qout; 02708 02709 structs = structs->next_in_list; 02710 } 02711 Qout = Qout1; 02712 } 02713 02714 Chan_list[chan_n]->wat_depth = CanWatDep; /* new canal water depth */ 02715 CH_vol = CanWatDep * Chan_list[chan_n]->area; /* new canal volume */ 02716 02717 if( debug > 3 ) 02718 { 02719 /* concentration in mg/L (kg/m3==g/L, convert P (not S) to mg/L) */ 02720 Chan_list[chan_n]->P_con = (CH_vol > 0) ? (Chan_list[chan_n]->P/CH_vol*1000.0) : 0.0; 02721 Chan_list[chan_n]->S_con = (CH_vol > 0) ? (Chan_list[chan_n]->S/CH_vol) : 0.0; 02722 fprintf( canDebugFile, 02723 "%4d %8.3f %8.4f %8.4f %12.1f %12.1f %12.1f %12.1f %12.1f %5d %9.1f %7.5f \n", 02724 Chan_list[chan_n]->number, Chan_list[chan_n]->wat_depth, Chan_list[chan_n]->P_con, 02725 Chan_list[chan_n]->S_con, T_flux_S, T_flux_G, T_flux_L, Qin, Qout, iter, Chan_list[chan_n]->area, error ); 02726 02727 } 02728 02729 return; 02730 }
void Flows_in_Structures | ( | float * | SWH, | |
float * | GW, | |||
float * | poros, | |||
float * | Elev, | |||
double * | NA, | |||
double * | PA, | |||
double * | SA | |||
) |
Calling function to functions that determine flows through water control structures.
SWH | SURFACE_WAT | |
GW | SAT_WATER | |
poros | HP_HYD_POROSITY | |
Elev | SED_ELEV | |
NA | DINdummy | |
PA | TP_SF_WT | |
SA | SALT_SURF_WT |
Definition at line 2811 of file WatMgmt.c.
References Structure::conc_N, Structure::conc_P, Structure::conc_S, Structure::flag, Structure::flagHWsched, Structure::flagHWtide, Structure::flagTWsched, Structure::flagTWtide, Structure::flow, flowCalc_CanCan(), flowCalc_CanCel(), flowCalc_CelCan(), flowCalc_CelCel(), flowData_CanCan(), flowData_CanCel(), flowData_CelCan(), flowData_CelCel(), FMOD(), GetGraph(), GP_SLRise, Structure::HW_graph, Structure::HW_stage, Structure::multiOut, Structure::next_in_list, printchan, Structure::S_nam, SimTime, Structure::SrcDest, struct_first, structs, Structure::Sum_P, Structure::Sum_S, Structure::SumFlow, simTime::TIME, Structure::TW_graph, Structure::TW_stage, WstructOutFile, WstructOutFile_P, and WstructOutFile_S.
Referenced by Run_Canal_Network().
02812 { 02816 struct Structure *structs, *struct_hist_start; 02817 int flow_code; /* v2.8 */ 02818 02819 structs = struct_first; 02820 02821 while ( structs != NULL ) 02822 { 02823 if ( structs->flag < 0 || (structs->flag >1) ) { /* nothing to do when structure inactive (neg or >1 flag) */ 02824 structs->flow = 0.0; /* used in summing up flows for Qin and Qout later */ 02825 structs->conc_P = 0.0; 02826 structs->conc_N = 0.0; 02827 structs->conc_S = 0.0; 02828 } 02829 else { 02830 02833 if ( structs->flagTWsched == 1 ) /* this means that there is a time series schedule graph for TailWater target */ 02834 { 02835 structs->TW_stage = GetGraph ( structs->TW_graph, ( FMOD(SimTime.TIME,365.0) >0.0 ) ? ( FMOD(SimTime.TIME,365.0) ) : ( 0.0) ); 02836 02837 /* add sea level rise (annual rate in GlobalParms input) if this is a tidaly-driven schedule */ 02838 if (structs->flagTWtide == 1) structs->TW_stage = structs->TW_stage + (SimTime.TIME/365) * GP_SLRise ; 02839 } 02840 02841 if ( structs->flagHWsched == 1 ) /* this means that there is a time series schedule graph for HeadWater target */ 02842 { 02843 structs->HW_stage = GetGraph ( structs->HW_graph, ( FMOD(SimTime.TIME,365.0) >0.0 ) ? ( FMOD(SimTime.TIME,365.0) ) : ( 0.0) ); 02844 02845 /* add sea level rise (annual rate in GlobalParms input) if this is a tidaly-driven schedule */ 02846 if (structs->flagHWtide == 1) structs->HW_stage = structs->HW_stage + (SimTime.TIME/365) * GP_SLRise ; 02847 } 02848 02849 if (strcmp(structs->SrcDest,"CanCan") == 0) flow_code = 0; 02850 if (strcmp(structs->SrcDest,"CelCel") == 0) flow_code = 1; 02851 if (strcmp(structs->SrcDest,"CanCel") == 0) flow_code = 2; 02852 if (strcmp(structs->SrcDest,"CelCan") == 0) flow_code = 3; 02853 02854 /* call the modules to move water & constituents thru the specific source-destination type of structure */ 02855 switch(flow_code) { 02856 case 0: 02857 if (structs->flag == 1) flowData_CanCan(structs, struct_hist_start, SWH, NA, PA, SA); 02858 else flowCalc_CanCan(structs, SWH, GW, poros, Elev, NA, PA, SA); 02859 break; 02860 case 1: 02861 if (structs->flag == 1) flowData_CelCel(structs, SWH, NA, PA, SA); 02862 else flowCalc_CelCel(structs, SWH, Elev, NA, PA, SA); 02863 break; 02864 case 2: 02865 if (structs->flag == 1) flowData_CanCel(structs, struct_hist_start, SWH, NA, PA, SA); 02866 else flowCalc_CanCel(structs, SWH, GW, poros, Elev, NA, PA, SA); 02867 break; 02868 case 3: 02869 if (structs->flag == 1) flowData_CelCan(structs, SWH, NA, PA, SA); 02870 else flowCalc_CelCan(structs, SWH, GW, poros, Elev, NA, PA, SA); 02871 break; 02872 default: { 02873 printf ("\nError in source-destination data for structure N %s: impossible condition! \n", structs->S_nam ); 02874 exit (-1); 02875 } 02876 } 02877 } 02878 02879 /* sum of flows and solute masses thru structs over the can_Intvl canal summary interval */ 02880 structs->SumFlow += structs->flow; 02881 structs->Sum_P += structs->conc_P * structs->flow; 02882 /* structs->Sum_N += structs->conc_N * structs->flow; */ 02883 structs->Sum_S += structs->conc_S * structs->flow; 02884 02885 structs->multiOut = 0; /* reset the multi-outflow flag to zero after done */ 02886 02887 /* print sum of flows and the flow weighted mean conc thru structures */ 02888 if ( printchan ) { 02889 fprintf( WstructOutFile, "%7.0f\t", (structs->SumFlow)/(2446.848) ); /* convert to cfs (0.02832*60*60*24) */ 02890 fprintf( WstructOutFile_P, "%7.4f\t", 02891 (structs->SumFlow > 0.0) ? (structs->Sum_P/structs->SumFlow*1000.0) : (0.0) ); /* convert g/L to mg/L */ 02892 /* fprintf( WstructOutFile_N, "%7.4f\t", 02893 (structs->SumFlow > 0.0) ? (structs->Sum_N/structs->SumFlow*1000.0) : (0.0) );*/ /* convert g/L to mg/L */ 02894 fprintf( WstructOutFile_S, "%7.4f\t", 02895 (structs->SumFlow > 0.0) ? (structs->Sum_S/structs->SumFlow) : (0.0) ); /* g/L, no conversion */ 02896 02897 structs->SumFlow = 0.0; 02898 structs->Sum_P = 0.0; 02899 /* structs->Sum_N = 0.0; */ 02900 structs->Sum_S = 0.0; 02901 } 02902 02903 /* increment to the next structure in the list */ 02904 structs = structs->next_in_list; 02905 } 02906 02907 if (printchan) { 02908 fflush( WstructOutFile ); 02909 fflush( WstructOutFile_P ); 02910 /* fflush( WstructOutFile_N ); */ 02911 fflush( WstructOutFile_S ); 02912 } 02913 02914 return; 02915 02916 }
void flowData_CanCan | ( | struct Structure * | structs, | |
struct Structure * | struct_hist_start, | |||
float * | SWH, | |||
double * | NA, | |||
double * | PA, | |||
double * | SA | |||
) |
Canal-to-Canal water control structure flows: Data-driven (historical/sfwmm).
SWH | SURFACE_WAT | |
NA | DINdummy | |
PA | TP_SF_WT | |
SA | SALT_SURF_WT |
Definition at line 2927 of file WatMgmt.c.
References Chan::area, HistData::arrayN, HistData::arrayP, HistData::arrayS, HistData::arrayWat, Chan::basin, basn, Structure::canal_fr, Structure::canal_to, canDebugFile, canstep, Structure::cell_i_to, Structure::cell_j_to, CELL_SIZE, Chan_list, CHo, Structure::conc_N, Structure::conc_P, Structure::conc_S, debug, dynERRORnum, Structure::flag, Structure::flow, Hist_data, Structure::histID, MINDEPTH, msgStr, Structure::multiOut, Chan::N, Structure::next_in_list, Chan::number, Chan::P, P_IN_STR, P_OUT_STR, ramp, Chan::S, S_IN_STR, Structure::S_nam, S_OUT_STR, SimTime, Structure::str_cell_i, Structure::str_cell_j, Chan::sumHistIn, Chan::sumHistOut, T, simTime::TIME, Structure::TN, Structure::TNser, Structure::TP, Structure::TPser, True, Structure::TS, Structure::TSser, VOL_IN_STR, VOL_OUT_STR, Chan::wat_depth, and WriteMsg().
Referenced by Flows_in_Structures().
02928 { 02929 int cell_to, cell_fr, can_to, can_fr; 02930 int cell_struct; 02931 double CH_vol; 02932 double Nconc, Pconc, Sconc; 02933 double N_fl, P_fl, S_fl; 02934 double chan_over; 02935 double ChanHistOut; 02936 02937 can_fr = structs->canal_fr - CHo; 02938 can_to = structs->canal_to - CHo; 02939 cell_struct = T(structs->str_cell_i,structs->str_cell_j); 02940 02941 /* DATA-DRIVEN STRUCTURE FLOW */ 02942 if (structs->multiOut == 1) return; /* this structure has already been processed as a multiple outflow from a canal */ 02943 /* FLOW */ 02944 /* don't do much with zero or negative flows */ 02945 structs->flow = Hist_data[structs->histID-1].arrayWat[((int)(SimTime.TIME))]*canstep; 02946 if (structs->flow == 0.0) { 02947 structs->conc_P = 0.0; 02948 structs->conc_N = 0.0; 02949 structs->conc_S = 0.0; 02950 return; 02951 } /* zero the reported struct flow conc (for output info only - mass is used in tracking actual flows) */ 02952 else if (structs->flow < 0.0) { 02953 sprintf( msgStr, "Day %6.1f: ERROR IN ASSUMPTION OF NO NEG HIST FLOW from chan %d", 02954 SimTime.TIME, Chan_list[can_to]->number ); 02955 WriteMsg( msgStr,True ); 02956 dynERRORnum++; 02957 return; 02958 } 02959 02960 /* for multiple historical/other-data outflows from a canal, ensure mass balance (sum of outflows !> avail volume) */ 02961 /* all flows from the canal associated with each set must be non-negative, which is currently valid */ 02962 /* the below cycle thru the structures will also process a canal->cell flow structure */ 02963 02964 struct_hist_start = structs; /* this is the first structure w/ historical info for a particular canal */ 02965 ChanHistOut = 0.0; /* sum of all historical/other-data outflows from a canal */ 02966 02967 while ( structs != NULL ) 02968 { 02969 if ( structs->flag == 1 && struct_hist_start->canal_fr == structs->canal_fr ) { /* look for outflows from same canal */ 02970 structs->flow = Hist_data[structs->histID-1].arrayWat[((int)(SimTime.TIME))]*canstep; 02971 ChanHistOut += structs->flow; /* sum the multiple historical/other-data outflows from canal */ 02972 } 02973 02974 structs = structs->next_in_list; /* increment to next structure */ 02975 } /* end cycle thru list of remaining structures in total list */ 02976 02977 structs = struct_hist_start; /* now we are pointing back to the first (or only) water control structure draining the canal */ 02978 02979 /* concentration in donor canal for structure flow, g/L = kg/m^3 */ 02980 /* this is based on previous depth/volume calc'd in FluxChannel */ 02981 /* or use historical conc */ 02982 02983 /* CONC */ 02984 /* canal TOTAL volume before new structure flows */ 02985 CH_vol = Chan_list[can_fr]->area*Chan_list[can_fr]->wat_depth; 02986 /* concentrations applied to all structures draining this canal */ 02987 Pconc = (structs->TPser == -1) ? 02988 ( (CH_vol>0) ? (Chan_list[can_fr]->P/CH_vol) : (0.0) ) : 02989 ( (structs->TPser == 0) ? (structs->TP) : ( Hist_data[structs->histID-1].arrayP[((int)(SimTime.TIME))] ) ); 02990 Nconc = (structs->TNser == -1) ? 02991 ( (CH_vol>0) ? (Chan_list[can_fr]->N/CH_vol) : (0.0) ) : 02992 ( (structs->TNser == 0) ? (structs->TN) : ( Hist_data[structs->histID-1].arrayN[((int)(SimTime.TIME))] ) ); 02993 Sconc = (structs->TSser == -1) ? 02994 ( (CH_vol>0) ? (Chan_list[can_fr]->S/CH_vol) : (0.0) ) : 02995 ( (structs->TSser == 0) ? (structs->TS) : ( Hist_data[structs->histID-1].arrayS[((int)(SimTime.TIME))] ) ); 02996 02997 02998 /* vol avail for fluxing */ 02999 CH_vol = Chan_list[can_fr]->area*(ramp(Chan_list[can_fr]->wat_depth-MINDEPTH) ); 03000 chan_over = (ChanHistOut > 0.0 ) ? ( CH_vol/ChanHistOut ) : 1.0; 03001 03002 do /* loop again through the remaining sequence of structures to correct any outflows for the canal */ 03003 { 03004 if (structs->flag == 1 && struct_hist_start->canal_fr == structs->canal_fr ) { 03005 03006 structs->multiOut = 1; /* set the flag to indicate this structure has been processed */ 03007 03008 /* revised FLOW */ 03009 if ( chan_over < 1.0 ) { /* if hist/other-data demand > canal vol */ 03010 if( debug > 0 ) { 03011 fprintf( canDebugFile, "Day \t%6.1f\t %s:\tTotDemand= \t%7.0f\t; exceeded chan \t%d\t avail vol= \t%7.0f \tby \t%7.0f \tm3 (\t%5.3f \tm deep).\n", 03012 SimTime.TIME, structs->S_nam, ChanHistOut, Chan_list[can_fr]->number, 03013 CH_vol, (ChanHistOut - CH_vol), Chan_list[can_fr]->wat_depth ); 03014 03015 } 03016 /* decrement the individual structure outflows by it's proportional contrib. */ 03017 structs->flow = (structs->flow) * chan_over ; 03018 } 03019 /* sum of all realized (corrected for excess demand) historical/other-data outflows from a canal during an iteration */ 03020 /* used to determine any allowable rule-based canal flows after the historical/other-data demands */ 03021 Chan_list[can_fr]->sumHistOut += structs->flow; 03022 03023 /* the recipient changes as we cycle thru the structures (may be another canal or a cell) */ 03024 can_to = structs->canal_to - CHo; 03025 cell_to = T(structs->cell_i_to,structs->cell_j_to); 03026 03027 structs->conc_P = Pconc;/* concentrations applied to all structures draining this canal */ 03028 structs->conc_N = Nconc; 03029 structs->conc_S = (structs->TSser == -1) ? 03030 (Sconc) : 03031 ( (structs->TSser == 0) ? (structs->TS) : 03032 ( Hist_data[structs->histID-1].arrayS[((int)(SimTime.TIME))] ) ); /* see note below on tracer conc. application */ 03033 03034 P_fl = structs->flow * structs->conc_P; 03035 N_fl = structs->flow * structs->conc_N; 03036 S_fl = structs->flow * structs->conc_S; 03037 /* change in nut mass in fr canal (kg) */ 03038 Chan_list[can_fr]->N -= N_fl ; 03039 Chan_list[can_fr]->P -= P_fl ; 03040 Chan_list[can_fr]->S -= (structs->TSser == -1) ? (S_fl) : (0); 03041 /* for the salt (S), we sometimes want to apply a tracer to internal canals/cells. 03042 Thus, in that case, we don't subtract salt from the canal because this is "introduced" salt 03043 that was not calculated from the available water and salt (i.e., the conc. was from the 03044 CanalData.struct data file, either fixed or a time series) */ 03045 03046 if (can_to > 0) { /* IF this is a canal recip, change in nut mass in to canal (kg) */ 03047 /* sum of all realized (corrected for excess demand) historical/other-data outflows into a canal during an iteration */ 03048 /* used to determine any allowable rule-based canal flows after the historical/other-data demands */ 03049 Chan_list[can_to]->sumHistIn += structs->flow; 03050 03051 Chan_list[can_to]->N += N_fl ; 03052 Chan_list[can_to]->P += P_fl ; 03053 Chan_list[can_to]->S += S_fl ; 03054 /* mass balance in fr and to canals */ 03055 /* canals themselves always belong to a parent hydro basin, 03056 thus canal-canal struct flows do not keep track of child-parent, child-child flows */ 03057 if (Chan_list[can_fr]->basin != Chan_list[can_to]->basin && debug > -999 ) { 03058 VOL_OUT_STR[Chan_list[can_fr]->basin] += structs->flow; 03059 VOL_IN_STR[Chan_list[can_to]->basin] += structs->flow; 03060 P_OUT_STR[Chan_list[can_fr]->basin] += P_fl; 03061 P_IN_STR[Chan_list[can_to]->basin] += P_fl; 03062 S_OUT_STR[Chan_list[can_fr]->basin] += (structs->TSser == -1) ? (S_fl) : (0); /* see note above on tracer conc. application */ 03063 S_IN_STR[Chan_list [can_to]->basin] += S_fl; 03064 } 03065 03066 03067 03068 } 03069 else if (cell_to > 0) { 03070 /* OR change in nut mass in downstream internal cell (kg) */ 03071 03072 if (structs->cell_i_to > 2 ) { /* to an on-map cell */ 03073 SWH[cell_to] += structs->flow/CELL_SIZE; 03074 PA[cell_to] += P_fl; 03075 NA[cell_to] += N_fl; 03076 SA[cell_to] += S_fl; 03077 /* mass balance in fr canal and to cell */ 03078 if (Chan_list[can_fr]->basin != basn[cell_to] && debug > -999 ) { 03079 VOL_OUT_STR[Chan_list[can_fr]->basin] += structs->flow; 03080 VOL_IN_STR[basn[cell_to]] += structs->flow; 03081 P_OUT_STR[Chan_list[can_fr]->basin] += P_fl; 03082 P_IN_STR[basn[cell_to]] += P_fl; 03083 S_OUT_STR[Chan_list[can_fr]->basin] += (structs->TSser == -1) ? (S_fl) : (0); /* see note above on tracer conc. application */ 03084 S_IN_STR[basn[cell_to]] += S_fl; 03085 03086 /* all structure flows, EXCEPT canal-canal, must be between parent (family) hydro basins */ 03087 // v2.8.4 if ( (Chan_list[can_fr]->family == basn_list[basn[cell_to]]->family) && (debug > 0) ) { 03088 // sprintf( msgStr, "Day %6.1f: ERROR in basin configuration for structure from chan %d to cell (%d,%d): flow must be between diff hydrologic basins", 03089 // SimTime.TIME, Chan_list[can_fr]->number,structs->cell_i_to,structs->cell_j_to ); 03090 // WriteMsg( msgStr,True ); 03091 // dynERRORnum++; 03092 // } 03093 } 03094 03095 03096 03097 } 03098 else if (structs->cell_i_to == 2 && debug > -999 ) { /* to off-map cell, mass balance check */ 03099 VOL_OUT_STR[Chan_list[can_fr]->basin] += structs->flow; 03100 VOL_OUT_STR[0] += structs->flow; 03101 P_OUT_STR[Chan_list[can_fr]->basin] += P_fl; 03102 P_OUT_STR[0] += P_fl; 03103 S_OUT_STR[Chan_list[can_fr]->basin] += (structs->TSser == -1) ? (S_fl) : (0); /* see note above on tracer conc. application */ 03104 S_OUT_STR[0] += (structs->TSser == -1) ? (S_fl) : (0); /* see note above on tracer conc. application */ 03105 } 03106 } 03107 /* don't do much with zero or negative flows */ 03108 if (structs->flow == 0.0) { 03109 structs->conc_P = 0.0; 03110 structs->conc_N = 0.0; 03111 structs->conc_S = 0.0; 03112 } /* for output purposes only, zero the reported conc */ 03113 else if (structs->flow < 0.0) { 03114 sprintf( msgStr, "Day %6.1f: ERROR IN ASSUMPTION OF NO NEG HIST FLOW from another cell/chan into chan %d", 03115 SimTime.TIME,Chan_list[can_fr]->number ); 03116 WriteMsg( msgStr,True ); 03117 dynERRORnum++; 03118 } 03119 } 03120 03121 structs = structs->next_in_list; 03122 } while (structs != NULL); /* cycling to the end of the list again !!!! */ 03123 03124 structs = struct_hist_start; /* now pointing back to the first historical outflow structure that we dealt with */ 03125 03126 03127 03128 } /* end of data-driven (historical/sfwmm) canal-canal flows */
void flowData_CelCel | ( | struct Structure * | structs, | |
float * | SWH, | |||
double * | NA, | |||
double * | PA, | |||
double * | SA | |||
) |
Cell-to-Cell water control structure flows: Data-driven (historical/sfwmm).
SWH | SURFACE_WAT | |
NA | DINdummy | |
PA | TP_SF_WT | |
SA | SALT_SURF_WT |
Definition at line 3325 of file WatMgmt.c.
References HistData::arrayN, HistData::arrayP, HistData::arrayS, HistData::arrayWat, basn, basn_list, canDebugFile, canstep, Structure::cell_i_fr, Structure::cell_i_to, Structure::cell_j_fr, Structure::cell_j_to, CELL_SIZE, Structure::conc_N, Structure::conc_P, Structure::conc_S, debug, dynERRORnum, Structure::flow, Hist_data, Structure::histID, msgStr, P_IN_STR, P_OUT_STR, S_IN_STR, Structure::S_nam, S_OUT_STR, SimTime, T, simTime::TIME, Structure::TN, Structure::TNser, Structure::TP, Structure::TPser, True, Structure::TS, Structure::TSser, VOL_IN_STR, VOL_OUT_STR, and WriteMsg().
Referenced by Flows_in_Structures().
03326 { 03327 int cell_to, cell_fr; 03328 03329 double cell_vol; 03330 double N_fl, P_fl, S_fl; 03331 03332 cell_to = T(structs->cell_i_to,structs->cell_j_to); 03333 cell_fr = T(structs->cell_i_fr,structs->cell_j_fr); 03334 03335 /* DATA-DRIVEN STRUCTURE FLOW */ 03336 /* don't do much with zero or negative flows */ 03337 structs->flow = Hist_data[structs->histID-1].arrayWat[((int)(SimTime.TIME))]*canstep; 03338 if (structs->flow == 0.0) { 03339 structs->conc_P = 0.0; 03340 structs->conc_N = 0.0; 03341 structs->conc_S = 0.0; 03342 return; /* for output purposes only, zero the reported conc */ 03343 } 03344 else if (structs->flow < 0.0) { /* all flows should be positive, but check */ 03345 sprintf( msgStr, "Day %6.1f: ERROR IN ASSUMPTION OF NO NEG HIST FLOW from cell (%d,%d)", 03346 SimTime.TIME, structs->cell_i_to, structs->cell_j_to); 03347 WriteMsg( msgStr,True ); 03348 return; 03349 } 03350 /* for internal cells, check for excessive historical/model demand */ 03351 if (structs->cell_i_fr != 2 ) 03352 { 03353 03354 cell_vol = SWH[cell_fr] * CELL_SIZE; 03355 if (structs->flow > cell_vol) { /* if hist/other-data demand > cell vol */ 03356 if( debug > 0 ) { 03357 fprintf( canDebugFile, "Day \t%6.1f\t %s:\tTotDemand= \t%7.0f\t; exceeded cell \t(%d,%d)\t vol= \t%7.0f \tby \t%7.0f\t m3.\n", 03358 SimTime.TIME, structs->S_nam, structs->flow, structs->cell_i_fr, structs->cell_j_fr, cell_vol, (structs->flow - cell_vol) ); 03359 03360 } 03361 03362 structs->flow = cell_vol; 03363 } 03364 } 03365 /* CONCENTRATION */ 03366 /* now calculate the nutrient conc in the donor cell */ 03367 /* nut conc in flow from outside system using historical data or 0.0 */ 03368 if (structs->cell_i_fr == 2) { 03369 structs->conc_P = (structs->TPser == 1) ? 03370 Hist_data[structs->histID-1].arrayP[((int)(SimTime.TIME))] : 03371 ((structs->TPser == 0) ? (structs->TP) : (0.0) ); 03372 structs->conc_N = (structs->TNser == 1) ? 03373 Hist_data[structs->histID-1].arrayN[((int)(SimTime.TIME))] : 03374 ((structs->TNser == 0) ? (structs->TN) : (0.0) ); 03375 structs->conc_S = (structs->TSser == 1) ? 03376 Hist_data[structs->histID-1].arrayS[((int)(SimTime.TIME))] : 03377 ((structs->TSser == 0) ? (structs->TS) : (0.0) ); 03378 } 03379 else 03380 { /* nut conc in flow within system - check to see if there are historical concs with the historical flow */ 03381 structs->conc_P = (structs->TPser == -1) ? 03382 ( (SWH[cell_fr] > 0) ? PA[cell_fr]/CELL_SIZE/SWH[cell_fr] : 0.0 ) : 03383 ( (structs->TPser == 0) ? (structs->TP) : (Hist_data[structs->histID-1].arrayP[((int)(SimTime.TIME))] ) ); 03384 structs->conc_N = ( structs->TNser == -1) ? 03385 ( (SWH[cell_fr] > 0) ? NA[cell_fr]/CELL_SIZE/SWH[cell_fr] : 0.0 ) : 03386 ( (structs->TNser == 0) ? (structs->TN) : (Hist_data[structs->histID-1].arrayN[((int)(SimTime.TIME))] ) ); 03387 structs->conc_S = ( structs->TSser == -1) ? 03388 ( (SWH[cell_fr] > 0) ? SA[cell_fr]/CELL_SIZE/SWH[cell_fr] : 0.0 ) : 03389 ( (structs->TSser == 0) ? (structs->TS) : (Hist_data[structs->histID-1].arrayS[((int)(SimTime.TIME))] ) ); 03390 } 03391 /* the nut and water update done after the rule-based flow calcs */ 03392 /* determine mass transfer */ 03393 03394 P_fl = structs->flow * structs->conc_P; 03395 N_fl = structs->flow * structs->conc_N; 03396 S_fl = structs->flow * structs->conc_S; 03397 03398 03399 if (structs->cell_i_to == 2) { /* "to" cell is outside system */ 03400 if (debug > -999) {/* m3 and kg nuts outflow out from the system */ 03401 VOL_OUT_STR[basn[cell_fr]] += structs->flow; /* mass balance */ 03402 VOL_OUT_STR[0] += structs->flow; 03403 P_OUT_STR[basn[cell_fr]] += P_fl; 03404 P_OUT_STR[0] += P_fl; 03405 S_OUT_STR[basn[cell_fr]] += (structs->TSser == -1) ? (S_fl) : (0); /* see below note on tracer application */ 03406 S_OUT_STR[0] += (structs->TSser == -1) ? (S_fl) : (0); /* see below note on tracer application */ 03407 } 03408 PA[cell_fr] -= P_fl; 03409 NA[cell_fr] -= N_fl; 03410 SA[cell_fr] -= (structs->TSser == -1) ? (S_fl) : (0); 03411 /* for the salt (S), we sometimes want to apply a tracer to internal canals/cells. 03412 Thus, in that case, we don't subtract salt from the canal because this is "introduced" salt 03413 that was not calculated from the available water and salt (i.e., the conc. was from the 03414 CanalData.struct data file, either fixed or a time series) */ 03415 /* recalculate the surface water depth in the "from" cell */ 03416 SWH[cell_fr] -= structs->flow/CELL_SIZE; 03417 } 03418 else if (structs->cell_i_fr == 2) { /* "from" cell is outside system */ 03419 if (debug > -999) {/* m3 and kg nuts inflow to the system */ 03420 VOL_IN_STR[basn[cell_to]] += structs->flow; 03421 VOL_IN_STR[0] += structs->flow; 03422 P_IN_STR[basn[cell_to]] += P_fl; 03423 P_IN_STR[0] += P_fl; 03424 S_IN_STR[basn[cell_to]] += S_fl; 03425 S_IN_STR[0] += S_fl; 03426 } 03427 PA[cell_to] += P_fl; 03428 NA[cell_to] += N_fl; 03429 SA[cell_to] += S_fl; 03430 /* recalculate the surface water depth in the "to" cell */ 03431 SWH[cell_to] += structs->flow/CELL_SIZE; 03432 } 03433 else { /* internal cell-cell m3 and kg nuts flow */ 03434 PA[cell_fr] -= P_fl; 03435 NA[cell_fr] -= N_fl; 03436 SA[cell_fr] -= (structs->TSser == -1) ? (S_fl) : (0); 03437 /* for the salt (S), we sometimes want to apply a tracer to internal canals/cells. 03438 Thus, in that case, we don't subtract salt from the cell because this is "introduced" salt 03439 that was not calculated from the available water and salt (i.e., the conc. was from the 03440 CanalData.struct data file, either fixed or a time series) */ 03441 03442 PA[cell_to] += P_fl; 03443 NA[cell_to] += N_fl; 03444 SA[cell_to] += S_fl; 03445 /* recalculate the surface water depth in the interacting cells */ 03446 SWH[cell_fr] -= structs->flow/CELL_SIZE; 03447 SWH[cell_to] += structs->flow/CELL_SIZE; 03448 if (basn[cell_to] != basn[cell_fr] && debug > -999 ) { 03449 VOL_OUT_STR[basn[cell_fr]] += structs->flow; 03450 VOL_IN_STR[basn[cell_to]] += structs->flow; 03451 P_OUT_STR[basn[cell_fr]] += P_fl; 03452 P_IN_STR[basn[cell_to]] += P_fl; 03453 S_OUT_STR[basn[cell_fr]] += (structs->TSser == -1) ? (S_fl) : (0); /* see above note on tracer application */ 03454 S_IN_STR[basn[cell_to]] += S_fl; 03455 03456 /* all structure flows, EXCEPT canal-canal, must be between parent (family) hydro basins */ 03457 if ( (basn_list[basn[cell_fr]]->family == basn_list[basn[cell_to]]->family) && (debug > 0) ) { 03458 sprintf( msgStr, "Day %6.1f: ERROR in basin configuration for structure from cell (%d,%d) to cell (%d,%d): flow must be between diff hydrologic basins", 03459 SimTime.TIME, structs->cell_i_fr,structs->cell_j_fr,structs->cell_i_to,structs->cell_j_to ); 03460 WriteMsg( msgStr,True ); dynERRORnum++; 03461 } 03462 } 03463 03464 } 03465 return; 03466 } /* end of data-driven (historical/sfwmm) cell-cell flows */
void flowData_CanCel | ( | struct Structure * | structs, | |
struct Structure * | struct_hist_start, | |||
float * | SWH, | |||
double * | NA, | |||
double * | PA, | |||
double * | SA | |||
) |
Canal-to-Cell water control structure flows: Data-driven (historical/sfwmm).
SWH | SURFACE_WAT | |
NA | DINdummy | |
PA | TP_SF_WT | |
SA | SALT_SURF_WT |
Definition at line 3528 of file WatMgmt.c.
References Chan::area, HistData::arrayN, HistData::arrayP, HistData::arrayS, HistData::arrayWat, Chan::basin, basn, Structure::canal_fr, Structure::canal_to, canDebugFile, canstep, Structure::cell_i_to, Structure::cell_j_to, CELL_SIZE, Chan_list, CHo, Structure::conc_N, Structure::conc_P, Structure::conc_S, debug, dynERRORnum, Structure::flag, Structure::flow, Hist_data, Structure::histID, MINDEPTH, msgStr, Structure::multiOut, Chan::N, Structure::next_in_list, Chan::number, Chan::P, P_IN_STR, P_OUT_STR, ramp, Chan::S, S_IN_STR, Structure::S_nam, S_OUT_STR, SimTime, Structure::str_cell_i, Structure::str_cell_j, Chan::sumHistIn, Chan::sumHistOut, T, simTime::TIME, Structure::TN, Structure::TNser, Structure::TP, Structure::TPser, True, Structure::TS, Structure::TSser, VOL_IN_STR, VOL_OUT_STR, Chan::wat_depth, and WriteMsg().
Referenced by Flows_in_Structures().
03529 { 03530 int cell_to, can_to, can_fr; 03531 int cell_struct; 03532 double CH_vol; 03533 double Nconc, Pconc, Sconc; 03534 double N_fl, P_fl, S_fl; 03535 double chan_over; 03536 double ChanHistOut; 03537 03538 can_fr = structs->canal_fr - CHo; 03539 cell_to = T(structs->cell_i_to,structs->cell_j_to); 03540 cell_struct = T(structs->str_cell_i,structs->str_cell_j); 03541 03542 03543 /* DATA-DRIVEN STRUCTURE FLOW */ 03544 if (structs->multiOut == 1) return; /* this structure has already been processed as a multiple outflow from a canal */ 03545 03546 structs->flow = Hist_data[structs->histID-1].arrayWat[((int)(SimTime.TIME))]*canstep; 03547 /* don't do much with zero or negative flows */ 03548 if (structs->flow == 0.0) {/* zero the reported struct flow conc (for output info only) */ 03549 structs->conc_P = 0.0; 03550 structs->conc_N = 0.0; 03551 structs->conc_S = 0.0; 03552 return; 03553 } 03554 else if (structs->flow < 0.0) { 03555 sprintf( msgStr, "Day %6.1f: ERROR IN ASSUMPTION OF NO NEG HIST FLOW from cell (%d,%d)", 03556 SimTime.TIME, structs->cell_i_to, structs->cell_j_to ); 03557 WriteMsg( msgStr,True ); dynERRORnum++; 03558 return; 03559 } 03560 03561 /* for multiple historical/other-data outflows from a canal, ensure mass balance (sum of outflows !> avail volume) */ 03562 /* all flows from the canal associated with each set must be non-negative, which is currently valid */ 03563 03564 struct_hist_start = structs; /* this is the first structure w/ historical info for a particular canal */ 03565 ChanHistOut = 0.0; /* sum of all historical outflows from a canal */ 03566 03567 while ( structs != NULL ) 03568 { 03569 if ( structs->flag == 1 && struct_hist_start->canal_fr == structs->canal_fr ) { /* look for outflows from same canal */ 03570 structs->flow = Hist_data[structs->histID-1].arrayWat[((int)(SimTime.TIME))]*canstep; 03571 ChanHistOut += structs->flow; /* sum the multiple historical outflows from canal */ 03572 } 03573 03574 structs = structs->next_in_list; /* increment to next structure */ 03575 } /* end cycle thru list of remaining structures in total list */ 03576 03577 structs = struct_hist_start; /* now we are pointing back to the first (or only) water control structure draining the canal */ 03578 03579 /* concentration in donor canal for structure flow, g/L = kg/m^3 */ 03580 /* this is based on previous depth/volume calc'd in FluxChannel */ 03581 /* or use historical conc */ 03582 /* canal TOTAL volume before new structure flows */ 03583 CH_vol = Chan_list[can_fr]->area*Chan_list[can_fr]->wat_depth; 03584 /* concentrations applied to all structures draining this canal */ 03585 Pconc = (structs->TPser == -1) ? 03586 ( (CH_vol>0) ? (Chan_list[can_fr]->P/CH_vol) : (0.0) ) : 03587 ( (structs->TPser == 0) ? (structs->TP) : (Hist_data[structs->histID-1].arrayP[((int)(SimTime.TIME))] ) ) ; 03588 Nconc = (structs->TNser == -1) ? 03589 ( (CH_vol>0) ? (Chan_list[can_fr]->N/CH_vol) : (0.0) ) : 03590 ( (structs->TNser == 0) ? (structs->TN) : (Hist_data[structs->histID-1].arrayN[((int)(SimTime.TIME))] ) ) ; 03591 Sconc = (structs->TSser == -1) ? 03592 ( (CH_vol>0) ? (Chan_list[can_fr]->S/CH_vol) : (0.0) ) : 03593 ( (structs->TSser == 0) ? (structs->TS) : (Hist_data[structs->histID-1].arrayS[((int)(SimTime.TIME))] ) ) ; 03594 03595 /* vol avail for fluxing */ 03596 CH_vol = Chan_list[can_fr]->area*(ramp(Chan_list[can_fr]->wat_depth-MINDEPTH) ); 03597 chan_over = (ChanHistOut > 0.0 ) ? ( CH_vol/ChanHistOut ) : 1.0; 03598 03599 do /* loop again through the remaining sequence of structures to correct any outflows for the canal */ 03600 { 03601 if ( structs->flag == 1 && struct_hist_start->canal_fr == structs->canal_fr ) { 03602 03603 structs->multiOut = 1; /* flag to indicate this structure has been processed (below) */ 03604 03605 /* revised FLOW */ 03606 if ( chan_over < 1.0 ) { /* if hist/other-data demand > canal vol */ 03607 if( debug > 0 ) { 03608 fprintf( canDebugFile, "Day \t%6.1f\t %s:\tTotDemand= \t%7.0f\t; exceeded chan \t%d\t avail vol= \t%7.0f\t by \t%7.0f\t m3 (\t%5.3f\t m deep).\n", 03609 SimTime.TIME, structs->S_nam, ChanHistOut, Chan_list[can_fr]->number, 03610 CH_vol, (ChanHistOut - CH_vol), Chan_list[can_fr]->wat_depth ); 03611 03612 } 03613 /* decrement the individual structure outflows by it's proportional contrib. */ 03614 structs->flow = (structs->flow) * chan_over ; 03615 } 03616 /* sum of all realized (corrected for excess demand) historical/other-data outflows from a canal during an iteration */ 03617 /* used to determine any allowable rule-based canal flows after the historical/other-data demands */ 03618 Chan_list[can_fr]->sumHistOut += structs->flow; 03619 03620 /* the recipient changes as we cycle thru the structures (may be another cell or a canal) */ 03621 can_to = structs->canal_to - CHo; 03622 cell_to = T(structs->cell_i_to,structs->cell_j_to); 03623 03624 structs->conc_P = Pconc;/* concentrations applied to all structures draining this canal */ 03625 structs->conc_N = Nconc; 03626 structs->conc_S = (structs->TSser == -1) ? 03627 (Sconc) : 03628 ( (structs->TSser == 0) ? (structs->TS) : 03629 ( Hist_data[structs->histID-1].arrayS[((int)(SimTime.TIME))] ) ); /* see note below on tracer conc. application */ 03630 03631 P_fl = structs->flow * structs->conc_P; 03632 N_fl = structs->flow * structs->conc_N; 03633 S_fl = structs->flow * structs->conc_S; 03634 /* change in nut mass in fr canal (kg) */ 03635 Chan_list[can_fr]->N -= N_fl ; 03636 Chan_list[can_fr]->P -= P_fl ; 03637 Chan_list[can_fr]->S -= (structs->TSser == -1) ? (S_fl) : (0); 03638 /* for the salt (S), we sometimes want to apply a tracer to internal canals/cells. 03639 Thus, in that case, we don't subtract salt from the canal because this is "introduced" salt 03640 that was not calculated from the available water and salt (i.e., the conc. was from the 03641 CanalData.struct data file, either fixed or a time series) */ 03642 03643 if (can_to > 0) { /* IF this is a canal recip, change in nut mass in to canal (kg) */ 03644 /* sum of all realized (corrected for excess demand) historical/other-data outflows into a canal during an iteration */ 03645 /* used to determine any allowable rule-based canal flows after the historical/other-data demands */ 03646 Chan_list[can_to]->sumHistIn += structs->flow; 03647 03648 Chan_list[can_to]->N += N_fl ; 03649 Chan_list[can_to]->P += P_fl ; 03650 Chan_list[can_to]->S += S_fl ; 03651 /* mass balance in fr and to canals */ 03652 if (Chan_list[can_fr]->basin != Chan_list[can_to]->basin && debug > -999 ) { 03653 VOL_OUT_STR[Chan_list[can_fr]->basin] += structs->flow; 03654 VOL_IN_STR[Chan_list [can_to]->basin] += structs->flow; 03655 P_OUT_STR[Chan_list[can_fr]->basin] += P_fl; 03656 P_IN_STR[Chan_list [can_to]->basin] += P_fl; 03657 S_OUT_STR[Chan_list[can_fr]->basin] += (structs->TSser == -1) ? (S_fl) : (0); /* see above note on tracer application */ 03658 S_IN_STR[Chan_list [can_to]->basin] += S_fl; 03659 } 03660 } 03661 else if (cell_to > 0) { 03662 /* OR change in nut mass in downstream cell (kg) */ 03663 03664 if (structs->cell_i_to > 2 ) { /* to an on-map cell */ 03665 SWH[cell_to] += structs->flow/CELL_SIZE; 03666 PA[cell_to] += P_fl; 03667 NA[cell_to] += N_fl; 03668 SA[cell_to] += S_fl; 03669 /* mass balance in fr canal and to cell */ 03670 if (Chan_list[can_fr]->basin != basn[cell_to] && debug > -999 ) { 03671 VOL_OUT_STR[Chan_list[can_fr]->basin] += structs->flow; 03672 VOL_IN_STR[basn[cell_to]] += structs->flow; 03673 P_OUT_STR[Chan_list[can_fr]->basin] += P_fl; 03674 P_IN_STR[basn[cell_to]] += P_fl; 03675 S_OUT_STR[Chan_list[can_fr]->basin] += (structs->TSser == -1) ? (S_fl) : (0); /* see above note on tracer application */ 03676 S_IN_STR[basn[cell_to]] += S_fl; 03677 03678 /* all structure flows, EXCEPT canal-canal, must be between parent (family) hydro basins */ 03679 // v2.8.4 if ( (Chan_list[can_fr]->family == basn_list[basn[cell_to]]->family) && (debug > 0) ) { 03680 // sprintf( msgStr, "Day %6.1f: ERROR in basin configuration for structure from chan %d to cell (%d,%d): flow must be between diff hydrologic basins", 03681 // SimTime.TIME, Chan_list[can_fr]->number,structs->cell_i_to,structs->cell_j_to ); 03682 // WriteMsg( msgStr,True ); dynERRORnum++; 03683 // } 03684 } 03685 } 03686 else if (structs->cell_i_to == 2 && debug > -999 ) { /* to off-map cell, mass balance check */ 03687 VOL_OUT_STR[Chan_list[can_fr]->basin] += structs->flow; 03688 VOL_OUT_STR[0] += structs->flow; 03689 P_OUT_STR[Chan_list[can_fr]->basin] += P_fl; 03690 P_OUT_STR[0] += P_fl; 03691 S_OUT_STR[Chan_list[can_fr]->basin] += (structs->TSser == -1) ? (S_fl) : (0); /* see above note on tracer application */ 03692 S_OUT_STR[0] += (structs->TSser == -1) ? (S_fl) : (0); /* see above note on tracer application */ 03693 } 03694 } 03695 /* don't do much with zero or negative flows */ 03696 if (structs->flow == 0.0) { 03697 structs->conc_P = 0.0; 03698 structs->conc_N = 0.0; 03699 structs->conc_S = 0.0; 03700 } /* for output purposes only, zero the reported conc */ 03701 else if (structs->flow < 0.0) { 03702 sprintf( msgStr, "Day %6.1f: ERROR IN ASSUMPTION OF NO NEG HIST FLOW from another chan/cell into chan %d", 03703 SimTime.TIME, Chan_list[can_fr]->number ); 03704 WriteMsg( msgStr,True ); dynERRORnum++; 03705 } 03706 } 03707 03708 structs = structs->next_in_list; 03709 } while (structs != NULL); /* cycling to the end of the list again !!!! */ 03710 03711 structs = struct_hist_start; /* now pointing back to the first historical outflow structure that we dealt with */ 03712 03713 03714 return; 03715 03716 } /* end of data-driven (historical/sfwmm) canal-cell flows */
void flowData_CelCan | ( | struct Structure * | structs, | |
float * | SWH, | |||
double * | NA, | |||
double * | PA, | |||
double * | SA | |||
) |
Cell-to-Canal water control structure flows: Data-driven (historical/sfwmm).
SWH | SURFACE_WAT | |
NA | DINdummy | |
PA | TP_SF_WT | |
SA | SALT_SURF_WT |
Definition at line 3907 of file WatMgmt.c.
References HistData::arrayN, HistData::arrayP, HistData::arrayS, HistData::arrayWat, Chan::basin, basn, basn_list, Structure::canal_to, canDebugFile, canstep, Structure::cell_i_fr, Structure::cell_j_fr, CELL_SIZE, Chan_list, CHo, Structure::conc_N, Structure::conc_P, Structure::conc_S, debug, dynERRORnum, Structure::flow, Hist_data, Structure::histID, msgStr, Structure::multiOut, Chan::N, Chan::number, Chan::P, P_IN_STR, P_OUT_STR, Chan::S, S_IN_STR, Structure::S_nam, S_OUT_STR, SimTime, Structure::str_cell_i, Structure::str_cell_j, Chan::sumHistIn, T, simTime::TIME, Structure::TN, Structure::TNser, Structure::TP, Structure::TPser, True, Structure::TS, Structure::TSser, VOL_IN_STR, VOL_OUT_STR, and WriteMsg().
Referenced by Flows_in_Structures().
03908 { 03909 int cell_fr, can_to; 03910 int cell_struct; 03911 double cell_vol; 03912 double N_fl, P_fl, S_fl; 03913 03914 can_to = structs->canal_to - CHo; 03915 cell_fr = T(structs->cell_i_fr,structs->cell_j_fr); 03916 cell_struct = T(structs->str_cell_i,structs->str_cell_j); 03917 03918 /* DATA-DRIVEN STRUCTURE FLOW */ 03919 03920 if (structs->multiOut == 1) { 03921 sprintf( msgStr, "Day %6.1f: ERROR IN ASSUMPTION OF NO NEG HIST FLOW from chan %d", 03922 SimTime.TIME, Chan_list[can_to]->number ); 03923 WriteMsg( msgStr,True ); dynERRORnum++; 03924 return; /* this structure has already been processed as a multiple outflow from a canal */ 03925 } 03926 03927 structs->flow = Hist_data[structs->histID-1].arrayWat[((int)(SimTime.TIME))]*canstep; 03928 /* don't do much with zero or negative flows */ 03929 if (structs->flow == 0.0) { 03930 structs->conc_P = 0.0; 03931 structs->conc_N = 0.0; 03932 structs->conc_S = 0.0; 03933 return; 03934 } 03935 else if (structs->flow <0) { 03936 sprintf( msgStr, "Day %6.1f: ERROR IN ASSUMPTION OF NO NEG HIST FLOW from chan %d", 03937 SimTime.TIME, Chan_list[can_to]->number ); 03938 WriteMsg( msgStr,True ); dynERRORnum++; 03939 return; 03940 } 03941 03942 if (structs->cell_i_fr != 2 ) /* cell (2,2) == (1,1) in maps, not in model domain */ 03943 { 03944 03945 cell_vol = SWH[cell_fr] * CELL_SIZE; 03946 if (structs->flow > cell_vol) { 03947 if( debug > 0 ) { 03948 fprintf( canDebugFile, "Day \t%6.1f\t %s:\tTotDemand= \t%7.0f\t; exceeded cell \t(%d,%d)\t vol= \t%7.0f\t by \t%7.0f\t m3.\n", 03949 SimTime.TIME, structs->S_nam, structs->flow, structs->cell_i_fr, structs->cell_j_fr, cell_vol, (structs->flow - cell_vol) ); 03950 03951 } 03952 structs->flow = cell_vol; 03953 }} 03954 /* calculate the nutrient conc in the donor cell */ 03955 /* nut conc in flow from outside system using historical data or 0.0 */ 03956 if (structs->cell_i_fr == 2) { 03957 structs->conc_P = (structs->TPser == 1) ? 03958 Hist_data[structs->histID-1].arrayP[((int)(SimTime.TIME))] : 03959 ((structs->TPser == 0) ? (structs->TP) : (0.0) ); 03960 structs->conc_N = (structs->TNser == 1) ? 03961 Hist_data[structs->histID-1].arrayN[((int)(SimTime.TIME))] : 03962 ((structs->TNser == 0) ? (structs->TN) : (0.0) ); 03963 structs->conc_S = (structs->TSser == 1) ? 03964 Hist_data[structs->histID-1].arrayS[((int)(SimTime.TIME))] : 03965 ((structs->TSser == 0) ? (structs->TS) : (0.0) ); 03966 } 03967 else 03968 { /* nut conc in flow within system - check to see if there are historical concs with the historical flow */ 03969 structs->conc_P = (structs->TPser == -1) ? 03970 ( (SWH[cell_fr] > 0) ? PA[cell_fr]/CELL_SIZE/SWH[cell_fr] : 0.0 ) : 03971 ( (structs->TPser == 0) ? (structs->TP) : (Hist_data[structs->histID-1].arrayP[((int)(SimTime.TIME))] ) ); 03972 structs->conc_N = ( structs->TNser == -1) ? 03973 ( (SWH[cell_fr] > 0) ? NA[cell_fr]/CELL_SIZE/SWH[cell_fr] : 0.0 ) : 03974 ( (structs->TNser == 0) ? (structs->TN) : (Hist_data[structs->histID-1].arrayN[((int)(SimTime.TIME))] ) ); 03975 structs->conc_S = ( structs->TSser == -1) ? 03976 ( (SWH[cell_fr] > 0) ? SA[cell_fr]/CELL_SIZE/SWH[cell_fr] : 0.0 ) : 03977 ( (structs->TSser == 0) ? (structs->TS) : (Hist_data[structs->histID-1].arrayS[((int)(SimTime.TIME))] ) ); 03978 } 03979 /* now determine the nutrient mass (kg) flow from cell to canal */ 03980 /* 1000 is to convert g/m3 to kg */ 03981 P_fl = structs->flow * structs->conc_P; 03982 N_fl = structs->flow * structs->conc_N; 03983 S_fl = structs->flow * structs->conc_S; 03984 if (structs->cell_i_fr == 2 ) {/* "from" cell is outside system */ 03985 if (debug > -999) { 03986 VOL_IN_STR[Chan_list[can_to]->basin] += structs->flow; /* mass balance */ 03987 VOL_IN_STR[0] += structs->flow; 03988 P_IN_STR[Chan_list[can_to]->basin] += P_fl; 03989 P_IN_STR[0] += P_fl; 03990 S_IN_STR[Chan_list[can_to]->basin] += S_fl; 03991 S_IN_STR[0] += S_fl; 03992 } } 03993 else { /* internal cell-> canal flow */ 03994 SWH[cell_fr] -= structs->flow/CELL_SIZE; 03995 PA[cell_fr] -= P_fl; 03996 NA[cell_fr] -= N_fl; 03997 SA[cell_fr] -= (structs->TSser == -1) ? (S_fl) : (0); 03998 /* for the salt (S), we sometimes want to apply a tracer to internal canals/cells. 03999 Thus, in that case, we don't subtract salt from the canal because this is "introduced" salt 04000 that was not calculated from the available water and salt (i.e., the conc. was from the 04001 CanalData.struct data file, either fixed or a time series) */ 04002 /* mass balance in fr cell and to canal */ 04003 if (basn[cell_fr] != Chan_list[can_to]->basin && debug > -999 ) { 04004 VOL_OUT_STR[basn[cell_fr]] += structs->flow; 04005 VOL_IN_STR[Chan_list[can_to]->basin] += structs->flow; 04006 P_OUT_STR[basn[cell_fr]] += P_fl; 04007 P_IN_STR[Chan_list[can_to]->basin] += P_fl; 04008 S_OUT_STR[basn[cell_fr]] += (structs->TSser == -1) ? (S_fl) : (0); /* see above note on tracer application */ 04009 S_IN_STR[Chan_list[can_to]->basin] += S_fl; 04010 04011 /* all structure flows, EXCEPT canal-canal, must be between parent (family) hydro basins */ 04012 if ( (Chan_list[can_to]->family == basn_list[basn[cell_fr]]->family) && (debug > 0) ) { 04013 sprintf( msgStr, "Day %6.1f: ERROR in basin configuration for structure from cell (%d,%d) to chan %d: flow must be between diff hydrologic basins", 04014 SimTime.TIME, structs->cell_i_fr, structs->cell_j_fr, Chan_list[can_to]->number ); 04015 WriteMsg( msgStr,True ); dynERRORnum++; 04016 } 04017 } 04018 } 04019 04020 /* sum of all realized (corrected for excess demand) historical/other-data outflows into a canal during an iteration */ 04021 /* used to determine any allowable rule-based canal flows after the historical/other-data demands */ 04022 Chan_list[can_to]->sumHistIn += structs->flow; 04023 04024 /* change in nut mass in "to" canal (kg) */ 04025 Chan_list[can_to]->N += N_fl ; 04026 Chan_list[can_to]->P += P_fl ; 04027 Chan_list[can_to]->S += S_fl ; 04028 return; 04029 04030 } /* end of data-driven (historical/sfwmm) cell-canal flows */
void flowCalc_CanCan | ( | struct Structure * | structs, | |
float * | SWH, | |||
float * | GW, | |||
float * | poros, | |||
float * | Elev, | |||
double * | NA, | |||
double * | PA, | |||
double * | SA | |||
) |
Canal-to-Canal water control structure flows: Calculated.
SWH | SURFACE_WAT | |
GW | SAT_WATER | |
poros | HP_HYD_POROSITY | |
Elev | SED_ELEV | |
NA | DINdummy | |
PA | TP_SF_WT | |
SA | SALT_SURF_WT |
TODO - put in place the CanalData.struct reading checks to ensure the conditions described above are met.
Definition at line 3156 of file WatMgmt.c.
References Abs, Chan::area, Structure::canal_fr, Structure::canal_to, canstep, Structure::cell_HW, Structure::cell_TW, Chan_list, CHo, Structure::conc_N, Structure::conc_P, Structure::conc_S, debug, Chan::depth, dynERRORnum, Structure::flagHWsched, Structure::flagTWsched, Structure::flow, GP_MinCheck, HAB, Structure::HW_stage, Min, MINDEPTH, msgStr, Chan::N, Chan::number, Chan::P, P, ramp, Chan::S, Structure::S_nam, SimTime, Structure::str_cell_i, Structure::str_cell_j, Chan::sumHistIn, Chan::sumHistOut, Chan::sumRuleIn, Chan::sumRuleOut, T, simTime::TIME, True, Structure::TW_stage, usrErr(), Structure::w_coef, Chan::wat_depth, and WriteMsg().
Referenced by Flows_in_Structures().
03158 { 03159 int can_to, can_fr; 03160 int cell_struct; 03161 float HeadH, HeadT, HeadH2, HeadT2; 03162 double CH_vol; 03163 double N_fl, P_fl, S_fl; 03164 float HeadH_drop, HeadT_drop; 03165 03166 float HWcheck, TWcheck, HWdiff, TWdiff; /* v2.8 */ 03167 int struct_open; 03168 03169 can_fr = structs->canal_fr - CHo; 03170 can_to = structs->canal_to - CHo; 03171 cell_struct = T(structs->str_cell_i,structs->str_cell_j); 03172 03173 /* VIRTUAL STRUCTURE FLOW */ 03174 if ( structs->w_coef == 0.0) {/* check for a virtual structure, flow only in pos direction */ 03175 HeadH_drop = 0.5 * Abs(Chan_list[can_fr]->elev_drop); /* Head_drops are midpoints of elevation difference between begin&end of canal reaches */ 03176 HeadT_drop = 0.5 * Abs(Chan_list[can_to]->elev_drop); 03177 /* v2.8 - added the sumRuleIn and sumRuleOut */ 03178 /* in both head and tail, add net historical/other-data flows before determining hydraulic potential */ 03179 HeadH = HeadH_drop + /* add portion of the elevation drop along the canal length */ 03180 Elev[cell_struct] - Chan_list[can_fr]->depth + Chan_list[can_fr]->wat_depth 03181 + (Chan_list[can_fr]->sumHistIn - Chan_list[can_fr]->sumHistOut)/Chan_list[can_fr]->area 03182 + (Chan_list[can_fr]->sumRuleIn - Chan_list[can_fr]->sumRuleOut)/Chan_list[can_fr]->area; 03183 /* OLD COMMENT: in tailwater only, check to see if other virtual struct has added water already, add to head */ 03184 HeadT = -HeadT_drop + /* subtract portion of the elevation drop along the canal length */ 03185 Elev [cell_struct] - Chan_list[can_to]->depth + Chan_list[can_to]->wat_depth 03186 + (Chan_list[can_to]->sumHistIn - Chan_list[can_to]->sumHistOut)/Chan_list[can_to]->area 03187 + (Chan_list[can_to]->sumRuleIn - Chan_list[can_to]->sumRuleOut)/Chan_list[can_to]->area; 03188 03189 if ( HeadH>HeadT ) { 03190 structs->flow = 03191 Chan_list[can_fr]->area*Chan_list[can_to]->area/ 03192 (Chan_list[can_fr]->area+Chan_list[can_to]->area) * (HeadH-HeadT) ; 03193 if (debug >3) { 03194 HeadH2 = HeadH - structs->flow/Chan_list[can_fr]->area; 03195 HeadT2 = HeadT + structs->flow/Chan_list[can_to]->area; 03196 sprintf( msgStr, "Day %6.1f: virtual flow from chan %d (%f m) to chan %d, New headH-headT=%f, Orig HeadH-HeadT=%f", 03197 SimTime.TIME,Chan_list[can_fr]->number,HeadH-Elev[cell_struct]+Chan_list[can_fr]->depth, 03198 Chan_list[can_to]->number,(HeadH2-HeadT2),(HeadH-HeadT) ); 03199 WriteMsg( msgStr,True ); 03200 if (Abs(HeadH2 - HeadT2) > GP_MinCheck) /* virtual flows should exactly equilibrate the two canals */ 03201 { sprintf( msgStr, "Day %6.1f: ERROR virtual flow from chan %d to chan %d, New headH-headT=%f, Orig HeadH-HeadT=%f", 03202 SimTime.TIME,Chan_list[can_fr]->number,Chan_list[can_to]->number,(HeadH2-HeadT2),(HeadH-HeadT) ); 03203 WriteMsg( msgStr,True ); dynERRORnum++; } 03204 03205 } 03206 03207 CH_vol = Chan_list[can_fr]->area* ramp((HeadH-HeadH_drop)-Elev[cell_struct]+Chan_list[can_fr]->depth-MINDEPTH); /* avail flow volume */ 03208 if (structs->flow > CH_vol) { 03209 structs->flow = CH_vol; 03210 HeadH2 = HeadH - structs->flow/Chan_list[can_fr]->area; 03211 HeadT2 = HeadT + structs->flow/Chan_list[can_to]->area; 03212 if (debug>3 && Abs(HeadH2 - HeadT2) > GP_MinCheck) { 03213 sprintf( msgStr, "Day %6.1f: Warning: stage didn't equilibrate in modified virtual struct flow from chan %d (%f m) to chan %d, New headH-headT=%f, Orig HeadH-HeadT=%f", 03214 SimTime.TIME,Chan_list[can_fr]->number,CH_vol/Chan_list[can_fr]->area,Chan_list[can_to]->number,(HeadH2-HeadT2),(HeadH-HeadT) ); 03215 WriteMsg( msgStr,True ); } 03216 } 03217 03218 /* revise volume to be TOTAL volume for conc calc */ 03219 CH_vol = CH_vol + MINDEPTH*Chan_list[can_fr]->area; 03220 /* conc in donor (fr) canal (kg/m3) */ 03221 structs->conc_P = (CH_vol>0) ? (Chan_list[can_fr]->P/CH_vol) : (0.0); 03222 structs->conc_N = (CH_vol>0) ? (Chan_list[can_fr]->N/CH_vol) : (0.0); 03223 structs->conc_S = (CH_vol>0) ? (Chan_list[can_fr]->S/CH_vol) : (0.0); 03224 } 03225 03226 else structs->flow = 0.0; /* when HeadH is not greater than HeadTailwater */ 03227 03228 } 03229 03230 03231 /* RULE-BASED STRUCTURE FLOW */ 03232 else /* a non-zero w_coef indicates a flow calc based on management rules */ 03233 { 03234 if ( (structs->flagTWsched != 1) || (structs->flagHWsched != 1) ) { 03235 sprintf (msgStr,"\nYou must assign both Headwater and Tailwater schedules for the rule-based canal-to-canal structure %s!\n", structs->S_nam); 03236 usrErr( msgStr ); 03237 exit(-1); 03238 } 03239 if ( (structs->cell_HW == 0) || (structs->cell_TW == 0) ) { 03240 sprintf (msgStr,"\nYou must assign cells to check for both the Headwater and Tailwater schedules for the rule-based canal-to-canal structure %s!\n", structs->S_nam); 03241 usrErr( msgStr ); 03242 exit(-1); 03243 } 03244 03245 struct_open = 0; /* the structure is closed, prior to making any checks of remote cell stages relative to their targets */ 03246 03247 /* headwater and tailwater checks are not at the source and the destination of any potential flow, but are at remote cells: 03248 thus any flow from this schedule will not be head-tail based, but is considered 03249 to be from a pump whose rate of pumping is dependent on the degree to which stage in the remote cells are approaching targets */ 03250 HWcheck = GW[structs->cell_HW]/poros[HAB[structs->cell_HW]] + SWH[structs->cell_HW] ; 03251 TWcheck = GW[structs->cell_TW]/poros[HAB[structs->cell_TW]] + SWH[structs->cell_TW] ; 03252 03253 03254 struct_open = ( (structs->TW_stage > TWcheck) && (structs->HW_stage < HWcheck) ) ? (1) : (0); 03255 03256 if ( struct_open == 1) 03257 { 03258 HWdiff = HWcheck - structs->HW_stage; 03259 TWdiff = structs->TW_stage - TWcheck; 03260 CH_vol = Chan_list[can_fr]->area * ramp(Chan_list[can_fr]->wat_depth-MINDEPTH); /* avail flow volume */ 03261 structs->flow = Min(structs->w_coef * ( HWdiff+TWdiff ) * canstep, CH_vol ); 03262 } 03263 else structs->flow = 0.0; 03264 03265 03266 } /* end of management rule based flow calcs */ 03267 03268 /* don't do much with zero or negative rule-based flows */ 03269 if (structs->flow == 0.0) { 03270 structs->conc_P = 0.0; 03271 structs->conc_N = 0.0; 03272 structs->conc_S = 0.0; 03273 return; 03274 } /* for output purposes only, zero the reported conc */ 03275 else if (structs->flow < 0.0 && structs->w_coef != 0) { 03276 sprintf( msgStr, "Day %6.1f: ERROR IN ASSUMPTION OF NO NEG RULE-BASED FLOW from chan %d", 03277 SimTime.TIME,Chan_list[can_to]->number); 03278 WriteMsg( msgStr,True ); 03279 return; 03280 } 03281 03282 /* revise volume to be TOTAL volume for conc calc */ 03283 CH_vol = CH_vol + MINDEPTH*Chan_list[can_fr]->area; 03284 /* conc in donor (fr) canal (kg/m3) */ 03285 structs->conc_P = (CH_vol>0) ? (Chan_list[can_fr]->P/CH_vol) : (0.0); 03286 structs->conc_N = (CH_vol>0) ? (Chan_list[can_fr]->N/CH_vol) : (0.0); 03287 structs->conc_S = (CH_vol>0) ? (Chan_list[can_fr]->S/CH_vol) : (0.0); 03288 03289 03290 /* increment the sum of rule-based inflows/outflows to canals 03291 for potential multiple virtual inflows into some canals */ 03292 Chan_list[can_fr]->sumRuleOut += structs->flow; 03293 Chan_list[can_to]->sumRuleIn += structs->flow; 03294 03295 /* nut flows */ 03296 P_fl = structs->flow * structs->conc_P; 03297 N_fl = structs->flow * structs->conc_N; 03298 S_fl = structs->flow * structs->conc_S; 03299 /* change in nut mass in fr canal (kg) */ 03300 Chan_list[can_fr]->N -= N_fl ; 03301 Chan_list[can_fr]->P -= P_fl ; 03302 Chan_list[can_fr]->S -= S_fl ; 03303 /* change in nut mass in to canal (kg) */ 03304 Chan_list[can_to]->N += N_fl ; 03305 Chan_list[can_to]->P += P_fl ; 03306 Chan_list[can_to]->S += S_fl ; 03307 /* mass balance in fr and to canals */ 03308 /* virtual structure flows can not (by definition) establish flow among basins */ 03309 if (Chan_list[can_fr]->basin != Chan_list[can_to]->basin && debug > 0 ) { 03310 sprintf( msgStr, "Day %6.1f: ERROR - no hydrologic basin-basin flows in canal-to-canal structure, canals %d - %d", 03311 SimTime.TIME, Chan_list[can_to]->number, Chan_list[can_fr]->number); 03312 WriteMsg( msgStr,True ); dynERRORnum++; 03313 } 03314 03315 } /* end of calculated canal-canal flows */
void flowCalc_CelCel | ( | struct Structure * | structs, | |
float * | SWH, | |||
float * | Elev, | |||
double * | NA, | |||
double * | PA, | |||
double * | SA | |||
) |
Cell-to-Cell water control structure flows: Calculated (rule-based).
SWH | SURFACE_WAT | |
Elev | SED_ELEV | |
NA | DINdummy | |
PA | TP_SF_WT | |
SA | SALT_SURF_WT |
Definition at line 3481 of file WatMgmt.c.
References Structure::cell_i_fr, Structure::cell_i_to, Structure::cell_j_fr, Structure::cell_j_to, CELL_SIZE, Structure::conc_P, Structure::conc_S, Structure::flow, Flux_SWcells(), Flux_SWstuff(), MCopen, SF_WT_VEL_mag, T, and Structure::w_coef.
Referenced by Flows_in_Structures().
03482 { 03483 int cell_to, cell_fr; 03484 03485 double cell_vol; 03486 double N_fl, P_fl, S_fl; 03487 float FFlux; 03488 extern float *SF_WT_VEL_mag; 03489 03490 cell_to = T(structs->cell_i_to,structs->cell_j_to); 03491 cell_fr = T(structs->cell_i_fr,structs->cell_j_fr); 03492 03493 /* RULE-BASED STRUCTURE FLOW */ 03494 if ( structs->w_coef != 0.0) {/* check for a virtual structure */ 03495 printf ("\nSorry - no rule-based cell-cell flows in this model version!\n"); exit(-1); 03496 } 03497 else { 03498 /* UN-RULEY, calculated STRUCTURE FLOW */ 03499 /* special case of calc'd flow, cell-cell, using the functions defined in Fluxes.c for overland flow. 03500 This is used ONLY for grid-cell wide overland flows under/through bridges in this version */ 03501 /* MCopen is a (whole array) of a single Manning's coef that are initialized at an open-water value */ 03502 FFlux = Flux_SWcells(structs->cell_i_fr,structs->cell_j_fr, 03503 structs->cell_i_to,structs->cell_j_to,SWH,Elev,MCopen); 03504 /* flow may be negative */ 03505 /* FFlux units = m */ 03506 structs->flow = FFlux*CELL_SIZE; 03507 structs->conc_P = (SWH[cell_fr] > 0) ? PA[cell_fr]/CELL_SIZE/SWH[cell_fr] : 0.0 ; 03508 /* structs->conc_N = (SWH[cell_fr] > 0) ? NA[cell_fr]/CELL_SIZE/SWH[cell_fr] : 0.0 ; */ 03509 structs->conc_S = (SWH[cell_fr] > 0) ? SA[cell_fr]/CELL_SIZE/SWH[cell_fr] : 0.0 ; 03510 03511 if (FFlux != 0.0) Flux_SWstuff ( structs->cell_i_fr,structs->cell_j_fr, 03512 structs->cell_i_to,structs->cell_j_to,FFlux,SWH,SA,NA,PA,SF_WT_VEL_mag); 03513 03514 03515 } 03516 } /* end of calculated cell-cell flows */
void flowCalc_CanCel | ( | struct Structure * | structs, | |
float * | SWH, | |||
float * | GW, | |||
float * | poros, | |||
float * | Elev, | |||
double * | NA, | |||
double * | PA, | |||
double * | SA | |||
) |
Canal-to-Cell water control structure flows: Calculated (rule-based).
SWH | SURFACE_WAT | |
GW | SAT_WATER | |
poros | HP_HYD_POROSITY | |
Elev | SED_ELEV | |
NA | DINdummy | |
PA | TP_SF_WT | |
SA | SALT_SURF_WT |
TODO - put in place the CanalData.struct reading checks to ensure the conditions described above are met.
Definition at line 3747 of file WatMgmt.c.
References Chan::area, Chan::basin, basn, boundcond_depth, Structure::canal_fr, canstep, Structure::cell_HW, Structure::cell_i_to, Structure::cell_i_TW, Structure::cell_j_to, Structure::cell_j_TW, CELL_SIZE, Chan_list, CHo, Structure::conc_N, Structure::conc_P, Structure::conc_S, debug, Chan::depth, dynERRORnum, Chan::elev_avg, Structure::flagHWsched, Structure::flagTWsched, Structure::flow, HAB, Structure::HW_stage, Min, MINDEPTH, msgStr, Chan::N, Chan::P, P, P_IN_STR, P_OUT_STR, ramp, Chan::S, S_IN_STR, Structure::S_nam, S_OUT_STR, SimTime, Structure::str_cell_i, Structure::str_cell_j, Chan::sumHistIn, Chan::sumHistOut, Chan::sumRuleOut, T, simTime::TIME, True, Structure::TW_stage, usrErr(), VOL_IN_STR, VOL_OUT_STR, Structure::w_coef, Chan::wat_depth, and WriteMsg().
Referenced by Flows_in_Structures().
03749 { 03750 int cell_to, can_fr; 03751 int cell_struct; 03752 float HeadH, HeadT; 03753 double CH_vol; 03754 double N_fl, P_fl, S_fl; 03755 float flow_rev; 03756 03757 /* from unitmod.h */ 03758 extern float* boundcond_depth; /* depth in external cells */ 03759 03760 float HWcheck, TWcheck, Hdiff; /* v2.8 */ 03761 int struct_open; 03762 03763 /* RULE-BASED STRUCTURE FLOW */ 03764 can_fr = structs->canal_fr - CHo; 03765 cell_to = T(structs->cell_i_to,structs->cell_j_to); 03766 cell_struct = T(structs->str_cell_i,structs->str_cell_j); 03767 03768 if (structs->cell_i_to != 2 ) { 03769 sprintf( msgStr, "ERROR in flow configuration for %s structure : this rule-based flow is restricted to outflow from the model domain.", 03770 structs->S_nam ); 03771 usrErr( msgStr ); exit(-1); 03772 } 03773 if (structs->flagTWsched == 1 && structs->flagHWsched == 1 ) { 03774 sprintf( msgStr, "ERROR in flow configuration for %s structure : this rule-based flow can not have both HeadWater and TailWater Schedules.", 03775 structs->S_nam ); 03776 usrErr( msgStr); exit(-1); 03777 } 03778 if ( structs->flagHWsched != 1 && structs->flagTWsched != 1 && structs->cell_i_TW == 0 ) { 03779 sprintf( msgStr, "ERROR in flow configuration for %s structure : without a head or tail water schedule, this rule-based flow must have a tailwater-check-cell defined (to acquire data from the boundary-condition model).", 03780 structs->S_nam ); 03781 usrErr( msgStr ); exit(-1); 03782 } 03783 /* v2.8 - added the sumRuleIn and sumRuleOut */ 03784 /* v2.8 - change HeadH from "Elev [cell_struct] -" ... to "Chan_list[can_fr]->elev_avg -" ... */ 03785 03786 HeadH = Chan_list[can_fr]->elev_avg - Chan_list[can_fr]->depth + Chan_list[can_fr]->wat_depth 03787 + (Chan_list[can_fr]->sumHistIn - Chan_list[can_fr]->sumHistOut)/Chan_list[can_fr]->area 03788 + (Chan_list[can_fr]->sumRuleIn - Chan_list[can_fr]->sumRuleOut)/Chan_list[can_fr]->area; 03789 03790 HeadT = (structs->flagTWsched == 1) ? (structs->TW_stage) : ( boundcond_depth[T(structs->cell_i_TW,structs->cell_j_TW)] + Elev[cell_struct]); 03791 03792 Hdiff = HeadH - HeadT; 03793 /* volume available for fluxing - leave MINDEPTH water; using the head estimate after previously calc'd losses is */ 03794 CH_vol = Chan_list[can_fr]->area* ramp(HeadH-Chan_list[can_fr]->elev_avg+Chan_list[can_fr]->depth-MINDEPTH); 03795 03796 struct_open = 1; /* the structure is open, prior to making any checks of remote cell stages relative to their target schedule */ 03797 03798 if (structs->flagHWsched == 1 && structs->cell_HW != 0) { 03799 /* headwater check is not at the source of any potential flow, but is at a remote cell: 03800 thus any flow from this schedule will not be head-tail based, but is considered 03801 to be from a pump whose variable rate of pumping is dependent on the degree to which stage in the remote cell is approaching target */ 03802 HWcheck = GW[structs->cell_HW]/poros[HAB[structs->cell_HW]] + SWH[structs->cell_HW] ; 03803 struct_open = (structs->HW_stage < HWcheck) ? (1) : (0); 03804 Hdiff = HWcheck - structs->HW_stage ; 03805 } 03806 03807 03808 if ( (Hdiff > 0.0) && struct_open == 1) 03809 { 03810 structs->flow = Min(structs->w_coef * ( Hdiff ) * canstep, CH_vol ); 03811 03812 /* all rule based instances of canal->cell flow go 03813 to external cells, so this reversal check should not be reached */ 03814 flow_rev = ( structs->cell_i_to != 2 ) ? 03815 (HeadH - structs->flow/Chan_list[can_fr]->area) - (HeadT + structs->flow/CELL_SIZE) : 03816 (0.0); 03817 /* the flux eqn is the same as the weir eqn for virtual structures, equilibrating the heads across two unequal area regions */ 03818 /* flow is only in positive direction */ 03819 if (flow_rev < 0.0) { structs->flow = 03820 ramp( Chan_list[can_fr]->area*CELL_SIZE*HeadH/(Chan_list[can_fr]->area+CELL_SIZE) - 03821 Chan_list[can_fr]->area*CELL_SIZE*HeadT/(Chan_list[can_fr]->area+CELL_SIZE) ); 03822 } 03823 } 03824 else structs->flow = 0.0; 03825 03826 03827 03828 /* don't do much with zero or negative flows */ 03829 if (structs->flow == 0.0) { 03830 structs->conc_P = 0.0; 03831 structs->conc_N = 0.0; 03832 structs->conc_S = 0.0; 03833 return; 03834 } /* for output purposes only, zero the reported conc */ 03835 else if (structs->flow < 0) { 03836 sprintf( msgStr, "Day %6.1f: ERROR IN ASSUMPTION OF NO NEG FLOW from cell (%d,%d)", 03837 SimTime.TIME, structs->cell_i_to, structs->cell_j_to ); 03838 WriteMsg( msgStr,True ); dynERRORnum++; 03839 return; 03840 } 03841 03842 /* rule-based flows: calculate the nutrient concentrations */ 03843 /* conc in canal -> cell flow */ 03844 CH_vol = Chan_list[can_fr]->area* ramp(HeadH-Elev[cell_struct]+Chan_list[can_fr]->depth); /* TOTAL volume */ 03845 /* conc in donor (fr) canal (kg/m3) */ 03846 structs->conc_P = (CH_vol>0) ? (Chan_list[can_fr]->P/CH_vol) : (0.0); 03847 structs->conc_N = (CH_vol>0) ? (Chan_list[can_fr]->N/CH_vol) : (0.0); 03848 structs->conc_S = (CH_vol>0) ? (Chan_list[can_fr]->S/CH_vol) : (0.0); 03849 03850 P_fl = structs->flow * structs->conc_P; 03851 N_fl = structs->flow * structs->conc_N; 03852 S_fl = structs->flow * structs->conc_S; 03853 03854 /* increment the sum of rule-based flows from canal 03855 for potential multiple virtual structure flows associated with some canals */ 03856 Chan_list[can_fr]->sumRuleOut += structs->flow; 03857 03858 /* change in nut mass in downstream cell (kg) */ 03859 if (structs->cell_i_to > 2 ) { /* to an on-map cell */ 03860 SWH[cell_to] += structs->flow/CELL_SIZE; 03861 PA[cell_to] += P_fl; 03862 NA[cell_to] += N_fl; 03863 SA[cell_to] += S_fl; 03864 /* mass balance in fr canal and to cell */ 03865 if (Chan_list[can_fr]->basin != basn[cell_to] && debug > -999 ) { 03866 VOL_OUT_STR[Chan_list[can_fr]->basin] += structs->flow; 03867 VOL_IN_STR[basn[cell_to]] += structs->flow; 03868 P_OUT_STR[Chan_list[can_fr]->basin] += P_fl; 03869 P_IN_STR[basn[cell_to]] += P_fl; 03870 S_OUT_STR[Chan_list[can_fr]->basin] += S_fl; 03871 S_IN_STR[basn[cell_to]] += S_fl; 03872 03873 /* all structure flows, EXCEPT canal-canal, must be between parent (family) hydro basins */ 03874 // v2.8.4 if ( (Chan_list[can_fr]->family == basn_list[basn[cell_to]]->family) && (debug > 0) ) { 03875 // sprintf( msgStr, "Day %6.1f: ERROR in basin configuration for structure from chan %d to cell (%d,%d): flow must be between diff hydrologic basins", 03876 // SimTime.TIME, Chan_list[can_fr]->number,structs->cell_i_to,structs->cell_j_to ); 03877 // WriteMsg( msgStr,True ); dynERRORnum++; 03878 // } 03879 } 03880 } 03881 else if (structs->cell_i_to == 2 && debug > -999 ) { /* to off-map cell, mass balance check */ 03882 VOL_OUT_STR[Chan_list[can_fr]->basin] += structs->flow; 03883 VOL_OUT_STR[0] += structs->flow; 03884 P_OUT_STR[Chan_list[can_fr]->basin] += P_fl; 03885 P_OUT_STR[0] += P_fl; 03886 S_OUT_STR[Chan_list[can_fr]->basin] += S_fl; 03887 S_OUT_STR[0] += S_fl; 03888 } 03889 03890 03891 /* calc the change in mass in canal (kg) */ 03892 Chan_list[can_fr]->N -= N_fl ; 03893 Chan_list[can_fr]->P -= P_fl ; 03894 Chan_list[can_fr]->S -= S_fl ; 03895 } /* end of calculated canal-cell flows */
void flowCalc_CelCan | ( | struct Structure * | structs, | |
float * | SWH, | |||
float * | GW, | |||
float * | poros, | |||
float * | Elev, | |||
double * | NA, | |||
double * | PA, | |||
double * | SA | |||
) |
Cell-to-Canal water water control structure flows: Calculated (rule-based).
SWH | SURFACE_WAT | |
GW | SAT_WATER | |
poros | HP_HYD_POROSITY | |
Elev | SED_ELEV | |
NA | DINdummy | |
PA | TP_SF_WT | |
SA | SALT_SURF_WT |
TODO - put in place the CanalData.struct reading checks to ensure the conditions described above are met.
Definition at line 4061 of file WatMgmt.c.
References Chan::area, HistData::arrayN, HistData::arrayP, HistData::arrayS, Chan::basin, boundcond_depth, Structure::canal_to, canstep, Structure::cell_i_fr, Structure::cell_i_HW, Structure::cell_j_HW, Structure::cell_TW, Chan_list, CHo, Structure::conc_N, Structure::conc_P, Structure::conc_S, Chan::depth, dynERRORnum, Chan::elev_avg, Structure::flagHWsched, Structure::flagTWsched, Structure::flow, HAB, Hist_data, Structure::histID, Structure::HW_stage, Max, msgStr, Chan::N, Chan::number, Chan::P, P_IN_STR, Chan::S, S_IN_STR, Structure::S_nam, SimTime, Chan::sumHistIn, Chan::sumHistOut, Chan::sumRuleIn, T, simTime::TIME, Structure::TN, Structure::TNser, Structure::TP, Structure::TPser, True, Structure::TS, Structure::TSser, Structure::TW_stage, usrErr(), VOL_IN_STR, Structure::w_coef, Chan::wat_depth, and WriteMsg().
Referenced by Flows_in_Structures().
04063 { 04064 int cell_fr, can_to; 04065 int cell_struct; 04066 float HeadH, HeadT; 04067 double N_fl, P_fl, S_fl; 04068 04069 /* from unitmod.h */ 04070 extern float* boundcond_depth; /* depth in external cells */ 04071 04072 float HWcheck, TWcheck, Hdiff; /* v2.8 */ 04073 int struct_open; 04074 04075 /* RULE-BASED STRUCTURE FLOW */ 04076 can_to = structs->canal_to - CHo; 04077 04078 if (structs->cell_i_fr != 2 ) { 04079 sprintf( msgStr, "ERROR in flow configuration for %s structure : this rule-based flow is restricted to inflow from outside the model domain.", 04080 structs->S_nam ); 04081 usrErr( msgStr); exit(-1); 04082 } 04083 if (structs->flagTWsched == 1 && structs->flagHWsched == 1 ) { 04084 sprintf( msgStr, "ERROR in flow configuration for %s structure : this rule-based flow can not have both HeadWater and TailWater Schedules.", 04085 structs->S_nam ); 04086 usrErr( msgStr); exit(-1); 04087 } 04088 if ( structs->flagTWsched != 1 && structs->flagHWsched != 1 && structs->cell_i_HW == 0 ) { 04089 sprintf( msgStr, "ERROR in flow configuration for %s structure : without a head or tail water schedule, this rule-based flow must have a headwater-check-cell defined (to acquire data from the boundary-condition model).", 04090 structs->S_nam ); 04091 usrErr( msgStr ); exit(-1); 04092 } 04093 04094 HeadH = (structs->flagHWsched == 1) ? (structs->HW_stage) : ( boundcond_depth[T(structs->cell_i_HW,structs->cell_j_HW)] + Elev[cell_struct]); 04095 /* in v2.3, the rule-based cell->canal flows use only tide data for boundary conditions */ 04096 /* v2.8 - add the sumRuleIn and sumRuleOut */ 04097 HeadT = Chan_list[can_to]->elev_avg - Chan_list[can_to]->depth + Chan_list[can_to]->wat_depth 04098 + (Chan_list[can_to]->sumHistIn - Chan_list[can_to]->sumHistOut)/Chan_list[can_to]->area 04099 + (Chan_list[can_to]->sumRuleIn - Chan_list[can_to]->sumRuleOut)/Chan_list[can_to]->area; 04100 04101 Hdiff = HeadH - HeadT; 04102 04103 struct_open = 1; /* the structure is open, prior to making any checks of remote cell stages relative to their targets */ 04104 04105 if (structs->flagTWsched == 1 && structs->cell_TW != 0) { 04106 /* tailwater check is not at the destination of any potential flow, but is at a remote cell: 04107 thus any flow from this schedule will not be head-tail based, but is considered 04108 to be from a pump whose rate of pumping is dependent on the degree to which stage in the remote cell is approaching target */ 04109 TWcheck = GW[structs->cell_TW]/poros[HAB[structs->cell_TW]] + SWH[structs->cell_TW] ; 04110 struct_open = (structs->TW_stage > TWcheck) ? (1) : (0); 04111 Hdiff = structs->TW_stage - TWcheck; 04112 } 04113 04114 04115 if ( struct_open == 1) 04116 { 04117 structs->flow = Max(structs->w_coef * ( Hdiff ) * canstep, 0 ); 04118 // printf (" On %s, %d %d, TWcheck= %f, target= %f, struct is %d, Hdiff=%f, flow=%f \n",structs->S_nam,structs->cell_i_TW, structs->cell_j_TW, TWcheck,structs->TW_stage, struct_open,Hdiff,structs->flow); 04119 } 04120 else structs->flow = 0.0; /* undefined flow if heads are equal, thus this stmt added */ 04121 04122 /* don't do much with zero or negative flows */ 04123 if (structs->flow == 0.0) { 04124 structs->conc_P = 0.0; 04125 structs->conc_N = 0.0; 04126 structs->conc_S = 0.0; 04127 return; 04128 } /* for output purposes only, zero the reported conc */ 04129 04130 /* rule-based: calculate the nutrients - this is restricted to calculated tidal boundary condition flows from outside of system */ 04131 /* concentration in structure flows, g/L = kg/m^3; mass of stock in kg */ 04132 04133 if (structs->cell_i_fr == 2) { 04134 structs->conc_P = (structs->TPser == 1) ? 04135 Hist_data[structs->histID-1].arrayP[((int)(SimTime.TIME))] : 04136 ((structs->TPser == 0) ? (structs->TP) : (0.0) ); 04137 structs->conc_N = (structs->TNser == 1) ? 04138 Hist_data[structs->histID-1].arrayN[((int)(SimTime.TIME))] : 04139 ((structs->TNser == 0) ? (structs->TN) : (0.0) ); 04140 structs->conc_S = (structs->TSser == 1) ? 04141 Hist_data[structs->histID-1].arrayS[((int)(SimTime.TIME))] : 04142 ((structs->TSser == 0) ? (structs->TS) : (0.0) ); 04143 } 04144 P_fl = structs->flow * structs->conc_P; 04145 N_fl = structs->flow * structs->conc_N; 04146 S_fl = structs->flow * structs->conc_S; 04147 04148 /* increment the sum of rule-based flows to canal 04149 for potential multiple virtual structure flows associated with some canals */ 04150 Chan_list[can_to]->sumRuleIn += structs->flow; 04151 04152 /* this calculated flow is restricted to an outside-system cell, which does not need updating */ 04153 /* these are nutrient stocks, not concentrations */ 04154 /* mass balance in fr cell and to canal */ 04155 if (structs->cell_i_fr == 2 ) { 04156 VOL_IN_STR[Chan_list[can_to]->basin] += structs->flow; 04157 VOL_IN_STR[0] += structs->flow; 04158 P_IN_STR[Chan_list[can_to]->basin] += P_fl; 04159 P_IN_STR[0] += P_fl; 04160 S_IN_STR[Chan_list[can_to]->basin] += S_fl; 04161 S_IN_STR[0] += S_fl; 04162 } 04163 else { 04164 sprintf( msgStr, "Day %6.1f: ERROR in flow to chan %d: cannot have calculated cell->canal flows except from outside of model domain. ", 04165 SimTime.TIME, Chan_list[can_to]->number); 04166 WriteMsg( msgStr,True ); dynERRORnum++; 04167 return; 04168 } 04169 04170 04171 /* change in nut mass in canal (kg) */ 04172 Chan_list[can_to]->N += N_fl ; 04173 Chan_list[can_to]->P += P_fl ; 04174 Chan_list[can_to]->S += S_fl ; 04175 04176 } /* end of calculated cell-canal flows */
float f_Manning | ( | float | delta, | |
float | Water, | |||
float | SW_coef | |||
) |
Surface water exchange between cell and canal.
delta | Head difference between cell and canal (m) | |
Water | Hydraulic radius (m) | |
SW_coef | Aggregated flow coefficient (m^0.5 * sec)/m^(1/3) |
Definition at line 2741 of file WatMgmt.c.
References Abs, canstep, GP_mannDepthPow, and sgn.
Referenced by FluxChannel().
02742 { float a_delta; 02743 02744 a_delta = Abs (delta); 02745 return ( sgn( delta ) * SW_coef * pow(Water, GP_mannDepthPow) * sqrt(a_delta) * canstep); 02746 02747 }
float f_Ground | ( | float | dh, | |
float | height, | |||
float | GW_coef, | |||
float | I_Length | |||
) |
Subsurface ground water exchange between cell and canal.
dh | Head difference between cell and canal (m) | |
height | Height of water (m) | |
GW_coef | Aggregated flow coefficient (m/d) | |
I_Length | Average length of cell along reach segment |
Definition at line 2759 of file WatMgmt.c.
References canstep, and celWid.
Referenced by FluxChannel().
02760 { 02761 float w; 02762 02763 /* porosity already part of GW_coef */ 02764 w = dh * I_Length * GW_coef / (0.5*celWid) * height * canstep; 02765 02766 return ( w); 02767 02768 }
float GetGraph | ( | struct Schedule * | graph, | |
float | x | |||
) |
Graph to read the time dependent schedules.
graph | A struct of Schedule | |
x | Time, julian day within recurring year |
Definition at line 4190 of file WatMgmt.c.
References Schedule::graph_points, Schedule::num_point, Points::time, and Points::value.
Referenced by Flows_in_Structures().
04191 { 04192 float s; 04193 int ig = 0, Np; 04194 04195 Np = graph->num_point; 04196 04197 while(1) 04198 { 04199 if (x <= graph->graph_points[ig].time) 04200 { if ( ig > 0 ) ig--; 04201 else return ( graph->graph_points[0].value ); 04202 } 04203 else if (x > graph->graph_points[ig].time && x <= graph->graph_points[ig+1].time) 04204 { 04205 s = ( graph->graph_points[ig+1].value - graph->graph_points[ig].value )/ 04206 ( graph->graph_points[ig+1].time - graph->graph_points[ig].time ); 04207 return ( s * ( x - graph->graph_points[ig].time ) + graph->graph_points[ig].value ); 04208 } 04209 else if (x > graph->graph_points[ig+1].time) 04210 { if ( ig < Np ) ig++; 04211 else return ( graph->graph_points[Np].value ); 04212 } 04213 } 04214 }
struct Chan* ReadChanStruct | ( | char * | filename | ) | [read] |
Reads the information about canal reaches from data file.
A canal in the model is termed a canal reach. A canal reach is defined by one or more straight segments. A segment is defined by two points with geographic coordinates. Thus, a curved canal reach is comprised of multiple, small segments.
filename | Canal/levee attributes data file. |
Definition at line 435 of file WatMgmt.c.
References Chan::basin, basins, basn_list, basndef::basnTxt, C_F, ChanInFile, CHANNEL_MAX_ITER, CHo, Chan::cond, Chan::depth, Chan::edgeMann, F_ERROR, basndef::family, Chan::family, H_OPSYS, Chan::ic_depth, Chan::ic_N_con, Chan::ic_P_con, Chan::ic_S_con, Chan::levee, MINDEPTH, modelFileName, modelName, ModelPath, msgStr, Chan::next_in_list, Chan_segm::next_segm, num_chan, numBasn, Chan::number, basndef::parent, Chan::parent, ProjName, Chan::roil, Chan::roir, Chan::segments, SimAlt, UNIX, usrErr(), UTM2kmx(), UTM2kmy(), UTM_EOrigin, UTM_NOrigin, Chan::wat_depth, Chan::width, Chan_segm::x0, Chan_segm::x1, Chan_segm::y0, and Chan_segm::y1.
Referenced by Canal_Network_Init().
00436 { 00437 struct Chan *channels, *chan_first, *chan_last; 00438 struct Chan_segm *C_segm, *last_segm, *next_segm; 00439 int i, index, firstSegm, firstCanal = 1; 00440 char ss[622], scenario[20], modnam[20], bas_txt[8]; 00441 float C_x, C_y, C_x1, C_y1; 00442 00443 00444 int ibas, foundBasn; 00445 00446 00447 { if(H_OPSYS==UNIX) 00448 sprintf( modelFileName, "%s/%s/Data/%s.chan", ModelPath, ProjName, filename ); 00449 else sprintf( modelFileName, "%s%s:Data:%s.chan", ModelPath, ProjName, filename ); 00450 } 00451 00452 /* Open file with canals data */ 00453 if ( ( ChanInFile = fopen( modelFileName, "r" ) ) == NULL ) 00454 { 00455 sprintf( msgStr,"Can't open %s file! ",modelFileName ) ; usrErr(msgStr); 00456 exit(-1) ; 00457 } 00458 00459 /* Allocate memory for canal reach segment structure. A canal segment is the straight canal segment */ 00460 /* defined in the canal data file by the coordinates of its beginning and ending points. */ 00461 /* Each canal reach is comprised of one or more canal segments */ 00462 if ( (C_segm = (struct Chan_segm *) malloc( (size_t) sizeof( struct Chan_segm ))) == NULL ) 00463 { 00464 usrErr( "No memory for first canal reach segment\n " ) ; 00465 exit( -2 ) ; 00466 }; 00467 00468 num_chan = 0; 00469 00470 /* Read the general canal network information */ 00471 fgets( ss, 620, ChanInFile ); sscanf( ss, "%d", &UTM_EOrigin ); 00472 fgets( ss, 620, ChanInFile ); sscanf( ss, "%d", &UTM_NOrigin ); 00473 fgets( ss, 620, ChanInFile ); /* skip comment line */ 00474 fgets( ss, 620, ChanInFile ); sscanf( ss,"%s %s %d %d", &modnam, &scenario, &CHo, &CHANNEL_MAX_ITER ); 00475 if (strcmp(scenario,SimAlt) != 0) { 00476 sprintf(msgStr, "The scenario (%s) found in the %s file doesn't match the one (%s) you asked for in Driver.parm!", 00477 scenario, modelFileName, SimAlt); usrErr(msgStr); 00478 exit(-1); 00479 } 00480 if (strcmp(modnam,modelName) != 0) { 00481 sprintf(msgStr, "The model name (%s) found in the %s file doesn't match the one (%s) you asked for in Driver.parm!", 00482 modnam, modelFileName, modelName); usrErr(msgStr); 00483 exit(-1); 00484 } 00485 00486 fgets( ss, 620, ChanInFile ); /* skip comment line */ 00487 fgets( ss, 620, ChanInFile ); sscanf ( ss, "%f %f %f ", &F_ERROR, &MINDEPTH, &C_F ); 00488 /* the C_F is used only for sensitivity experiments */ 00489 fgets( ss, 620, ChanInFile ); /* skip comment line */ 00490 00491 /* Read canal descriptors until none left */ 00492 while ( fgets( ss, 620, ChanInFile ) != NULL && !feof( ChanInFile ) ) 00493 { 00494 if ( *ss == '#' ) /* "#" identifies each new canal in the data file */ 00495 { /* Allocate memory for canal reach structure */ 00496 if ( (channels = (struct Chan *) malloc( (size_t) sizeof( struct Chan ))) == NULL ) 00497 { 00498 printf( "No memory for first canal\n " ) ; 00499 exit( -2 ) ; 00500 }; 00501 00502 /* Read canal information: - canal number, 00503 - levee marker (1 - left levee, -1 - right, 0 - none, 2 - both sides), 00504 - ranges of cell interaction to the left and to the right - functionality removed, should ALWAYS=1, 00505 - canal depth and width, 00506 - seepage coefficient through the levee, 00507 - initial S and P concentrations (doubles) in the canal water, 00508 - initial water depth in canal (can be >, = or < than canal depth 00509 - Manning's n associated w/ edge of canal, to accomodate topographic lip/berm and/or denser veg along canal length 00510 - hydrologic basin that canal exchanges surface water with */ 00511 i = sscanf( ss+1, "%d\t%d\t%d\t%d\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%s", 00512 &channels->number, 00513 &channels->levee, 00514 &channels->roil, &channels->roir, 00515 &channels->depth, &channels->width, 00516 &channels->cond, 00517 &channels->ic_S_con, &channels->ic_P_con, 00518 &channels->wat_depth, &channels->edgeMann, &bas_txt); 00519 00520 foundBasn=0; 00521 for (ibas=numBasn;ibas>0;ibas--) { 00522 basins = basn_list[ibas]; 00523 if(strcmp(bas_txt,basins->basnTxt)==0) { 00524 channels->basin = ibas; 00525 foundBasn=1; 00526 channels->family = basn_list[ibas]->family; 00527 channels->parent = basn_list[ibas]->parent; 00528 /* canals may ONLY belong to parent hydro basins, not to indicator regions */ 00529 if (!channels->parent) { 00530 printf ("Sorry - %s's canal %d's basin is not a parent hydrologic basin! Please assign to a hydro basin in the CanalData.chan file.\n", 00531 modelName,channels->number); exit (-1);} 00532 } 00533 } 00534 if (foundBasn==0) { printf ("Sorry - %s's canal %d's basin does not exist! Please define the basin in the basinIR file.\n", 00535 modelName,channels->number); exit (-1);} 00536 00537 channels->ic_P_con *= 0.001; /* initial input value in mg/L, convert to g/L==kg/m3 */ 00538 channels->ic_N_con = 0.00; /* v2.2 "removed" N */ /* initial input value in mg/L, convert to g/L==kg/m3 */ 00539 channels->ic_S_con *= 1.0; /* initial input value in g/L, no conversion */ 00540 /* store the initial depth for re-initializing under Positional Analysis mode */ 00541 channels->ic_depth = channels->wat_depth; 00542 00543 00544 channels->segments = C_segm; 00545 00546 if (i < 10) /* check for the number of input fields read */ 00547 {printf ( " Error in CanalData.chan: reach input %d\n", (num_chan+1) ); exit (-1);} 00548 00549 00550 num_chan++; /*count the number of canal reaches (not canal segments) */ 00551 firstSegm = 1; 00552 00553 if (firstCanal) 00554 { 00555 firstCanal = 0; 00556 chan_first = channels; 00557 chan_last = channels; 00558 continue; 00559 } 00560 00561 last_segm->next_segm = NULL; 00562 chan_last->next_in_list = channels; 00563 chan_last = channels; 00564 } 00565 else 00566 { /* read the pairs of coordinates for the consecutive canal segments */ 00567 i = sscanf ( ss, "%f %f", &C_x1, &C_y1 ); 00568 if (i < 2) /* check for the number of input fields read */ 00569 {printf ( " Error in CanalData.chan coords: Reach %d \n", (num_chan+1) ); exit (-1);} 00570 00571 /* Convert from UTM to km units with 0,0 origin */ 00572 C_x = UTM2kmx (C_x1); C_y = UTM2kmy (C_y1); 00573 C_segm->x1 = C_x; C_segm->y1 = C_y; 00574 00575 if ( firstSegm ) 00576 { C_segm->x0 = C_x; C_segm->y0 = C_y; 00577 firstSegm = 0; 00578 } 00579 else 00580 { 00581 /* Allocate memory for canal reach segment structure */ 00582 if ( (next_segm = (struct Chan_segm *) malloc( (size_t) sizeof( struct Chan_segm ))) == NULL ) 00583 { printf( "No memory for canal reach segment\n " ) ; 00584 exit( -2 ) ; 00585 }; 00586 C_segm->next_segm = next_segm; 00587 last_segm = C_segm; 00588 C_segm = next_segm; 00589 C_segm->x0 = C_x; C_segm->y0 = C_y; 00590 } 00591 } 00592 }/* end loop for reading */ 00593 00594 chan_last->next_in_list = NULL; 00595 last_segm->next_segm = NULL; 00596 free ((char *) C_segm); 00597 fclose (ChanInFile); 00598 00599 usrErr( "\tCanal locs/attributes read OK" ); 00600 00601 return (chan_first); 00602 }
struct Cells* MarkCell | ( | int | x, | |
int | y, | |||
int | c_ind, | |||
float | length, | |||
struct Cells * | cell, | |||
int | direction, | |||
int | levee, | |||
int | xm, | |||
int | ym, | |||
int | c_num, | |||
int * | marked, | |||
float | distTot | |||
) | [read] |
Mark cell function.
This function does two things:
1. It stores the cell coordinates (x, y) in the interaction array, also identifying the location of this cell with respect to the canal;
2. It marks the cell (xm,ym) on the ON_MAP array to prevent horizontal overland fluxes if there is a levee associated with this canal.
x | Grid cell row | |
y | Grid cell column | |
c_ind | Cell index = 1 for left cells and -1 for right cells | |
length | Length of canal associated with this cell | |
cell | A struct of Cells | |
direction | Direction of interaction: 1 - none, 2 -to the East, 3 - to the South, 4 - all directions | |
levee | Levee location attribute | |
xm | Grid cell row marked | |
ym | Grid cell column marked | |
c_num | Canal ID number | |
marked | Denote a marked cell | |
distTot | Cumulative (along grid cells) distance along a canal reach, from the starting point (m) |
Definition at line 1858 of file WatMgmt.c.
References ALL, C_Mark, CanalCellInteractDebug, cell_last, celWid, Cells::ind, Cells::length, Cells::next_cell, ON_MAP, Cells::reachDistDown, s0, s1, T, Cells::x, and Cells::y.
Referenced by Channel_configure().
01860 { struct Cells *cell_next; 01861 int N, cellLoc; 01862 01863 if ( x > s0 || y > s1 ) /* v2.6 changed evaluation to ">" (was ">=") */ 01864 { printf ( "Error in definition of canal in cell row=%d col=%d ", x, y ); 01865 exit (-2); /*check that cells obtained are within array boundaries */ 01866 } 01867 01868 N = T(xm+1, ym+1); 01869 if ( !ON_MAP[N] ) return cell; 01870 01871 if ( levee && direction != ALL ) 01872 ON_MAP[N] = ((ON_MAP[N]-1) & (direction+100)) + 1; /* modifying ON_MAP to take into account the 01873 allowed direction of fluxing: 00 - none, 01=1 - to the East, 10=2 - to the South, 11=3 - all 01874 ON_MAP they naturally become 1 - none, 2 -to the East, 3 - to the South, 4 - all directions 01875 0 is reserved for cells out of the ON_MAP area*/ 01876 01877 if ( !C_Mark ) return cell; /* C_Mark is to make gaps between canals, so that there will be no 01878 canals being connected through cells if it turns out that they are linked to the same cells */ 01879 01880 /* a temporary fix used to determine if a cell belonging to a canal has already been marked */ 01881 /***********/ 01882 cellLoc = T(x+1,y+1); 01883 if (marked[cellLoc] == c_num ) return cell; 01884 marked[cellLoc] = c_num; 01885 /***********/ 01886 01887 01888 01889 cell->x = x+1; /* shift coord to match the other maps */ 01890 cell->y = y+1; 01891 cell->ind = c_ind; 01892 cell->length = length*celWid; /* length of canal associated with this cell * cell width m */ 01893 cell->reachDistDown = distTot; /* cumulative (by grid cells) distance along a canal reach, from the starting point (m) (v2.5) */ 01894 01895 fprintf ( CanalCellInteractDebug, " %d, %d, l/r = %d, distance= %7.1f\n", cell->x, cell->y, c_ind, cell->reachDistDown ); 01896 01897 /* allocate memory for next cell structure */ 01898 if ( (cell_next = (struct Cells *) malloc((size_t) sizeof( struct Cells ))) == NULL ) 01899 { 01900 printf( "Failed to allocate memory for cell structure\n " ) ; 01901 exit( -2 ) ; 01902 } 01903 cell->next_cell = cell_next; 01904 cell_last = cell; 01905 01906 return cell_next; 01907 }
struct Schedule* Read_schedule | ( | char * | sched_name, | |
char * | filename, | |||
float | BASE_DATUM | |||
) | [read] |
Read target stage schedule as a recurring time-series graph.
sched_name | The name of the target stage location | |
filename | Input file name for graph | |
BASE_DATUM | GP_DATUM_DISTANCE |
Definition at line 1342 of file WatMgmt.c.
References EOL, EOS, Schedule::graph_points, H_OPSYS, modelFileName, modelName, ModelPath, msgStr, Schedule::num_point, NumScheds, ProjName, schedFile, Schedule::schedName, Scip(), SimAlt, Points::time, True, UNIX, usrErr(), Points::value, Wrdcmp(), and WriteMsg().
Referenced by ReadStructures().
01343 { 01344 char ss[601], *s, scenario[30], modnam[30]; 01345 int i, count = 1, sched_found=0; 01346 struct Schedule *Sce_Graph; 01347 01348 { if(H_OPSYS==UNIX) 01349 sprintf( modelFileName, "%s/%s/Data/%s.graph", ModelPath, ProjName, filename ); 01350 else sprintf( modelFileName, "%s%s:Data:%s.graph", ModelPath, ProjName, filename ); 01351 } 01352 01353 /* Open file with schedule graphs */ 01354 if ( ( schedFile = fopen( modelFileName, "r" ) ) == NULL ) 01355 { 01356 printf( "Can't open %s file!\n", modelFileName ) ; 01357 exit(-1) ; 01358 } 01359 01360 fgets( ss, 600, schedFile ); /* skip comment line */ 01361 fgets( ss, 600, schedFile ); /* skip comment line */ 01362 fgets( ss, 600, schedFile ); /* skip comment line */ 01363 fgets( ss, 600, schedFile ); sscanf( ss,"%s %s", &modnam, &scenario ); 01364 if (strcmp(scenario,SimAlt) != 0) { 01365 sprintf(msgStr, "The scenario (%s) found in the %s file doesn't match the one (%s) you asked for in Driver.parm!", 01366 scenario, modelFileName, SimAlt); usrErr(msgStr); 01367 exit(-1); 01368 } 01369 if (strcmp(modnam,modelName) != 0) { 01370 sprintf(msgStr, "The model name (%s) found in the %s file doesn't match the one (%s) you asked for in Driver.parm!", 01371 modnam, modelFileName, modelName); usrErr(msgStr); 01372 exit(-1); 01373 } 01374 01375 /* Read schedule descriptors until none left */ 01376 while ( fgets( ss, 600, schedFile ) != NULL && !feof( schedFile ) ) 01377 { if ( !Wrdcmp ( ss, sched_name ) ) continue; /* v2.8 - bugfix - reversed arg order in this version: Wrdcmp looks to see if the next char is a space in the first arg; the ss, sched_name is correct order for this to work (old code allowed sched_names that started with the same string to be treated as the same) */ 01378 sched_found = True; 01379 01380 fgets( ss, 600, schedFile ); 01381 s = ss; 01382 /* count the number of pairs for the graph */ 01383 while ( *s++ != EOL ) if ( *s == '(' ) count++; 01384 01385 /* Allocate memory for next schedule */ 01386 if ( (Sce_Graph = (struct Schedule *) malloc( (size_t) sizeof( struct Schedule ))) == NULL ) 01387 { 01388 printf( "Failed to allocate memory for Managed flow Schedule graph in (%s)\n ", sched_name ) ; 01389 exit( -2 ) ; 01390 }; 01391 01392 /* Allocate memory for next schedule graph containing 'count' points*/ 01393 if ( (Sce_Graph->graph_points = 01394 (struct Points *) malloc( (size_t) sizeof( struct Points ) * count)) == NULL ) 01395 { 01396 printf( "Failed to allocate memory for Managed flow Schedule graph in (%s)\n ", sched_name ) ; 01397 exit( -2 ) ; 01398 }; 01399 01400 Sce_Graph->num_point = count; 01401 01402 s = ss; 01403 for ( i = 0; i < count && *s!=EOS; i++ ) 01404 { 01405 s = Scip( s,'('); 01406 sscanf( s, "%f", &Sce_Graph->graph_points[i].time ); 01407 s = Scip ( s, ','); 01408 sscanf( s, "%f", &Sce_Graph->graph_points[i].value ); 01409 Sce_Graph->graph_points[i].value += BASE_DATUM; 01410 } 01411 } /* end of while */ 01412 /* v2.5 included this error-trap */ 01413 if (!sched_found) { 01414 sprintf(msgStr, "The schedule name (%s) was not found in the %s schedule file! (Was named in the CanalData.struct file.)", 01415 sched_name, modelFileName); usrErr(msgStr); 01416 exit(-1); 01417 } 01418 01419 /* v2.8 writing this to Driver1.out debug file */ 01420 sprintf(msgStr, "Read target schedule graph: %s, which contained %d time points.",strcpy(Sce_Graph->schedName, sched_name), Sce_Graph->num_point); 01421 WriteMsg(msgStr,1); 01422 NumScheds = NumScheds+1; /* used just for writing info to console on number of schedules you've read */ 01423 01424 01425 fclose (schedFile); 01426 return Sce_Graph; 01427 }
int Wrdcmp | ( | char * | s, | |
char * | t | |||
) |
Compare two words.
s | A string | |
t | Another string |
Definition at line 4243 of file WatMgmt.c.
References EOS.
Referenced by Read_schedule().
04244 { 04245 for ( ; *s == *t; s++, t++ ) 04246 if ( isspace (*(s+1)) || *(s+1) == EOS ) return 1; 04247 04248 return 0; 04249 04250 }
float UTM2kmx | ( | double | UTM | ) |
Converter from meters in UTM to grid cell row location (zero origin).
UTM | Geographic coordinate (m, ELM uses UTM zone17, NAD'27, but not important here) |
Definition at line 4232 of file WatMgmt.c.
References Abs, celWid, and UTM_NOrigin.
Referenced by ReadChanStruct().
04233 { return ( Abs(UTM - UTM_NOrigin)/celWid ); 04234 }
float UTM2kmy | ( | double | UTM | ) |
Converter from meters in UTM to grid cell column location (zero origin).
UTM | Geographic coordinate (m, ELM uses UTM zone17, NAD'27, but not important here) |
Definition at line 4223 of file WatMgmt.c.
References Abs, celWid, and UTM_EOrigin.
Referenced by ReadChanStruct().
04224 { return ( Abs(UTM - UTM_EOrigin)/celWid ); 04225 }
double julday | ( | int | mon, | |
int | day, | |||
int | year, | |||
int | h, | |||
int | mi, | |||
double | se | |||
) |
Determine the Julian calendar day from a Gregorian date.
mon | Month | |
day | Day | |
year | Year | |
h | Hour | |
mi | Minute | |
se | Second |
Definition at line 1583 of file Driver_Utilities.c.
01584 { 01585 long m = mon, d = day, y = year; 01586 long c, ya, j; 01587 double seconds = h * 3600.0 + mi * 60 + se; 01588 01589 if (m > 2) 01590 m -= 3; 01591 else { 01592 m += 9; 01593 --y; 01594 } 01595 c = y / 100L; 01596 ya = y - (100L * c); 01597 j = (146097L * c) / 4L + (1461L * ya) / 4L + (153L * m + 2L) / 5L + d + 1721119L; 01598 if (seconds < 12 * 3600.0) { 01599 j--; 01600 seconds += 12.0 * 3600.0; 01601 } 01602 else { 01603 seconds = seconds - 12.0 * 3600.0; 01604 } 01605 return (j + (seconds / 3600.0) / 24.0); 01606 }
void init_pvar | ( | VOIDP | Map, | |
UCHAR * | mask, | |||
unsigned char | Mtype, | |||
float | iv | |||
) |
Initialize a variable to a value.
Map | array of data | |
mask | data mask | |
Mtype | the data type of the map data | |
iv | the value used to initialize variable |
Definition at line 1008 of file Driver_Utilities.c.
01009 { 01010 int i0, i1; 01011 01012 switch(Mtype) { 01013 case 'b' : /* added double for (non-map) basin (b) array budget calcs */ 01014 for(i0=0; i0<=numBasn; i0++) { 01015 ((double*)Map)[i0] = iv; 01016 } 01017 break; 01018 case 'l' : /* added double (l == letter "ell" ) for map arrays */ 01019 for(i0=0; i0<=s0+1; i0++) 01020 for(i1=0; i1<=s1+1; i1++) { 01021 if(mask==NULL) ((double*)Map)[T(i0,i1)] = iv; 01022 else if ( mask[T(i0,i1)] == 0 ) ((double*)Map)[T(i0,i1)] = 0; 01023 else ((double*)Map)[T(i0,i1)] = iv; 01024 } 01025 break; 01026 case 'f' : 01027 for(i0=0; i0<=s0+1; i0++) 01028 for(i1=0; i1<=s1+1; i1++) { 01029 if(mask==NULL) ((float*)Map)[T(i0,i1)] = iv; 01030 else if ( mask[T(i0,i1)] == 0 ) ((float*)Map)[T(i0,i1)] = 0; 01031 else ((float*)Map)[T(i0,i1)] = iv; 01032 } 01033 break; 01034 case 'i' : case 'd' : 01035 for(i0=0; i0<=s0+1; i0++) 01036 for(i1=0; i1<=s1+1; i1++) { 01037 if(mask==NULL) ((int*)Map)[T(i0,i1)] = (int)iv; 01038 else if ( mask[T(i0,i1)] == 0 ) ((int*)Map)[T(i0,i1)] = 0; 01039 else ((int*)Map)[T(i0,i1)] = (int)iv; 01040 } 01041 break; 01042 case 'c' : 01043 for(i0=0; i0<=s0+1; i0++) 01044 for(i1=0; i1<=s1+1; i1++) { 01045 if(mask==NULL) ((unsigned char*)Map)[T(i0,i1)] = (unsigned char) '\0' + (int) iv; 01046 else if ( mask[T(i0,i1)] == 0 ) ((unsigned char*)Map)[T(i0,i1)] = '\0'; 01047 else ((unsigned char*)Map)[T(i0,i1)] = (unsigned char) '\0' + (int) iv; 01048 } 01049 break; 01050 01051 default : 01052 printf(" in default case\n"); 01053 break; 01054 } 01055 }
VOIDP nalloc | ( | unsigned | mem_size, | |
const char | var_name[] | |||
) |
Allocate memory for a variable.
mem_size | The size of memory space | |
var_name | The variable's name |
Definition at line 1857 of file Driver_Utilities.c.
01858 { 01859 VOIDP rp; 01860 01861 01862 if(mem_size == 0) return(NULL); 01863 rp = (VOIDP)malloc( mem_size ); 01864 total_memory += mem_size; 01865 fasync(stderr); 01866 if( rp == NULL ) { 01867 fprintf(stderr,"Sorry, out of memory(%d): %s\n",mem_size,var_name); 01868 Exit(0); 01869 } 01870 fmulti(stderr); 01871 return(rp); 01872 }
char* Scip | ( | char * | s, | |
char | SYM | |||
) |
Skip ahead in a string until next field.
s | A character array | |
SYM | The specific symbol being used to skip over |
Definition at line 1788 of file Driver_Utilities.c.
References EOS.
01789 { 01790 if(*s == SYM ) return ++s; 01791 while(*s != SYM && *s != EOS ) s++; 01792 if(*s != EOS) return ++s; 01793 else return s; 01794 }
int isInteger | ( | char * | target_str | ) |
Determine if an integer is present in string.
target_str | Target string |
Definition at line 1475 of file Driver_Utilities.c.
01475 { 01476 01477 int i=-1,first_num=0; 01478 char ch; 01479 01480 while( (ch=target_str[++i]) != '\0' ) { 01481 if( isdigit(ch) ) first_num=1; 01482 if( (ch=='-' || ch=='+') && first_num ) return(0); 01483 if( !( isspace(ch) || isdigit(ch) || ch=='-' || ch=='+') ) return(0); 01484 } 01485 return(1); 01486 }
int isFloat | ( | char * | target_str | ) |
Determine if a float is present in string.
target_str | Target string |
Definition at line 1493 of file Driver_Utilities.c.
01493 { 01494 01495 int i=-1,first_num=0; 01496 char ch; 01497 01498 while( (ch=target_str[++i]) != '\0' ) { 01499 if( isdigit(ch) ) first_num=1; 01500 if( (ch=='-' || ch=='+') && first_num ) return(0); 01501 if( !( isspace(ch) || isdigit(ch) || ch=='-' || ch=='+' || ch=='.' || toupper(ch) == 'E') ) return(0); 01502 } 01503 return(1); 01504 }
float FMOD | ( | float | x, | |
float | y | |||
) |
Modulus of a pair of (double) arguments.
x | Numerator | |
y | Denominator |
Definition at line 1675 of file Driver_Utilities.c.
int Round | ( | float | x | ) |
truncate (not rounding) to an integer
x | the value being operated on |
Definition at line 1777 of file Driver_Utilities.c.
float Flux_SWcells | ( | int | i0, | |
int | i1, | |||
int | j0, | |||
int | j1, | |||
float * | SWater, | |||
float * | Elevation, | |||
float * | MC | |||
) |
Surface water flux calculations.
Application of Manning's eqn to calculate flux between two adjacent cells (i0,i1) and (j0,j1) Returns height flux. Flux is positive if flow is from i to j. Checks for available volume, and that flow cannot make the head in recepient cell higher than in the donor one.
i0 | Row of cell from (positive flow) | |
i1 | Column of cell from (positive flow) | |
j0 | Row of cell to (positive flow) | |
j1 | Column of cell to (positive flow) | |
SWater | SURFACE_WAT | |
Elevation | SED_ELEV | |
MC | HYD_MANNINGS_N |
Definition at line 231 of file Fluxes.c.
References Abs, BCondFlow, boundcond_depth, GP_BC_InputRow, GP_BC_SfWat_add, GP_BC_SfWat_addHi, GP_BC_SfWat_targ, GP_DetentZ, GP_mannDepthPow, GP_mannHeadPow, isModExperim, Max, Min, ON_MAP, ramp, step_Cell, and T.
00232 { 00239 float dh, adh; 00240 float MC_cells; 00241 float Hi, Hj, stage_i, stage_j; 00242 float Flux = 0.; 00243 int cellLoci = T(i0,i1); 00244 int cellLocj = T(j0,j1); 00245 float garb, garb2; 00246 float GP_BC_SfWat_addOut; /* v2.6 added new calculated var, used only in model experiments */ 00247 00248 00249 MC_cells = (MC[cellLoci] + MC[cellLocj] )/2.; 00250 00251 /* If an on-map cell is marked 3, we are at a model boundary allowing surface water exchange */ 00252 if (!ON_MAP[cellLoci] && BCondFlow[cellLocj] == 3 ) 00253 { 00254 /* v2.6, ONLY in model experiments (isModExperim), calculate synthetic boundary stages */ 00255 /* assume equivalent land surface elevation in cell external to model, 00256 and induce a constant stage diff */ 00257 /* v2.6 parameters found in special "ModExperimParms_NOM" file */ 00258 if (isModExperim) { 00259 if (j0 < GP_BC_InputRow) { 00260 SWater[cellLoci] = SWater[cellLocj] + GP_BC_SfWat_add; 00261 } 00262 else { 00263 GP_BC_SfWat_addOut = ( SWater[cellLocj] > GP_BC_SfWat_targ ) ? 00264 ( (GP_BC_SfWat_addHi+GP_BC_SfWat_add) * ( pow( (SWater[cellLocj] / (GP_BC_SfWat_targ+0.001)) ,2.0) ) ) : 00265 (GP_BC_SfWat_add); 00266 SWater[cellLoci] = Max( SWater[cellLocj] - GP_BC_SfWat_addOut, 0.0); 00267 } 00268 stage_i = Elevation[cellLocj] + SWater[cellLoci]; 00269 } 00270 else 00271 { 00272 /* v2.6 - error in v2.5 found here, where Hi did not have Elevation added (boundcond_depth was originally intended to be stage, w/ stage in name). 00273 Regional ELM v2.5 did not have significant overland flow across domain boundaries in the two regions where that operated (northern BCNP, Model Lands north of C-111, used to be no-flow areas for overland boundary flows). */ 00274 stage_i = Elevation[cellLocj] + Max( Max(boundcond_depth[cellLoci],0.0) + GP_BC_SfWat_add,0.0); /* v2.6 GP_BC_SfWat_add is non-zero only when performing model experiments (ModExperimParms parm file exists) */ 00275 /*stage_i = boundcond_depth[cellLoci]; */ /* v2.5 */ 00276 } 00277 00278 Hi = stage_i ; /* whether model experiment or standard sim, get the value of Hi for overland flux calcs */ 00279 00280 MC_cells = MC[cellLocj]; /* the mannings n is not avg, but the value of onmap boundary cell */ 00281 } 00282 00283 else 00284 Hi = SWater[cellLoci] + Elevation[cellLoci]; 00285 00286 if(BCondFlow[cellLoci] == 3 && !ON_MAP[cellLocj] ) 00287 { 00288 /* v2.6, ONLY in model experiments (isModExperim), calculate synthetic boundary stages */ 00289 /* assume equivalent land surface elevation in cell external to model, 00290 and induce a constant stage diff */ 00291 /* v2.6 parameters found in special "ModExperimParms_NOM" file */ 00292 if (isModExperim) { 00293 if (i0 < GP_BC_InputRow) { 00294 SWater[cellLocj] = SWater[cellLoci] + GP_BC_SfWat_add; 00295 } 00296 else { 00297 GP_BC_SfWat_addOut = ( SWater[cellLoci] > GP_BC_SfWat_targ ) ? 00298 ( (GP_BC_SfWat_addHi+GP_BC_SfWat_add) * ( pow( (SWater[cellLoci] / (GP_BC_SfWat_targ+0.001)) ,2.0) ) ) : 00299 (GP_BC_SfWat_add); 00300 SWater[cellLocj] = Max(SWater[cellLoci] - GP_BC_SfWat_addOut, 0.0); 00301 } 00302 stage_j = Elevation[cellLoci] + SWater[cellLocj]; 00303 } 00304 else 00305 { 00306 /* v2.6 - error in v2.5 found here, where Hi did not have Elevation added (boundcond_depth was originally intended to be stage, w/ stage in name). 00307 Regional ELM v2.5 did not have significant overland flow across domain boundaries in the two regions where that operated (northern BCNP, Model Lands north of C-111, used to be no-flow areas for overland boundary flows). */ 00308 stage_j = Elevation[cellLoci] + Max( Max(boundcond_depth[cellLocj],0.0) + GP_BC_SfWat_add,0.0); /* v2.6 GP_BC_SfWat_add is non-zero only when performing model experiments (ModExperimParms parm file exists) */ 00309 /*stage_j = boundcond_depth[cellLocj];*/ /* v2.5 */ 00310 } 00311 00312 Hj = stage_j; /* whether model experiment or standard sim, get the value of Hj for overland flux calcs */ 00313 00314 MC_cells = MC[cellLoci]; /* the mannings n is not avg, but the value of onmap boundary cell */ 00315 } 00316 00317 else 00318 Hj = SWater[cellLocj] + Elevation[cellLocj]; 00319 00320 dh = Hi - Hj; /* dh is "from --> to" */ 00321 adh = Abs (dh); 00322 00323 if (dh > 0) 00324 { 00325 if(SWater[cellLoci] < GP_DetentZ) 00326 return 0.0; 00327 /* step_Cell is constant calc'd in Generic_Driver.c at initialization ( m^(-1.5) * sec )*/ 00328 Flux = (MC_cells != 0) ? 00329 (pow(adh,GP_mannHeadPow) / MC_cells * pow(SWater[cellLoci],GP_mannDepthPow)*step_Cell) : (0.0); 00330 //garb=Flux; 00331 /* ensure adequate volume avail */ 00332 Flux = ( Flux > ramp(SWater[cellLoci] - GP_DetentZ) ) ? (ramp(SWater[cellLoci] - GP_DetentZ)) : (Flux); 00333 00334 /* check to ensure no flip/flops associated with depth */ 00335 if ( ( Hi - Flux ) < ( Hj + Flux ) ) Flux = Min ( 0.5*dh, ramp(SWater[cellLoci] - GP_DetentZ) ); /* v2.8.4 was dh/2.0 */ 00336 //if (Flux > 0) printf("\nsfwt= %f; N= %f; dh= %f; Flux1= %f; Flux= %f; ",SWater[cellLoci],MC_cells, dh, garb, Flux); 00337 00338 } /* end of dh > 0 */ 00339 00340 else 00341 { 00342 if (SWater[cellLocj] < GP_DetentZ) 00343 return 0.0; 00344 /* step_Cell is constant calc'd in Generic_Driver.c at initialization ( m^(-1.5) * sec )*/ 00345 /* Flux is negative in this case */ 00346 Flux = (MC_cells != 0) ? 00347 ( - pow(adh,GP_mannHeadPow) / MC_cells * pow(SWater[cellLocj],GP_mannDepthPow)*step_Cell) : (0.0); 00348 00349 /* ensure adequate volume avail */ 00350 Flux = ( -Flux > ramp(SWater[cellLocj] - GP_DetentZ) ) ? (-ramp(SWater[cellLocj] - GP_DetentZ)) : (Flux); 00351 00352 /* check to ensure no flip/flops associated with depth */ 00353 if ( ( Hi - Flux ) > ( Hj + Flux ) ) Flux = - Min ( 0.5*adh, ramp(SWater[cellLocj] - GP_DetentZ) ); /* v2.8.4 was adh/2.0 */ 00354 // if (Flux < 0) printf("\nsfwt= %f; N= %f; dh= %f; Flux= %f; ",SWater[cellLoci],MC_cells, dh, Flux); 00355 00356 } 00357 00358 return (Flux); /* returns height flux */ 00359 }
void Flux_SWstuff | ( | int | i0, | |
int | i1, | |||
int | j0, | |||
int | j1, | |||
float | Flux, | |||
float * | SURFACE_WAT, | |||
double * | STUF1, | |||
double * | STUF2, | |||
double * | STUF3, | |||
float * | SfWat_vel_day | |||
) |
Flux of surface water constituents.
The constituents (nutrients, salinity, etc), are passed among cells, and surface water variable is updated, along with making budget calcs. These are units of constituent mass being fluxed from i0,i1 to j0,j1 Flux & SURFACE_WAT are in units of height (m)
i0 | Row of cell from (positive flow) | |
i1 | Column of cell from (positive flow) | |
j0 | Row of cell to (positive flow) | |
j1 | Column of cell to (positive flow) | |
Flux | Water flux (m) between grid cells | |
SURFACE_WAT | SURFACE_WAT | |
STUF1 | SALT_SURF_WT | |
STUF2 | DINdummy | |
STUF3 | TP_SF_WT | |
SfWat_vel_day | SF_WT_VEL_mag |
Definition at line 383 of file Fluxes.c.
References basins, basn, basn_list, CELL_SIZE, debug, Disp_Calc(), dynERRORnum, basndef::family, basndef::FLok, GP_BC_Pconc, GP_BC_Sconc, GP_MinCheck, Max, Min, msgStr, basndef::numFLok, ON_MAP, P_IN_OVL, P_OUT_OVL, S_IN_OVL, S_OUT_OVL, sfstep, SimTime, T, simTime::TIME, True, Veloc_Calc(), VOL_IN_OVL, VOL_OUT_OVL, WatMgmtOn, and WriteMsg().
00384 { 00385 float m1=0.0, m2=0.0, m3=0.0; 00386 int ii, flo_chek, cel_i, cel_j; 00387 float FluxAdj; /* Flux adjusted for numerical dispersioin */ 00388 double fl_prop_i, fl_prop_j; /* proportion of surface water constituents that should be fluxed with water (depends on magnitude of dispersion) */ 00389 double sf_wt_veloc=0.0; /* v2.7.0 horizontal velocity of advected water (m/d) */ 00390 00391 cel_i = T(i0,i1); 00392 cel_j = T(j0,j1); 00393 00394 /*sf_wt_veloc = Abs(Flux) * celWid/( (Flux>0.0) ? (SURFACE_WAT[cel_i]) : (SURFACE_WAT[cel_j]) ) / (sfstep) ; */ 00395 sf_wt_veloc = Veloc_Calc(Flux, SURFACE_WAT[cel_i], SURFACE_WAT[cel_j], sfstep); 00396 00397 FluxAdj = Disp_Calc(Flux, SURFACE_WAT[cel_i], SURFACE_WAT[cel_j], sfstep, sf_wt_veloc); 00398 /* FluxAdj is the Flux that was adjusted (increase/decrease) to accomodate the targeted level of constituent dispersion */ 00399 00400 if (Flux > 0.0) { 00401 fl_prop_i = (SURFACE_WAT[cel_i]>0.0) ? (FluxAdj/SURFACE_WAT[cel_i]) : (0.0); /* pos Flux */ 00402 fl_prop_i = Min(fl_prop_i, 1.0); 00403 } 00404 else { 00405 fl_prop_j = (SURFACE_WAT[cel_j]>0.0) ? (-FluxAdj/SURFACE_WAT[cel_j]) : (0.0); /* neg Flux */ 00406 fl_prop_j = Max(fl_prop_j, -1.0); /* v2.6 error found? (was Min(fl_prop_j, 1.0) )*/ 00407 } 00408 00409 if (Flux >0.0) { /* the i,i cell is donor if pos flow */ /* v2.6 added the boundary flux conc */ 00410 m1 = (ON_MAP[cel_i]) ? (STUF1[cel_i]*fl_prop_i) : (Flux * CELL_SIZE * GP_BC_Sconc); 00411 m2 = STUF2[cel_i]*fl_prop_i; /* inactive */ 00412 m3 = (ON_MAP[cel_i]) ? (STUF3[cel_i]*fl_prop_i) : (Flux * CELL_SIZE * GP_BC_Pconc); 00413 } 00414 else { /* the j,j cell is donor if neg flow */ 00415 m1 = (ON_MAP[cel_j]) ? (STUF1[cel_j]*fl_prop_j) : (Flux * CELL_SIZE * GP_BC_Sconc); 00416 m2 = STUF2[cel_j]*fl_prop_j; /* inactive */ 00417 m3 = (ON_MAP[cel_j]) ? (STUF3[cel_j]*fl_prop_j) : (Flux * CELL_SIZE * GP_BC_Pconc); 00418 } 00419 00420 if (ON_MAP[cel_j]) { 00421 STUF1[cel_j] += m1; /* add the masses of constituents */ 00422 STUF2[cel_j] += m2; 00423 STUF3[cel_j] += m3; 00424 SURFACE_WAT[cel_j] += Flux; /* now update the surfwater depths */ 00425 } 00426 if (ON_MAP[cel_i]) { 00427 STUF1[cel_i] -= m1; 00428 STUF2[cel_i] -= m2; 00429 STUF3[cel_i] -= m3; 00430 SURFACE_WAT[cel_i] -= Flux; 00431 } 00432 00433 /* v2.7.0 sum of the velocities during the multiple iterations within a day (will be averaged in UnitMod.c) */ 00434 /* v2.8.4 the sum of velocities included flows into and out of cell, which, during looping, may have (?) tended to negate the desired sum 00435 When conditional with "if (Flux >0.0) " to only use fluxes in a single direction, no real diff, so have left it as it was */ 00436 SfWat_vel_day[cel_i] += sf_wt_veloc; 00437 00438 if (debug > 2) { 00439 if (STUF3[cel_j] < -GP_MinCheck) { 00440 sprintf(msgStr,"Day %6.1f: capacityERR - neg surface water P (%f kg) in cell (%d,%d) after SWfluxes!", 00441 SimTime.TIME, STUF3[cel_j], j0,j1 ); 00442 WriteMsg( msgStr,True ); dynERRORnum++;} 00443 if (STUF3[cel_i] < -GP_MinCheck) { 00444 sprintf(msgStr,"Day %6.1f: capacityERR - neg surface water P (%f kg) in cell (%d,%d) after SWfluxes!", 00445 SimTime.TIME, STUF3[cel_i], i0,i1 ); 00446 WriteMsg( msgStr,True ); dynERRORnum++; } 00447 if (STUF1[cel_j] < -GP_MinCheck) { 00448 sprintf(msgStr,"Day %6.1f: capacityERR - neg surface water S (%f kg) in cell (%d,%d) after SWfluxes!", 00449 SimTime.TIME, STUF1[cel_j], j0,j1 ); 00450 WriteMsg( msgStr,True ); dynERRORnum++; } 00451 if (STUF1[cel_i] < -GP_MinCheck) { 00452 sprintf(msgStr,"Day %6.1f: capacityERR - neg surface water S (%f kg) in cell (%d,%d) after SWfluxes!", 00453 SimTime.TIME, STUF1[cel_i], i0,i1 ); 00454 WriteMsg( msgStr,True ); dynERRORnum++; } 00455 if (SURFACE_WAT[cel_j] < -GP_MinCheck) { 00456 sprintf(msgStr,"Day %6.1f: capacityERR - negative surface water (%f m) in cell (%d,%d)!", 00457 SimTime.TIME, SURFACE_WAT[cel_j], j0,j1 ) ; 00458 WriteMsg( msgStr,True ); dynERRORnum++;} 00459 00460 if (SURFACE_WAT[cel_i] < -GP_MinCheck) { 00461 sprintf(msgStr,"Day %6.1f: capacityERR - negative surface water (%f m) in cell (%d,%d)!", 00462 SimTime.TIME, SURFACE_WAT[cel_i], i0,i1 ) ; 00463 WriteMsg( msgStr,True ); dynERRORnum++; } 00464 } 00465 00466 00467 /* mass balance sums */ 00468 if (basn[cel_i] != basn[cel_j]) { 00469 00470 /* first do the normal case where all cells are on-map */ 00471 if ( ON_MAP[cel_j] && ON_MAP[cel_i] ) { 00472 if ( Flux > 0 ) { /* positive fluxes out of basn[cel_i] */ 00473 if (basn_list[basn[cel_i]]->family != 00474 basn_list[basn[cel_j]]->family ) { /* if the flow is not within the family... */ 00475 if ( !basn_list[basn[cel_i]]->parent ) { /* and if the donor or recipient is a child... */ 00476 /* then find out about the flow for the family's sake */ 00477 VOL_OUT_OVL[basn_list[basn[cel_i]]->family] += Flux*CELL_SIZE; 00478 P_OUT_OVL[basn_list[basn[cel_i]]->family] += m3; 00479 S_OUT_OVL[basn_list[basn[cel_i]]->family] += m1; 00480 } 00481 if ( !basn_list[basn[cel_j]]->parent ) { 00482 /* then find out about the flow for the family's sake */ 00483 VOL_IN_OVL[basn_list[basn[cel_j]]->family] += Flux*CELL_SIZE; 00484 P_IN_OVL[basn_list[basn[cel_j]]->family] += m3; 00485 S_IN_OVL[basn_list[basn[cel_j]]->family] += m1; 00486 } 00487 /* now sum the parents' flows */ 00488 VOL_OUT_OVL[basn[cel_i]] += Flux*CELL_SIZE; 00489 P_OUT_OVL[basn[cel_i]] += m3; 00490 S_OUT_OVL[basn[cel_i]] += m1; 00491 VOL_IN_OVL[basn[cel_j]] += Flux*CELL_SIZE; 00492 P_IN_OVL[basn[cel_j]] += m3; 00493 S_IN_OVL[basn[cel_j]] += m1; 00494 00495 } 00496 else { /* if it's flow within a family, just keep 00497 track of what the children do among themselves */ 00498 if ( !basn_list[basn[cel_i]]->parent ) { 00499 VOL_OUT_OVL[basn[cel_i]] += Flux*CELL_SIZE; 00500 P_OUT_OVL[basn[cel_i]] += m3; 00501 S_OUT_OVL[basn[cel_i]] += m1; 00502 } 00503 if ( !basn_list[basn[cel_j]]->parent ) { 00504 VOL_IN_OVL[basn[cel_j]] += Flux*CELL_SIZE; 00505 P_IN_OVL[basn[cel_j]] += m3; 00506 S_IN_OVL[basn[cel_j]] += m1; 00507 } 00508 } 00509 00510 if (debug > 0 && WatMgmtOn) { /* check for basin misconfiguration (allowable basin-basin flows) */ 00511 basins = basn_list[basn[cel_i]]; 00512 flo_chek = 0; 00513 for (ii=0; ii<basins->numFLok; ii++) { if (basn[cel_j] == basins->FLok[ii] ) flo_chek = 1; } 00514 if (!flo_chek) { 00515 sprintf(msgStr,"Day %5.3f: ERROR - no (pos) SW flow from cell (%d,%d) of basin %d into cell (%d,%d) of basin %d!", 00516 SimTime.TIME, i0,i1,basn[cel_i], j0,j1, basn[cel_j]); 00517 WriteMsg( msgStr,True ); dynERRORnum++; } 00518 } 00519 00520 00521 } 00522 else { /* negative fluxes out of basn[cel_j] */ 00523 if (basn_list[basn[cel_i]]->family != 00524 basn_list[basn[cel_j]]->family ) { /* if the flow is not within the family... */ 00525 if ( !basn_list[basn[cel_j]]->parent ) { /* and if the donor or recipient is a child... */ 00526 /* then find out about the flow for the family's sake */ 00527 VOL_OUT_OVL[basn_list[basn[cel_j]]->family] -= Flux*CELL_SIZE; 00528 P_OUT_OVL[basn_list[basn[cel_j]]->family] -= m3; 00529 S_OUT_OVL[basn_list[basn[cel_j]]->family] -= m1; 00530 } 00531 if ( !basn_list[basn[cel_i]]->parent ) { 00532 /* then find out about the flow for the family's sake */ 00533 VOL_IN_OVL[basn_list[basn[cel_i]]->family] -= Flux*CELL_SIZE; 00534 P_IN_OVL[basn_list[basn[cel_i]]->family] -= m3; 00535 S_IN_OVL[basn_list[basn[cel_i]]->family] -= m1; 00536 } 00537 /* now sum the parents' flows */ 00538 VOL_OUT_OVL[basn[cel_j]] -= Flux*CELL_SIZE; 00539 P_OUT_OVL[basn[cel_j]] -= m3; 00540 S_OUT_OVL[basn[cel_j]] -= m1; 00541 VOL_IN_OVL[basn[cel_i]] -= Flux*CELL_SIZE; 00542 P_IN_OVL[basn[cel_i]] -= m3; 00543 S_IN_OVL[basn[cel_i]] -= m1; 00544 00545 } 00546 else { /* if it's flow within a family, just keep 00547 track of what the children do among themselves */ 00548 if ( !basn_list[basn[cel_j]]->parent ) { 00549 VOL_OUT_OVL[basn[cel_j]] -= Flux*CELL_SIZE; 00550 P_OUT_OVL[basn[cel_j]] -= m3; 00551 S_OUT_OVL[basn[cel_j]] -= m1; 00552 } 00553 if ( !basn_list[basn[cel_i]]->parent ) { 00554 VOL_IN_OVL[basn[cel_i]] -= Flux*CELL_SIZE; 00555 P_IN_OVL[basn[cel_i]] -= m3; 00556 S_IN_OVL[basn[cel_i]] -= m1; 00557 } 00558 } 00559 00560 00561 if (debug > 0 && WatMgmtOn) { /* check for basin misconfiguration (allowable basin-basin flows) */ 00562 basins = basn_list[basn[cel_j]]; 00563 flo_chek = 0; 00564 for (ii=0; ii<basins->numFLok; ii++) { if (basn[cel_i] == basins->FLok[ii] ) flo_chek = 1; } 00565 if (!flo_chek) { 00566 sprintf(msgStr,"Day %5.3f: ERROR - no (neg) SW flow from cell (%d,%d) of basin %d into cell (%d,%d) of basin %d!", 00567 SimTime.TIME, i0,i1, basn[cel_j], j0,j1, basn[cel_i]); 00568 WriteMsg( msgStr,True ); dynERRORnum++; } 00569 } 00570 00571 00572 } 00573 } 00574 else if ( !ON_MAP[cel_j]) /* so now the j,j cell is off-map, recipient if pos flow */ 00575 if (Flux > 0) { 00576 if ( !basn_list[basn[cel_i]]->parent ) { /* child's play */ 00577 VOL_OUT_OVL[basn_list[basn[cel_i]]->family] += Flux*CELL_SIZE; 00578 P_OUT_OVL[basn_list[basn[cel_i]]->family] += m3; 00579 S_OUT_OVL[basn_list[basn[cel_i]]->family] += m1; 00580 } 00581 /* parents' play */ 00582 VOL_OUT_OVL[basn[cel_i]] += Flux*CELL_SIZE; 00583 VOL_OUT_OVL[0]+= Flux*CELL_SIZE; 00584 P_OUT_OVL[basn[cel_i]] += m3; 00585 P_OUT_OVL[0]+= m3; 00586 S_OUT_OVL[basn[cel_i]] += m1; 00587 S_OUT_OVL[0]+= m1; 00588 } 00589 else { /* negative flows */ 00590 if ( !basn_list[basn[cel_i]]->parent ) {/* child's play */ 00591 VOL_IN_OVL[basn_list[basn[cel_i]]->family] -= Flux*CELL_SIZE; 00592 P_IN_OVL[basn_list[basn[cel_i]]->family] -= m3; 00593 S_IN_OVL[basn_list[basn[cel_i]]->family] -= m1; 00594 } 00595 /* parents' play */ 00596 VOL_IN_OVL[basn[cel_i]] -= Flux*CELL_SIZE; 00597 VOL_IN_OVL[0] -= Flux*CELL_SIZE; 00598 P_IN_OVL[basn[cel_i]] -= m3; 00599 P_IN_OVL[0] -= m3; 00600 S_IN_OVL[basn[cel_i]] -= m1; 00601 S_IN_OVL[0] -= m1; 00602 } 00603 else if ( !ON_MAP[cel_i]) /* so now the i,i cell is off-map, donor if pos flow */ 00604 if (Flux > 0) { 00605 if ( !basn_list[basn[cel_j]]->parent ) {/* child's play */ 00606 VOL_IN_OVL[basn_list[basn[cel_j]]->family] += Flux*CELL_SIZE; 00607 P_IN_OVL[basn_list[basn[cel_j]]->family] += m3; 00608 S_IN_OVL[basn_list[basn[cel_j]]->family] += m1; 00609 } 00610 /* parents' play */ 00611 VOL_IN_OVL[basn[cel_j]] += Flux*CELL_SIZE; 00612 VOL_IN_OVL[0] += Flux*CELL_SIZE; 00613 P_IN_OVL[basn[cel_j]] += m3; 00614 P_IN_OVL[0] += m3; 00615 S_IN_OVL[basn[cel_j]] += m1; 00616 S_IN_OVL[0] += m1; 00617 } 00618 else { /*negative flows */ 00619 if ( !basn_list[basn[cel_j]]->parent ) {/* child's play */ 00620 VOL_OUT_OVL[basn_list[basn[cel_j]]->family] -= Flux*CELL_SIZE; 00621 P_OUT_OVL[basn_list[basn[cel_j]]->family] -= m3; 00622 S_OUT_OVL[basn_list[basn[cel_j]]->family] -= m1; 00623 } 00624 /* parents' play */ 00625 VOL_OUT_OVL[basn[cel_j]] -= Flux*CELL_SIZE; 00626 VOL_OUT_OVL[0] -= Flux*CELL_SIZE; 00627 P_OUT_OVL[basn[cel_j]] -= m3; 00628 P_OUT_OVL[0] -= m3; 00629 S_OUT_OVL[basn[cel_j]] -= m1; 00630 S_OUT_OVL[0] -= m1; 00631 } 00632 } 00633 00634 return; 00635 00636 }
FILE* schedFile |
File pointer to the schedule data file
Definition at line 43 of file watmgmt.h.
Referenced by Read_schedule().
FILE* ChanInFile |
File pointer to several (opened-closed) input files
Definition at line 44 of file watmgmt.h.
Referenced by Canal_Network_Init(), ReadChanStruct(), and ReadStructures().
FILE* CanalOutFile |
File pointer to canal hydrologic output file
Definition at line 45 of file watmgmt.h.
Referenced by Canal_Network_Init(), and Run_Canal_Network().
FILE* CanalOutFile_P |
File pointer to canal phosphorus output file
Definition at line 46 of file watmgmt.h.
Referenced by Canal_Network_Init(), and Run_Canal_Network().
FILE* CanalOutFile_S |
File pointer to canal salt/tracer output file
Definition at line 47 of file watmgmt.h.
Referenced by Canal_Network_Init(), and Run_Canal_Network().
FILE* WstructOutFile |
File pointer to water control structure hydrologic output file
Definition at line 48 of file watmgmt.h.
Referenced by Canal_Network_Init(), Flows_in_Structures(), and Run_Canal_Network().
FILE* WstructOutFile_P |
File pointer to water control structure phosphorus output file
Definition at line 49 of file watmgmt.h.
Referenced by Canal_Network_Init(), Flows_in_Structures(), and Run_Canal_Network().
FILE* WstructOutFile_S |
File pointer to water control structure salt/tracer output file
Definition at line 50 of file watmgmt.h.
Referenced by Canal_Network_Init(), Flows_in_Structures(), and Run_Canal_Network().
FILE* canDebugFile |
File pointer to canal debug file
Definition at line 51 of file watmgmt.h.
Referenced by Canal_Network_Init(), flowData_CanCan(), flowData_CanCel(), flowData_CelCan(), flowData_CelCel(), FluxChannel(), and Run_Canal_Network().
FILE* CanalCellInteractDebug |
File pointer to canal-cell interaction file
Definition at line 52 of file watmgmt.h.
Referenced by Channel_configure(), getCanalElev(), and MarkCell().
FILE* F_struct_wat |
File pointer to the water control structure flow data file
Definition at line 53 of file watmgmt.h.
Referenced by ReadStructFlow_PtSer().
FILE* F_struct_TP |
File pointer to the water control structure TP data file
Definition at line 54 of file watmgmt.h.
Referenced by ReadStructTP_PtSer().
FILE* F_struct_TS |
File pointer to the water control structure TS (salt/tracer) data file
Definition at line 55 of file watmgmt.h.
Referenced by ReadStructTS_PtSer().
int CHo |
the number of the first canal in Chan.file sequence
Definition at line 57 of file watmgmt.h.
Referenced by Channel_configure(), flowCalc_CanCan(), flowCalc_CanCel(), flowCalc_CelCan(), flowData_CanCan(), flowData_CanCel(), flowData_CelCan(), FluxChannel(), getCanalElev(), ReadChanStruct(), and ReadStructures().
int CHANNEL_MAX_ITER |
maximal number of iterations in relaxation procedure (input data)
Definition at line 58 of file watmgmt.h.
Referenced by FluxChannel(), and ReadChanStruct().
int UTM_EOrigin |
int UTM_NOrigin |
Map origin, easting and northing UTM
Definition at line 59 of file watmgmt.h.
Referenced by ReadChanStruct(), and UTM2kmx().
int printchan = 0 |
flag to indicate time to print canal/struct data
Definition at line 60 of file watmgmt.h.
Referenced by Flows_in_Structures(), and Run_Canal_Network().
int N_c_iter = 0 |
cumulative number of iterations through canal code
Definition at line 61 of file watmgmt.h.
Referenced by Run_Canal_Network().
int num_cell = 0 |
counter of number cells along a reach segment
Definition at line 62 of file watmgmt.h.
Referenced by Channel_configure().
int C_Mark = 0 |
indicator that a cell is marked with a canal already
Definition at line 63 of file watmgmt.h.
Referenced by Channel_configure(), and MarkCell().
float C_F |
acceleration of overland flow for canal/cell interactions - for sensitivity experiments only
Definition at line 65 of file watmgmt.h.
Referenced by Channel_configure(), and ReadChanStruct().
float F_ERROR |
convergence error for relaxation procedure in canals
Definition at line 66 of file watmgmt.h.
Referenced by FluxChannel(), and ReadChanStruct().
float MINDEPTH |
minimal allowed water depth in canal
Definition at line 67 of file watmgmt.h.
Referenced by Channel_configure(), flowCalc_CanCan(), flowCalc_CanCel(), flowData_CanCan(), flowData_CanCel(), FluxChannel(), and ReadChanStruct().
int num_chan |
number of channels (canals)
Definition at line 69 of file watmgmt.h.
Referenced by Canal_Network_Init(), CanalReInit(), Channel_configure(), ReadChanStruct(), ReadStructures(), and Run_Canal_Network().
int num_struct_hist |
number of structures driven by data
Definition at line 70 of file watmgmt.h.
Referenced by ReadStructFlow_PtSer(), ReadStructTP_PtSer(), ReadStructTS_PtSer(), and ReadStructures().
int numTPser |
number of structures with hist TP data
Definition at line 71 of file watmgmt.h.
Referenced by ReadStructTP_PtSer(), and ReadStructures().
int numTSser |
number of structures hist TS (TotalSalt/tracer) data
Definition at line 72 of file watmgmt.h.
Referenced by ReadStructTS_PtSer(), and ReadStructures().
int disAggNum |
v2.6 number of disaggregated water control structure flows
Definition at line 73 of file watmgmt.h.
Referenced by ReadStructFlow_PtSer(), ReadStructTP_PtSer(), ReadStructTS_PtSer(), and ReadStructures().
int IDhist[MAX_H_STRUCT] |
v2.6 ID of historical data set of water control structure time series data
Definition at line 74 of file watmgmt.h.
Referenced by ReadStructTP_PtSer(), ReadStructTS_PtSer(), and ReadStructures().
float* MCopen |
manning's coef for open water, fixed parameter for all domain (used in structure flow for bridges)
Definition at line 77 of file watmgmt.h.
Referenced by Canal_Network_Init(), and flowCalc_CelCel().
char modelFileName[300] |
Definition at line 134 of file watmgmt.h.
Referenced by Canal_Network_Init(), CanalReInit(), Channel_configure(), flowCalc_CanCan(), flowCalc_CanCel(), flowCalc_CelCan(), flowData_CanCan(), flowData_CanCel(), flowData_CelCan(), FluxChannel(), getCanalElev(), ReadStructures(), and Run_Canal_Network().
Definition at line 149 of file watmgmt.h.
Referenced by Channel_configure(), FluxChannel(), getCanalElev(), and HabSwitch().
struct Structure* struct_first |
Definition at line 200 of file watmgmt.h.
Referenced by Canal_Network_Init(), Flows_in_Structures(), FluxChannel(), ReadStructFlow_PtSer(), and ReadStructures().
Definition at line 201 of file watmgmt.h.
Referenced by Canal_Network_Init(), Flows_in_Structures(), FluxChannel(), ReadStructFlow_PtSer(), and ReadStructures().
pointer to array of pointers for the water control structure time series
Definition at line 230 of file watmgmt.h.
Referenced by flowCalc_CelCan(), flowData_CanCan(), flowData_CanCel(), flowData_CelCan(), flowData_CelCel(), ReadStructFlow_PtSer(), ReadStructTP_PtSer(), ReadStructTS_PtSer(), and ReadStructures().
int NumScheds = 0 |
char* ModelPath |
Definition at line 40 of file driver_utilities.h.
char * OutputPath |
base pathname for all model output (user input)
Definition at line 42 of file driver_utilities.h.
char * ProjName |
Definition at line 40 of file driver_utilities.h.
char modelName[20] |
Definition at line 48 of file driver_utilities.h.
char modelVers[10] |
Definition at line 48 of file driver_utilities.h.
char SimAlt[20] |
simulation scenario/alterative name
Definition at line 42 of file generic_driver.h.
Referenced by BIRoutfiles(), Canal_Network_Init(), get_parmf(), open_point_lists(), Read_schedule(), ReadChanStruct(), ReadStructFlow_PtSer(), ReadStructTP_PtSer(), ReadStructTS_PtSer(), ReadStructures(), and writeFloatNetCDF().
char SimModif[20] |
simulation scenario/alterative modifier name/note
Definition at line 43 of file generic_driver.h.
Referenced by BIRoutfiles(), Canal_Network_Init(), get_parmf(), open_point_lists(), ReadStructures(), and writeFloatNetCDF().
double Jdate_init |
julian day (since epochs ago) of the initialization of model
Definition at line 49 of file generic_driver.h.
Referenced by get_parmf(), readSeriesCol(), ReadStructFlow_PtSer(), ReadStructTP_PtSer(), ReadStructTS_PtSer(), send_point_lists2(), and track_time().
double Jdate_end |
julian day (since epochs ago) of the ending of model
Definition at line 50 of file generic_driver.h.
Referenced by get_parmf(), ReadStructFlow_PtSer(), ReadStructTP_PtSer(), and ReadStructTS_PtSer().
int PORnumday |
number of days of simulation Period Of Record (incl. start day)
Definition at line 65 of file generic_driver.h.
Referenced by get_parmf(), processData(), readSeriesCol(), ReadStructFlow_PtSer(), ReadStructTP_PtSer(), ReadStructTS_PtSer(), and track_time().
float can_Intvl |
time (day) interval between canal (water management) summaries
Definition at line 75 of file generic_driver.h.
Referenced by get_parmf(), and track_time().
int canPrint |
boolean flag to indicate if canal data is to be printed at current time
Definition at line 82 of file generic_driver.h.
Referenced by Run_Canal_Network(), and track_time().
unsigned char* HAB |
_Units_: dimless; _Brief_: Habitat, or vegetation community type (integer attribute, defining database parameter lookups)
Definition at line 74 of file unitmod_vars.h.
int* basn |
_Units_: dimless; _Brief_: Map array defining hydrologic basins and Indicator Regions
Definition at line 136 of file unitmod_vars.h.
float GP_DetentZ |
Global parameter. _Units_: m; _Brief_: ***detention depth in a grid cell, below which surface flows do not occur; _Extended_: scale-dependent relative to topographic heterogeneity
Definition at line 45 of file unitmod_globparms.h.
float GP_MinCheck |
Global parameter. _Units_: m; _Brief_: ***small threshold number, for relative error-checking (not a multiplier etc); _Extended_: only used in constraining fluxes at extremely mimimal conditions
Definition at line 47 of file unitmod_globparms.h.
float GP_SLRise |
Global parameter. _Units_: m/yr; _Brief_: ***rate of Sea Level Rise; _Extended_: based on CERP Guidance Memo 016.00
Definition at line 50 of file unitmod_globparms.h.
Referenced by Flows_in_Structures(), and ReadGlobalParms().
float GP_mannDepthPow |
Global parameter. _Units_: dimless; _Brief_: ***power used in manning's equation water depth; _Extended_: for "true" manning's, use 1.667
Definition at line 35 of file unitmod_globparms.h.
float GP_mannHeadPow |
Global parameter. _Units_: dimless; _Brief_: ***power used in manning's equation head difference; _Extended_: for "true" manning's, use 0.5
Definition at line 36 of file unitmod_globparms.h.
float GP_calibGWat |
Global parameter. _Units_: dimless; _Brief_: ***calibration parameter, multiply by aquifer hydraulic conductivity, levee seepage; _Extended_:
Definition at line 37 of file unitmod_globparms.h.
Referenced by Channel_configure(), init_eqns(), and ReadGlobalParms().
int numBasn |
number of basins in model domain
Definition at line 33 of file budgstats.h.
Basin/Indicator Region data
Definition at line 31 of file budgstats.h.
Basin/Indicator Region data
Definition at line 32 of file budgstats.h.
double* TOT_VOL_CAN |
_Units_: m^3; _Brief_:
Definition at line 34 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_reset(), BIRbudg_sumFinal(), and Run_Canal_Network().
double* VOL_IN_STR |
_Units_: m^3; _Brief_:
Definition at line 45 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_print(), BIRbudg_reset(), BIRbudg_sumFinal(), flowCalc_CanCel(), flowCalc_CelCan(), flowData_CanCan(), flowData_CanCel(), flowData_CelCan(), and flowData_CelCel().
double * VOL_IN_OVL |
_Units_: m^3; _Brief_:
Definition at line 43 of file budgstats_birvars.h.
double * VOL_IN_SPG |
_Units_: m^3; _Brief_:
Definition at line 44 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_print(), BIRbudg_reset(), BIRbudg_sumFinal(), and FluxChannel().
double * VOL_IN_GW |
_Units_: m^3; _Brief_:
Definition at line 42 of file budgstats_birvars.h.
double* VOL_OUT_STR |
_Units_: m^3; _Brief_:
Definition at line 52 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_print(), BIRbudg_reset(), BIRbudg_sumFinal(), flowCalc_CanCel(), flowData_CanCan(), flowData_CanCel(), flowData_CelCan(), and flowData_CelCel().
double * VOL_OUT_OVL |
_Units_: m^3; _Brief_:
Definition at line 50 of file budgstats_birvars.h.
double * VOL_OUT_SPG |
_Units_: m^3; _Brief_:
Definition at line 51 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_print(), BIRbudg_reset(), BIRbudg_sumFinal(), and FluxChannel().
double * VOL_OUT_GW |
_Units_: m^3; _Brief_:
Definition at line 49 of file budgstats_birvars.h.
double* TOT_P_CAN |
_Units_: kgP; _Brief_:
Definition at line 74 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_reset(), BIRbudg_sumFinal(), and Run_Canal_Network().
double* P_IN_STR |
_Units_: kgP; _Brief_:
Definition at line 63 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_print(), BIRbudg_reset(), BIRbudg_sumFinal(), flowCalc_CanCel(), flowCalc_CelCan(), flowData_CanCan(), flowData_CanCel(), flowData_CelCan(), and flowData_CelCel().
double * P_IN_OVL |
_Units_: kgP; _Brief_:
Definition at line 61 of file budgstats_birvars.h.
double * P_IN_SPG |
_Units_: kgP; _Brief_:
Definition at line 62 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_print(), BIRbudg_reset(), BIRbudg_sumFinal(), and FluxChannel().
double * P_IN_GW |
_Units_: kgP; _Brief_:
Definition at line 60 of file budgstats_birvars.h.
double* P_OUT_STR |
_Units_: kgP; _Brief_:
Definition at line 71 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_print(), BIRbudg_reset(), BIRbudg_sumFinal(), flowCalc_CanCel(), flowData_CanCan(), flowData_CanCel(), flowData_CelCan(), and flowData_CelCel().
double * P_OUT_OVL |
_Units_: kgP; _Brief_:
Definition at line 69 of file budgstats_birvars.h.
double * P_OUT_SPG |
_Units_: kgP; _Brief_:
Definition at line 70 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_print(), BIRbudg_reset(), BIRbudg_sumFinal(), and FluxChannel().
double * P_OUT_GW |
_Units_: kgP; _Brief_:
Definition at line 68 of file budgstats_birvars.h.
double* TOT_S_CAN |
_Units_: kgSalt; _Brief_:
Definition at line 145 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_reset(), BIRbudg_sumFinal(), and Run_Canal_Network().
double* S_IN_STR |
_Units_: kgSalt; _Brief_:
Definition at line 134 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_print(), BIRbudg_reset(), BIRbudg_sumFinal(), flowCalc_CanCel(), flowCalc_CelCan(), flowData_CanCan(), flowData_CanCel(), flowData_CelCan(), and flowData_CelCel().
double * S_IN_OVL |
_Units_: kgSalt; _Brief_:
Definition at line 132 of file budgstats_birvars.h.
double * S_IN_SPG |
_Units_: kgSalt; _Brief_:
Definition at line 133 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_print(), BIRbudg_reset(), BIRbudg_sumFinal(), and FluxChannel().
double * S_IN_GW |
_Units_: kgSalt; _Brief_:
Definition at line 131 of file budgstats_birvars.h.
double* S_OUT_STR |
_Units_: kgSalt; _Brief_:
Definition at line 141 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_print(), BIRbudg_reset(), BIRbudg_sumFinal(), flowCalc_CanCel(), flowData_CanCan(), flowData_CanCel(), flowData_CelCan(), and flowData_CelCel().
double * S_OUT_OVL |
_Units_: kgSalt; _Brief_:
Definition at line 139 of file budgstats_birvars.h.
double * S_OUT_SPG |
_Units_: kgSalt; _Brief_:
Definition at line 140 of file budgstats_birvars.h.
Referenced by alloc_mem_stats(), BIRbudg_print(), BIRbudg_reset(), BIRbudg_sumFinal(), and FluxChannel().
double * S_OUT_GW |
_Units_: kgSalt; _Brief_:
Definition at line 138 of file budgstats_birvars.h.