Exemple #1
0
/*****************************************************************************
  InitPrecipMap()
*****************************************************************************/
void InitPrecipMap(MAPSIZE * Map, PRECIPPIX *** PrecipMap, VEGPIX ** VegMap,
		   LAYER * Veg, TOPOPIX ** TopoMap)
{
  const char *Routine = "InitPrecipMap";
  int x;			/* counter */
  int y;			/* counter */
  int NVeg;			/* Number of veg layers at current pixel */

  if (DEBUG)
    printf("Initializing precipitation map\n");

  if (!(*PrecipMap = (PRECIPPIX **) calloc(Map->NY, sizeof(PRECIPPIX *))))
    ReportError((char *) Routine, 1);

  for (y = 0; y < Map->NY; y++) {
    if (!((*PrecipMap)[y] = (PRECIPPIX *) calloc(Map->NX, sizeof(PRECIPPIX))))
      ReportError((char *) Routine, 1);
  }

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	NVeg = Veg->NLayers[(VegMap[y][x].Veg - 1)];
	if (!((*PrecipMap)[y][x].IntRain =
	      (float *) calloc(NVeg, sizeof(float))))
	  ReportError((char *) Routine, 1);
      }
    }
  }

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	NVeg = Veg->NLayers[(VegMap[y][x].Veg - 1)];
	if (!((*PrecipMap)[y][x].IntSnow =
	      (float *) calloc(NVeg, sizeof(float))))
	  ReportError((char *) Routine, 1);
      }
    }
  }

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) 
	(*PrecipMap)[y][x].PrecipStart = TRUE;
    }
  }
}
Exemple #2
0
/* -------------------------------------------------------------
   HeadSlopeAspect
   This computes slope and aspect using the water table elevation.

   Comment: rewritten to fill the sinks (Ning, 2013)
   ------------------------------------------------------------- */
void HeadSlopeAspect(MAPSIZE * Map, TOPOPIX ** TopoMap, SOILPIX ** SoilMap,
                     float **FlowGrad, unsigned char ***Dir, unsigned int **TotalDir)
{
    int x;
    int y;
    int n;
    float neighbor_elev[NNEIGHBORS];

    /* let's assume for now that WaterLevel is the SOILPIX map is
       computed elsewhere */
    for (x = 0; x < Map->NX; x++) {
        for (y = 0; y < Map->NY; y++) {
            if (INBASIN(TopoMap[y][x].Mask)) {
                float slope, aspect;
                for (n = 0; n < NNEIGHBORS; n++) {
                    int xn = x + xneighbor[n];
                    int yn = y + yneighbor[n];
                    if (valid_cell(Map, xn, yn)) {
                        neighbor_elev[n] =
                            ((TopoMap[yn][xn].Mask) ? SoilMap[yn][xn].WaterLevel : (float) OUTSIDEBASIN);
                    }
                    else {
                        neighbor_elev[n] = (float) OUTSIDEBASIN;
                    }
                }
                slope_aspect(Map->DX, Map->DY, SoilMap[y][x].WaterLevel, neighbor_elev,
                             &slope, &aspect);
                flow_fractions(Map->DX, Map->DY, slope, aspect, neighbor_elev,
                               &(FlowGrad[y][x]), Dir[y][x], &(TotalDir[y][x]));
            }
        }
    }
    return;
}
Exemple #3
0
/*****************************************************************************
  InitEvapMap()
*****************************************************************************/
void InitEvapMap(MAPSIZE *Map, EVAPPIX ***EvapMap, SOILPIX **SoilMap,
		 LAYER *Soil, VEGPIX **VegMap, LAYER *Veg,
		 TOPOPIX **TopoMap)
{
  const char *Routine = "InitEvapMap";
  int i;			/* counter */
  int x;			/* counter */
  int y;			/* counter */
  int NSoil;			/* Number of soil layers for current pixel */
  int NVeg;			/* Number of veg layers for current pixel */

  if (DEBUG)
    printf("Initializing evaporation map\n");

  if (!(*EvapMap = (EVAPPIX **) calloc(Map->NY, sizeof(EVAPPIX *))))
    ReportError((char *) Routine, 1);

  for (y = 0; y < Map->NY; y++) {
    if (!((*EvapMap)[y] = (EVAPPIX *) calloc(Map->NX, sizeof(EVAPPIX))))
      ReportError((char *) Routine, 1);
  }

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	NVeg = Veg->NLayers[(VegMap[y][x].Veg - 1)];
	NSoil = Soil->NLayers[(SoilMap[y][x].Soil - 1)];
	assert(VegMap[y][x].Veg > 0 && SoilMap[y][x].Soil > 0);

	if (!((*EvapMap)[y][x].EPot =
	      (float *) calloc(NVeg + 1, sizeof(float))))
	  ReportError((char *) Routine, 1);

	if (!((*EvapMap)[y][x].EAct =
	      (float *) calloc(NVeg + 1, sizeof(float))))
	  ReportError((char *) Routine, 1);

	if (!((*EvapMap)[y][x].EInt = (float *) calloc(NVeg, sizeof(float))))
	  ReportError((char *) Routine, 1);

	if (!((*EvapMap)[y][x].ESoil =
	      (float **) calloc(NVeg, sizeof(float *))))
	  ReportError((char *) Routine, 1);

	for (i = 0; i < NVeg; i++) {
	  if (!((*EvapMap)[y][x].ESoil[i] =
		(float *) calloc(NSoil, sizeof(float))))
	    ReportError((char *) Routine, 1);
	}
      }
    }
  }
}
/*****************************************************************************
  RouteCulvertSediment()

*****************************************************************************/
void RouteCulvertSediment(CHANNEL * ChannelData, MAPSIZE * Map,
			  TOPOPIX ** TopoMap, SEDPIX ** SedMap, 
			  AGGREGATED * Total, float *SedDiams)
{
  int x, y;
  float CulvertSedFlow;   /* culvert flow of sediment, kg */
  int i;

  Total->CulvertReturnSedFlow = 0.0;

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
 
	for(i=0; i<NSEDSIZES; i++) {
	    
	  CulvertSedFlow = ChannelCulvertSedFlow(y, x, ChannelData, i);
	  CulvertSedFlow /= Map->DX * Map->DY;

	  if (channel_grid_has_channel(ChannelData->stream_map, x, y)) {
	    /* Percent delivery to streams is conservative and based on particle size */
	    if (SedDiams[i] <= 0.063){
	      ChannelData->stream_map[x][y]->channel->sediment.overlandinflow[i] += CulvertSedFlow;
	      Total->CulvertSedToChannel += CulvertSedFlow;
	      CulvertSedFlow = 0.;
	    }
	    if ((SedDiams[i] > 0.063) && (SedDiams[i] <= 0.5)){
	      ChannelData->stream_map[x][y]->channel->sediment.overlandinflow[i] += 0.3*CulvertSedFlow;
	      Total->CulvertSedToChannel += 0.3*CulvertSedFlow;
	      Total->CulvertReturnSedFlow += 0.7*CulvertSedFlow;
	      CulvertSedFlow = 0.;
	    }
	    if ((SedDiams[i] > 0.5) && (SedDiams[i] <= 2.)){
	      ChannelData->stream_map[x][y]->channel->sediment.overlandinflow[i] += 0.1*CulvertSedFlow;
	      Total->CulvertSedToChannel += 0.1*CulvertSedFlow;
	      Total->CulvertReturnSedFlow += 0.9*CulvertSedFlow;
	      CulvertSedFlow = 0.;
	    }
	    Total->CulvertReturnSedFlow += CulvertSedFlow;
	  }
	  else {
	    Total->CulvertReturnSedFlow += CulvertSedFlow;
	  }
	}
      }
    }
  }
}
Exemple #5
0
/*****************************************************************************
  RouteSubSurface()

  Sources: 
  Wigmosta, M. S., L. W. Vail, and D. P. Lettenmaier, A distributed 
      hydrology-vegetation model for complex terrain, Water Resour. Res.,
      30(6), 1665-1679, 1994.

  Quinn, P., K. Beven, P. Chevallier, and O. Planchon, The prediction of 
      hillslope flow paths for distributed hydrological modelling using 
      digital terrain models, Hydrological Processes, 5, 59-79, 1991.

  This routine follows Wigmosta et al. [1994] in calculating the subsurface
  flow.  The local gradient is based on the local hydraulic head, consisting 
  of the height of the pixel surface minus the depth of the water table 
  below the water surface.  This has the disadvantage that the local gradients
  have to be recalculated for each pixel for each timestep.  In Wigmosta et
  al. [1994] the local gradient is taken to be equal to the slope of the land
  surface, which is a reasonable assunption for mountainous areas.  For the 
  flat boreal forest landscape it is probably better to use the slope
  of the water surface.

  Set the gradient with pixels that are outside tha basin to zero.  This 
  ensures that there is no flux of water across the basin boundary.  In the 
  current implementation water can only leave the basin as surface flow.  
  This may not be entirely realistic, and should be analyzed further.  
  One consequence of this could be that the soil in the basin is more 
  saturated than it would be if subsurface flow out of the basin would
  be allowed.

  The surrounding grid cells are numbered in the following way

                |-----| DX

          0-----1-----2  ---
	  |\    |    /|   |
          | \   |   / |   |
          |  \  |  /  |   | DY
          |   \ | /   |   |
          |    \|/    |   |
          7-----*-----3  ---
          |    /|\    |
          |   / | \   |
          |  /  |  \  |
          | /   |   \ |
          |/    |    \|
          6-----5-----4

  For the current implementation it is assumed that the resolution is the 
  same in both the X and the Y direction.  If this is not the case an error
  message is generated and the program exits.  The reason is that the 
  formulation for the flow width in the diagonal direction changes if the
  grid is not square.  The method for defining the flow widths in the case
  of square grids is taken from Quinn et al [1991]

  Update Jan 2004 COD
  When Gradient = WATERTABLE, the watertable was used to route the
  surface water. This was because of the common use of TopoMap.Dir and 
  TopoMap.TotalDir. These are now for surface routing (always) and subsurface 
  routing (when Gradient = TOPOGRAPHY). Subsurface routing directions 
  and FlowGrad (SubDir, SubTotalDir, SubFlowGrad) for Gradient = WATERTABLE 
  are now determined locally here (in RouteSubsurface.c.)

  WORK IN PROGRESS
*****************************************************************************/
void RouteSubSurface(int Dt, MAPSIZE *Map, TOPOPIX **TopoMap,
		     VEGTABLE *VType, VEGPIX **VegMap,
		     ROADSTRUCT **Network, SOILTABLE *SType,
		     SOILPIX **SoilMap, CHANNEL *ChannelData,
		     TIMESTRUCT *Time, OPTIONSTRUCT *Options, 
		     char *DumpPath, SEDPIX **SedMap, FINEPIX ***FineMap,
		     SEDTABLE *SedType, int MaxStreamID, SNOWPIX **SnowMap)
{
  const char *Routine = "RouteSubSurface";
  int x;			/* counter */
  int y;			/* counter */
  int i,j, ii, jj, yy, xx;	/* counters for FineMap initialization */
  float BankHeight;
  float *Adjust;
  float fract_used;
  float depth;
  float OutFlow;
  float water_out_road;
  float Transmissivity;
  float AvailableWater;
  int k;
  float **SubFlowGrad;	        /* Magnitude of subsurface flow gradient
				   slope * width */
  unsigned char ***SubDir;         /* Fraction of flux moving in each direction*/ 
  unsigned int **SubTotalDir;	/* Sum of Dir array */

  /* variables for mass wasting trigger. */
  int count, totalcount;
  float mgrid, sat;
  char buffer[32];
  char satoutfile[100];          /* Character arrays to hold file name. */ 
  FILE *fs;                     /* File pointer. */

  /*****************************************************************************
   Allocate memory 
  ****************************************************************************/
  
  if (!(SubFlowGrad = (float **)calloc(Map->NY, sizeof(float *))))
    ReportError((char *) Routine, 1);
  for(i=0; i<Map->NY; i++) {
    if (!(SubFlowGrad[i] = (float *)calloc(Map->NX, sizeof(float))))
      ReportError((char *) Routine, 1);
  }
  
  if (!((SubDir) = (unsigned char ***) calloc(Map->NY, sizeof(unsigned char **))))
    ReportError((char *) Routine, 1);
  for(i=0; i<Map->NY; i++) {
    if (!((SubDir)[i] = (unsigned char **) calloc(Map->NX, sizeof(unsigned char*))))
	ReportError((char *) Routine, 1);
    for(j=0; j<Map->NX; j++) {
      if (!(SubDir[i][j] = (unsigned char *)calloc(NDIRS, sizeof(unsigned char ))))
    ReportError((char *) Routine, 1);
    }
  }

  if (!(SubTotalDir = (unsigned int **)calloc(Map->NY, sizeof(unsigned int *))))
    ReportError((char *) Routine, 1);
  for(i=0; i<Map->NY; i++) {
    if (!(SubTotalDir[i] = (unsigned int *)calloc(Map->NX, sizeof(unsigned int))))
      ReportError((char *) Routine, 1);
  }
  
  /* reset the saturated subsurface flow to zero */
  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	SoilMap[y][x].SatFlow = 0;
	/* ChannelInt and RoadInt are initialized in Aggregate.c Why are there here? */
	/* 	SoilMap[y][x].ChannelInt = 0; */
	SoilMap[y][x].RoadInt = 0;
      }
    }
  }

  if (Options->FlowGradient == WATERTABLE)
    HeadSlopeAspect(Map, TopoMap, SoilMap, SubFlowGrad, SubDir, SubTotalDir);

  /* next sweep through all the grid cells, calculate the amount of
     flow in each direction, and divide the flow over the surrounding
     pixels */

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	
	if (Options->FlowGradient == TOPOGRAPHY){
	  SubTotalDir[y][x] = TopoMap[y][x].TotalDir;
	  SubFlowGrad[y][x] = TopoMap[y][x].FlowGrad;
	  for (k = 0; k < NDIRS; k++) 
	    SubDir[y][x][k] = TopoMap[y][x].Dir[k];
	}

	BankHeight = (Network[y][x].BankHeight > SoilMap[y][x].Depth) ?
	  SoilMap[y][x].Depth : Network[y][x].BankHeight;
	Adjust = Network[y][x].Adjust;
	fract_used = 0.0f;
	water_out_road = 0.0;

	if (!channel_grid_has_channel(ChannelData->stream_map, x, y)) {
	  for (k = 0; k < NDIRS; k++) {
	    fract_used += (float) SubDir[y][x][k];
/* 	    fract_used += (float) TopoMap[y][x].Dir[k]; */
	  }
/* 	  fract_used /= 255.0f; */
/* 	  fract_used /= (float) TopoMap[y][x].TotalDir; */
	  if (SubTotalDir[y][x] > 0)
	    fract_used /= (float) SubTotalDir[y][x];
	  else
	    fract_used = 0.;

	  /* only bother calculating subsurface flow if water table is above bedrock */
	  if (SoilMap[y][x].TableDepth < SoilMap[y][x].Depth) {
	    depth =
	      ((SoilMap[y][x].TableDepth > BankHeight) ?
	       SoilMap[y][x].TableDepth : BankHeight);

	    Transmissivity =
	      CalcTransmissivity(SoilMap[y][x].Depth, depth,
				 SType[SoilMap[y][x].Soil - 1].KsLat,
				 SType[SoilMap[y][x].Soil - 1].KsLatExp,
				 SType[SoilMap[y][x].Soil - 1].DepthThresh);

	    OutFlow =
	      (Transmissivity * fract_used * SubFlowGrad[y][x] * Dt) /
	      (Map->DX * Map->DY);
/* 	      (Transmissivity * fract_used * TopoMap[y][x].FlowGrad * Dt) / */
/* 	      (Map->DX * Map->DY); */

	    /* check whether enough water is available for redistribution */

	    AvailableWater =
	      CalcAvailableWater(VType[VegMap[y][x].Veg - 1].NSoilLayers,
				 SoilMap[y][x].Depth,
				 VType[VegMap[y][x].Veg - 1].RootDepth,
				 SType[SoilMap[y][x].Soil - 1].Porosity,
				 SType[SoilMap[y][x].Soil - 1].FCap,
				 SoilMap[y][x].TableDepth, Adjust);

	    OutFlow = (OutFlow > AvailableWater) ? AvailableWater : OutFlow;
	  }
	  else {
	    depth = SoilMap[y][x].Depth;
	    OutFlow = 0.0f;
	  }

	  /* compute road interception if water table is above road cut */

	  if (SoilMap[y][x].TableDepth < BankHeight &&
	      channel_grid_has_channel(ChannelData->road_map, x, y)) {
/* 	    fract_used = ((float) Network[y][x].fraction / 255.0f); */
/* 	    fract_used = ((float) Network[y][x].fraction / (float)TopoMap[y][x].TotalDir); */
	    if (SubTotalDir[y][x] > 0)
	      fract_used = ((float) Network[y][x].fraction /
			    (float)SubTotalDir[y][x]);
	    else
	      fract_used = 0.;

	    Transmissivity =
	      CalcTransmissivity(BankHeight, SoilMap[y][x].TableDepth,
				 SType[SoilMap[y][x].Soil - 1].KsLat,
				 SType[SoilMap[y][x].Soil - 1].KsLatExp,
				 SType[SoilMap[y][x].Soil - 1].DepthThresh);
	    water_out_road = (Transmissivity * fract_used *
			      SubFlowGrad[y][x] * Dt) / (Map->DX *
							      Map->DY);
/*                               (Transmissivity * fract_used * */
/* 			      TopoMap[y][x].FlowGrad * Dt) / (Map->DX * */
/* 							      Map->DY); */

	    AvailableWater =
	      CalcAvailableWater(VType[VegMap[y][x].Veg - 1].NSoilLayers,
				 BankHeight,
				 VType[VegMap[y][x].Veg - 1].RootDepth,
				 SType[SoilMap[y][x].Soil - 1].Porosity,
				 SType[SoilMap[y][x].Soil - 1].FCap,
				 SoilMap[y][x].TableDepth, Adjust);
	    water_out_road = (water_out_road > AvailableWater) ? AvailableWater
	      : water_out_road;

	    /* increase lateral inflow to road channel */
	    SoilMap[y][x].RoadInt = water_out_road;
	    channel_grid_inc_inflow(ChannelData->road_map, x, y,
				    water_out_road * Map->DX * Map->DY);

	  }

	  /* Subsurface Component - Decrease water change by outwater */

	  SoilMap[y][x].SatFlow -= OutFlow + water_out_road;

	  /* Assign the water to appropriate surrounding pixels */

/* 	  OutFlow /= 255.0f; */
/* 	  OutFlow /= (float) TopoMap[y][x].TotalDir; */
	  if (SubTotalDir[y][x] > 0)
	    OutFlow /= (float) SubTotalDir[y][x];
	  else
	    OutFlow = 0.;

	  for (k = 0; k < NDIRS; k++) {
	    int nx = xdirection[k] + x;
	    int ny = ydirection[k] + y;
	    if (valid_cell(Map, nx, ny)) {
	      SoilMap[ny][nx].SatFlow += OutFlow * SubDir[y][x][k];
/* 	      SoilMap[ny][nx].SatFlow += OutFlow * TopoMap[y][x].Dir[k]; */
	    }
	  }

	}
	else {			/* cell has a stream channel */

	  if (SoilMap[y][x].TableDepth < BankHeight &&
	      channel_grid_has_channel(ChannelData->stream_map, x, y)) {
	    /* float gradient =  */
	    /*   (4.0 * SoilMap[y][x].Depth > 2.0 * MIN_GRAD * Map->DX) ?  */
	    /*   4.0 * SoilMap[y][x].Depth : 2.0 * MIN_GRAD * Map->DX; */

	    float gradient = 4.0 * (BankHeight - SoilMap[y][x].TableDepth);
	    if (gradient < 0.0)
	      gradient = 0.0;

	    Transmissivity =
	      CalcTransmissivity(BankHeight, SoilMap[y][x].TableDepth,
				 SType[SoilMap[y][x].Soil - 1].KsLat,
				 SType[SoilMap[y][x].Soil - 1].KsLatExp,
				 SType[SoilMap[y][x].Soil - 1].DepthThresh);

	    OutFlow = (Transmissivity * gradient * Dt) / (Map->DX * Map->DY);

	    /* check whether enough water is available for redistribution */

	    AvailableWater =
	      CalcAvailableWater(VType[VegMap[y][x].Veg - 1].NSoilLayers,
				 BankHeight,
				 VType[VegMap[y][x].Veg - 1].RootDepth,
				 SType[SoilMap[y][x].Soil - 1].Porosity,
				 SType[SoilMap[y][x].Soil - 1].FCap,
				 SoilMap[y][x].TableDepth, Adjust);

	    OutFlow = (OutFlow > AvailableWater) ? AvailableWater : OutFlow;

	    /* remove water going to channel from the grid cell */
	    SoilMap[y][x].SatFlow -= OutFlow;

	    /* contribute to channel segment lateral inflow */
	    channel_grid_inc_inflow(ChannelData->stream_map, x, y,
				    OutFlow * Map->DX * Map->DY);

	    SoilMap[y][x].ChannelInt += OutFlow;
	  }
	}
      }
    }
  }

 for(i=0; i<Map->NY; i++) { 
    free(SubTotalDir[i]);
    free(SubFlowGrad[i]);
    for(j=0; j<Map->NX; j++){
      free(SubDir[i][j]);
    }
    free(SubDir[i]);
  }
  free(SubDir);
  free(SubTotalDir);
  free(SubFlowGrad);

  /**********************************************************************/
  /* Dump saturation extent file to screen for Mass Wasting dates.
     Saturation extent is based on the number of pixels with a water table 
     that is at least MTHRESH of soil depth. */ 
  
  count =0;
  totalcount = 0;
  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	mgrid = (SoilMap[y][x].Depth - SoilMap[y][x].TableDepth)/SoilMap[y][x].Depth;
	if(mgrid > MTHRESH) count += 1;
	totalcount +=1;
      }
    }
  }
 
  sat = 100.*((float)count/(float)totalcount);
  
  sprintf(satoutfile, "%ssaturation_extent.txt", DumpPath);
  
  if((fs=fopen(satoutfile,"a")) == NULL){
    printf("Cannot open saturation extent output file.\n");
    exit(0);
  }
  
  SPrintDate(&(Time->Current), buffer);
  fprintf(fs, "%-20s %.4f \n", buffer, sat); 
  fclose(fs);    
  
  /* Initialize the mass wasting variables for all time steps
     to maintain the mass balance */
  if(Options->Sediment){
    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {
	  for(ii=0; ii< Map->DY/Map->DMASS; ii++) { /* Fine resolution counters. */
	    for(jj=0; jj< Map->DX/Map->DMASS; jj++) {
	      yy = (int) y*Map->DY/Map->DMASS + ii;
	      xx = (int) x*Map->DX/Map->DMASS + jj;
	      (*FineMap[yy][xx]).Probability = 0.;
	      (*FineMap[yy][xx]).MassWasting = 0.;
	      (*FineMap[yy][xx]).MassDeposition = 0.;
	      (*FineMap[yy][xx]).SedimentToChannel = 0.;
	    }
	  }
	}
      }
    }
    
    /* Call the mass wasting algorithm */
    if(Options->MassWaste){
      if(Time->NMWMTotalSteps > 0){
	if(Time->Current.Julian == Time->MWMnext.Julian){   
	  MainMWM(SedMap, FineMap, VType, SedType, ChannelData, DumpPath, SoilMap,
		  Time, Map, TopoMap, SType, VegMap, MaxStreamID, SnowMap);
	  
	  /* catch the next date */
	  for (i = 0; i < Time->NMWMTotalSteps; i++){
	    if(Time->MWMnext.Julian < Time->MWM[i].Julian){
	      Time->MWMnext = Time->MWM[i];
	      break;
	    }
	  }
	}
      }
      else{ /* Time->NMWMTotalSteps == 0 run the old way*/
	if((float)count/((float)totalcount) > SATPERCENT) {
	  MainMWM(SedMap, FineMap, VType, SedType, ChannelData, DumpPath, SoilMap,
		  Time, Map, TopoMap, SType, VegMap, MaxStreamID, SnowMap);
	}
      }
    }
  }
  
  /**********************************************************************/
  /* End added code. */
  
}
Exemple #6
0
/*****************************************************************************
  Function name: CalcWeights()

  Purpose      : Calculate interpolation weights to interpolate the
                 meteorological data from the various stations for every
                 individual pixel

  Required     :
    METLOCATION *Station - Location of meteorological stations
    int NStats           - Number of meteorological stations
    int NX               - Number of pixels in East - West direction
    int NY               - Number of pixels in North - South direction
    uchar ** BasinMask   - BasinMask
    uchar ***WeightArray - 3D array with interpolation weights
  
  Returns      :  void

  Modifies     :
    The values stored at the addresses pointed to by WeightArray (i.e. it
    calculates the weights and stores them)

  Comments     :
*****************************************************************************/
void CalcWeights(METLOCATION * Station, int NStats, int NX, int NY,
		 uchar ** BasinMask, uchar **** WeightArray,
		 OPTIONSTRUCT * Options)
{
  double *Weights;		/* Array with weights for all stations */
  double *Distance;		/* Array with distances to all stations */
  double *InvDist2;		/* Array with inverse distance squared */
  double Denominator;		/* Sum of 1/Distance^2 */
  double mindistance;
  double avgdistance;
  double tempdistance;
  double cr, crt;
  int totalweight;
  int y;			/* Counter for rows */
  int x;			/* Counter for columns */
  int i, j;			/* Counter for stations */
  int CurrentStation;		/* Station at current location (if any) */
  int *stationid;		/* index array for sorted list of station distances */
  int *stat;
  int tempid;
  int closest;
  int crstat;
  COORD Loc;			/* Location of current point */

  /* Allocate memory for a 3 dimensional array */

  if (DEBUG)
    printf("Calculating interpolation weights for %d stations\n", NStats);

  if (!((*WeightArray) = (uchar ***) calloc(NY, sizeof(uchar **))))
    ReportError("CalcWeights()", 1);

  for (y = 0; y < NY; y++)
    if (!((*WeightArray)[y] = (uchar **) calloc(NX, sizeof(uchar *))))
      ReportError("CalcWeights()", 1);

  for (y = 0; y < NY; y++)
    for (x = 0; x < NX; x++)
      if (!((*WeightArray)[y][x] = (uchar *) calloc(NStats, sizeof(uchar))))
	ReportError("CalcWeights()", 1);

  /* Allocate memory for the array that will contain weights, and the array for
     the distances to each of the towers, and the inverse distance squared */

  if (!(Weights = (double *) calloc(NStats, sizeof(double))))
    ReportError("CalcWeights()", 1);

  if (!(Distance = (double *) calloc(NStats, sizeof(double))))
    ReportError("CalcWeights()", 1);

  if (!(InvDist2 = (double *) calloc(NStats, sizeof(double))))
    ReportError("CalcWeights()", 1);

  if (!(stationid = (int *) calloc(NStats, sizeof(int))))
    ReportError("CalcWeights()", 1);
  if (!(stat = (int *) calloc(NStats + 1, sizeof(int))))
    ReportError("CalcWeights()", 1);

  /* Calculate the weights for each location that is inside the basin mask */
  /* note stations themselves can be outside the mask */
  /* this first scheme is an inverse distance squared scheme */

  if (Options->Interpolation == INVDIST) {
    for (y = 0; y < NY; y++) {
      Loc.N = y;
      for (x = 0; x < NX; x++) {
	Loc.E = x;
	if (INBASIN(BasinMask[y][x])) {
	  if (IsStationLocation(&Loc, NStats, Station, &CurrentStation)) {
	    for (i = 0; i < NStats; i++) {
	      if (i == CurrentStation)
		(*WeightArray)[y][x][i] = MAXUCHAR;
	      else
		(*WeightArray)[y][x][i] = 0;
	    }
	  }
	  else {
	    for (i = 0, Denominator = 0; i < NStats; i++) {
	      Distance[i] = CalcDistance(&(Station[i].Loc), &Loc);
	      InvDist2[i] = 1 / (Distance[i] * Distance[i]);
	      Denominator += InvDist2[i];
	    }
	    for (i = 0; i < NStats; i++) {
	      (*WeightArray)[y][x][i] =
		(uchar) Round(InvDist2[i] / Denominator * MAXUCHAR);
	    }
	  }
	}
	else {
	  for (i = 0; i < NStats; i++)
	    (*WeightArray)[y][x][i] = 0;
	}
      }
    }
  }
  if (Options->Interpolation == NEAREST) {

    /* this next scheme is a nearest station */
    printf("Number of stations is %d \n", NStats);

    for (y = 0; y < NY; y++) {
      Loc.N = y;
      for (x = 0; x < NX; x++) {
	Loc.E = x;
	if (INBASIN(BasinMask[y][x])) {	/*we are inside the basin mask */
	  /* find the distance to nearest station */
	  mindistance = DHSVM_HUGE;
	  avgdistance = 0.0;
	  for (i = 0; i < NStats; i++) {
	    Distance[i] = CalcDistance(&(Station[i].Loc), &Loc);
	    avgdistance += Distance[i] / ((double) NStats);
	    if (Distance[i] < mindistance) {
	      mindistance = Distance[i];
	      closest = i;
	    }
	  }
	  /* got closest station */

	  for (i = 0; i < NStats; i++) {
	    if (i == closest)
	      (*WeightArray)[y][x][i] = MAXUCHAR;
	    else
	      (*WeightArray)[y][x][i] = 0;
	  }

	}			/* done in basin mask */
	else {
	  for (i = 0; i < NStats; i++)
	    (*WeightArray)[y][x][i] = 0;
	}
      }
    }
  }

  if (Options->Interpolation == VARCRESS) {

    /* this next scheme is a variable radius cressman */
    /* find the distance to the nearest station */
    /* make a decision based on the maximum allowable radius, cr */
    /* and the distance to the closest station */
    /* while limiting the number of interpolation stations to three */
    cr = (double) Options->CressRadius;
    if (cr < 2)
      ReportError("CalcWeights.c", 42);
    crstat = Options->CressStations;
    if (crstat < 2)
      ReportError("CalcWeights.c", 42);
    for (y = 0; y < NY; y++) {
      Loc.N = y;
      for (x = 0; x < NX; x++) {
	Loc.E = x;
	if (INBASIN(BasinMask[y][x])) {	/*we are inside the basin mask */
	  /* find the distance to nearest station */
	  for (i = 0; i < NStats; i++) {
	    Distance[i] = CalcDistance(&(Station[i].Loc), &Loc);
	    stationid[i] = i;
	  }
	  /* got distances for each station */
	  /* now sort the list by distance */
	  for (i = 0; i < NStats; i++) {
	    for (j = 0; j < NStats; j++) {
	      if (Distance[j] > Distance[i]) {
		tempdistance = Distance[i];
		tempid = stationid[i];
		Distance[i] = Distance[j];
		stationid[i] = stationid[j];
		Distance[j] = tempdistance;
		stationid[j] = tempid;
	      }
	    }
	  }

	  crt = Distance[0] * 2.0;
	  if (crt < 1.0)
	    crt = 1.0;
	  for (i = 0, Denominator = 0; i < NStats; i++) {
	    if (i < crstat && Distance[i] < crt) {
	      InvDist2[i] =
		(crt * crt - Distance[i] * Distance[i]) /
		(crt * crt + Distance[i] * Distance[i]);
	      Denominator += InvDist2[i];
	    }
	    else
	      InvDist2[i] = 0.0;
	  }

	  for (i = 0; i < NStats; i++)
	    (*WeightArray)[y][x][stationid[i]] =
	      (uchar) Round(InvDist2[i] / Denominator * MAXUCHAR);

	  /*at this point all weights have been assigned to one or more stations */

	}
      }
    }
  }

  /*check that all weights add up to MAXUCHAR */
  /* and output some stats on the interpolation field */

  for (i = 0; i <= NStats; i++)
    stat[i] = 0;
  for (i = 0; i < NStats; i++)
    stationid[i] = 0;

  printf("\nChecking interpolation weights\n");
  printf("Sum should be 255 for all pixels \n");
  printf("Some error is expected due to roundoff \n");
  printf("Errors greater than +/- 2 Percent are: \n");

  for (y = 0; y < NY; y++) {
    for (x = 0; x < NX; x++) {
      if (INBASIN(BasinMask[y][x])) {	/*we are inside the basin mask */
	tempid = 0;
	totalweight = 0;

	for (i = 0; i < NStats; i++) {
	  totalweight += (int) (*WeightArray)[y][x][i];
	  if ((*WeightArray)[y][x][i] > 0) {
	    tempid += 1;
	    stationid[i] = 1;
	  }
	}

	if (totalweight < 250 || totalweight > 260)
	{
	  printf("error in interpolation weight at pixel y %d x %d : %d \n", y,
		 x, totalweight);
	  assert(FALSE);
	}
	stat[tempid] += 1;
      }

    }
  }
  for (i = 0; i <= NStats; i++)
    if (stat[i] > 0)
      printf("this many pixels %d are linked to %d met stations \n", stat[i],
	     i);

  for (i = 0; i < NStats; i++)
    if (stationid[i] > 0)
      printf("Station: %s used in interpolation \n", Station[i].Name);

  /* Free memory */

  free(Weights);
  free(Distance);
  free(InvDist2);
  free(stationid);
  free(stat);
}
Exemple #7
0
/*****************************************************************************
  Aggregate()
  
  Calculate the average values for the different fluxes and state variables
  over the basin.  Only the runoff and some of the sediment variables (as 
  noted) are calculated as a totals (i.e. runoff is total volume) instead
  of an average.  In the current implementation the local radiation
  elements are not stored for the entire area.  Therefore these components
  are aggregated in AggregateRadiation() inside MassEnergyBalance().
  
  The aggregated values are set to zero in the function RestAggregate,
  which is executed at the beginning of each time step.
*****************************************************************************/
void Aggregate(MAPSIZE *Map, OPTIONSTRUCT *Options, TOPOPIX **TopoMap,
	       LAYER *Soil, LAYER * Veg, VEGPIX **VegMap, EVAPPIX **Evap,
	       PRECIPPIX **Precip, RADCLASSPIX **RadMap, SNOWPIX **Snow,
	       SOILPIX **SoilMap, AGGREGATED *Total, VEGTABLE *VType,
	       ROADSTRUCT **Network, SEDPIX **SedMap, FINEPIX ***FineMap,
	       CHANNEL *ChannelData, float *roadarea)
{
  int NPixels;			/* Number of pixels in the basin */
  int NPixelsfine;		/* Number of pixels in the finemap */
  int NSoilL;			/* Number of soil layers for current pixel */
  int NVegL;			/* Number of vegetation layers for current pixel */
  int i;				/* counter */
  int j;				/* counter */
  int x;
  int y;
  float DeepDepth;		/* depth to bottom of lowest rooting zone */
  int ii;				/* FineMap counter */
  int jj;				/* FineMap counter */
  int xx;				/* x-coordinate on FineMap grid */
  int yy;				/* y-coordinate on FineMap grid */

  NPixels = 0;
  *roadarea = 0.;
  NPixelsfine = 0;

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
		  NPixels++;
		  NSoilL = Soil->NLayers[SoilMap[y][x].Soil - 1];
		  NVegL = Veg->NLayers[VegMap[y][x].Veg - 1];
		  
		  /* aggregate the evaporation data */
		  Total->Evap.ETot += Evap[y][x].ETot;
		  for (i = 0; i < NVegL; i++) {
			  Total->Evap.EPot[i] += Evap[y][x].EPot[i];
			  Total->Evap.EAct[i] += Evap[y][x].EAct[i];
			  Total->Evap.EInt[i] += Evap[y][x].EInt[i];
		  }
		  Total->Evap.EPot[Veg->MaxLayers] += Evap[y][x].EPot[NVegL];
		  Total->Evap.EAct[Veg->MaxLayers] += Evap[y][x].EAct[NVegL];
		  
		  for (i = 0; i < NVegL; i++) {
			  for (j = 0; j < NSoilL; j++) {
				  Total->Evap.ESoil[i][j] += Evap[y][x].ESoil[i][j];
			  }
		  }
		  Total->Evap.EvapSoil += Evap[y][x].EvapSoil;
		  
		  /* aggregate precipitation data */
		  Total->Precip.Precip += Precip[y][x].Precip;
		  for (i = 0; i < NVegL; i++) {
			  Total->Precip.IntRain[i] += Precip[y][x].IntRain[i];
			  Total->Precip.IntSnow[i] += Precip[y][x].IntSnow[i];
			  Total->CanopyWater += Precip[y][x].IntRain[i] +
			  Precip[y][x].IntSnow[i];
		  }

	/* aggregate radiation data */
	if (Options->MM5 == TRUE) {
	  Total->RadClass.Beam = NOT_APPLICABLE;
	  Total->RadClass.Diffuse = NOT_APPLICABLE;
	}
	else {
	  Total->RadClass.Beam += RadMap[y][x].Beam;
	  Total->RadClass.Diffuse += RadMap[y][x].Diffuse;
	}

	/* aggregate snow data */
	if (Snow[y][x].HasSnow)
		Total->Snow.HasSnow = TRUE;
		Total->Snow.Swq += Snow[y][x].Swq;
		Total->Snow.Glacier += Snow[y][x].Glacier;
		/* Total->Snow.Melt += Snow[y][x].Melt; */
		Total->Snow.Melt += Snow[y][x].Outflow;
		Total->Snow.PackWater += Snow[y][x].PackWater;
		Total->Snow.TPack += Snow[y][x].TPack;
		Total->Snow.SurfWater += Snow[y][x].SurfWater;
		Total->Snow.TSurf += Snow[y][x].TSurf;
		Total->Snow.ColdContent += Snow[y][x].ColdContent;
		Total->Snow.Albedo += Snow[y][x].Albedo;
		Total->Snow.Depth += Snow[y][x].Depth;
		Total->Snow.VaporMassFlux += Snow[y][x].VaporMassFlux;
		Total->Snow.CanopyVaporMassFlux += Snow[y][x].CanopyVaporMassFlux;

		/* aggregate soil moisture data */
		Total->Soil.Depth += SoilMap[y][x].Depth;
		DeepDepth = 0.0;

		for (i = 0; i < NSoilL; i++) {
			Total->Soil.Moist[i] += SoilMap[y][x].Moist[i];
			assert(SoilMap[y][x].Moist[i] >= 0.0);
			Total->Soil.Perc[i] += SoilMap[y][x].Perc[i];
			Total->Soil.Temp[i] += SoilMap[y][x].Temp[i];
			Total->SoilWater += SoilMap[y][x].Moist[i] * VType[VegMap[y][x].Veg - 1].RootDepth[i] * Network[y][x].Adjust[i]; 
			DeepDepth += VType[VegMap[y][x].Veg - 1].RootDepth[i];
		}

		Total->Soil.Moist[Soil->MaxLayers] += SoilMap[y][x].Moist[NSoilL];
		Total->SoilWater += SoilMap[y][x].Moist[NSoilL] * (SoilMap[y][x].Depth - DeepDepth) * Network[y][x].Adjust[NSoilL];
		Total->Soil.TableDepth += SoilMap[y][x].TableDepth;

		if (SoilMap[y][x].TableDepth <= 0)
			(Total->Saturated)++;
		
		Total->Soil.WaterLevel += SoilMap[y][x].WaterLevel;
		Total->Soil.SatFlow += SoilMap[y][x].SatFlow;
		Total->Soil.TSurf += SoilMap[y][x].TSurf;
		Total->Soil.Qnet += SoilMap[y][x].Qnet;
		Total->Soil.Qs += SoilMap[y][x].Qs;
		Total->Soil.Qe += SoilMap[y][x].Qe;
		Total->Soil.Qg += SoilMap[y][x].Qg;
		Total->Soil.Qst += SoilMap[y][x].Qst;
		Total->Soil.IExcess += SoilMap[y][x].IExcess;
		Total->Soil.DetentionStorage += SoilMap[y][x].DetentionStorage;
		if(Options->RoadRouting){
			if (Network[y][x].RoadArea > 0) {
				for (i = 0; i < CELLFACTOR; i++)
					Total->Road.IExcess += (Network[y][x].h[i]* Network[y][x].RoadArea)/((float)CELLFACTOR * (Map->DX*Map->DY));
			}
		}
		
		if (Options->Infiltration == DYNAMIC)
			Total->Soil.InfiltAcc += SoilMap[y][x].InfiltAcc;
		
		Total->Runoff += SoilMap[y][x].Runoff;
		Total->ChannelInt += SoilMap[y][x].ChannelInt;
		SoilMap[y][x].ChannelInt = 0.0;
		Total->RoadInt += SoilMap[y][x].RoadInt;
		SoilMap[y][x].RoadInt = 0.0;
		
		if(Options->Sediment){
			if (Options->SurfaceErosion) {
				Total->Sediment.Erosion += SedMap[y][x].Erosion; 
				Total->Sediment.SedFluxOut += SedMap[y][x].SedFluxOut; 
			}
			*roadarea += Network[y][x].RoadArea;
			Total->Road.Erosion += Network[y][x].Erosion;
			Total->Sediment.RoadSed += SedMap[y][x].RoadSed;
			for (ii=0; ii< Map->DY/Map->DMASS; ii++) {
				for (jj=0; jj< Map->DX/Map->DMASS; jj++) {
					yy = (int) y*Map->DY/Map->DMASS + ii;
					xx = (int) x*Map->DX/Map->DMASS + jj;
					Total->Fine.SatThickness += (*FineMap[yy][xx]).SatThickness;
					Total->Fine.DeltaDepth += (*FineMap[yy][xx]).DeltaDepth;
					Total->Fine.Probability += (*FineMap[yy][xx]).Probability;
					Total->Fine.MassWasting += (*FineMap[yy][xx]).MassWasting;
					Total->Fine.MassDeposition += (*FineMap[yy][xx]).MassDeposition;
					Total->Fine.SedimentToChannel += (*FineMap[yy][xx]).SedimentToChannel;
				}
			}
		}
      }
    }
  }
  /* divide road area by pixel area so it can be used to calculate depths
     over the road surface in FinalMassBalancs */
  *roadarea /= Map->DX * Map->DY * NPixels;

  /* calculate average values for all quantities except the surface flow */

  /* average evaporation data */
  Total->Evap.ETot /= NPixels;
  for (i = 0; i < Veg->MaxLayers + 1; i++) {
    Total->Evap.EPot[i] /= NPixels;
    Total->Evap.EAct[i] /= NPixels;
  }
  for (i = 0; i < Veg->MaxLayers; i++)
    Total->Evap.EInt[i] /= NPixels;
  for (i = 0; i < Veg->MaxLayers; i++) {
    for (j = 0; j < Soil->MaxLayers; j++) {
      Total->Evap.ESoil[i][j] /= NPixels;
    }
  }
  Total->Evap.EvapSoil /= NPixels;;

  /* average precipitation data */
  Total->Precip.Precip /= NPixels;
  for (i = 0; i < Veg->MaxLayers; i++) {
    Total->Precip.IntRain[i] /= NPixels;
    Total->Precip.IntSnow[i] /= NPixels;
  }
  Total->CanopyWater /= NPixels;

  /* average radiation data */
  for (i = 0; i < Veg->MaxLayers + 1; i++) {
    Total->Rad.NetShort[i] /= NPixels;
    Total->Rad.LongIn[i] /= NPixels;
    Total->Rad.LongOut[i] /= NPixels;
  }
  Total->Rad.PixelNetShort /= NPixels;
  Total->Rad.PixelLongIn /= NPixels;
  Total->Rad.PixelLongOut /= NPixels;

  Total->RadClass.Beam /= NPixels;
  Total->RadClass.Diffuse /= NPixels;

  /* average snow data */
  Total->Snow.Swq /= NPixels;
  Total->Snow.Melt /= NPixels;
  Total->Snow.PackWater /= NPixels;
  Total->Snow.TPack /= NPixels;
  Total->Snow.SurfWater /= NPixels;
  Total->Snow.TSurf /= NPixels;
  Total->Snow.ColdContent /= NPixels;
  Total->Snow.Albedo /= NPixels;
  Total->Snow.Depth /= NPixels;
  Total->Snow.VaporMassFlux /= NPixels;
  Total->Snow.CanopyVaporMassFlux /= NPixels;

  /* average soil moisture data */
  Total->Soil.Depth /= NPixels;
  for (i = 0; i < Soil->MaxLayers; i++) {
    Total->Soil.Moist[i] /= NPixels;
    Total->Soil.Perc[i] /= NPixels;
    Total->Soil.Temp[i] /= NPixels;
  }
  Total->Soil.Moist[Soil->MaxLayers] /= NPixels;
  Total->Soil.TableDepth /= NPixels;
  Total->Soil.WaterLevel /= NPixels;
  Total->Soil.SatFlow /= NPixels;
  Total->Soil.TSurf /= NPixels;
  Total->Soil.Qnet /= NPixels;
  Total->Soil.Qs /= NPixels;
  Total->Soil.Qe /= NPixels;
  Total->Soil.Qg /= NPixels;
  Total->Soil.Qst /= NPixels;
  Total->Soil.IExcess /= NPixels;
  Total->Soil.DetentionStorage /= NPixels;
  Total->Road.IExcess /= NPixels;
  
  if (Options->Infiltration == DYNAMIC)
    Total->Soil.InfiltAcc /= NPixels;
  Total->SoilWater /= NPixels;
  Total->Runoff /= NPixels;
  Total->ChannelInt /= NPixels;
  Total->RoadInt /= NPixels;
  Total->CulvertReturnFlow /= NPixels;
  Total->CulvertToChannel /= NPixels;
  Total->RunoffToChannel /= NPixels;

  /* Average Sediment results */
  if (Options->Sediment) {
    if (Options->SurfaceErosion){
      Total->Sediment.Erosion /= NPixels; 
      Total->Sediment.SedFluxOut /= NPixels; 
    }
    Total->Road.Erosion /= NPixels;
    Total->Sediment.RoadSed /= NPixels;
    // FineMap quantities must be averaged over number of FineMap cells
    // rather than over the number of coarse grid cells
    Total->Fine.SatThickness /= (NPixels*Map->DMASS*Map->DMASS); 
    Total->Fine.DeltaDepth /= (NPixels*Map->DMASS*Map->DMASS); 
    Total->Fine.Probability /= (NPixels*Map->DMASS*Map->DMASS); 
    // (We don't divide SedimentToChannel, MassWasting, etc. by NPixels,
    // since they are totals and not averages)
  }
}
Exemple #8
0
/* -------------------------------------------------------------
   RouteChannel
   ------------------------------------------------------------- */
