!! Manage meteorological forcings
!|author: Giovanni Ravazzani
! license: GPL
!
!### History
!
! current version 1.1 - 2nd February 2023
!
! | version | date | comment |
! |----------|-------------|----------|
! | 1.0 | 17/Oct/2017 | Original code |
! | 1.1 | 02/Feb/2023 | added subroutine to export point data |
!
!### License
! license: GNU GPL
!
!### Module Description
! Module to manage meteorological forcings
!
MODULE Meteo
! Modules used:
USE DataTypeSizes, ONLY : &
! Imported Parameters:
float, short
USE Loglib, ONLY : &
!Imported routines:
Catch
USE IniLib, ONLY : &
!Imported types:
IniList, &
!Imported routines:
IniOpen, SectionIsPresent, &
IniClose
USE GridLib, ONLY : &
!Imported types:
grid_real, grid_integer
USE Precipitation, ONLY : &
!Imported routines:
PrecipitationInit, PrecipitationRead, &
!Imported variables:
dtPrecipitation, precipitationRate
USE PrecipitationDaily, ONLY : &
!Imported routines:
PrecipitationDailyInit, PrecipitationDailyRead, &
!Imported variables:
dtPrecipitationDaily
USE AirTemperature, ONLY : &
!Imported routines:
AirTemperatureInit, AirTemperatureRead, &
!Imported variables:
dtTemperature, temperatureAir
USE AirTemperatureDailyMean, ONLY : &
!Imported routines:
AirTemperatureDailyMeanInit, AirTemperatureDailyMeanRead, &
!Imported variables:
dtTemperatureDailyMean
USE AirTemperatureDailyMax, ONLY : &
!Imported routines:
AirTemperatureDailyMaxInit, AirTemperatureDailyMaxRead, &
!Imported variables:
dtTemperatureDailyMax
USE AirTemperatureDailyMin, ONLY : &
!Imported routines:
AirTemperatureDailyMinInit, AirTemperatureDailyMinRead, &
!Imported variables:
dtTemperatureDailyMin
USE SolarRadiation, ONLY : &
!Imported routines:
SolarRadiationInit, SolarRadiationRead, &
!Imported variables:
dtRadiation, radiation
USE AirRelativeHumidity, ONLY : &
!Imported routines:
AirRelativeHumidityInit, AirRelativeHumidityRead, &
!Imported variables:
dtRelHumidity, relHumidityAir
USE WindFlux, ONLY : &
!Imported routines:
WindFluxInit, WindFluxRead, &
!Imported variables:
dtWindSpeed, windSpeed
USE Chronos, ONLY : &
!Imported types:
DateTime, &
!Imported operators:
OPERATOR (==), &
OPERATOR (+)
USE ObservationalNetworks, ONLY : &
!Imported routines:
ReadMetadata, CopyNetwork, &
WriteMetadata, DestroyNetwork, &
AssignDataFromGrid, WriteData, &
!Imported defined variable:
ObservationalNetwork
USE Utilities, ONLY : &
!Imported routines:
GetUnit
IMPLICIT NONE
! Global (i.e. public) Declarations:
INTEGER (KIND = short) :: dtMeteo
LOGICAL :: demHiResRequired = .FALSE.
!Public routines
PUBLIC :: MeteoInit
PUBLIC :: MeteoRead
PUBLIC :: MeteoPointInit
!Local (i.e. private) declarations
TYPE (IniList), PRIVATE :: meteoini
TYPE (ObservationalNetwork), PRIVATE :: sites
TYPE (ObservationalNetwork), PRIVATE :: sitesPrecipitation
TYPE (ObservationalNetwork), PRIVATE :: sitesTemperature
TYPE (ObservationalNetwork), PRIVATE :: sitesRadiation
TYPE (ObservationalNetwork), PRIVATE :: sitesRH
TYPE (ObservationalNetwork), PRIVATE :: sitesWS
INTEGER (KIND = short), PRIVATE :: fileUnitPointPrecipitation
INTEGER (KIND = short), PRIVATE :: fileUnitPointTemperature
INTEGER (KIND = short), PRIVATE :: fileUnitPointRadiation
INTEGER (KIND = short), PRIVATE :: fileUnitPointRH
INTEGER (KIND = short), PRIVATE :: fileUnitPointWS
INTEGER (KIND = short), PRIVATE :: timeIncrementSites
TYPE (DateTime), PRIVATE :: timePointExport
!Private routines
PRIVATE :: MeteoPointExport
!Local routines
!=======
CONTAINS
!=======
! Define procedures contained in this module.
!==============================================================================
!| Description:
! Initialize meteorological forcings
SUBROUTINE MeteoInit &
!
( inifile, tstart, mask, dem, dem_loaded, albedo_loaded )
IMPLICIT NONE
CHARACTER (LEN = *), INTENT(IN) :: inifile !!name of configuration file
TYPE (DateTime), INTENT(IN) :: tstart !!initial time
TYPE (grid_integer), INTENT(IN) :: mask !!defines interpolation extent
!INTEGER (KIND = short), INTENT(IN) :: dtMeteo !! deltat of meteo data reading
TYPE(grid_real), INTENT(in) :: dem !!digital elevation model to be used to modify interpolated data
LOGICAL , INTENT (in) :: dem_loaded !! true if dem has been loaded
LOGICAL , INTENT (in) :: albedo_loaded !! true if dem has been loaded
!-------------------------end of declarations----------------------------------
!open and load configuration file
CALL IniOpen (inifile, meteoini)
!configure precipitation
IF (SectionIsPresent (section = "precipitation", iniDB = meteoini)) THEN
CALL Catch ('info', 'Meteo', 'initialize precipitation ')
CALL PrecipitationInit (meteoini, mask, dtMeteo, tstart, dem_loaded)
ELSE
CALL Catch ('warning', 'Meteo', 'precipitation is turned off')
END IF
!configure daily precipitation
IF (SectionIsPresent (section = "precipitation-daily", iniDB = meteoini)) THEN
CALL Catch ('info', 'Meteo', 'initialize daily precipitation ')
CALL PrecipitationDailyInit (meteoini, mask, dtMeteo, tstart, dem_loaded)
ELSE
CALL Catch ('warning', 'Meteo', 'daily precipitation is turned off')
END IF
!configure air temperature
IF (SectionIsPresent (section = "temperature", iniDB = meteoini)) THEN
CALL Catch ('info', 'Meteo', 'initialize air temperature ')
CALL AirTemperatureInit (meteoini, mask, dtMeteo, tstart, dem_loaded)
ELSE
CALL Catch ('warning', 'Meteo', 'air temperature is turned off')
END IF
!configure mean daily air temperature
IF (SectionIsPresent (section = "temperature-daily-mean", iniDB = meteoini)) THEN
CALL Catch ('info', 'Meteo', 'initialize daily mean air temperature ')
CALL AirTemperatureDailyMeanInit (meteoini, mask, dtMeteo, tstart, dem_loaded)
ELSE
CALL Catch ('warning', 'Meteo', 'daily mean air temperature is turned off')
END IF
!configure maximum daily air temperature
IF (SectionIsPresent (section = "temperature-daily-max", iniDB = meteoini)) THEN
CALL Catch ('info', 'Meteo', 'initialize daily max air temperature ')
CALL AirTemperatureDailyMaxInit (meteoini, mask, dtMeteo, tstart, dem_loaded)
ELSE
CALL Catch ('warning', 'Meteo', 'daily max air temperature is turned off')
END IF
!configure minimum daily air temperature
IF (SectionIsPresent (section = "temperature-daily-min", iniDB = meteoini)) THEN
CALL Catch ('info', 'Meteo', 'initialize daily min air temperature ')
CALL AirTemperatureDailyMinInit (meteoini, mask, dtMeteo, tstart, dem_loaded)
ELSE
CALL Catch ('warning', 'Meteo', 'daily min air temperature is turned off')
END IF
!configure relative humidity
IF (SectionIsPresent (section = "relative-humidity", iniDB = meteoini)) THEN
CALL Catch ('info', 'Meteo', 'initialize relative humidity ')
CALL AirRelativeHumidityInit (meteoini, mask, dtMeteo, tstart)
ELSE
CALL Catch ('warning', 'Meteo', 'relative humidity is turned off')
END IF
!configure solar radiation
IF (SectionIsPresent (section = "solar-radiation", iniDB = meteoini)) THEN
CALL Catch ('info', 'Meteo', 'initialize solar radiation ')
CALL SolarRadiationInit (meteoini, mask, dtMeteo, tstart, dem, dem_loaded, &
albedo_loaded, dtTemperature, dtRelHumidity )
ELSE
CALL Catch ('warning', 'Meteo', 'solar radiation is turned off')
END IF
!configure wind speed
IF (SectionIsPresent (section = "wind-speed", iniDB = meteoini)) THEN
CALL Catch ('info', 'Meteo', 'initialize wind flux ')
CALL WindFluxInit (meteoini, mask, dtMeteo, tstart, dem, dem_loaded)
ELSE
CALL Catch ('warning', 'Meteo', 'wind speed is turned off')
END IF
!close ini
CALL IniClose (meteoini)
RETURN
END SUBROUTINE MeteoInit
!==============================================================================
!| Description:
! Initialize export of point site data
SUBROUTINE MeteoPointInit &
!
( pointfile, path_out, time )
IMPLICIT NONE
!Arguments with intent (in):
CHARACTER (LEN = *), INTENT(IN) :: pointfile !!file containing coordinate of points
CHARACTER (LEN = *), INTENT(IN) :: path_out !!path of output folder
TYPE (DateTime), INTENT(IN) :: time !!start time
!local declarations
INTEGER (KIND = short) :: err_io
INTEGER (KIND = short) :: fileunit
!-------------------------end of declarations----------------------------------
timePointExport = time
!open point file
fileunit = GetUnit ()
OPEN ( unit = fileunit, file = pointfile(1:LEN_TRIM(pointfile)), &
status='OLD', iostat = err_io )
IF ( err_io /= 0 ) THEN
!file does not exist
CALL Catch ('error', 'Meteo', 'out point file does not exist')
END IF
!Read metadata
CALL ReadMetadata (fileunit, sites)
!set time increment
timeIncrementSites = sites % timeIncrement
!check dt
IF (.NOT. ( MOD ( sites % timeIncrement, dtMeteo ) == 0 ) ) THEN
CALL Catch ('error', 'Meteo', 'dt out sites must be multiple of dtMeteo ')
END IF
CLOSE ( fileunit )
!create virtual network and initialize file for output
!precipitation
IF ( dtPrecipitation > 0 ) THEN
fileUnitPointPrecipitation = GetUnit ()
OPEN ( unit = fileUnitPointPrecipitation, &
file = TRIM(path_out) // 'point_precipitation.fts' )
CALL CopyNetwork ( sites, sitesPrecipitation )
sitesPrecipitation % description = 'precipitation data exported from FEST'
sitesPrecipitation % unit = 'mm'
sitesPrecipitation % offsetZ = 2.
CALL WriteMetadata ( network = sitesPrecipitation, &
fileunit = fileUnitPointPrecipitation )
CALL WriteData (sitesPrecipitation, fileUnitPointPrecipitation, .TRUE.)
END IF
!air temperature
IF ( dtTemperature > 0 ) THEN
fileUnitPointTemperature = GetUnit ()
OPEN ( unit = fileUnitPointTemperature, &
file = TRIM(path_out) // 'point_temperature.fts' )
CALL CopyNetwork ( sites, sitesTemperature )
sitesTemperature % description = 'air temperature data exported from FEST'
sitesTemperature % unit = 'degree Celsius'
sitesTemperature % offsetZ = 2.
CALL WriteMetadata ( network = sitesTemperature, &
fileunit = fileUnitPointTemperature )
CALL WriteData (sitesTemperature, fileUnitPointTemperature, .TRUE.)
END IF
!solar radiation
IF ( dtRadiation > 0 ) THEN
fileUnitPointRadiation = GetUnit ()
OPEN ( unit = fileUnitPointRadiation, &
file = TRIM(path_out) // 'point_radiation.fts' )
CALL CopyNetwork ( sites, sitesRadiation )
sitesRadiation % description = 'solar radiation data exported from FEST'
sitesRadiation % unit = 'w/m2'
sitesRadiation % offsetZ = 2.
CALL WriteMetadata ( network = sitesRadiation, &
fileunit = fileUnitPointRadiation )
CALL WriteData (sitesRadiation, fileUnitPointRadiation, .TRUE.)
END IF
!air relative humidity
IF ( dtRelHumidity > 0 ) THEN
fileUnitPointRH = GetUnit ()
OPEN ( unit = fileUnitPointRH, &
file = TRIM(path_out) // 'point_RH.fts' )
CALL CopyNetwork ( sites, sitesRH )
sitesRH % description = 'air relative humidity data exported from FEST'
sitesRH % unit = '% 0-100'
sitesRH % offsetZ = 2.
CALL WriteMetadata ( network = sitesRH, &
fileunit = fileUnitPointRH )
CALL WriteData (sitesRH, fileUnitPointRH, .TRUE.)
END IF
!wind speed
IF ( dtWindSpeed > 0 ) THEN
fileUnitPointWS = GetUnit ()
OPEN ( unit = fileUnitPointWS, &
file = TRIM(path_out) // 'point_WS.fts' )
CALL CopyNetwork ( sites, sitesWS )
sitesWS % description = 'wind speed data exported from FEST'
sitesWS % unit = 'm/s'
sitesWS % offsetZ = 10.
CALL WriteMetadata ( network = sitesWS, &
fileunit = fileUnitPointWS )
CALL WriteData (sitesWS, fileUnitPointWS, .TRUE.)
END IF
! destroy sites
CALL DestroyNetwork ( sites )
RETURN
END SUBROUTINE MeteoPointInit
!==============================================================================
!| Description:
! Read meteorological forcings
SUBROUTINE MeteoRead &
!
( time, dem, albedo )
IMPLICIT NONE
!Arguments with intent(in):
TYPE (DateTime), INTENT(IN) :: time !!current time
TYPE (grid_real), OPTIONAL, INTENT(IN) :: dem !!used to apply drift of station data
TYPE (grid_real), OPTIONAL, INTENT(IN) :: albedo !!used to apply drift of radiation site data
!-------------------------end of declarations----------------------------------
IF (dtPrecipitation > 0) THEN
CALL PrecipitationRead (time, dem)
END IF
IF (dtPrecipitationDaily > 0) THEN
CALL PrecipitationDailyRead (time, dem)
END IF
IF (dtTemperature > 0) THEN
CALL AirTemperatureRead (time, dem)
END IF
IF (dtTemperatureDailyMean > 0) THEN
CALL AirTemperatureDailyMeanRead (time, dem)
END IF
IF (dtTemperatureDailyMax > 0) THEN
CALL AirTemperatureDailyMaxRead (time, dem)
END IF
IF (dtTemperatureDailyMin > 0) THEN
CALL AirTemperatureDailyMinRead (time, dem)
END IF
IF (dtRelHumidity > 0) THEN
CALL AirRelativeHumidityRead (time)
END IF
IF (dtRadiation > 0) THEN
CALL SolarRadiationRead (time, dem, albedo, temperatureAir, relHumidityAir )
END IF
IF (dtWindSpeed > 0) THEN
CALL WindFluxRead (time, dem)
END IF
IF ( time == timePointExport ) THEN
CALL MeteoPointExport ( time )
timePointExport = timePointExport + timeIncrementSites
END IF
RETURN
END SUBROUTINE MeteoRead
!==============================================================================
!| Description:
! Export of point site data
SUBROUTINE MeteoPointExport &
!
( time )
IMPLICIT NONE
!Arguments with intent(in):
TYPE (DateTime), INTENT (IN) :: time
!local declarations:
INTEGER (KIND = short) :: i
!-------------------------end of declarations----------------------------------
!precipitation
IF ( dtPrecipitation > 0 ) THEN
!set current time
sitesPrecipitation % time = time
!populate data
CALL AssignDataFromGrid (precipitationRate, sitesPrecipitation )
!unit conversion m/s -> mm
DO i = 1, sitesPrecipitation % countObs
IF ( sitesPrecipitation % obs (i) % value /= &
sitesPrecipitation % nodata ) THEN
sitesPrecipitation % obs (i) % value = &
sitesPrecipitation % obs (i) % value * dtPrecipitation * 1000.
END IF
END DO
!write data
CALL WriteData (sitesPrecipitation, fileUnitPointPrecipitation)
END IF
!air temperature
IF ( dtTemperature > 0 ) THEN
!set current time
sitesTemperature % time = time
!populate data
CALL AssignDataFromGrid (temperatureAir, sitesTemperature )
!write data
CALL WriteData (sitesTemperature, fileUnitPointTemperature)
END IF
!solar radiation
IF ( dtRadiation > 0 ) THEN
!set current time
sitesRadiation % time = time
!populate data
CALL AssignDataFromGrid ( radiation, sitesRadiation )
!write data
CALL WriteData ( sitesRadiation, fileUnitPointRadiation )
END IF
!air relative humidity
IF ( dtRelHumidity > 0 ) THEN
!set current time
sitesRH % time = time
!populate data
CALL AssignDataFromGrid ( relHumidityAir, sitesRH )
!write data
CALL WriteData ( sitesRH, fileUnitPointRH )
END IF
!wind speed
IF ( dtWindSpeed > 0 ) THEN
!set current time
sitesWS % time = time
!populate data
CALL AssignDataFromGrid ( windSpeed, sitesWS )
!write data
CALL WriteData ( sitesWS, fileUnitPointWS )
END IF
RETURN
END SUBROUTINE MeteoPointExport
END MODULE Meteo