5.13.3-dev0
mHM
The mesoscale Hydrological Model
Loading...
Searching...
No Matches
mo_read_wrapper.f90
Go to the documentation of this file.
1!> \file mo_read_wrapper.f90
2!> \brief \copybrief mo_read_wrapper
3!> \details \copydetails mo_read_wrapper
4
5!> \brief Wrapper for all reading routines.
6!> \details This module is to wrap up all reading routines.
7!! The general written reading routines are used to store now the read data into global variables.
8!> \authors Juliane Mai, Matthias Zink
9!> \date Jan 2013
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_mpr
14
15 USE mo_kind, ONLY : i4, dp
17 use mo_message, only: message, error_message
18
19 IMPLICIT NONE
20
21 PUBLIC :: read_data ! reads all available data
22
23CONTAINS
24
25 ! ------------------------------------------------------------------
26
27 ! NAME
28 ! read_data
29
30 ! PURPOSE
31 !> \brief Reads data.
32
33 !> \details The namelists are already read by read_config call.
34 !> All LUTs are read from their respective directory and information within those
35 !> files are shared across all domains to be modeled.
36
37 ! INTENT(IN), OPTIONAL
38 !> \param[in] "type(period), dimension(:), optional :: LAIPer"
39
40 ! HISTORY
41 !> \authors Juliane Mai & Matthias Zink
42
43 !> \date Feb 2013
44
45 ! Modifications:
46 ! Luis Samaniego Feb 2013 - rotate fdir variable to the new coordinate system
47 ! Rohini Kumar Aug 2013 - name changed from "L0_LAI" to "L0_LCover_LAI"
48 ! Rohini Kumar Aug 2013 - added dirSoil_LUT and dirGeology_LUT, and changed to
49 ! read datapaths and variables made accordingly
50 ! Rohini Kumar Aug 2013 - added iFlag_LAI_data_format to handle LAI options, and changed
51 ! within the code made accordingly
52 ! Rohini Kumar Sep 2013 - read input data for routing processes according to process_matrix flag
53 ! Matthias Zink Mar 2014 - added inflow gauge
54 ! Kumar & Schroen Apr 2014 - added check for consistency of L0 and L1 spatial resolution
55 ! Stephan Thober Jun 2014 - added perform_mpr for omitting L0 read
56 ! Matthias Cuntz & Juliane Mai Nov 2014 - LAI input from daily, monthly or yearly files
57 ! Stephan Thober Aug 2015 - moved routing related variables and routines to mRM
58 ! Rohini Kumar Mar 2016 - options to handle different soil databases
59 ! Matthias Zink Mar 2014 - added subroutine for consistency check
60 ! Stephan Thober Nov 2016 - moved processMatrix to common variables
61 ! Rohini Kumar Dec 2016 - option to handle monthly mean gridded fields of LAI
62 ! Robert Schweppe Jun 2018 - refactoring and reformatting
63
64 subroutine read_data(LAIPer)
65
66 use mo_append, only : append, paste
67 use mo_constants, only : yearmonths
69 use mo_common_types, only: period, grid
80 use mo_read_latlon, only : read_latlon
84 use mo_string_utils, only : num2str
85 use mo_timer, only : timer_get, timer_start, &
86 timer_stop
87
88 implicit none
89
90 type(period), dimension(:), intent(in), optional :: laiper
91
92 ! loop variables
93 integer(i4) :: domainid, idomain, ivar, ihorizon, imon, itimer, ll
94
95 ! dummy variable
96 integer(i4) :: nh
97
98 ! file unit of file to read
99 integer(i4) :: nunit
100
101 ! file name of file to read
102 character(256) :: fname
103
104 real(dp), dimension(:, :), allocatable :: data_dp_2d
105
106 integer(i4), dimension(:, :), allocatable :: data_i4_2d
107
108 integer(i4), dimension(:, :), allocatable :: datamatrix_i4
109
110 logical, dimension(:, :), allocatable :: mask_2d
111
112 integer(i4), dimension(:), allocatable :: dummy_i4
113
114 type(grid), pointer :: level0_idomain
115
116 real(dp), parameter :: slope_minval = 0.01_dp
117
118 real(dp), parameter :: aspect_minval = 1.00_dp
119
120
121 call message(' Reading data ...')
122 itimer = 1
123 call timer_start(itimer)
124
125 call message(' Reading dem and lcover ...')
126 call read_dem()
127 call read_lcover()
128
129 ! ************************************************
130 ! READ LOOKUP TABLES
131 ! ************************************************
132 !
133 ! Soil LUT
134 if(iflag_soildb .eq. 0) then
135 fname = trim(adjustl(dircommonfiles)) // trim(adjustl(file_soil_database))
136 else if(iflag_soildb .eq. 1) then
137 fname = trim(adjustl(dircommonfiles)) // trim(adjustl(file_soil_database_1))
138 end if
139 call read_soil_lut(trim(fname))
140
141 ! Geological formation LUT
142 fname = trim(adjustl(dircommonfiles)) // trim(adjustl(file_geolut))
144
145 ! LAI LUT
146 if(timestep_lai_input .EQ. 0) then
147 fname = trim(adjustl(dircommonfiles)) // trim(adjustl(file_lailut))
148 call read_lai_lut(trim(fname), ulailut, nlaiclass, laiunitlist, lailut)
149 end if
150
151 domains: do idomain = 1, domainmeta%nDomains
152 domainid = domainmeta%indices(idomain)
153
154 level0_idomain => level0(domainmeta%L0DataFrom(idomain))
155
156 call message(' Reading data for domain: ', trim(adjustl(num2str(domainid))), ' ...')
157 ! check whether L0 data is shared
158 ! ToDo: check change
159 if (domainmeta%L0DataFrom(idomain) < idomain) then
160 !
161 call message(' Using data of domain ', &
162 trim(adjustl(num2str(domainmeta%indices(domainmeta%L0DataFrom(idomain))))), ' for domain: ',&
163 trim(adjustl(num2str(domainid))), '...')
164 ! DO NOT read L0 data
165 cycle
166
167 end if
168
169 itimer = 2
170 call timer_start(itimer)
171
172 ! read slope and aspect - datatype real
173 nvars_real : do ivar = 1, 2
174 select case (ivar)
175 case(1) ! slope
176 call message(' Reading slope ...')
177 fname = trim(adjustl(dirmorpho(idomain))) // trim(adjustl(file_slope))
178 nunit = uslope
179 case(2) ! aspect
180 call message(' Reading aspect ...')
181 fname = trim(adjustl(dirmorpho(idomain))) // trim(adjustl(file_aspect))
182 nunit = uaspect
183 end select
184
185 ! reading
186 call read_spatial_data_nc_or_ascii(trim(fname), nunit, &
187 level0_idomain%nrows, level0_idomain%ncols, level0_idomain%xllcorner, &
188 level0_idomain%yllcorner, level0_idomain%cellsize, data_dp_2d, mask_2d)
189 ! put global nodata value into array (probably not all grid cells have values)
190 data_dp_2d = merge(data_dp_2d, nodata_dp, mask_2d)
191 ! put data in variable
192 select case (ivar)
193 case(1) ! slope
194 call append(l0_slope, pack(data_dp_2d, level0_idomain%mask))
195
196 case(2) ! aspect
197 call append(l0_asp, pack(data_dp_2d, level0_idomain%mask))
198 end select
199 ! deallocate arrays
200 deallocate(data_dp_2d, mask_2d)
201
202 end do nvars_real
203
204 ! read datatype integer
205 ! ***** CHANGE IS MADE HERE TO ACCOMODATE READ SEVERAL TYPES OF SOIL DATABASES
206 ! change from the earlier code where everything was done in the DO loop (**see below **)
207 ! here everything is more explicit and no do loop appears as was the case in previous version
208
209 ! read soilID in both options
210 call message(' Reading soil ids ...')
211
212 nh = 1 !> by default; when iFlag_soilDB = 0
213 if(iflag_soildb .eq. 1) nh = nsoilhorizons_mhm
214 ! modified way to read multiple horizons specific soil class
215 do ihorizon = 1, nh
216 if(iflag_soildb .eq. 0) then
217 fname = trim(adjustl(dirmorpho(idomain))) // trim(adjustl(file_soilclass))
218 else if(iflag_soildb .eq. 1) then
219 write(fname, 172) ihorizon
220 172 format('soil_class_horizon_', i2.2, '.asc')
221 fname = trim(adjustl(dirmorpho(idomain))) // trim(adjustl(fname))
222 end if
223 call read_spatial_data_nc_or_ascii(trim(fname), usoilclass, &
224 level0_idomain%nrows, level0_idomain%ncols, level0_idomain%xllcorner, &
225 level0_idomain%yllcorner, level0_idomain%cellsize, data_i4_2d, mask_2d)
226 ! put global nodata value into array (probably not all grid cells have values)
227 data_i4_2d = merge(data_i4_2d, nodata_i4, mask_2d)
228 call paste(datamatrix_i4, pack(data_i4_2d, level0_idomain%mask), nodata_i4)
229 deallocate(data_i4_2d)
230 end do
231 call append(l0_soilid, datamatrix_i4)
232 deallocate(datamatrix_i4)
233
234 ! read geoUnit
235 fname = trim(adjustl(dirmorpho(idomain))) // trim(adjustl(file_hydrogeoclass))
236 ! reading and transposing
238 level0_idomain%nrows, level0_idomain%ncols, level0_idomain%xllcorner, &
239 level0_idomain%yllcorner, level0_idomain%cellsize, data_i4_2d, mask_2d)
240 ! put global nodata value into array (probably not all grid cells have values)
241 data_i4_2d = merge(data_i4_2d, nodata_i4, mask_2d)
242 call append(l0_geounit, pack(data_i4_2d, level0_idomain%mask))
243 deallocate(data_i4_2d, mask_2d)
244
245 ! LAI values
246 call message(' Reading LAI ...')
247 select case (timestep_lai_input)
248 case(1) ! long term mean monthly gridded fields
249 call prepare_gridded_mean_monthly_lai_data(idomain, level0_idomain%nrows, level0_idomain%ncols, level0_idomain%mask)
250
251 case(0) ! long term mean monthly values per class with LUT
252 ! only set if not yet allocated (e.g. domain 1)
253 if (.not. allocated(laiboundaries)) then
254 nlai = int(yearmonths, i4)
255 allocate(laiboundaries(nlai+1))
256 laiboundaries = [(imon, imon=1, nlai+1)]
257 end if
258
259 fname = trim(adjustl(dirmorpho(idomain))) // trim(adjustl(file_laiclass))
260 ! reading and transposing
261 call read_spatial_data_nc_or_ascii(trim(fname), ulaiclass, &
262 level0_idomain%nrows, level0_idomain%ncols, level0_idomain%xllcorner, &
263 level0_idomain%yllcorner, level0_idomain%cellsize, data_i4_2d, mask_2d)
264 ! put global nodata value into array (probably not all grid cells have values)
265 data_i4_2d = merge(data_i4_2d, nodata_i4, mask_2d)
266 allocate(dummy_i4(count(level0_idomain%mask)))
267 dummy_i4 = pack(data_i4_2d, level0_idomain%mask)
268 deallocate(data_i4_2d, mask_2d)
269
271
272 allocate(data_dp_2d(count(level0_idomain%mask), nlai))
273 do imon = 1, nlai
274 ! determine LAIs per month
275 do ll = 1, size(lailut, dim = 1)
276 data_dp_2d(:, imon) = merge(lailut(ll, imon), data_dp_2d(:, imon), dummy_i4(:) .EQ. laiunitlist(ll))
277 end do
278 end do
279 call append(l0_gridded_lai, data_dp_2d(:, :))
280 deallocate(dummy_i4, data_dp_2d)
281 ! correction for 0 LAI values to avoid numerical instabilities
282 l0_gridded_lai(:, :) = merge(1.00e-10_dp, l0_gridded_lai(:, :), l0_gridded_lai(:, :) .LT. 1.00e-10_dp)
283 l0_gridded_lai(:, :) = merge(30.0_dp, l0_gridded_lai(:, :), l0_gridded_lai(:, :) .GT. 30.0_dp)
284 case(-3 : -1) ! daily, monthly or yearly gridded fields (time-series)
285 call prepare_gridded_daily_lai_data(idomain, level0_idomain%nrows, level0_idomain%ncols, level0_idomain%mask, &
286 laiper(idomain))
287
288 end select
289
290 ! read lat lon coordinates of each domain
291 call message(' Reading latitude/logitude ...')
292 call read_latlon(idomain, "lon_l0", "lat_l0", "level0", level0_idomain)
293
294 call timer_stop(itimer)
295 call message(' in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
296
297 end do domains
298 itimer = 1
299 call timer_stop(itimer)
300 call message(' in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
301
302 !Soil
303 ! determine name od soil class definition file based on input option iFlag_soilDB
304 if(iflag_soildb .eq. 0) then
305 fname = file_soil_database
306 else if(iflag_soildb .eq. 1) then
308 end if
309
310 ! If you are getting segmentation fault with intel on large file (e.g. here on soils), then
311 ! make sure to include following into your Marefile: INTEL_EXCLUDE := mo_read_wrapper.f90
312 call check_consistency_lut_map(reshape(l0_soilid, (/ size(l0_soilid, 1) * size(l0_soilid, 2) /)), &
313 soildb%id(:), fname)
314 ! Geology
316
317 ! deactivate parameters of non existing geological classes in study domain for optimization
318 ! loop over geological units in look up list
319 do ivar = 1, size(geounitlist, 1)
320 ! check if unit appears in geological map (dummy_i4 is unique number in L0_geoUnit)
321 if (.not. any(dummy_i4 .EQ. geounitlist(ivar))) then
322 ! deactivate optimization flag (dim=4 from global_parameters)
323 global_parameters(processmatrix(9, 3) - processmatrix(9, 2) + ivar, 4) = 0
324 call message('***WARNING: Geological unit ', trim(adjustl(num2str(geounitlist(ivar)))))
325 call message(' is not appearing in study domain.')
326 end if
327 end do
328
329 deallocate(dummy_i4) ! is allocated in subroutine check_consistency_lut_map - geology
330
331 !----------------------------------------------------------------
332 ! Correction for slope and aspect -- min value set above
333 !----------------------------------------------------------------
334 ! keep the colons (:) in the statements because of Intel's reallocation lhs problem
335 l0_slope(:) = merge(slope_minval, l0_slope(:), (l0_slope(:) .lt. slope_minval))
336 l0_asp(:) = merge(aspect_minval, l0_asp(:), (l0_asp(:) .lt. aspect_minval))
337
338 end subroutine read_data
339
340 ! ------------------------------------------------------------------
341
342 ! NAME
343 ! check_consistency_lut_map
344
345 ! PURPOSE
346 !> \brief Checks if classes in input maps appear in look up tables.
347
348 !> \details Determines wether a class appearing in the morphological input
349 !> is occuring in the respective look up table. mHM breaks if inconsistencies
350 !> are discovered.
351
352 ! INTENT(IN)
353 !> \param[in] "integer(i4), dimension(:) :: data" map of study domain
354 !> \param[in] "integer(i4), dimension(:) :: lookuptable" look up table corresponding to map
355 !> \param[in] "character(*) :: filename" name of the lut file - ERORR warn
356
357 ! INTENT(OUT), OPTIONAL
358 !> \param[out] "integer(i4), dimension(:), optional :: unique_values" array of unique values in dataone
359
360 ! HISTORY
361 !> \authors Matthias Zink
362
363 !> \date Nov 2016
364
365 ! Modifications:
366 ! Robert Schweppe Jun 2018 - refactoring and reformatting
367
368 subroutine check_consistency_lut_map(data, lookuptable, filename, unique_values)
369
370 use mo_orderpack, only : unista
371 use mo_string_utils, only : num2str
372
373 implicit none
374
375 ! map of study domain
376 integer(i4), dimension(:), intent(in) :: data
377
378 ! look up table corresponding to map
379 integer(i4), dimension(:), intent(in) :: lookuptable
380
381 ! name of the lut file - ERORR warn
382 character(*), intent(in) :: filename
383
384 ! array of unique values in dataone
385 integer(i4), dimension(:), allocatable, intent(out), optional :: unique_values
386
387 integer(i4) :: n_unique_elements
388
389 integer(i4) :: ielement
390
391 integer(i4), dimension(:), allocatable :: temp
392
393
394 allocate(temp(size(data, 1)))
395 ! copy L0_geoUnit because subroutine unista overwrites the nunit entries of the
396 ! input array with the unique array values
397 temp = data
398 ! retrieve unique values of data
399 call unista(temp, n_unique_elements)
400 ! check if unit exists in look up table
401 do ielement = 1, n_unique_elements
402 if ( temp(ielement) == nodata_i4 ) call error_message( &
403 '***ERROR: Class ', trim(adjustl(num2str(temp(ielement)))), &
404 ' was searched in ', trim(adjustl(filename)), &
405 ' which indicates a masking problem!' &
406 )
407 if (.not. any(lookuptable .EQ. temp(ielement))) then
408 call error_message('***ERROR: Class ', trim(adjustl(num2str(temp(ielement)))), ' is missing', raise=.false.)
409 call error_message(' in input file ', trim(adjustl(filename)), ' ...')
410 end if
411 end do
412
413 ! pass unique values if optional argument unique_values is given
414 if (present(unique_values)) then
415 allocate(unique_values(n_unique_elements))
416 unique_values(:) = temp(1 : n_unique_elements)
417 end if
418 deallocate(temp)
419
420 end subroutine check_consistency_lut_map
421
422
423END MODULE mo_read_wrapper
Reads spatial data files of nc or ASCII format.
Provides constants commonly used by mHM, mRM and MPR.
real(dp), parameter, public nodata_dp
integer(i4), parameter, public nodata_i4
Common reading routines.
subroutine, public read_lcover
TODO: add description.
subroutine, public read_dem
TODO: add description.
Provides common types needed by mHM, mRM and/or mpr.
Provides structures needed by mHM, mRM and/or mpr.
real(dp), dimension(:, :), allocatable, target, public global_parameters
type(domain_meta), public domainmeta
character(256), public dircommonfiles
character(256), dimension(:), allocatable, public dirmorpho
integer(i4), dimension(nprocesses, 3), public processmatrix
type(grid), dimension(:), allocatable, target, public level0
Provides file names and units for mRM.
character(len=*), parameter file_soil_database_1
Soil database file (iFlag_soilDB = 1)
integer, parameter usoilclass
Unit for soil classes input data file.
character(len=*), parameter file_slope
slope input data file
integer, parameter uaspect
Unit for aspect input data file.
character(len=*), parameter file_hydrogeoclass
hydrogeological classes input data file
character(len=*), parameter file_aspect
aspect input data file
integer, parameter uslope
Unit for slope input data file.
integer, parameter ulailut
Unit for LAI classes lookup table file.
character(len=*), parameter file_laiclass
LAI classes input data file.
character(len=*), parameter file_lailut
LAI classes lookup table file.
integer, parameter ulaiclass
Unit for LAI input data file.
integer, parameter uhydrogeoclass
Unit for hydrogeological classes input data file.
character(len=*), parameter file_soil_database
Soil database file (iFlag_soilDB = 0) = classical mHM format.
integer, parameter ugeolut
Unit for geological formation lookup table file.
character(len=*), parameter file_soilclass
soil classes input data file
character(len=*), parameter file_geolut
geological formation lookup table file
Global variables for mpr only.
integer(i4), dimension(:), allocatable, public geounitkar
integer(i4), dimension(:), allocatable, public geounitlist
type(period), dimension(:), allocatable, public laiper
integer(i4), dimension(:), allocatable, public laiunitlist
integer(i4), dimension(:), allocatable, public l0_geounit
real(dp), dimension(:), allocatable, public l0_asp
real(dp), dimension(:, :), allocatable, public lailut
integer(i4), public nsoilhorizons_mhm
integer(i4), dimension(:, :), allocatable, public l0_soilid
real(dp), dimension(:, :), allocatable, public l0_gridded_lai
real(dp), dimension(:), allocatable, public laiboundaries
integer(i4), public timestep_lai_input
real(dp), dimension(:), allocatable, public l0_slope
Prepare daily LAI fields (e.g., MODIS data) for mHM.
subroutine, public prepare_gridded_mean_monthly_lai_data(idomain, nrows, ncols, mask)
prepare_gridded_mean_monthly_LAI_data
subroutine, public prepare_gridded_daily_lai_data(idomain, nrows, ncols, mask, laiper_idomain)
Prepare gridded daily LAI data.
reading latitude and longitude coordinates for each domain
subroutine, public read_latlon(ii, lon_var_name, lat_var_name, level_name, level)
reads latitude and longitude coordinates
Routines reading lookup tables (lut).
subroutine, public read_lai_lut(filename, fileunit, nlai, laiidlist, lai)
Reads LUT containing LAI information.
subroutine, public read_geoformation_lut(filename, fileunit, ngeo, geo_unit, geo_karstic)
Reads LUT containing geological formation information.
Reads spatial input data.
Wrapper for all reading routines.
subroutine check_consistency_lut_map(data, lookuptable, filename, unique_values)
Checks if classes in input maps appear in look up tables.
subroutine, public read_data(laiper)
Reads data.
Generating soil database from input file.
subroutine, public read_soil_lut(filename)
Reads the soil LUT file.