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