void
RouteChannel(CHANNEL * ChannelData, TIMESTRUCT * Time, MAPSIZE * Map,
	    TOPOPIX ** TopoMap, SOILPIX ** SoilMap, AGGREGATED * Total, 
	     OPTIONSTRUCT *Options, ROADSTRUCT ** Network, 
	     SOILTABLE * SType, PRECIPPIX ** PrecipMap, SEDPIX **SedMap,
	     float Tair, float Rh, float *SedDiams)
{
  int x, y;
  int flag;
  char buffer[32];
  float CulvertFlow;


  /* give any surface water to roads w/o sinks */
  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	SoilMap[y][x].IExcessSed = SoilMap[y][x].IExcess;
	if (channel_grid_has_channel(ChannelData->road_map, x, y) && !channel_grid_has_sink(ChannelData->road_map, x, y)) {	/* road w/o sink */


	  SoilMap[y][x].RoadInt += SoilMap[y][x].IExcess;
	  channel_grid_inc_inflow(ChannelData->road_map, x, y,
				  SoilMap[y][x].IExcess * Map->DX * Map->DY);
	  SoilMap[y][x].IExcess = 0.0f;
	  
	}
      }
    }
  }
  
  if(Options->RoadRouting){
    RouteRoad(Map, Time, TopoMap, SoilMap, Network, SType, ChannelData, 
	      PrecipMap, SedMap, Tair, Rh, SedDiams);  
  }

  /* route the road network and save results */
  SPrintDate(&(Time->Current), buffer);
  flag = IsEqualTime(&(Time->Current), &(Time->Start));
  if (ChannelData->roads != NULL) {
    channel_route_network(ChannelData->roads, Time->Dt);
    channel_save_outflow_text(buffer, ChannelData->roads,
			      ChannelData->roadout, ChannelData->roadflowout,
			      flag);
  }
  
  /* add culvert outflow to surface water */
  Total->CulvertReturnFlow = 0.0;
  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {

	CulvertFlow = ChannelCulvertFlow(y, x, ChannelData);
	CulvertFlow /= Map->DX * Map->DY;
	/* CulvertFlow = (CulvertFlow > 0.0) ? CulvertFlow : 0.0; */
	
	if (channel_grid_has_channel(ChannelData->stream_map, x, y)) {
	  channel_grid_inc_inflow(ChannelData->stream_map, x, y,
				  (SoilMap[y][x].IExcess + 
				   CulvertFlow) * Map->DX * Map->DY);
	  SoilMap[y][x].ChannelInt += SoilMap[y][x].IExcess;
	  
	  Total->CulvertToChannel += CulvertFlow;
	  Total->RunoffToChannel += SoilMap[y][x].IExcess;
	  
	  SoilMap[y][x].IExcess = 0.0f;

	}
	else {
	  SoilMap[y][x].IExcess += CulvertFlow;
	  Total->CulvertReturnFlow += CulvertFlow;
	  
	}
      }
    }
  }
  /* route stream channels */
  if (ChannelData->streams != NULL) {
    channel_route_network(ChannelData->streams, Time->Dt);
    channel_save_outflow_text(buffer, ChannelData->streams,
			      ChannelData->streamout,
			      ChannelData->streamflowout, flag);
	/* save parameters for John's RBM model */
	if (Options->StreamTemp)
	  channel_save_outflow_text_cplmt(Time, buffer,ChannelData->streams,ChannelData, flag);
  }
  
}
Exemple #9
0
void CheckOut(int CanopyRadAttOption, LAYER Veg, LAYER Soil,
              VEGTABLE *VType, SOILTABLE *SType, MAPSIZE *Map,
              TOPOPIX **TopoMap, VEGPIX **VegMap, SOILPIX **SoilMap)
{

    int y, x, i, j;
    int *count = NULL, *scount = NULL;
    float a, b, l, Taud, Taub20, Taub40, Taub60, Taub80;

    int npixels;

    if (!(count = static_cast<int*>(calloc(Veg.NTypes, sizeof(int))))) {
        ReportError("Checkout", 1);
    }
    if (!(scount = static_cast<int *>(calloc(Soil.NTypes, sizeof(int))))) {
        ReportError("Checkout", 1);
    }

    for (y = 0; y < Map->NY; y++) {
        for (x = 0; x < Map->NX; x++) {
            if (INBASIN(TopoMap[y][x].Mask)) {
                if (VegMap[y][x].Veg < 1 || VegMap[y][x].Veg > Veg.NTypes) {
                    printf("veg value %d out of range \n", VegMap[y][x].Veg);
                    exit(-1);
                }

                count[VegMap[y][x].Veg - 1]++;

                if (SoilMap[y][x].Soil < 1 || SoilMap[y][x].Soil > Soil.NTypes) {
                    printf("soil value %d out of range \n", SoilMap[y][x].Soil);
                    exit(-1);
                }
                scount[SoilMap[y][x].Soil - 1]++;

            }
        }
    }

    i = 0;
    for (y = 0; y < Map->NY; y++) {
        for (x = 0; x < Map->NX; x++) {
            if (INBASIN(TopoMap[y][x].Mask)) {
                i = i + 1;
            }
        }
    }
    printf("\nBasin has %d active pixels \n", i);
    npixels = i;

    printf("\nThe following VEG types are in the current basin \n");

    for (i = 0; i < Veg.NTypes; i++) {
        if (count[i] > 0)
            printf
            ("Class # %d of Type: %s has fraction basin area: %5.3f\n",
             i + 1, VType[i].Desc, (float) count[i] / (float) npixels);
        VType[i].TotalDepth = 0.0;
        for (y = 0; y < VType[i].NSoilLayers; y++) {
            VType[i].TotalDepth += VType[i].RootDepth[y];
        }
    }

    printf("\nThe following SOIL types are in the current basin \n");
    for (i = 0; i < Soil.NTypes; i++)
        if (scount[i] > 0)
            printf
            ("Class # %d of Type: %s has fraction basin area: %5.3f\n",
             i + 1, SType[i].Desc, (float) scount[i] / (float) npixels);

    printf("\nSome estimates for current vegetation specification\n");
    for (i = 0; i < Veg.NTypes; i++) {
        if (count[i] > 0) {

            printf("\nVegetation Type: %s\n", VType[i].Desc);
            printf("2meter    wind speed fraction of ref level %1.3f\n",
                   VType[i].USnow);
            if (VType[i].OverStory) {
                for (j = 0; j < 12; j++) {
                    if (fequal(VType[i].LAIMonthly[0][j], 0.0)) {
                        printf("Overstory LAI must be > 0\n");
                        exit(-1);
                    }
                }
                /* printf("Overstory LAI July %2.3f Effective LAI July %2.3f\n", VType[i].LAIMonthly[0][6]);*/
                if (CanopyRadAttOption == VARIABLE) {
                    a = VType[i].LeafAngleA;
                    b = VType[i].LeafAngleB;
                    l = VType[i].LAIMonthly[0][6] / VType[i].ClumpingFactor;
                    if (l == 0)
                        Taud = 1.0;
                    else
                        Taud =
                            exp(-b * l) * ((1 - a * l) * exp(-a * l) +
                                           (a * l) * (a * l) * evalexpint(1, a * l));
                    Taub20 = exp(-l * (VType[i].LeafAngleA /
                                       0.342 + VType[i].LeafAngleB));
                    Taub40 = exp(-l * (VType[i].LeafAngleA /
                                       0.642 + VType[i].LeafAngleB));
                    Taub60 = exp(-l * (VType[i].LeafAngleA /
                                       0.866 + VType[i].LeafAngleB));
                    Taub80 = exp(-l * (VType[i].LeafAngleA /
                                       0.984 + VType[i].LeafAngleB));
                    printf("Solar Altitude 20 deg Tbeam %f Tdiff %f\n", Taub20, Taud);
                    printf("Solar Altitude 40 deg Tbeam %f Tdiff %f\n", Taub40, Taud);
                    printf("Solar Altitude 60 deg Tbeam %f Tdiff %f\n", Taub60, Taud);
                    printf("Solar Altitude 80 deg Tbeam %f Tdiff %f\n", Taub80, Taud);
                }
            }
        }
    }

    for (y = 0; y < Map->NY; y++) {
        for (x = 0; x < Map->NX; x++) {
            if (INBASIN(TopoMap[y][x].Mask)) {
                if (SoilMap[y][x].Depth <= VType[VegMap[y][x].Veg - 1].TotalDepth) {
                    printf("Error for class %d of Type %s  \n", VegMap[y][x].Veg,
                           VType[VegMap[y][x].Veg - 1].Desc);
                    printf("%d %d Soil depth is %f, Root depth is %f \n", y,x,SoilMap[y][x].Depth,
                           VType[VegMap[y][x].Veg - 1].TotalDepth);
                    exit(-1);
                }
            }
        }
    }
    if (count) {
        free(count);
    }
    if (scount) {
        free(scount);
    }
}
Exemple #10
0
/* -------------------------------------------------------------
   ElevationSlopeAspect
   ------------------------------------------------------------- */
