Ecological Landscape Modeling: Models Pages

Fluxes.c

Go to the documentation of this file.
00001 
00023 /* double precision for all constituent vars */
00024 
00025 /* General NOTES on revisions to this source file:
00026         April 00 VERSION 2.1 - output available for application for water quality performance
00027         July 02 VERSIOIN 2.1a - first widely-available public release of code -
00028               - made a start at adding dynamic stage boundary conditions - INCOMPLETE, not functional
00029               - added some more code documentation, etc.
00030 
00031         July 2004 VERSION 2.2.1 - added dynamic stage boundary conditions
00032               - in globals (celldyn1) module of UnitMod.c, have read daily, coarse-grid boundary stage data
00033               - in this version, we have not turned on that new boundary condition code, still using v2.1 
00034                 estimated boundary conditions
00035         Aug 2004 VERSION 2.3.0 - added dynamic boundary conditions 
00036                 - used new spatial time series data input for dynamic boundary conditions
00037         Oct 2004 VERSION 2.3.1 - internal release 
00038                 - checked that results reasonable, not fully checked
00039         Nov 2004 VERSION 2.3.2 - documentation upgrade
00040         Jan 2005 v2.4.0 - encoded the AND dispersion
00041         Oct 2006 v2.6.0: added more boundary condition functionality
00042                 - added model-experiment parameters (ModExperimParms_NOM, boundary condition experiments for non-gridIO data)
00043             - omission found in surface water flows with external cells (e.g., boundary of Big Cypress in regional ELM), 
00044                 where the external cell was expected to have stage (output from SFWMM), but it was provided (SFWMM) data on depth.
00045                 (Stage was correctly derived for the groundwater flows with external cells, which is where the high-volume, 
00046                 critical flows occur). 
00047         Nov 2006 v2.6.0: enhanced documentation for release
00048         Oct 2007 v2.7.0: added functionality of calc'ing surface water flow velocities
00049                 - new variable of surface water flow velocities
00050                 - fixed bug (identified in Oct '06) in auto-scaling of dispersion among model grids of diff sizes
00051                 - fixed bug (identified in Oct '06) in boundary condition surface water flows
00052                 
00053 
00054 */
00055 
00056 #include "fluxes.h" 
00057 
00058 
00059 /*************************************************************************************************/
00121 void Flux_SWater(int it, float *SURFACE_WAT,float *SED_ELEV,float *HYD_MANNINGS_N, 
00122                  double *STUF1, double *STUF2, double *STUF3, float *SfWat_vel_day)
00123 { 
00129 int ix, iy;
00130   float FFlux;
00131 
00132 
00133   
00134   /* check the donor and recipients cells for a) on-map, b) the cell attribute that allows sfwater
00135      boundary flow from the system and c) the attribute that indicates levee presence:
00136      the levee attribute of 1 (bitwise) allows flow to east;
00137      attribute of 2 (bitwise) allows flow to south (levee atts calc'd by WatMgmt.c) 
00138    */
00139 
00140   /* as always, x is row, y is column! */
00141   for(ix=1; ix<=s0; ix++) 
00142   {
00143     if (it%2)   /* alternate loop directions every other hyd_iter (it) */
00144     {
00145       for(iy=1; iy<=s1; iy++)  /* loop from west to east */
00146       {
00147         if( ( ON_MAP[T(ix,iy)] && ON_MAP[T(ix,iy+1)] && (int)(ON_MAP[T(ix,iy)]-1) & 1  ) || 
00148               BCondFlow[T(ix,iy+1)] == 3 ||  BCondFlow[T(ix,iy)] == 3  )
00149         {
00150           FFlux = Flux_SWcells(ix,iy,ix,iy+1,SURFACE_WAT,SED_ELEV,HYD_MANNINGS_N); 
00151           /* FFlux units = m */
00152           if (FFlux != 0.0) 
00153             Flux_SWstuff ( ix,iy,ix,iy+1,FFlux,SURFACE_WAT,STUF1,STUF2,STUF3,SfWat_vel_day);
00154 
00155         } /* endof if */
00156       } /* end of for */
00157     }  /* end of if */
00158      
00159 
00160     else 
00161     { 
00162       for(iy=s1; iy>=1; iy--)   /* loop from east to west */
00163         if( ( ON_MAP[T(ix,iy)] && ON_MAP[T(ix,iy-1)] && (int)(ON_MAP[T(ix,iy-1)]-1) & 1 ) || 
00164               BCondFlow[T(ix,iy-1)] == 3 || BCondFlow[T(ix,iy)] == 3  )
00165         {
00166           FFlux = Flux_SWcells(ix,iy-1,ix,iy,SURFACE_WAT,SED_ELEV,HYD_MANNINGS_N); 
00167                                 /* FFlux units = m */
00168           if (FFlux != 0.0) 
00169             Flux_SWstuff ( ix,iy-1,ix,iy,FFlux,SURFACE_WAT,STUF1,STUF2,STUF3,SfWat_vel_day);
00170 
00171         }  /* end of if */
00172     }  /* end of else */
00173   }
00174         
00175   for(iy=1; iy<=s1; iy++) 
00176   {
00177     if (it%2)   /* alternate loop directions every other hyd_iter (it) */
00178     {
00179       for(ix=1; ix<=s0; ix++)  /* loop from north to south */
00180         if( ( ON_MAP[T(ix,iy)] && ON_MAP[T(ix+1,iy)]  && (int)(ON_MAP[T(ix,iy)]-1) & 2 ) ||
00181               BCondFlow[T(ix+1,iy)] == 3 || BCondFlow[T(ix,iy)] == 3  )
00182         { 
00183           FFlux = Flux_SWcells(ix,iy,ix+1,iy,SURFACE_WAT,SED_ELEV,HYD_MANNINGS_N); 
00184           /* FFlux units = m */
00185           if (FFlux != 0.0) 
00186             Flux_SWstuff ( ix,iy,ix+1,iy,FFlux,SURFACE_WAT,STUF1,STUF2,STUF3,SfWat_vel_day);
00187         }
00188     } 
00189 
00190 
00191     else 
00192     { 
00193       for(ix=s0; ix>=1; ix--)  /* loop from south to north */
00194         if( ( ON_MAP[T(ix,iy)] && ON_MAP[T(ix-1,iy)] && (int)(ON_MAP[T(ix-1,iy)]-1) & 2 ) ||
00195               BCondFlow[T(ix-1,iy)] == 3 || BCondFlow[T(ix,iy)] == 3  )
00196         {
00197              
00198           FFlux = Flux_SWcells(ix-1,iy,ix,iy,SURFACE_WAT,SED_ELEV,HYD_MANNINGS_N); 
00199           /* FFlux units = m */
00200           if (FFlux != 0.0) 
00201             Flux_SWstuff ( ix-1,iy,ix,iy,FFlux,SURFACE_WAT,STUF1,STUF2,STUF3,SfWat_vel_day);
00202 
00203         } /* end of if */
00204     } /* end of else */
00205   } /* end of for */
00206 
00207 } /* end of function */
00208 
00209 
00210 
00211 
00212 /************************************************************************************************/
00231 float Flux_SWcells(int i0,int i1,int j0,int j1, float *SWater,float *Elevation,float *MC)
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 }
00360 
00361 
00362 /*************************************************************************************************/
00383 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)
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 }
00637 
00638 /*************************************************************************************************/
00649 double Veloc_Calc(float flux, float depth_i, float depth_j, float tim_step)
00650 {
00651         double sf_wt_veloc_mag;
00652         
00653         sf_wt_veloc_mag =  Abs(flux) * celWid/( (flux>0.0) ? (depth_i) : (depth_j) ) / (tim_step) ;
00654 //if (flux > 0) printf("depth= %f; Flux= %f; Velo= %f",depth_i,flux,sf_wt_veloc_mag);
00655         return (sf_wt_veloc_mag);
00656 }
00657 
00658 /*************************************************************************************************/
00670 float Disp_Calc(float flux, float depth_i, float depth_j, float tim_step, double sf_wt_veloc)
00671 {
00672     float disp_num; /* numerical dispersion in current model grid (m2/d) */
00673     float disp_num_targ; /*  targeted numerical dispersion (associated w/ grid size of the targeted dispersion length parameter) (m2/d) */
00674     float veloc_adj;  /* horizontal velocity associated w/ constituent flow, adjusted for the targeted numerical dispersion (m/d) */
00675     float flux_adj; /* flux (height) associated w/ constituents, adjusted for numerical dispersioin */
00676     extern float GP_dispLenRef, GP_dispParm; /* from unitmod.h */
00677 
00678     disp_num = 0.5 * sf_wt_veloc * (celWid - sf_wt_veloc * tim_step)  ; 
00679     disp_num_targ = 0.5 * sf_wt_veloc * (GP_dispLenRef - sf_wt_veloc * tim_step)  ; 
00680     veloc_adj = GP_dispParm * (sf_wt_veloc * celWid - disp_num + disp_num_targ )/celWid; 
00681     flux_adj = veloc_adj * tim_step * ( (flux>0.0) ? (depth_i) : (depth_j) )/celWid;
00682     return (flux_adj); /* return the height-flux that was adjusted (decreased/increased) due to dispersion */
00683 }
00684 
00685 
00686 /*************************************************************************************************/
00721 void Flux_GWater(int it, float *SatWat, float *Unsat, float *SfWat,
00722                   float *rate, float *poros, float *sp_yield, float *elev,
00723                   double *gwSTUF1, double *gwSTUF2, double *gwSTUF3,
00724                   double *swSTUF1, double *swSTUF2, double *swSTUF3)
00725 
00726 { 
00727   int ix, iy; /* ix is row, iy is col! */
00728 /* we only check the donor cell for on-map, allowing losses from the system */
00729  for(ix=1; ix<=s0; ix++) 
00730  {
00731      if (it%2) {  /* alternate loop directions every other iteration (it = int(hyd_iter-1)/2 ) */
00732      for(iy=1; iy<=s1; iy++)  /* loop from west to east */
00733              /* allow boundary flow if donor cell is marked 3 or higher (v2.5 had specific markings of 4 or 9, no longer pertinent in v2.6+) */
00734              if (( ON_MAP[T(ix,iy)] && ON_MAP[T(ix,iy+1)]) || 
00735                 ((BCondFlow[T(ix,iy+1)]) > 2) || ((BCondFlow[T(ix,iy)]) > 2) ) 
00736          {
00737              Flux_GWcells(ix,iy,ix,iy+1,SatWat, Unsat, SfWat, rate, poros, sp_yield, elev,
00738                           gwSTUF1, gwSTUF2, gwSTUF3, swSTUF1, swSTUF2, swSTUF3); 
00739          }
00740      } 
00741              
00742      else { 
00743      for(iy=s1; iy>=1; iy--)   /* loop from east to west */
00744              /* allow boundary flow if donor cell is marked 3 or higher  (v2.5 had specific markings of 4 or 9, no longer pertinent in v2.6+) */
00745          if (( ON_MAP[T(ix,iy)] && ON_MAP[T(ix,iy-1)]) || 
00746                 ((BCondFlow[T(ix,iy-1)]) > 2) || ((BCondFlow[T(ix,iy)]) > 2) ) 
00747          {
00748          
00749              Flux_GWcells(ix,iy,ix,iy-1,SatWat, Unsat, SfWat, rate, poros, sp_yield, elev,
00750                           gwSTUF1, gwSTUF2, gwSTUF3, swSTUF1, swSTUF2, swSTUF3); 
00751          }
00752      } 
00753  }
00754         
00755  for(iy=1; iy<=s1; iy++) 
00756  {
00757      if (it%2) {  /* alternate loop directions every other iteration (it = int(hyd_iter-1)/2 ) */
00758      for(ix=1; ix<=s0; ix++)  /* loop from north to south */
00759              /* allow boundary flow if donor cell is marked 3 or higher  (v2.5 had specific markings of 4 or 9, no longer pertinent in v2.6+) */
00760          if (( ON_MAP[T(ix,iy)] && ON_MAP[T(ix+1,iy)]) || 
00761                 ((BCondFlow[T(ix+1,iy)]) > 2) || ((BCondFlow[T(ix,iy)]) > 2) ) 
00762          {
00763          
00764              Flux_GWcells(ix,iy,ix+1,iy,SatWat, Unsat, SfWat, rate, poros, sp_yield, elev,
00765                           gwSTUF1, gwSTUF2, gwSTUF3, swSTUF1, swSTUF2, swSTUF3); 
00766          }
00767          } 
00768      else { 
00769      for(ix=s0; ix>=1; ix--)  /* loop from south to north */
00770              /* allow boundary flow if donor cell is marked 3 or higher  (v2.5 had specific markings of 4 or 9, no longer pertinent in v2.6+) */
00771          if (( ON_MAP[T(ix,iy)] && ON_MAP[T(ix-1,iy)]) || 
00772                 ((BCondFlow[T(ix-1,iy)]) > 2) || ((BCondFlow[T(ix,iy)]) > 2) ) 
00773          {
00774          
00775              Flux_GWcells(ix,iy,ix-1,iy,SatWat, Unsat, SfWat, rate, poros, sp_yield, elev,
00776                           gwSTUF1, gwSTUF2, gwSTUF3, swSTUF1, swSTUF2, swSTUF3); 
00777          }
00778      } 
00779  }
00780 
00781 }
00782 
00783 /************************************************************************************************/
00815 void Flux_GWcells( int i0, int i1, int j0, int j1, float *SatWat, float *Unsat, float *SfWat, 
00816                     float *rate, float *poros, float *sp_yield, float *elev,
00817                     double *gwSTUF1, double *gwSTUF2, double *gwSTUF3,
00818                     double *swSTUF1, double *swSTUF2, double *swSTUF3)
00819 {       
00820             
00855     int cell_don, cell_rec, cell_i, cell_j;
00856     int sign, equilib, revers=1;
00857     float GW_head_i,GW_head_j,tot_head_i,tot_head_j;
00858     float dh;
00859     float AvgRate;
00860 
00861     float H_pot_don, H_pot_rec;
00862     
00863     double Flux;
00864     double fluxTOunsat_don;
00865     double fluxHoriz; 
00866 
00867     float Sat_vs_unsat;
00868 
00869     double UnsatZ_don, UnsatCap_don, UnsatPot_don; 
00870     double UnsatZ_rec, UnsatCap_rec, UnsatPot_rec; 
00871     double sfTOsat_don, unsatTOsat_don, unsatTOsat_rec, satTOsf_rec, horizTOsat_rec; 
00872     
00873     double sedwat_don, sedwat_rec;
00874     double sf_stuf1fl_don, sf_stuf2fl_don, sf_stuf3fl_don; 
00875     double sed_stuf1fl_horz, sed_stuf2fl_horz, sed_stuf3fl_horz; 
00876     double sed_stuf1fl_rec, sed_stuf2fl_rec, sed_stuf3fl_rec; 
00877 
00878     
00879     cell_i = T(i0,i1); 
00880     cell_j = T(j0,j1);
00881     
00882     if (ON_MAP[cell_i] ) {
00883         GW_head_i = SatWat[cell_i] / poros[HAB[cell_i]]; 
00884         tot_head_i = GW_head_i + SfWat[cell_i];
00885     }
00886     
00887     if (ON_MAP[cell_j] ) {
00888         GW_head_j = SatWat[cell_j] / poros[HAB[cell_j]]; 
00889         tot_head_j = GW_head_j + SfWat[cell_j];
00890     }
00891     
00902     if (!ON_MAP[cell_i] ) { /* for an external i0,i1 cell */
00903         poros[HAB[cell_i]] = poros[HAB[cell_j]]; /* other variables = donor cell or zero */
00904         sp_yield[HAB[cell_i]] = sp_yield[HAB[cell_j]]; 
00905         elev[cell_i] = elev[cell_j];
00906         rate[cell_i] = rate[cell_j];
00907         Unsat[cell_i] = 0.0; /* no water in any potential unsat zone */
00908 
00909             /* outflow of groundwater from boundary cell*/
00910         if (BCondFlow[cell_j] > 2)  { /* v2.6  (v2.5 had specific markings of 4 or 9, no longer pertinent in v2.6+)  */
00911             if (boundcond_depth[cell_i] > 0.0) /* boundcond_depth= positive or negative water depth relative to land surface elev */
00912             {
00913                 SatWat[cell_i] =  elev[cell_i] * poros[HAB[cell_i]];    
00914                 SfWat[cell_i] = boundcond_depth[cell_i]; 
00915             }
00916         else
00917             {
00918                 SatWat[cell_i] =  (elev[cell_i] + boundcond_depth[cell_i]) * poros[HAB[cell_i]];  
00919                 SfWat[cell_i] = 0.0; 
00920             }
00921         }
00922     
00923     GW_head_i = SatWat[cell_i] / poros[HAB[cell_i]]; 
00924     tot_head_i = GW_head_i + SfWat[cell_i];
00925     
00926             /* v2.6 when we don't have data on boundary condition heads */
00927     if ( isModExperim ) { 
00928         if (j0 < GP_BC_InputRow) {
00929                 tot_head_i = tot_head_j /* + GP_BC_SatWat_add */ ;
00930         } 
00931         else {
00932                 tot_head_i = (SfWat[cell_j] > GP_BC_SatWat_add) ? (tot_head_j - GP_BC_SatWat_add) : (tot_head_j);
00933         }
00934     } /* end of isModExperim */
00935     
00936     }
00937 
00938     if (!ON_MAP[cell_j] ) { /* for an external j0,j1 cell */
00939         poros[HAB[cell_j]] = poros[HAB[cell_i]]; /* other variables = donor cell or zero */
00940         sp_yield[HAB[cell_j]] = sp_yield[HAB[cell_i]]; 
00941         elev[cell_j] = elev[cell_i];
00942         rate[cell_j] = rate[cell_i];
00943         Unsat[cell_j] = 0.0; /* no water in any potential unsat zone */
00944             
00945             /* outflow of groundwater from boundary cell*/
00946         if ( BCondFlow[cell_i] > 2 )  { /* v2.6  (v2.5 had specific markings of 4 or 9, no longer pertinent in v2.6+)  */
00947             if (boundcond_depth[cell_j] > 0.0) /* boundcond_depth=relative water depth; v2.3tmp instead of: boundcond_depth[cell_j] > elev[cell_j]  */
00948             {
00949                 SatWat[cell_j] =  elev[cell_j] * poros[HAB[cell_j]];    
00950                 SfWat[cell_j] = boundcond_depth[cell_j]; /* boundcond_depth=relative water depth; v2.3tmp instead of: boundcond_depth[cell_j] - elev[cell_j]  */
00951             }
00952         else
00953             {
00954                 SatWat[cell_j] =  (elev[cell_j] + boundcond_depth[cell_j]) * poros[HAB[cell_j]];  /* boundcond_depth=relative water depth; v2.3tmp instead of: boundcond_depth[cell_j] * poros[HAB[cell_j]]  */  
00955                 SfWat[cell_j] = 0.0; 
00956             }
00957         }
00958             
00959     GW_head_j = SatWat[cell_j] / poros[HAB[cell_j]]; 
00960     tot_head_j = GW_head_j + SfWat[cell_j];
00961 
00962             /* v2.6 when we don't have data on boundary condition heads */
00963     if ( isModExperim ) {
00964         if (j0 < GP_BC_InputRow) { 
00965                 tot_head_j = tot_head_i /* + GP_BC_SatWat_add */;
00966         } 
00967         else { 
00968                 tot_head_j = (SfWat[cell_i] > GP_BC_SatWat_add) ? (tot_head_i - GP_BC_SatWat_add) : (tot_head_i);
00969         }
00970     } /* end of isModExperim */
00971     
00972     }
00973 
00974     AvgRate = ( rate[cell_i] + rate[cell_j] )/2.0; /* average hyd conductivity of the two cells */
00975     
00976 /* hydraulic head difference, positive flux from cell_i to cell_j */
00977     dh = tot_head_i - tot_head_j; 
00978 
00979  
00980         /* determine donor and recipient cells based on head difference,
00981            and provide the sign of the flux;
00982            The surface water detention depth also used here as threshold
00983            head difference for fluxing (currently global, 1 cm)*/
00984     if (dh > GP_DetentZ) 
00985     {
00986         cell_don=cell_i;
00987         cell_rec=cell_j;
00988         sign = 1; 
00989     }
00990     else if (dh < -GP_DetentZ) 
00991     {   
00992         cell_don=cell_j;
00993         cell_rec=cell_i;
00994         sign = -1;
00995     }
00996     else 
00997         return; /* no flux (or surface-groundwater integration) under minimal head diffs */
00998     
00999 
01000 /* Potential horizontal flux eqn (Darcy's eqn simplified to square cells).
01001    This is the maximum height (m) of water vol to flux under fully saturated condition.
01002    Note that the Min check is probably not important under current implementations, as SatWat includes water
01003    down to the model's base datum, which is below the land elevation vertical datum (NGVD29 or NAVD88) 
01004    by the value of GP_DATUM_DISTANCE (has always been 6 m as of v2.8)  */
01005     Flux = Min(Abs(dh) * AvgRate * SatWat[cell_don] / CELL_SIZE * gwstep , SatWat[cell_don]);
01006  
01007 /**** this do-while routine (1) integrates the surface, saturated, and unsaturated water,
01008   and (2) checks to ensure the heads do not reverse in a time step due to large fluxes.
01009   If heads do reverse, the total Flux is decremented until there is no reversal */
01010 /****/
01011     do {
01012         /* The total potential flux is apportioned to (1) the horizontal component
01013            that fluxes to an adjacent cell and (2) the vertical component that
01014            remains in the donor cell after the horizontal outflow from a donor cell.
01015            Thus, an unsaturated zone is created, or increased in size, with loss of
01016            saturated water from the donor cell; this lateral gravitational flow leaves behind
01017            the field capacity moisture in an unsat zone. (If donor-cell surface water is present,
01018            it potentially will replace the unsaturated soil capacity within the same time
01019            step in this routine).*/
01020         fluxTOunsat_don = Flux/poros[HAB[cell_don]] * (poros[HAB[cell_don]] - sp_yield[HAB[cell_don]])  ;
01021         fluxHoriz = Flux - fluxTOunsat_don;
01022 
01023 /**** given the total potential groundwater Flux, get the donor cell's
01024       new **post-flux** capacities */
01025         UnsatZ_don  =   elev[cell_don] - (SatWat[cell_don]-fluxHoriz /*Flux*/) / poros[HAB[cell_don]] ; /* unsat zone depth */
01026     
01027     /* ?v2.2 this check was against "-0.001", increased here to "-0.01", as it was only showing several mm capacityERR
01028         due to canal interactions (i.e., only when watmgmt turned on), and we haven't explicitly added sf-ground 
01029         integration to grid cells in canal code */
01030         if (debug>3 && (UnsatZ_don < -0.01 ) ) { 
01031             sprintf(msgStr,"Day %6.1f: capacityERR - neg unsat depth (%f m) in donor cell (%d,%d) in GWfluxes!", 
01032                     SimTime.TIME, UnsatZ_don, i0,i1 ); WriteMsg( msgStr,True ); dynERRORnum++; }
01033             
01034         UnsatCap_don =  UnsatZ_don * poros[HAB[cell_don]]; /* maximum pore space capacity (UnsatCap)
01035                                                               in the depth (UnsatZ) of new unsaturated zone */
01036         UnsatPot_don  = UnsatCap_don - (Unsat[cell_don]+fluxTOunsat_don); /* (height of) the volume of pore space
01037                                                                              (soil "removed") that is unoccupied in the unsat zone */
01038             /* determining the pathway of flow (to sat vs. unsat) of surface water depending on depth
01039                of an unsat zone relative to the surface water.  With a relatively deep unsat zone, this
01040                downflow tends to zero (infiltration occurs within the vertical hydrology module of UnitMod.c) */ 
01041         Sat_vs_unsat  = 1/Exp(100.0*Max((SfWat[cell_don]-UnsatZ_don),0.0)); 
01042 
01043     /* sf-unsat-sat fluxes */
01044         if (SfWat[cell_don] > 0.0) { /* surface water downflow is assumed to be as fast
01045                                         as horizontal groundwater outflows */
01046             sfTOsat_don  = 
01047                 ( (1.0-Sat_vs_unsat)*UnsatPot_don>SfWat[cell_don] ) ? 
01048                 ( SfWat[cell_don] ) : 
01049                 ( (1.0-Sat_vs_unsat)*UnsatPot_don); 
01050            /* with downflow of surface water into an unsat zone, the proportion of that height
01051               that is made into saturated storage is allocated to the sat storage variable */
01052             if (sfTOsat_don >=  UnsatPot_don) {
01053                     sfTOsat_don = UnsatPot_don ; /* downflow constrained to the avail soil capacity */
01054                     unsatTOsat_don = Unsat[cell_don]; /* allocate unsat to sat in this case */
01055                 }
01056             else { 
01057                 unsatTOsat_don = (UnsatZ_don > 0.0) ?
01058                     ( (sfTOsat_don/poros[HAB[cell_don]] ) / UnsatZ_don * Unsat[cell_don] ) :
01059                     (0.0); /*  allocate to saturated storage whatever proportion of
01060                                unsat zone that is now saturated by sfwat downflow */
01061             }
01062         }
01063         else { /* w/o surface water, these vertical fluxes are zero */
01064             sfTOsat_don = unsatTOsat_don = 0.0;
01065         }
01066 /**** potential new head in donor cell will be ... */
01067         H_pot_don = (SatWat[cell_don] - fluxTOunsat_don - fluxHoriz + sfTOsat_don + unsatTOsat_don )
01068             / poros[HAB[cell_don]] +(SfWat[cell_don] - sfTOsat_don) ; 
01069                 
01070 
01071 /**** recipient cell's **pre-flux** capacities */
01072         UnsatZ_rec  =   elev[cell_rec] - SatWat[cell_rec] / poros[HAB[cell_rec]] ; /* unsat zone depth */
01073     
01074     /* ?v2.2 this check was against "-0.001", increased here to "-0.01", as it was only showing several mm capacityERR
01075         due to canal interactions (i.e., only when watmgmt turned on), and we haven't explicitly added sf-ground 
01076         integration to grid cells in canal code */
01077         if (debug>3 && (UnsatZ_rec < -0.01 ) ) {
01078             sprintf(msgStr,"Day %6.1f: capacityERR - neg unsat depth (%f m) in recipient cell (%d,%d) in GWfluxes!", 
01079                     SimTime.TIME, UnsatZ_rec, i0,i1 ); WriteMsg( msgStr,True );  dynERRORnum++; }
01080             
01081         UnsatCap_rec =  UnsatZ_rec * poros[HAB[cell_rec]]; /* maximum pore space capacity (UnsatCap)
01082                                                               in the depth (UnsatZ) of new unsaturated zone */
01083         UnsatPot_rec  = UnsatCap_rec - Unsat[cell_rec]; /* (height of) the volume of pore space (soil "removed")
01084                                                            that is unoccupied in the unsat zone */
01085      /* sf-unsat-sat fluxes */
01086         horizTOsat_rec = fluxHoriz; /* lateral inflow to soil into saturated storage */
01087         satTOsf_rec = Max(fluxHoriz - UnsatPot_rec, 0.0); /* upwelling beyond soil capacity */
01088         unsatTOsat_rec = (UnsatZ_rec > 0.0) ? /* incorporation of unsat moisture into sat storage with
01089                                                  rising water table due to horiz inflow */
01090             ( ((horizTOsat_rec-satTOsf_rec)/poros[HAB[cell_rec]] ) / UnsatZ_rec * Unsat[cell_rec] ) :
01091             (0.0);
01092 /**** potential new head in recipient cell will be ... */
01093         H_pot_rec = (SatWat[cell_rec] + horizTOsat_rec + unsatTOsat_rec - satTOsf_rec)
01094             / poros[HAB[cell_rec]] + (SfWat[cell_rec] + satTOsf_rec) ; 
01095 
01096 /**** check for a head reversal - if so, reduce flux to achieve equilibrium (donor >= recip) */
01097         if ( (Flux != 0.0) && ((H_pot_rec - H_pot_don) > GP_MinCheck) ) {
01098             revers++;
01099             Flux *= 0.90;
01100             equilib = 0; 
01101                /* if the unsat water storage causes an unfixable (very rare(/never?)) head reversal due to the
01102                    sfwat and gwater integration alone, set the Flux to zero, then allow the vertical
01103                    sf/ground integration to be done with no horiz flux and be done with it */
01104             if (revers>1) { /* v2.3 temp, was >4 */
01105                 if (debug>2) { sprintf(msgStr,"Day %6.1f: FYI - head reversal (%f m) due to surf/ground integration, associated with cell (%d,%d).  Total flux was to be %f. Fixed with 0 flux. ", 
01106                                        SimTime.TIME, (H_pot_don - H_pot_rec),  i0,i1,Flux*sign ); WriteMsg( msgStr,True );}
01107                 Flux =  0.0;
01108                 }
01109         }
01110         else {
01111             equilib = 1;
01112         }
01113         
01114     } while  (!equilib); /* end of routine for integrating groundwater-surface water and preventing head reversals */
01115         
01116 /**********
01117   finished calc'ing the water fluxes
01118   *************/
01119 /* calc the flux of the constituents between sed/soil across cells in horiz dir,
01120  but don't update the state vars until the conc's for vertical flows have been calc'd */
01121     sedwat_don = SatWat[cell_don] + Unsat[cell_don];
01122     sed_stuf1fl_horz = (sedwat_don > 0.0) ? (gwSTUF1[cell_don] / sedwat_don*fluxHoriz) : (0.0);
01123     sed_stuf2fl_horz = (sedwat_don > 0.0) ? (gwSTUF2[cell_don] / sedwat_don*fluxHoriz) : (0.0);
01124     sed_stuf3fl_horz = (sedwat_don > 0.0) ? (gwSTUF3[cell_don] / sedwat_don*fluxHoriz) : (0.0);
01125 
01126 /* pass along the constituents between sed/soil and surface water in vertical dir;
01127    for "simplicity", this does not account for the phosphorus active-zone conc. gradient,
01128    but assumes the homogeneity of conc within the entire soil column */
01129     if (sfTOsat_don > 0.0) {
01130         sf_stuf1fl_don = (SfWat[cell_don] > 0.0) ? (swSTUF1[cell_don] / SfWat[cell_don]*sfTOsat_don) : (0.0);
01131         sf_stuf2fl_don = (SfWat[cell_don] > 0.0) ? (swSTUF2[cell_don] / SfWat[cell_don]*sfTOsat_don) : (0.0);
01132         sf_stuf3fl_don = (SfWat[cell_don] > 0.0) ? (swSTUF3[cell_don] / SfWat[cell_don]*sfTOsat_don) : (0.0);
01133         gwSTUF1[cell_don] += sf_stuf1fl_don;
01134         gwSTUF2[cell_don] += sf_stuf2fl_don;
01135         gwSTUF3[cell_don] += sf_stuf3fl_don;
01136         swSTUF1[cell_don] -= sf_stuf1fl_don;
01137         swSTUF2[cell_don] -= sf_stuf2fl_don;
01138         swSTUF3[cell_don] -= sf_stuf3fl_don;
01139         
01140     }
01141     if (satTOsf_rec > 0.0) {
01142         sedwat_rec = SatWat[cell_rec] + Unsat[cell_rec];
01143         sed_stuf1fl_rec = (sedwat_rec > 0.0) ? (gwSTUF1[cell_rec] / sedwat_rec*satTOsf_rec) : (0.0);
01144         sed_stuf2fl_rec = (sedwat_rec > 0.0) ? (gwSTUF2[cell_rec] / sedwat_rec*satTOsf_rec) : (0.0);
01145         sed_stuf3fl_rec = (sedwat_rec > 0.0) ? (gwSTUF3[cell_rec] / sedwat_rec*satTOsf_rec) : (0.0);
01146         gwSTUF1[cell_rec] -= sed_stuf1fl_rec;
01147         gwSTUF2[cell_rec] -= sed_stuf2fl_rec;
01148         gwSTUF3[cell_rec] -= sed_stuf3fl_rec;
01149         swSTUF1[cell_rec] += sed_stuf1fl_rec;
01150         swSTUF2[cell_rec] += sed_stuf2fl_rec;
01151         swSTUF3[cell_rec] += sed_stuf3fl_rec;
01152     }
01153     
01154 /* update the groundwater constituents due to horiz flows */
01155     gwSTUF1[cell_don] -= sed_stuf1fl_horz;
01156     gwSTUF2[cell_don] -= sed_stuf2fl_horz;
01157     gwSTUF3[cell_don] -= sed_stuf3fl_horz;
01158     gwSTUF1[cell_rec] += sed_stuf1fl_horz;
01159     gwSTUF2[cell_rec] += sed_stuf2fl_horz;
01160     gwSTUF3[cell_rec] += sed_stuf3fl_horz;
01161         
01162 
01163 /* update the hydro state variables */
01164     SfWat[cell_don]  += (-sfTOsat_don);
01165     Unsat[cell_don]  += ( fluxTOunsat_don - unsatTOsat_don) ;
01166     SatWat[cell_don] += (sfTOsat_don + unsatTOsat_don - fluxTOunsat_don - fluxHoriz);
01167     SfWat[cell_rec]  += ( satTOsf_rec); 
01168     Unsat[cell_rec]  += (-unsatTOsat_rec);
01169     SatWat[cell_rec] += (horizTOsat_rec + unsatTOsat_rec - satTOsf_rec); /* (horizTOsat_rec + satTOsf_rec) = fluxHoriz */
01170         
01171 /*******BUDGET
01172 **************/
01173 /*  sum the flow of groundwater and constituents (nutrients, salinity, etc) among basins, with budget calcs.*/
01174     if ( basn[cell_i] != basn[cell_j] ) { 
01175 
01176         fluxHoriz = sign*fluxHoriz*CELL_SIZE; /* signed water flux volume (m^3) */
01177         sed_stuf1fl_horz = sign*sed_stuf1fl_horz; /* signed constituent flux (kg) */
01178         sed_stuf3fl_horz = sign*sed_stuf3fl_horz; /* signed constituent flux (kg) */
01179 
01180         /* first do the normal case where all cells are on-map */
01181         if ( ON_MAP[cell_j] && ON_MAP[cell_i] ) { 
01182             if ( fluxHoriz > 0  ) { /* fluxes out of basn[cell_i] */
01183              if (basn_list[basn[cell_i]]->family !=  
01184                  basn_list[basn[cell_j]]->family ) {        /* if the flow is not within the family... */
01185                  if  ( !basn_list[basn[cell_i]]->parent  ) { /* and if the donor or recipient is a child... */
01186                      /* then find out about the flow for the family's sake */
01187                      VOL_OUT_GW[basn_list[basn[cell_i]]->family] += fluxHoriz;
01188                      P_OUT_GW[basn_list[basn[cell_i]]->family] += sed_stuf3fl_horz;
01189                      S_OUT_GW[basn_list[basn[cell_i]]->family] += sed_stuf1fl_horz;
01190                  }
01191                  if ( !basn_list[basn[cell_j]]->parent ) {                 
01192                      /* then find out about the flow for the family's sake */
01193                      VOL_IN_GW[basn_list[basn[cell_j]]->family] += fluxHoriz;
01194                      P_IN_GW[basn_list[basn[cell_j]]->family] += sed_stuf3fl_horz;
01195                      S_IN_GW[basn_list[basn[cell_j]]->family] += sed_stuf1fl_horz;
01196                  }
01197                      /* now sum the parents' flows */
01198                  VOL_OUT_GW[basn[cell_i]] += fluxHoriz;
01199                  VOL_IN_GW[basn[cell_j]]  += fluxHoriz;
01200                  P_OUT_GW[basn[cell_i]] += sed_stuf3fl_horz;
01201                  P_IN_GW[basn[cell_j]]  += sed_stuf3fl_horz;
01202                  S_OUT_GW[basn[cell_i]] += sed_stuf1fl_horz;
01203                  S_IN_GW[basn[cell_j]]  += sed_stuf1fl_horz;
01204              }
01205              
01206                         
01207              else {    /* if it's flow within a family, just keep
01208                           track of what the children do among themselves */            
01209                  if  ( !basn_list[basn[cell_i]]->parent  ) { 
01210                      VOL_OUT_GW[basn[cell_i]] += fluxHoriz; 
01211                      P_OUT_GW[basn[cell_i]] += sed_stuf3fl_horz; 
01212                      S_OUT_GW[basn[cell_i]] += sed_stuf1fl_horz; 
01213                  }
01214                  if ( !basn_list[basn[cell_j]]->parent ) {                 
01215                      VOL_IN_GW[basn[cell_j]]  += fluxHoriz; 
01216                      P_IN_GW[basn[cell_j]]  += sed_stuf3fl_horz; 
01217                      S_IN_GW[basn[cell_j]]  += sed_stuf1fl_horz; 
01218                  }
01219              }
01220 
01221             }
01222             else { /* negative fluxes out of basn[cell_j] */
01223              if (basn_list[basn[cell_i]]->family !=  
01224                  basn_list[basn[cell_j]]->family ) {        /* if the flow is not within the family... */
01225                  if  ( !basn_list[basn[cell_j]]->parent  ) { /* and if the donor or recipient is a child... */
01226                      /* then find out about the flow for the family's sake */
01227                      VOL_OUT_GW[basn_list[basn[cell_j]]->family] -= fluxHoriz;
01228                      P_OUT_GW[basn_list[basn[cell_j]]->family] -= sed_stuf3fl_horz;
01229                      S_OUT_GW[basn_list[basn[cell_j]]->family] -= sed_stuf1fl_horz;
01230                  }
01231                  if ( !basn_list[basn[cell_i]]->parent ) {                 
01232                      /* then find out about the flow for the family's sake */
01233                      VOL_IN_GW[basn_list[basn[cell_i]]->family] -= fluxHoriz;
01234                      P_IN_GW[basn_list[basn[cell_i]]->family] -= sed_stuf3fl_horz;
01235                      S_IN_GW[basn_list[basn[cell_i]]->family] -= sed_stuf1fl_horz;
01236                  }
01237                      /* now sum the parents' flows */
01238                 VOL_OUT_GW[basn[cell_j]] -= fluxHoriz;
01239                 VOL_IN_GW[basn[cell_i]]  -= fluxHoriz;
01240                 P_OUT_GW[basn[cell_j]] -= sed_stuf3fl_horz;
01241                 P_IN_GW[basn[cell_i]]  -= sed_stuf3fl_horz;
01242                 S_OUT_GW[basn[cell_j]] -= sed_stuf1fl_horz;
01243                 S_IN_GW[basn[cell_i]]  -= sed_stuf1fl_horz;
01244 
01245             }
01246              else {    /* if it's flow within a family, just keep
01247                           track of what the children do among themselves */            
01248                  if  ( !basn_list[basn[cell_j]]->parent  ) { 
01249                      VOL_OUT_GW[basn[cell_j]] -= fluxHoriz; 
01250                      P_OUT_GW[basn[cell_j]] -= sed_stuf3fl_horz; 
01251                      S_OUT_GW[basn[cell_j]] -= sed_stuf1fl_horz; 
01252                  }
01253                  if ( !basn_list[basn[cell_i]]->parent ) {                 
01254                      VOL_IN_GW[basn[cell_i]]  -= fluxHoriz; 
01255                      P_IN_GW[basn[cell_i]]  -= sed_stuf3fl_horz; 
01256                      S_IN_GW[basn[cell_i]]  -= sed_stuf1fl_horz; 
01257                  }
01258              }
01259             }
01260             
01261 
01262         }
01263         else  if ( !ON_MAP[cell_j]) {/* so now the j,j cell is off-map, recipient if pos flow */
01264             if (fluxHoriz > 0) { 
01265              if ( !basn_list[basn[cell_i]]->parent ) { /* child's play */
01266                  VOL_OUT_GW[basn_list[basn[cell_i]]->family] += fluxHoriz;
01267                  P_OUT_GW[basn_list[basn[cell_i]]->family] += sed_stuf3fl_horz;
01268                  S_OUT_GW[basn_list[basn[cell_i]]->family] += sed_stuf1fl_horz;
01269              }
01270              /* parents' play */
01271                 VOL_OUT_GW[basn[cell_i]] += fluxHoriz;
01272                 VOL_OUT_GW[0]              += fluxHoriz;
01273                 P_OUT_GW[basn[cell_i]] += sed_stuf3fl_horz;
01274                 P_OUT_GW[0]              += sed_stuf3fl_horz;
01275                 S_OUT_GW[basn[cell_i]] += sed_stuf1fl_horz;
01276                 S_OUT_GW[0]              += sed_stuf1fl_horz;
01277             }
01278             else {/* negative flows */
01279              if ( !basn_list[basn[cell_i]]->parent ) {/* child's play */
01280                  VOL_IN_GW[basn_list[basn[cell_i]]->family] -= fluxHoriz;
01281                  P_IN_GW[basn_list[basn[cell_i]]->family] -= sed_stuf3fl_horz;
01282                  S_IN_GW[basn_list[basn[cell_i]]->family] -= sed_stuf1fl_horz;
01283              }
01284              /* parents' play */
01285                 VOL_IN_GW[basn[cell_i]]  -= fluxHoriz;
01286                 VOL_IN_GW[0]               -= fluxHoriz;
01287                 P_IN_GW[basn[cell_i]]  -= sed_stuf3fl_horz;
01288                 P_IN_GW[0]               -= sed_stuf3fl_horz;
01289                 S_IN_GW[basn[cell_i]]  -= sed_stuf1fl_horz;
01290                 S_IN_GW[0]               -= sed_stuf1fl_horz;
01291             }
01292         }
01293         
01294         else  if ( !ON_MAP[cell_i]) { /* so now the i,i cell is off-map, donor if pos flow */
01295             if (fluxHoriz > 0) { 
01296              if ( !basn_list[basn[cell_j]]->parent ) {/* child's play */
01297                  VOL_IN_GW[basn_list[basn[cell_j]]->family] += fluxHoriz;
01298                  P_IN_GW[basn_list[basn[cell_j]]->family] += sed_stuf3fl_horz;
01299                  S_IN_GW[basn_list[basn[cell_j]]->family] += sed_stuf1fl_horz;
01300              }
01301              /* parents' play */
01302                 VOL_IN_GW[basn[cell_j]] += fluxHoriz;
01303                 VOL_IN_GW[0]              += fluxHoriz;
01304                 P_IN_GW[basn[cell_j]] += sed_stuf3fl_horz;
01305                 P_IN_GW[0]              += sed_stuf3fl_horz;
01306                 S_IN_GW[basn[cell_j]] += sed_stuf1fl_horz;
01307                 S_IN_GW[0]              += sed_stuf1fl_horz;
01308             }
01309             else {/*negative flows */
01310              if ( !basn_list[basn[cell_j]]->parent ) {/* child's play */
01311                  VOL_OUT_GW[basn_list[basn[cell_j]]->family] -= fluxHoriz;
01312                  P_OUT_GW[basn_list[basn[cell_j]]->family] -= sed_stuf3fl_horz;
01313                  S_OUT_GW[basn_list[basn[cell_j]]->family] -= sed_stuf1fl_horz;
01314              }
01315              /* parents' play */
01316                 VOL_OUT_GW[basn[cell_j]]  -= fluxHoriz;
01317                 VOL_OUT_GW[0]               -= fluxHoriz;
01318                 P_OUT_GW[basn[cell_j]]  -= sed_stuf3fl_horz;
01319                 P_OUT_GW[0]               -= sed_stuf3fl_horz;
01320                 S_OUT_GW[basn[cell_j]]  -= sed_stuf1fl_horz;
01321                 S_OUT_GW[0]               -= sed_stuf1fl_horz;
01322             }
01323     }
01324 }
01325 
01326 
01327     return ; 
01328         
01329 } /* end Flux_GWcells */
01330 
01331   
01332 
01333 
01334 /***************************************************************************************/

Generated on Sat Jan 7 14:04:15 2012 for ELM source code by  doxygen 1.5.6