5.13.3
mHM
The mesoscale Hydrological Model
Loading...
Searching...
No Matches
mo_mhm_interface.F90
Go to the documentation of this file.
1!> \file mo_mhm_interface.f90
2!> \brief \copybrief mo_mhm_interface
3!> \details \copydetails mo_mhm_interface
4
5!> \brief Module providing interfaces for mHM.
6!> \details Interfaces to control the mHM workflow from outside (init, run, get infos, etc.).
7!> \authors Sebastian Mueller
8!> \version 0.1
9!> \date Oct 2021
10!> \copyright Copyright 2005-\today, the mHM Developers, Luis Samaniego, Sabine Attinger: All rights reserved.
11!! mHM is released under the LGPLv3+ license \license_note
12!> \ingroup f_mhm
14
15 use mo_kind, only: i4, dp
16 use mo_message, only: message, error_message
17 use mo_string_utils, only: num2str
18
19#ifdef MPI
20 use mpi_f08
21#endif
22
23 implicit none
24
25 private
26
27 public :: mhm_interface_init
30 public :: mhm_interface_run
33
34contains
35
36 !> \brief initialize mHM from given namelist paths.
37 subroutine mhm_interface_init(namelist_mhm, namelist_mhm_param, namelist_mhm_output, namelist_mrm_output, cwd)
38 use mo_file, only: &
42 use mo_mrm_file, only: mrm_file_defoutput => file_defoutput
43 use mo_common_read_config, only: &
50 use mo_read_wrapper, only : read_data
51 use mo_mrm_init, only: &
52 mrm_init, &
54 use mo_common_variables, only: &
55 level0, &
56 level1, &
57 itimer, &
58 domainmeta, &
60 use mo_common_mhm_mrm_variables, only : &
61 timestep, &
62 simper, &
63 optimize, &
67 use mo_mhm_messages, only: &
70 use mo_timer, only: &
71 timers_init, &
72 timer_start, &
73 timer_stop, &
74 timer_get
75 use mo_startup, only: mhm_initialize
76 use mo_global_variables, only: &
77 couple_cfg, &
79 l1_twsaobs, &
80 l1_etobs, &
82 l1_smobs, &
83 bfi_calc, &
87 use mo_mhm_bfi, only: calculate_bfi
88 use mo_os, only: change_dir
89
90 implicit none
91
92 character(*), optional, intent(in) :: namelist_mhm !< path to mHM configuration namelist
93 character(*), optional, intent(in) :: namelist_mhm_param !< path to mHM parameter namelist
94 character(*), optional, intent(in) :: namelist_mhm_output !< path to mHM output namelist
95 character(*), optional, intent(in) :: namelist_mrm_output !< path to mRM output namelist
96 character(*), optional, intent(in) :: cwd !< desired working directory
97
98 integer(i4) :: domainid, idomain
99
100#ifdef MPI
101 integer :: ierror
102 integer(i4) :: nproc, rank
103#endif
104
105 ! reset nml paths if wanted
106 if (present(namelist_mhm)) file_namelist_mhm = namelist_mhm
107 if (present(namelist_mhm_param)) file_namelist_mhm_param = namelist_mhm_param
108 if (present(namelist_mhm_output)) file_defoutput = namelist_mhm_output
109 if (present(namelist_mrm_output)) mrm_file_defoutput = namelist_mrm_output
110 ! change working directory
111 if (present(cwd)) call change_dir(cwd)
112
113 ! startup message
114 call startup_message()
115
116 ! coupling configuration
117 call couple_cfg%read_config(file_namelist_mhm)
118 ! read configs
123 call couple_cfg%check(domainmeta, optimize)
125 mrm_coupling_mode = 2_i4 ! TODO: this shouldn't be needed
128
129 ! Message about input directories
131
132 ! Start timings
133 call timers_init
134
135 ! --------------------------------------------------------------------------
136 ! READ AND INITIALIZE
137 ! --------------------------------------------------------------------------
138 itimer = 1
139#ifdef MPI
140 call mpi_comm_size(domainmeta%comMaster, nproc, ierror)
141 ! find the number the process is referred to, called rank
142 call mpi_comm_rank(domainmeta%comMaster, rank, ierror)
143 ! ComLocal is a communicator, i.e. a group of processes assigned to the same
144 ! domain, with a master and subprocesses. Only the master processes of these
145 ! groups need to read the data. The master process with rank 0 only
146 ! coordinates the other processes and does not need to read the data.
147 if (rank > 0 .and. domainmeta%isMasterInComLocal) then
148#endif
149 call message()
150
151 if (.not. read_restart) then
152 call message(' Read data ...')
153 call timer_start(itimer)
154 ! for DEM, slope, ... define nGvar local
155 ! read_data has a domain loop inside
156 call read_data(simper)
157 call timer_stop(itimer)
158 call message(' in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
159 end if
160
161 ! read data for every domain
162 itimer = itimer + 1
163 call message(' Initialize domains ...')
164 call timer_start(itimer)
165 call mhm_initialize()
166 call meteo_handler%init_level2(level0, level1)
167 call timer_stop(itimer)
168 call message(' in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
169 if (processmatrix(8, 1) > 0) &
171
172 itimer = itimer + 1
173 call message(' Read forcing and optional data ...')
174 call timer_start(itimer)
175
176 do idomain = 1, domainmeta%nDomains
177 domainid = domainmeta%indices(idomain)
178 ! read meteorology now, if it should be loaded in one go
179 if (meteo_handler%single_read(idomain)) call meteo_handler%prepare_data(1, idomain, level1, simper)
180
181 ! read optional optional data if necessary
182 if (optimize) then
183 select case (opti_function)
184 case(10 : 13, 28, 35, 38, 43)
185 ! read optional spatio-temporal soil mositure data
186 call readoptidataobs(idomain, domainid, l1_smobs(idomain))
187 case(17)
188 ! read optional spatio-temporal neutrons data
189 call readoptidataobs(idomain, domainid, l1_neutronsobs(idomain))
190 case(27, 29, 30, 36, 39, 41, 44)
191 ! read optional spatio-temporal evapotranspiration data
192 call readoptidataobs(idomain, domainid, l1_etobs(idomain))
193 case(15)
194 ! read optional spatio-temporal tws data
195 call readoptidataobs(idomain, domainid, l1_twsaobs(idomain))
196 case(33)
197 ! read optional spatio-temporal evapotranspiration data
198 if (domainmeta%optidata(idomain) == 0 .or. domainmeta%optidata(idomain) == 5 .or. &
199 domainmeta%optidata(idomain) == 6 ) then
200 call readoptidataobs(idomain, domainid, l1_etobs(idomain))
201 end if
202 ! read optional spatio-temporal tws data
203 if (domainmeta%optidata(idomain) == 0 .or. domainmeta%optidata(idomain) == 3 .or. &
204 domainmeta%optidata(idomain) == 6 ) then
205 call readoptidataobs(idomain, domainid, l1_twsaobs(idomain))
206 end if
207 case(37, 40, 42, 45)
208 ! read optional spatio-temporal soil moisture and evapotranspiration data
209 call readoptidataobs(idomain, domainid, l1_smobs(idomain))
210 call readoptidataobs(idomain, domainid, l1_etobs(idomain))
211 case(46, 47)
212 ! read optional spatio-temporal SPF data
213 call readoptidataobs(idomain, domainid, l1_spfobs(idomain))
214 end select
215 end if
216 end do
217
218 ! calculate observed BFI if wanted
219 if ( optimize .and. opti_function==34 .and. bfi_calc ) call calculate_bfi()
220
221 call timer_stop(itimer)
222 call message(' in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
223
224 !this call may be moved to another position as it writes the master config out file for all domains
225 call write_configfile(meteo_handler%dirPrecipitation, meteo_handler%dirReferenceET, meteo_handler%dirTemperature)
226
227#ifdef MPI
228 end if
229#endif
230
231 end subroutine mhm_interface_init
232
233 !> \brief Get current global parameter value of mHM.
236
237 implicit none
238
239 real(dp), dimension(:), allocatable, intent(out) :: para !< global parameter values of mHM
240
241 allocate(para(size(global_parameters, dim=1)))
242
243 para = global_parameters(:, 3)
244
245 end subroutine mhm_interface_get_parameter
246
247 !> \brief Get number of current global parameter value of mHM.
250
251 implicit none
252
253 integer(i4), intent(out) :: n !< number of global parameter values of mHM
254
255 n = size(global_parameters, dim=1)
256
258
259 !> \brief Run mHM with current settings.
260 subroutine mhm_interface_run()
261#ifdef MPI
263#endif
264 use mo_common_variables, only: &
265 itimer, &
267 use mo_timer, only: &
268 timer_start, &
269 timer_stop, &
270 timer_get
271 use mo_mhm_eval, only: mhm_eval
272
273 implicit none
274
275#ifdef MPI
276 integer :: ierror
277 integer(i4) :: nproc, rank
278
279 call mpi_comm_size(domainmeta%comMaster, nproc, ierror)
280 ! find the number the process is referred to, called rank
281 call mpi_comm_rank(domainmeta%comMaster, rank, ierror)
282#endif
283
284 itimer = itimer + 1
285
286 ! --------------------------------------------------------------------------
287 ! call mHM
288 ! get runoff timeseries if possible (i.e. when domainMeta%doRouting,
289 ! processMatrix(8,1) > 0)
290 ! get other model outputs (i.e. gridded fields of model output)
291 ! --------------------------------------------------------------------------
292
293#ifdef MPI
294 if (rank > 0 .and. domainmeta%isMasterInComLocal) then
295#endif
296
297 call message(' Run mHM')
298 call timer_start(itimer)
299 call mhm_eval(global_parameters(:, 3))
300 call timer_stop(itimer)
301 call message(' in ', trim(num2str(timer_get(itimer), '(F12.3)')), ' seconds.')
302
303#ifdef MPI
304 endif
305#endif
306
307 end subroutine mhm_interface_run
308
309 !> \brief Run mHM optimization with current settings.
311#ifdef MPI
313 use mo_objective_function, only: &
314 objective_subprocess, &
315 objective_master
319#endif
320 use mo_common_variables, only: &
321 itimer, &
322 dirconfigout, &
326 use mo_common_mhm_mrm_variables, only : &
328 use mo_timer, only: &
329 timer_start, &
330 timer_stop, &
331 timer_get
332 use mo_mhm_eval, only: mhm_eval
336 use mo_write_ascii, only: &
337 write_optifile, & ! Writing optimized parameter set and objective
338 write_optinamelist ! Writing optimized parameter set to a namelist
339
340 implicit none
341
342 procedure(mhm_eval), pointer :: eval
343 procedure(objective), pointer :: obj_func
344
345 real(dp) :: funcbest ! best objective function achivied during optimization
346 logical, dimension(:), allocatable :: maskpara ! true = parameter will be optimized, = parameter(i,4) = 1
347 ! ! false = parameter will not be optimized = parameter(i,4) = 0
348
349#ifdef MPI
350 integer :: ierror
351 integer(i4) :: nproc, rank
352
353 call mpi_comm_size(domainmeta%comMaster, nproc, ierror)
354 ! find the number the process is referred to, called rank
355 call mpi_comm_rank(domainmeta%comMaster, rank, ierror)
356#endif
357
358 itimer = itimer + 1
359 call message(' Run mHM optimization')
360 call timer_start(itimer)
361
362 eval => mhm_eval
363
364 select case(opti_function)
365 case(1 : 9, 14, 31 : 32)
366 ! call optimization against only runoff (no other variables)
367 obj_func => single_objective_runoff
368#ifdef MPI
369 if (rank == 0 .and. domainmeta%isMasterInComLocal) then
371 call optimization(eval, obj_func, dirconfigout, funcbest, maskpara)
372 else if (domainmeta%isMasterInComLocal) then
373 ! In case of a master process from ComLocal, i.e. a master of a group of
374 ! processes that are assigned to a single domain, this process calls the
375 ! objective subroutine directly. The master over all processes collects
376 ! the data and runs the dds/sce/other opti method.
378 end if
379#else
380 call optimization(eval, obj_func, dirconfigout, funcbest, maskpara)
381#endif
382
383 case(10 : 13, 15, 17, 27, 28, 29, 30, 33, 34, 35 : 47)
384 ! call optimization for other variables
385 obj_func => objective
386#ifdef MPI
387 if (rank == 0 .and. domainmeta%isMasterInComLocal) then
388 obj_func => objective_master
389 call optimization(eval, obj_func, dirconfigout, funcbest, maskpara)
390 else if (domainmeta%isMasterInComLocal) then
391 ! In case of a master process from ComLocal, i.e. a master of a group of
392 ! processes that are assigned to a single domain, this process calls the
393 ! objective subroutine directly. The master over all processes collects
394 ! the data and runs the dds/sce/other opti method.
395 call objective_subprocess(eval)
396 end if
397#else
398 call optimization(eval, obj_func, dirconfigout, funcbest, maskpara)
399#endif
400
401 case default
402 call error_message('***ERROR: mhm_driver: The given objective function number ', &
403 trim(adjustl(num2str(opti_function))), ' in mhm.nml is not valid!')
404 end select
405
406#ifdef MPI
407 if (rank == 0 .and. domainmeta%isMasterInComLocal) then
408#endif
409
410 ! write a file with final objective function and the best parameter set
412 ! write a file with final best parameter set in a namlist format
414 deallocate(maskpara)
415
416#ifdef MPI
417 end if
418#endif
419
420 call timer_stop(itimer)
421 call message(' in ', trim(num2str(timer_get(itimer), '(F12.3)')), ' seconds.')
422
423 end subroutine mhm_interface_run_optimization
424
425 !> \brief Write mHM restart.
427#ifdef MPI
429#endif
430 use mo_common_variables, only: &
431 itimer, &
435 use mo_common_mhm_mrm_variables, only : &
437 use mo_timer, only: &
438 timer_start, &
439 timer_stop, &
440 timer_get
442 use mo_mrm_write, only : mrm_write
445
446 implicit none
447
448#ifdef MPI
449 integer :: ierror
450 integer(i4) :: nproc, rank
451
452 call mpi_comm_size(domainmeta%comMaster, nproc, ierror)
453 ! find the number the process is referred to, called rank
454 call mpi_comm_rank(domainmeta%comMaster, rank, ierror)
455 if (rank > 0 .and. domainmeta%isMasterInComLocal) then
456#endif
457
458 ! --------------------------------------------------------------------------
459 ! WRITE RESTART files
460 ! --------------------------------------------------------------------------
461 if (write_restart .AND. (.NOT. optimize)) then
462 itimer = itimer + 1
463 call message()
464 call message(' Write restart file')
465 call timer_start(itimer)
467 call timer_stop(itimer)
468 call message(' in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
469 end if
470
471 ! --------------------------------------------------------------------------
472 ! WRITE RUNOFF (INCLUDING RESTART FILES, has to be called after mHM restart
473 ! files are written)
474 ! --------------------------------------------------------------------------
475 if (processmatrix(8, 1) > 0) call mrm_write()
476
477#ifdef MPI
478 end if
479#endif
480
481 call finish_message()
482
483 ! clean up all allocated variables
485
486 end subroutine mhm_interface_finalize
487
488end module mo_mhm_interface
Module to clean up after a mHM run.
subroutine, public deallocate_global_variables()
Deallocate all global variables.
Reading of main model configurations.
subroutine, public check_optimization_settings
check optimization settings
subroutine, public common_mhm_mrm_read_config(file_namelist)
Read main configurations for common parts.
Provides structures needed by mHM, mRM and/or mpr.
type(period), dimension(:), allocatable, public simper
Reading of main model configurations.
subroutine, public common_read_config(file_namelist)
Read main configurations commonly used by mHM, mRM and MPR.
Provides structures needed by mHM, mRM and/or mpr.
character(256), dimension(:), allocatable, public mhmfilerestartout
logical, public write_restart
real(dp), dimension(:, :), allocatable, target, public global_parameters
character(256), dimension(:), allocatable, public global_parameters_name
type(domain_meta), public domainmeta
character(256), public dirconfigout
integer(i4), dimension(nprocesses, 3), public processmatrix
type(grid), dimension(:), allocatable, target, public level1
type(grid), dimension(:), allocatable, target, public level0
Provides file names and units for mHM.
Definition mo_file.F90:29
character(:), allocatable file_namelist_mhm_param
Parameter namelists file name.
Definition mo_file.F90:44
character(:), allocatable file_namelist_mhm
Namelist file name.
Definition mo_file.F90:42
character(:), allocatable file_defoutput
file defining mHM's outputs
Definition mo_file.F90:46
Main global variables for mHM.
type(meteo_handler_type), public meteo_handler
the meteo handler class
type(optidata), dimension(:), allocatable, public l1_twsaobs
this stores L1_tws, the mask, the directory of the observerd data, and the timestepInput of the simul...
logical, public bfi_calc
calculate observed BFI from gauges with Eckhardt filter
type(optidata), dimension(:), allocatable, public l1_neutronsobs
type(optidata), dimension(:), allocatable, public l1_spfobs
type(couple_cfg_type), public couple_cfg
coupling configuration class
type(optidata), dimension(:), allocatable, public l1_smobs
type(optidata), dimension(:), allocatable, public l1_etobs
Module to calculate BFI form gauging stations in mHM.
subroutine, public calculate_bfi()
Calculate BFI from given discharge observation.
Runs mhm with a specific parameter set and returns required variables, e.g.
subroutine, public mhm_eval(parameterset, opti_domain_indices, runoff, smoptisim, neutronsoptisim, etoptisim, twsoptisim, bfi, sweoptisim)
Runs mhm with a specific parameter set and returns required variables, e.g.
Module providing interfaces for mHM.
subroutine, public mhm_interface_init(namelist_mhm, namelist_mhm_param, namelist_mhm_output, namelist_mrm_output, cwd)
initialize mHM from given namelist paths.
subroutine, public mhm_interface_run()
Run mHM with current settings.
subroutine, public mhm_interface_get_parameter(para)
Get current global parameter value of mHM.
subroutine, public mhm_interface_get_parameter_number(n)
Get number of current global parameter value of mHM.
subroutine, public mhm_interface_run_optimization()
Run mHM optimization with current settings.
subroutine, public mhm_interface_finalize()
Write mHM restart.
Module for mHM messages.
subroutine, public domain_dir_check_message()
Check input directories for mHM.
subroutine, public startup_message()
write startup message of mHM.
subroutine, public finish_message()
Finish message for mHM.
Reading of main model configurations.
subroutine, public mhm_read_config(file_namelist)
Read main configurations for mHM.
subroutine, public mpr_read_config(file_namelist, file_namelist_param)
Read the general config of mpr.
Provides file names and units for mRM.
Wrapper for initializing Routing.
subroutine, public mrm_configuration(file_namelist, file_namelist_param)
read mRM configuration from namelists
subroutine, public mrm_init(file_namelist, file_namelist_param)
Initialize all mRM variables at all levels (i.e., L0, L1, and L11).
Objective Functions for Optimization of mHM/mRM against runoff.
real(dp) function, public single_objective_runoff(parameterset, eval, arg1, arg2, arg3)
Wrapper for objective functions optimizing agains runoff.
subroutine, public single_objective_runoff_subprocess(eval, arg1, arg2, arg3)
Wrapper for objective functions optimizing agains runoff.
real(dp) function, public single_objective_runoff_master(parameterset, eval, arg1, arg2, arg3)
Wrapper for objective functions optimizing agains runoff.
write of discharge and restart files
subroutine, public mrm_write
write discharge and restart files
Objective Functions for Optimization of mHM.
real(dp) function, public objective(parameterset, eval, arg1, arg2, arg3)
Wrapper for objective functions.
Wrapper subroutine for optimization against runoff and sm.
subroutine, public optimization(eval, objective, dirconfigout, funcbest, maskpara)
Wrapper for optimization.
Read optional data for mHM calibration.
subroutine, public readoptidataobs(idomain, domainid, l1_optiobs)
Read evapotranspiration data from NetCDF file for calibration.
Wrapper for all reading routines.
subroutine, public read_data(laiper)
Reads data.
reading and writing states, fluxes and configuration for restart of mHM.
subroutine, public write_restart_files(outfile)
write restart files for each domain
Startup procedures for mHM.
subroutine, public mhm_initialize
Initialize main mHM variables.
Module to write ascii file output.
subroutine, public write_configfile(dirprecipitation, dirreferenceet, dirtemperature)
This modules writes the results of the configuration into an ASCII-file.
subroutine, public write_optinamelist(processmatrix, parameters, maskpara, parameters_name)
Write final, optimized parameter set in a namelist format.
subroutine, public write_optifile(best_of, best_paramset, param_names)
Write briefly final optimization results.