void ElevationSlopeAspect(MAPSIZE * Map, TOPOPIX ** TopoMap)
{
  const char *Routine = "ElevationSlopeAspect";
  int x;
  int y;
  int n;
  int k;
  float neighbor_elev[NNEIGHBORS];
  int tempdir[NDIRS];
  int steepestdirection;
  unsigned int sum;
  float min;
  int xn, yn;

  /* fill neighbor array */
  
  for (x = 0; x < Map->NX; x++) {
    for (y = 0; y < Map->NY; y++) {
      if (INBASIN(TopoMap[y][x].Mask)) {

	/* Count the number of cells in the basin.  
	   Need this to allocate memory for
	   the new, smaller Elev[] and Coords[][].  */
	Map->NumCells++;

	for (n = 0; n < NNEIGHBORS; n++) {
	  xn = x + xneighbor[n];
	  yn = y + yneighbor[n];
	  
	  
	  if (valid_cell(Map, xn, yn)) {
	    neighbor_elev[n] = ((TopoMap[yn][xn].Mask) ? TopoMap[yn][xn].Dem : (float) OUTSIDEBASIN);
	  }
	  else {
	    neighbor_elev[n] = (float) OUTSIDEBASIN;
	  }
	}
	
	slope_aspect(Map->DX, Map->DY, TopoMap[y][x].Dem, neighbor_elev,
		     &(TopoMap[y][x].Slope), &(TopoMap[y][x].Aspect));
	
	/* fill Dirs in TopoMap too */
	
	flow_fractions(Map->DX, Map->DY, TopoMap[y][x].Slope,
		       TopoMap[y][x].Aspect,
		       neighbor_elev, &(TopoMap[y][x].FlowGrad),
		       TopoMap[y][x].Dir, &(TopoMap[y][x].TotalDir));

	/* Check that upslope neighbors && outsidebasin Dir = 0. */
	
	for (n = 0; n < NDIRS; n++)
	  tempdir[n] = 0; /* initialize */
	   
	sum = 0;
	for (n = 0; n < NDIRS; n++) {
	  xn = x + xdirection[n];
	  yn = y + ydirection[n];
	  
	  if ((TopoMap[y][x].Dir[n] > 0) && valid_cell(Map, xn, yn)) {
	    
	    if (!INBASIN(TopoMap[yn][xn].Mask))  { 
	      /* Can never have flow in this direction.*/
	      (TopoMap[y][x].TotalDir) -= TopoMap[y][x].Dir[n];
	      TopoMap[y][x].Dir[n] = 0; 
	    }
	    else if(TopoMap[yn][xn].Dem >= TopoMap[y][x].Dem) {
	      /* Will put flow in this direction if no other choice to
		 preserve water balance. */
	      (TopoMap[y][x].TotalDir) -= TopoMap[y][x].Dir[n];
	      tempdir[n]=TopoMap[y][x].Dir[n];
	      TopoMap[y][x].Dir[n] = 0; 
	    }
	  }
	  else if((TopoMap[y][x].Dir[n] > 0) && valid_cell(Map, xn, yn)) {
	    /* Can never have flow in this direction, should not be 
	       possible to get here. */
	    (TopoMap[y][x].TotalDir) -= TopoMap[y][x].Dir[n];
	      TopoMap[y][x].Dir[n] = 0; 
	    }
	  sum+=TopoMap[y][x].Dir[n];
	}
	
	/* If there is a sink, check again to see if there 
	   is a direction of steepest descent. Does not account 
	   for ties.*/
	steepestdirection = -99;
	if(sum==0) {
	 
	  min = DHSVM_HUGE;
	       
	  for (n = 0; n < NDIRS; n++) {
	    xn = x + xdirection[n];
	    yn = y + ydirection[n];
	  
	    if (valid_cell(Map, xn, yn)) {
	      if (INBASIN(TopoMap[yn][xn].Mask)) {
		if(TopoMap[yn][xn].Dem < min)
		{ 
		  min = TopoMap[yn][xn].Dem;
		  steepestdirection = n;
		}}
	    }
	  }
	  
	  if(min < TopoMap[y][x].Dem) {
	    TopoMap[y][x].Dir[steepestdirection] = (int)(255.0 + 0.5);
	    TopoMap[y][x].TotalDir = (int)(255.0 + 0.5);
	  }
	  else {
	    /*  Last resort: set the Dir of the cell to the cell that is
		closest in elevation. This should only happen for the 
		basin outlet, unless the Dem wasn't filled. */
	  
	    TopoMap[y][x].Dir[steepestdirection] = (int)(255.0 + 0.5);
	    TopoMap[y][x].TotalDir = (int)(255.0 + 0.5);
	    
	    xn = x + xdirection[steepestdirection];
	    yn = y + ydirection[steepestdirection];
	  }
	}
	
      } // end if (INBASIN(TopoMap[y][x].Mask)) {
    }
  } // end of for loops
	
  /* Create a structure to hold elevations of only those cells
     within the basin and the y,x of those cells.*/
 
  if (!(Map->OrderedCells = (ITEM *) calloc(Map->NumCells, sizeof(ITEM))))
    ReportError((char *) Routine, 1);
  
  k = 0;
  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      /* Save the elevation, y, and x in the ITEM structure. */
      if (INBASIN(TopoMap[y][x].Mask)) {
        Map->OrderedCells[k].Rank = TopoMap[y][x].Dem;
        Map->OrderedCells[k].y = y;
        Map->OrderedCells[k].x = x;
        k++;
      }
    }
  }

  /* Sort Elev in descending order-- Elev.x and Elev.y hold indices. */
  
  quick(Map->OrderedCells, Map->NumCells);

  /* End of modifications to create ordered cell coordinates.  SRW 10/02, LCB 03/03 */

  return;
}
Exemple #11
0
void MainMWM(SEDPIX **SedMap, FINEPIX ***FineMap, VEGTABLE *VType,
	     SEDTABLE *SedType, CHANNEL *ChannelData, char *DumpPath, 
	     SOILPIX **SoilMap, TIMESTRUCT *Time, MAPSIZE *Map,
	     TOPOPIX **TopoMap, SOILTABLE *SType, VEGPIX **VegMap,
	     int MaxStreamID, SNOWPIX **SnowMap) 
{
  int x,y,xx,yy,i,j,ii,jj,k,iter;  /* Counters. */
  int coursei, coursej;
  int nextx, nexty;
  int prevx, prevy;
  int numfailedpixels;
  int numlikelyfailedpixels;
  int numfailures;
  float avgnumfailures;
  float avgpixperfailure;
  float failure_threshold = 0.0;
  char buffer[32];
  char sumoutfile[100];  /* Character array to hold file name. */ 
  int **failure;
  float factor_safety;
  float LocalSlope;
  FILE *fs;                  /* File pointer. */
  int numpixels;
  int cells, count, checksink;
  int massitertemp;               /* if massiter is 0, sets the counter to 1 here */
  float TotalVolume;
  node *head, *tail;
  float SlopeAspect, SedimentToChannel;
  float *SegmentSediment;         /* The cumulative sediment content over all stochastic
				     iterations for each channel segment. */
  float **SegmentSedimentm;         /* The cumulative sediment mass over all stochastic
				     iterations for each channel segment. */
  float *InitialSegmentSediment; /* Placeholder of segment sediment load at 
				    beginning of time step. */
float **InitialSegmentSedimentm; /* Placeholder of segment sediment mass at 
				    beginning of time step. */
  float **SedThickness;          /* Cumulative sediment depth over all stochastic
				    iterations for each pixel.  */
  float **InitialSediment;       /* Place holder of pixel sediment load at beginning of
				    time step. */
  float SedToDownslope;		/* Sediment wasted from a pixel, awaiting redistribution */
  float SedFromUpslope;		/* Wasted sediment being redistributed */
  float FineMapTableDepth;       /* Fine grid water table depth (m) */
  float TableDepth;              /* Coarse grid water table depth (m) */
  float FineMapSatThickness;    /* Fine grid saturated thickness (m) */
  float **Redistribute, **TopoIndex, **TopoIndexAve;
  int firsti, firstj;
  head = NULL;
  tail = NULL;

  /*****************************************************************************
   Allocate memory for Soil Moisture Redistribution
  ****************************************************************************/
  if (!(Redistribute = (float **)calloc(Map->NY, sizeof(float *))))
    ReportError("MainMWM", 1);
  for(i=0; i<Map->NY; i++) {
    if (!(Redistribute[i] = (float *)calloc(Map->NX, sizeof(float))))
      ReportError("MainMWM", 1);
  }
  
  if (!(TopoIndex = (float **)calloc(Map->NY, sizeof(float *))))
    ReportError("MainMWM", 1);
  for(i=0; i<Map->NY; i++) {
    if (!(TopoIndex[i] = (float *)calloc(Map->NX, sizeof(float))))
      ReportError("MainMWM", 1);
  }
  
  if (!(TopoIndexAve = (float **)calloc(Map->NY, sizeof(float *))))
    ReportError("MainMWM", 1);
  for(i=0; i<Map->NY; i++) {
    if (!(TopoIndexAve[i] = (float *)calloc(Map->NX, sizeof(float))))
      ReportError("MainMWM", 1);
  }
  
  /* Redistribute soil moisture from coarse grid to fine grid. The is done similarly
     to Burton, A. and J.C. Bathurst, 1998, Physically based modelling of shallow 
     landslide sediment yield as a catchment scale, Environmental Geology, 
     35 (2-3), 89-99.*/
  
  for (i = 0; i < Map->NY; i++) {
    for (j = 0; j < Map->NX; j++) {
      
      /* Check to make sure region is in the basin. */
      if (INBASIN(TopoMap[i][j].Mask)) {
	
        /* Step over each fine resolution cell within the model grid cell. */
	for(ii=0; ii< Map->DY/Map->DMASS; ii++) { /* Fine resolution counters. */
	  for(jj=0; jj< Map->DX/Map->DMASS; jj++) {
	    y = (int) i*Map->DY/Map->DMASS + ii;
	    x = (int) j*Map->DX/Map->DMASS + jj;
	    
	    TopoIndex[i][j] += (*FineMap[y][x]).TopoIndex;
	    
	  }
	}
	/* TopoIndexAve is the TopoIndex for the coarse grid calculated as the average of the 
	   TopoIndex of the fine grids in the coarse grid. */
	TopoIndexAve[i][j] = TopoIndex[i][j]/Map->NumFineIn;
      }
    }
  }
  
  FineMapSatThickness = 0.;
  
  for (i = 0; i < Map->NY; i++) {
    for (j  = 0; j < Map->NX; j++) {
      if (INBASIN(TopoMap[i][j].Mask)) {
	
	TableDepth = SoilMap[i][j].TableDepth;
	
	/* Do not want to distribute ponded water  */
	if (TableDepth < 0.)
	  TableDepth = 0.;
	
	for(ii=0; ii< Map->DY/Map->DMASS; ii++) {
	  for(jj=0; jj< Map->DX/Map->DMASS; jj++) {
	    y = (int) i*Map->DY/Map->DMASS + ii;
	    x = (int) j*Map->DX/Map->DMASS + jj;
	    
	    if (SoilMap[i][j].Depth > SoilMap[i][j].TableDepth){

	      FineMapTableDepth = TableDepth + 
		((TopoIndexAve[i][j]-(*FineMap[y][x]).TopoIndex)/ 
		 SType[SoilMap[i][j].Soil - 1].KsLatExp);
	      
	      if (FineMapTableDepth < 0.) {
		(*FineMap[y][x]).SatThickness = (*FineMap[y][x]).sediment; 
	      }
	      else if (FineMapTableDepth > (*FineMap[y][x]).sediment)
		(*FineMap[y][x]).SatThickness = 0.; 
	      
	      else 
		(*FineMap[y][x]).SatThickness = (*FineMap[y][x]).sediment -
		  FineMapTableDepth;
	    }	    
	    else (*FineMap[y][x]).SatThickness = 0.; 
	    
	    FineMapSatThickness += (*FineMap[y][x]).SatThickness;
	    
	    if ((ii== Map->DY/Map->DMASS - 1) & (jj== Map->DX/Map->DMASS - 1)){
	      
	      /* Calculating the difference between the volume of water distributed
		 (only saturated) and available volume of water (m3)*/
	      Redistribute[i][j] = (Map->DY * Map->DX *
				    (SoilMap[i][j].Depth - TableDepth)) - 
		(FineMapSatThickness*Map->DMASS*Map->DMASS); 
	      FineMapSatThickness = 0.;
	    }
	  }
	}
      }
    }
  }
  
  /* Redistribute volume difference. Start with cells with too much water. */ 
  for (i = 0; i < Map->NY; i++) {
    for (j  = 0; j < Map->NX; j++) {
      if (INBASIN(TopoMap[i][j].Mask)) {
	
	if (Redistribute[i][j]< -25.){
	  
	  for (k = 0; k < Map->NumFineIn; k++) { 
	    y = TopoMap[i][j].OrderedTopoIndex[k].y;
	    x = TopoMap[i][j].OrderedTopoIndex[k].x;
	    yy = TopoMap[i][j].OrderedTopoIndex[(Map->NumFineIn)-k-1].y;
	    xx = TopoMap[i][j].OrderedTopoIndex[(Map->NumFineIn)-k-1].x;
	    
	    /* Convert sat thickness to a volume */
	    (*FineMap[y][x]).SatThickness *= (Map->DMASS)*(Map->DMASS);
	    /* Add to volume based on amount to be redistributed */
	    (*FineMap[y][x]).SatThickness += Redistribute[i][j] * 
	      ((*FineMap[yy][xx]).TopoIndex/TopoIndex[i][j]); 
	    /* Convert back to thickness (m)*/
	    (*FineMap[y][x]).SatThickness /= (Map->DMASS)*(Map->DMASS);
	    
	  }
	}
      }
    }
  }
  
  /* Redistribute volume difference for cells with too little water.*/ 
  for (i = 0; i < Map->NY; i++) {
    for (j  = 0; j < Map->NX; j++) {
      
      if (INBASIN(TopoMap[i][j].Mask)) {
	
	for(ii=0; ii< Map->DY/Map->DMASS; ii++) {
	  for(jj=0; jj< Map->DX/Map->DMASS; jj++) {
	    y = (int) i*Map->DY/Map->DMASS + ii;
	    x = (int) j*Map->DX/Map->DMASS + jj;
	    
	    if (Redistribute[i][j] > 25.){
	      
	      /* Convert sat thickness to a volume */
	      (*FineMap[y][x]).SatThickness *= (Map->DMASS)*(Map->DMASS);
	      /* Add to volume based on amount to be redistributed */
	      (*FineMap[y][x]).SatThickness += Redistribute[i][j] * 
		((*FineMap[y][x]).TopoIndex/TopoIndex[i][j]);
	      /* Convert back to thickness (m)*/
	      (*FineMap[y][x]).SatThickness /= (Map->DMASS)*(Map->DMASS);
	      
	    }
	    
	    if ((Redistribute[i][j] > 25.)||(Redistribute[i][j]< -25.)){
	      
	      if ((*FineMap[y][x]).SatThickness > (*FineMap[y][x]).sediment)
		(*FineMap[y][x]).SatThickness = (*FineMap[y][x]).sediment; 
	      
	      else if ((*FineMap[y][x]).SatThickness < 0.)
		(*FineMap[y][x]).SatThickness = 0.;
	    }
	  }
	}
      }
    }
  }	      
  
  for(i=0; i<Map->NY; i++) { 
    free(Redistribute[i]);
    free(TopoIndex[i]);
    free(TopoIndexAve[i]);
  }
  free(Redistribute);
  free(TopoIndex);
  free(TopoIndexAve);
  
  /*****************************************************************************
    Allocate memory for ensemble calculations
  *****************************************************************************/
  if (!(failure = (int **)calloc(Map->NYfine, sizeof(int *))))
    ReportError("MainMWM", 1);
  for(i=0; i<Map->NYfine; i++) {
    if (!(failure[i] = (int *)calloc(Map->NXfine, sizeof(int))))
      ReportError("MainMWM", 1);
  }
  
  if (!(SedThickness = (float **)calloc(Map->NYfine, sizeof(float *))))
    ReportError("MainMWM", 1);
  for(i=0; i<Map->NYfine; i++) {
    if (!(SedThickness[i] = (float *)calloc(Map->NXfine, sizeof(float))))
      ReportError("MainMWM", 1);
  }
  
  if (!(InitialSediment = (float **)calloc(Map->NYfine, sizeof(float *))))
    ReportError("MainMWM", 1);
  for(i=0; i<Map->NYfine; i++) {
    if (!(InitialSediment[i] = (float *)calloc(Map->NXfine, sizeof(float))))
      ReportError("MainMWM", 1);
  }
  
  if (!(SegmentSediment = (float *)calloc(MaxStreamID, sizeof(float ))))
    ReportError("MainMWM", 1);

  if (!(SegmentSedimentm = (float **)calloc(MaxStreamID, sizeof(float *))))
    ReportError("MainMWM", 1);
  for(i=1; i<MaxStreamID+1; i++) {
    if (!(SegmentSedimentm[i] = (float *)calloc(NSEDSIZES, sizeof(float))))
      ReportError("MainMWM", 1);
  }
  
  if (!(InitialSegmentSediment = (float *)calloc(MaxStreamID, sizeof(float ))))
    ReportError("MainMWM", 1);

  if (!(InitialSegmentSedimentm = (float **)calloc(MaxStreamID, sizeof(float *))))
    ReportError("MainMWM", 1);  
 for(i=1; i<MaxStreamID+1; i++) {
    if (!(InitialSegmentSedimentm[i] = (float *)calloc(NSEDSIZES, sizeof(float))))
      ReportError("MainMWM", 1);
  }

  /* Initialize arrays. */
  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	for(ii=0; ii< Map->DY/Map->DMASS; ii++) { /* Fine resolution counters. */
	  for(jj=0; jj< Map->DX/Map->DMASS; jj++) {
	    yy = (int) y*Map->DY/Map->DMASS + ii;
	    xx = (int) x*Map->DX/Map->DMASS + jj;
	    InitialSediment[yy][xx] = (*FineMap[yy][xx]).sediment;
	    (*FineMap[yy][xx]).Probability = 0.;
	    (*FineMap[yy][xx]).MassWasting = 0.;
	    (*FineMap[yy][xx]).MassDeposition = 0.;
	    (*FineMap[yy][xx]).SedimentToChannel = 0.;
	  }
	}
      }
    }
  }
  initialize_sediment_mass(ChannelData->streams, InitialSegmentSedimentm);
  update_sediment_array(ChannelData->streams, InitialSegmentSediment, InitialSegmentSedimentm);
  
  /************************************************************************/
  /* Begin iteration for multiple ensembles. */
  /************************************************************************/

  /* sloppy fix for when MASSITER=0 -- this only needs to be checked once */
  if(MASSITER==0) massitertemp=1;
  else massitertemp=MASSITER;
  
  numfailures = 0;
  for(iter=0; iter < massitertemp; iter++) {
    
    printf("iter=%d\n",iter);
    
    /************************************************************************/
    /* Begin factor of safety code. */
    /************************************************************************/
    for(i=0; i<Map->NY; i++) {
      for(j=0; j<Map->NX; j++) {
	if (INBASIN(TopoMap[i][j].Mask)) {		
	  
	  for(ii=0; ii<Map->DY/Map->DMASS; ii++) {
	    for(jj=0; jj<Map->DX/Map->DMASS; jj++) {
	      y = i*Map->DY/Map->DMASS + ii; 
	      x = j*Map->DX/Map->DMASS + jj;
	      coursei = i;
	      coursej = j;

	      firsti=y;
	      firstj=x;
	      /* Don't allow failures that will propagate outside the basin. */
	      /* Fine mask is optional, so they still may occur. */
	      if(INBASIN((*FineMap[y][x]).Mask)) {
		checksink = 0;
		numpixels = 0;
		SedToDownslope = 0.0;
		SedFromUpslope = 0.0;
		SedimentToChannel = 0.0;
		/* First check for original failure. */
		if((*FineMap[y][x]).SatThickness/SoilMap[i][j].Depth > MTHRESH && failure[y][x] == 0
		   && (*FineMap[y][x]).sediment > 0.0) {

		  LocalSlope = ElevationSlope(Map, TopoMap, FineMap, y, x, &nexty, &nextx, y, x, &SlopeAspect);
	
		  if(LocalSlope >= 10.) { 
		    factor_safety = CalcSafetyFactor(LocalSlope, SoilMap[i][j].Soil, 
						     (*FineMap[y][x]).sediment, 
						     VegMap[i][j].Veg, SedType, VType, 
						     (*FineMap[y][x]).SatThickness, SType, 
						     SnowMap[i][j].Swq, SnowMap[i][j].Depth,
						     iter);
		    
		    /* check if fine pixel fails */
		    if (factor_safety < FS_CRITERIA && factor_safety > 0) {
                      numfailures++;
		      numpixels = 1;
		      failure[y][x] = 1;	      
		      
		      /* Update sediment depth. All sediment leaves failed fine pixel */
		      SedToDownslope = (*FineMap[y][x]).sediment;
		      (*FineMap[y][x]).sediment = 0.0;
		   		      
		      // Pass sediment down to next pixel
		      SedFromUpslope = SedToDownslope;

		      /* Follow failures down slope; skipped if no original failure. */
		      while(failure[y][x] == 1 && checksink == 0 
			    && !channel_grid_has_channel(ChannelData->stream_map, coursej, coursei)
			    && INBASIN(TopoMap[coursei][coursej].Mask)) {
			
			/* Update counters. */
			prevy = y;
			prevx = x;
			y = nexty;
			x = nextx;
			coursei = floor(y*Map->DMASS/Map->DY);
			coursej = floor(x*Map->DMASS/Map->DX);
			
			if (!INBASIN(TopoMap[coursei][coursej].Mask)) {
			  
			  printf("WARNING: attempt to propagate failure to grid cell outside basin: y %d x %d\n",y,x);
			  printf("Depositing wasted sediment in grid cell y %d x %d\n",prevy,prevx);
			  (*FineMap[prevy][prevx]).sediment += SedFromUpslope;
			  SedFromUpslope = SedToDownslope = 0.0;
			  
			  // Since we're returning SedFromUpslope to the upslope pixel,
			  // the upslope pixel can't be considered as part of the failure
			  failure[prevy][prevx] = 0;
			  
			}
			else {
			  
			  // Add sediment from upslope to current sediment
			  (*FineMap[y][x]).sediment += SedFromUpslope;
			 			  
			  LocalSlope = ElevationSlope(Map, TopoMap, FineMap, y, x, &nexty, 
					            &nextx, prevy, prevx, &SlopeAspect);
			  /*  Check that not a sink */
			  if(LocalSlope >= 0.) {
			    
			    factor_safety = CalcSafetyFactor(LocalSlope, SoilMap[coursei][coursej].Soil, 
							     (*FineMap[y][x]).sediment, 
							     VegMap[coursei][coursej].Veg, SedType, VType,
							     (*FineMap[y][x]).SatThickness, SType,
							     SnowMap[coursei][coursej].Swq, 
							     SnowMap[coursei][coursej].Depth, iter);
			    
			    /* check if fine pixel fails */
			    if (factor_safety < FS_CRITERIA && factor_safety > 0) {
			      numpixels += 1;
			      failure[y][x] = 1;
			      
			      /* Update sediment depth. All sediment leaves failed fine pixel */
			      SedToDownslope = (*FineMap[y][x]).sediment;
			      (*FineMap[y][x]).sediment = 0.0;
			      
			      // Pass sediment down to next pixel
			      SedFromUpslope = SedToDownslope;
			      
			    }
			    else {
			      /* Update sediment depth. */
			      // Remove the sediment we added for the slope calculation
			      // and instead prepare to distribute this sediment along runout zone
			      (*FineMap[y][x]).sediment -= SedFromUpslope;
			      
			    }
			  } /* end  if(LocalSlope >= 0) { */
			  else {
			    /* Update sediment depth. */
			    // Remove the sediment we added for the slope calculation
			    // and instead prepare to distribute this sediment along runout zone
			    //   (*FineMap[y][x]).sediment -= SedFromUpslope;
			    /* If it reaches here, a sink exists. A sink can 
			       not fail or run out, so move to the next pixel. */
			    checksink++;
			    
			  }
			  
			}
			
		      }  /* End of while loop. */
		      
		      if (checksink > 0) continue;
		      
		      /* Failure has stopped, now calculate runout distance and 
			 redistribute sediment. */
		      
		      // y and x are now the coords of the first pixel of the runout
		      // (downslope neighbor of final pixel of the failure);
		      // this is the pixel that caused the last loop to exit,
		      // whether due to being a sink, not failing,
		      // being in a coarse pixel containing a stream,
		      // or being outside the basin
		      
		      // If current cell is outside the basin,
		      // stop processing this runout and go to next failure candidate
		      if (!INBASIN(TopoMap[coursei][coursej].Mask)) {
			continue;
		      }
		      
		      // TotalVolume = depth (not volume) being redistributed
		      TotalVolume = SedFromUpslope;
		      
		      cells = 1;
		      
		      /* queue begins with initial unfailed pixel. */
		      enqueue(&head, &tail, y, x); 
		      
		      while(LocalSlope > 4. && !channel_grid_has_channel(ChannelData->stream_map, coursej, coursei)
			    && INBASIN(TopoMap[coursei][coursej].Mask)) {
			/* Redistribution stops if last pixel was a channel
			   or was outside the basin. */
			/* Update counters. */
			prevy = y;
			prevx = x;
			y = nexty;
			x = nextx;
			coursei = floor(y*Map->DMASS/Map->DY);
			coursej = floor(x*Map->DMASS/Map->DX);
			
			if (INBASIN(TopoMap[coursei][coursej].Mask)) {
			  
			  LocalSlope = ElevationSlope(Map, TopoMap, FineMap, y, x, &nexty,
						      &nextx, prevy, prevx,
						      &SlopeAspect);
			  enqueue(&head, &tail, y, x);
			  cells++;
			}
			else {
			  printf("WARNING: attempt to propagate runout to grid cell outside the basin: y %d x %d\n",y,x);
			  printf("Final grid cell of runout will be: y %d x %d\n",prevy,prevx);
			}
		      }
		      prevy = y;
		      prevx = x;
		      
		      for(count=0; count < cells; count++) {
			dequeue(&head, &tail, &y, &x);
			coursei = floor(y*Map->DMASS/Map->DY);
			coursej = floor(x*Map->DMASS/Map->DX);
			
			
			// If this node has a channel, then this MUST be the end of the queue
			if(channel_grid_has_channel(ChannelData->stream_map, coursej, coursei)) {
			  /* TotalVolume at this point is a depth in m over one fine
			     map grid cell - convert to m3 */
			  SedimentToChannel = TotalVolume*(Map->DMASS*Map->DMASS)/(float) cells;
			}
			else {
			  /* Redistribute sediment equally among all hillslope cells. */
			  (*FineMap[y][x]).sediment += TotalVolume/cells;
			}
		      }
		      
		      if(SedimentToChannel > 0.0) {
			if(SlopeAspect < 0.) {
			  printf("Invalid aspect (%3.1f) in cell y= %d x= %d\n",
				  SlopeAspect,y,x);
			  exit(0);
			}
			else {
			  
			  // Add Current value of SedimentToChannel to running total for this FineMap cell
			  // (allowing for more than one debris flow to end at the same channel)
			  (*FineMap[y][x]).SedimentToChannel += SedimentToChannel;
			  
			  // Now route SedimentToChannel through stream network
			  RouteDebrisFlow(&SedimentToChannel, coursei, coursej, SlopeAspect, ChannelData, Map); 

			}
		      }
		     
		    } /* End of this failure/runout event */
		    
		  }		      
		}
	      
	      }   /* End of fine mask check. */
	    }  /* End of jj loop. */
	  }
	}
	
	
      }       
    }    /* End of course resolution loop. */
    
    /* Record failures and Reset failure map for new iteration. */
    for(i=0; i<Map->NY; i++) {
      for(j=0; j<Map->NX; j++) {
	if (INBASIN(TopoMap[i][j].Mask)) {		
	  
	  for(ii=0; ii<Map->DY/Map->DMASS; ii++) {
	    for(jj=0; jj<Map->DX/Map->DMASS; jj++) {
	      y = i*Map->DY/Map->DMASS + ii; 
	      x = j*Map->DX/Map->DMASS + jj;
	      
	      (*FineMap[y][x]).Probability += (float) failure[y][x];
	  
	      /* Record cumulative sediment volume. */
	      SedThickness[y][x] += (*FineMap[y][x]).sediment;
	  
	      /* Reset sediment thickness for each iteration; otherwise there is 
	         a decreasing probability of failure for subsequent iterations. */
	      /* If not in stochastic mode, then allow a history of past failures
	         and do not reset sediment depth */
	      if(massitertemp>1) {
	        (*FineMap[y][x]).sediment = InitialSediment[y][x];
	        failure[y][x] = 0;
	      }
	    }
	  }
	}
      }
    }
/*  printf("Sediment Mass is "); */
/*  count_sediment_mass(ChannelData->streams, InitialSegmentSediment); */
    

    /* Record cumulative stream sediment volumes. */
    initialize_sediment_array(ChannelData->streams, SegmentSediment,
			      SegmentSedimentm);

    /* Reset channel sediment volume for each iteration. */
    update_sediment_array(ChannelData->streams, InitialSegmentSediment, InitialSegmentSedimentm);
    
    update_sediment_mass(ChannelData->streams, SegmentSedimentm, 
			 massitertemp);

  }    /* End iteration loop */

  // Normalize mass wasting vars by number of iterations
  numfailedpixels = 0;
  numlikelyfailedpixels = 0;
  for(i=0; i<Map->NY; i++) {
    for(j=0; j<Map->NX; j++) {
      if (INBASIN(TopoMap[i][j].Mask)) {		
	  
	for(ii=0; ii<Map->DY/Map->DMASS; ii++) {
	  for(jj=0; jj<Map->DX/Map->DMASS; jj++) {
	    y = i*Map->DY/Map->DMASS + ii; 
	    x = j*Map->DX/Map->DMASS + jj;
	      
	    (*FineMap[y][x]).Probability /= (float)massitertemp;
	    (*FineMap[y][x]).sediment = SedThickness[y][x]/(float)massitertemp;
	    (*FineMap[y][x]).SedimentToChannel /= (float)massitertemp;

	    if ((*FineMap[y][x]).sediment > InitialSediment[y][x]) {
	      (*FineMap[y][x]).MassDeposition = ((*FineMap[y][x]).sediment - InitialSediment[y][x])*(Map->DMASS*Map->DMASS);
	      (*FineMap[y][x]).MassWasting = 0.0;
	    }
	    else if ((*FineMap[y][x]).sediment < InitialSediment[y][x]) {
	      (*FineMap[y][x]).MassDeposition = 0.0;
	      (*FineMap[y][x]).MassWasting = (InitialSediment[y][x] - (*FineMap[y][x]).sediment)*(Map->DMASS*Map->DMASS);
	    }
	    if((*FineMap[y][x]).Probability > 0)
	      numfailedpixels +=1;
	  
	    if((*FineMap[y][x]).Probability > failure_threshold)
	      numlikelyfailedpixels +=1;
	  
	    (*FineMap[y][x]).DeltaDepth = (*FineMap[y][x]).sediment - 
	      SoilMap[i][j].Depth;

	  }
	}
      }
    }
  }

  // Compute average number of failures
  avgnumfailures = numfailures/(float)massitertemp;

  // Compute average number of pixels per failure
  if (numfailures > 0) {
    avgpixperfailure = (float)numfailedpixels/(float)numfailures;
  }
  else {
    avgpixperfailure = 0.0;
  }

  // Average sediment delivery to each stream segment
  for(i=1; i<MaxStreamID+1; i++) {
    SegmentSediment[i] /= (float)massitertemp;
    if(SegmentSediment[i] < 0.0) SegmentSediment[i]=0.0;
  }
  update_sediment_array(ChannelData->streams, SegmentSediment, SegmentSedimentm);
  /* Take new sediment inflow and distribute it by representative diameters*/
  /* and convert to mass */
  sed_vol_to_distrib_mass(ChannelData->streams, SegmentSediment);


  /*************************************************************************/
  /* Create failure summary file, in the specified output directory:       */
  /* failure_summary.txt - for each date that the mwm algorithm is run:    */
  /*                       ave. no. of failures (strip of pixels           */
  /*                            originating from a failed pixel)           */
  /*                       ave. no. of pixles per failure                  */
  /*                       total number of failed pixels with probability  */
  /*                            of failure > failure_threshold             */ 
  /*************************************************************************/

  sprintf(sumoutfile, "%sfailure_summary.txt", DumpPath);

  if((fs=fopen(sumoutfile,"a")) == NULL)
    {
      printf("Cannot open factor of safety summary output file.\n");
      exit(0);
    }

  SPrintDate(&(Time->Current), buffer);
  fprintf(fs, "%-20s %.4f %.4f %7d\n", buffer, avgnumfailures, avgpixperfailure, numlikelyfailedpixels); 
  printf("%.4f failures; %.4f pixels per failure; %d pixels have failure likelihood > %.2f\n",
    avgnumfailures, avgpixperfailure, numlikelyfailedpixels, failure_threshold);
  fclose(fs);

  for(i=0; i<Map->NYfine; i++) { 
    free(failure[i]);
    free(SedThickness[i]);
    free(InitialSediment[i]);
  }
  for(i=1; i<MaxStreamID+1; i++) {
    free(SegmentSedimentm[i]);
  }
  free(failure);
  free(SedThickness);
  free(InitialSediment);
  free(SegmentSediment);
  free(SegmentSedimentm);
  free(InitialSegmentSediment);
  free(InitialSegmentSedimentm);
}
Exemple #12
0
/*****************************************************************************
  InitFineMaps()
*****************************************************************************/
void InitFineMaps(LISTPTR Input, OPTIONSTRUCT *Options, MAPSIZE *Map, 
		     LAYER *Soil, TOPOPIX ***TopoMap, SOILPIX ***SoilMap, 
		     FINEPIX ****FineMap)
{
 
  const char *Routine = "InitFineMaps";
  char VarName[BUFSIZE+1];	/* Variable name */
  int i, k, x, y;		/* Counters */
  int ii, jj, xx, yy, xy;            /* Counters */
  int NumberType;		/* Number type of data set */
  float *Elev;                   /* Surface elevation */
  int MASKFLAG;
  unsigned char *Mask = NULL;          /* Fine resolution mask */

  STRINIENTRY StrEnv[] = {
    {"FINEDEM", "DEM FILE"        , ""  , ""},
    {"FINEDEM", "MASK FILE"        , ""  , ""},
    {NULL       , NULL            , ""  , NULL}
  };
  
  printf("Initializing mass wasting resolution maps\n");
  
  /* Process the [FINEDEM] section in the input file */
  
  /* Read the key-entry pair for the dem from the input file */
  GetInitString(StrEnv[0].SectionName, StrEnv[0].KeyName, StrEnv[0].Default,
		StrEnv[0].VarStr, (unsigned long) BUFSIZE, Input);
  if (IsEmptyStr(StrEnv[0].VarStr))
    ReportError(StrEnv[0].KeyName, 51);
  
  /* Read the elevation dataset */ 
  
  GetVarName(001, 0, VarName);
  GetVarNumberType(001, &NumberType);
  if (!(Elev = (float *) calloc(Map->NXfine * Map->NYfine, 
				SizeOfNumberType(NumberType)))) 
    ReportError((char *) Routine, 1);
  Read2DMatrix(StrEnv[demfile].VarStr, Elev, NumberType, Map->NYfine, Map->NXfine, 0,
	       VarName);
  
  /* Read the key-entry pair for the mask from the input file */
  GetInitString(StrEnv[1].SectionName, StrEnv[1].KeyName, StrEnv[1].Default,
		StrEnv[1].VarStr, (unsigned long) BUFSIZE, Input);
  if (IsEmptyStr(StrEnv[1].VarStr)) {
    printf("\nWARNING: Fine resolution mask not provided, will be set equal to \n");
    printf("coarse resolution mask.\n\n");
    MASKFLAG = FALSE;
  }
  else {
    printf("fine mask = %s\n",StrEnv[1].VarStr);
    /* Read the mask */
    GetVarName(002, 0, VarName);
    GetVarNumberType(002, &NumberType);
    if (!(Mask = (unsigned char *) calloc(Map->NXfine * Map->NYfine,
					  SizeOfNumberType(NumberType))))
      ReportError((char *) Routine, 1);
    Read2DMatrix(StrEnv[maskfile].VarStr, Mask, NumberType, Map->NYfine, Map->NXfine, 0,
		 VarName);
    MASKFLAG = TRUE;
    
  }
  
  /* Assign the attributes to the correct map pixel */
  if (!(*FineMap = (FINEPIX ***) calloc(Map->NYfine, sizeof(FINEPIX **))))
    ReportError((char *) Routine, 1);
  for (y = 0; y < Map->NYfine; y++) {
    if (!((*FineMap)[y] = (FINEPIX **) calloc(Map->NXfine, sizeof(FINEPIX *))))
      ReportError((char *) Routine, 1);
  }
  // Only allocate a FINEPIX structure for a fine grid cell if that grid cell
  // is in the coarse grid mask
  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) { 
      if (INBASIN((*TopoMap)[y][x].Mask)) {
	for (ii=0; ii< Map->DY/Map->DMASS; ii++) { 
 	  for (jj=0; jj< Map->DX/Map->DMASS; jj++) { 
	    yy = (int) y*Map->DY/Map->DMASS + ii; 
 	    xx = (int) x*Map->DX/Map->DMASS + jj; 
            if (!((*FineMap)[yy][xx] = (FINEPIX *) malloc(sizeof(FINEPIX)))) {
	      printf("error allocating FineMap[%d][%d]\n",yy,xx);
              ReportError((char *) Routine, 1);
            }
	  }
	}
      }
    }
  }
  
  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) { 
      if (INBASIN((*TopoMap)[y][x].Mask)) {
	for (ii=0; ii< Map->DY/Map->DMASS; ii++) { 
 	  for (jj=0; jj< Map->DX/Map->DMASS; jj++) { 
	    yy = (int) y*Map->DY/Map->DMASS + ii; 
 	    xx = (int) x*Map->DX/Map->DMASS + jj; 
	    xy = (int) yy*Map->NXfine + xx;
	    (*(*FineMap)[yy][xx]).Dem  = Elev[xy]; 
	  }
	}
      }
    }
  }
  
  free(Elev);
  
  if(MASKFLAG == TRUE){
    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) { 
	if (INBASIN((*TopoMap)[y][x].Mask)) {
	  for (ii=0; ii< Map->DY/Map->DMASS; ii++) { 
	    for (jj=0; jj< Map->DX/Map->DMASS; jj++) { 
	      yy = (int) y*Map->DY/Map->DMASS + ii; 
	      xx = (int) x*Map->DX/Map->DMASS + jj; 
	      xy = (int) yy*Map->NXfine + xx;
	      (*(*FineMap)[yy][xx]).Mask  = Mask[xy]; 
	    }
	  }
	}
      }
    }
  }

 free(Mask);  
  /* Create fine resolution mask, sediment and bedrock maps.
   Initialize other variables*/
  
  for (y = 0, i = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++, i++) {
      for (ii=0; ii< Map->DY/Map->DMASS; ii++) {
	for (jj=0; jj< Map->DX/Map->DMASS; jj++) {
	  if (INBASIN((*TopoMap)[y][x].Mask)) {
	    yy = (int) y*Map->DY/Map->DMASS + ii;
	    xx = (int) x*Map->DX/Map->DMASS + jj;
	    if(MASKFLAG==FALSE)
	      (*(*FineMap)[yy][xx]).Mask = (*TopoMap)[y][x].Mask;
	    /*   else { */
	      // Don't allow fine mask to extend beyond edges of coarse mask.
	      // This means that failures may still try to leave the basin if the coarse 
	      // mask isn't wide enough because some of the drainage area may be cropped.
	/*       if (!INBASIN((*TopoMap)[y][x].Mask)) */
/* 		(*(*FineMap)[yy][xx]).Mask = (*TopoMap)[y][x].Mask; */
	 /*    } */
	    (*(*FineMap)[yy][xx]).bedrock = (*(*FineMap)[yy][xx]).Dem - (*SoilMap)[y][x].Depth;
	    (*(*FineMap)[yy][xx]).sediment = (*SoilMap)[y][x].Depth;
	    (*(*FineMap)[yy][xx]).SatThickness = 0.;
	    (*(*FineMap)[yy][xx]).DeltaDepth = 0.;
	    (*(*FineMap)[yy][xx]).Probability = 0.;
	    (*(*FineMap)[yy][xx]).MassWasting = 0.;
	    (*(*FineMap)[yy][xx]).MassDeposition = 0.;
	    (*(*FineMap)[yy][xx]).SedimentToChannel = 0.;
	    (*(*FineMap)[yy][xx]).TopoIndex = 0.;
	  }
	}
      }
    }
  }
  
  Map->NumFineIn = (Map->DX/Map->DMASS) * (Map->DY/Map->DMASS);

 /* NumCellsfine is used in CalcTopoIndex.  The topo index is calculated for every 
     fine cell within the boundary of the coarse mask, so this number may exceed the 
     number of pixels within the fine resolution mask.  */

  Map->NumCellsfine = Map->NumCells*Map->NumFineIn;

  printf("Basin has %d active pixels in the mass wasting resolution map\n",
	 Map->NumCellsfine);
  
  /* Calculate the topographic index */
  CalcTopoIndex(Map, *FineMap, *TopoMap);
  
  for (y = 0; y < Map->NY; y++) {
    for (x  = 0; x < Map->NX; x++) {
      if (INBASIN((*TopoMap)[y][x].Mask)) {
	if (!((*TopoMap)[y][x].OrderedTopoIndex = (ITEM *) calloc(Map->NumFineIn, sizeof(ITEM))))
	  ReportError((char *) Routine, 1);
      }
    }
  }
  
  for (y = 0; y < Map->NY; y++) {
    for (x  = 0; x < Map->NX; x++) {
      if (INBASIN((*TopoMap)[y][x].Mask)) {
	k = 0;
	for(ii=0; ii< Map->DY/Map->DMASS; ii++) {
	  for(jj=0; jj< Map->DX/Map->DMASS; jj++) {
	    yy = (int) y*Map->DY/Map->DMASS + ii;
	    xx = (int) x*Map->DX/Map->DMASS + jj;
	    (*TopoMap)[y][x].OrderedTopoIndex[k].Rank = (*(*FineMap)[yy][xx]).TopoIndex;
	    (*TopoMap)[y][x].OrderedTopoIndex[k].y = yy;
	    (*TopoMap)[y][x].OrderedTopoIndex[k].x = xx;
	    k++;
	  }
	}
       	quick((*TopoMap)[y][x] .OrderedTopoIndex, Map->NumFineIn);
      }
    }
  }
}
Exemple #13
0
int main(int argc, char **argv)
{
  float *Hydrograph = NULL;
  float ***MM5Input = NULL;
  float **PrecipLapseMap = NULL;
  float **PrismMap = NULL;
  unsigned char ***ShadowMap = NULL;
  float **SkyViewMap = NULL;
  float ***WindModel = NULL;
  int MaxStreamID, MaxRoadID;
  float SedDiams[NSEDSIZES];     /* Sediment particle diameters (mm) */
  clock_t start, finish1;
  double runtime = 0.0;
  int t = 0;
  float roadarea;
  time_t tloc;
  int flag;
  int i;
  int j;
  int x;						/* row counter */
  int y;						/* column counter */
  int shade_offset;				/* a fast way of handling arraay position given the number of mm5 input options */
  int NStats;					/* Number of meteorological stations */
  uchar ***MetWeights = NULL;	/* 3D array with weights for interpolating meteorological variables between the stations */

  int NGraphics;				/* number of graphics for X11 */
  int *which_graphics;			/* which graphics for X11 */
  char buffer[32];

  AGGREGATED Total = {			/* Total or average value of a  variable over the entire basin */
    {0.0, NULL, NULL, NULL, NULL, 0.0},												/* EVAPPIX */
    {0.0, 0.0, 0.0, 0.0, 0.0, NULL, NULL, 0.0, 0, 0.0},								/* PRECIPPIX */
    {{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}, 0.0, 0.0, 0.0},							/* PIXRAD */
    {0.0, 0.0},																		/* RADCLASSPIX */
    {0.0, 0.0, 0, NULL, NULL, 0.0, 0, 0.0, 0.0, 0.0, 0.0, NULL, 
	NULL, NULL, NULL, NULL, NULL, 0.0},												/* ROADSTRUCT*/
    {0, 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},		/* SNOWPIX */
    {0, 0.0, NULL, NULL, NULL, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},			/*SOILPIX */
    { 0.0, 0.0, 0.0, 0.0, 0.0},														/*SEDPIX */
    { 0.0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},							/*FINEPIX */
    0.0, 0.0, 0.0, 0.0, 0.0, 0l, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
  };
  CHANNEL ChannelData = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL};
  DUMPSTRUCT Dump;
  EVAPPIX **EvapMap = NULL;
  INPUTFILES InFiles;
  LAYER Soil;
  LAYER Veg;
  LISTPTR Input = NULL;			/* Linked list with input strings */
  MAPSIZE Map;					/* Size and location of model area */
  MAPSIZE Radar;				/* Size and location of area covered by precipitation radar */
  MAPSIZE MM5Map;				/* Size and location of area covered by MM5 input files */
  METLOCATION *Stat = NULL;
  OPTIONSTRUCT Options;			/* Structure with information which program options to follow */
  PIXMET LocalMet;				/* Meteorological conditions for current pixel */
  FINEPIX ***FineMap	= NULL;
  PRECIPPIX **PrecipMap = NULL;
  RADARPIX **RadarMap	= NULL;
  RADCLASSPIX **RadMap	= NULL;
  PIXRAD **RadiationMap = NULL;
  ROADSTRUCT **Network	= NULL;	/* 2D Array with channel information for each pixel */
  SNOWPIX **SnowMap		= NULL;
  MET_MAP_PIX **MetMap	= NULL;
  SNOWTABLE *SnowAlbedo = NULL;
  SOILPIX **SoilMap		= NULL;
  SEDPIX **SedMap		= NULL;
  SOILTABLE *SType	    = NULL;
  SEDTABLE *SedType		= NULL;
  SOLARGEOMETRY SolarGeo;		/* Geometry of Sun-Earth system (needed for INLINE radiation calculations */
  TIMESTRUCT Time;
  TOPOPIX **TopoMap = NULL;
  UNITHYDR **UnitHydrograph = NULL;
  UNITHYDRINFO HydrographInfo;	/* Information about unit hydrograph */
  VEGPIX **VegMap = NULL;
  VEGTABLE *VType = NULL;
  WATERBALANCE Mass =			/* parameter for mass balance calculations */
    { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,  
      0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };

