/***************************************************************************** ReadRadarMap() *****************************************************************************/ void ReadRadarMap(DATE * Current, DATE * StartRadar, int Dt, MAPSIZE * Radar, RADARPIX ** RadarMap, char *FileName) { const char *Routine = "ReadRadarMap"; int i; /* counter */ int x; /* counter */ int y; /* counter */ int RadarStep; /* Location of current timestep in radarfile */ int NumberType; /* number type */ void *Array; if (DEBUG) printf("Reading precipitation radar data from file: %s\n", FileName); NumberType = NC_FLOAT; if (!(Array = (float *) calloc(Radar->NY * Radar->NX, SizeOfNumberType(NumberType)))) ReportError((char *) Routine, 1); RadarStep = NumberOfSteps(StartRadar, Current, Dt); /* Read the precipitation */ Read2DMatrix(FileName, Array, NumberType, Radar->NY, Radar->NX, RadarStep); for (y = 0, i = 0; y < Radar->NY; y++) for (x = 0; x < Radar->NX; x++, i++) RadarMap[y][x].Precip = ((float *) Array)[i]; free(Array); }
/******************************************************************************* Function name: InitImageDump() Purpose : Initialize the image dumps. This information is in the [OUTPUT] section of the input file Required : LISTPTR Input - Linked list with input strings int Dt - Model timestep in seconds MAPSIZE *MapDump - Information about areal extent int MaxSoilLayers - Maximum number of soil layers int MaxVegLayers - Maximum number of vegetation layers char *Path - Directory to write output to int NMaps - Number of maps to dump int NImages - Number of images to dump MAPDUMP **DMap - Array of maps and images to dump Returns : void Modifies : Members of DMap Comments : InitImageDump must be preceded by a call to InitMapDump, since the necessary memory is allocated there *******************************************************************************/ void InitImageDump(LISTPTR Input, int Dt, MAPSIZE * Map, int MaxSoilLayers, int MaxVegLayers, char *Path, int NMaps, int NImages, MAPDUMP ** DMap) { char *Routine = "InitImageDump"; DATE End; /* End of low resolution map dump period */ DATE Start; /* Start of low resolution map dump period */ int i; /* counter */ int j; /* counter */ int Interval; /* Interval between low resolution map dumps */ int MaxLayers; /* Maximum number of layers allowed for this variable */ char KeyName[image_lower + 1][BUFSIZE + 1]; char *KeyStr[] = { "IMAGE VARIABLE", "IMAGE LAYER", "IMAGE START", "IMAGE END", "IMAGE INTERVAL", "IMAGE UPPER LIMIT", "IMAGE LOWER LIMIT" }; char *SectionName = "OUTPUT"; char VarStr[image_lower + 1][BUFSIZE + 1]; float tmpInterval; for (i = NMaps - NImages; i < NMaps; i++) { /* Read the key-entry pairs from the input file */ for (j = 0; j <= image_lower; j++) { sprintf(KeyName[j], "%s %d", KeyStr[j], i - (NMaps - NImages) + 1); GetInitString(SectionName, KeyName[j], "", VarStr[j], (unsigned long)BUFSIZE, Input); } /* Assign the entries to the appropriate variables */ if (!CopyInt(&((*DMap)[i].ID), VarStr[image_variable], 1)) ReportError(KeyName[image_variable], 51); if (!IsValidID((*DMap)[i].ID)) ReportError("Input Options File", 19); if (IsMultiLayer((*DMap)[i].ID)) { MaxLayers = GetVarNLayers((*DMap)[i].ID, MaxSoilLayers, MaxVegLayers); if (!CopyInt(&((*DMap)[i].Layer), VarStr[image_layer], 1)) ReportError(KeyName[image_layer], 51); if ((*DMap)[i].Layer < 1 || (*DMap)[i].Layer > MaxLayers) ReportError("Input Options File", 20); } else (*DMap)[i].Layer = 1; (*DMap)[i].Resolution = IMAGE_OUTPUT; strncpy((*DMap)[i].FileName, Path, BUFSIZE); GetVarAttr(&((*DMap)[i])); (*DMap)[i].NumberType = NC_BYTE; strcpy((*DMap)[i].Format, "%d"); CreateMapFile((*DMap)[i].FileName, (*DMap)[i].FileLabel, Map); if (!SScanDate(VarStr[image_start], &Start)) ReportError(KeyName[image_start], 51); if (!SScanDate(VarStr[image_end], &End)) ReportError(KeyName[image_end], 51); if (!CopyFloat(&tmpInterval, VarStr[image_interval], 1)) ReportError(KeyName[image_interval], 51); Interval = SECPHOUR * tmpInterval; if (Interval % Dt != 0 || Interval <= 0) ReportError("Input Options File", 24); if (((*DMap)[i].N = NumberOfSteps(&Start, &End, Interval)) < 1) ReportError("Input Options File", 25); if (!((*DMap)[i].DumpDate = (DATE *)calloc((*DMap)[i].N, sizeof(DATE)))) ReportError(Routine, 1); CopyDate(&((*DMap)[i].DumpDate[0]), &Start); for (j = 1; j < (*DMap)[i].N; j++) (*DMap)[i].DumpDate[j] = NextDate(&((*DMap)[i].DumpDate[j - 1]), Interval); if (!CopyFloat(&((*DMap)[i].MaxVal), VarStr[image_upper], 1)) ReportError(KeyName[image_upper], 51); if (!CopyFloat(&((*DMap)[i].MinVal), VarStr[image_lower], 1)) ReportError(KeyName[image_lower], 51); } }
int InitTime(TIMESTRUCT * Time, DATE * Start, DATE * End, DATE * StartRadar, DATE * StartMM5, int Dt) { const char *Routine = "InitTime"; int tmpsecond; Time->Dt = Dt; /* timestep in seconds */ /* Just to be sure, recalculate the Julian and JDay fields of all the dates */ if (Start != NULL) { CopyDate(&(Time->Start), Start); Time->Start.JDay = DayOfYear(Time->Start.Year, Time->Start.Month, Time->Start.Day); Time->Start.Julian = GregorianToJulianDay(Time->Start.Year, Time->Start.Month, Time->Start.Day, Time->Start.Hour, Time->Start.Min, Time->Start.Sec); CopyDate(&(Time->Current), &(Time->Start)); } if (End != NULL) { CopyDate(&(Time->End), End); Time->End.JDay = DayOfYear(Time->End.Year, Time->End.Month, Time->End.Day); Time->End.Julian = GregorianToJulianDay(Time->End.Year, Time->End.Month, Time->End.Day, Time->End.Hour, Time->End.Min, Time->End.Sec); } if (StartRadar != NULL) { CopyDate(&(Time->StartRadar), StartRadar); Time->StartRadar.JDay = DayOfYear(Time->StartRadar.Year, Time->StartRadar.Month, Time->StartRadar.Day); Time->StartRadar.Julian = GregorianToJulianDay(Time->StartRadar.Year, Time->StartRadar.Month, Time->StartRadar.Day, Time->StartRadar.Hour, Time->StartRadar.Min, Time->StartRadar.Sec); } if (StartMM5 != NULL) { CopyDate(&(Time->StartMM5), StartMM5); Time->StartMM5.JDay = DayOfYear(Time->StartMM5.Year, Time->StartMM5.Month, Time->StartMM5.Day); Time->StartMM5.Julian = GregorianToJulianDay(Time->StartMM5.Year, Time->StartMM5.Month, Time->StartMM5.Day, Time->StartMM5.Hour, Time->StartMM5.Min, Time->StartMM5.Sec); } if (Start != NULL && End != NULL) { if (After(&(Time->Start), &(Time->End))) return FALSE; Time->Step = 0; Time->NDaySteps = SECPDAY / Time->Dt; if ((SECPDAY - Time->NDaySteps * Time->Dt) != 0) ReportError((char *) Routine, 7); /* the 0.5 in the next line is because Julian day is measured from midday, and we want since midnight */ tmpsecond = Round(((Time->Start.Julian - 0.5) - floor(Time->Start.Julian - 0.5)) * SECPDAY); Time->DayStep = tmpsecond / Time->Dt; /* The following line insures that the first timestep of the day would coincide with midnight */ if (tmpsecond - Time->DayStep * Time->Dt != 0) ReportError((char *) Routine, 9); Time->NTotalSteps = NumberOfSteps(&(Time->Start), &(Time->End), Time->Dt); if (Time->NTotalSteps == FAIL) return FALSE; } return TRUE; }
/***************************************************************************** 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); }