📄 initialize_atmos.c
字号:
#include <stdio.h>#include <stdlib.h>#include <vicNl.h>static char vcid[] = "$";void initialize_atmos(atmos_data_struct *atmos, dmy_struct *dmy, FILE **infile, double theta_l, double theta_s, double phi, double elevation, double annual_prec, double wind_h, double roughness, double avgJulyAirTemp, double *Tfactor,#if OUTPUT_FORCE char *AboveTreeLine, outfiles_struct *outfiles)#else /* OUTPUT_FORCE */ char *AboveTreeLine)#endif /* OUTPUT_FORCE *//********************************************************************** initialize_atmos Keith Cherkauer February 3, 1997 This routine initializes atmospheric variables for both the model time step, and the time step used by the snow algorithm (if different). Air temperature is estimated using MTCLIM (see routine for reference), atmospheric moisture is estimated using Kimball's algorithm (see routine for reference), and radiation is estimated using Bras's algorithms (see routines for reference). WARNING: This subroutine is site specific. Location parameters must be changed before compilation. UNITS: mks energy - W/m^2 Modifications: 11-18-98 Removed variable array yearly_epot, since yearly potential evaporation is no longer used for estimating the dew point temperature from daily minimum temperature. KAC 11-25-98 Added second check to make sure that the difference between tmax and tmin is positive, after being reset when it was equal to 0. DAG, EFW 12-1-98 Changed relative humidity computations so that they use air temperature for the time step, instead of average daily temperature. This allows relative humidity to change during the day, when the time step is less than daily. KAC 8-19-99 MIN_TDEW was added to prevent the dew point temperature estimated by Kimball's equations from becoming so low that svp() fails. Bart 9-4-99 Code was largely rewritten to change make use of the MTCLIM meteorological preprocessor which estimates sub-daily met forcings for all time steps. The atmos_data_struct was also reconfigured so that it has a new record for each model time step, but stores sub-time step forcing data (that might be needed for the snow model) within each record, eliminating the on the fly estimations used in previous versions of the model. Bart and Greg 03-12-03 Modifed to add AboveTreeLine to soil_con_struct so that the model can make use of the computed treeline. KAC 09-02-2003 Moved COMPUTE_TREELINE flag from user_def.h to the options structure. Now when not set to FALSE, the value indicates the default above treeline vegetation if no usable vegetation types are in the grid cell (i.e. everything has a canopy). A negative value will cause the model to use bare soil. Make sure that positive index value refer to a non-canopied vegetation type in the vegetation library. KAC 07-May-04 Replaced rint(something) with (float)(int)(something + 0.5) to handle rounding errors without resorting to rint() function. TJB 16-Jun-04 Modified to pass avgJulyAirTemp argument to compute_treeline(). TJB**********************************************************************/{ extern option_struct options; extern param_set_struct param_set; extern global_param_struct global_param; extern int NR, NF; int i; int j; int band; int day; int hour; int rec; int step; int idx; int *tmaxhour; int *tminhour; double deltat; double min_Tfactor; double shortwave; double svp_tair; double *hourlyrad; double *prec; double *tmax; double *tmin; double *tair; double *tskc; double *vp; double min, max; double rainonly; int Ndays; int stepspday; double sum; double **forcing_data; /* compute number of simulation days */ Ndays = ( global_param.nrecs * global_param.dt) / 24; /* compute number of full model time steps per day */ stepspday = 24/global_param.dt; if (!param_set.TYPE[PREC].SUPPLIED) nrerror("Precipitation must be given to the model, check input files\n"); if ((!param_set.TYPE[TMAX].SUPPLIED || !param_set.TYPE[TMIN].SUPPLIED) && !param_set.TYPE[AIR_TEMP].SUPPLIED) nrerror("Daily maximum and minimum air temperature or sub-daily air temperature must be given to the model, check input files\n"); if (param_set.TYPE[AIR_TEMP].SUPPLIED && param_set.FORCE_DT[param_set.TYPE[AIR_TEMP].SUPPLIED-1] == 24) nrerror("Model cannot use daily average temperature, must provide daily maximum and minimum or sub-daily temperatures."); if ((param_set.TYPE[SHORTWAVE].SUPPLIED && !param_set.TYPE[VP].SUPPLIED) || (!param_set.TYPE[SHORTWAVE].SUPPLIED && param_set.TYPE[VP].SUPPLIED)) nrerror("Sub-daily shortwave and vapor pressure forcing data must be supplied together."); /* if ((param_set.TYPE[SHORTWAVE].SUPPLIED && !param_set.TYPE[LONGWAVE].SUPPLIED)) nrerror("Model cannot be run with shortwave supplied, if longwave is not provided."); */ /* mtclim routine memory allocations */ hourlyrad = (double *) calloc(Ndays*24, sizeof(double)); prec = (double *) calloc(Ndays*24, sizeof(double)); tair = (double *) calloc(Ndays*24, sizeof(double)); tmax = (double *) calloc(Ndays, sizeof(double)); tmaxhour = (int *) calloc(Ndays, sizeof(double)); tmin = (double *) calloc(Ndays, sizeof(double)); tminhour = (int *) calloc(Ndays, sizeof(double)); tskc = (double *) calloc(Ndays*24, sizeof(double)); vp = (double *) calloc(Ndays*24, sizeof(double)); if (hourlyrad == NULL || prec == NULL || tair == NULL || tmax == NULL || tmaxhour == NULL || tmin == NULL || tminhour == NULL || tskc == NULL || vp == NULL) nrerror("Memory allocation failure in initialize_atmos()"); /******************************* read in meteorological data *******************************/ forcing_data = read_forcing_data(infile, global_param); fprintf(stderr,"\nRead meteorological forcing file\n"); /************************************************* Create sub-daily precipitation if not provided *************************************************/ if(param_set.FORCE_DT[param_set.TYPE[PREC].SUPPLIED-1] == 24) { /* daily prec provided */ rec = 0; for (day = 0; day < Ndays; day++) { for (i = 0; i < stepspday; i++) { sum = 0; for (j = 0; j < NF; j++) { atmos[rec].prec[j] = forcing_data[PREC][day] / (float)(NF * stepspday); sum += atmos[rec].prec[j]; } if(NF>1) atmos[rec].prec[NR] = sum; if(global_param.dt == 24) atmos[rec].prec[NR] = forcing_data[PREC][day]; rec++; } } } else { /* sub-daily prec speed provided */ idx = 0; for(rec = 0; rec < global_param.nrecs; rec++) { sum = 0; for(i = 0; i < NF; i++) { atmos[rec].prec[i] = forcing_data[PREC][idx]; sum += atmos[rec].prec[i]; idx++; } if(NF>1) atmos[rec].prec[NR] = sum; } } /************************************************ Set maximum daily air temperature if provided ************************************************/ if(param_set.TYPE[TMAX].SUPPLIED) { if(param_set.FORCE_DT[param_set.TYPE[TMAX].SUPPLIED-1] == 24) { /* daily tmax provided */ for (day = 0; day < Ndays; day++) { tmax[day] = forcing_data[TMAX][day]; } } else { /* sub-daily tmax speed provided */ idx = 0; for(rec = 0; rec < global_param.nrecs; rec++) { tmax[rec/stepspday] = forcing_data[TMAX][idx]; for(i = 0; i < NF; i++) idx++; } } } /************************************************ Set minimum daily air temperature if provided ************************************************/ if(param_set.TYPE[TMIN].SUPPLIED) { if(param_set.FORCE_DT[param_set.TYPE[TMIN].SUPPLIED-1] == 24) { /* daily tmin provided */ for (day = 0; day < Ndays; day++) { tmin[day] = forcing_data[TMIN][day]; } } else { /* sub-daily tmin speed provided */ idx = 0; for(rec = 0; rec < global_param.nrecs; rec++) { tmin[rec/stepspday] = forcing_data[TMIN][idx]; for(i = 0; i < NF; i++) idx++; } } } /************************************************* Store sub-daily air temperature if provided *************************************************/ if(param_set.TYPE[AIR_TEMP].SUPPLIED) { /* forcing data defined as equal to or less than SNOW_STEP */ idx = 0; for (rec = 0; rec < global_param.nrecs; rec++) { sum = 0; for (i = 0; i < NF; i++, step++) { atmos[rec].air_temp[i] = forcing_data[AIR_TEMP][idx]; sum += atmos[rec].air_temp[i]; idx++; } if(NF > 1) atmos[rec].air_temp[NR] = sum / (float)NF; } } /****************************************************** Determine Tmax and Tmin from sub-daily temperatures ******************************************************/ if(!(param_set.TYPE[TMAX].SUPPLIED && param_set.TYPE[TMIN].SUPPLIED)) { rec = 0; while(rec < global_param.nrecs) { min = max = atmos[rec].air_temp[0]; for (j = 0; j < stepspday; j++) { for (i = 0; i < NF; i++, step++) { if ( atmos[rec].air_temp[i] > max ) max = atmos[rec].air_temp[i]; if ( atmos[rec].air_temp[i] < min ) min = atmos[rec].air_temp[i]; } rec++; } tmax[(rec-1)/stepspday] = max; tmin[(rec-1)/stepspday] = min; } } /************************************************** use the mtclim code to get the hourly shortwave and the daily dew point temperature requires prec, tmax, and tmin **************************************************/ if(!(param_set.TYPE[VP].SUPPLIED && param_set.TYPE[SHORTWAVE].SUPPLIED)) { /** do not use mtclim estimates if vapor pressure and shortwave radiation are supplied **/ for (i = 0; i < Ndays; i++) prec[i] = 0; for (rec = 0; rec < global_param.nrecs; rec++) { prec[rec/stepspday] += atmos[rec].prec[NR]; } mtclim42_wrapper(0, 0, (theta_l-theta_s)*24./360., elevation, annual_prec, phi, &global_param, dmy, prec, tmax, tmin, tskc, vp, hourlyrad); } /*********************************************************** reaggregate the hourly shortwave to the larger timesteps ***********************************************************/ if(!param_set.TYPE[SHORTWAVE].SUPPLIED) { for (rec = 0, hour = 0; rec < global_param.nrecs; rec++) { for (i = 0; i < NF; i++) { atmos[rec].shortwave[i] = 0; for (j = 0; j < options.SNOW_STEP; j++, hour++) { atmos[rec].shortwave[i] += hourlyrad[hour]; } atmos[rec].shortwave[i] /= options.SNOW_STEP; } if (NF > 1) { atmos[rec].shortwave[NR] = 0; for (i = 0; i < NF; i++) { atmos[rec].shortwave[NR] += atmos[rec].shortwave[i]; } atmos[rec].shortwave[NR] /= NF; } } } else { /* sub-daily shortwave provided, so it will be used instead of the mtclim estimates */ idx = 0; for (rec = 0, hour = 0; rec < global_param.nrecs; rec++) { sum = 0; for (i = 0; i < NF; i++, step++) { atmos[rec].shortwave[i] = forcing_data[SHORTWAVE][idx]; sum += atmos[rec].shortwave[i]; idx++; } if (NF > 1) atmos[rec].shortwave[NR] = sum / (float)NF; } } /************************************************************************** Calculate the hours at which the minimum and maximum temperatures occur **************************************************************************/ if(!param_set.TYPE[AIR_TEMP].SUPPLIED) { set_max_min_hour(hourlyrad, Ndays, tmaxhour, tminhour); /********************************************************************** Calculate the subdaily and daily temperature based on tmax and tmin **********************************************************************/ HourlyT(options.SNOW_STEP, Ndays, tmaxhour, tmax, tminhour, tmin, tair); for (rec = 0, step = 0; rec < global_param.nrecs; rec++) { for (i = 0; i < NF; i++, step++) { atmos[rec].air_temp[i] = tair[step]; } if (NF > 1) { atmos[rec].air_temp[NR] = 0; for (i = 0; i < NF; i++) { atmos[rec].air_temp[NR] += atmos[rec].air_temp[i]; } atmos[rec].air_temp[NR] /= NF; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -