5.13.2-dev0
mHM
The mesoscale Hydrological Model
Loading...
Searching...
No Matches
mo_common_restart.f90
Go to the documentation of this file.
1!> \file mo_common_restart.f90
2!> \brief \copybrief mo_common_read_data
3!> \details \copydetails mo_common_read_data
4
5!> \brief common restart tools
6!> \details Routines to deal with grid infos for restart files
7!> \authors Robert Schweppe
8!> \date Jun 2018
9!> \copyright Copyright 2005-\today, the mHM Developers, Luis Samaniego, Sabine Attinger: All rights reserved.
10!! mHM is released under the LGPLv3+ license \license_note
11!> \ingroup f_common
13
14 use mo_kind, only : i4, dp
15 use mo_message, only: message, error_message
16
17 IMPLICIT NONE
18
19 PRIVATE
20
21 PUBLIC :: write_grid_info
22 PUBLIC :: read_grid_info ! read restart files for configuration from a given path
24
25
26 !> \brief check consistency of two given items
29 end interface check_consistency_element
30
31
32CONTAINS
33
34
35 !> \brief write restart files for each domain
36 !> \details write restart files for each domain. For each domain
37 !! three restart files are written. These are xxx_states.nc,
38 !! xxx_L11_config.nc, and xxx_config.nc (xxx being the three digit
39 !! domain index). If a variable is added here, it should also be added
40 !! in the read restart routines below.
41 !> \changelog
42 !! - Stephan Thober Aug 2015
43 !! - moved write of routing states to mRM
44 !! - David Schaefer Nov 2015
45 !! - mo_netcdf
46 !! - Stephan Thober Nov 2016
47 !! - moved processMatrix to common variables
48 !! - Zink M. Demirel C. Mar 2017
49 !! - Added Jarvis soil water stress function at SM process(3)
50 !! - Robert Schweppe Feb 2018
51 !! - Removed all L0 references
52 !! - Robert Schweppe Jun 2018
53 !! - refactoring and reformatting
54 !! - Stephan Thober May 2019
55 !! - where statement for gnu73 to translate level0 mask
56 !> \authors Stephan Thober
57 !> \date Jun 2014
58 subroutine write_grid_info(grid_in, level_name, nc)
59
61 use mo_common_types, only: grid
62 use mo_netcdf, only : ncdataset, ncdimension, ncvariable
63
64 implicit none
65
66 !> level to be written
67 type(grid), intent(in) :: grid_in
68
69 !> level_id
70 character(*), intent(in) :: level_name
71
72 !> NcDataset to write information to
73 type(ncdataset), intent(inout) :: nc
74
75 ! dummy for gnu73
76 integer(i4), allocatable :: dummy(:, :)
77
78 type(ncdimension) :: rows, cols
79
80 type(ncvariable) :: var
81
82
83 rows = nc%setDimension("nrows" // trim(level_name), grid_in%nrows)
84 cols = nc%setDimension("ncols" // trim(level_name), grid_in%ncols)
85
86 ! now set everything related to the grid
87 var = nc%setVariable("L" // trim(level_name) // "_domain_mask", "i32", (/rows, cols/))
88 call var%setFillValue(nodata_i4)
89 ! transform from logical to i32
90 ! ST: where statement is used because gnu73 does not properly translate with merge
91 allocate(dummy(size(grid_in%mask, 1), size(grid_in%mask, 2)))
92 dummy = 0_i4
93 where(grid_in%mask) dummy = 1_i4
94 call var%setData(dummy)
95 deallocate(dummy)
96 call var%setAttribute("long_name", "Mask at level " // trim(level_name))
97
98 var = nc%setVariable("L" // trim(level_name) // "_domain_lat", "f64", (/rows, cols/))
99 call var%setFillValue(nodata_dp)
100 call var%setData(grid_in%y)
101 call var%setAttribute("long_name", "Latitude at level " // trim(level_name))
102
103 var = nc%setVariable("L" // trim(level_name) // "_domain_lon", "f64", (/rows, cols/))
104 call var%setFillValue(nodata_dp)
105 call var%setData(grid_in%x)
106 call var%setAttribute("long_name", "Longitude at level " // trim(level_name))
107
108 var = nc%setVariable("L" // trim(level_name) // "_domain_cellarea", "f64", (/rows, cols/))
109 call var%setFillValue(nodata_dp)
110 call var%setData(unpack(grid_in%CellArea * 1.0e-6_dp, grid_in%mask, nodata_dp))
111 call var%setAttribute("long_name", "Cell area at level " // trim(level_name))
112
113 call nc%setAttribute("xllcorner_L" // trim(level_name), grid_in%xllcorner)
114 call nc%setAttribute("yllcorner_L" // trim(level_name), grid_in%yllcorner)
115 call nc%setAttribute("cellsize_L" // trim(level_name), grid_in%cellsize)
116 call nc%setAttribute("nrows_L" // trim(level_name), grid_in%nrows)
117 call nc%setAttribute("ncols_L" // trim(level_name), grid_in%ncols)
118 call nc%setAttribute("nCells_L" // trim(level_name), grid_in%nCells)
119
120 end subroutine write_grid_info
121
122
123 !> \brief reads configuration apart from Level 11 configuration from a restart directory
124 !> \details read configuration variables from a given restart
125 !> directory and initializes all configuration variables,
126 !> that are initialized in the subroutine initialise,
127 !> contained in module mo_startup.
128 !> \changelog
129 !! - David Schaefer Nov 2015
130 !! - mo_netcdf
131 !! - Zink M. Demirel C. Mar 2017
132 !! - Added Jarvis soil water stress function at SM process(3)
133 !! - Robert Schweppe Feb 2018
134 !! - Removed all L0 references
135 !! - Robert Schweppe Jun 2018
136 !! - refactoring and reformatting
137 !! - Stephan Thober May 2019
138 !! - added allocation check for mask and cellArea because cellArea needs to be read by mRM, but mask is created before by mHM
139 !> \authors Stephan Thober
140 !> \date Apr 2013
141 subroutine read_grid_info(InFile, level_name, new_grid)
142
143 use mo_common_types, only: grid
144 use mo_netcdf, only : ncdataset, ncvariable
145
146 implicit none
147
148 !> Input Path including trailing slash
149 character(256), intent(in) :: infile
150
151 !> level_name (id)
152 character(*), intent(in) :: level_name
153
154 !> grid to save information to
155 type(grid), intent(inout) :: new_grid
156
157 ! dummy, 2 dimension I4
158 integer(i4), dimension(:, :), allocatable :: dummyi2
159
160 ! dummy, 2 dimension DP
161 real(dp), dimension(:, :), allocatable :: dummyd2
162
163 character(256) :: fname
164
165 type(ncdataset) :: nc
166
167 type(ncvariable) :: var
168
169 integer(i4) :: k
170
171
172 ! read config
173 fname = trim(infile)
174 call message(' Reading config from ', trim(adjustl(fname)), ' ...')
175
176 nc = ncdataset(fname, "r")
177
178 ! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
179 ! Read L1 variables <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
180 ! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
181 ! read the grid properties
182 call nc%getAttribute("xllcorner_L" // trim(level_name), new_grid%xllcorner)
183 call nc%getAttribute("yllcorner_L" // trim(level_name), new_grid%yllcorner)
184 call nc%getAttribute("nrows_L" // trim(level_name), new_grid%nrows)
185 call nc%getAttribute("ncols_L" // trim(level_name), new_grid%ncols)
186 call nc%getAttribute("cellsize_L" // trim(level_name), new_grid%cellsize)
187 call nc%getAttribute("nCells_L" // trim(level_name), new_grid%nCells)
188
189 if (.not. allocated(new_grid%mask)) allocate(new_grid%mask(new_grid%nrows, new_grid%ncols))
190 if (.not. allocated(new_grid%x)) allocate(new_grid%x(new_grid%nrows, new_grid%ncols))
191 if (.not. allocated(new_grid%y)) allocate(new_grid%y(new_grid%nrows, new_grid%ncols))
192 ! read L1 mask
193 var = nc%getVariable("L" // trim(level_name) // "_domain_mask")
194 ! read integer
195 call var%getData(dummyi2)
196 ! transform to logical
197 new_grid%mask = (dummyi2 .eq. 1_i4)
198
199 var = nc%getVariable("L" // trim(level_name) // "_domain_lat")
200 call var%getData(new_grid%y)
201
202 var = nc%getVariable("L" // trim(level_name) // "_domain_lon")
203 call var%getData(new_grid%x)
204
205 var = nc%getVariable("L" // trim(level_name) // "_domain_cellarea")
206 call var%getData(dummyd2)
207 if (.not. allocated(new_grid%CellArea)) new_grid%CellArea = pack(dummyd2 / 1.0e-6_dp, new_grid%mask)
208 ! new_grid%CellArea = pack(dummyD2 / 1.0E-6_dp, new_grid%mask)
209
210 call nc%close()
211
212 new_grid%Id = (/ (k, k = 1, new_grid%nCells) /)
213
214 end subroutine read_grid_info
215
216
217 !> \brief read nubmer of LAI time steps and check dimension configurations read from restart file
218 !> \author Robert Schweppe
219 !> \date Aug 2019
220 !> \author Sebastian Mueller
221 !> \date Feb 2023
222 subroutine read_nlai_and_check_dims(iDomain, InFile)
223
224 use mo_mpr_global_variables, only: nlai, laiboundaries ! may read from restart
225 use mo_netcdf, only : ncdataset, ncvariable, ncdimension
228
229 implicit none
230
231 !> domain counter (not ID)
232 integer(i4), intent(in) :: idomain
233 !> Input Path including trailing slash
234 character(256), intent(in) :: infile
235
236 character(256) :: fname
237 type(ncdataset) :: nc
238 type(ncvariable) :: var
239 type(ncdimension) :: nc_dim
240
241 integer(i4) :: nsoilhorizons_temp, nlais_temp, nlandcoverperiods_temp
242 real(dp), dimension(:), allocatable :: landcoverperiodboundaries_temp, soilhorizonboundaries_temp, &
243 laiboundaries_temp
244
245 ! dummy, 2 dimension
246 real(dp), dimension(:, :), allocatable :: dummyd2, dummyd2_tmp
247
248 integer(i4) :: ii
249
250 ! read config
251 fname = trim(infile)
252 call message(' Reading and checking LAI, land-cover and soil-horizons from ', trim(adjustl(fname)), ' ...')
253
254 nc = ncdataset(fname, "r")
255
256 ! get the dimensions
257 var = nc%getVariable(trim(soilhorizonsvarname)//'_bnds')
258 call var%getData(dummyd2_tmp)
259 if (allocated(dummyd2)) deallocate(dummyd2)
261 allocate(dummyd2(size(dummyd2_tmp,2), size(dummyd2_tmp,1)))
262 dummyd2 = transpose(dummyd2_tmp)
263 else
264 allocate(dummyd2(size(dummyd2_tmp,1), size(dummyd2_tmp,2)))
265 dummyd2 = dummyd2_tmp
266 end if
267 deallocate(dummyd2_tmp)
268 nsoilhorizons_temp = size(dummyd2, 2)
269 allocate(soilhorizonboundaries_temp(nsoilhorizons_temp+1))
270 soilhorizonboundaries_temp(1:nsoilhorizons_temp) = dummyd2(1, :)
271 soilhorizonboundaries_temp(nsoilhorizons_temp+1) = dummyd2(2, nsoilhorizons_temp)
272
273 ! get the landcover dimension
274 var = nc%getVariable(trim(landcoverperiodsvarname)//'_bnds')
275 call var%getData(dummyd2_tmp)
276 if (allocated(dummyd2)) deallocate(dummyd2)
278 allocate(dummyd2(size(dummyd2_tmp,2), size(dummyd2_tmp,1)))
279 dummyd2 = transpose(dummyd2_tmp)
280 else
281 allocate(dummyd2(size(dummyd2_tmp,1), size(dummyd2_tmp,2)))
282 dummyd2 = dummyd2_tmp
283 end if
284 deallocate(dummyd2_tmp)
285 nlandcoverperiods_temp = size(dummyd2, 2)
286 allocate(landcoverperiodboundaries_temp(nlandcoverperiods_temp+1))
287 landcoverperiodboundaries_temp(1:nlandcoverperiods_temp) = dummyd2(1, :)
288 landcoverperiodboundaries_temp(nlandcoverperiods_temp+1) = dummyd2(2, nlandcoverperiods_temp)
289
290 ! get the LAI dimension
291 if (nc%hasVariable(trim(laivarname)//'_bnds')) then
292 var = nc%getVariable(trim(laivarname)//'_bnds')
293 call var%getData(dummyd2_tmp)
294 if (allocated(dummyd2)) deallocate(dummyd2)
296 allocate(dummyd2(size(dummyd2_tmp,2), size(dummyd2_tmp,1)))
297 dummyd2 = transpose(dummyd2_tmp)
298 else
299 allocate(dummyd2(size(dummyd2_tmp,1), size(dummyd2_tmp,2)))
300 dummyd2 = dummyd2_tmp
301 end if
302 deallocate(dummyd2_tmp)
303 nlais_temp = size(dummyd2, 2)
304 allocate(laiboundaries_temp(nlais_temp+1))
305 laiboundaries_temp(1:nlais_temp) = dummyd2(1, :)
306 laiboundaries_temp(nlais_temp+1) = dummyd2(2, nlais_temp)
307 else if (nc%hasDimension('L1_LAITimesteps')) then
308 nc_dim = nc%getDimension('L1_LAITimesteps')
309 nlais_temp = nc_dim%getLength()
310 allocate(laiboundaries_temp(nlais_temp+1))
311 laiboundaries_temp = [(ii, ii=1, nlais_temp+1)]
312 else
313 call error_message('***ERROR: no LAI information in restart file for reading')
314 end if
315
316 ! check LAI for consistency on all domains (-1 indicates first reading)
317 if (nlai == -1_i4) then
318 nlai = nlais_temp
319 allocate(laiboundaries(nlai + 1_i4))
320 laiboundaries = laiboundaries_temp
321 end if
322
323 call check_dimension_consistency(idomain, nsoilhorizons_temp, soilhorizonboundaries_temp, &
324 nlais_temp, laiboundaries_temp, nlandcoverperiods_temp, landcoverperiodboundaries_temp)
325
326 call nc%close()
327
328 end subroutine read_nlai_and_check_dims
329
330 !> \brief checks dimension configurations read from restart file
331 !> \authors Robert Schweppe
332 !> \date Aug 2019
333 subroutine check_dimension_consistency(iDomain, nSoilHorizons_temp, soilHorizonBoundaries_temp, &
334 nLAIs_temp, LAIBoundaries_temp, nLandCoverPeriods_temp, landCoverPeriodBoundaries_temp)
335
337 use mo_common_variables, only: nlcoverscene, lc_year_start, lc_year_end ! read from nml
338 use mo_string_utils, only: compress, num2str
339
340 integer(i4), intent(in) :: iDomain
341
342 integer(i4), intent(in) :: nSoilHorizons_temp, nLAIs_temp, nLandCoverPeriods_temp
343 real(dp), dimension(:), intent(inout) :: landCoverPeriodBoundaries_temp, soilHorizonBoundaries_temp, &
344 LAIBoundaries_temp
345 character(256) :: errorString
346
347 integer(i4) :: k
348
349 ! compare local to global
350 call check_consistency_element(nlcoverscene, nlandcoverperiods_temp, 'number of land cover periods', idomain)
351 call check_consistency_element(nsoilhorizons_mhm, nsoilhorizons_temp, 'number of soil horizons', idomain)
352 call check_consistency_element(nlai, nlais_temp, 'number of LAI timesteps', idomain)
353
354 ! now check the boundaries
355 do k=1, nlcoverscene
356 errorstring = compress(trim(num2str(k)))//'th land cover boundary'
357 call check_consistency_element(real(lc_year_start(k), dp), landcoverperiodboundaries_temp(k), errorstring, idomain)
358 end do
359 errorstring = 'last land cover boundary (with 1 year added due to real/int conversion) '
360 call check_consistency_element(real(lc_year_end(nlcoverscene) + 1_i4, dp), &
361 landcoverperiodboundaries_temp(nlcoverscene+1), errorstring, idomain)
362
363 ! last soil horizon is spatially variable, so this is not checked yet
364 ! first soil horizon 0 and not contained in HorizonDepth_mHM, so skip that, too
365 do k=2, nsoilhorizons_mhm
366 errorstring = compress(trim(num2str(k)))//'th soil horizon boundary'
367 call check_consistency_element(horizondepth_mhm(k-1), soilhorizonboundaries_temp(k), errorstring, idomain)
368 end do
369
370 do k=1, nlai+1
371 errorstring = compress(trim(num2str(k)))//'th LAI period boundary'
372 call check_consistency_element(laiboundaries(k), laiboundaries_temp(k), errorstring, idomain)
373 end do
374
375 end subroutine check_dimension_consistency
376
377 !> \copydoc check_consistency_element
378 subroutine check_consistency_element_dp(item1, item2, name, iDomain)
379 use mo_utils, only: ne
380 use mo_string_utils, only: compress, num2str
381
382 real(dp), intent(in) :: item1, item2
383 character(*), intent(in) :: name
384 integer(i4), intent(in) :: iDomain
385
386 if (ne(item1, item2)) then
387 call error_message( &
388 'The ', trim(name),&
389 ' as set in the configuration file (', &
390 compress(trim(num2str(item1))), &
391 ') does not conform with domain ', &
392 compress(trim(num2str(idomain))), ' (', compress(trim(num2str(item2))), ').')
393 end if
394 end subroutine check_consistency_element_dp
395
396 !> \copydoc check_consistency_element
397 subroutine check_consistency_element_i4(item1, item2, name, iDomain)
398 use mo_string_utils, only: compress, num2str
399
400 integer(i4), intent(in) :: item1, item2
401 character(*), intent(in) :: name
402 integer(i4), intent(in) :: iDomain
403
404 if (item1 /= item2) then
405 call error_message( &
406 'The ', trim(name),&
407 ' as set in the configuration file (', &
408 compress(trim(num2str(item1))), &
409 ') does not conform with domain ', &
410 compress(trim(num2str(idomain))), ' (', compress(trim(num2str(item2))), ').')
411 end if
412 end subroutine check_consistency_element_i4
413
414end module mo_common_restart
check consistency of two given items
Provides constants commonly used by mHM, mRM and MPR.
character(64), parameter, public soilhorizonsvarname
character(64), parameter, public landcoverperiodsvarname
character(64), parameter, public laivarname
real(dp), parameter, public nodata_dp
integer(i4), parameter, public nodata_i4
Provides structures needed by mHM, mRM and/or mpr.
common restart tools
subroutine, public read_grid_info(infile, level_name, new_grid)
reads configuration apart from Level 11 configuration from a restart directory
subroutine, public write_grid_info(grid_in, level_name, nc)
write restart files for each domain
subroutine check_consistency_element_i4(item1, item2, name, idomain)
check consistency of two given items
subroutine, public read_nlai_and_check_dims(idomain, infile)
read nubmer of LAI time steps and check dimension configurations read from restart file
subroutine check_consistency_element_dp(item1, item2, name, idomain)
check consistency of two given items
subroutine check_dimension_consistency(idomain, nsoilhorizons_temp, soilhorizonboundaries_temp, nlais_temp, laiboundaries_temp, nlandcoverperiods_temp, landcoverperiodboundaries_temp)
checks dimension configurations read from restart file
Provides common types needed by mHM, mRM and/or mpr.
Provides structures needed by mHM, mRM and/or mpr.
integer(i4), public nlcoverscene
integer(i4), dimension(:), allocatable, public lc_year_end
integer(i4), dimension(:), allocatable, public lc_year_start
Global variables for mpr only.
integer(i4), public nsoilhorizons_mhm
real(dp), dimension(:), allocatable, public laiboundaries
real(dp), dimension(:), allocatable, public horizondepth_mhm