!! Manage mean daily air temperature !|author: Giovanni Ravazzani ! license: GPL ! !### History ! ! current version 1.0 - 19th May 2021 ! ! | version | date | comment | ! |----------|-------------|----------| ! | 1.0 | 19/May/2021 | Original code | ! !### License ! license: GNU GPL ! !### Module Description ! Module to manage mean daily air temperature ! MODULE AirTemperatureDailyMean ! Modules used: USE DataTypeSizes, ONLY : & ! Imported Parameters: float, short USE Loglib, ONLY : & !Imported routines: Catch USE ObservationalNetworks, ONLY : & !Imported types: ObservationalNetwork, & !Imported routines: ReadMetadata, ReadData, & CopyNetwork, & !Imported operators: ASSIGNMENT (=) USE Chronos, ONLY : & !Imported types: DateTime, & !Imported variables: timeString, & !Imported operations: OPERATOR (<), & OPERATOR (>), & OPERATOR (>=), & OPERATOR (<=), & OPERATOR (+), & OPERATOR (==), & ASSIGNMENT (=) USE GridLib, ONLY : & !Imported types: grid_real, grid_integer, & !Imported routines: NewGrid, GetDtGrid, & GridDestroy, ExportGrid, & SetLongName, SetStandardName, & SetUnits, SetCurrentTime, & !Imported parameters: NET_CDF, ESRI_ASCII, & ESRI_BINARY USE GridOperations, ONLY : & !Imported routines: GridByIni, GridResample, & CRSisEqual, GridConvert, & !Imported operations: ASSIGNMENT (=) USE IniLib, ONLY : & !Imported types: IniList, & !Imported routines: IniReadInt, IniReadReal, & KeyIsPresent, IniReadString, & SubSectionIsPresent USE Utilities, ONLY: & !Imported routines: GetUnit USE MeteoUtilities, ONLY: & !Imported routines: ReadField, ShiftMeteoWithLapse, & Interpolate, ShiftBackWithLapse, & Offset, Scale USE FileSys, ONLY: & !Imported routines: DirExists, FileExists, & FileDelete, CurrentDir, & GetOS, DirNew, & !Imported parameters: WIN32 USE GeoLib, ONLY: & !Imported variables: point1, point2, & !Imported routines: DecodeEPSG, Convert, & !Imported types: CRS, & !Imported operations: OPERATOR (==) USE StringManipulation, ONLY: & !Imported routines: ReplaceChar, ToString USE Statistics, ONLY: & !imported routines: LinearRegressionSlope USE Units, ONLY: & !imported parameters: day IMPLICIT NONE ! Global (i.e. public) Declarations: INTEGER (KIND = short) :: dtTemperatureDailyMean = 0 !!cumulation deltat TYPE(ObservationalNetwork) :: thermometersDailyMean !!temperature stations network TYPE(grid_real) :: temperatureAirDailyMean !![°C] !Private declarations TYPE(DateTime), PRIVATE :: timeNew !!time when new data must be read TYPE(ObservationalNetwork), PRIVATE :: stationsRefElev !!stations network at reference elevation INTEGER (KIND = short), PRIVATE :: fileunit !! unit of file containing data INTEGER (KIND = short), PRIVATE :: interpolationMethod !!method to spatial interpolate site data INTEGER (KIND = short), PRIVATE :: interpolationMethod_assignment !!method to assign spatial interpolation ! !!1 = one method for the entire domain, 2 = a map with interpolation method codes TYPE (grid_integer), PRIVATE :: interpolationMethod_map INTEGER (KIND = short), PRIVATE :: interpolationMethod_vector (3) !!defines active interpolation methods TYPE (grid_real), PRIVATE :: interpolatedMap (3) !!1 = map for thiessen, 2 = map for idw, 3 = map for kriging REAL (KIND = float), PRIVATE :: cellsizeInterpolation !!spatial resolution of interpolated grid TYPE(grid_real), PRIVATE :: gridTemp !temporary grid used to interpolate to !different spatial resolution INTEGER (KIND = short), PRIVATE :: neighbors !!number of closest data to use for interpolation TYPE(grid_real), PRIVATE :: grid_devst !!standard deviation of kriging interpolation CHARACTER (LEN = 300), PRIVATE :: fileGrid !!file containing grids INTEGER (KIND = short), PRIVATE :: dtGrid !!dt of imported field INTEGER (KIND = short), PRIVATE :: elevationDrift !! 1 = use elevation to modify interpolated data TYPE(grid_real), PRIVATE :: lapse_map !!lapse rate map REAL (KIND = float), PRIVATE :: lapse !!lapse rate [°C/m] REAL (KIND = float), PRIVATE :: lapse_computed !!lapse rate computed from data [°C/m] REAL (KIND = float), PRIVATE :: r2min !! value of linear regression R2 below which lapse-rate-scalar is used instead of computed lapse rate INTEGER (KIND = short), PRIVATE :: lapse_rate_assignment !!1 = scalar, 2 = map that may change with time INTEGER (KIND = short), PRIVATE :: lapse_rate_computation !!1 = compute lapse rate from data at each time step, 0 = use assigned lapse rate REAL, ALLOCATABLE, PRIVATE :: vectorT (:), vectorZ (:) !!vector of temperatures and elevation to compute lapse rate INTEGER (KIND = short), PRIVATE :: i, j !!loop index REAL (KIND = float), PARAMETER, PRIVATE :: refElevation = 1000. !!reference elevation for applying lapse rate REAL (KIND = float), PRIVATE, PARAMETER :: MISSING_DEF_REAL = -9999.9 REAL (KIND = float), PRIVATE :: scale_factor !!scale factor to apply to final map REAL (KIND = float), PRIVATE :: offset_value !!offset to apply to final map REAL (KIND = float), PRIVATE :: valid_prcn !!when data from several time steps are read, !!this is the minimum percentage (0-1) of valid !!data that must be prresent to consider !!valid the aggregated value. !used by inverse distance weighting interpolation REAL (KIND = float), PRIVATE :: idw_power !! power to be used with IDW !used by kriging INTEGER (KIND = short), PRIVATE :: krige_var !! when set to 1 a grid of kriging variance is generated and exported if export option is active, default to 0 INTEGER (KIND = short), PRIVATE :: krige_anisotropy !! considers anisotropy, default = 0 excludes anisotropy INTEGER (KIND = short), PRIVATE :: krige_varmodel !! 1 = spherical, 2 = exponential, 3 = gaussian, 0 = automatic fitting. default to 2 INTEGER (KIND = short), PRIVATE :: krige_lags !! number of lags for semivariogram. if undefined or set to 0 default to 15 REAL (KIND = float) , PRIVATE :: krige_maxlag !! maximum distance to be considered for semivariogram assessment. If undefined or set to 0, it is computed automatically INTEGER (KIND = short), PRIVATE :: export !!activates grid exporting CHARACTER (LEN = 1000), PRIVATE :: export_path !!folder where to put exported grids CHARACTER (LEN = 1000), PRIVATE :: export_file !!name of exported grid CHARACTER (LEN = 1000), PRIVATE :: export_file_var !!name of exported variance grid TYPE (DateTime), PRIVATE :: export_start !! time and date to start exporting TYPE (DateTime), PRIVATE :: export_stop !! time and date to stop exporting INTEGER (KIND = short), PRIVATE :: export_dt !! time between two exportations TYPE (DateTime), PRIVATE :: timeNewExport !! time when new exporting must occur INTEGER (KIND = short), PRIVATE :: export_format !! 1 = esri_ascii, 2 = esri_binary, 3 = netcdf INTEGER (KIND = short), PRIVATE :: export_epsg !! coordinate reference system of exported grid TYPE (grid_real), PRIVATE :: exportedGrid, exportedGridVar TYPE (CRS), PRIVATE :: exportGridMapping LOGICAL, PRIVATE :: needConversion !Public routines PUBLIC :: AirTemperatureDailyMeanInit PUBLIC :: AirTemperatureDailyMeanRead !Local routines PRIVATE :: SetSpecificProperties !======= CONTAINS !======= ! Define procedures contained in this module. !============================================================================== !| Description: ! Initialize air temperature SUBROUTINE AirTemperatureDailyMeanInit & ! ( ini, mask, dtMeteo, tstart, dem_loaded ) IMPLICIT NONE TYPE (IniList), INTENT(IN) :: ini TYPE (grid_integer), INTENT(IN) :: mask !!defines interpolation extent INTEGER (KIND = short), INTENT(IN) :: dtMeteo !! deltat of meteo data reading TYPE (DateTime), INTENT(IN) :: tstart !!initial time LOGICAL , INTENT (IN) :: dem_loaded !! true if dem has been loaded !local declarations CHARACTER (LEN = 1000) :: filename TYPE (DateTime) :: lapseTime TYPE (grid_real) :: meteoTemp !-------------------------end of declarations---------------------------------- !set initial time timeNew = tstart !initialize grid CALL NewGrid (temperatureAirDailyMean, mask, 0.) CALL NewGrid (grid_devst, mask, 0.) !set deltat dtTemperatureDailyMean = day !check dt is multiple of dtMeteo IF (.NOT.(MOD(dtTemperatureDailyMean,dtMeteo) == 0)) THEN CALL Catch ('error', 'AirTemperatureDailyMean', & 'dt is not multiple of dtMeteo') END IF !set valid threshold IF (KeyIsPresent ('valid-threshold', ini, & section = 'temperature-daily-mean') ) THEN valid_prcn = IniReadReal ('valid-threshold', ini, & section = 'temperature-daily-mean') ELSE ! set to default = 1.0 CALL Catch ('info', 'AirTemperatureDailyMean', & 'valid-threshold not defined, set to 1') valid_prcn = 1. END IF !set cell-size cellsizeInterpolation = mask % cellsize !interpolation-assignment method IF (KeyIsPresent('interpolation-assignment', ini, & section = 'temperature-daily-mean') ) THEN interpolationMethod_assignment = IniReadInt ('interpolation-assignment', ini, & section = 'temperature-daily-mean') ELSE CALL Catch ('error', 'AirTemperatureDailyMean', & 'interpolation-assignment missing in meteo configuration file') END IF !set interpolation method IF (interpolationMethod_assignment == 1) THEN interpolationMethod = IniReadInt ('interpolation', ini, & section = 'temperature-daily-mean') CALL SetSpecificProperties (interpolationMethod, ini, mask) ELSE !read map interpolationMethod = -1 CALL GridByIni (ini, interpolationMethod_map, 'temperature-daily-mean', & "interpolation") !scan for interpolation methods included interpolationMethod_vector = 0 DO i = 1, interpolationMethod_map % idim DO j = 1, interpolationMethod_map % jdim IF (interpolationMethod_map % mat(i,j) /= & interpolationMethod_map % nodata) THEN interpolationMethod_vector & (interpolationMethod_map % mat (i,j)) = & interpolationMethod_map % mat (i,j) END IF END DO END DO DO i = 1, 3 CALL SetSpecificProperties (interpolationMethod_vector (i), ini, mask) END DO END IF !scale factor and offset IF (KeyIsPresent('offset', ini, section = 'temperature-daily-mean')) THEN offset_value = IniReadReal ('offset', ini, section = 'temperature-daily-mean') ELSE offset_value = MISSING_DEF_REAL END IF IF (KeyIsPresent('scale-factor', ini, section = 'temperature-daily-mean')) THEN scale_factor = IniReadReal ('scale-factor', ini, section = 'temperature-daily-mean') ELSE scale_factor = MISSING_DEF_REAL END IF !set power_idw IF (KeyIsPresent('idw-power', ini, section = 'temperature-daily-mean')) THEN idw_power = IniReadReal ('idw-power', ini, section = 'temperature-daily-mean') ELSE !set default value idw_power = 2. END IF !file filename = IniReadString ('file', ini, section = 'temperature-daily-mean') IF (interpolationMethod_assignment == 1 .AND. & interpolationMethod == 0) THEN !data are stored in net-cdf file !store net-cdf filename fileGrid = filename IF ( KeyIsPresent ('variable', ini, section = 'temperature-daily-mean') ) THEN temperatureAirDailyMean % var_name = IniReadString ('variable', & ini, section = 'temperature-daily-mean') !read grid and store as temporary file CALL NewGrid (layer = meteoTemp, fileName = TRIM(fileGrid), & fileFormat = NET_CDF, & variable = TRIM(temperatureAirDailyMean % var_name) ) ELSE IF (KeyIsPresent ('standard_name', ini, & section = 'temperature-daily-mean') ) THEN temperatureAirDailyMean % standard_name = IniReadString ('standard_name', & ini, section = 'temperature-daily-mean') ELSE CALL Catch ('error', 'AirTemperatureDailyMean', & 'standard_name or variable missing in section temeprature' ) END IF !set cellsize to zero. Optimal cellsize is automatically computed cellsizeInterpolation = 0. ELSE !open file containing local measurements fileunit = GetUnit () OPEN(fileunit,file = filename(1:LEN_TRIM(filename)),status='old') END IF !use elevation to drift interpolation IF ( KeyIsPresent ('elevation-drift', ini, section = 'temperature-daily-mean') ) THEN elevationDrift = IniReadInt ('elevation-drift', ini, section = 'temperature-daily-mean') ELSE elevationDrift = 0 !default, suppress drift END IF IF (elevationDrift == 1) THEN IF (interpolationMethod == 0 ) THEN CALL Catch ('error', 'AirTemperatureDailyMean', & 'elevation drift cannot be applied when interpolation = 0 ') END IF !check if have been loaded by domain properties IF ( .NOT. dem_loaded) THEN CALL Catch ('error', 'AirTemperatureDailyMean', & 'dem for elevation drift was not loaded ') END IF !need lapse-rate computation? IF (KeyIsPresent ('lapse-rate-computation', ini, & section = 'temperature-daily-mean') ) THEN lapse_rate_computation = IniReadInt ('lapse-rate-computation', ini, & section = 'temperature-daily-mean') ELSE !lapse-rate-computation is missing CALL Catch ('error', 'AirTemperatureDailyMean', & 'lapse-rate-computation missing in meteo configuration file') END IF IF ( lapse_rate_computation == 1 .AND. interpolationMethod == 0 ) THEN CALL Catch ('error', 'AirTemperatureDailyMean', & 'lapse_rate_computation option requires interpolation different from 0') END IF IF (KeyIsPresent ('r2min', ini, & section = 'temperature-daily-mean') ) THEN r2min = IniReadInt ('r2min', ini, & section = 'temperature-daily-mean') ELSE !r2min is missing IF (lapse_rate_computation == 1) THEN CALL Catch ('error', 'AirTemperatureDailyMean', & 'r2min missing in meteo configuration file') END IF END IF !set lapse rate assignment IF (KeyIsPresent ('lapse-rate-assignment', ini, & section = 'temperature-daily-mean') ) THEN lapse_rate_assignment = IniReadInt ('lapse-rate-assignment', ini, & section = 'temperature-daily-mean') ELSE !lapse-rate-assignment missing IF (lapse_rate_computation == 0) THEN CALL Catch ('error', 'AirTemperatureDailyMean', & 'lapse-rate-assignment missing in meteo configuration file') ELSE lapse_rate_assignment = 1 END IF END IF !lapse rate map IF (lapse_rate_assignment == 2) THEN IF ( SubSectionIsPresent (subsection = 'lapse-rate-map', & section = 'temperature-daily-mean', iniDb = ini) ) THEN !check all keywords are defined IF (IniReadString ('format', ini, 'temperature-daily-mean',& 'lapse-rate-map') == 'net-cdf') THEN IF (KeyIsPresent ('time',ini, 'temperature-daily-mean', & 'lapse-rate-map')) THEN timeString = IniReadString ('time', ini, & 'temperature-daily-mean', 'lapse-rate-map') lapseTime = timeString IF (lapseTime > tstart) THEN CALL Catch ('error', 'AirTemperatureDailyMean', & 'lapse-rate-map time greater than starting time' ) END IF ELSE CALL Catch ('error', 'AirTemperatureDailyMean', & 'time keyword is missing in lapse-rate-map subsection' ) END IF END IF CALL GridByIni (ini, lapse_map, 'temperature-daily-mean', "lapse-rate-map") !check coordinate reference system and spatial resolution IF (.NOT. CRSisEqual (mask = mask, grid = lapse_map, & checkCells= .TRUE.)) THEN CALL Catch ('error', 'AirTemperatureDailyMean', & 'wrong lapse-rate-map spatial reference system ') END IF ELSE CALL Catch ('error', 'AirTemperatureDailyMean', & 'lapse-rate-map missing in meteo configuration file') END IF ELSE !build lapse map from scalar value IF ( KeyIsPresent ('lapse-rate-scalar', ini, & section = 'temperature-daily-mean') ) THEN lapse = IniReadReal ('lapse-rate-scalar', ini, & section = 'temperature-daily-mean') CALL NewGrid (lapse_map, mask) lapse_map = lapse ELSE CALL Catch ('error', 'AirTemperatureDailyMean', & 'lapse-rate-scalar missing in meteo configuration file') END IF END IF END IF !grid exporting settings IF (KeyIsPresent ('export', ini, section = 'temperature-daily-mean') ) THEN export = IniReadInt ('export', ini, section = 'temperature-daily-mean') ELSE export = 0 END IF IF (export == 1) THEN !set export path name IF (KeyIsPresent ('export-path', ini, section = 'temperature-daily-mean') ) THEN export_path = IniReadString ('export-path', ini, section = 'temperature-daily-mean') !check if path ends with / or \ IF ( export_path (LEN_TRIM (export_path):LEN_TRIM (export_path)) /= '\' .AND. & export_path (LEN_TRIM (export_path):LEN_TRIM (export_path)) /= '/' ) THEN export_path (LEN_TRIM (export_path)+1:LEN_TRIM (export_path)+1) = '\' END IF IF (INDEX (export_path,'.') == 1) THEN !detected relative path, remove '.' export_path = export_path (2:LEN_TRIM(export_path)) !build absolute path export_path = TRIM(CurrentDir() ) // TRIM(export_path) END IF !check OS convention IF (GetOS () == WIN32) THEN export_path = ReplaceChar (export_path,'/','\') ELSE export_path = ReplaceChar (export_path,'\','/') END IF !check folder exists IF ( .NOT. DirExists (TRIM (export_path) ) ) THEN CALL Catch ('info', 'AirTemperatureDailyMean', & 'creating directory: ', argument = TRIM(export_path)) CALL DirNew (export_path) END IF ELSE CALL Catch ('error', 'AirTemperatureDailyMean', & 'missing export-path') END IF !starting time IF (KeyIsPresent ('export-start', ini, section = 'temperature-daily-mean') ) THEN timeString = IniReadString ('export-start', ini, 'temperature-daily-mean') export_start = timeString ELSE CALL Catch ('error', 'AirTemperatureDailyMean', & 'missing export-start') END IF !initialize timeNewExport timeNewExport = export_start !ending time IF (KeyIsPresent ('export-stop', ini, section = 'temperature-daily-mean') ) THEN timeString = IniReadString ('export-stop', ini, 'temperature-daily-mean') export_stop = timeString ELSE CALL Catch ('error', 'AirTemperatureDailyMean', & 'missing export-start') END IF !export dt IF (KeyIsPresent ('export-dt', ini, section = 'temperature-daily-mean') ) THEN export_dt = IniReadInt ('export-dt', ini, section = 'temperature-daily-mean') ELSE CALL Catch ('error', 'AirTemperatureDailyMean', & 'missing export-dt') END IF !coordinate reference system IF (KeyIsPresent ('export-epsg', ini, section = 'temperature-daily-mean') ) THEN export_epsg = IniReadInt ('export-epsg', ini, section = 'temperature-daily-mean') exportGridMapping = DecodeEPSG (export_epsg) IF (exportGridMapping == temperatureAirDailyMean % grid_mapping) THEN needConversion = .FALSE. !initialize grid for exporting with CRS as meteo variable CALL NewGrid (exportedGrid, temperatureAirDailyMean) CALL NewGrid (exportedGridVar, temperatureAirDailyMean) ELSE needConversion = .TRUE. !initialize grid for converting with required CRS exportedGrid % grid_mapping = DecodeEPSG (export_epsg) exportedGridVar % grid_mapping = DecodeEPSG (export_epsg) END IF ELSE CALL Catch ('info', 'AirTemperatureDailyMean', & 'export-epsg not defined, use default') needConversion = .FALSE. !initialize grid for exporting with CRS CALL NewGrid (exportedGrid, temperatureAirDailyMean) CALL NewGrid (exportedGridVar, temperatureAirDailyMean) END IF !export file format IF (KeyIsPresent ('export-format', ini, section = 'temperature-daily-mean') ) THEN export_format = IniReadInt ('export-format', ini, section = 'temperature-daily-mean') ELSE CALL Catch ('error', 'AirTemperatureDailyMean', & 'missing export-format') END IF IF (export_format == 3) THEN !grid map CALL SetLongName ( 'air_temperature', exportedGrid) CALL SetStandardName ( 'air_temperature', exportedGrid) CALL SetUnits ('degree_Celsius', exportedGrid) !this unit is for exporting grid, it is converted internally to m/s !if file exists, remove it export_file = TRIM(export_path) // 'temperature_daily_mean.nc' IF ( FileExists (export_file) ) THEN CALL FileDelete (export_file) END IF !variance of kriging CALL SetLongName ( 'air_temperature_variance', exportedGridVar) CALL SetStandardName ( 'air_temperature_variance', exportedGridVar) CALL SetUnits ('degree_Celsius', exportedGridVar) !this unit is for exporting grid !if file exists, remove it export_file_var = TRIM(export_path) // 'temperature_daily_mean_variance.nc' IF ( FileExists (export_file_var) ) THEN CALL FileDelete (export_file_var) END IF END IF END IF !complete initialization IF (interpolationMethod == 0) THEN !Get the dt of imported field. Assume dt is regular dtGrid = GetDtGrid (filename = fileGrid, checkRegular = .TRUE.) !check dt is multiple of dtGrid IF (.NOT.(MOD(dtTemperatureDailyMean,dtGrid) == 0)) THEN CALL Catch ('error', 'AirTemperatureDailyMean', & 'dt temperature daily mean is not multiple of dt of input grid') END IF ELSE !populate metadata CALL ReadMetadata (fileunit, thermometersDailyMean) !check spatial reference system IF ( .NOT. thermometersDailyMean % mapping == mask % grid_mapping) THEN CALL Catch ('info', 'AirTemperatureDailyMean', & 'converting coordinate of stations') !convert stations' coordinate point1 % system = thermometersDailyMean % mapping point2 % system = mask % grid_mapping thermometersDailyMean % mapping = mask % grid_mapping DO i = 1, thermometersDailyMean % countObs point1 % easting = thermometersDailyMean % obs (i) % xyz % easting point1 % northing = thermometersDailyMean % obs (i) % xyz % northing point1 % elevation = thermometersDailyMean % obs (i) % z CALL Convert (point1, point2) thermometersDailyMean % obs (i) % xyz % easting = point2 % easting thermometersDailyMean % obs (i) % xyz % northing = point2 % northing END DO END IF !set supplementary stations network for elevation drift IF (elevationDrift == 1) THEN stationsRefElev = thermometersDailyMean DO i = 1, thermometersDailyMean % countObs stationsRefElev % obs (i) % xyz % elevation = refElevation END DO END IF !allocate vectors if lapse rate has to be computed from data IF ( lapse_rate_computation == 1) THEN ALLOCATE (vectorT (thermometersDailyMean % countObs) ) ALLOCATE (vectorZ (thermometersDailyMean % countObs)) END IF END IF RETURN END SUBROUTINE AirTemperatureDailymeanInit !============================================================================== !| Description: ! Read air temperature data SUBROUTINE AirTemperatureDailyMeanRead & ! ( time, dem ) IMPLICIT NONE !Arguments with intent(in): TYPE (DateTime), INTENT(IN) :: time !!current time TYPE (grid_real), INTENT(IN) :: dem !digital elevation model to apply drift !local declarations: TYPE (DateTime) :: time_toread !! time to start reading from CHARACTER (LEN = 300) :: filename CHARACTER (LEN = 300) :: varname REAL (KIND = float) :: rsquare INTEGER (KIND = short) :: i, j !-------------------------end of declarations---------------------------------- IF ( .NOT. (time < timeNew) ) THEN !time_toread = time + - (dtTemperatureDailyMean - thermometersDailyMean % timeIncrement) time_toread = time timeString = time_toread CALL Catch ('info', 'AirTemperatureDailyMean', & 'read new temperature data: ', & argument = timeString) !update lapse rate from maps when required IF (elevationDrift == 1) THEN IF (time == lapse_map % next_time) THEN !update lapse_map varname = lapse_map %var_name filename = lapse_map % file_name !destroy current grid CALL GridDestroy (lapse_map) !read new grid in netcdf file CALL NewGrid (layer = lapse_map, fileName = TRIM(filename), & fileFormat = NET_CDF, & variable = TRIM(varname), & time = time_toread) END IF END IF SELECT CASE (interpolationMethod) CASE (0) !input grid CALL ReadField (fileGrid, time_toread, & dtTemperatureDailyMean, dtGrid, & 'M', temperatureAirDailyMean, & varName = temperatureAirDailyMean % var_name) CASE DEFAULT !requires interpolation !read new data CALL ReadData (network = thermometersDailyMean, fileunit = fileunit, & time = time_toread, aggr_time = dtTemperatureDailyMean, & aggr_type = 'ave', tresh = valid_prcn) IF (elevationDrift == 1) THEN !update lapse rate from data IF (lapse_rate_computation == 1) THEN DO i = 1, thermometersDailyMean % countObs vectorT (i) = thermometersDailyMean % obs (i) % value vectorZ (i) = thermometersDailyMean % obs (i) % xyz % elevation END DO lapse_computed = LinearRegressionSlope (x=vectorZ, y=vectorT, & nodata = thermometersDailyMean % nodata, r2 = rsquare) IF (rsquare < r2min) THEN lapse_computed = lapse ENDIF lapse_map = lapse_computed END IF !shift observation to reference elevation by applying lapse rate CALL ShiftMeteoWithLapse (thermometersDailyMean, lapse_map, refElevation, & stationsRefElev) !interpolate IF (interpolationMethod_assignment == 1) THEN !only one method is applied CALL Interpolate (network = stationsRefElev, & method = interpolationMethod, & near = neighbors, & idw_power = idw_power, & anisotropy = krige_anisotropy, & varmodel = krige_varmodel, & lags = krige_lags, & maxlag = krige_maxlag, & grid = temperatureAirDailyMean, & devst = grid_devst) ELSE !loop trough interpolation methods DO i = 1, 3 IF (interpolationMethod_vector(i) > 0) THEN CALL Interpolate (network = stationsRefElev, & method = interpolationMethod_vector(i), & near = neighbors, & idw_power = idw_power, & anisotropy = krige_anisotropy, & varmodel = krige_varmodel, & lags = krige_lags, & maxlag = krige_maxlag, & grid = interpolatedMap (i), & devst = grid_devst) END IF END DO !compose the final interpolated field DO i = 1, interpolationMethod_map % idim DO j = 1, interpolationMethod_map % jdim IF (interpolationMethod_map % mat(i,j) /= & interpolationMethod_map % nodata ) THEN temperatureAirDailyMean % mat (i,j) = & interpolatedMap (interpolationMethod_map % mat(i,j)) % mat(i,j) END IF END DO END DO END IF !Shift back interpolated field to terrain surface CALL ShiftBackWithLapse (temperatureAirDailyMean, dem, & lapse_map, refElevation) ELSE !elevationdrift = 0 IF (interpolationMethod_assignment == 1) THEN !only one method is applied CALL Interpolate (network = thermometersDailyMean, & method = interpolationMethod, & near = neighbors, & idw_power = idw_power, & anisotropy = krige_anisotropy, & varmodel = krige_varmodel, & lags = krige_lags, & maxlag = krige_maxlag, & grid = temperatureAirDailyMean, & devst = grid_devst) ELSE !loop trough interpolation methods DO i = 1, 3 IF (interpolationMethod_vector(i) > 0) THEN CALL Interpolate (network = thermometersDailyMean, & method = interpolationMethod_vector(i), & near = neighbors, & idw_power = idw_power, & anisotropy = krige_anisotropy, & varmodel = krige_varmodel, & lags = krige_lags, & maxlag = krige_maxlag, & grid = interpolatedMap (i), & devst = grid_devst) END IF END DO !compose the final interpolated field DO i = 1, interpolationMethod_map % idim DO j = 1, interpolationMethod_map % jdim IF (interpolationMethod_map % mat(i,j) /= & interpolationMethod_map % nodata ) THEN temperatureAirDailyMean % mat (i,j) = & interpolatedMap (interpolationMethod_map % mat(i,j)) % mat(i,j) END IF END DO END DO END IF !1 or more interpolation methods END IF !elevationDrift END SELECT !apply scale factor and offset, if defined IF (offset_value /= MISSING_DEF_REAL) THEN CALL Offset (temperatureAirDailyMean, offset_value) END IF IF (scale_factor /= MISSING_DEF_REAL) THEN CALL Scale (temperatureAirDailyMean, scale_factor) END IF !grid exporting IF(export > 0 ) THEN IF( time == timeNewExport .AND. & time >= export_start .AND. & time <= export_stop ) THEN timeString = time timeString = timeString(1:19) timeString(14:14) = '-' timeString(17:17) = '-' grid_devst % reference_time = temperatureAirDailyMean % reference_time IF (needConversion) THEN CALL GridConvert (temperatureAirDailyMean, exportedGrid) CALL GridConvert (grid_devst, exportedGridVar) ELSE exportedGrid = temperatureAirDailyMean exportedGridVar = grid_devst END IF SELECT CASE (export_format) CASE (1) !esri-ascii export_file = TRIM(export_path) // TRIM(timeString) // & '_temperature_daily_mean.asc' CALL Catch ('info', 'AirTemperatureDailyMean', & 'exporting grid to file: ', & argument = TRIM(export_file)) CALL ExportGrid (exportedGrid, export_file, ESRI_ASCII) IF (krige_var == 1) THEN !export kriging variance export_file_var = TRIM(export_path) // TRIM(timeString) // & '_temperature_daily_mean_variance.asc' CALL Catch ('info', 'AirTemperatureDailyMean', & 'exporting variance grid to file: ', & argument = TRIM(export_file_var)) CALL ExportGrid (exportedGridVar, export_file_var, ESRI_ASCII) END IF CASE (2) !esri-binary export_file = TRIM(export_path) // TRIM(timeString) // & '_temperature_daily_mean' CALL Catch ('info', 'AirTemperatureDailyMean', & 'exporting grid to file: ', & argument = TRIM(export_file)) CALL ExportGrid (exportedGrid, export_file, ESRI_BINARY) IF (krige_var == 1) THEN !export kriging variance export_file_var = TRIM(export_path) // TRIM(timeString) // & '_temperature_daily_mean_variance' CALL Catch ('info', 'AirTemperatureDailyMean', & 'exporting variance grid to file: ', & argument = TRIM(export_file_var)) CALL ExportGrid (exportedGridVar, export_file_var, ESRI_BINARY) END IF CASE (3) !net_cdf CALL SetCurrentTime (time, exportedGrid) CALL Catch ('info', 'AirTemperatureDailyMean', & 'exporting grid to file: ', & argument = TRIM(export_file)) CALL ExportGrid (exportedGrid, export_file, 'air_temperature', 'append') IF (krige_var == 1) THEN !export kriging variance CALL SetCurrentTime (time, exportedGridVar) CALL Catch ('info', 'AirTemperatureDailyMean', & 'exporting grid to file: ', & argument = TRIM(export_file_var)) CALL ExportGrid (exportedGridVar, export_file_var, 'air_temperature_variance', 'append') END IF END SELECT timeNewExport = timeNewExport + export_dt END IF ENDIF !time forward timeNew = timeNew + dtTemperatureDailyMean END IF RETURN END SUBROUTINE AirTemperatureDailyMeanRead !============================================================================== !! Description: !! set properties and initialize variables for each interpolation method SUBROUTINE SetSpecificProperties & ! ( method, ini, mask ) IMPLICIT NONE !Arguments with intent(in): INTEGER (KIND = short), INTENT(in) :: method TYPE (IniList) , INTENT(in) :: ini TYPE (grid_integer) , INTENT(in) :: mask !----------------------------end of declarations------------------------------- !set data specific for each interpolation method SELECT CASE (method) CASE (1) !thiessen CALL NewGrid (interpolatedMap (1), mask, 0.) CASE (2) !inverse distance CALL NewGrid (interpolatedMap (2), mask, 0.) !nearest-points IF (KeyIsPresent ('nearest-points', ini, & section = 'temperature-daily-mean') ) THEN neighbors = IniReadInt ('nearest-points', ini, & section = 'temperature-daily-mean') ELSE !nearest-points missing CALL Catch ('error', 'AirTemperatureDailyMean', & 'nearest-points missing in meteo configuration file') END IF CASE (3) !kriging CALL NewGrid (interpolatedMap (3), mask, 0.) !nearest-points IF (KeyIsPresent ('nearest-points', ini, & section = 'temperature-daily-mean') ) THEN neighbors = IniReadInt ('nearest-points', ini, & section = 'temperature-daily-mean') CALL Catch ('info', 'AirTemperatureDailyMean', & 'neighbors set to: ', argument = ToString (neighbors) ) ELSE !nearest-points missing CALL Catch ('error', 'AirTemperatureDailyMean', & 'nearest-points missing in meteo configuration file') END IF !kriging-variance IF (KeyIsPresent ('kriging-variance', ini, & section = 'temperature-daily-mean') ) THEN krige_var = IniReadInt ('kriging-variance', ini, & section = 'temperature-daily-mean') CALL Catch ('info', 'AirTemperatureDailyMean', & 'kriging variance export set to ', argument = ToString(krige_var) ) ELSE !kriging-variance missing krige_var = 0 CALL Catch ('info', 'AirTemperatureDailyMean', & 'kriging variance export set to default (0)') END IF !kriging-anisotropy IF (KeyIsPresent ('kriging-anisotropy', ini, & section = 'temperature-daily-mean') ) THEN krige_anisotropy = IniReadInt ('kriging-anisotropy', ini, & section = 'temperature-daily-mean') CALL Catch ('info', 'AirTemperatureDailyMean', & 'kriging anisotropy set to: ', argument = ToString (krige_anisotropy) ) ELSE !kriging-anisotropy missing krige_anisotropy = 0 CALL Catch ('info', 'AirTemperatureDailyMean', & 'kriging anisotropy set to default (0)') END IF !kriging-variogram-model IF (KeyIsPresent ('kriging-variogram-model', ini, & section = 'temperature-daily-mean') ) THEN krige_varmodel = IniReadInt ('kriging-variogram-model', ini, & section = 'temperature-daily-mean') CALL Catch ('info', 'AirTemperatureDailyMean', & 'kriging variogram model set to: ', argument = ToString (krige_varmodel) ) IF (krige_varmodel == 0 ) krige_varmodel = 5 !automatic fitting ELSE !kriging-variogram-model krige_varmodel = 2 CALL Catch ('info', 'AirTemperatureDailyMean', & 'kriging variogram model set to default (2 exponential)') END IF !kriging-lags IF (KeyIsPresent ('kriging-lags', ini, & section = 'temperature-daily-mean') ) THEN krige_lags = IniReadInt ('kriging-lags', ini, & section = 'temperature-daily-mean') IF (krige_lags == 0) krige_lags = 15 CALL Catch ('info', 'AirTemperatureDailyMean', & 'kriging lags set to: ', argument = ToString (krige_lags) ) ELSE !kriging-variogram-model krige_lags = 15 CALL Catch ('info', 'AirTemperatureDailyMean', & 'kriging lags set to default (15)') END IF !kriging-maxlag IF (KeyIsPresent ('kriging-maxlag', ini, & section = 'temperature-daily-mean') ) THEN krige_maxlag = IniReadInt ('kriging-maxlag', ini, & section = 'temperature-daily-mean') CALL Catch ('info', 'AirTemperatureDailyMean', & 'kriging max lag set to: ', argument = ToString (krige_maxlag) ) ELSE !kriging-maxlag missing krige_maxlag = 0 CALL Catch ('error', 'AirTemperatureDailyMean', & 'kriging max lag set to default (0)') END IF END SELECT RETURN END SUBROUTINE SetSpecificProperties END MODULE AirTemperatureDailyMean