Manage meteorological forcings
!! Manage meteorological forcings !|author: <a href="mailto:giovanni.ravazzani@polimi.it">Giovanni Ravazzani</a> ! license: <a href="http://www.gnu.org/licenses/">GPL</a> ! !### 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 <http://www.gnu.org/licenses/> ! !### 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