16 use mo_kind,
only: dp, i4
30 logical :: active = .false.
31 integer(i4) :: case = 0_i4
32 character(256) :: nml_name =
'config_riv_temp'
34 character(256),
dimension(:),
allocatable :: dir_riv_widths
35 character(256) :: riv_widths_file
36 character(256) :: riv_widths_name
37 real(dp),
public,
dimension(:),
allocatable :: l11_riv_widths
38 real(dp),
public,
dimension(:),
allocatable :: l11_riv_areas
40 real(dp) :: albedo_water
41 real(dp) :: pt_a_water
43 real(dp) :: emissivity_water
44 real(dp) :: turb_heat_ex_coeff
46 real(dp) :: delta_t = 0.1_dp
48 integer(i4) :: max_iter
49 real(dp) :: delta_iter
53 logical :: bisect_iter
54 real(dp) :: up_bnd_iter
55 real(dp) :: low_bnd_iter
57 real(dp),
dimension(:),
allocatable :: l1_runoff_e
58 real(dp),
dimension(:),
allocatable :: l1_acc_ssrd
59 real(dp),
dimension(:),
allocatable :: l1_acc_strd
60 real(dp),
dimension(:),
allocatable :: l1_acc_temp
61 real(dp),
dimension(:),
allocatable :: l1_ssrd_calc
62 real(dp),
dimension(:),
allocatable :: l1_strd_calc
63 real(dp),
dimension(:),
allocatable :: l1_tann_calc
68 real(dp),
dimension(:,:),
allocatable :: netnode_e_in
69 real(dp),
dimension(:,:),
allocatable :: netnode_e_r
70 real(dp),
dimension(:),
allocatable :: netnode_e_mod
71 real(dp),
dimension(:),
allocatable :: netnode_e_out
72 real(dp),
dimension(:),
allocatable :: l11_srad_net
73 real(dp),
dimension(:),
allocatable :: l11_lrad_in
74 real(dp),
dimension(:),
allocatable :: l11_air_temp
76 real(dp),
dimension(:),
allocatable :: river_temp
135 if (
allocated(self%L1_runoff_E) )
deallocate(self%L1_runoff_E)
136 if (
allocated(self%L1_acc_strd) )
deallocate(self%L1_acc_strd)
137 if (
allocated(self%L1_acc_ssrd) )
deallocate(self%L1_acc_ssrd)
138 if (
allocated(self%L1_acc_temp) )
deallocate(self%L1_acc_temp)
139 if (
allocated(self%dir_riv_widths) )
deallocate(self%dir_riv_widths)
140 if (
allocated(self%L11_riv_widths) )
deallocate(self%L11_riv_widths)
141 if (
allocated(self%L11_riv_areas) )
deallocate(self%L11_riv_areas)
142 if (
allocated(self%netNode_E_IN) )
deallocate(self%netNode_E_IN)
143 if (
allocated(self%netNode_E_R) )
deallocate(self%netNode_E_R)
144 if (
allocated(self%netNode_E_mod) )
deallocate(self%netNode_E_mod)
145 if (
allocated(self%netNode_E_out) )
deallocate(self%netNode_E_out)
146 if (
allocated(self%L11_srad_net) )
deallocate(self%L11_srad_net)
147 if (
allocated(self%L11_lrad_in) )
deallocate(self%L11_lrad_in)
148 if (
allocated(self%L11_air_temp) )
deallocate(self%L11_air_temp)
149 if (
allocated(self%river_temp) )
deallocate(self%river_temp)
151 if (
allocated(self%L1_ssrd_calc) )
deallocate(self%L1_ssrd_calc)
152 if (
allocated(self%L1_strd_calc) )
deallocate(self%L1_strd_calc)
153 if (
allocated(self%L1_tann_calc) )
deallocate(self%L1_tann_calc)
162 file_namelist_param, &
168 use mo_nml,
only : close_nml, open_nml, position_nml
170 USE mo_string_utils,
ONLY : num2str
175 character(*),
intent(in) :: file_namelist
176 character(*),
intent(in) :: file_namelist_param
177 integer,
intent(in) :: unamelist
178 integer,
intent(in) :: unamelist_param
181 real(dp) :: albedo_water
182 real(dp) :: pt_a_water
183 real(dp) :: emissivity_water
184 real(dp) :: turb_heat_ex_coeff
186 integer(i4) :: max_iter
187 real(dp) :: delta_iter
188 real(dp) :: step_iter
190 character(256),
dimension(maxNoDomains) :: dir_riv_widths
191 character(256) :: riv_widths_file
192 character(256) :: riv_widths_name
194 integer(i4) :: iDomain, domainID
197 namelist /config_riv_temp/ &
201 turb_heat_ex_coeff, &
210 allocate(self%dir_riv_widths(
domainmeta%nDomains))
213 albedo_water = 0.15_dp
215 emissivity_water = 0.96_dp
216 turb_heat_ex_coeff = 20.0_dp
218 delta_iter = 1.0e-02_dp
222 call open_nml(file_namelist, unamelist, quiet=.true.)
224 call position_nml(self%nml_name, unamelist)
226 read(unamelist, nml=config_riv_temp)
228 self%albedo_water = albedo_water
229 self%pt_a_water = pt_a_water
230 self%emissivity_water = emissivity_water
231 self%turb_heat_ex_coeff = turb_heat_ex_coeff
232 self%delta_iter = delta_iter
233 self%max_iter = max_iter
234 self%step_iter = step_iter
235 self%riv_widths_file = riv_widths_file
236 self%riv_widths_name = riv_widths_name
237 self%dir_riv_widths = dir_riv_widths
240 call close_nml(unamelist)
245 path=self%dir_riv_widths(idomain), &
246 text=
"(domain "//trim(num2str(domainid,
'(I3)'))//
") River widths directory:", &
260 use mo_append,
only : append
267 integer(i4),
intent(in) :: nCells
269 real(dp),
dimension(:),
allocatable :: dummy_Vector11
270 real(dp),
dimension(:, :),
allocatable :: dummy_Matrix11_IT
273 allocate(dummy_vector11(ncells))
275 dummy_vector11(:) = 0.0_dp
276 dummy_matrix11_it(:, :) = 0.0_dp
279 call append(self%netNode_E_mod, dummy_vector11)
281 call append(self%river_temp, dummy_vector11)
283 call append(self%netNode_E_out, dummy_vector11)
285 call append(self%netNode_E_IN, dummy_matrix11_it)
287 call append(self%netNode_E_R, dummy_matrix11_it)
290 deallocate(dummy_vector11)
291 deallocate(dummy_matrix11_it)
308 use mo_append,
only : append
314 integer(i4),
intent(in) :: iDomain
315 integer(i4),
dimension(:),
intent(in) :: L11_netPerm
316 integer(i4),
dimension(:),
intent(in) :: L11_fromN
317 real(dp),
dimension(:),
intent(in) :: L11_length
318 integer(i4),
intent(in) :: nLinks
319 integer(i4),
intent(in) :: nCells
320 integer(i4),
intent(in) :: ncols
321 integer(i4),
intent(in) :: nrows
322 logical,
dimension(:, :),
intent(in) :: L11_mask
324 real(dp),
dimension(:,:),
allocatable :: L11_data
325 real(dp),
dimension(:),
allocatable :: L11_riv_widths, L11_riv_areas
327 integer(i4) :: i, k, iNode
330 trim(self%dir_riv_widths(idomain)), &
333 self%riv_widths_name, &
335 self%riv_widths_file &
338 allocate(l11_riv_widths(ncells))
339 l11_riv_widths(:) = pack(l11_data(:,:), mask=l11_mask)
340 call append(self%L11_riv_widths, l11_riv_widths)
342 allocate(l11_riv_areas(ncells))
344 l11_riv_areas = 0.0_dp
349 l11_riv_areas(inode) = l11_length(i) * l11_riv_widths(inode)
351 call append(self%L11_riv_areas, l11_riv_areas)
354 deallocate(l11_riv_widths)
355 deallocate(l11_riv_areas)
375 real(dp),
dimension(:),
intent(in) :: temp_air
376 real(dp),
intent(in),
dimension(:) :: efecarea
377 integer(i4),
intent(in),
dimension(:) :: L1_L11_Id
378 real(dp),
intent(in),
dimension(:) :: L11_areacell
379 integer(i4),
intent(in),
dimension(:) :: L11_L1_Id
380 logical,
intent(in) :: map_flag
384 temp_air, efecarea, l1_l11_id, l11_areacell, l11_l1_id, map_flag, self%river_temp(self%s11 : self%e11))
387 self%river_temp(self%s11 : self%e11) = max(self%delta_T, self%river_temp(self%s11 : self%e11))
400 self%L1_runoff_E = 0.0_dp
401 self%L1_acc_strd = 0.0_dp
402 self%L1_acc_ssrd = 0.0_dp
403 self%L1_acc_temp = 0.0_dp
415 integer(i4),
intent(in) :: nCells
417 allocate(self%L1_runoff_E(ncells))
418 allocate(self%L1_acc_strd(ncells))
419 allocate(self%L1_acc_ssrd(ncells))
420 allocate(self%L1_acc_temp(ncells))
422 allocate(self%L1_ssrd_calc(ncells))
423 allocate(self%L1_strd_calc(ncells))
424 allocate(self%L1_tann_calc(ncells))
426 call self%reset_timestep()
438 deallocate(self%L1_runoff_E)
439 deallocate(self%L1_acc_strd)
440 deallocate(self%L1_acc_ssrd)
441 deallocate(self%L1_acc_temp)
442 deallocate(self%L1_ssrd_calc)
443 deallocate(self%L1_strd_calc)
444 deallocate(self%L1_tann_calc)
451 fSealed_area_fraction, &
464 real(dp),
dimension(:),
intent(in) :: fSealed_area_fraction
465 real(dp),
dimension(:),
intent(in) :: fast_interflow
466 real(dp),
dimension(:),
intent(in) :: slow_interflow
467 real(dp),
dimension(:),
intent(in) :: baseflow
468 real(dp),
dimension(:),
intent(in) :: direct_runoff
469 real(dp),
dimension(:),
intent(in) :: temp_air
472 self%ts_cnt = self%ts_cnt + 1_i4
477 fsealed_area_fraction, &
478 fast_interflow, slow_interflow, baseflow, direct_runoff, &
479 temp_air, self%L1_tann_calc, &
483 self%L1_acc_ssrd = self%L1_acc_ssrd + self%L1_ssrd_calc
484 self%L1_acc_strd = self%L1_acc_strd + self%L1_strd_calc
485 self%L1_acc_temp = self%L1_acc_temp + temp_air
506 real(dp),
intent(in),
dimension(:) :: efecarea
508 integer(i4),
intent(in),
dimension(:) :: L1_L11_Id
510 real(dp),
intent(in),
dimension(:) :: L11_areacell
512 integer(i4),
intent(in),
dimension(:) :: L11_L1_Id
514 integer(i4),
intent(in) :: timestep
516 logical,
intent(in) :: map_flag
519 if (
allocated(self%L11_srad_net) )
deallocate(self%L11_srad_net)
520 if (
allocated(self%L11_lrad_in) )
deallocate(self%L11_lrad_in)
521 if (
allocated(self%L11_air_temp) )
deallocate(self%L11_air_temp)
522 allocate(self%L11_srad_net(
size(l11_l1_id, dim = 1)))
523 allocate(self%L11_lrad_in(
size(l11_l1_id, dim = 1)))
524 allocate(self%L11_air_temp(
size(l11_l1_id, dim = 1)))
535 self%netNode_E_out(self%s11 : self%e11) &
539 self%L1_acc_ssrd = self%L1_acc_ssrd / real(self%ts_cnt, dp)
540 call l11_meteo_acc(self%L1_acc_ssrd, efecarea, l1_l11_id, l11_areacell, l11_l1_id, map_flag, self%L11_srad_net)
542 self%L11_srad_net = self%L11_srad_net * (1._dp - self%albedo_water)
544 self%L1_acc_strd = self%L1_acc_strd / real(self%ts_cnt, dp)
545 call l11_meteo_acc(self%L1_acc_strd, efecarea, l1_l11_id, l11_areacell, l11_l1_id, map_flag, self%L11_lrad_in)
547 self%L1_acc_temp = self%L1_acc_temp / real(self%ts_cnt, dp)
548 call l11_meteo_acc(self%L1_acc_temp, efecarea, l1_l11_id, l11_areacell, l11_l1_id, map_flag, self%L11_air_temp)
556 use mo_constants,
only: sigma_dp
562 real(dp),
intent(in) :: riv_temp
565 lrad_out = self%emissivity_water * sigma_dp * riv_temp ** 4_i4
571 real(dp) function
get_lat_heat(self, air_temp, netrad) result(lat_heat)
573 use mo_constants,
only : psychro_dp
580 real(dp),
intent(in) :: air_temp
582 real(dp),
intent(in) :: netrad
589 lat_heat = self%pt_a_water * delta / (psychro_dp + delta) * max(netrad, 0._dp)
600 real(dp),
intent(in) :: air_temp
601 real(dp),
intent(in) :: riv_temp
604 sens_heat = self%turb_heat_ex_coeff * (riv_temp - air_temp)
610 real(dp) function
get_e_io(self, riv_temp, cell) result(e_io)
612 use mo_constants,
only : t0_dp, cp_w_dp
619 real(dp),
intent(in) :: riv_temp
621 integer(i4),
intent(in) :: cell
623 real(dp) :: netrad, sens_heat, lat_heat
626 netrad = self%L11_srad_net(cell) + self%L11_lrad_in(cell) - self%get_lrad_out(riv_temp)
628 sens_heat = self%get_sens_heat(self%L11_air_temp(cell), riv_temp - t0_dp)
630 lat_heat = self%get_lat_heat(self%L11_air_temp(cell), netrad)
634 e_io = (netrad - sens_heat - lat_heat) / (
h2odens * cp_w_dp)
653 use mo_constants,
only : t0_dp
659 integer(i4),
intent(in) :: nLinks
661 integer(i4),
dimension(:),
intent(in) :: netPerm
663 integer(i4),
dimension(:),
intent(in) :: netLink_fromN
665 integer(i4),
dimension(:),
intent(in) :: netLink_toN
667 real(dp),
dimension(:),
intent(in) :: netLink_C1
669 real(dp),
dimension(:),
intent(in) :: netLink_C2
671 integer(i4),
intent(in) :: nInflowGauges
673 logical,
dimension(:),
intent(in) :: InflowHeadwater
675 integer(i4),
dimension(:),
intent(in) :: InflowNodeList
677 real(dp),
intent(in),
dimension(:) :: L11_qTR
679 real(dp),
intent(in),
dimension(:) :: L11_Qmod
681 integer(i4) :: i, k, m, iNode, tNode, L11in, L11to
682 real(dp) :: E_IO_in, E_IO, T_est, T_rout
685 self%netNode_E_IN(self%s11 : self%e11, 2) = 0.0_dp
687 riv_loop:
do k = 1, nlinks
690 inode = netlink_fromn(i)
691 tnode = netlink_ton(i)
693 l11in = inode + self%s11 - 1_i4
694 l11to = tnode + self%s11 - 1_i4
697 self%netNode_E_IN(l11in, 2) = self%netNode_E_IN(l11in, 2) + self%netNode_E_out(l11in)
699 self%river_temp(l11in) = self%netNode_E_IN(l11in, 2) / l11_qmod(inode) - t0_dp
702 t_est = self%river_temp(l11in) + t0_dp
704 e_io_in = self%get_E_IO(t_est, inode)
707 call self%init_iter()
709 iterloop:
do m=1, self%max_iter
711 e_io = (e_io_in + self%get_E_IO(t_est, tnode)) * 0.5_dp * self%L11_riv_areas(l11in)
713 self%netNode_E_R(l11in, 2) = self%netNode_E_R(l11in, 1) &
714 + netlink_c1(i) * (self%netNode_E_IN(l11in, 1) - self%netNode_E_R(l11in, 1)) &
715 + netlink_c2(i) * (self%netNode_E_IN(l11in, 2) + e_io - self%netNode_E_IN(l11in, 1))
717 t_rout = self%netNode_E_R(l11in, 2) / l11_qtr(inode)
719 if ( abs(t_rout - t_est) < self%delta_iter )
exit iterloop
721 call self%next_iter(t_est, t_rout)
725 self%netNode_E_IN(l11in, 2) = self%netNode_E_IN(l11in, 2) + e_io
728 if (ninflowgauges .GT. 0)
then
729 do i = 1, ninflowgauges
731 if ((tnode == inflownodelist(i)) .AND. (.NOT. inflowheadwater(i))) &
732 self%netNode_E_R(l11in, 2) = 0.0_dp
737 self%netNode_E_IN(l11to, 2) = self%netNode_E_IN(l11to, 2) + self%netNode_E_R(l11in, 2)
742 tnode = netlink_ton(netperm(nlinks))
743 l11to = tnode + self%s11 - 1_i4
744 self%netNode_E_IN(l11to, 2) = self%netNode_E_IN(l11to, 2) + self%netNode_E_out(l11to)
746 self%river_temp(l11to) = self%netNode_E_IN(l11to, 2) / l11_qmod(tnode) - t0_dp
749 self%netNode_E_R(self%s11 : self%e11, 1) = self%netNode_E_R(self%s11 : self%e11, 2)
750 self%netNode_E_IN(self%s11 : self%e11, 1) = self%netNode_E_IN(self%s11 : self%e11, 2)
762 self%first_iter = .true.
764 self%bisect_iter = .false.
774 real(dp),
intent(inout) :: T_est
775 real(dp),
intent(in) :: T_rout
778 if ( .not. self%bisect_iter )
then
780 if ( self%first_iter )
then
781 self%first_iter = .false.
783 self%up_iter = ( t_rout > t_est )
786 if ( self%up_iter .eqv. ( t_rout > t_est ) )
then
787 if ( self%up_iter )
then
788 t_est = t_est + self%step_iter
790 t_est = t_est - self%step_iter
795 self%bisect_iter = .true.
797 if ( self%up_iter )
then
798 self%up_bnd_iter = t_est
799 self%low_bnd_iter = t_est - self%step_iter
801 self%up_bnd_iter = t_est + self%step_iter
802 self%low_bnd_iter = t_est
805 t_est = (self%up_bnd_iter + self%low_bnd_iter) / 2.0_dp
810 if ( t_rout < t_est )
then
811 self%up_bnd_iter = t_est
814 self%low_bnd_iter = t_est
817 t_est = (self%up_bnd_iter + self%low_bnd_iter) / 2.0_dp
subroutine, public check_dir(path, text, raise, tab, text_length)
Check if a given directory exists.
Provides constants commonly used by mHM, mRM and MPR.
integer(i4), parameter, public maxnodomains
integer(i4), parameter, public nodata_i4
Provides structures needed by mHM, mRM and/or mpr.
type(domain_meta), public domainmeta
Provides mHM specific constants.
real(dp), parameter, public h2odens
Provides mRM specific constants.
integer(i4), parameter, public nroutingstates
Performs pre-processing for routing for mHM at level L11.
subroutine, public l11_meteo_acc(meteo_all, efecarea, l1_l11_id, l11_areacell, l11_l1_id, map_flag, meteo_acc)
meteo forcing accumulation at L11 for temperature routing.
subroutine, public l11_runoff_acc(qall, efecarea, l1_l11_id, l11_areacell, l11_l1_id, ts, map_flag, qacc)
total runoff accumulation at L11.
subroutine, public calc_l1_runoff_e(fsealed_area_fraction, fast_interflow, slow_interflow, baseflow, direct_runoff, temp_air, mean_temp_air, lateral_e)
calculate lateral temperature energy from runoff components.
Class for the river temperature calculations.
real(dp) function get_sens_heat(self, air_temp, riv_temp)
sensible heat flux of riv_temp_type
subroutine config(self, file_namelist, unamelist, file_namelist_param, unamelist_param)
configure the riv_temp_type class from the mhm namelist
real(dp) function get_lat_heat(self, air_temp, netrad)
latent heat flux of riv_temp_type
subroutine init_riv_temp(self, temp_air, efecarea, l1_l11_id, l11_areacell, l11_l1_id, map_flag)
initialize the river temperature of riv_temp_type class for the current domain
real(dp) function get_lrad_out(self, riv_temp)
get outgoing longwave radiation of riv_temp_type
subroutine dealloc_lateral(self)
deallocate lateral temp components of riv_temp_type
subroutine finalize_source_e(self, efecarea, l1_l11_id, l11_areacell, l11_l1_id, timestep, map_flag)
finalize energy sources of riv_temp_type
subroutine alloc_lateral(self, ncells)
allocate lateral temp components of riv_temp_type class for current domain
subroutine clean_up(self)
clean up
subroutine next_iter(self, t_est, t_rout)
execute next iteration with iterative solver of riv_temp_type
subroutine init_iter(self)
initialize iterative solver of riv_temp_type
subroutine init_area(self, idomain, l11_netperm, l11_fromn, l11_length, nlinks, ncells, nrows, ncols, l11_mask)
initialize the river area of riv_temp_type class for the current domain
real(dp) function get_e_io(self, riv_temp, cell)
get complete energy source of riv_temp_type at given cell
subroutine acc_source_e(self, fsealed_area_fraction, fast_interflow, slow_interflow, baseflow, direct_runoff, temp_air)
accumulate energy sources of riv_temp_type
subroutine reset_timestep(self)
reset riv_temp_type class for next timestep
subroutine init(self, ncells)
initalize the riv_temp_type class for the current domain
subroutine l11_routing_e(self, nlinks, netperm, netlink_fromn, netlink_ton, netlink_c1, netlink_c2, ninflowgauges, inflowheadwater, inflownodelist, l11_qtr, l11_qmod)
execute the temperature routing of riv_temp_type
Module for calculating reference/potential evapotranspiration [mm d-1].
elemental pure real(dp) function, public slope_satpressure(tavg)
slope of saturation vapour pressure curve
Reads forcing input data.
subroutine, public read_const_nc(folder, nrows, ncols, varname, data, filename)
Reads time independent forcing input in NetCDF file format.
This is a container to define the river temperature routing in the current time step.