/*****************************************************************************
  Initialization Procedures 
*****************************************************************************/
  if (argc != 2) {
    fprintf(stderr, "\nUsage: %s inputfile\n\n", argv[0]);
    fprintf(stderr, "DHSVM uses two output streams: \n");
    fprintf(stderr, "Standard Out, for the majority of output \n");
    fprintf(stderr, "Standard Error, for the final mass balance \n");
    fprintf(stderr, "\nTo pipe output correctly to files: \n");
    fprintf(stderr, "(cmd > f1) >& f2 \n");
    fprintf(stderr, "where f1 is stdout_file and f2 is stderror_file\n");
    exit(EXIT_FAILURE);
  }

  sprintf(commandline, "%s %s", argv[0], argv[1]);
  printf("%s \n", commandline);
  fprintf(stderr, "%s \n", commandline);
  strcpy(InFiles.Const, argv[1]);

  printf("\nRunning DHSVM %s\n", version);
  printf("\nSTARTING INITIALIZATION PROCEDURES\n\n");

  /* Start recording time */
  start = clock();

  ReadInitFile(InFiles.Const, &Input);
  InitConstants(Input, &Options, &Map, &SolarGeo, &Time);

  InitFileIO(Options.FileFormat);
  InitTables(Time.NDaySteps, Input, &Options, &SType, &Soil, &VType, &Veg,
	     &SnowAlbedo);

  InitTerrainMaps(Input, &Options, &Map, &Soil, &TopoMap, &SoilMap, &VegMap);

  CheckOut(Options.CanopyRadAtt, Veg, Soil, VType, SType, &Map, TopoMap, 
	   VegMap, SoilMap);

  if (Options.HasNetwork)
    InitChannel(Input, &Map, Time.Dt, &ChannelData, SoilMap, &MaxStreamID, &MaxRoadID, &Options);
  else if (Options.Extent != POINT)
    InitUnitHydrograph(Input, &Map, TopoMap, &UnitHydrograph,
		       &Hydrograph, &HydrographInfo);
 
  InitNetwork(Map.NY, Map.NX, Map.DX, Map.DY, TopoMap, SoilMap, 
	      VegMap, VType, &Network, &ChannelData, Veg, &Options);

  InitMetSources(Input, &Options, &Map, Soil.MaxLayers, &Time,
		 &InFiles, &NStats, &Stat, &Radar, &MM5Map);

  /* the following piece of code is for the UW PRISM project */
  /* for real-time verification of SWE at Snotel sites */
  /* Other users, set OPTION.SNOTEL to FALSE, or use TRUE with caution */

  if (Options.Snotel == TRUE && Options.Outside == FALSE) {
    printf
      ("Warning: All met stations locations are being set to the vegetation class GLACIER\n");
    printf
      ("Warning: This requires that you have such a vegetation class in your vegetation table\n");
    printf("To disable this feature set Snotel OPTION to FALSE\n");
    for (i = 0; i < NStats; i++) {
      printf("veg type for station %d is %d ", i,
	     VegMap[Stat[i].Loc.N][Stat[i].Loc.E].Veg);
      for (j = 0; j < Veg.NTypes; j++) {
	    if (VType[j].Index == GLACIER) {
	      VegMap[Stat[i].Loc.N][Stat[i].Loc.E].Veg = j;
		  break;
		}
      }
      if (j == Veg.NTypes) {	/* glacier class not found */
	    ReportError("MainDHSVM", 62);
	  }
      printf("setting to glacier type (assumed bare class): %d\n", j);
    }
  }

  InitMetMaps(Time.NDaySteps, &Map, &Radar, &Options, InFiles.WindMapPath,
	      InFiles.PrecipLapseFile, &PrecipLapseMap, &PrismMap,
	      &ShadowMap, &SkyViewMap, &EvapMap, &PrecipMap,
	      &RadarMap, &RadMap, SoilMap, &Soil, VegMap, &Veg, TopoMap,
	      &MM5Input, &WindModel);

  InitInterpolationWeights(&Map, &Options, TopoMap, &MetWeights, Stat, NStats);

  InitDump(Input, &Options, &Map, Soil.MaxLayers, Veg.MaxLayers, Time.Dt,
	   TopoMap, &Dump, &NGraphics, &which_graphics);

  if (Options.HasNetwork == TRUE) {
    InitChannelDump(&Options, &ChannelData, Dump.Path);
    ReadChannelState(Dump.InitStatePath, &(Time.Start), ChannelData.streams);
  }

  InitSnowMap(&Map, &SnowMap);
  InitAggregated(Veg.MaxLayers, Soil.MaxLayers, &Total);

  InitModelState(&(Time.Start), &Map, &Options, PrecipMap, SnowMap, SoilMap,
		 Soil, SType, VegMap, Veg, VType, Dump.InitStatePath,
		 SnowAlbedo, TopoMap, Network, &HydrographInfo, Hydrograph);

  InitNewMonth(&Time, &Options, &Map, TopoMap, PrismMap, ShadowMap,
	       RadMap, &InFiles, Veg.NTypes, VType, NStats, Stat, 
	       Dump.InitStatePath);

  InitNewDay(Time.Current.JDay, &SolarGeo);

  if (NGraphics > 0) {
    printf("Initialzing X11 display and graphics \n");
    InitXGraphics(argc, argv, Map.NY, Map.NX, NGraphics, &MetMap);
  }

  shade_offset = FALSE;
  if (Options.Shading == TRUE)
    shade_offset = TRUE;

  /* Done with initialization, delete the list with input strings */
  DeleteList(Input);

  /*****************************************************************************
  Sediment Initialization Procedures 
  *****************************************************************************/
  if(Options.Sediment) {
     time (&tloc);
     srand (tloc);
  /* Randomize Random Generator */
 
  /* Commenting the line above and uncommenting the line below 
     allows for the comparison of scenarios. */
  /*  srand48 (0);  */
    printf("\nSTARTING SEDIMENT INITIALIZATION PROCEDURES\n\n");

    ReadInitFile(Options.SedFile, &Input);

    InitParameters(Input, &Options, &Map, &Network, &ChannelData, TopoMap,
		   &Time, SedDiams);

    InitSedimentTables(Time.NDaySteps, Input, &SedType, &SType, &VType, &Soil, &Veg);

    InitFineMaps(Input, &Options, &Map, &Soil, &TopoMap, &SoilMap, 
		  &FineMap);

    if (Options.HasNetwork){ 
      printf("Initializing channel sediment\n\n");
      InitChannelSedimentDump(&ChannelData, Dump.Path, Options.ChannelRouting); 
      InitChannelSediment(ChannelData.streams, &Total);
      InitChannelSediment(ChannelData.roads, &Total);
    }

    InitSedMap( &Map, &SedMap);

    /* Done with initialization, delete the list with input strings */
    DeleteList(Input);
  }

  /* setup for mass balance calculations */
  Aggregate(&Map, &Options, TopoMap, &Soil, &Veg, VegMap, EvapMap, PrecipMap,
	      RadMap, SnowMap, SoilMap, &Total, VType, Network, SedMap, FineMap,
	      &ChannelData, &roadarea);

  Mass.StartWaterStorage =
    Total.Soil.IExcess + Total.CanopyWater + Total.SoilWater + Total.Snow.Swq +
    Total.Soil.SatFlow;
  Mass.OldWaterStorage = Mass.StartWaterStorage;

  if (Options.Sediment) {
    Mass.StartChannelSedimentStorage = Total.ChannelSedimentStorage;
    Mass.LastChannelSedimentStorage = Mass.StartChannelSedimentStorage;
  }

  /* computes the number of grid cell contributing to one segment */
  if (Options.StreamTemp) 
	Init_segment_ncell(TopoMap, ChannelData.stream_map, Map.NY, Map.NX, ChannelData.streams);

