28 USE mo_kind,
ONLY : i4, dp
29 USE mo_constants,
ONLY : yearmonths
31 use mo_message,
only : message, error_message
33 use mo_sentinel,
only : set_sentinel, check_sentinel
34 use mo_datetime,
only : datetime, timedelta, zero_delta, one_hour, one_day
45 character(256) :: dir_nml_name =
'directories_mHM'
46 character(256) :: weight_nml_name =
'nightDayRatio'
48 CHARACTER(256) :: file_meteo_header =
'header.txt'
50 INTEGER :: umeteo_header = 50
52 logical :: bound_error
53 integer(i4) :: pet_case
54 integer(i4) :: riv_temp_case
56 integer(i4),
public :: ntstepforcingday
58 logical,
public :: is_hourly_forcing
59 integer(i4),
public :: timestep
60 integer(i4),
public :: ntstepday
61 real(dp),
public :: ntstepday_dp
65 type(
grid),
dimension(:),
allocatable,
public :: level2
69 integer(i4),
dimension(:),
allocatable,
public :: timestep_model_inputs
70 logical,
public :: read_meteo_weights
71 character(256),
public :: inputformat_meteo_forcings
76 character(256),
dimension(:),
allocatable,
public :: dir_meteo_header
77 character(256),
dimension(:),
allocatable,
public :: dirprecipitation
78 character(256),
dimension(:),
allocatable,
public :: dirtemperature
79 character(256),
dimension(:),
allocatable,
public :: dirmintemperature
80 character(256),
dimension(:),
allocatable,
public :: dirmaxtemperature
81 character(256),
dimension(:),
allocatable,
public :: dirnetradiation
82 character(256),
dimension(:),
allocatable,
public :: dirabsvappressure
83 character(256),
dimension(:),
allocatable,
public :: dirwindspeed
84 character(256),
dimension(:),
allocatable,
public :: dirreferenceet
86 character(256),
dimension(:),
allocatable,
public :: dirradiation
94 real(dp),
public,
dimension(:, :, :),
allocatable :: l1_temp_weights
95 real(dp),
public,
dimension(:, :, :),
allocatable :: l1_pet_weights
96 real(dp),
public,
dimension(:, :, :),
allocatable :: l1_pre_weights
97 real(dp),
public,
dimension(:, :),
allocatable :: l1_pre
98 real(dp),
public,
dimension(:, :),
allocatable :: l1_temp
99 real(dp),
public,
dimension(:, :),
allocatable :: l1_pet
100 real(dp),
public,
dimension(:, :),
allocatable :: l1_tmin
101 real(dp),
public,
dimension(:, :),
allocatable :: l1_tmax
102 real(dp),
public,
dimension(:, :),
allocatable :: l1_netrad
103 real(dp),
public,
dimension(:, :),
allocatable :: l1_absvappress
104 real(dp),
public,
dimension(:, :),
allocatable :: l1_windspeed
106 real(dp),
public,
dimension(:, :),
allocatable :: l1_ssrd
107 real(dp),
public,
dimension(:, :),
allocatable :: l1_strd
108 real(dp),
public,
dimension(:, :),
allocatable :: l1_tann
114 real(dp),
public,
dimension(int(YearMonths, i4)) :: fday_prec
115 real(dp),
public,
dimension(int(YearMonths, i4)) :: fnight_prec
116 real(dp),
public,
dimension(int(YearMonths, i4)) :: fday_pet
117 real(dp),
public,
dimension(int(YearMonths, i4)) :: fnight_pet
118 real(dp),
public,
dimension(int(YearMonths, i4)) :: fday_temp
119 real(dp),
public,
dimension(int(YearMonths, i4)) :: fnight_temp
120 real(dp),
public,
dimension(int(YearMonths, i4)) :: fday_ssrd
121 real(dp),
public,
dimension(int(YearMonths, i4)) :: fnight_ssrd
122 real(dp),
public,
dimension(int(YearMonths, i4)) :: fday_strd
123 real(dp),
public,
dimension(int(YearMonths, i4)) :: fnight_strd
129 integer(i4) :: s_meteo
131 integer(i4) :: e_meteo
133 integer(i4) :: imeteots
139 integer(i4) :: ndomains
140 integer(i4),
dimension(:),
allocatable :: indices
141 integer(i4),
dimension(:),
allocatable :: l0datafrom
149 type(timedelta) :: couple_step_delta
150 type(datetime) :: couple_pre_time
151 type(datetime) :: couple_temp_time
152 type(datetime) :: couple_pet_time
153 type(datetime) :: couple_tmin_time
154 type(datetime) :: couple_tmax_time
155 type(datetime) :: couple_netrad_time
156 type(datetime) :: couple_absvappress_time
157 type(datetime) :: couple_windspeed_time
158 type(datetime) :: couple_ssrd_time
159 type(datetime) :: couple_strd_time
160 type(datetime) :: couple_tann_time
161 logical,
public :: couple_pre
162 logical,
public :: couple_temp
163 logical,
public :: couple_pet
164 logical,
public :: couple_tmin
165 logical,
public :: couple_tmax
166 logical,
public :: couple_netrad
167 logical,
public :: couple_absvappress
168 logical,
public :: couple_windspeed
169 logical,
public :: couple_ssrd
170 logical,
public :: couple_strd
171 logical,
public :: couple_tann
172 logical,
public :: couple_all
173 logical,
public :: couple_is_hourly
211 if (
allocated(self%indices) )
deallocate(self%indices)
212 if (
allocated(self%L0DataFrom) )
deallocate(self%L0DataFrom)
213 if (
allocated(self%timeStep_model_inputs) )
deallocate(self%timeStep_model_inputs)
214 if (
allocated(self%dir_meteo_header) )
deallocate(self%dir_meteo_header)
215 if (
allocated(self%dirPrecipitation) )
deallocate(self%dirPrecipitation)
216 if (
allocated(self%dirTemperature) )
deallocate(self%dirTemperature)
217 if (
allocated(self%dirMinTemperature) )
deallocate(self%dirMinTemperature)
218 if (
allocated(self%dirMaxTemperature) )
deallocate(self%dirMaxTemperature)
219 if (
allocated(self%dirNetRadiation) )
deallocate(self%dirNetRadiation)
220 if (
allocated(self%dirabsVapPressure) )
deallocate(self%dirabsVapPressure)
221 if (
allocated(self%dirwindspeed) )
deallocate(self%dirwindspeed)
222 if (
allocated(self%dirReferenceET) )
deallocate(self%dirReferenceET)
223 if (
allocated(self%dirRadiation) )
deallocate(self%dirRadiation)
224 if (
allocated(self%level2) )
deallocate(self%level2)
225 if (
allocated(self%L1_temp_weights) )
deallocate(self%L1_temp_weights)
226 if (
allocated(self%L1_pet_weights) )
deallocate(self%L1_pet_weights)
227 if (
allocated(self%L1_pre_weights) )
deallocate(self%L1_pre_weights)
228 if (
allocated(self%L1_pre) )
deallocate(self%L1_pre)
229 if (
allocated(self%L1_temp) )
deallocate(self%L1_temp)
230 if (
allocated(self%L1_pet) )
deallocate(self%L1_pet)
231 if (
allocated(self%L1_tmin) )
deallocate(self%L1_tmin)
232 if (
allocated(self%L1_tmax) )
deallocate(self%L1_tmax)
233 if (
allocated(self%L1_netrad) )
deallocate(self%L1_netrad)
234 if (
allocated(self%L1_absvappress) )
deallocate(self%L1_absvappress)
235 if (
allocated(self%L1_windspeed) )
deallocate(self%L1_windspeed)
236 if (
allocated(self%L1_ssrd) )
deallocate(self%L1_ssrd)
237 if (
allocated(self%L1_strd) )
deallocate(self%L1_strd)
238 if (
allocated(self%L1_tann) )
deallocate(self%L1_tann)
243 subroutine config(self, file_namelist, unamelist, optimize, domainMeta, processMatrix, timeStep, couple_cfg)
247 use mo_nml,
only : close_nml, open_nml, position_nml
253 character(*),
intent(in) :: file_namelist
254 integer,
intent(in) :: unamelist
255 logical,
intent(in) :: optimize
257 integer(i4),
dimension(nProcesses, 3),
intent(in) :: processMatrix
258 integer(i4),
intent(in) :: timeStep
261 integer(i4),
dimension(maxNoDomains) :: time_step_model_inputs
262 character(256),
dimension(maxNoDomains) :: dir_meteo_header
263 character(256),
dimension(maxNoDomains) :: dir_Precipitation
264 character(256),
dimension(maxNoDomains) :: dir_Temperature
265 character(256),
dimension(maxNoDomains) :: dir_MinTemperature
266 character(256),
dimension(maxNoDomains) :: dir_MaxTemperature
267 character(256),
dimension(maxNoDomains) :: dir_NetRadiation
268 character(256),
dimension(maxNoDomains) :: dir_windspeed
269 character(256),
dimension(maxNoDomains) :: dir_absVapPressure
270 character(256),
dimension(maxNoDomains) :: dir_ReferenceET
271 character(256),
dimension(maxNoDomains) :: dir_Radiation
272 character(256) :: inputFormat_meteo_forcings
274 logical :: read_meteo_weights, bound_error
275 real(dp),
dimension(int(YearMonths, i4)) :: fnight_prec
276 real(dp),
dimension(int(YearMonths, i4)) :: fnight_pet
277 real(dp),
dimension(int(YearMonths, i4)) :: fnight_temp
278 real(dp),
dimension(int(YearMonths, i4)) :: fnight_ssrd
279 real(dp),
dimension(int(YearMonths, i4)) :: fnight_strd
281 integer(i4) :: domainID, iDomain
284 namelist /directories_mhm/ &
285 inputformat_meteo_forcings, &
291 dir_mintemperature, &
292 dir_maxtemperature, &
293 dir_absvappressure, &
297 time_step_model_inputs
300 namelist /nightdayratio/ &
301 read_meteo_weights, &
309 self%couple_cfg = couple_cfg
312 self%nDomains = domainmeta%nDomains
313 allocate(self%indices(self%nDomains))
314 allocate(self%L0DataFrom(self%nDomains))
315 self%indices(:) = domainmeta%indices(:)
316 self%L0DataFrom(:) = domainmeta%L0DataFrom(:)
322 self%pet_case = processmatrix(5,1)
323 self%riv_temp_case = processmatrix(11,1)
325 self%timeStep = timestep
326 self%nTStepDay = 24_i4 / timestep
327 self%nTstepDay_dp = real(self%nTStepDay, dp)
330 allocate(self%dir_meteo_header(self%nDomains))
331 allocate(self%dirPrecipitation(self%nDomains))
332 allocate(self%dirTemperature(self%nDomains))
333 allocate(self%dirwindspeed(self%nDomains))
334 allocate(self%dirabsVapPressure(self%nDomains))
335 allocate(self%dirReferenceET(self%nDomains))
336 allocate(self%dirMinTemperature(self%nDomains))
337 allocate(self%dirMaxTemperature(self%nDomains))
338 allocate(self%dirNetRadiation(self%nDomains))
339 allocate(self%dirRadiation(self%nDomains))
341 allocate(self%timestep_model_inputs(self%nDomains))
344 call open_nml(file_namelist, unamelist, quiet=.true.)
349 call set_sentinel(dir_meteo_header)
350 inputformat_meteo_forcings =
"nc"
352 call position_nml(self%dir_nml_name, unamelist)
353 read(unamelist, nml = directories_mhm)
355 self%bound_error = bound_error
356 self%inputFormat_meteo_forcings = inputformat_meteo_forcings
358 do idomain = 1, self%nDomains
359 domainid = self%indices(idomain)
360 self%timestep_model_inputs(idomain) = time_step_model_inputs(domainid)
361 self%dirPrecipitation(idomain) = dir_precipitation(domainid)
362 self%dirTemperature(idomain) = dir_temperature(domainid)
363 self%dirReferenceET(idomain) = dir_referenceet(domainid)
364 self%dirMinTemperature(idomain) = dir_mintemperature(domainid)
365 self%dirMaxTemperature(idomain) = dir_maxtemperature(domainid)
366 self%dirNetRadiation(idomain) = dir_netradiation(domainid)
367 self%dirwindspeed(idomain) = dir_windspeed(domainid)
368 self%dirabsVapPressure(idomain) = dir_absvappressure(domainid)
370 self%dirRadiation(idomain) = dir_radiation(domainid)
372 if (check_sentinel(dir_meteo_header(domainid)))
then
373 self%dir_meteo_header(idomain) = self%dirPrecipitation(idomain)
375 self%dir_meteo_header(idomain) = dir_meteo_header(domainid)
380 if (any(self%timestep_model_inputs .ne. 0) .and. .not. all(self%timestep_model_inputs .ne. 0))
then
381 call error_message(
'***ERROR: timestep_model_inputs either have to be all zero or all non-zero')
384 if (optimize .and. (any(self%timestep_model_inputs .ne. 0)))
then
385 call error_message(
'***ERROR: optimize and chunk read is switched on! (set timestep_model_inputs to zero)')
393 fnight_strd = 0.45_dp
396 call position_nml(self%weight_nml_name, unamelist)
397 read(unamelist, nml = nightdayratio)
398 self%read_meteo_weights = read_meteo_weights
399 self%fnight_prec = fnight_prec
400 self%fnight_pet = fnight_pet
401 self%fnight_temp = fnight_temp
402 self%fnight_ssrd = fnight_ssrd
403 self%fnight_strd = fnight_strd
404 self%fday_prec = 1.0_dp - self%fnight_prec
405 self%fday_pet = 1.0_dp - self%fnight_pet
406 self%fday_temp = -1.0_dp * self%fnight_temp
407 self%fday_ssrd = 1.0_dp - self%fnight_ssrd
408 self%fday_strd = 1.0_dp - self%fnight_strd
414 call close_nml(unamelist)
417 self%couple_is_hourly = .false.
418 self%couple_all = .false.
419 self%couple_pre = self%couple_cfg%active() .and. self%couple_cfg%meteo_expect_pre
420 self%couple_temp = self%couple_cfg%active() .and. self%couple_cfg%meteo_expect_temp
421 self%couple_pet = self%couple_cfg%active() .and. self%couple_cfg%meteo_expect_pet
422 self%couple_tmin = self%couple_cfg%active() .and. self%couple_cfg%meteo_expect_tmin
423 self%couple_tmax = self%couple_cfg%active() .and. self%couple_cfg%meteo_expect_tmax
424 self%couple_netrad = self%couple_cfg%active() .and. self%couple_cfg%meteo_expect_netrad
425 self%couple_absvappress = self%couple_cfg%active() .and. self%couple_cfg%meteo_expect_absvappress
426 self%couple_windspeed = self%couple_cfg%active() .and. self%couple_cfg%meteo_expect_windspeed
427 self%couple_ssrd = self%couple_cfg%active() .and. self%couple_cfg%meteo_expect_ssrd
428 self%couple_strd = self%couple_cfg%active() .and. self%couple_cfg%meteo_expect_strd
429 self%couple_tann = self%couple_cfg%active() .and. self%couple_cfg%meteo_expect_tann
430 if (self%couple_cfg%active())
then
431 self%couple_step_delta = timedelta(hours=self%couple_cfg%meteo_timestep)
432 self%couple_is_hourly = self%couple_step_delta == one_hour()
434 if (self%couple_cfg%meteo_expect_pre) self%couple_pre_time = datetime()
435 if (self%couple_cfg%meteo_expect_temp) self%couple_temp_time = datetime()
437 if (self%couple_cfg%meteo_expect_pet) self%couple_pet_time = datetime()
438 if (self%couple_cfg%meteo_expect_tmin) self%couple_tmin_time = datetime()
439 if (self%couple_cfg%meteo_expect_tmax) self%couple_tmax_time = datetime()
440 if (self%couple_cfg%meteo_expect_netrad) self%couple_netrad_time = datetime()
441 if (self%couple_cfg%meteo_expect_absvappress) self%couple_absvappress_time = datetime()
442 if (self%couple_cfg%meteo_expect_windspeed) self%couple_windspeed_time = datetime()
444 if (self%couple_cfg%meteo_expect_ssrd) self%couple_ssrd_time = datetime()
445 if (self%couple_cfg%meteo_expect_strd) self%couple_strd_time = datetime()
446 if (self%couple_cfg%meteo_expect_tann) self%couple_tann_time = datetime()
448 self%couple_all = self%couple_cfg%meteo_expect_pre .and. self%couple_cfg%meteo_expect_temp
449 select case (self%pet_case)
451 self%couple_all = self%couple_all .and. self%couple_cfg%meteo_expect_pet
452 if (self%couple_cfg%meteo_expect_tmin)
call error_message(
"Coupling: tmin expected but not needed for PET.")
453 if (self%couple_cfg%meteo_expect_tmax)
call error_message(
"Coupling: tmax expected but not needed for PET.")
454 if (self%couple_cfg%meteo_expect_netrad)
call error_message(
"Coupling: netrad expected but not needed for PET.")
455 if (self%couple_cfg%meteo_expect_absvappress)
call error_message(
"Coupling: absvappress expected but not needed for PET.")
456 if (self%couple_cfg%meteo_expect_windspeed)
call error_message(
"Coupling: windspeed expected but not needed for PET.")
459 self%couple_all = self%couple_all .and. self%couple_cfg%meteo_expect_tmin
460 self%couple_all = self%couple_all .and. self%couple_cfg%meteo_expect_tmax
461 if (self%couple_cfg%meteo_expect_pet)
call error_message(
"Coupling: pet expected but not needed for PET.")
462 if (self%couple_cfg%meteo_expect_netrad)
call error_message(
"Coupling: netrad expected but not needed for PET.")
463 if (self%couple_cfg%meteo_expect_absvappress)
call error_message(
"Coupling: absvappress expected but not needed for PET.")
464 if (self%couple_cfg%meteo_expect_windspeed)
call error_message(
"Coupling: windspeed expected but not needed for PET.")
467 self%couple_all = self%couple_all .and. self%couple_cfg%meteo_expect_netrad
468 if (self%couple_cfg%meteo_expect_pet)
call error_message(
"Coupling: pet expected but not needed for PET.")
469 if (self%couple_cfg%meteo_expect_tmin)
call error_message(
"Coupling: tmin expected but not needed for PET.")
470 if (self%couple_cfg%meteo_expect_tmax)
call error_message(
"Coupling: tmax expected but not needed for PET.")
471 if (self%couple_cfg%meteo_expect_absvappress)
call error_message(
"Coupling: absvappress expected but not needed for PET.")
472 if (self%couple_cfg%meteo_expect_windspeed)
call error_message(
"Coupling: windspeed expected but not needed for PET.")
475 self%couple_all = self%couple_all .and. self%couple_cfg%meteo_expect_netrad
476 self%couple_all = self%couple_all .and. self%couple_cfg%meteo_expect_absvappress
477 self%couple_all = self%couple_all .and. self%couple_cfg%meteo_expect_windspeed
478 if (self%couple_cfg%meteo_expect_pet)
call error_message(
"Coupling: pet expected but not needed for PET.")
479 if (self%couple_cfg%meteo_expect_tmin)
call error_message(
"Coupling: tmin expected but not needed for PET.")
480 if (self%couple_cfg%meteo_expect_tmax)
call error_message(
"Coupling: tmax expected but not needed for PET.")
483 if ( self%riv_temp_case == 0 )
then
484 if (self%couple_cfg%meteo_expect_ssrd)
call error_message(
"Coupling: ssrd expected but river temperature not activated.")
485 if (self%couple_cfg%meteo_expect_strd)
call error_message(
"Coupling: strd expected but river temperature not activated.")
486 if (self%couple_cfg%meteo_expect_tann)
call error_message(
"Coupling: tann expected but river temperature not activated.")
488 self%couple_all = self%couple_all .and. self%couple_cfg%meteo_expect_ssrd
489 self%couple_all = self%couple_all .and. self%couple_cfg%meteo_expect_strd
490 self%couple_all = self%couple_all .and. self%couple_cfg%meteo_expect_tann
500 integer(i4),
intent(in) :: idomain
501 single_read = self%timeStep_model_inputs(idomain) == 0_i4
511 use mo_string_utils,
only : num2str
517 type(
grid),
dimension(:),
intent(in) :: level0
519 type(
grid),
dimension(:),
intent(in) :: level1
522 integer(i4) :: nrows2, ncols2
523 real(dp) :: xllcorner2, yllcorner2
524 real(dp) :: cellsize2, nodata_dummy
526 character(256) :: fName
528 integer(i4) :: iDomain
531 allocate(self%level2(self%nDomains))
534 if (self%couple_all)
then
535 self%level2(:) = level1(:)
539 do idomain = 1, self%nDomains
541 fname = trim(adjustl(self%dir_meteo_header(idomain))) // trim(adjustl(self%file_meteo_header))
543 nrows2, ncols2, xllcorner2, yllcorner2, cellsize2, nodata_dummy)
545 call init_lowres_level(level0(self%L0DataFrom(idomain)), cellsize2, self%level2(idomain))
547 if ((ncols2 .ne. self%level2(idomain)%ncols) .or. &
548 (nrows2 .ne. self%level2(idomain)%nrows) .or. &
549 (abs(xllcorner2 - self%level2(idomain)%xllcorner) .gt. tiny(1.0_dp)) .or. &
550 (abs(yllcorner2 - self%level2(idomain)%yllcorner) .gt. tiny(1.0_dp)) .or. &
551 (abs(cellsize2 - self%level2(idomain)%cellsize) .gt. tiny(1.0_dp)))
then
552 call error_message(
' ***ERROR: subroutine L2_variable_init: size mismatch in grid file for level2 in domain ', &
553 trim(adjustl(num2str(idomain))),
'!', raise=.false.)
554 call error_message(
' Expected to have following properties (based on L0):', raise=.false.)
555 call error_message(
'... rows: ', trim(adjustl(num2str(self%level2(idomain)%nrows))),
', ', raise=.false.)
556 call error_message(
'... cols: ', trim(adjustl(num2str(self%level2(idomain)%ncols))),
', ', raise=.false.)
557 call error_message(
'... cellsize: ', trim(adjustl(num2str(self%level2(idomain)%cellsize))),
', ', raise=.false.)
558 call error_message(
'... xllcorner:', trim(adjustl(num2str(self%level2(idomain)%xllcorner))),
', ', raise=.false.)
559 call error_message(
'... yllcorner:', trim(adjustl(num2str(self%level2(idomain)%yllcorner))),
', ', raise=.false.)
560 call error_message(
' Provided (in precipitation file):', raise=.false.)
561 call error_message(
'... rows: ', trim(adjustl(num2str(nrows2))),
', ', raise=.false.)
562 call error_message(
'... cols: ', trim(adjustl(num2str(ncols2))),
', ', raise=.false.)
563 call error_message(
'... cellsize: ', trim(adjustl(num2str(cellsize2))),
', ', raise=.false.)
564 call error_message(
'... xllcorner:', trim(adjustl(num2str(xllcorner2))),
', ', raise=.false.)
565 call error_message(
'... yllcorner:', trim(adjustl(num2str(yllcorner2))),
', ')
580 integer(i4),
intent(in) :: tt
581 real(dp),
intent(in) :: time
582 integer(i4),
intent(in) :: iDomain
584 type(grid),
dimension(:),
intent(in) :: level1
586 type(period),
dimension(:),
intent(in) :: simPer
590 self%s1 = level1(idomain)%iStart
591 self%e1 = level1(idomain)%iEnd
595 if (self%single_read(idomain) .or. self%couple_all)
then
599 self%s_meteo = level1(idomain)%iStart
600 self%e_meteo = level1(idomain)%iEnd
604 if (self%couple_all)
then
607 self%iMeteoTS = ceiling(real(tt, dp) / real(nint( 24._dp / real(self%nTstepForcingDay, dp)), dp))
611 call self%prepare_data(tt, idomain, level1, simper)
614 self%e_meteo = level1(idomain)%iEnd - level1(idomain)%iStart + 1
616 self%iMeteoTS = ceiling(real(tt, dp) / real(nint( 24._dp / real(self%nTstepForcingDay, dp)), dp)) &
617 - (self%readPer%julStart - simper(idomain)%julStart)
647 use mo_string_utils,
only : num2str
648 use mo_timer,
only : timer_get, timer_start, timer_stop
654 integer(i4),
intent(in) :: tt
655 integer(i4),
intent(in) :: iDomain
657 type(grid),
dimension(:),
intent(in) :: level1
659 type(period),
dimension(:),
intent(in) :: simPer
663 integer(i4) :: domainID
666 if (self%couple_pre .and. .not.
allocated(self%L1_pre))
allocate(self%L1_pre(level1(idomain)%nCells, 1))
667 if (self%couple_temp .and. .not.
allocated(self%L1_temp))
allocate(self%L1_temp(level1(idomain)%nCells, 1))
668 if (self%couple_pet .and. .not.
allocated(self%L1_pet))
allocate(self%L1_pet(level1(idomain)%nCells, 1))
669 if (self%couple_tmin .and. .not.
allocated(self%L1_tmin))
allocate(self%L1_tmin(level1(idomain)%nCells, 1))
670 if (self%couple_tmax .and. .not.
allocated(self%L1_tmax))
allocate(self%L1_tmax(level1(idomain)%nCells, 1))
671 if (self%couple_netrad .and. .not.
allocated(self%L1_netrad))
allocate(self%L1_netrad(level1(idomain)%nCells, 1))
672 if (self%couple_absvappress .and. .not.
allocated(self%L1_absvappress))
allocate(self%L1_absvappress(level1(idomain)%nCells, 1))
673 if (self%couple_windspeed .and. .not.
allocated(self%L1_windspeed))
allocate(self%L1_windspeed(level1(idomain)%nCells, 1))
674 if (self%couple_ssrd .and. .not.
allocated(self%L1_ssrd))
allocate(self%L1_ssrd(level1(idomain)%nCells, 1))
675 if (self%couple_strd .and. .not.
allocated(self%L1_strd))
allocate(self%L1_strd(level1(idomain)%nCells, 1))
676 if (self%couple_tann .and. .not.
allocated(self%L1_tann))
allocate(self%L1_tann(level1(idomain)%nCells, 1))
678 domainid = self%indices(idomain)
681 call chunk_config(idomain, tt, self%nTstepDay, simper, self%timestep, self%timeStep_model_inputs, read_flag, self%readPer)
689 if (self%single_read(idomain))
call message(
' read meteo weights for tavg ...')
691 self%L1_temp_weights, level1=level1, level2=self%level2, ncvarname =
'tavg_weight')
693 if (self%single_read(idomain))
call message(
' read meteo weights for pet ...')
695 self%L1_pet_weights, level1=level1, level2=self%level2, ncvarname =
'pet_weight')
697 if (self%single_read(idomain))
call message(
' read meteo weights for pre ...')
699 self%L1_pre_weights, level1=level1, level2=self%level2, ncvarname =
'pre_weight')
703 if (self%timeStep_model_inputs(idomain) .ne. 0)
then
704 if (.not. self%couple_pre .and.
allocated(self%L1_pre))
deallocate(self%L1_pre)
705 if (.not. self%couple_temp .and.
allocated(self%L1_temp))
deallocate(self%L1_temp)
706 if (.not. self%couple_pet .and.
allocated(self%L1_pet))
deallocate(self%L1_pet)
707 if (.not. self%couple_tmin .and.
allocated(self%L1_tmin))
deallocate(self%L1_tmin)
708 if (.not. self%couple_tmax .and.
allocated(self%L1_tmax))
deallocate(self%L1_tmax)
709 if (.not. self%couple_netrad .and.
allocated(self%L1_netrad))
deallocate(self%L1_netrad)
710 if (.not. self%couple_absvappress .and.
allocated(self%L1_absvappress))
deallocate(self%L1_absvappress)
711 if (.not. self%couple_windspeed .and.
allocated(self%L1_windspeed))
deallocate(self%L1_windspeed)
715 if (self%single_read(idomain))
then
716 call message(
' Reading meteorological forcings for Domain: ', trim(adjustl(num2str(domainid))),
' ...')
721 if (.not. self%couple_pre)
then
722 if (self%single_read(idomain))
call message(
' read precipitation ...')
725 dataout1=self%L1_pre, &
726 readper=self%readPer, ntstepforcingday=self%nTstepForcingDay, level1=level1, level2=self%level2, &
727 lower = 0.0_dp, upper = 2000._dp, ncvarname =
'pre', bound_error=self%bound_error)
731 if (.not. self%couple_temp)
then
732 if (self%single_read(idomain))
call message(
' read temperature ...')
734 dataout1=self%L1_temp, &
735 readper=self%readPer, ntstepforcingday=self%nTstepForcingDay, level1=level1, level2=self%level2, &
736 lower = -100._dp, upper = 100._dp, ncvarname =
'tavg', bound_error=self%bound_error)
741 select case (self%pet_case)
743 if (.not. self%couple_pet)
then
744 if (self%single_read(idomain))
call message(
' read pet ...')
746 dataout1=self%L1_pet, &
747 readper=self%readPer, ntstepforcingday=self%nTstepForcingDay, level1=level1, level2=self%level2, &
748 lower = 0.0_dp, upper = 1000._dp, ncvarname =
'pet', bound_error=self%bound_error)
751 if ((idomain.eq.self%nDomains) .OR. (self%timeStep_model_inputs(idomain) .NE. 0))
then
752 allocate(self%L1_tmin(1, 1))
753 allocate(self%L1_tmax(1, 1))
754 allocate(self%L1_netrad(1, 1))
755 allocate(self%L1_absvappress(1, 1))
756 allocate(self%L1_windspeed(1, 1))
760 if (.not. self%couple_tmin)
then
761 if (self%single_read(idomain))
call message(
' read min. temperature ...')
763 dataout1=self%L1_tmin, &
764 readper=self%readPer, ntstepforcingday=self%nTstepForcingDay, level1=level1, level2=self%level2, &
765 lower = -100.0_dp, upper = 100._dp, ncvarname =
'tmin', bound_error=self%bound_error)
767 if (.not. self%couple_tmax)
then
768 if (self%single_read(idomain))
call message(
' read max. temperature ...')
770 dataout1=self%L1_tmax, &
771 readper=self%readPer, ntstepforcingday=self%nTstepForcingDay, level1=level1, level2=self%level2, &
772 lower = -100.0_dp, upper = 100._dp, ncvarname =
'tmax', bound_error=self%bound_error)
775 if ((idomain .eq. self%nDomains) .OR. (self%timeStep_model_inputs(idomain) .NE. 0))
then
776 allocate(self%L1_pet (
size(self%L1_tmax, dim = 1),
size(self%L1_tmax, dim = 2)))
777 allocate(self%L1_netrad(1, 1))
778 allocate(self%L1_absvappress(1, 1))
779 allocate(self%L1_windspeed(1, 1))
783 if (.not. self%couple_netrad)
then
784 if (self%single_read(idomain))
call message(
' read net radiation ...')
786 dataout1=self%L1_netrad, &
787 readper=self%readPer, ntstepforcingday=self%nTstepForcingDay, level1=level1, level2=self%level2, &
788 lower = -500.0_dp, upper = 1500._dp, ncvarname =
'net_rad', bound_error=self%bound_error)
791 if ((idomain .eq. self%nDomains) .OR. (self%timeStep_model_inputs(idomain) .NE. 0))
then
792 allocate(self%L1_pet (
size(self%L1_netrad, dim = 1),
size(self%L1_netrad, dim = 2)))
793 allocate(self%L1_tmin(1, 1))
794 allocate(self%L1_tmax(1, 1))
795 allocate(self%L1_absvappress(1, 1))
796 allocate(self%L1_windspeed(1, 1))
800 if (.not. self%couple_netrad)
then
801 if (self%single_read(idomain))
call message(
' read net radiation ...')
803 dataout1=self%L1_netrad, &
804 readper=self%readPer, ntstepforcingday=self%nTstepForcingDay, level1=level1, level2=self%level2, &
805 lower = -500.0_dp, upper = 1500._dp, ncvarname =
'net_rad', bound_error=self%bound_error)
807 if (.not. self%couple_absvappress)
then
808 if (self%single_read(idomain))
call message(
' read absolute vapour pressure ...')
810 dataout1=self%L1_absvappress, &
811 readper=self%readPer, ntstepforcingday=self%nTstepForcingDay, level1=level1, level2=self%level2, &
812 lower = 0.0_dp, upper = 15000.0_dp, ncvarname =
'eabs', bound_error=self%bound_error)
814 if (.not. self%couple_windspeed)
then
815 if (self%single_read(idomain))
call message(
' read windspeed ...')
817 dataout1=self%L1_windspeed, &
818 readper=self%readPer, ntstepforcingday=self%nTstepForcingDay, level1=level1, level2=self%level2, &
819 lower = 0.0_dp, upper = 250.0_dp, ncvarname =
'windspeed', bound_error=self%bound_error)
822 if ((idomain.eq.self%nDomains) .OR. (self%timeStep_model_inputs(idomain) .NE. 0))
then
823 allocate(self%L1_pet (
size(self%L1_absvappress, dim = 1),
size(self%L1_absvappress, dim = 2)))
824 allocate(self%L1_tmin(1, 1))
825 allocate(self%L1_tmax(1, 1))
830 if ( self%riv_temp_case .ne. 0 )
then
832 if (self%timeStep_model_inputs(idomain) .ne. 0)
then
833 if (.not. self%couple_ssrd .and.
allocated(self%L1_ssrd))
deallocate(self%L1_ssrd)
834 if (.not. self%couple_strd .and.
allocated(self%L1_strd))
deallocate(self%L1_strd)
835 if (.not. self%couple_tann .and.
allocated(self%L1_tann))
deallocate(self%L1_tann)
837 if (.not. self%couple_ssrd)
then
838 if (self%single_read(idomain))
call message(
' read short-wave radiation ...')
840 idomain, self%dirRadiation(idomain), self%inputFormat_meteo_forcings, &
841 dataout1=self%L1_ssrd, &
842 readper=self%readPer, ntstepforcingday=self%nTstepForcingDay, level1=level1, level2=self%level2, &
843 lower = 0.0_dp, upper = 1500._dp, ncvarname =
'ssrd', bound_error=self%bound_error)
845 if (.not. self%couple_strd)
then
846 if (self%single_read(idomain))
call message(
' read long-wave radiation ...')
848 idomain, self%dirRadiation(idomain), self%inputFormat_meteo_forcings, &
849 dataout1=self%L1_strd, &
850 readper=self%readPer, ntstepforcingday=self%nTstepForcingDay, level1=level1, level2=self%level2, &
851 lower = 0.0_dp, upper = 1500._dp, ncvarname =
'strd', bound_error=self%bound_error)
853 if (.not. self%couple_tann)
then
854 if (self%single_read(idomain))
call message(
' read annual mean temperature ...')
856 idomain, self%dirTemperature(idomain), self%inputFormat_meteo_forcings, &
857 dataout1=self%L1_tann, &
858 readper=self%readPer, ntstepforcingday=self%nTstepForcingDay, level1=level1, level2=self%level2, &
859 lower = -100.0_dp, upper = 100._dp, ncvarname =
'tann', bound_error=self%bound_error)
863 if (self%single_read(idomain))
then
865 call message(
' in ', trim(num2str(timer_get(1),
'(F9.3)')),
' seconds.')
871 if (self%couple_all)
then
872 self%nTstepForcingDay = int(one_day() / self%couple_step_delta, i4)
873 self%is_hourly_forcing = self%couple_is_hourly
875 self%is_hourly_forcing = (self%nTstepForcingDay .eq. 24_i4)
879 select case (self%pet_case)
881 if (self%couple_temp .and. self%couple_tmin .and. self%couple_tmax)
then
882 if (self%couple_is_hourly)
call error_message(
"Coupling: PET - Hargreaves-Samani needs daily data. Got hourly.")
883 else if (self%couple_temp .or. self%couple_tmin .or. self%couple_tmax)
then
884 if (self%couple_is_hourly)
call error_message(
"Coupling: PET - Hargreaves-Samani needs daily data. Got hourly.")
885 if (self%is_hourly_forcing)
call error_message(
"Meteo: PET - Hargreaves-Samani needs daily data. Got hourly.")
887 if (self%is_hourly_forcing)
call error_message(
"Meteo: PET - Hargreaves-Samani needs daily data. Got hourly.")
891 if (self%couple_temp .and. self%couple_netrad)
then
892 if (self%couple_is_hourly)
call error_message(
"Coupling: PET - Priestley-Taylor needs daily data. Got hourly.")
893 else if (self%couple_temp .or. self%couple_netrad)
then
894 if (self%couple_is_hourly)
call error_message(
"Coupling: PET - Priestley-Taylor needs daily data. Got hourly.")
895 if (self%is_hourly_forcing)
call error_message(
"Meteo: PET - Priestley-Taylor needs daily data. Got hourly.")
897 if (self%is_hourly_forcing)
call error_message(
"Meteo: PET - Priestley-Taylor needs daily data. Got hourly.")
901 if (self%couple_temp .and. self%couple_netrad .and. self%couple_absvappress .and. self%couple_windspeed)
then
902 if (self%couple_is_hourly)
call error_message(
"Coupling: PET - Penman-Monteith needs daily data. Got hourly.")
903 else if (self%couple_temp .or. self%couple_netrad .or. self%couple_absvappress .or. self%couple_windspeed)
then
904 if (self%couple_is_hourly)
call error_message(
"Coupling: PET - Penman-Monteith needs daily data. Got hourly.")
905 if (self%is_hourly_forcing)
call error_message(
"Meteo: PET - Penman-Monteith needs daily data. Got hourly.")
907 if (self%is_hourly_forcing)
call error_message(
"Meteo: PET - Penman-Monteith needs daily data. Got hourly.")
916 petLAIcorFactorL1, fAsp, HarSamCoeff, latitude, PrieTayAlpha, aeroResist, surfResist)
919 use mo_julian,
only : date2dec, dec2date
921 use mo_string_utils,
only : num2str
928 real(dp),
dimension(:),
intent(inout) :: pet_calc
930 real(dp),
dimension(:),
intent(in) :: petLAIcorFactorL1
932 real(dp),
dimension(:),
intent(in) :: fAsp
934 real(dp),
dimension(:),
intent(in) :: HarSamCoeff
936 real(dp),
dimension(:),
intent(in) :: latitude
938 real(dp),
dimension(:),
intent(in) :: PrieTayAlpha
940 real(dp),
dimension(:),
intent(in) :: aeroResist
942 real(dp),
dimension(:),
intent(in) :: surfResist
946 logical :: isday, is_hourly
947 integer(i4) :: year, month, day, hour
948 type(datetime) :: curr_dt
949 type(timedelta) :: meteo_time_delta
955 integer(i4) :: nCells1
957 integer(i4) :: k, i, s1
959 integer(i4) :: mTS_pet, mTS_temp, mTS_tmin, mTS_tmax, mTS_rn, mTS_avp, mTS_ws
962 call dec2date(self%time, yy = year, mm = month, dd = day, hh = hour)
963 curr_dt = datetime(year, month, day, hour)
966 ncells1 = self%e1 - self%s1 + 1
969 if (self%couple_pet)
then
970 meteo_time_delta = curr_dt - self%couple_pet_time
972 if (meteo_time_delta < zero_delta() .or. meteo_time_delta >= self%couple_step_delta) &
973 call error_message(
"meteo_handler: PET was expected from coupler, but has a wrong time-stamp.")
975 is_hourly = self%couple_is_hourly
977 mts_pet = self%iMeteoTS
978 is_hourly = self%is_hourly_forcing
981 if (self%couple_temp)
then
982 meteo_time_delta = curr_dt - self%couple_temp_time
984 if (meteo_time_delta < zero_delta() .or. meteo_time_delta >= self%couple_step_delta) &
985 call error_message(
"meteo_handler: temperature was expected from coupler, but has a wrong time-stamp.")
989 mts_temp = self%iMeteoTS
992 if (self%couple_tmin)
then
993 meteo_time_delta = curr_dt - self%couple_tmin_time
995 if (meteo_time_delta < zero_delta() .or. meteo_time_delta >= self%couple_step_delta) &
996 call error_message(
"meteo_handler: minimum temperature was expected from coupler, but has a wrong time-stamp.")
1000 mts_tmin = self%iMeteoTS
1003 if (self%couple_tmax)
then
1004 meteo_time_delta = curr_dt - self%couple_tmax_time
1006 if (meteo_time_delta < zero_delta() .or. meteo_time_delta >= self%couple_step_delta) &
1007 call error_message(
"meteo_handler: maximum temperature was expected from coupler, but has a wrong time-stamp.")
1011 mts_tmax = self%iMeteoTS
1014 if (self%couple_netrad)
then
1015 meteo_time_delta = curr_dt - self%couple_netrad_time
1017 if (meteo_time_delta < zero_delta() .or. meteo_time_delta >= self%couple_step_delta) &
1018 call error_message(
"meteo_handler: net-radiation was expected from coupler, but has a wrong time-stamp.")
1022 mts_rn = self%iMeteoTS
1025 if (self%couple_absvappress)
then
1026 meteo_time_delta = curr_dt - self%couple_absvappress_time
1028 if (meteo_time_delta < zero_delta() .or. meteo_time_delta >= self%couple_step_delta) &
1029 call error_message(
"meteo_handler: Abs. vapour pressure was expected from coupler, but has a wrong time-stamp.")
1033 mts_avp = self%iMeteoTS
1036 if (self%couple_windspeed)
then
1037 meteo_time_delta = curr_dt - self%couple_windspeed_time
1039 if (meteo_time_delta < zero_delta() .or. meteo_time_delta >= self%couple_step_delta) &
1040 call error_message(
"meteo_handler: windspeed was expected from coupler, but has a wrong time-stamp.")
1044 mts_ws = self%iMeteoTS
1048 isday = (hour .gt. 6) .AND. (hour .le. 18)
1056 i = self%s_meteo - 1 + k
1059 select case (self%pet_case)
1061 pet = petlaicorfactorl1(k) * self%L1_pet(i, mts_pet)
1064 pet = fasp(k) * self%L1_pet(i, mts_pet)
1068 if (self%L1_tmax(i, mts_tmax) .lt. self%L1_tmin(i, mts_tmin)) &
1069 call message(
'WARNING: tmax smaller than tmin at doy ', &
1070 num2str(doy),
' in year ', num2str(year),
' at cell', num2str(k),
'!')
1072 harsamcoeff=harsamcoeff(k), &
1074 tavg=self%L1_temp(i, mts_temp), &
1075 tmax=self%L1_tmax(i, mts_tmax), &
1076 tmin=self%L1_tmin(i, mts_tmin), &
1077 latitude=latitude(k), &
1083 prietayparam=prietayalpha(k), &
1084 rn=max(self%L1_netrad(i, mts_rn), 0.0_dp), &
1085 tavg=self%L1_temp(i, mts_temp))
1089 net_rad=max(self%L1_netrad(i, mts_rn), 0.0_dp), &
1090 tavg=self%L1_temp(i, mts_temp), &
1091 act_vap_pressure=self%L1_absvappress(i, mts_avp) / 1000.0_dp, &
1092 aerodyn_resistance=aeroresist(k) / self%L1_windspeed(i, mts_ws), &
1093 bulksurface_resistance=surfresist(k), &
1099 if (self%is_hourly_forcing)
then
1102 if (self%read_meteo_weights)
then
1105 meteo_val_day=pet, &
1106 meteo_val_weights=self%L1_pet_weights(s1 - 1 + k, month, hour + 1), &
1107 meteo_val=pet_calc(k))
1112 ntimesteps_day=self%nTstepDay_dp, &
1113 meteo_val_day=pet, &
1114 fday_meteo_val=self%fday_pet(month), &
1115 fnight_meteo_val=self%fnight_pet(month), &
1116 meteo_val=pet_calc(k))
1128 use mo_julian,
only : dec2date
1130 use mo_constants,
only : t0_dp
1136 real(dp),
dimension(:),
intent(inout) :: temp_calc
1138 logical :: isday, is_hourly
1139 integer(i4) :: year, month, day, hour
1140 type(datetime) :: curr_dt
1141 type(timedelta) :: meteo_time_delta
1144 integer(i4) :: nCells1
1146 integer(i4) :: k, i, s1, mTS
1149 call dec2date(self%time, yy=year, mm=month, dd=day, hh=hour)
1151 ncells1 = self%e1 - self%s1 + 1
1153 if (self%couple_temp)
then
1154 curr_dt = datetime(year, month, day, hour)
1155 meteo_time_delta = curr_dt - self%couple_temp_time
1157 if (meteo_time_delta < zero_delta() .or. meteo_time_delta >= self%couple_step_delta) &
1158 call error_message(
"meteo_handler: temperature was expected from coupler, but has a wrong time-stamp.")
1160 is_hourly = self%couple_is_hourly
1163 is_hourly = self%is_hourly_forcing
1168 temp_calc(:) = self%L1_temp(self%s_meteo : self%e_meteo, mts)
1173 isday = (hour .gt. 6) .AND. (hour .le. 18)
1181 i = self%s_meteo - 1 + k
1183 if (self%read_meteo_weights)
then
1186 meteo_val_day=self%L1_temp(i, mts), &
1187 meteo_val_weights=self%L1_temp_weights(s1 - 1 + k, month, hour + 1), &
1188 meteo_val=temp_calc(k), &
1189 weights_correction=t0_dp)
1194 ntimesteps_day=self%nTstepDay_dp, &
1195 meteo_val_day=self%L1_temp(i, mts), &
1196 fday_meteo_val=self%fday_temp(month), &
1197 fnight_meteo_val=self%fnight_temp(month), &
1198 meteo_val=temp_calc(k), &
1199 add_correction=.true.)
1210 use mo_julian,
only : dec2date
1217 real(dp),
dimension(:),
intent(inout) :: prec_calc
1219 logical :: isday, is_hourly
1220 integer(i4) :: year, month, day, hour
1221 type(datetime) :: curr_dt
1222 type(timedelta) :: meteo_time_delta
1225 integer(i4) :: nCells1
1227 integer(i4) :: k, i, s1, mTS
1230 call dec2date(self%time, yy=year, mm=month, dd=day, hh=hour)
1232 ncells1 = self%e1 - self%s1 + 1
1234 if (self%couple_pre)
then
1235 curr_dt = datetime(year, month, day, hour)
1236 meteo_time_delta = curr_dt - self%couple_pre_time
1238 if (meteo_time_delta < zero_delta() .or. meteo_time_delta >= self%couple_step_delta) &
1239 call error_message(
"meteo_handler: precipitation was expected from coupler, but has a wrong time-stamp.")
1241 is_hourly = self%couple_is_hourly
1244 is_hourly = self%is_hourly_forcing
1249 prec_calc(:) = self%L1_pre(self%s_meteo : self%e_meteo, mts)
1254 isday = (hour .gt. 6) .AND. (hour .le. 18)
1262 i = self%s_meteo - 1 + k
1265 if (self%read_meteo_weights)
then
1268 meteo_val_day=self%L1_pre(i, mts), &
1269 meteo_val_weights=self%L1_pre_weights(s1 - 1 + k, month, hour + 1), &
1270 meteo_val=prec_calc(k))
1275 ntimesteps_day=self%nTstepDay_dp, &
1276 meteo_val_day=self%L1_pre(i, mts), &
1277 fday_meteo_val=self%fday_prec(month), &
1278 fnight_meteo_val=self%fnight_prec(month), &
1279 meteo_val=prec_calc(k))
1290 use mo_julian,
only : dec2date
1297 real(dp),
dimension(:),
intent(inout) :: ssrd_calc
1299 logical :: isday, is_hourly
1300 integer(i4) :: year, month, day, hour
1301 type(datetime) :: curr_dt
1302 type(timedelta) :: meteo_time_delta
1305 integer(i4) :: nCells1
1307 integer(i4) :: k, i, s1, mTS
1310 call dec2date(self%time, yy=year, mm=month, dd=day, hh=hour)
1312 ncells1 = self%e1 - self%s1 + 1
1314 if (self%couple_ssrd)
then
1315 curr_dt = datetime(year, month, day, hour)
1316 meteo_time_delta = curr_dt - self%couple_ssrd_time
1318 if (meteo_time_delta < zero_delta() .or. meteo_time_delta >= self%couple_step_delta) &
1319 call error_message(
"meteo_handler: ssrd was expected from coupler, but has a wrong time-stamp.")
1321 is_hourly = self%couple_is_hourly
1324 is_hourly = self%is_hourly_forcing
1329 ssrd_calc(:) = self%L1_ssrd(self%s_meteo : self%e_meteo, mts)
1334 isday = (hour .gt. 6) .AND. (hour .le. 18)
1341 i = self%s_meteo - 1 + k
1346 ntimesteps_day=self%nTstepDay_dp, &
1347 meteo_val_day=self%L1_ssrd(i, mts), &
1348 fday_meteo_val=self%fday_ssrd(month), &
1349 fnight_meteo_val=self%fnight_ssrd(month), &
1350 meteo_val=ssrd_calc(k) &
1361 use mo_julian,
only : dec2date
1368 real(dp),
dimension(:),
intent(inout) :: strd_calc
1370 logical :: isday, is_hourly
1371 integer(i4) :: year, month, day, hour
1372 type(datetime) :: curr_dt
1373 type(timedelta) :: meteo_time_delta
1376 integer(i4) :: nCells1
1378 integer(i4) :: k, i, s1, mTS
1381 call dec2date(self%time, yy=year, mm=month, dd=day, hh=hour)
1383 ncells1 = self%e1 - self%s1 + 1
1385 if (self%couple_strd)
then
1386 curr_dt = datetime(year, month, day, hour)
1387 meteo_time_delta = curr_dt - self%couple_strd_time
1389 if (meteo_time_delta < zero_delta() .or. meteo_time_delta >= self%couple_step_delta) &
1390 call error_message(
"meteo_handler: strd was expected from coupler, but has a wrong time-stamp.")
1392 is_hourly = self%couple_is_hourly
1395 is_hourly = self%is_hourly_forcing
1400 strd_calc(:) = self%L1_strd(self%s_meteo : self%e_meteo, mts)
1405 isday = (hour .gt. 6) .AND. (hour .le. 18)
1412 i = self%s_meteo - 1 + k
1417 ntimesteps_day=self%nTstepDay_dp, &
1418 meteo_val_day=self%L1_strd(i, mts), &
1419 fday_meteo_val=self%fday_strd(month), &
1420 fnight_meteo_val=self%fnight_strd(month), &
1421 meteo_val=strd_calc(k) &
1431 use mo_julian,
only : dec2date
1437 real(dp),
dimension(:),
intent(inout) :: tann_calc
1439 type(datetime) :: curr_dt
1440 type(timedelta) :: meteo_time_delta
1441 integer(i4) :: year, month, day, hour, mTS
1443 if (self%couple_tann)
then
1445 call dec2date(self%time, yy=year, mm=month, dd=day, hh=hour)
1446 curr_dt = datetime(year, month, day, hour)
1447 meteo_time_delta = curr_dt - self%couple_tann_time
1449 if (meteo_time_delta < zero_delta() .or. meteo_time_delta >= self%couple_step_delta) &
1450 call error_message(
"meteo_handler: tann was expected from coupler, but has a wrong time-stamp.")
1457 tann_calc(:) = self%L1_tann(self%s_meteo : self%e_meteo, mts)
1463 year, month, day, hour, &
1477 integer(i4),
intent(in) :: year
1478 integer(i4),
intent(in) :: month
1479 integer(i4),
intent(in) :: day
1480 integer(i4),
intent(in),
optional :: hour
1481 real(dp),
dimension(:),
optional,
intent(in) :: pre
1482 real(dp),
dimension(:),
optional,
intent(in) :: temp
1483 real(dp),
dimension(:),
optional,
intent(in) :: pet
1484 real(dp),
dimension(:),
optional,
intent(in) :: tmin
1485 real(dp),
dimension(:),
optional,
intent(in) :: tmax
1486 real(dp),
dimension(:),
optional,
intent(in) :: netrad
1487 real(dp),
dimension(:),
optional,
intent(in) :: absvappress
1488 real(dp),
dimension(:),
optional,
intent(in) :: windspeed
1489 real(dp),
dimension(:),
optional,
intent(in) :: ssrd
1490 real(dp),
dimension(:),
optional,
intent(in) :: strd
1491 real(dp),
dimension(:),
optional,
intent(in) :: tann
1493 integer(i4) :: hour_
1494 type(datetime) :: input_time
1496 if (.not. self%couple_cfg%active()) &
1497 call error_message(
"meteo_handler%set_meteo: coupling was not activated.")
1501 if (
present(hour))
then
1503 else if (self%couple_cfg%meteo_timestep == 24_i4)
then
1506 if (hour_ == -1_i4) &
1507 call error_message(
"meteo_handler%set_meteo: hour for the meteo date needs to be given if the timestep is not daily.")
1508 input_time = datetime(year, month, day, hour_)
1511 if (self%couple_cfg%meteo_time_ref_endpoint) input_time = input_time - self%couple_step_delta
1514 if (mod(input_time%hour, self%couple_cfg%meteo_timestep) /= 0) &
1515 call error_message(
"meteo_handler%set_meteo: given time doesn't match couple timestep: ", input_time%str())
1518 if (
present(pre))
then
1519 if (.not. self%couple_pre) &
1520 call error_message(
"meteo_handler%set_meteo: precipitation was not set to be coupled.")
1521 self%couple_pre_time = input_time
1522 self%L1_pre(:, 1_i4) = pre(:)
1526 if (
present(temp))
then
1527 if (.not. self%couple_temp) &
1528 call error_message(
"meteo_handler%set_meteo: avg. temperature was not set to be coupled.")
1529 self%couple_temp_time = input_time
1530 self%L1_temp(:, 1_i4) = temp(:)
1534 if (
present(pet))
then
1535 if (.not. self%couple_pet) &
1536 call error_message(
"meteo_handler%set_meteo: PET was not set to be coupled.")
1537 self%couple_pet_time = input_time
1538 self%L1_pet(:, 1_i4) = pet(:)
1542 if (
present(tmin))
then
1543 if (.not. self%couple_tmin) &
1544 call error_message(
"meteo_handler%set_meteo: tmin was not set to be coupled.")
1545 self%couple_tmin_time = input_time
1546 self%L1_tmin(:, 1_i4) = tmin(:)
1550 if (
present(tmax))
then
1551 if (.not. self%couple_tmax) &
1552 call error_message(
"meteo_handler%set_meteo: tmax was not set to be coupled.")
1553 self%couple_tmax_time = input_time
1554 self%L1_tmax(:, 1_i4) = tmax(:)
1558 if (
present(netrad))
then
1559 if (.not. self%couple_netrad) &
1560 call error_message(
"meteo_handler%set_meteo: netrad was not set to be coupled.")
1561 self%couple_netrad_time = input_time
1562 self%L1_netrad(:, 1_i4) = netrad(:)
1566 if (
present(absvappress))
then
1567 if (.not. self%couple_absvappress) &
1568 call error_message(
"meteo_handler%set_meteo: absvappress was not set to be coupled.")
1569 self%couple_absvappress_time = input_time
1570 self%L1_absvappress(:, 1_i4) = absvappress(:)
1574 if (
present(windspeed))
then
1575 if (.not. self%couple_windspeed) &
1576 call error_message(
"meteo_handler%set_meteo: windspeed was not set to be coupled.")
1577 self%couple_windspeed_time = input_time
1578 self%L1_windspeed(:, 1_i4) = windspeed(:)
1582 if (
present(ssrd))
then
1583 if (.not. self%couple_ssrd) &
1584 call error_message(
"meteo_handler%set_meteo: ssrd was not set to be coupled.")
1585 self%couple_ssrd_time = input_time
1586 self%L1_ssrd(:, 1_i4) = ssrd(:)
1590 if (
present(strd))
then
1591 if (.not. self%couple_strd) &
1592 call error_message(
"meteo_handler%set_meteo: strd was not set to be coupled.")
1593 self%couple_strd_time = input_time
1594 self%L1_strd(:, 1_i4) = strd(:)
1598 if (
present(tann))
then
1599 if (.not. self%couple_tann) &
1600 call error_message(
"meteo_handler%set_meteo: tann was not set to be coupled.")
1601 self%couple_tann_time = input_time
1602 self%L1_tann(:, 1_i4) = tann(:)
Provides constants commonly used by mHM, mRM and MPR.
integer(i4), parameter, public maxnodomains
integer(i4), parameter, public nodata_i4
Provides common types needed by mHM, mRM and/or mpr.
Provides structures needed by mHM, mRM and/or mpr.
integer(i4), parameter, public nprocesses
Types to specify the coupling configuration of mHM.
subroutine clean_up(self)
clean up
subroutine, public set_domain_indices(grids, indices)
TODO: add description.
subroutine, public init_lowres_level(highres, target_resolution, lowres, highres_lowres_remap)
Level-1 variable initialization.
Class for the meteo handler.
subroutine set_meteo(self, year, month, day, hour, pre, temp, pet, tmin, tmax, netrad, absvappress, windspeed, ssrd, strd, tann)
set meteo_data from coupling
subroutine get_temp(self, temp_calc)
get surface temperature for the current timestep and domain
subroutine update_timestep(self, tt, time, idomain, level1, simper)
update the current time-step of the meteo_handler_type class
subroutine config(self, file_namelist, unamelist, optimize, domainmeta, processmatrix, timestep, couple_cfg)
configure the meteo_handler_type class from the mhm namelist
subroutine get_ssrd(self, ssrd_calc)
get surface short-wave (solar) radiation downwards for the current timestep and domain
subroutine get_corrected_pet(self, pet_calc, petlaicorfactorl1, fasp, harsamcoeff, latitude, prietayalpha, aeroresist, surfresist)
get corrected PET for the current timestep and domain
subroutine get_tann(self, tann_calc)
get annual mean surface temperature for the current timestep and domain
subroutine get_prec(self, prec_calc)
get precipitation for the current timestep and domain
subroutine init_level2(self, level0, level1)
Initialize meteo data and level-2 grid.
logical function single_read(self, idomain)
whether meteo data should be read completely at the begining
subroutine prepare_data(self, tt, idomain, level1, simper)
Prepare meteorological forcings data for a given variable.
subroutine get_strd(self, strd_calc)
get surface long-wave (thermal) radiation downwards for the current timestep and domain
Prepare meteorological forcings data for mHM.
subroutine, public chunk_config(idomain, tt, ntstepday, simper, timestep, timestep_model_inputs, read_flag, readper)
determines the start date, end date, and read_flag given Domain id and current timestep
subroutine, public meteo_weights_wrapper(idomain, read_meteo_weights, datapath, dataout1, level1, level2, lower, upper, ncvarname)
Prepare weights for meteorological forcings data for mHM at Level-1.
subroutine, public meteo_forcings_wrapper(idomain, datapath, inputformat, dataout1, readper, ntstepforcingday, level1, level2, lower, upper, ncvarname, bound_error)
Prepare meteorological forcings data for mHM at Level-1.
Provides mHM specific constants.
real(dp), parameter, public harsamconst
Hargreaves-Samani ref.
Module for calculating reference/potential evapotranspiration [mm d-1].
elemental pure real(dp) function, public pet_penman(net_rad, tavg, act_vap_pressure, aerodyn_resistance, bulksurface_resistance, a_s, a_sh)
Reference Evapotranspiration after Penman-Monteith.
elemental pure real(dp) function, public pet_hargreaves(harsamcoeff, harsamconst, tavg, tmax, tmin, latitude, doy)
Reference Evapotranspiration after Hargreaves.
elemental pure real(dp) function, public pet_priestly(prietayparam, rn, tavg)
Reference Evapotranspiration after Priestly-Taylor.
Reads spatial input data.
subroutine, public read_header_ascii(filename, fileunit, header_ncols, header_nrows, header_xllcorner, header_yllcorner, header_cellsize, header_nodata)
Reads header lines of ASCII files.
DOMAIN general description.
This is a container to hold all coupling configurations for mHM.
This is a handler for the meteorological forcings.