5.13.2-dev0
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: &
44 use mo_mrm_file, only: mrm_file_defoutput => file_defoutput
45 use mo_common_read_config, only: &
52 use mo_read_wrapper, only : read_data
53 use mo_mrm_init, only: &
54 mrm_init, &
56 use mo_common_variables, only: &
57 level0, &
58 level1, &
59 itimer, &
60 domainmeta, &
62 use mo_common_mhm_mrm_variables, only : &
63 timestep, &
64 simper, &
65 optimize, &
69 use mo_mhm_messages, only: &
72 use mo_timer, only: &
73 timers_init, &
74 timer_start, &
75 timer_stop, &
76 timer_get
77 use mo_startup, only: mhm_initialize
78 use mo_file, only: &
81 use mo_global_variables, only: &
82 couple_cfg, &
84 l1_twsaobs, &
85 l1_etobs, &
87 l1_smobs, &
91 use mo_mhm_bfi, only: calculate_bfi
92 use mo_os, only: change_dir
93
94 implicit none
95
96 character(*), optional, intent(in) :: namelist_mhm !< path to mHM configuration namelist
97 character(*), optional, intent(in) :: namelist_mhm_param !< path to mHM parameter namelist
98 character(*), optional, intent(in) :: namelist_mhm_output !< path to mHM output namelist
99 character(*), optional, intent(in) :: namelist_mrm_output !< path to mRM output namelist
100 character(*), optional, intent(in) :: cwd !< desired working directory
101
102 integer(i4) :: domainid, idomain
103
104#ifdef MPI
105 integer :: ierror
106 integer(i4) :: nproc, rank
107#endif
108
109 ! reset nml paths if wanted
110 if (present(namelist_mhm)) file_namelist_mhm = namelist_mhm
111 if (present(namelist_mhm_param)) file_namelist_mhm_param = namelist_mhm_param
112 if (present(namelist_mhm_output)) file_defoutput = namelist_mhm_output
113 if (present(namelist_mrm_output)) mrm_file_defoutput = namelist_mrm_output
114 ! change working directory
115 if (present(cwd)) call change_dir(cwd)
116
117 ! startup message
118 call startup_message()
119
120 ! coupling configuration
122 ! read configs
127 call couple_cfg%check(domainmeta, optimize)
129 mrm_coupling_mode = 2_i4 ! TODO: this shouldn't be needed
132
133 ! Message about input directories
135
136 ! Start timings
137 call timers_init
138
139 ! --------------------------------------------------------------------------
140 ! READ AND INITIALIZE
141 ! --------------------------------------------------------------------------
142 itimer = 1
143#ifdef MPI
144 call mpi_comm_size(domainmeta%comMaster, nproc, ierror)
145 ! find the number the process is referred to, called rank
146 call mpi_comm_rank(domainmeta%comMaster, rank, ierror)
147 ! ComLocal is a communicator, i.e. a group of processes assigned to the same
148 ! domain, with a master and subprocesses. Only the master processes of these
149 ! groups need to read the data. The master process with rank 0 only
150 ! coordinates the other processes and does not need to read the data.
151 if (rank > 0 .and. domainmeta%isMasterInComLocal) then
152#endif
153 call message()
154
155 if (.not. read_restart) then
156 call message(' Read data ...')
157 call timer_start(itimer)
158 ! for DEM, slope, ... define nGvar local
159 ! read_data has a domain loop inside
160 call read_data(simper)
161 call timer_stop(itimer)
162 call message(' in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
163 end if
164
165 ! read data for every domain
166 itimer = itimer + 1
167 call message(' Initialize domains ...')
168 call timer_start(itimer)
169 call mhm_initialize()
170 call meteo_handler%init_level2(level0, level1)
171 call timer_stop(itimer)
172 call message(' in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
173 if (processmatrix(8, 1) > 0) &
175
176 itimer = itimer + 1
177 call message(' Read forcing and optional data ...')
178 call timer_start(itimer)
179
180 do idomain = 1, domainmeta%nDomains
181 domainid = domainmeta%indices(idomain)
182 ! read meteorology now, if it should be loaded in one go
183 if (meteo_handler%single_read(idomain)) call meteo_handler%prepare_data(1, idomain, level1, simper)
184
185 ! read optional optional data if necessary
186 if (optimize) then
187 select case (opti_function)
188 case(10 : 13, 28)
189 ! read optional spatio-temporal soil mositure data
190 call readoptidataobs(idomain, domainid, l1_smobs(idomain))
191 case(17)
192 ! read optional spatio-temporal neutrons data
193 call readoptidataobs(idomain, domainid, l1_neutronsobs(idomain))
194 case(27, 29, 30)
195 ! read optional spatio-temporal evapotranspiration data
196 call readoptidataobs(idomain, domainid, l1_etobs(idomain))
197 case(15)
198 ! read optional spatio-temporal tws data
199 call readoptidataobs(idomain, domainid, l1_twsaobs(idomain))
200 case(33)
201 ! read optional spatio-temporal evapotranspiration data
202 if (domainmeta%optidata(idomain) == 0 .or. domainmeta%optidata(idomain) == 5 .or. &
203 domainmeta%optidata(idomain) == 6 ) then
204 call readoptidataobs(idomain, domainid, l1_etobs(idomain))
205 end if
206 ! read optional spatio-temporal tws data
207 if (domainmeta%optidata(idomain) == 0 .or. domainmeta%optidata(idomain) == 3 .or. &
208 domainmeta%optidata(idomain) == 6 ) then
209 call readoptidataobs(idomain, domainid, l1_twsaobs(idomain))
210 end if
211 end select
212 end if
213 end do
214
215 ! calculate observed BFI if wanted
216 if ( optimize .and. opti_function==34 .and. bfi_calc ) call calculate_bfi()
217
218 call timer_stop(itimer)
219 call message(' in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
220
221 !this call may be moved to another position as it writes the master config out file for all domains
222 call write_configfile(meteo_handler%dirPrecipitation, meteo_handler%dirReferenceET, meteo_handler%dirTemperature)
223
224#ifdef MPI
225 end if
226#endif
227
228 end subroutine mhm_interface_init
229
230 !> \brief Get current global parameter value of mHM.
233
234 implicit none
235
236 real(dp), dimension(:), allocatable, intent(out) :: para !< global parameter values of mHM
237
238 allocate(para(size(global_parameters, dim=1)))
239
240 para = global_parameters(:, 3)
241
242 end subroutine mhm_interface_get_parameter
243
244 !> \brief Get number of current global parameter value of mHM.
247
248 implicit none
249
250 integer(i4), intent(out) :: n !< number of global parameter values of mHM
251
252 n = size(global_parameters, dim=1)
253
255
256 !> \brief Run mHM with current settings.
257 subroutine mhm_interface_run()
258 use mo_common_variables, only: &
259#ifdef mpi
260 domainmeta, &
261#endif
262 itimer, &
264 use mo_timer, only: &
265 timer_start, &
266 timer_stop, &
267 timer_get
268 use mo_mhm_eval, only: mhm_eval
269
270 implicit none
271
272#ifdef MPI
273 integer :: ierror
274 integer(i4) :: nproc, rank
275
276 call mpi_comm_size(domainmeta%comMaster, nproc, ierror)
277 ! find the number the process is referred to, called rank
278 call mpi_comm_rank(domainmeta%comMaster, rank, ierror)
279#endif
280
281 itimer = itimer + 1
282
283 ! --------------------------------------------------------------------------
284 ! call mHM
285 ! get runoff timeseries if possible (i.e. when domainMeta%doRouting,
286 ! processMatrix(8,1) > 0)
287 ! get other model outputs (i.e. gridded fields of model output)
288 ! --------------------------------------------------------------------------
289
290#ifdef MPI
291 if (rank > 0 .and. domainmeta%isMasterInComLocal) then
292#endif
293
294 call message(' Run mHM')
295 call timer_start(itimer)
296 call mhm_eval(global_parameters(:, 3))
297 call timer_stop(itimer)
298 call message(' in ', trim(num2str(timer_get(itimer), '(F12.3)')), ' seconds.')
299
300#ifdef MPI
301 endif
302#endif
303
304 end subroutine mhm_interface_run
305
306 !> \brief Run mHM optimization with current settings.
308 use mo_common_variables, only: &
309#ifdef mpi
310 domainmeta, &
311#endif
312 itimer, &
313 dirconfigout, &
317 use mo_common_mhm_mrm_variables, only : &
319 use mo_timer, only: &
320 timer_start, &
321 timer_stop, &
322 timer_get
323 use mo_mhm_eval, only: mhm_eval
324 use mo_objective_function, only: &
325#ifdef mpi
326 objective_subprocess, &
327 objective_master, &
328#endif
332#ifdef mpi
335#endif
337 use mo_write_ascii, only: &
338 write_optifile, & ! Writing optimized parameter set and objective
339 write_optinamelist ! Writing optimized parameter set to a namelist
340
341 implicit none
342
343 procedure(mhm_eval), pointer :: eval
344 procedure(objective), pointer :: obj_func
345
346 real(dp) :: funcbest ! best objective function achivied during optimization
347 logical, dimension(:), allocatable :: maskpara ! true = parameter will be optimized, = parameter(i,4) = 1
348 ! ! false = parameter will not be optimized = parameter(i,4) = 0
349
350#ifdef MPI
351 integer :: ierror
352 integer(i4) :: nproc, rank
353
354 call mpi_comm_size(domainmeta%comMaster, nproc, ierror)
355 ! find the number the process is referred to, called rank
356 call mpi_comm_rank(domainmeta%comMaster, rank, ierror)
357#endif
358
359 itimer = itimer + 1
360 call message(' Run mHM optimization')
361 call timer_start(itimer)
362
363 eval => mhm_eval
364
365 select case(opti_function)
366 case(1 : 9, 14, 31 : 32)
367 ! call optimization against only runoff (no other variables)
368 obj_func => single_objective_runoff
369#ifdef MPI
370 if (rank == 0 .and. domainmeta%isMasterInComLocal) then
372 call optimization(eval, obj_func, dirconfigout, funcbest, maskpara)
373 else if (domainmeta%isMasterInComLocal) then
374 ! In case of a master process from ComLocal, i.e. a master of a group of
375 ! processes that are assigned to a single domain, this process calls the
376 ! objective subroutine directly. The master over all processes collects
377 ! the data and runs the dds/sce/other opti method.
379 end if
380#else
381 call optimization(eval, obj_func, dirconfigout, funcbest, maskpara)
382#endif
383
384 case(10 : 13, 15, 17, 27, 28, 29, 30, 33, 34)
385 ! call optimization for other variables
386 obj_func => objective
387#ifdef MPI
388 if (rank == 0 .and. domainmeta%isMasterInComLocal) then
389 obj_func => objective_master
390 call optimization(eval, obj_func, dirconfigout, funcbest, maskpara)
391 else if (domainmeta%isMasterInComLocal) then
392 ! In case of a master process from ComLocal, i.e. a master of a group of
393 ! processes that are assigned to a single domain, this process calls the
394 ! objective subroutine directly. The master over all processes collects
395 ! the data and runs the dds/sce/other opti method.
396 call objective_subprocess(eval)
397 end if
398#else
399 call optimization(eval, obj_func, dirconfigout, funcbest, maskpara)
400#endif
401
402 case default
403 call error_message('***ERROR: mhm_driver: The given objective function number ', &
404 trim(adjustl(num2str(opti_function))), ' in mhm.nml is not valid!')
405 end select
406
407#ifdef MPI
408 if (rank == 0 .and. domainmeta%isMasterInComLocal) then
409#endif
410
411 ! write a file with final objective function and the best parameter set
413 ! write a file with final best parameter set in a namlist format
415 deallocate(maskpara)
416
417#ifdef MPI
418 end if
419#endif
420
421 call timer_stop(itimer)
422 call message(' in ', trim(num2str(timer_get(itimer), '(F12.3)')), ' seconds.')
423
424 end subroutine mhm_interface_run_optimization
425
426 !> \brief Write mHM restart.
428 use mo_common_variables, only: &
429#ifdef mpi
430 domainmeta, &
431#endif
432 itimer, &
436 use mo_common_mhm_mrm_variables, only : &
438 use mo_timer, only: &
439 timer_start, &
440 timer_stop, &
441 timer_get
443 use mo_mrm_write, only : mrm_write
446
447 implicit none
448
449#ifdef MPI
450 integer :: ierror
451 integer(i4) :: nproc, rank
452
453 call mpi_comm_size(domainmeta%comMaster, nproc, ierror)
454 ! find the number the process is referred to, called rank
455 call mpi_comm_rank(domainmeta%comMaster, rank, ierror)
456 if (rank > 0 .and. domainmeta%isMasterInComLocal) then
457#endif
458
459 ! --------------------------------------------------------------------------
460 ! WRITE RESTART files
461 ! --------------------------------------------------------------------------
462 if (write_restart .AND. (.NOT. optimize)) then
463 itimer = itimer + 1
464 call message()
465 call message(' Write restart file')
466 call timer_start(itimer)
468 call timer_stop(itimer)
469 call message(' in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
470 end if
471
472 ! --------------------------------------------------------------------------
473 ! WRITE RUNOFF (INCLUDING RESTART FILES, has to be called after mHM restart
474 ! files are written)
475 ! --------------------------------------------------------------------------
476 if (processmatrix(8, 1) > 0) call mrm_write()
477
478#ifdef MPI
479 end if
480#endif
481
482 call finish_message()
483
484 ! clean up all allocated variables
486
487 end subroutine mhm_interface_finalize
488
489end 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 common_mhm_mrm_read_config(file_namelist, unamelist)
Read main configurations for common parts.
subroutine, public check_optimization_settings
check optimization settings
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, unamelist)
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
integer, parameter unamelist_mhm_param
Unit for namelist.
Definition mo_file.F90:48
character(:), allocatable file_namelist_mhm_param
Parameter namelists file name.
Definition mo_file.F90:46
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:50
integer, parameter unamelist_mhm
Unit for namelist.
Definition mo_file.F90:44
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(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)
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, unamelist)
Read main configurations for mHM.
subroutine, public mpr_read_config(file_namelist, unamelist, file_namelist_param, unamelist_param)
Read the general config of mpr.
Provides file names and units for mRM.
Wrapper for initializing Routing.
subroutine, public mrm_configuration(file_namelist, unamelist, file_namelist_param, unamelist_param)
read mRM configuration from namelists
subroutine, public mrm_init(file_namelist, unamelist, file_namelist_param, unamelist_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.