/*****************************************************************************
  Perform Calculations 
*****************************************************************************/
  while (Before(&(Time.Current), &(Time.End)) ||
	 IsEqualTime(&(Time.Current), &(Time.End))) {
    ResetAggregate(&Soil, &Veg, &Total, &Options);

    if (IsNewMonth(&(Time.Current), Time.Dt))
      InitNewMonth(&Time, &Options, &Map, TopoMap, PrismMap, ShadowMap,
		   RadMap, &InFiles, Veg.NTypes, VType, NStats, Stat, 
		   Dump.InitStatePath);

    if (IsNewDay(Time.DayStep)) {
      InitNewDay(Time.Current.JDay, &SolarGeo);
      PrintDate(&(Time.Current), stdout);
      printf("\n");
    }

    /* determine surface erosion and routing scheme */
    SedimentFlag(&Options, &Time); 

    InitNewStep(&InFiles, &Map, &Time, Soil.MaxLayers, &Options, NStats, Stat,
		InFiles.RadarFile, &Radar, RadarMap, &SolarGeo, TopoMap, RadMap,
        SoilMap, MM5Input, WindModel, &MM5Map);

    /* initialize channel/road networks for time step */
    if (Options.HasNetwork) {
      channel_step_initialize_network(ChannelData.streams);
      channel_step_initialize_network(ChannelData.roads);
    }

    for (y = 0; y < Map.NY; y++) {
      for (x = 0; x < Map.NX; x++) {
	    if (INBASIN(TopoMap[y][x].Mask)) {
		  if (Options.Shading)
	        LocalMet =
	        MakeLocalMetData(y, x, &Map, Time.DayStep, &Options, NStats,
			       Stat, MetWeights[y][x], TopoMap[y][x].Dem,
			       &(RadMap[y][x]), &(PrecipMap[y][x]), &Radar,
			       RadarMap, PrismMap, &(SnowMap[y][x]),
			       SnowAlbedo, MM5Input, WindModel, PrecipLapseMap,
			       &MetMap, NGraphics, Time.Current.Month,
			       SkyViewMap[y][x], ShadowMap[Time.DayStep][y][x],
			       SolarGeo.SunMax, SolarGeo.SineSolarAltitude);
		  else
	        LocalMet =
	        MakeLocalMetData(y, x, &Map, Time.DayStep, &Options, NStats,
			       Stat, MetWeights[y][x], TopoMap[y][x].Dem,
			       &(RadMap[y][x]), &(PrecipMap[y][x]), &Radar,
			       RadarMap, PrismMap, &(SnowMap[y][x]),
			       SnowAlbedo, MM5Input, WindModel, PrecipLapseMap,
			       &MetMap, NGraphics, Time.Current.Month, 0.0,
			       0.0, SolarGeo.SunMax,
			       SolarGeo.SineSolarAltitude);
		  
		  for (i = 0; i < Soil.MaxLayers; i++) {
	        if (Options.HeatFlux == TRUE) {
	          if (Options.MM5 == TRUE)
		        SoilMap[y][x].Temp[i] =
				MM5Input[shade_offset + i + N_MM5_MAPS][y][x];
			  else
		        SoilMap[y][x].Temp[i] = Stat[0].Data.Tsoil[i];
			}
	        else
	          SoilMap[y][x].Temp[i] = LocalMet.Tair;
		  }
		  
		  MassEnergyBalance(&Options, y, x, SolarGeo.SineSolarAltitude, Map.DX, Map.DY, 
			    Time.Dt, Options.HeatFlux, Options.CanopyRadAtt, Options.RoadRouting, 
			    Options.Infiltration, Veg.MaxLayers, &LocalMet, &(Network[y][x]), 
			    &(PrecipMap[y][x]), &(VType[VegMap[y][x].Veg-1]), &(VegMap[y][x]),
			    &(SType[SoilMap[y][x].Soil-1]), &(SoilMap[y][x]), &(SnowMap[y][x]), 
				&(EvapMap[y][x]), &(Total.Rad), &ChannelData, SkyViewMap);
		 
		  PrecipMap[y][x].SumPrecip += PrecipMap[y][x].Precip;
		}
	  }
    }

	/* Average all RBM inputs over each segment */
	if (Options.StreamTemp) {
	  channel_grid_avg(ChannelData.streams);
	}

 #ifndef SNOW_ONLY

    /* set sediment inflows to zero - they are incremented elsewhere */
    if ((Options.HasNetwork) && (Options.Sediment)){ 
      InitChannelSedInflow(ChannelData.streams);
      InitChannelSedInflow(ChannelData.roads);
	}
    
    RouteSubSurface(Time.Dt, &Map, TopoMap, VType, VegMap, Network,
		    SType, SoilMap, &ChannelData, &Time, &Options, Dump.Path,
		    SedMap, FineMap, SedType, MaxStreamID, SnowMap);

    if (Options.HasNetwork)
      RouteChannel(&ChannelData, &Time, &Map, TopoMap, SoilMap, &Total, 
		   &Options, Network, SType, PrecipMap, SedMap,
		   LocalMet.Tair, LocalMet.Rh, SedDiams);

    /* Sediment Routing in Channel and output to sediment files */
    if ((Options.HasNetwork) && (Options.Sediment)){
      SPrintDate(&(Time.Current), buffer);
      flag = IsEqualTime(&(Time.Current), &(Time.Start));

      if (Options.ChannelRouting){
	    if (ChannelData.roads != NULL) {
	      RouteChannelSediment(ChannelData.roads, Time, &Dump, &Total, SedDiams);
	      channel_save_sed_outflow_text(buffer, ChannelData.roads,
					ChannelData.sedroadout,
					ChannelData.sedroadflowout, flag);
		  RouteCulvertSediment(&ChannelData, &Map, TopoMap, SedMap, 
			       &Total, SedDiams);
		}
	    RouteChannelSediment(ChannelData.streams, Time, &Dump, &Total, SedDiams);
 	    channel_save_sed_outflow_text(buffer, ChannelData.streams,
				      ChannelData.sedstreamout,
				      ChannelData.sedstreamflowout, flag);
	  }
      else {
	    if (ChannelData.roads != NULL) {
			channel_save_sed_inflow_text(buffer, ChannelData.roads,
			ChannelData.sedroadinflow, SedDiams,flag);
		}
	    channel_save_sed_inflow_text(buffer, ChannelData.streams,
			ChannelData.sedstreaminflow, SedDiams,flag);
      }
      SaveChannelSedInflow(ChannelData.roads, &Total);
      SaveChannelSedInflow(ChannelData.streams, &Total);
    }
    
    if (Options.Extent == BASIN)
      RouteSurface(&Map, &Time, TopoMap, SoilMap, &Options,
		   UnitHydrograph, &HydrographInfo, Hydrograph,
		   &Dump, VegMap, VType, SType, &ChannelData, SedMap,
		   PrecipMap, SedType, LocalMet.Tair, LocalMet.Rh, SedDiams);

#endif

    if (NGraphics > 0)
      draw(&(Time.Current), IsEqualTime(&(Time.Current), &(Time.Start)),
	   Time.DayStep, &Map, NGraphics, which_graphics, VType,
	   SType, SnowMap, SoilMap, SedMap, FineMap, VegMap, TopoMap, PrecipMap,
	   PrismMap, SkyViewMap, ShadowMap, EvapMap, RadMap, MetMap, Network,
	   &Options);
    
    Aggregate(&Map, &Options, TopoMap, &Soil, &Veg, VegMap, EvapMap, PrecipMap,
	      RadMap, SnowMap, SoilMap, &Total, VType, Network, SedMap, FineMap,
	      &ChannelData, &roadarea);
    
    MassBalance(&(Time.Current), &(Dump.Balance), &(Dump.SedBalance), &Total, 
		&Mass, &Options);

    ExecDump(&Map, &(Time.Current), &(Time.Start), &Options, &Dump, TopoMap,
	     EvapMap, RadiationMap, PrecipMap, RadMap, SnowMap, MetMap, VegMap, &Veg, 
		 SoilMap, SedMap, Network, &ChannelData, FineMap, &Soil, &Total, 
		 &HydrographInfo,Hydrograph);
	
    IncreaseTime(&Time);
	t += 1;
  }

  ExecDump(&Map, &(Time.Current), &(Time.Start), &Options, &Dump, TopoMap,
	   EvapMap, RadiationMap, PrecipMap, RadMap, SnowMap, MetMap, VegMap, &Veg, SoilMap,
	   SedMap, Network, &ChannelData, FineMap, &Soil, &Total, &HydrographInfo, Hydrograph);

  FinalMassBalance(&(Dump.FinalBalance), &Total, &Mass, &Options, roadarea);

  /*printf("\nSTARTING CLEANUP\n\n");
  cleanup(&Dump, &ChannelData, &Options);*/
  printf("\nEND OF MODEL RUN\n\n");

  /* record the run time at the end of each time loop */
  finish1 = clock ();
  runtime = (finish1-start)/CLOCKS_PER_SEC;
  printf("***********************************************************************************");
  printf("\nRuntime Summary:\n");
  printf("%6.2f hours elapsed for the simulation period of %d hours (%.1f days) \n", 
	  runtime/3600, t*Time.Dt/3600, (float)t*Time.Dt/3600/24);

  return EXIT_SUCCESS;
}
Exemple #14
0
/*****************************************************************************
  Function name: InitNetwork()

  Purpose      : Initialize road/channel work.  Memory is allocated, and the
                 necessary adjustments for the soil profile are calculated

  Comments     : 
*****************************************************************************/
void InitNetwork(int NY, int NX, float DX, float DY, TOPOPIX **TopoMap, 
		 SOILPIX **SoilMap, VEGPIX **VegMap, VEGTABLE *VType, 
		 ROADSTRUCT ***Network, CHANNEL *ChannelData, 
		 LAYER Veg, OPTIONSTRUCT *Options)
{
  const char *Routine = "InitNetwork";
  int i;			/* counter */
  int x;			/* column counter */
  int y;			/* row counter */
  int sx, sy;
  int minx, miny;
  int doimpervious;
  int numroads;          /* Counter of number of pixels
			    with a road and channel */
  int numroadschan;      /* Counter of number of pixels
			    with a road */
  FILE *inputfile;
  /* Allocate memory for network structure */

  if (!(*Network = (ROADSTRUCT **) calloc(NY, sizeof(ROADSTRUCT *))))
    ReportError((char *) Routine, 1);

  for (y = 0; y < NY; y++) {
    if (!((*Network)[y] = (ROADSTRUCT *) calloc(NX, sizeof(ROADSTRUCT))))
      ReportError((char *) Routine, 1);
  }

  for (y = 0; y < NY; y++) {
    for (x = 0; x < NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
		  if (!((*Network)[y][x].Adjust = 
			  (float *) calloc((VType[VegMap[y][x].Veg - 1].NSoilLayers + 1), sizeof(float))))
			  ReportError((char *) Routine, 1);
		  
		  if (!((*Network)[y][x].PercArea =
			  (float *) calloc((VType[VegMap[y][x].Veg - 1].NSoilLayers + 1), sizeof(float))))
			  ReportError((char *) Routine, 1);
      }
    }
  }

  numroadschan = 0;
  numroads = 0;

  /* If a road/channel Network is imposed on the area, read the Network
     information, and calculate the storage adjustment factors */
  if (Options->HasNetwork) {
    for (y = 0; y < NY; y++) {
      for (x = 0; x < NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {
	  ChannelCut(y, x, ChannelData, &((*Network)[y][x]));
	  AdjustStorage(VType[VegMap[y][x].Veg - 1].NSoilLayers,
			SoilMap[y][x].Depth,
			VType[VegMap[y][x].Veg - 1].RootDepth,
			(*Network)[y][x].Area, DX, DY, 
			(*Network)[y][x].BankHeight,
			(*Network)[y][x].PercArea,
			(*Network)[y][x].Adjust,
			&((*Network)[y][x].CutBankZone));
	  (*Network)[y][x].IExcess = 0.;
	  if (channel_grid_has_channel(ChannelData->road_map, x, y)) {
	    numroads++;
	    if (channel_grid_has_channel(ChannelData->stream_map, x, y)) {
	      numroadschan++;
	    }
	    (*Network)[y][x].fraction =
	      ChannelFraction(&(TopoMap[y][x]), ChannelData->road_map[x][y]);
	    (*Network)[y][x].MaxInfiltrationRate = 
	      MaxRoadInfiltration(ChannelData->road_map, x, y);
	    (*Network)[y][x].RoadClass = 
	      channel_grid_class(ChannelData->road_map, x, y);
	    (*Network)[y][x].FlowSlope = 
	      channel_grid_flowslope(ChannelData->road_map, x, y);
	    (*Network)[y][x].FlowLength = 
	      channel_grid_flowlength(ChannelData->road_map, x, y,(*Network)[y][x].FlowSlope);
	    (*Network)[y][x].RoadArea = channel_grid_cell_width(ChannelData->road_map, x, y) * channel_grid_cell_length(ChannelData->road_map, x, y);
	  }
	  else {
	    (*Network)[y][x].MaxInfiltrationRate = DHSVM_HUGE;
	    (*Network)[y][x].FlowSlope = 0.;
	    (*Network)[y][x].FlowLength = 0.;
	    (*Network)[y][x].RoadArea = 0.;
	    (*Network)[y][x].RoadClass = NULL;
	    (*Network)[y][x].IExcess = 0.;
	  }
	}
      }
    }
  }
  /* if no road/channel Network is imposed, set the adjustment factors to the
     values they have in the absence of an imposed network */
  else {
    for (y = 0; y < NY; y++) {
      for (x = 0; x < NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {
	  for (i = 0; i <= VType[VegMap[y][x].Veg - 1].NSoilLayers; i++) {
	    (*Network)[y][x].Adjust[i] = 1.0;
	    (*Network)[y][x].PercArea[i] = 1.0;
	    (*Network)[y][x].CutBankZone = NO_CUT;
	    (*Network)[y][x].MaxInfiltrationRate = 0.;
	  }
	  (*Network)[y][x].FlowSlope = 0.;
	  (*Network)[y][x].FlowLength = 0.;
	  (*Network)[y][x].RoadArea = 0.;
	  (*Network)[y][x].RoadClass = NULL;
	  (*Network)[y][x].IExcess = 0.;
	}
      }
    }
  }

  if (numroads > 0){
    printf("There are %d pixels with a road and %d with a road and a channel.\n",
	    numroads, numroadschan);
  }
 
  /* this all pertains to the impervious surface */

  doimpervious = 0;
  for (i = 0; i < Veg.NTypes; i++)
    if (VType[i].ImpervFrac > 0.0)
      doimpervious = 1;

  if (doimpervious) {
    if (!(inputfile = fopen(Options->ImperviousFilePath, "rt"))) {
      fprintf(stderr, 
	      "User has specified a percentage impervious area \n");
      fprintf(stderr, 
	      "To incorporate impervious area, DHSVM needs a file\n");
      fprintf(stderr, 
	      "identified by the key: \"IMPERVIOUS SURFACE ROUTING FILE\",\n");
      fprintf(stderr, 
	      "in the \"VEGETATION\" section.  This file is used to \n");
      fprintf(stderr, 
	      "determine the fate of surface runoff, i.e. where does it go \n");
      fprintf(stderr, 
	      "This file was not found: see InitNetwork.c \n");
      fprintf(stderr, 
	      "The code find_nearest_channel.c will make the file\n");
      ReportError(Options->ImperviousFilePath, 3);
    }
    for (y = 0; y < NY; y++) {
      for (x = 0; x < NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {
	  if (fscanf(inputfile, "%d %d %d %d \n", &sy, &sx, &miny, &minx) !=
	      EOF) {
	    TopoMap[y][x].drains_x = minx;
	    TopoMap[y][x].drains_y = miny;
	  }
	  else {
	    ReportError(Options->ImperviousFilePath, 63);
	  }
	  if (sx != x || sy != y) {
	    ReportError(Options->ImperviousFilePath, 64);
	  }
         if (!channel_grid_has_channel(ChannelData->stream_map, minx, miny)) {
	    printf("Routing file is wrong. The desitination cell is no channel cell!\n"); 
	    exit(0);
	  }
	}
      }
    }
  }
}
Exemple #15
0
/*****************************************************************************
  StoreModelState()

  Store the current state of the model.

  The state variables for DHSVM include the following variables:

    - Canopy interception for each vegetation layer

    - Snow pack conditions:
      - presence/absence
      - number of days since last snowfall (used in albedo calculation)
      - snow water equivalent
      - for each layer of the snow pack:
        - liquid water content
        - temperature
      - cold content

    - Soil conditions:
      - for each soil layer:
        - soil moisture (also for the layer below the deepest root zone)
        - temperature
      - surface temperature
      - ground heat storage
*****************************************************************************/
void StoreModelState(char *Path, DATE * Current, MAPSIZE * Map,
		     OPTIONSTRUCT * Options, TOPOPIX ** TopoMap,
		     PRECIPPIX ** PrecipMap, SNOWPIX ** SnowMap,
		     MET_MAP_PIX ** MetMap, RADCLASSPIX ** RadMap,
		     VEGCHEMPIX ** VegChemMap, LAYER * Veg, SOILPIX ** SoilMap,
		     LAYER * Soil, UNITHYDRINFO * HydrographInfo,
		     float *Hydrograph)
{
  const char *Routine = "StoreModelState";
  char Str[NAMESIZE + 1];
  char FileLabel[MAXSTRING + 1];
  char FileName[NAMESIZE + 1];
  FILE *HydroStateFile;
  int i;			/* counter */
  int x;			/* counter */
  int y;			/* counter */
  int NSoil;			/* Number of soil layers for current pixel */
  int NVeg;			/* Number of veg layers for current pixel */
  MAPDUMP DMap;			/* Dump Info */
  void *Array;

  /* print a message to stdout that state is being stored */
  
  printf("Saving Model State at: ");
  PrintDate(Current, stdout);
  printf("\n");

  /* Only save met state during debug, it is not needed for start-up */
  if (MetMap != NULL && DEBUG) {

    sprintf(Str, "%02d.%02d.%04d.%02d.%02d.%02d", Current->Month, Current->Day,
	    Current->Year, Current->Hour, Current->Min, Current->Sec);
    sprintf(FileName, "%sMet.State.%s%s", Path, Str, fileext);
    strcpy(FileLabel, "Basic Meteorology at time step");

    CreateMapFile(FileName, FileLabel, Map);

    if (!(Array = (float *) calloc(Map->NY * Map->NX, sizeof(float))))
      ReportError((char *) Routine, 1);

    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {

	  ((float *) Array)[y * Map->NX + x] = PrecipMap[y][x].Precip;

	}
	else
	  ((float *) Array)[y * Map->NX + x] = NA;
      }
    }
    DMap.ID = 201;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);
    Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {

	  ((float *) Array)[y * Map->NX + x] = MetMap[y][x].accum_precip;

	}
	else
	  ((float *) Array)[y * Map->NX + x] = NA;
      }
    }
    DMap.ID = 701;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);
    Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {

	  ((float *) Array)[y * Map->NX + x] = MetMap[y][x].air_temp;

	}
	else
	  ((float *) Array)[y * Map->NX + x] = NA;
      }
    }
    DMap.ID = 702;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);
    Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {

	  ((float *) Array)[y * Map->NX + x] = MetMap[y][x].wind_speed;

	}
	else
	  ((float *) Array)[y * Map->NX + x] = NA;
      }
    }
    DMap.ID = 703;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);
    Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {

	  ((float *) Array)[y * Map->NX + x] = MetMap[y][x].humidity;

	}
	else
	  ((float *) Array)[y * Map->NX + x] = NA;
      }
    }
    DMap.ID = 704;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);
    Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {

	  ((float *) Array)[y * Map->NX + x] = RadMap[y][x].Beam +
	    RadMap[y][x].Diffuse;

	}
	else
	  ((float *) Array)[y * Map->NX + x] = NA;
      }
    }
    DMap.ID = 303;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);
    Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

    free(Array);
  }
  /* Store the canopy interception */

  sprintf(Str, "%02d.%02d.%04d.%02d.%02d.%02d", Current->Month, Current->Day,
	  Current->Year, Current->Hour, Current->Min, Current->Sec);
  printf("Writing %sInterception.State.%s%s...\n", Path, Str, fileext);
  sprintf(FileName, "%sInterception.State.%s%s", Path, Str, fileext);
  strcpy(FileLabel, "Interception storage for each vegetation layer");

  CreateMapFile(FileName, FileLabel, Map);

  if (!(Array = (float *) calloc(Map->NY * Map->NX, sizeof(float))))
    ReportError((char *) Routine, 1);

  for (i = 0; i < Veg->MaxLayers; i++) {
    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {
	  NVeg = Veg->NLayers[(VegChemMap[y][x].Veg - 1)];
	  if (i < NVeg)
	    ((float *) Array)[y * Map->NX + x] = PrecipMap[y][x].IntRain[i];
	  else
	    ((float *) Array)[y * Map->NX + x] = NA;
	}
	else
	  ((float *) Array)[y * Map->NX + x] = NA;
      }
    }
    DMap.ID = 202;
    DMap.Layer = i;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);
    Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);
  }

  for (i = 0; i < Veg->MaxLayers; i++) {
    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {
	  NVeg = Veg->NLayers[(VegChemMap[y][x].Veg - 1)];
	  if (i < NVeg)
	    ((float *) Array)[y * Map->NX + x] = PrecipMap[y][x].IntSnow[i];
	  else
	    ((float *) Array)[y * Map->NX + x] = NA;
	}
	else
	  ((float *) Array)[y * Map->NX + x] = NA;
      }
    }
    DMap.ID = 203;
    DMap.Layer = i;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);
    Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);
  }

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	((float *) Array)[y * Map->NX + x] = PrecipMap[y][x].TempIntStorage;
      }
      else {
	((float *) Array)[y * Map->NX + x] = NA;
      }
    }
  }
  DMap.ID = 204;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);
  Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

  free(Array);

  /* Store the snow pack conditions */

  printf("Writing %sSnow.State.%s%s...\n", Path, Str, fileext);
  sprintf(FileName, "%sSnow.State.%s%s", Path, Str, fileext);
  strcpy(FileLabel, "Snow pack moisture and temperature state");
  CreateMapFile(FileName, FileLabel, Map);

  if (!(Array = (float *) calloc(Map->NY * Map->NX, sizeof(float))))
    ReportError((char *) Routine, 1);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask))
	((float *) Array)[y * Map->NX + x] = (float) SnowMap[y][x].HasSnow;
      else
	((float *) Array)[y * Map->NX + x] = NA;
    }
  }
  DMap.ID = 401;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);
  Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask))
	((float *) Array)[y * Map->NX + x] = (float) SnowMap[y][x].LastSnow;
      else
	((float *) Array)[y * Map->NX + x] = NA;
    }
  }
  DMap.ID = 403;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);
  Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask))
	((float *) Array)[y * Map->NX + x] = SnowMap[y][x].Swq;
      else
	((float *) Array)[y * Map->NX + x] = NA;
    }
  }
  DMap.ID = 404;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);
  Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask))
	((float *) Array)[y * Map->NX + x] = SnowMap[y][x].PackWater;
      else
	((float *) Array)[y * Map->NX + x] = NA;
    }
  }
  DMap.ID = 406;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);
  Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask))
	((float *) Array)[y * Map->NX + x] = SnowMap[y][x].TPack;
      else
	((float *) Array)[y * Map->NX + x] = NA;
    }
  }
  DMap.ID = 407;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);
  Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask))
	((float *) Array)[y * Map->NX + x] = SnowMap[y][x].SurfWater;
      else
	((float *) Array)[y * Map->NX + x] = NA;
    }
  }
  DMap.ID = 408;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);
  Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask))
	((float *) Array)[y * Map->NX + x] = SnowMap[y][x].TSurf;
      else
	((float *) Array)[y * Map->NX + x] = NA;
    }
  }
  DMap.ID = 409;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);
  Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask))
	((float *) Array)[y * Map->NX + x] = SnowMap[y][x].ColdContent;
      else
	((float *) Array)[y * Map->NX + x] = NA;
    }
  }
  DMap.ID = 410;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);
  Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

  free(Array);

  /* Store the soil conditions */

  printf("Writing %sSoil.State.%s%s...\n", Path, Str, fileext);
  sprintf(FileName, "%sSoil.State.%s%s", Path, Str, fileext);
  strcpy(FileLabel, "Soil moisture and temperature state");
  CreateMapFile(FileName, FileLabel, Map);

  if (!(Array = (float *) calloc(Map->NY * Map->NX, sizeof(float))))
    ReportError((char *) Routine, 1);

  for (i = 0; i < Soil->MaxLayers + 1; i++) {
    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {
	  NSoil = Soil->NLayers[(SoilMap[y][x].Soil - 1)];
	  if (i <= NSoil)
	    ((float *) Array)[y * Map->NX + x] = SoilMap[y][x].Moist_m_m[i];
	  else
	    ((float *) Array)[y * Map->NX + x] = NA;
	}
	else
	  ((float *) Array)[y * Map->NX + x] = NA;
      }
    }
    DMap.ID = 501;
    DMap.Layer = i;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);
    Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);
  }

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask))
	((float *) Array)[y * Map->NX + x] = SoilMap[y][x].TSurf;
      else
	((float *) Array)[y * Map->NX + x] = SoilMap[y][x].TSurf;
    }
  }
  DMap.ID = 505;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);
  Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

  for (i = 0; i < Soil->MaxLayers; i++) {
    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {
	  NSoil = Soil->NLayers[SoilMap[y][x].Soil - 1];
	  if (i < NSoil)
	    ((float *) Array)[y * Map->NX + x] = SoilMap[y][x].Temp[i];
	  else
	    ((float *) Array)[y * Map->NX + x] = NA;
	}
	else
	  ((float *) Array)[y * Map->NX + x] = NA;
      }
    }
    DMap.ID = 511;
    DMap.Layer = i;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);
    Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);
  }

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask))
	((float *) Array)[y * Map->NX + x] = SoilMap[y][x].Qst;
      else
	((float *) Array)[y * Map->NX + x] = NA;
    }
  }
  DMap.ID = 510;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);
  Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask))
	((float *) Array)[y * Map->NX + x] = SoilMap[y][x].Runoff_m;
      else
	((float *) Array)[y * Map->NX + x] = NA;
    }
  }
  DMap.ID = 512;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);
  Write2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, &DMap, 0);

  free(Array);

  /* If the unit hydrograph is used for flow routing, store the unit 
     hydrograph array */

  if (Options->Extent == BASIN && Options->HasNetwork == FALSE) {
    sprintf(FileName, "%sHydrograph.State.%s", Path, Str);
    OpenFile(&HydroStateFile, FileName, "w", FALSE);
    for (i = 0; i < HydrographInfo->TotalWaveLength; i++)
      fprintf(HydroStateFile, "%f\n", Hydrograph[i]);
    fclose(HydroStateFile);
  }
}
/*******************************************************************************
Function name: InitGridMet()

Purpose      : Read the gridded met file.  This information
is in the [METEOROLOGY] section
*****************************************************************************/
void InitGridMet(OPTIONSTRUCT *Options, LISTPTR Input, MAPSIZE *Map, 
  TOPOPIX **TopoMap, GRID *Grid, METLOCATION **Stat, int *NStats)
{
  char *Routine = "InitGridMet";
  char KeyName[BUFSIZE + 1];
  char VarStr[BUFSIZE + 1];
  int i, j, k, m;
  float lat, lon, North, East;

  STRINIENTRY StrEnv[] = {
    { "METEOROLOGY", "GRID ROWS", "", "" },
    { "METEOROLOGY", "GRID COLS", "", "" },
    { "METEOROLOGY", "EXTREME NORTH LAT", "", "" },
    { "METEOROLOGY", "EXTREME EAST LON", "", "" },
    { "METEOROLOGY", "GRID SIZE", "", "" },
    { "METEOROLOGY", "MET FILE PATH", "", "" },
    { NULL, NULL, "", NULL },
  };

   /* Allocate memory for the stations */
  if (!(Grid = (GRID *) calloc(1, sizeof(GRID))))
    ReportError(Routine, 1);

  /* Read the key-entry pairs from the input file */
  for (i = 0; StrEnv[i].SectionName; i++)
    GetInitString(StrEnv[i].SectionName, StrEnv[i].KeyName, StrEnv[i].Default,
      StrEnv[i].VarStr, (unsigned long)BUFSIZE, Input);

  if (!CopyFloat(&(Grid->LatOrig), StrEnv[grid_ext_north].VarStr, 1))
    ReportError(StrEnv[grid_ext_north].KeyName, 51);

  if (!CopyFloat(&(Grid->LonOrig), StrEnv[grid_ext_east].VarStr, 1))
    ReportError(StrEnv[grid_ext_east].KeyName, 51);

  if (!CopyInt(&(Grid->row), StrEnv[grid_rows].VarStr, 1))
    ReportError(StrEnv[grid_rows].KeyName, 51);

  if (!CopyInt(&(Grid->col), StrEnv[grid_cols].VarStr, 1))
    ReportError(StrEnv[grid_cols].KeyName, 51);

  /* total number of grid cell */
  *NStats = Grid->row * Grid->col; 

  if (!CopyFloat(&(Grid->GridSize), StrEnv[grid_size].VarStr, 1))
    ReportError(StrEnv[grid_size].KeyName, 51);

  /* path to all grid met files */
  if (IsEmptyStr(StrEnv[grid_met_file].VarStr))
    ReportError(StrEnv[grid_met_file].KeyName, 51);
  strcpy(Grid->filepath, StrEnv[grid_met_file].VarStr);

  /* Allocate memory for the stations */
  if (!(*Stat = (METLOCATION *)calloc(*NStats, sizeof(METLOCATION))))
    ReportError(Routine, 1);

  k = 0;
  m = 0;
  for (i = 0; i < Grid->col; i++) {
    for (j = 0; j < Grid->row; j++) {
      lon = Grid->LonOrig - Grid->GridSize * i;
      lat = Grid->LatOrig - Grid->GridSize * j;

      /* convert lat and lon to utm */
      deg2utm(lat, lon, &East, &North);
      (*Stat)[k].Loc.N = Round(((Map->Yorig - 0.5 * Map->DY) - North) / Map->DY);
      (*Stat)[k].Loc.E = Round((East - (Map->Xorig + 0.5 * Map->DX)) / Map->DX);
      sprintf((*Stat)[k].Name, "data_%.5f_%.5f", lat, lon);
      m += 1;
      if (((*Stat)[k].Loc.N >= Map->NY || (*Stat)[k].Loc.N < 0 || 
        (*Stat)[k].Loc.E >= Map->NX || (*Stat)[k].Loc.E < 0) )
        printf("Station %d outside the basin: %s ignored\n", m + 1, (*Stat)[k].Name);
      else {
        if (INBASIN(TopoMap[(*Stat)[k].Loc.N][(*Stat)[k].Loc.E].Mask)) {  
          /* open met data file */
          sprintf((*Stat)[k].MetFile.FileName, "%s%.5f_%.5f", Grid->filepath, lat, lon);
          
          if (!((*Stat)[k].MetFile.FilePtr = fopen((*Stat)[k].MetFile.FileName, "r"))) {
            printf("%s doesn't exist\n", (*Stat)[k].MetFile.FileName);
            continue;
          }
          k = k + 1;
        }
      }
    }
  }
  /* if no grid is found within the mask, exit with error */
  if (k < 1)
    ReportError(Routine, 69);

  if (Options->Outside == FALSE)
    printf("Final number of stations in bounding box is %d \n\n", k);
  else
    printf("Forced to include all %d stations \n", k);
  *NStats = k;

}
void main_spinup(MAPSIZE *Map, TOPOPIX **TopoMap, SNOWPIX **Snow, GLPIX **GlacierMap, double dt_year, double year_min, double year_max,DATE *Current, DUMPSTRUCT *Dump, OPTIONSTRUCT * Options)
{
 
  FILE   *f_out1 ;
  double  *b, *s_init, *s_out,  *b_dot; 
  double  dt_yr;
  double  yr_min;
  double  yr_max;
  float gl_cov;
  float h_max;
  int  k;
  int x;
  int y;
  char file_out1[80];
  float *Array1;
  int n_mask;
  /* Use Glen parameter with Annual units */
  double  A_GLEN  = 7.5738e-17; // 7.5738e-17 Cuffey & Paterson (4th ed) Glen's law parameter in Pa^{-3} yr^{-1} units (same as A_GLEN=2.4e-24 Pa^{-3} s^{-1})

  extern double  RHO;     
  extern double  n_GLEN;
  extern double  C_SLIDE;
  extern double  m_SLIDE;
  extern double  A_tilde;
  extern double  C_tilde;
  extern double g;
  extern double dx;
  extern int N;
  extern double  nm_half;
  extern double  np1;
  extern double  mm_half;
  extern double  m1; 

  
  
  // h      = malloc(N*sizeof(double));         // ice thickness (vectorized)
  b      = malloc(N*sizeof(double));         // bed surface elevation (vectorized)
  s_init = malloc(N*sizeof(double));         // initial ice surface elevation (vectorized)
  s_out  = malloc(N*sizeof(double));         // output ice surface elevation (vectorized)
        
  b_dot      = malloc(N*sizeof(double));
  
  // Array  = malloc(N*sizeof(float));
  // if (!(Array1 = (float *) calloc(Map->NX * Map->NY, sizeof(float))));
  
  dt_yr = dt_year;
 
  yr_min = year_min;
  yr_max =  year_max;
  k = 0;
  nm_half = (n_GLEN-1)/2;
  np1     = n_GLEN+1;
  mm_half = (m_SLIDE-1)/2;
  m1      = m_SLIDE;
  n_mask = 0;
  gl_cov = 0;
  h_max = 0;
  
  //  printf("dt_yr= %f yr_min= %f yr_max= %f", dt_yr, yr_min, yr_max);ic_jp[k] = ny*ic[i] + jp[j];for (i=0; i<nx; i++)
   for (x = 0; x < Map->NX; x++) {
     for (y = 0; y < Map->NY; y++) {
       k    = x*Map->NY + y;
       if (INBASIN(TopoMap[y][x].Mask)){
	 b_dot[k] = GlacierMap[y][x].Mbal;
	 b[k] = GlacierMap[y][x].b;
	 s_init[k]= b[k];
	 n_mask +=1;
       }
       else {
	 /*The following line forces mass balance to be very negative outside of glacier mask*/
        //b_dot[k] = -20;
	 b[k] = GlacierMap[y][x].b;
	 s_init[k] =  b[k];
       }
	    
     }
   }

   A_tilde = 2*A_GLEN*pow(RHO*g,n_GLEN)/((n_GLEN+2)*pow(dx,2));
   C_tilde = C_SLIDE*pow(RHO*g,m_SLIDE)/pow(dx,2);
   
   SetupIndexArrays();

   RunGlacier(b, s_init, s_out, yr_min, yr_max, dt_yr, b_dot, Options);
  
   gl_cov = 0;
   h_max = 0;
   for (x = 0; x < Map->NX; x++) {
     for (y = 0; y < Map->NY; y++) {
       if (INBASIN(TopoMap[y][x].Mask)){
	 k    = x*Map->NY + y;
	 GlacierMap[y][x].s_init = s_out[k];
	 GlacierMap[y][x].s_out = s_out[k];
	 GlacierMap[y][x].h = GlacierMap[y][x].s_out - GlacierMap[y][x].b;
	 Snow[y][x].Iwq = GlacierMap[y][x].h * (900./1000.);
	 Snow[y][x].iweold = Snow[y][x].Iwq;
	 GlacierMap[y][x].totmbal = 0.0;
	 if( GlacierMap[y][x].s_out<=GlacierMap[y][x].b)
	   GlacierMap[y][x].s_out  =  GlacierMap[y][x].b;
	 else
	   {
	     if (GlacierMap[y][x].s_out- GlacierMap[y][x].b > h_max)
	       h_max =  GlacierMap[y][x].s_out - GlacierMap[y][x].b;
	   }
	 
	 if (GlacierMap[y][x].s_out > GlacierMap[y][x].b)
	  gl_cov += 1;
       }
       //else{
	 //b_dot[k] = -20;
	 //b[k] = GlacierMap[y][x].b;
	 //s_init[k] =  b[k];
	 
      // } 
       
     }
   }

   sprintf(file_out1, "%sh_spinup.bin", Dump->Path);

   if((f_out1=fopen(file_out1,"wb"))==NULL)
     {
       printf("main(): Cannot open output file %s\n", file_out1);
       exit(1);
     }
   
   for (x = 0; x < Map->NX; x++) {
     for (y = 0; y < Map->NY; y++){
       k    = x*Map->NY + y;
       //((float *) Array)[y * Map->NX + x] = b_dot[k];
       ((float *) Array1)[y * Map->NX + x] = GlacierMap[y][x].h;
     }
   }
   fwrite(Array1, sizeof(Array1), Map->NY * Map->NX, f_out1);

   free(Array1);
   free(b);
   free(s_out);
   free(s_init);
   
   free(b_dot); 
   fclose(f_out1);
   printf("ALL DONE: %.2f yr integration\n", yr_max);
}
Exemple #18
0
/*****************************************************************************
  InitSoilMap()
*****************************************************************************/
void InitSoilMap(LISTPTR Input, OPTIONSTRUCT * Options, MAPSIZE * Map,
		 LAYER * Soil, TOPOPIX ** TopoMap, SOILPIX *** SoilMap)
{
  const char *Routine = "InitSoilMap";
  char VarName[BUFSIZE + 1];	/* Variable name */
  int i;			/* counter */
  int x;			/* counter */
  int y;			/* counter */
  int NumberType;		/* number type */
  unsigned char *Type;		/* Soil type */
  float *Depth;			/* Soil depth */
  int flag;
  STRINIENTRY StrEnv[] = {
    {"SOILS", "SOIL MAP FILE", "", ""},
    {"SOILS", "SOIL DEPTH FILE", "", ""},
    {NULL, NULL, "", NULL}
  };

  /* Process the filenames in the [SOILS] section in the input file */
  /* Assign the attributes to the correct map pixel */
  if (!(*SoilMap = (SOILPIX **) calloc(Map->NY, sizeof(SOILPIX *))))
    ReportError((char *) Routine, 1);
  for (y = 0; y < Map->NY; y++) {
    if (!((*SoilMap)[y] = (SOILPIX *) calloc(Map->NX, sizeof(SOILPIX))))
      ReportError((char *) Routine, 1);
  }

  /* Read the key-entry pairs from the input file */
  for (i = 0; StrEnv[i].SectionName; i++) {
    GetInitString(StrEnv[i].SectionName, StrEnv[i].KeyName, StrEnv[i].Default,
		  StrEnv[i].VarStr, (unsigned long) BUFSIZE, Input);
    if (IsEmptyStr(StrEnv[i].VarStr))
      ReportError(StrEnv[i].KeyName, 51);
  }

  /* Read the soil type */
  GetVarName(003, 0, VarName);
  GetVarNumberType(003, &NumberType);
  if (!(Type = (unsigned char *) calloc(Map->NX * Map->NY,
					SizeOfNumberType(NumberType))))
    ReportError((char *) Routine, 1);
  flag = Read2DMatrix(StrEnv[soiltype_file].VarStr, Type, NumberType, Map->NY,
	       Map->NX, 0, VarName, 0);

  if ((Options->FileFormat == NETCDF && flag == 0) 
	  || (Options->FileFormat == BIN))
  {
	  for (y = 0, i = 0; y < Map->NY; y++) {
		  for (x = 0; x < Map->NX; x++, i++) {
			  if (((int) Type[i]) > Soil->NTypes)
				  ReportError(StrEnv[soiltype_file].VarStr, 32);
			  (*SoilMap)[y][x].Soil = Type[i]; }
	  }
  }
  else if (Options->FileFormat == NETCDF && flag == 1){
	  for (y = Map->NY - 1, i = 0; y >= 0; y--) {
		  for (x = 0; x < Map->NX; x++, i++) {
			  if (((int) Type[i]) > Soil->NTypes)
				  ReportError(StrEnv[soiltype_file].VarStr, 32);
			  (*SoilMap)[y][x].Soil = Type[i]; }
	  }
  }
  else ReportError((char *) Routine, 57);

  /* Read the total soil depth  */
  GetVarName(004, 0, VarName);
  GetVarNumberType(004, &NumberType);
  if (!(Depth = (float *) calloc(Map->NX * Map->NY,
				 SizeOfNumberType(NumberType))))
    ReportError((char *) Routine, 1);
  flag = Read2DMatrix(StrEnv[soildepth_file].VarStr, Depth, NumberType, Map->NY,
	       Map->NX, 0, VarName, 0);

  /* Assign the attributes to the correct map pixel */
  if ((Options->FileFormat == NETCDF && flag == 0) 
	  || (Options->FileFormat == BIN))
  {
	  for (y = 0, i = 0; y < Map->NY; y++) {
		  for (x = 0; x < Map->NX; x++, i++) {
			  (*SoilMap)[y][x].Depth = Depth[i]; }
	  }
  }
  else if (Options->FileFormat == NETCDF && flag == 1){
	  for (y = Map->NY - 1, i = 0; y >= 0; y--) {
		  for (x = 0; x < Map->NX; x++, i++) {
			  (*SoilMap)[y][x].Depth = Depth[i]; }
	  }
  }
  else ReportError((char *) Routine, 57);

  for (y = 0, i = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++, i++) {
      if (Options->Infiltration == DYNAMIC)
		  (*SoilMap)[y][x].InfiltAcc = 0.; 
	  (*SoilMap)[y][x].MoistInit = 0.; 

     /* allocate memory for the number of root layers, plus an additional 
	  layer below the deepest root layer */
	  if (INBASIN(TopoMap[y][x].Mask)) {
		  if (!((*SoilMap)[y][x].Moist = 
			  (float *) calloc((Soil->NLayers[Type[i] - 1] + 1), sizeof(float))))
			  ReportError((char *) Routine, 1);
		  if (!((*SoilMap)[y][x].Perc =
			  (float *) calloc(Soil->NLayers[Type[i] - 1], sizeof(float))))
			  ReportError((char *) Routine, 1);
		  if (!((*SoilMap)[y][x].Temp =
			  (float *) calloc(Soil->NLayers[Type[i] - 1], sizeof(float))))
			  ReportError((char *) Routine, 1);
	  }
      else {
		  (*SoilMap)[y][x].Moist = NULL;
		  (*SoilMap)[y][x].Perc = NULL;
		  (*SoilMap)[y][x].Temp = NULL;
      }
    }
  }
  free(Type);
  free(Depth);
}
Exemple #19
0
int main(int argc, char **argv)
{
  float *Hydrograph = NULL;
  float ***MM5Input = NULL;
  float **PrecipLapseMap = NULL;
  float **PrismMap = NULL;
  unsigned char ***ShadowMap = NULL;
  float **SkyViewMap = NULL;
  float ***WindModel = NULL;
  /* Glacier Model Variable */
  double  dt_year;
  double  year_min;
  double  year_max;
  int MaxStreamID, MaxRoadID;
  clock_t start, finish1;
  double runtime = 0.0;
  int t = 0;
  float roadarea;
  int i;
  int j;
  int x;						/* row counter */
  int y;						/* column counter */
  int shade_offset;				/* a fast way of handling arraay position given the number of mm5 input options */
  int NStats;					/* Number of meteorological stations */
  uchar ***MetWeights = NULL;	/* 3D array with weights for interpolating meteorological variables between the stations */

  int NGraphics;				/* number of graphics for X11 */
  int *which_graphics;			/* which graphics for X11 */

  AGGREGATED Total = {			/* Total or average value of a  variable over the entire basin */
    {0.0, NULL, NULL, NULL, NULL, 0.0},												/* EVAPPIX */
    {0.0, 0.0, 0.0, 0.0, 0.0, NULL, NULL, 0.0, 0, 0.0},								/* PRECIPPIX */
    {{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}, 0.0, {0.0, 0.0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
                                                                                    /* PIXRAD */
    {0.0, 0.0, 0, NULL, NULL, 0.0, 0, 0.0, 0.0, 0.0, 0.0, NULL, NULL},				/* ROADSTRUCT*/
    {0, 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},		/* SNOWPIX */
    {0, 0.0, NULL, NULL, NULL, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},			                /* SOILPIX */
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0l, 0.0, 0.0
  };
  CHANNEL ChannelData = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL};
  DUMPSTRUCT Dump;
  EVAPPIX **EvapMap = NULL;
  INPUTFILES InFiles;
  LAYER Soil;
  LAYER Veg;
  LISTPTR Input = NULL;			/* Linked list with input strings */
  MAPSIZE Map;					/* Size and location of model area */
  MAPSIZE Radar;				/* Size and location of area covered by precipitation radar */
  MAPSIZE MM5Map;				/* Size and location of area covered by MM5 input files */
  GRID Grid;
  METLOCATION *Stat = NULL;
  OPTIONSTRUCT Options;			/* Structure with information which program options to follow */
  PIXMET LocalMet;				/* Meteorological conditions for current pixel */
  PRECIPPIX **PrecipMap = NULL;
  RADARPIX **RadarMap	= NULL;
  PIXRAD **RadiationMap = NULL;
  ROADSTRUCT **Network	= NULL;	/* 2D Array with channel information for each pixel */
  SNOWPIX **SnowMap		= NULL;
  GLPIX **GlacierMap = NULL; /* glacier model*/
  MET_MAP_PIX **MetMap	= NULL;
  SNOWTABLE *SnowAlbedo = NULL;
  SOILPIX **SoilMap		= NULL;
  SOILTABLE *SType	    = NULL;
  SOLARGEOMETRY SolarGeo;		/* Geometry of Sun-Earth system (needed for INLINE radiation calculations */
  TIMESTRUCT Time;
  TOPOPIX **TopoMap = NULL;
  UNITHYDR **UnitHydrograph = NULL;
  UNITHYDRINFO HydrographInfo;	/* Information about unit hydrograph */
  VEGPIX **VegMap = NULL;
  VEGTABLE *VType = NULL;
  WATERBALANCE Mass =			/* parameter for mass balance calculations */
    { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };

/*****************************************************************************
  Initialization Procedures 
*****************************************************************************/
  if (argc != 2) {
    fprintf(stderr, "\nUsage: %s inputfile\n\n", argv[0]);
    fprintf(stderr, "DHSVM uses two output streams: \n");
    fprintf(stderr, "Standard Out, for the majority of output \n");
    fprintf(stderr, "Standard Error, for the final mass balance \n");
    fprintf(stderr, "\nTo pipe output correctly to files: \n");
    fprintf(stderr, "(cmd > f1) >& f2 \n");
    fprintf(stderr, "where f1 is stdout_file and f2 is stderror_file\n");
    exit(EXIT_FAILURE);
  }

  sprintf(commandline, "%s %s", argv[0], argv[1]);
  printf("%s \n", commandline);
  fprintf(stderr, "%s \n", commandline);
  strcpy(InFiles.Const, argv[1]);

  printf("\nRunning DHSVM %s\n", version);
  printf("\nSTARTING INITIALIZATION PROCEDURES\n\n");

  /* Start recording time */
  start = clock();

  ReadInitFile(InFiles.Const, &Input);
  InitConstants(Input, &Options, &Map, &SolarGeo, &Time);

  InitFileIO(Options.FileFormat);
  InitTables(Time.NDaySteps, Input, &Options, &SType, &Soil, &VType, &Veg,
	     &SnowAlbedo);
  InitGlacierMap(&Map, &GlacierMap); /*glacier model*/
  InitTerrainMaps(Input, &Options, &Map, &Soil, &TopoMap, &SoilMap, &VegMap, &GlacierMap);
  
  CheckOut(&Options, Veg, Soil, VType, SType, &Map, TopoMap, VegMap, SoilMap);

  if (Options.HasNetwork)
    InitChannel(Input, &Map, Time.Dt, &ChannelData, SoilMap, &MaxStreamID, &MaxRoadID, &Options);
  else if (Options.Extent != POINT)
    InitUnitHydrograph(Input, &Map, TopoMap, &UnitHydrograph,
		       &Hydrograph, &HydrographInfo);
 
  InitNetwork(Map.NY, Map.NX, Map.DX, Map.DY, TopoMap, SoilMap, 
	      VegMap, VType, &Network, &ChannelData, Veg, &Options);

  InitMetSources(Input, &Options, &Map, TopoMap, Soil.MaxLayers, &Time,
		 &InFiles, &NStats, &Stat, &Radar, &MM5Map, &Grid);

  /* the following piece of code is for the UW PRISM project */
  /* for real-time verification of SWE at Snotel sites */
  /* Other users, set OPTION.SNOTEL to FALSE, or use TRUE with caution */

  if (Options.Snotel == TRUE && Options.Outside == FALSE) {
    printf
      ("Warning: All met stations locations are being set to the vegetation class GLACIER\n");
    printf
      ("Warning: This requires that you have such a vegetation class in your vegetation table\n");
    printf("To disable this feature set Snotel OPTION to FALSE\n");
    for (i = 0; i < NStats; i++) {
      printf("veg type for station %d is %d ", i,
	     VegMap[Stat[i].Loc.N][Stat[i].Loc.E].Veg);
      for (j = 0; j < Veg.NTypes; j++) {
	    if (VType[j].Index == GLACIER) {
	      VegMap[Stat[i].Loc.N][Stat[i].Loc.E].Veg = j;
		  break;
		}
      }
      if (j == Veg.NTypes) {	/* glacier class not found */
	    ReportError("MainDHSVM", 62);
	  }
      printf("setting to glacier type (assumed bare class): %d\n", j);
    }
  }

  InitMetMaps(Time.NDaySteps, &Map, &Radar, &Options, InFiles.WindMapPath,
	      InFiles.PrecipLapseFile, &PrecipLapseMap, &PrismMap,
	      &ShadowMap, &SkyViewMap, &EvapMap, &PrecipMap,
	      &RadarMap, &RadiationMap, SoilMap, &Soil, VegMap, &Veg, TopoMap,
	      &MM5Input, &WindModel);

  InitInterpolationWeights(&Map, &Options, TopoMap, &MetWeights, Stat, NStats);

  InitDump(Input, &Options, &Map, Soil.MaxLayers, Veg.MaxLayers, Time.Dt,
	   TopoMap, &Dump, &NGraphics, &which_graphics);

  if (Options.HasNetwork == TRUE) {
    InitChannelDump(&Options, &ChannelData, Dump.Path);
    ReadChannelState(Dump.InitStatePath, &(Time.Start), ChannelData.streams);
	if (Options.StreamTemp && Options.CanopyShading)
	  InitChannelRVeg(&Time, ChannelData.streams);
  }

  InitSnowMap(&Map, &SnowMap);
  InitAggregated(Veg.MaxLayers, Soil.MaxLayers, &Total);

  InitModelState(&(Time.Start), &Map, &Options, PrecipMap, SnowMap, SoilMap,
		 Soil, SType, VegMap, Veg, VType, Dump.InitStatePath,
		 SnowAlbedo, TopoMap, Network, &HydrographInfo, Hydrograph, &Total, GlacierMap);

#ifdef HAVE_GLACIER
/* Glacier Model is run independently to "spinup" glacier ice state over 1000 years */
  if (Options.Glacier == GLSPINUP){
   dt_year  = 1;
   year_min = 0;
   year_max = 1000;
   printf("Glacier model spin up run for %f years\n", year_max);
   main_spinup(&Map, TopoMap, SnowMap,GlacierMap, dt_year,year_min,year_max, 
   &(Time.Current), &Dump, &Options);
   return EXIT_SUCCESS;
  }
#endif

  InitNewMonth(&Time, &Options, &Map, TopoMap, PrismMap, ShadowMap,
	       &InFiles, Veg.NTypes, VType, NStats, Stat, Dump.InitStatePath);

  InitNewDay(Time.Current.JDay, &SolarGeo);

  if (NGraphics > 0) {
    printf("Initialzing X11 display and graphics \n");
    InitXGraphics(argc, argv, Map.NY, Map.NX, NGraphics, &MetMap);
  }

  shade_offset = FALSE;
  if (Options.Shading == TRUE)
    shade_offset = TRUE;

  /* Done with initialization, delete the list with input strings */
  DeleteList(Input);

  /* setup for mass balance calculations */
  Aggregate(&Map, &Options, TopoMap, &Soil, &Veg, VegMap, EvapMap, PrecipMap,
	      RadiationMap, SnowMap, SoilMap, &Total, VType, Network, &ChannelData, &roadarea);

  Mass.StartWaterStorage =
    Total.Soil.IExcess + Total.CanopyWater + Total.SoilWater + Total.Snow.Swq +
    Total.Soil.SatFlow + Total.Snow.Iwq + Total.Snow.IceRemoved;
  Mass.OldWaterStorage = Mass.StartWaterStorage;

  /* computes the number of grid cell contributing to one segment */
  if (Options.StreamTemp) 
	Init_segment_ncell(TopoMap, ChannelData.stream_map, Map.NY, Map.NX, ChannelData.streams);

/*****************************************************************************
  Perform Calculations 
*****************************************************************************/
  while (Before(&(Time.Current), &(Time.End)) ||
	 IsEqualTime(&(Time.Current), &(Time.End))) {

    /* debug */
    if (Time.Current.Month == 5 && Time.Current.Day == 20 && Time.Current.Hour >= 9 && Time.Current.Hour <= 15)
      printf("stop here for a little\n");
    /* debug ends */

    /* reset aggregated variables */
    ResetAggregate(&Soil, &Veg, &Total, &Options);

    if (IsNewMonth(&(Time.Current), Time.Dt)){
      InitNewMonth(&Time, &Options, &Map, TopoMap, PrismMap, ShadowMap,
		   &InFiles, Veg.NTypes, VType, NStats, Stat, Dump.InitStatePath);
#ifdef HAVE_GLACIER
          /* Run the glacier model at the end of every month */
	  if (Options.Glacier == GLSTATIC || Options.Glacier == GLDYNAMIC){
            dt_year  = 1.0;
            year_min = 1.0;
            year_max = 1.0;
             if(Time.Current.Month == 10 && Time.Current.Day == 1){
            /* Calculate Equilibrium Line Altitude at end of Water Year (assumed Oct1) */
	    /* will need to be changed depending on geography define water year */
	     calc_ela(&Map, TopoMap,SnowMap,GlacierMap,&(Time.Current), &Dump);
	}

            main_gl(&Map, TopoMap, SnowMap,GlacierMap, dt_year,year_min,year_max,
	    &(Time.Current), &Dump,&Options);
            /*Use the next program to output balance information for indivdual glaciers */
            gl_massbalance(&Map, TopoMap, SnowMap,GlacierMap, dt_year,year_min,
	    year_max, &(Time.Current), &Dump);
	}
#endif
    }
    if (IsNewDay(Time.DayStep)) {
      InitNewDay(Time.Current.JDay, &SolarGeo);
      PrintDate(&(Time.Current), stdout);
      printf("\n");
    }

    InitNewStep(&InFiles, &Map, &Time, Soil.MaxLayers, &Options, NStats, Stat,
		InFiles.RadarFile, &Radar, RadarMap, &SolarGeo, TopoMap, 
        SoilMap, MM5Input, WindModel, &MM5Map);

    /* initialize channel/road networks for time step */
    if (Options.HasNetwork) {
      channel_step_initialize_network(ChannelData.streams);
      channel_step_initialize_network(ChannelData.roads);
    }

    for (y = 0; y < Map.NY; y++) {
      for (x = 0; x < Map.NX; x++) {
	    if (INBASIN(TopoMap[y][x].Mask)) {
		  if (Options.Shading)
	        LocalMet =
	        MakeLocalMetData(y, x, &Map, Time.DayStep, &Options, NStats,
			       Stat, MetWeights[y][x], TopoMap[y][x].Dem,
			       &(RadiationMap[y][x]), &(PrecipMap[y][x]), &Radar,
			       RadarMap, PrismMap, &(SnowMap[y][x]),
			       SnowAlbedo, MM5Input, WindModel, PrecipLapseMap,
			       &MetMap, NGraphics, Time.Current.Month,
			       SkyViewMap[y][x], ShadowMap[Time.DayStep][y][x],
			       SolarGeo.SunMax, SolarGeo.SineSolarAltitude);
		  else
	        LocalMet =
	        MakeLocalMetData(y, x, &Map, Time.DayStep, &Options, NStats,
			       Stat, MetWeights[y][x], TopoMap[y][x].Dem,
			       &(RadiationMap[y][x]), &(PrecipMap[y][x]), &Radar,
			       RadarMap, PrismMap, &(SnowMap[y][x]),
			       SnowAlbedo, MM5Input, WindModel, PrecipLapseMap,
			       &MetMap, NGraphics, Time.Current.Month, 0.0,
			       0.0, SolarGeo.SunMax,
			       SolarGeo.SineSolarAltitude);

		  /* get surface tempeature of each soil layer */
		  for (i = 0; i < Soil.MaxLayers; i++) {
	        if (Options.HeatFlux == TRUE) {
	          if (Options.MM5 == TRUE)
		        SoilMap[y][x].Temp[i] =
				MM5Input[shade_offset + i + N_MM5_MAPS][y][x];

              /* read tempeature of each soil layer from met station input */
			  else
		        SoilMap[y][x].Temp[i] = Stat[0].Data.Tsoil[i];
			}
            /* if heat flux option is turned off, soil temperature of all 3 layers 
            is taken equal to air tempeature */
	        else
	          SoilMap[y][x].Temp[i] = LocalMet.Tair;
		  }
		  
		  MassEnergyBalance(&Options, y, x, SolarGeo.SineSolarAltitude, Map.DX, Map.DY, 
			    Time.Dt, Options.HeatFlux, Options.CanopyRadAtt, Options.Infiltration, 
				Veg.MaxLayers, &LocalMet, &(Network[y][x]), &(PrecipMap[y][x]), 
			    &(VType[VegMap[y][x].Veg-1]), &(VegMap[y][x]), &(SType[SoilMap[y][x].Soil-1]),
			    &(SoilMap[y][x]), &(SnowMap[y][x]), &(RadiationMap[y][x]), &(EvapMap[y][x]), 
                &(Total.Rad), &ChannelData, SkyViewMap);
		 
		  PrecipMap[y][x].SumPrecip += PrecipMap[y][x].Precip;
		}
	  }
    }

	/* Average all RBM inputs over each segment */
	if (Options.StreamTemp) {
	  channel_grid_avg(ChannelData.streams);
      if (Options.CanopyShading)
	    CalcCanopyShading(&Time, ChannelData.streams, &SolarGeo);
	}

 #ifndef SNOW_ONLY
    
    RouteSubSurface(Time.Dt, &Map, TopoMap, VType, VegMap, Network,
		    SType, SoilMap, &ChannelData, &Time, &Options, Dump.Path,
		    MaxStreamID, SnowMap);

    if (Options.HasNetwork)
      RouteChannel(&ChannelData, &Time, &Map, TopoMap, SoilMap, &Total, 
		   &Options, Network, SType, PrecipMap, LocalMet.Tair, LocalMet.Rh);

    if (Options.Extent == BASIN)
      RouteSurface(&Map, &Time, TopoMap, SoilMap, &Options,
        UnitHydrograph, &HydrographInfo, Hydrograph,
        &Dump, VegMap, VType, &ChannelData);

#endif

    if (NGraphics > 0)
      draw(&(Time.Current), IsEqualTime(&(Time.Current), &(Time.Start)),
	   Time.DayStep, &Map, NGraphics, which_graphics, VType,
	   SType, SnowMap, SoilMap, VegMap, TopoMap, PrecipMap,
	   PrismMap, SkyViewMap, ShadowMap, EvapMap, RadiationMap, 
	   MetMap, Network, &Options);
    
    Aggregate(&Map, &Options, TopoMap, &Soil, &Veg, VegMap, EvapMap, PrecipMap,
	      RadiationMap, SnowMap, SoilMap, &Total, VType, Network, &ChannelData, &roadarea);
    
    MassBalance(&(Time.Current), &(Time.Start), &(Dump.Balance), &Total, &Mass);

    ExecDump(&Map, &(Time.Current), &(Time.Start), &Options, &Dump, TopoMap,
	     EvapMap, RadiationMap, PrecipMap, SnowMap, MetMap, VegMap, &Veg, 
		 SoilMap, Network, &ChannelData, &Soil, &Total, &HydrographInfo,Hydrograph);
	
    IncreaseTime(&Time);
	t += 1;
  }

  ExecDump(&Map, &(Time.Current), &(Time.Start), &Options, &Dump, TopoMap,
	   EvapMap, RadiationMap, PrecipMap, SnowMap, MetMap, VegMap, &Veg, SoilMap,
	   Network, &ChannelData, &Soil, &Total, &HydrographInfo, Hydrograph);

  FinalMassBalance(&(Dump.FinalBalance), &Total, &Mass);

  printf("\nEND OF MODEL RUN\n\n");

  /* record the run time at the end of each time loop */
  finish1 = clock ();
  runtime = (finish1-start)/CLOCKS_PER_SEC;
  printf("***********************************************************************************");
  printf("\nRuntime Summary:\n");
  printf("%6.2f hours elapsed for the simulation period of %d hours (%.1f days) \n", 
	  runtime/3600, t*Time.Dt/3600, (float)t*Time.Dt/3600/24);

  return EXIT_SUCCESS;
}
Exemple #20
0
/*******************************************************************************
  Function name: InitPixDump()

  Purpose      : Initialize the pixel dumps.  This information is in the
         [OUTPUT] section of the input file

  Required     :
    LISTPTR Input         - Linked list with input strings
    MAPSIZE *Map          - Information about basin extent
    uchar **BasinMask     - Basin mask
    char *Path            - Directory to write output to
    int NPix              - Number of pixels to dump
    PIXDUMP **Pix         - Array of pixels to dump

  Returns      : number of accepted dump pixels (i.e. in the mask, etc)

  Modifies     : NPix and its members

  Comments     :
*******************************************************************************/
int InitPixDump(LISTPTR Input, MAPSIZE *Map, uchar **BasinMask, char *Path,
  int NPix, PIXDUMP **Pix, OPTIONSTRUCT *Options)
{
  char *Routine = "InitPixDump";
  char Str[BUFSIZE + 1];
  double North;
  double East;
  int i;			/* counter */
  int j;
  int ok;
  char temp_name[BUFSIZE + 1];
  char KeyName[name + 1][BUFSIZE + 1];
  char *KeyStr[] = {
    "NORTH COORDINATE",
    "EAST COORDINATE",
    "NAME"
  };
  char *SectionName = "OUTPUT";
  char VarStr[name + 1][BUFSIZE + 1];

  ok = 0;

  if (!(*Pix = (PIXDUMP *)calloc(NPix, sizeof(PIXDUMP))))
    ReportError(Routine, 1);

  for (i = 0; i < NPix; i++) {

    /* Read the key-entry pairs from the input file */
    for (j = 0; j <= name; j++) {
      sprintf(KeyName[j], "%s %d", KeyStr[j], i + 1);
      GetInitString(SectionName, KeyName[j], "", VarStr[j],
        (unsigned long)BUFSIZE, Input);
    }

    /* Assign the entries to the appropriate variables */
    if (!CopyDouble(&North, VarStr[north], 1))
      ReportError(KeyName[north], 51);

    if (!CopyDouble(&East, VarStr[east], 1))
      ReportError(KeyName[east], 51);

    if (IsEmptyStr(VarStr[name]))
      ReportError(KeyName[name], 51);
    strcpy(temp_name, VarStr[name]);

    /* Convert map coordinates to matrix coordinates */
    (*Pix)[i].Loc.N = Round(((Map->Yorig - 0.5 * Map->DY) - North) / Map->DY);
    (*Pix)[i].Loc.E = Round((East - (Map->Xorig + 0.5 * Map->DX)) / Map->DX);

    if (!InArea(Map, &((*Pix)[i].Loc)) ||
      !INBASIN(BasinMask[(*Pix)[i].Loc.N][(*Pix)[i].Loc.E])) {
      printf("Ignoring dump command for pixel named %s \n", temp_name);
    }
    else {
      printf("Accepting dump command for pixel named %s \n", temp_name);
      sprintf(Str, "%s", temp_name);
      sprintf((*Pix)[ok].OutFile.FileName, "%sPixel.%s", Path, Str);
      (*Pix)[ok].Loc.N = (*Pix)[i].Loc.N;
      (*Pix)[ok].Loc.E = (*Pix)[i].Loc.E;
      OpenFile(&((*Pix)[ok].OutFile.FilePtr), (*Pix)[ok].OutFile.FileName, "w", TRUE);
      ok++;
    }
  }
  return ok;
}
Exemple #21
0
/*****************************************************************************
  Function name: InitModelState()

  Purpose      : Initialize the state of the model using initial conditions
                 or a saved state from an earlier model run

  Required     :

  Returns      : void

  Modifies     :

  Comments : 
    Initialize the model state, by reading the state variables from a series
    of files.  This allows restarts of the model from any timestep for which
    the model state is known.  These model states can be stored using the
    routine StoreModelState().  Timesteps at which to dump the model state
    can be specified in the file with dump information.

*****************************************************************************/
void InitModelState(DATE * Start, MAPSIZE * Map, OPTIONSTRUCT * Options,
		    PRECIPPIX ** PrecipMap, SNOWPIX ** SnowMap,
		    SOILPIX ** SoilMap, LAYER Soil, SOILTABLE * SType,
		    VEGCHEMPIX ** VegChemMap, LAYER Veg, VEGTABLE * VType, char *Path,
		    SNOWTABLE * SnowAlbedo, TOPOPIX ** TopoMap,
		    ROADSTRUCT ** Network, UNITHYDRINFO * HydrographInfo,
		    float *Hydrograph)
{
  const char *Routine = "InitModelState";
  char Str[NAMESIZE + 1];
  char FileName[NAMESIZE + 1];
  FILE *HydroStateFile;
  int i;			/* counter */
  int x;			/* counter */
  int y;			/* counter */
  int NSet;			/* Number of dataset to be read */
  int NSoil;			/* Number of soil layers for current pixel */
  int NVeg;			/* Number of veg layers for current pixel */
  void *Array;
  MAPDUMP DMap;			/* Dump Info */
  float remove;

 
  /* Restore canopy interception */

  NSet = 0;

  if (DEBUG)
    printf("Restoring canopy conditions\n");

  sprintf(Str, "%02d.%02d.%02d.%02d.%02d.%02d", Start->Month, Start->Day,
	  Start->Year, Start->Hour, Start->Min, Start->Sec);

  printf("Reading %sInterception.State.%s%s...\n",Path, Str, fileext);
  sprintf(FileName, "%sInterception.State.%s%s", Path, Str, fileext);

  DMap.ID = 202;
  DMap.Layer = 0;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);
  if (!(Array = calloc(Map->NY * Map->NX, SizeOfNumberType(DMap.NumberType))))
    ReportError((char *) Routine, 1);

  for (i = 0; i < Veg.MaxLayers; i++) {

    DMap.ID = 202;
    DMap.Layer = i;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);

    Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,
		 DMap.Name);

    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {
	  PrecipMap[y][x].IntRain[i] = 0.0;
	  NVeg = Veg.NLayers[(VegChemMap[y][x].Veg - 1)];
	  if (i < NVeg) {
	    PrecipMap[y][x].IntRain[i] = ((float *) Array)[y * Map->NX + x];
	    if (PrecipMap[y][x].IntRain[i] < 0.0) {
	      fprintf(stderr, "InitModelState at (x, y) is (%d, %d):\n", x, y);
	      fprintf(stderr,
		      "\tRain interception negative on layer %d of max %d ... reset to 0\n",
		      i, Veg.MaxLayers);
	      PrecipMap[y][x].IntRain[i] = 0.0;
	    }
	  }
	}
      }
    }
  }

  for (i = 0; i < Veg.MaxLayers; i++) {

    DMap.ID = 203;
    DMap.Layer = i;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);

    Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,DMap.Name);

    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {
	  PrecipMap[y][x].IntSnow[i] = 0.0;
	  NVeg = Veg.NLayers[(VegChemMap[y][x].Veg - 1)];
	  if (i < NVeg) {
	    PrecipMap[y][x].IntSnow[i] = ((float *) Array)[y * Map->NX + x];
	    if (PrecipMap[y][x].IntSnow[i] < 0.0) {
	      fprintf(stderr, "InitModelState at (x, y) is (%d, %d):\n", x, y);
	      fprintf(stderr,"Snow interception negative on layer %d of max %d ... reset to 0\n",i, Veg.MaxLayers);
	      PrecipMap[y][x].IntSnow[i] = 0.0;
	    }
	  }
	}
      }
    }
  }

  DMap.ID = 204;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);

  Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,DMap.Name);
  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	PrecipMap[y][x].TempIntStorage = ((float *) Array)[y * Map->NX + x];
	if (PrecipMap[y][x].TempIntStorage < 0.0) {
	  fprintf(stderr, "InitModelState at (x, y) is (%d, %d):\n", x, y);
	  fprintf(stderr,
		  "Total intercepted precipitation negative on layer %d of max %d ... reset to 0\n",
		  i, Veg.MaxLayers);
	  PrecipMap[y][x].TempIntStorage = 0.0;
	}
      }
    }
  }

  free(Array);

  /* Restore snow pack conditions */

  NSet = 0;

  if (DEBUG)
    printf("Restoring snow pack conditions\n");

  printf("Reading %sSnow.State.%s%s...\n",Path, Str, fileext);
  sprintf(FileName, "%sSnow.State.%s%s", Path, Str, fileext);

  DMap.ID = 401;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);

  if (!(Array = (float *) calloc(Map->NY * Map->NX,
				 SizeOfNumberType(DMap.NumberType))))
    ReportError((char *) Routine, 1);

  Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,
	       DMap.Name);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	SnowMap[y][x].HasSnow =
	  (unsigned char) ((float *) Array)[y * Map->NX + x];
      }
    }
  }

  DMap.ID = 403;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);

  Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,
	       DMap.Name);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	SnowMap[y][x].LastSnow =
	  (unsigned short) ((float *) Array)[y * Map->NX + x];
      }
    }
  }

  DMap.ID = 404;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);

  Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,
	       DMap.Name);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	SnowMap[y][x].Swq = ((float *) Array)[y * Map->NX + x];
	//if ( SnowMap[y][x].Swq > 100 ) SnowMap[y][x].Swq = 100;
      }
    }
  }

  DMap.ID = 406;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);

  Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,
	       DMap.Name);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	SnowMap[y][x].PackWater = ((float *) Array)[y * Map->NX + x];
      }
    }
  }

  DMap.ID = 407;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);

  Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,
	       DMap.Name);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	SnowMap[y][x].TPack = ((float *) Array)[y * Map->NX + x];
      }
    }
  }

  DMap.ID = 408;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);

  Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,
	       DMap.Name);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	SnowMap[y][x].SurfWater = ((float *) Array)[y * Map->NX + x];
      }
    }
  }

  DMap.ID = 409;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);

  Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,
	       DMap.Name);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	SnowMap[y][x].TSurf = ((float *) Array)[y * Map->NX + x];
      }
    }
  }

  DMap.ID = 410;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);

  Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,
	       DMap.Name);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	SnowMap[y][x].ColdContent = ((float *) Array)[y * Map->NX + x];
      }
    }
  }
	free(Array);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	if (SnowMap[y][x].HasSnow) {
	  SnowMap[y][x].Albedo = CalcSnowAlbedo(SnowMap[y][x].TSurf,
						SnowMap[y][x].LastSnow,
						SnowAlbedo);
	} else {
	  SnowMap[y][x].Albedo = 0;
	}
	SnowMap[y][x].ShearStress = 0.0;
	SnowMap[y][x].IceA = 0.0;
	SnowMap[y][x].IceFlux = 0.0;
	SnowMap[y][x].IceVelocity = 0.0;
      } else {
        SnowMap[y][x].ShearStress = NA;
	SnowMap[y][x].IceA = NA;
	SnowMap[y][x].IceFlux = NA;
	SnowMap[y][x].Albedo = NA;
	SnowMap[y][x].IceVelocity = NA;
      }
    }
  }

  /* Restore soil conditions */

  NSet = 0;

  printf("Reading %sSoil.State.%s%s...\n",Path, Str, fileext);
  sprintf(FileName, "%sSoil.State.%s%s", Path, Str, fileext);

  DMap.ID = 501;
  DMap.Layer = 0;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);

  if (!(Array = (float *) calloc(Map->NY * Map->NX,
				 SizeOfNumberType(DMap.NumberType))))
    ReportError((char *) Routine, 1);

  for (i = 0; i < Soil.MaxLayers + 1; i++) {

    DMap.ID = 501;
    DMap.Layer = i;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);

    Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,DMap.Name);
    for (y = 0; y < Map->NY; y++) {
		for (x = 0; x < Map->NX; x++) {
			if (INBASIN(TopoMap[y][x].Mask)) {
				NSoil = Soil.NLayers[(SoilMap[y][x].Soil - 1)];
				if (i <= NSoil) {			 
				SoilMap[y][x].Moist_m_m[i] = ((float *) Array)[y * Map->NX + x];
				if (SoilMap[y][x].Moist_m_m[i] < 0.0) {
					fprintf(stderr, "InitModelState at (x, y) is (%d, %d):\n", x, y);
					fprintf(stderr,"Soil moisture negative in layer %d of max %d ... reset to 0, was %f\n",
						i, Soil.MaxLayers, SoilMap[y][x].Moist_m_m[i]);
				SoilMap[y][x].Moist_m_m[i] = 0.0;
				}
				}
		/* this appears to be redundant - value also set by init-state file jsb 3/4/09
	  if (i == NSoil) {
	    if (SoilMap[y][x].Moist_m_m[i] < SType[SoilMap[y][x].Soil - 1].FCap[NSoil - 1]) 
	      SoilMap[y][x].Moist_m_m[i] = SType[SoilMap[y][x].Soil - 1].FCap[NSoil - 1];
	    
	  }
	  if (i < NSoil) {
	    if (SoilMap[y][x].Moist_m_m[i] <SType[SoilMap[y][x].Soil - 1].WP[NSoil - 1]) {
	      SoilMap[y][x].Moist_m_m[i] = SType[SoilMap[y][x].Soil - 1].WP[NSoil - 1];
	    }
	  }*/
	}
      }
    }
  }

  DMap.ID = 505;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);

  Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,
	       DMap.Name);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	SoilMap[y][x].TSurf = ((float *) Array)[y * Map->NX + x];
      }
    }
  }

  for (i = 0; i < Soil.MaxLayers; i++) {

    DMap.ID = 511;
    DMap.Layer = i;
    DMap.Resolution = MAP_OUTPUT;
    strcpy(DMap.FileName, "");
    GetVarAttr(&DMap);

    Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,
		 DMap.Name);
    printf("Reading Soil Temperature State[%d]\n",i);
    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {
	  NSoil = Soil.NLayers[(SoilMap[y][x].Soil - 1)];
	  if (i < NSoil)
	    SoilMap[y][x].Temp[i] = ((float *) Array)[y * Map->NX + x];
	}
      }
    }
  }

  DMap.ID = 510;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);

  Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,
	       DMap.Name);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	SoilMap[y][x].Qst = ((float *) Array)[y * Map->NX + x];
      }
    }
  }

  DMap.ID = 512;
  DMap.Resolution = MAP_OUTPUT;
  strcpy(DMap.FileName, "");
  GetVarAttr(&DMap);

  Read2DMatrix(FileName, Array, DMap.NumberType, Map->NY, Map->NX, NSet++,
	       DMap.Name);

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {
      if (INBASIN(TopoMap[y][x].Mask)) {
	SoilMap[y][x].Runoff_m = ((float *) Array)[y * Map->NX + x];
	//DISABLEDTEST: BURPTEST((SoilMap[y][x].Runoff_m<1),"( SoilMap[y][x].Runoff_m <1)");
      }
    }
  }
  free(Array);

  /* Calculate the water table depth at each point based on the soil 
     moisture profile. Give an error message if the water ponds on the
     surface since that should not be allowed at this point */
  remove = 0.0;

  for (y = 0; y < Map->NY; y++) {
    for (x = 0; x < Map->NX; x++) {

      /* SatFlow_m needs to be initialized properly in the future.  For now it 
         will just be set to zero here */
      SoilMap[y][x].SatFlow_m = 0.0;
      if (INBASIN(TopoMap[y][x].Mask)) {
	if ((SoilMap[y][x].TableDepth_m =
		WaterTableDepth((Soil.NLayers[SoilMap[y][x].Soil - 1]),SoilMap[y][x].Depth,VType[VegChemMap[y][x].Veg - 1].RootDepth_m,
		SType[SoilMap[y][x].Soil - 1].Porosity, SType[SoilMap[y][x].Soil - 1].FCap,Network[y][x].Adjust, SoilMap[y][x].Moist_m_m))< 0.0){ 
			remove -= SoilMap[y][x].TableDepth_m * Map->DX * Map->DY;
			SoilMap[y][x].TableDepth_m = 0.0;
		}
      }
      else SoilMap[y][x].TableDepth_m = 0;
      
    }
  }
  if (remove > 0.0) {
    printf("WARNING:excess water in soil profile is %f m^3 \n", remove);
    printf("Expect possible large flood wave during first timesteps \n");
  }

  /* If the unit hydrograph is used for flow routing, initialize the unit 
     hydrograph array */

  if (Options->Extent == BASIN && Options->HasNetwork == FALSE) {
    sprintf(FileName, "%sHydrograph.State.%s", Path, Str);
    OpenFile(&HydroStateFile, FileName, "r", FALSE);
    for (i = 0; i < HydrographInfo->TotalWaveLength; i++)
		fscanf(HydroStateFile, "%f\n", &(Hydrograph[i]));
    fclose(HydroStateFile);
  }
}
Exemple #22
0
void main_gl(MAPSIZE *Map, TOPOPIX **TopoMap, SNOWPIX **Snow, GLPIX **GlacierMap, double dt_year, double year_min, double year_max,DATE *Current, DUMPSTRUCT *Dump,OPTIONSTRUCT * Options)
{
 
  FILE   *f_out1, *f_out2 ;
  double  *b, *s_init, *s_out, *swecc, *iwecc, *h_old,*hcc, *b_dot, *s_initcc; 
  double  dt_yr;
  double  yr_min;
  double  yr_max;
  float gl_cov,wsh_gl_cov;
  float sn_cov, sn_cov_gl;
  float  wsh_sn_cov,wsh_sn_cov_gl,wsh_mask;
  float h_max;
  int  k;
  int x;
  int y;
  char file_out1[150];
  char file_out2[150];
  float *Array1;
  int n_mask;
  float gl_vol;


    
  extern double  RHO;     
  extern double  A_GLEN ;
  extern double  n_GLEN;
  extern double  C_SLIDE;
  extern double  m_SLIDE;
  extern double  A_tilde;
  extern double  C_tilde;
  extern double g;
  extern double dx;
  extern int N;
  extern double  nm_half;
  extern double  np1;
  extern double  mm_half;
  extern double  m1; 
  
  
  // h      = malloc(N*sizeof(double));         // ice thickness (vectorized)
  b      = malloc(N*sizeof(double));         // bed surface elevation (vectorized)
  s_init = malloc(N*sizeof(double));         // initial ice surface elevation (vectorized)
  s_out  = malloc(N*sizeof(double));         // output ice surface elevation (vectorized)
        
  b_dot      = malloc(N*sizeof(double));
  swecc      = malloc(N*sizeof(double));
  iwecc      = malloc(N*sizeof(double));
  h_old      = malloc(N*sizeof(double));
  hcc      = malloc(N*sizeof(double));
  s_initcc = malloc(N*sizeof(double));
  // Array  = malloc(N*sizeof(float));
  if (!(Array1 = (float *) calloc(Map->NX * Map->NY, sizeof(float))));
  dt_yr = dt_year;
 
  yr_min = year_min;
  yr_max =  year_max;
  k = 0;
  nm_half = (n_GLEN-1)/2;
  np1     = n_GLEN+1;
  mm_half = (m_SLIDE-1)/2;
  m1      = m_SLIDE;
  n_mask = 0;
  gl_cov = 0;
  sn_cov=sn_cov_gl= 0;
  h_max = 0;
  gl_cov = 0;
  gl_vol = 0;
  wsh_gl_cov = 0;
  sn_cov= 0;
  h_max = 0;
  wsh_sn_cov= wsh_sn_cov_gl=0;
  wsh_mask = 0;
   for (x = 0; x < Map->NX; x++) {
     for (y = 0; y < Map->NY; y++) {
       k    = x*Map->NY + y;
       if (INBASIN(TopoMap[y][x].Mask)){

	 swecc[k] = (double)Snow[y][x].Swq - (double)Snow[y][x].sweold;  //change in swe in previous month
	 Snow[y][x].sweold = Snow[y][x].Swq;
	 iwecc[k] = (double)Snow[y][x].Iwq - (double)Snow[y][x].iweold;  // change in iwe in previous month
	 

	 b_dot[k] = iwecc[k];    //mass gain or loss of glacier layer used in dynamics
	 GlacierMap[y][x].Mbal = iwecc[k]+swecc[k];
	 GlacierMap[y][x].totmbal =  GlacierMap[y][x].Mbal + GlacierMap[y][x].totmbal; 
	 b[k] = GlacierMap[y][x].b;
	 s_initcc[k] = GlacierMap[y][x].s_init + b_dot[k]; // change in surface topography due to mass balance
	 if(s_initcc[k] <= b[k])
	   s_initcc[k] = b[k];
	 h_old[k] = s_initcc[k] - b[k];
	 s_init[k] =  GlacierMap[y][x].s_init;
	 if (Options->Glacier == GLSTATIC)
	   GlacierMap[y][x].s_out = GlacierMap[y][x].s_init;
	 
	 
       }
       else {
	 //b_dot[k] = -20;
	 b[k] = GlacierMap[y][x].b;
	 h_old[k]= 0.0;
	 s_init[k] =  b[k];
	 //printf("h_old= %f", h_old[k]);
       }
	    
     }
   }
   if (Options->Glacier == GLDYNAMIC)
     {
       printf("Glacier Model monthly run (Dynamic)\n");
       A_tilde = 2*A_GLEN*pow(RHO*g,n_GLEN)/((n_GLEN+2)*pow(dx,2));
       C_tilde = C_SLIDE*pow(RHO*g,m_SLIDE)/pow(dx,2);
       SetupIndexArrays();
       RunGlacier(b, s_init, s_out, yr_min, yr_max, dt_yr, b_dot, Options); 
     }
   
   
   for (x = 0; x < Map->NX; x++) {
     for (y = 0; y < Map->NY; y++) {
       if (INBASIN(TopoMap[y][x].Mask)){ 
	 if (Options->Glacier == GLDYNAMIC)
     {
	 k    = x*Map->NY + y;
	 GlacierMap[y][x].s_init = s_out[k];
	 GlacierMap[y][x].s_out = s_out[k];
	 GlacierMap[y][x].h = GlacierMap[y][x].s_out - GlacierMap[y][x].b;
	 hcc[k] = GlacierMap[y][x].h - h_old[k]; //change in ice thickness due to glacier movement
	 /*Update Glacier Ice Base on Ice Flow Only (Surface Balance Change Already Accounted for)*/
	 Snow[y][x].Iwq =  Snow[y][x].Iwq + (hcc[k] * (900./1000.)); 
	 }
	 if(GlacierMap[y][x].GlMask>=1){
	   Snow[y][x].Iwq = Snow[y][x].Iwq;
	   Snow[y][x].iweold = Snow[y][x].Iwq;
	   
	 }
	 	 
	 else
	   {
     /*The following was added to not allow glaciers to exist outside of Glacier Mask*/
     /*Do to unavoidable inaccuracies in model inputs, in some cases small glaciers */
     /*sometime grow outside of the historical glacier footprint, since they do not contribute to runoff*/
     /*but would erroneously contribute in a future warmer climate they are deleted to avoid error*/
     /*in future glacier contribution. The amount removed is tracked with the IceRemoved variable*/
	     Snow[y][x].IceRemoved += Snow[y][x].Iwq;
             Snow[y][x].Iwq = 0;
	     Snow[y][x].iweold = 0.0;
             b[k] = GlacierMap[y][x].b;
             h_old[k]= 0.0;
             s_init[k] =  b[k];


	   }
	 
	 if(Snow[y][x].Iwq < 0.00){
	   Snow[y][x].Iwq = 0;
	   Snow[y][x].iweold = 0.0;
	 }
	/*Only Inluding Pixels with more than 1 meter I.W.E. in extent calculation*/ 
         if(GlacierMap[y][x].GlMask>=1){
             n_mask += 1;
	     gl_vol += Snow[y][x].Iwq * dx * dx;
	   if(Snow[y][x].Iwq > 1.0)
	     gl_cov +=1;    
	 }
	 if(Snow[y][x].Iwq > 1.0 && GlacierMap[y][x].WshMask==1) 
	   wsh_gl_cov +=1; 
	 if(Snow[y][x].Swq > 0){  
	   sn_cov +=1;
	   if(Snow[y][x].Iwq > 1.0) 
	     sn_cov_gl +=1;
	 }
	 if(GlacierMap[y][x].WshMask==1 && Snow[y][x].Swq > 0){
	   wsh_sn_cov +=1;
	   if(Snow[y][x].Iwq > 1.0) 
	     wsh_sn_cov_gl +=1;
	 }
	 if(GlacierMap[y][x].WshMask==1)
	   wsh_mask +=1;
       }
       else {
	 
	 b[k] = GlacierMap[y][x].b;
	 h_old[k]= 0.0;
	 s_init[k] =  b[k];
         Snow[y][x].Iwq = 0;
	 Snow[y][x].iweold = 0.0;
       }
     }
   }

     
   

   /********************************OUTPUTS*****************************/
   sprintf(file_out2, "%sgl_sn_cov.txt", Dump->Path);
   if((f_out2=fopen(file_out2,"ab"))==NULL)
     {
       printf("main(): Cannot open output file %s\n", file_out2);
       exit(1);
     }

   
   
   //gl_cov = 100*gl_cov/(float)n_mask;
   //sn_cov = 100*sn_cov/(float)n_mask;
   //wsh_gl_cov = 100*wsh_gl_cov/wsh_mask;
   //wsh_sn_cov = 100*wsh_sn_cov/wsh_mask;
   //printf("Ice Extent (percent of initial) = %.3f percent\n", 100*gl_cov/(float)n_mask);
   printf("Watershed Snow-covered area      = %.3f percent\n", 100*wsh_sn_cov/wsh_mask);
   printf("Watershed glacier-covered area   = %.3f percent\n", 100*wsh_gl_cov/wsh_mask);

   fprintf(f_out2,"Ice-covered area (km^2)                                   = %04d %02d %02d %.3f\n",Current->Year,Current->Month,Current->Day, (gl_cov*dx*dx)/1000000);
   fprintf(f_out2, "Snow-covered area (km^2)                                = %04d %02d %02d %.3f\n", Current->Year,Current->Month,Current->Day,(sn_cov*dx*dx)/1000000);
   fprintf(f_out2, "Snow-covered area on glacier surfaces (km^2)            = %04d %02d %02d %.3f\n", Current->Year,Current->Month,Current->Day,(sn_cov_gl*dx*dx)/1000000);
   fprintf(f_out2, "Watershed Snow-covered (km^2)                           = %04d %02d %02d %.3f\n", Current->Year,Current->Month,Current->Day,(wsh_sn_cov*dx*dx)/1000000);
   fprintf(f_out2, "Watershed Snow-covered area on glacier surface (km^2)   = %04d %02d %02d %.3f\n", Current->Year,Current->Month,Current->Day,(wsh_sn_cov_gl*dx*dx)/1000000);
   fprintf(f_out2, "Watershed glacier-covered area (km^2)                   = %04d %02d %02d %.3f\n", Current->Year,Current->Month,Current->Day,(wsh_gl_cov*dx*dx)/1000000);

    fprintf(f_out2, "Glacier Volume                                         = %04d %02d %02d %.3f\n", Current->Year,Current->Month,Current->Day,gl_vol);

   
   sprintf(file_out1, "%sbalance_sum.bin", Dump->Path);


     if((f_out1=fopen(file_out1,"wb"))==NULL)
     {
       printf("main(): Cannot open output file %s\n", file_out1);
       exit(1);
     }
   
   for (x = 0; x < Map->NX; x++) {
     for (y = 0; y < Map->NY; y++){
       k    = x*Map->NY + y;
       //((float *) Array)[y * Map->NX + x] = b_dot[k];
       ((float *) Array1)[y * Map->NX + x] = GlacierMap[y][x].totmbal;
     }
   }
   fwrite(Array1, sizeof(Array1), Map->NY * Map->NX, f_out1);

   free(Array1);
   free(b);
   free(s_out);
   free(s_init);
   
   free(b_dot); 
   free(swecc);
   free(iwecc);
   free(hcc);
   free(h_old);
   free(s_initcc);
   fclose(f_out1);
   fclose(f_out2);
   printf("ALL DONE: %.2f yr integration\n", yr_max);
}
Exemple #23
0
float ElevationSlope(MAPSIZE *Map, TOPOPIX **TopoMap, FINEPIX ***FineMap, int y, int x, int *nexty, 
		     int *nextx, int prevy, int prevx, float *Aspect) 
{
  int n, direction;
  float soil_elev[NNEIGHBORS];
  float bedrock_elev[NNEIGHBORS];
  float Slope;
  float temp_slope[NNEIGHBORS];
  double length_diagonal;
  float dx, dy, celev;
  int coarsej, coarsei;

  /* fill neighbor array */
  
  for (n = 0; n < NNEIGHBORS; n++) {

    int xn = x + xneighbor[n];
    int yn = y + yneighbor[n];
   
    // Initialize soil_elev and bedrock_elev
    soil_elev[n] = (float) OUTSIDEBASIN;
    bedrock_elev[n] = (float) OUTSIDEBASIN;

    // Check whether yn, xn are within FineMap array bounds
    if (valid_cell_fine(Map,xn,yn)){

      coarsej = floor(yn*Map->DMASS/Map->DY);
      coarsei = floor(xn*Map->DMASS/Map->DX);

      // Check whether FineMap element has been allocated for this cell
      // (equivalent to checking whether parent coarse grid cell is within coarse mask)
      if (INBASIN(TopoMap[coarsej][coarsei].Mask)) { 

	bedrock_elev[n] = (((*FineMap[yn][xn]).Mask) ? (*FineMap[yn][xn]).bedrock : (float) OUTSIDEBASIN);
	soil_elev[n] = (((*FineMap[yn][xn]).Mask) ? (*FineMap[yn][xn]).bedrock+(*FineMap[yn][xn]).sediment : (float) OUTSIDEBASIN);
	
      }
    }
    
  }       
  /*  Find bedrock slope in all directions. Negative slope = ascent, positive slope = descent.  */     
  dx = Map->DMASS;
  dy = Map->DMASS;
  celev = (*FineMap[y][x]).bedrock;


  length_diagonal = sqrt((pow(dx, 2)) + (pow(dy, 2))); 

  for (n = 0; n < NNEIGHBORS; n++) {
    if (bedrock_elev[n] == OUTSIDEBASIN) 
      bedrock_elev[n] = DHSVM_HUGE;
    
    if(n==0 || n==2 || n==4 || n==6)
      temp_slope[n] = (atan((celev - bedrock_elev[n]) / length_diagonal))
	* DEGPRAD;
    else if(n==1 || n==5)
      temp_slope[n] = (atan((celev - bedrock_elev[n]) / dy)) * DEGPRAD;
    else
      temp_slope[n] = (atan((celev - bedrock_elev[n]) / dx)) * DEGPRAD;
  }
    
 /* Find largest (positive) slope, this is the direction of failure along bedrock plain.  
     Backtracking isn't a problem if using the bedrock, but sinks may exist. */ 
   
  Slope = -999.;
  *Aspect = -99.;

  for (n = 0; n < NNEIGHBORS; n++){
    if(temp_slope[n] > Slope) {
      Slope = temp_slope[n];
      *Aspect = temp_aspect[n] * PI / 180.0;
      direction = n;
      *nexty = y + yneighbor[n];
      *nextx = x + xneighbor[n];
    }
  }

  /* If no positive slope found, a bedrock sink was encountered.  Assuming the 
     sink should be filled to the lowest "pour elevation", aspect should have 
     already been assigned correctly. */

  /* Find dynamic slope in direction of steepest descent. */
  
  celev = (*FineMap[y][x]).bedrock + (*FineMap[y][x]).sediment;
  if(direction==0 || direction==2 || direction==4 || direction==6)
    Slope = (atan((celev - soil_elev[direction]) / length_diagonal))
      * DEGPRAD;
  else if(direction==1 || direction==5)
    Slope = (atan((celev - soil_elev[direction]) / dy)) * DEGPRAD;
  else
    Slope = (atan((celev - soil_elev[direction]) / dx)) * DEGPRAD;

  /* It is possible that a "soil" sink could be encountered at this point.  
     This is not really an error, and is checked for in MainMWM. */
  // if(Slope < 0.0 ) {
  // fprintf(stderr, "Sink encountered in cell y= %d x= %d, all routes from here go up!\n", y,x);
  // }

  if(Slope == -999. || *Aspect == -99.) {
    fprintf(stderr, "Aspect not assigned, this shouldn't have happened.\n");
    exit(0);
  }

  return Slope;
}
Exemple #24
0
/*****************************************************************************
  Function name: InitNewStep()

  Purpose      : Initialize Earth-Sun geometry and meteorological data at the
                 beginning of each timestep

  Required     :
    MAPSIZE Map              - Structure with information about location
    TIMESTRUCT Time          - Structure with time information
    int PrecipType           - Type of precipitation input, RADAR, STATION or
                               OROGRAPHIC
    int FlowGradient         - Type of FlowGradient calculation
    int NStats               - Number of meteorological stations
    METLOCATION *Stat        - Structure with information about the
                               meteorological stations in or near the study
                               area 
    char *RadarFileName      - Name of file with radar images
    MAPSIZE Radar            - Structure with information about the
                               precipitation radar coverage
    RADCLASSPIX **RadMap     - Structure with radiation data for each pixel
    RADARPIX **RadarMap      - Structure with precipitation information for
                               each radar pixel
    SOLARGEOMETRY *SolarGeo  - structure with information about Earth-Sun 
                               geometry
    SOILPIX **SoilMap        - structure with soil information
    float ***MM5Input        - MM5 input maps
    float ***WindModel       - Wind model maps
                           
  Returns      : void

  Modifies     :

  Comments     : To be executed at the beginning of each time step
*****************************************************************************/
void InitNewStep(INPUTFILES *InFiles, MAPSIZE *Map, TIMESTRUCT *Time,
		 int NSoilLayers, OPTIONSTRUCT *Options, int NStats,
		 METLOCATION *Stat, char *RadarFileName, MAPSIZE *Radar,
		 RADARPIX **RadarMap, SOLARGEOMETRY *SolarGeo, 
		 TOPOPIX **TopoMap, RADCLASSPIX **RadMap, SOILPIX **SoilMap,
		 float ***MM5Input, float ***WindModel, MAPSIZE *MM5Map)
{
  const char *Routine = "InitNewStep";
  int i;			/* counter */
  int j;			/* counter */
  int x;			/* counter */
  int y;			/* counter */
  int NumberType;		/* number type in MM5 input */
  int Step;			/* Step in the MM5 Input */
  float *Array = NULL;
  int MM5Y, MM5X;

  /* Calculate variables related to the position of the sun above the
     horizon, this is only necessary if shading is TRUE */

  SolarHour(SolarGeo->Latitude,
	    (Time->DayStep + 1) * ((float) Time->Dt) / SECPHOUR,
	    ((float) Time->Dt) / SECPHOUR, SolarGeo->NoonHour,
	    SolarGeo->Declination, SolarGeo->Sunrise, SolarGeo->Sunset,
	    SolarGeo->TimeAdjustment, SolarGeo->SunEarthDistance,
	    &(SolarGeo->SineSolarAltitude), &(SolarGeo->DayLight),
	    &(SolarGeo->SolarTimeStep), &(SolarGeo->SunMax),
	    &(SolarGeo->SolarAzimuth));

/*printf("SunMax is %f\n",SolarGeo->SunMax);*/
  if (Options->MM5 == TRUE) {

    /* Read the data from the MM5 files */

    if (!(Array = (float *) calloc(MM5Map->NY * MM5Map->NX, sizeof(float))))
      ReportError((char *) Routine, 1);
    NumberType = NC_FLOAT;

    Step = NumberOfSteps(&(Time->StartMM5), &(Time->Current), Time->Dt);

    Read2DMatrix(InFiles->MM5Temp, Array, NumberType, MM5Map->NY,
		 MM5Map->NX, Step);
    for (y = 0; y < Map->NY; y++)
      for (x = 0; x < Map->NX; x++) {
	MM5Y = (int) ((y + MM5Map->OffsetY) * Map->DY / MM5Map->DY);
	MM5X = (int) ((x - MM5Map->OffsetX) * Map->DX / MM5Map->DY);
	MM5Input[MM5_temperature - 1][y][x] = Array[MM5Y * MM5Map->NX + MM5X];
      }

    Read2DMatrix(InFiles->MM5Humidity, Array, NumberType, MM5Map->NY,
		 MM5Map->NX, Step);

    for (y = 0; y < Map->NY; y++)
      for (x = 0; x < Map->NX; x++) {
	MM5Y = (int) ((y + MM5Map->OffsetY) * Map->DY / MM5Map->DY);
	MM5X = (int) ((x - MM5Map->OffsetX) * Map->DX / MM5Map->DY);
	MM5Input[MM5_humidity - 1][y][x] = Array[MM5Y * MM5Map->NX + MM5X];
      }

    Read2DMatrix(InFiles->MM5Wind, Array, NumberType, MM5Map->NY,
		 MM5Map->NX, Step);
    for (y = 0; y < Map->NY; y++)
      for (x = 0; x < Map->NX; x++) {
	MM5Y = (int) ((y + MM5Map->OffsetY) * Map->DY / MM5Map->DY);
	MM5X = (int) ((x - MM5Map->OffsetX) * Map->DX / MM5Map->DY);
	MM5Input[MM5_wind - 1][y][x] = Array[MM5Y * MM5Map->NX + MM5X];
      }

    Read2DMatrix(InFiles->MM5ShortWave, Array, NumberType, MM5Map->NY,
		 MM5Map->NX, Step);
    for (y = 0; y < Map->NY; y++)
      for (x = 0; x < Map->NX; x++) {
	MM5Y = (int) ((y + MM5Map->OffsetY) * Map->DY / MM5Map->DY);
	MM5X = (int) ((x - MM5Map->OffsetX) * Map->DX / MM5Map->DY);
	MM5Input[MM5_shortwave - 1][y][x] = Array[MM5Y * MM5Map->NX + MM5X];
      }

    Read2DMatrix(InFiles->MM5LongWave, Array, NumberType, MM5Map->NY,
		 MM5Map->NX, Step);
    for (y = 0; y < Map->NY; y++)
      for (x = 0; x < Map->NX; x++) {
	MM5Y = (int) ((y + MM5Map->OffsetY) * Map->DY / MM5Map->DY);
	MM5X = (int) ((x - MM5Map->OffsetX) * Map->DX / MM5Map->DY);
	MM5Input[MM5_longwave - 1][y][x] = Array[MM5Y * MM5Map->NX + MM5X];
      }

    Read2DMatrix(InFiles->MM5Precipitation, Array, NumberType, MM5Map->NY,
		 MM5Map->NX, Step);
    for (y = 0; y < Map->NY; y++)
      for (x = 0; x < Map->NX; x++) {
	MM5Y = (int) ((y + MM5Map->OffsetY) * Map->DY / MM5Map->DY);
	MM5X = (int) ((x - MM5Map->OffsetX) * Map->DX / MM5Map->DY);
	MM5Input[MM5_precip - 1][y][x] = Array[MM5Y * MM5Map->NX + MM5X];
	if (MM5Input[MM5_precip - 1][y][x] < 0.0) {
	  printf("Warning: MM5 precip is less than zero %f\n",
		 MM5Input[MM5_precip - 1][y][x]);
	  MM5Input[MM5_precip - 1][y][x] = 0.0;
	}
      }
    Read2DMatrix(InFiles->MM5Terrain, Array, NumberType, MM5Map->NY,
		 MM5Map->NX, Step);
    for (y = 0; y < Map->NY; y++)
      for (x = 0; x < Map->NX; x++) {
	MM5Y = (int) ((y + MM5Map->OffsetY) * Map->DY / MM5Map->DY);
	MM5X = (int) ((x - MM5Map->OffsetX) * Map->DX / MM5Map->DY);
	MM5Input[MM5_terrain - 1][y][x] = Array[MM5Y * MM5Map->NX + MM5X];
      }
    Read2DMatrix(InFiles->MM5Lapse, Array, NumberType, MM5Map->NY,
		 MM5Map->NX, Step);
    for (y = 0; y < Map->NY; y++)
      for (x = 0; x < Map->NX; x++) {
	MM5Y = (int) ((y + MM5Map->OffsetY) * Map->DY / MM5Map->DY);
	MM5X = (int) ((x - MM5Map->OffsetX) * Map->DX / MM5Map->DY);
	MM5Input[MM5_lapse - 1][y][x] = Array[MM5Y * MM5Map->NX + MM5X];
      }

    if (Options->HeatFlux == TRUE) {

      for (i = 0, j = MM5_lapse; i < NSoilLayers; i++, j++) {
	Read2DMatrix(InFiles->MM5SoilTemp[i], Array, NumberType, MM5Map->NY,
		     MM5Map->NX, Step);
	for (y = 0; y < Map->NY; y++)
	  for (x = 0; x < Map->NX; x++) {
	    MM5Y = (int) ((y + MM5Map->OffsetY) * Map->DY / MM5Map->DY);
	    MM5X = (int) ((x - MM5Map->OffsetX) * Map->DX / MM5Map->DY);
	    MM5Input[j][y][x] = Array[MM5Y * MM5Map->NX + MM5X];
	  }
      }
    }
    free(Array);
  }
/*end if MM5*/

  /* if the flow gradient is based on the water table, recalculate the water
     table gradients.  Flow directions are now calculated in RouteSubSurface*/
  if (Options->FlowGradient == WATERTABLE) {
    /* Calculate the WaterLevel, i.e. the height of the water table above 
       some datum */
    for (y = 0; y < Map->NY; y++) {
      for (x = 0; x < Map->NX; x++) {
	if (INBASIN(TopoMap[y][x].Mask)) {
	  SoilMap[y][x].WaterLevel =
	    TopoMap[y][x].Dem - SoilMap[y][x].TableDepth;
	}
      }
    }
/*     HeadSlopeAspect(Map, TopoMap, SoilMap); */
  }

  if ((Options->MM5 == TRUE && Options->QPF == TRUE) || Options->MM5 == FALSE)
    GetMetData(Options, Time, NSoilLayers, NStats, SolarGeo->SunMax, Stat,
	       Radar, RadarMap, RadarFileName);
}