Ejemplo n.º 1
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);
  }
}
Ejemplo n.º 2
0
/*****************************************************************************
  Function name: MakeLocalMetData()

  Purpose      : Generates meteorological for each individual cell

  Required     :
    int y 
    int x
    MAPSIZE Map
    int DayStep
    unsigned char PrecipType
    int NStats
    METLOCATION *Stat
    uchar *MetWeights
    float LocalElev
    RADCLASSPIX *RadMap 
    PRECIPPIX *PrecipMap
    MAPSIZE Radar
    RADARPIX **RadarMap

  Returns      :
    PIXMET LocalMet

  Modifies     :

  Comments     :
    Reference: Shuttleworth, W.J., Evaporation,  In: Maidment, D. R. (ed.),
               Handbook of hydrology,  1993, McGraw-Hill, New York, etc..
*****************************************************************************/
PIXMET MakeLocalMetData(int y, int x, MAPSIZE * Map, int DayStep,
			OPTIONSTRUCT * Options, int NStats,
			METLOCATION * Stat, uchar * MetWeights,
			float LocalElev, RADCLASSPIX * RadMap,
			PRECIPPIX * PrecipMap, MAPSIZE * Radar,
			RADARPIX ** RadarMap, float **PrismMap,
			SNOWPIX * LocalSnow, SNOWTABLE * SnowAlbedo,
			float ***MM5Input, float ***WindModel,
			float **PrecipLapseMap, MET_MAP_PIX *** MetMap,
			int NGraphics, int Month, float skyview,
			unsigned char shadow, float SunMax,
			float SineSolarAltitude)
{
  float CurrentWeight;		/* weight for current station */
  float ScaleWind = 1;		/* Wind to be scaled by model factors if 
				   WindSource == MODEL */
  float Temp;			/* Temporary variable */
  float WeightSum;		/* sum of the weights */
  int i;			/* counter */
  int RadarX;			/* X coordinate of radar map coordinate */
  int RadarY;			/* Y coordinate of radar map coordinate */
  float TempLapseRate;
  int WindDirection = 0;	/* Direction of model wind */
  PIXMET LocalMet;		/* local met data */

  LocalMet.Tair = 0.0;
  LocalMet.Rh = 0.0;
  LocalMet.Wind = 0.0;
  LocalMet.Sin = 0.0;
  LocalMet.SinBeam = 0.0;
  LocalMet.SinDiffuse = 0.0;
  LocalMet.Lin = 0.0;
  TempLapseRate = 0.0;

  if (Options->MM5 == TRUE && Options->QPF == TRUE) {
    WeightSum = 0.0;
    for (i = 0; i < NStats; i++)
      WeightSum += (float) MetWeights[i];
  }

  if (Options->MM5 == TRUE) {
    LocalMet.Tair = MM5Input[MM5_temperature - 1][y][x] +
      (LocalElev - MM5Input[MM5_terrain - 1][y][x]) * MM5Input[MM5_lapse -
							       1][y][x];
    LocalMet.Rh = MM5Input[MM5_humidity - 1][y][x];
    LocalMet.Wind = MM5Input[MM5_wind - 1][y][x];
    LocalMet.Sin = MM5Input[MM5_shortwave - 1][y][x];

    if (Options->Shading == TRUE) {
      if (SunMax > 0.0) {
	SeparateRadiation(LocalMet.Sin, LocalMet.Sin / SunMax,
			  &(LocalMet.SinBeam), &(LocalMet.SinDiffuse));
      }
      else {
	/* if sun is below horizon, the force all shortwave to zero */
	LocalMet.Sin = 0.0;
	LocalMet.SinBeam = 0.0;
	LocalMet.SinDiffuse = 0.0;

      }
    }

    LocalMet.Lin = MM5Input[MM5_longwave - 1][y][x];
    LocalMet.Press = 101300.0;
    PrecipMap->Precip = MM5Input[MM5_precip - 1][y][x];
/*    if(LocalMet.Sin>0) {
    printf("LocalMet.Sin, LocalMet.Lin are: %f %f \n",LocalMet.Sin, LocalMet.Lin);
} */
  }
  else {			/* MM5 is false and we need to interpolate the basic met records */

    WeightSum = 0.0;
    for (i = 0; i < NStats; i++) {
      WeightSum += (float) MetWeights[i];
      if (Options->WindSource == MODEL && Stat[i].IsWindModelLocation) {
	ScaleWind = Stat[i].Data.Wind;
	WindDirection = Stat[i].Data.WindDirection;
      }
    }
    for (i = 0; i < NStats; i++) {
      CurrentWeight = ((float) MetWeights[i]) / WeightSum;
      LocalMet.Tair += CurrentWeight *
	LapseT(Stat[i].Data.Tair, Stat[i].Elev, LocalElev,
	       Stat[i].Data.TempLapse);
      LocalMet.Rh += CurrentWeight * Stat[i].Data.Rh;
      if (Options->WindSource == STATION)
	LocalMet.Wind += CurrentWeight * Stat[i].Data.Wind;
      LocalMet.Lin += CurrentWeight * Stat[i].Data.Lin;
      LocalMet.Sin += CurrentWeight * Stat[i].Data.Sin;
      if (Options->Shading == TRUE) {
	LocalMet.SinBeam += CurrentWeight * Stat[i].Data.SinBeamObs;
	LocalMet.SinDiffuse += CurrentWeight * Stat[i].Data.SinDiffuseObs;
      }
      TempLapseRate += CurrentWeight * Stat[i].Data.TempLapse;
    }
    if (Options->WindSource == MODEL)
      LocalMet.Wind = ScaleWind * WindModel[WindDirection - 1][y][x];

    if (Options->PrecipType == RADAR) {
      RadarY = (int) ((y + Radar->OffsetY) * Map->DY / Radar->DY);
      RadarX = (int) ((x - Radar->OffsetX) * Map->DX / Radar->DX);
      PrecipMap->Precip = RadarMap[RadarY][RadarX].Precip;
    }
    /* WORK IN PROGRESS, taken from old DHSVM version */
    /* Air pressure */
    /* In rare cases - i.e. when the lapse rate has a different sign for 
       different met stations - you can end up with a TemplapseRate of 0.0
       This will result in a crash, so a check was put in (Jul 28, 1997 - Bart
       Nijssen).  It is somewhat awkward to interpolate lapse rates anyway, so
       a better way of doing this would be welcome */
    if (TempLapseRate != 0.0) {
      Temp = 9.8067 / (TempLapseRate * 287.0);
      LocalMet.Press =
	101300. * pow(((288.0 - TempLapseRate * LocalElev) / 288.0), Temp);
    }
    else
      LocalMet.Press = 101300.;

  }				/* end of else MM5==TRUE, i.e. all basic met, except for precip */
  /* has been interpolated */

  /* Here is how the following section works */
  /* Arc-Info (through use of the hillshade command) will give */
  /* an output file that ranges from 0 to 255 (the shade factor) */
  /* These correspond to the reflectance of the direct beam radiation */
  /* for a given sun position (altitude and azimuth) taking */
  /* into account the slope and aspect and topographic shading */
  /* of the local pixel.  If we wanted to use this value directly */
  /* then the correction to the observed beam w.r.t. a horizontal plane */
  /* would be   actual = horizontal*shadefactor/255/sin(solar_altitude) */
  /* the sin(solar_altitude) is necessary to convert horizontal into the maximum */
  /* possible flux */

  /* We can either have DHSVM make the solar_altitude calculation, which */
  /* is not all that hard, but is prone to user error (e.g. GMT time shifts, etc) */
  /* or we can simply include the solar_altitude info in the shade_factor */
  /* the question is how do we include the sin(solar_altitude) while */
  /* keeping new_shade_factor = shadefactor/255/sin(solar_altitude) defined */
  /* as a unsigned character */
  /* Answer:  At sal = 5 degrees max_new_shadefactor = 11.47 */
  /* i.e. the actual flux normal to sal is 11.47*observed_horizontal_flux */
  /* if we adopt this 5 degree value as a cutoff, we can then be assured that */
  /*    0<=newshadefactor<=11.47      and then scale it between 0 and 255 */
  /* the final calculation becomes,  */
  /*       actual = horizontal*(float)shadefactor/255.0*11.47 or simply
     acutal = horizontal*(float)shadefactor/22.23191               */
  /* thus radiation increases from 0 to 11.47 times the observed value in */
  /* increments of 4.5 percent */
  /* a finer resolution than this would require a higher min angle or more memory */

  if (Options->Shading == TRUE) {
    LocalMet.SinBeam = LocalMet.Sin * (float) shadow / 22.23191;
    LocalMet.SinDiffuse *= skyview;
    if (LocalMet.SinBeam + LocalMet.SinDiffuse > SOLARCON)
      LocalMet.SinBeam = SOLARCON - LocalMet.SinDiffuse;
  }
  else {
    LocalMet.SinBeam = LocalMet.Sin;
    LocalMet.SinDiffuse = 0;
  }
  RadMap->Beam = LocalMet.SinBeam;
  RadMap->Diffuse = LocalMet.SinDiffuse;
  LocalMet.Sin = RadMap->Beam + RadMap->Diffuse;

  if (Options->QPF == TRUE || Options->MM5 == FALSE) {
    if (Options->PrecipType == STATION && Options->Prism == FALSE) {
      PrecipMap->Precip = 0.0;
      for (i = 0; i < NStats; i++) {
	CurrentWeight = ((float) MetWeights[i]) / WeightSum;
	if (Options->PrecipLapse == MAP)
	  PrecipMap->Precip += CurrentWeight *
	    LapsePrecip(Stat[i].Data.Precip, 0, 1, PrecipLapseMap[y][x]);
	else
	  PrecipMap->Precip += CurrentWeight *
	    LapsePrecip(Stat[i].Data.Precip, Stat[i].Elev, LocalElev,
			Stat[i].Data.PrecipLapse);
      }
    }
    else if (Options->PrecipType == STATION && Options->Prism == TRUE) {
      PrecipMap->Precip = 0.0;
      for (i = 0; i < NStats; i++) {
	CurrentWeight = ((float) MetWeights[i]) / WeightSum;
	/* this is the real prism interpolation */
	/* note that X = position from left  boundary, ie # of columns */
	/* note that Y = position from upper boundary, ie # of rows   */
	if (Options->Outside == FALSE)
	  PrecipMap->Precip +=
	    CurrentWeight * Stat[i].Data.Precip /
	    PrismMap[Stat[i].Loc.N][Stat[i].Loc.E] * PrismMap[y][x];
	else
	  PrecipMap->Precip +=
	    CurrentWeight * Stat[i].Data.Precip /
	    Stat[i].PrismPrecip[Month - 1] * PrismMap[y][x];
	if(PrismMap[y][x] < 0){
	  printf("negative PrismMap value in MakeLocalMetData.c\n");
	  exit(0);
	}
      }
    }
  }

  /* due to the nature of the interpolation scheme in DHSVM and the */
  /* interpolation scheme to handle the mess of different formats of met stations */
  /* in the PRISM project */
  /* relative humidities can be quite low when precip is occuring */
  /* at times this will results in PET being greater than precip */
  /* allow an option in DHSVM to override RH if Precip is occuring */

  if (Options->Rhoverride == TRUE) {
    if (PrecipMap->Precip > 0.0)
      LocalMet.Rh = 100.0;
  }

  /* Separate precipitation into rainfall and snowfall */
  if (PrecipMap->Precip > 0.0 && LocalMet.Tair < MAX_SNOW_TEMP) {
    if (LocalMet.Tair > MIN_RAIN_TEMP)
      PrecipMap->SnowFall = PrecipMap->Precip *
	(MAX_SNOW_TEMP - LocalMet.Tair) / (MAX_SNOW_TEMP - MIN_RAIN_TEMP);
    else
      PrecipMap->SnowFall = PrecipMap->Precip;
  }
  else
    PrecipMap->SnowFall = 0.0;

  PrecipMap->RainFall = PrecipMap->Precip - PrecipMap->SnowFall;

  /* Local heat of vaporization, Eq. 4.2.1, Shuttleworth (1993) */
  LocalMet.Lv = 2501000 - 2361 * LocalMet.Tair;

  /* Psychrometric constant */
  LocalMet.Gamma = CP * LocalMet.Press / (EPS * LocalMet.Lv);

  /* Saturated vapor pressure, Eq. 4.2.2, Shuttleworth (1993) */
  LocalMet.Es = SatVaporPressure(LocalMet.Tair);

  /* Slope of vapor pressure curve, Eq. 4.2.3, Shuttleworth (1993) */
  LocalMet.Slope = 4098.0 * LocalMet.Es /
    ((237.3 + LocalMet.Tair) * (237.3 + LocalMet.Tair));

  /* Actual vapor pressure */
  LocalMet.Eact = LocalMet.Es * (LocalMet.Rh / 100.);

  /* Vapor pressure deficit */
  LocalMet.Vpd = LocalMet.Es - LocalMet.Eact;

  /* Air density, Eq. 4.2.4 Shuttleworth (1993) */
  LocalMet.AirDens = 0.003486 * LocalMet.Press / (275 + LocalMet.Tair);

  if (LocalSnow->HasSnow) {
    if (PrecipMap->SnowFall > 0.0)
      LocalSnow->LastSnow = 0;
    else
      LocalSnow->LastSnow++;
    LocalSnow->Albedo = CalcSnowAlbedo(LocalSnow->TSurf, LocalSnow->LastSnow,
				       SnowAlbedo);
  }
  else
    LocalSnow->LastSnow = 0;

  if (NGraphics > 0) {

    (*MetMap)[y][x].accum_precip =
      (*MetMap)[y][x].accum_precip + PrecipMap->Precip;
    (*MetMap)[y][x].air_temp = LocalMet.Tair;
    (*MetMap)[y][x].wind_speed = LocalMet.Wind;
    (*MetMap)[y][x].humidity = LocalMet.Rh;
  }

  return LocalMet;
}