5.13.2-dev0
mHM
The mesoscale Hydrological Model
Loading...
Searching...
No Matches
mo_grid.f90
Go to the documentation of this file.
1!> \file mo_grid.f90
2!> \brief \copybrief mo_grid
3!> \details \copydetails mo_grid
4
5!> \brief gridding tools
6!> \details Common tools to deal with grids in mHM.
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
12module mo_grid
13 use mo_kind, only : dp, i4
14
15 IMPLICIT NONE
16
17 PRIVATE
18
21contains
22 ! ------------------------------------------------------------------
23
24 ! NAME
25 ! init_lowres_level
26
27 ! PURPOSE
28 !> \brief Level-1 variable initialization
29
30 !> \details following tasks are performed for L1 datasets
31 !> - cell id & numbering
32 !> - mask creation
33 !> - storage of cell cordinates (row and coloum id)
34 !> - sorage of four corner L0 cordinates
35 !> If a variable is added or removed here, then it also has to
36 !> be added or removed in the subroutine config_variables_set in
37 !> module mo_restart and in the subroutine set_config in module
38 !> mo_set_netcdf_restart
39
40 ! INTENT(IN)
41 !> \param[in] "type(Grid) :: highres"
42 !> \param[in] "real(dp) :: target_resolution"
43
44 ! INTENT(INOUT)
45 !> \param[inout] "type(Grid) :: lowres"
46
47 ! INTENT(INOUT), OPTIONAL
48 !> \param[inout] "type(GridRemapper), optional :: highres_lowres_remap"
49
50 ! HISTORY
51 !> \authors Rohini Kumar
52
53 !> \date Jan 2013
54
55 ! Modifications:
56 ! Robert Schweppe Jun 2018 - refactoring and reformatting
57
58 subroutine init_lowres_level(highres, target_resolution, lowres, highres_lowres_remap)
59
62
63 implicit none
64
65 type(grid), target, intent(in) :: highres
66
67 real(dp), intent(in) :: target_resolution
68
69 type(grid), target, intent(inout) :: lowres
70
71 type(gridremapper), intent(inout), optional :: highres_lowres_remap
72
73 real(dp), dimension(:, :), allocatable :: areacell0_2d
74
75 real(dp) :: cellfactor
76
77 integer(i4) :: iup, idown
78
79 integer(i4) :: jl, jr
80
81 integer(i4) :: i, j, k, ic, jc
82
83 ! STEPS ::
84
85 !--------------------------------------------------------
86 ! 1) Estimate each variable locally for a given domain
87 ! 2) Pad each variable to its corresponding global one
88 !--------------------------------------------------------
89 ! grid properties
90 if (.not. allocated(lowres%mask)) then
91 call calculate_grid_properties(highres%nrows, highres%ncols, &
92 highres%xllcorner, highres%yllcorner, highres%cellsize, &
93 target_resolution, &
94 lowres%nrows, lowres%ncols, &
95 lowres%xllcorner, lowres%yllcorner, lowres%cellsize)
96 ! cellfactor = leve1-1 / level-0
97 cellfactor = anint(lowres%cellsize / highres%cellsize)
98
99 ! allocation and initalization of mask at level-1
100 allocate(lowres%mask(lowres%nrows, lowres%ncols))
101 lowres%mask(:, :) = .false.
102
103 ! create mask at level-1
104 do j = 1, highres%ncols
105 jc = ceiling(real(j, dp) / cellfactor)
106 do i = 1, highres%nrows
107 if (.NOT. highres%mask(i, j)) cycle
108 ic = ceiling(real(i, dp) / cellfactor)
109 lowres%mask(ic, jc) = .true.
110 end do
111 end do
112
113 ! estimate ncells and initalize related variables
114 lowres%nCells = count(lowres%mask)
115 ! allocate and initalize cell1 related variables
116 allocate(lowres%Id (lowres%nCells))
117 lowres%Id = (/ (k, k = 1, lowres%nCells) /)
118 end if
119
120 if (present(highres_lowres_remap)) then
121 ! cellfactor = leve1-1 / level-0, set again in case not yet initialized
122 cellfactor = lowres%cellsize / highres%cellsize
123
124 ! lowres additional properties
125 allocate(areacell0_2d(highres%nrows, highres%ncols))
126 areacell0_2d(:, :) = unpack(highres%CellArea, highres%mask, nodata_dp)
127
128 if (.not. allocated(lowres%CellCoor)) then
129 allocate(lowres%CellCoor (lowres%nCells, 2))
130 allocate(lowres%CellArea (lowres%nCells))
131 end if
132
133 allocate(highres_lowres_remap%lower_bound(lowres%nCells))
134 allocate(highres_lowres_remap%upper_bound(lowres%nCells))
135 allocate(highres_lowres_remap%left_bound (lowres%nCells))
136 allocate(highres_lowres_remap%right_bound(lowres%nCells))
137 allocate(highres_lowres_remap%n_subcells (lowres%nCells))
138 allocate(highres_lowres_remap%lowres_id_on_highres (highres%nrows, highres%ncols))
139 highres_lowres_remap%lowres_id_on_highres = nodata_i4
140
141 highres_lowres_remap%high_res_grid => highres
142 highres_lowres_remap%low_res_grid => lowres
143
144 k = 0
145 do jc = 1, lowres%ncols
146 do ic = 1, lowres%nrows
147 if (.NOT. lowres%mask(ic, jc)) cycle
148 k = k + 1
149
150 lowres%CellCoor(k, 1) = ic
151 lowres%CellCoor(k, 2) = jc
152
153 ! coord. of all corners -> of finer scale level-0
154 iup = (ic - 1) * nint(cellfactor, i4) + 1
155 idown = ic * nint(cellfactor, i4)
156 jl = (jc - 1) * nint(cellfactor, i4) + 1
157 jr = jc * nint(cellfactor, i4)
158
159 ! constrain the range of up, down, left, and right boundaries
160 if(iup < 1) iup = 1
161 if(idown > highres%nrows) idown = highres%nrows
162 if(jl < 1) jl = 1
163 if(jr > highres%ncols) jr = highres%ncols
164
165 highres_lowres_remap%upper_bound (k) = iup
166 highres_lowres_remap%lower_bound (k) = idown
167 highres_lowres_remap%left_bound (k) = jl
168 highres_lowres_remap%right_bound(k) = jr
169
170 ! effective area [km2] & total no. of L0 cells within a given L1 cell
171 lowres%CellArea(k) = sum(areacell0_2d(iup : idown, jl : jr), highres%mask(iup : idown, jl : jr))
172 highres_lowres_remap%n_subcells(k) = count(highres%mask(iup : idown, jl : jr))
173 ! Delimitation of level-11 cells on level-0
174 highres_lowres_remap%lowres_id_on_highres(iup : idown, jl : jr) = k
175 end do
176 end do
177
178 ! free space
179 deallocate(areacell0_2d)
180
181 end if
182
183 end subroutine init_lowres_level
184
185 ! NAME
186 ! set_domain_indices
187
188 ! PURPOSE
189 !> \brief TODO: add description
190
191 !> \details TODO: add description
192
193 ! INTENT(INOUT)
194 !> \param[inout] "type(Grid), dimension(:) :: grids"
195
196 ! HISTORY
197 !> \authors Robert Schweppe
198
199 !> \date Jun 2018
200
201 ! Modifications:
202 ! Stephan Thober, Aug 2019 - added optional indices for L0 data because L0 data can be shared among domains
203
204 subroutine set_domain_indices(grids, indices)
205
206 use mo_common_types, only: grid
207
208 implicit none
209
210 type(grid), intent(inout), dimension(:) :: grids
211 integer(i4), intent(in), dimension(:), optional :: indices
212
213 integer(i4) :: idomain
214
215
216 do idomain = 1, size(grids)
217 ! Saving indices of mask and packed data
218 if(idomain .eq. 1_i4) then
219 grids(idomain)%iStart = 1_i4
220 else
221 if (present(indices)) then
222 grids(idomain)%iStart = grids(indices(idomain - 1))%iEnd + 1_i4
223 else
224 grids(idomain)%iStart = grids(idomain - 1_i4)%iEnd + 1_i4
225 end if
226 end if
227 grids(idomain)%iEnd = grids(idomain)%iStart + grids(idomain)%nCells - 1_i4
228 end do
229
230 end subroutine set_domain_indices
231
232 ! ------------------------------------------------------------------
233
234 ! NAME
235 ! L0_grid_setup
236
237 ! PURPOSE
238 !> \brief level 0 variable initialization
239
240 !> \details following tasks are performed for L0 data sets
241 !> - cell id & numbering
242 !> - storage of cell cordinates (row and coloum id)
243 !> - empirical dist. of terrain slope
244 !> - flag to determine the presence of a particular soil id
245 !> in this configuration of the model run
246 !> If a variable is added or removed here, then it also has to
247 !> be added or removed in the subroutine config_variables_set in
248 !> module mo_restart and in the subroutine set_config in module
249 !> mo_set_netcdf_restart
250
251 ! INTENT(INOUT)
252 !> \param[inout] "type(Grid) :: new_grid"
253
254 ! HISTORY
255 !> \authors Rohini Kumar
256
257 !> \date Jan 2013
258
259 ! Modifications:
260 ! Rohini Kumar & Matthias Cuntz May 2014 - cell area calulation based on a regular lat-lon grid or
261 ! on a regular X-Y coordinate system
262 ! Matthias Cuntz May 2014 - changed empirical distribution function so that doubles get the same value
263 ! Matthias Zink & Matthias Cuntz Feb 2016 - code speed up due to reformulation of CDF calculation
264 ! Rohini Kumar Mar 2016 - changes for handling multiple soil database options
265 ! Robert Schweppe Jun 2018 - refactoring and reformatting
266
267 subroutine l0_grid_setup(new_grid)
268
269 use mo_common_types, only: grid
271 use mo_constants, only : radiusearth_dp, twopi_dp
272
273 implicit none
274
275 type(grid), intent(inout) :: new_grid
276
277 real(dp), dimension(:, :), allocatable :: areacell_2d
278
279 integer(i4) :: i, j, k
280
281 real(dp) :: rdum, degree_to_radian, degree_to_metre
282
283 ! STEPS ::
284
285
286 !--------------------------------------------------------
287 ! 1) Estimate each variable locally for a given domain
288 ! 2) Pad each variable to its corresponding global one
289 !--------------------------------------------------------
290 ! level-0 information
291 new_grid%nCells = count(new_grid%mask)
292
293 allocate(new_grid%CellCoor(new_grid%nCells, 2))
294 allocate(new_grid%Id(new_grid%nCells))
295 allocate(new_grid%CellArea(new_grid%nCells))
296 allocate(areacell_2d(new_grid%nrows, new_grid%ncols))
297
298 new_grid%Id = (/ (k, k = 1, new_grid%nCells) /)
299
300 !------------------------------------------------
301 ! start looping for cell cordinates and ids
302 !------------------------------------------------
303 k = 0
304 do j = 1, new_grid%ncols
305 do i = 1, new_grid%nrows
306 if (.NOT. new_grid%mask(i, j)) cycle
307 k = k + 1
308 new_grid%cellCoor(k, 1) = i
309 new_grid%cellCoor(k, 2) = j
310 end do
311 end do
312
313 ! ESTIMATE AREA [m2]
314
315 ! regular X-Y coordinate system
316 if(iflag_cordinate_sys .eq. 0) then
317 new_grid%CellArea(:) = new_grid%cellsize * new_grid%cellsize
318
319 ! regular lat-lon coordinate system
320 else if(iflag_cordinate_sys .eq. 1) then
321
322 degree_to_radian = twopi_dp / 360.0_dp
323 degree_to_metre = radiusearth_dp * twopi_dp / 360.0_dp
324 do i = new_grid%ncols, 1, -1
325 j = new_grid%ncols - i + 1
326 ! get latitude in degrees
327 rdum = new_grid%yllcorner + (real(j, dp) - 0.5_dp) * new_grid%cellsize
328 ! convert to radians
329 rdum = rdum * degree_to_radian
330 ! AREA [m2]
331 areacell_2d(:, i) = (new_grid%cellsize * cos(rdum) * degree_to_metre) * (new_grid%cellsize * degree_to_metre)
332 end do
333 new_grid%CellArea(:) = pack(areacell_2d(:, :), new_grid%mask)
334
335 end if
336
337 ! free space
338 deallocate(areacell_2d)
339
340 end subroutine l0_grid_setup
341
342
343 !------------------------------------------------------------------
344 ! NAME
345 ! mapCoordinates
346
347 ! PURPOSE
348 !> \brief Generate map coordinates
349
350 !> \details Generate map coordinate arrays for given domain and level
351
352 ! INTENT(IN)
353 !> \param[in] "type(Grid) :: level" -> grid reference
354
355 ! INTENT(OUT)
356 !> \param[out] "real(dp), dimension(:) :: x, y"
357 !> \param[out] "real(dp), dimension(:) :: x, y"
358
359 ! HISTORY
360 !> \authors Matthias Zink
361
362 !> \date Apr 2013
363
364 ! Modifications:
365 ! Stephan Thober Nov 2013 - removed fproj dependency
366 ! David Schaefer Jun 2015 - refactored the former subroutine CoordSystem
367 ! Robert Schweppe Jun 2018 - refactoring and reformatting
368
369
370 subroutine mapcoordinates(level, y, x)
371
372 use mo_common_types, only: grid
373
374 implicit none
375
376 ! -> grid reference
377 type(grid), intent(in) :: level
378
379 real(dp), intent(out), allocatable, dimension(:) :: x, y
380
381 integer(i4) :: ii, ncols, nrows
382
383 real(dp) :: cellsize
384
385
386 cellsize = level%cellsize
387 nrows = level%nrows
388 ncols = level%ncols
389
390 allocate(x(nrows), y(ncols))
391
392 x(1) = level%xllcorner + 0.5_dp * cellsize
393 do ii = 2, nrows
394 x(ii) = x(ii - 1) + cellsize
395 end do
396
397 ! inverse for Panoply, ncview display
398 y(ncols) = level%yllcorner + 0.5_dp * cellsize
399 do ii = ncols - 1, 1, -1
400 y(ii) = y(ii + 1) + cellsize
401 end do
402
403 end subroutine mapcoordinates
404
405 !------------------------------------------------------------------
406 ! NAME
407 ! geoCoordinates
408
409 ! PURPOSE
410 !> \brief Generate geographic coordinates
411
412 !> \details Generate geographic coordinate arrays for given domain and level
413
414 ! INTENT(IN)
415 !> \param[in] "type(Grid) :: level" -> grid reference
416
417 ! INTENT(OUT)
418 !> \param[out] "real(dp), dimension(:, :) :: lat, lon"
419 !> \param[out] "real(dp), dimension(:, :) :: lat, lon"
420
421 ! HISTORY
422 !> \authors Matthias Zink
423
424 !> \date Apr 2013
425
426 ! Modifications:
427 ! Stephan Thober Nov 2013 - removed fproj dependency
428 ! David Schaefer Jun 2015 - refactored the former subroutine CoordSystem
429 ! Stephan Thober Sep 2015 - using mask to unpack coordinates
430 ! Stephan Thober Oct 2015 - writing full lat/lon again
431 ! Robert Schweppe Jun 2018 - refactoring and reformatting
432
433 subroutine geocoordinates(level, lat, lon)
434
435 use mo_common_types, only: grid
436
437 implicit none
438
439 ! -> grid reference
440 type(grid), intent(in) :: level
441
442 real(dp), intent(out), allocatable, dimension(:, :) :: lat, lon
443
444
445 lat = level%y
446 lon = level%x
447
448 end subroutine geocoordinates
449
450 ! ------------------------------------------------------------------
451
452 ! NAME
453 ! calculate_grid_properties
454
455 ! PURPOSE
456 !> \brief Calculates basic grid properties at a required coarser level using
457 !> information of a given finer level.
458 !> Calculates basic grid properties at a required coarser level (e.g., L11) using
459 !> information of a given finer level (e.g., L0). Basic grid properties such as
460 !> nrows, ncols, xllcorner, yllcorner cellsize are estimated in this
461 !> routine.
462
463 !> \details TODO: add description
464
465 ! INTENT(IN)
466 !> \param[in] "integer(i4) :: nrowsIn" no. of rows at an input level
467 !> \param[in] "integer(i4) :: ncolsIn" no. of cols at an input level
468 !> \param[in] "real(dp) :: xllcornerIn" xllcorner at an input level
469 !> \param[in] "real(dp) :: yllcornerIn" yllcorner at an input level
470 !> \param[in] "real(dp) :: cellsizeIn" cell size at an input level
471 !> \param[in] "real(dp) :: aimingResolution" resolution of an output level
472
473 ! INTENT(OUT)
474 !> \param[out] "integer(i4) :: nrowsOut" no. of rows at an output level
475 !> \param[out] "integer(i4) :: ncolsOut" no. of cols at an output level
476 !> \param[out] "real(dp) :: xllcornerOut" xllcorner at an output level
477 !> \param[out] "real(dp) :: yllcornerOut" yllcorner at an output level
478 !> \param[out] "real(dp) :: cellsizeOut" cell size at an output level
479
480 ! HISTORY
481 !> \authors Matthias Zink & Rohini Kumar
482
483 !> \date Feb 2013
484
485 ! Modifications:
486 ! R. Kumar Sep 2013 - documentation added according to the template
487 ! Robert Schweppe Jun 2018 - refactoring and reformatting
488
489 subroutine calculate_grid_properties(nrowsIn, ncolsIn, xllcornerIn, yllcornerIn, cellsizeIn, aimingResolution, &
490 nrowsOut, ncolsOut, xllcornerOut, yllcornerOut, cellsizeOut)
491
492 use mo_message, only : error_message
493 use mo_string_utils, only : num2str
494
495 implicit none
496
497 ! no. of rows at an input level
498 integer(i4), intent(in) :: nrowsIn
499
500 ! no. of cols at an input level
501 integer(i4), intent(in) :: ncolsIn
502
503 ! xllcorner at an input level
504 real(dp), intent(in) :: xllcornerIn
505
506 ! yllcorner at an input level
507 real(dp), intent(in) :: yllcornerIn
508
509 ! cell size at an input level
510 real(dp), intent(in) :: cellsizeIn
511
512 ! resolution of an output level
513 real(dp), intent(in) :: aimingResolution
514
515 ! no. of rows at an output level
516 integer(i4), intent(out) :: nrowsOut
517
518 ! no. of cols at an output level
519 integer(i4), intent(out) :: ncolsOut
520
521 ! xllcorner at an output level
522 real(dp), intent(out) :: xllcornerOut
523
524 ! yllcorner at an output level
525 real(dp), intent(out) :: yllcornerOut
526
527 ! cell size at an output level
528 real(dp), intent(out) :: cellsizeOut
529
530 real(dp) :: cellFactor, rounded
531 integer(i4) :: rounded_int
532
533
534 cellfactor = aimingresolution / cellsizein
535 rounded = anint(cellfactor)
536 rounded_int = nint(cellfactor)
537
538 if (abs(rounded - cellfactor) > 1.e-7_dp) then
539 call error_message( &
540 '***ERROR: Two resolutions size do not confirm: ', &
541 trim(adjustl(num2str(nint(aimingresolution)))), &
542 trim(adjustl(num2str(nint(cellsizein)))))
543 end if
544
545 cellsizeout = aimingresolution
546 ncolsout = nint(real(ncolsin, dp) / cellfactor)
547 nrowsout = nint(real(nrowsin, dp) / cellfactor)
548
549 ! if we rounded down, but now we would miss cells, add rows and/or cols
550 if ( ncolsout * rounded_int < ncolsin ) ncolsout = ncolsout + 1_i4
551 if ( nrowsout * rounded_int < nrowsin ) nrowsout = nrowsout + 1_i4
552
553 xllcornerout = xllcornerin + real(ncolsin, dp) * aimingresolution / rounded - real(ncolsout, dp) * cellsizeout
554 yllcornerout = yllcornerin + real(nrowsin, dp) * aimingresolution / rounded - real(nrowsout, dp) * cellsizeout
555
556 end subroutine calculate_grid_properties
557
558end module mo_grid
Provides constants commonly used by mHM, mRM and MPR.
real(dp), parameter, public nodata_dp
integer(i4), parameter, public nodata_i4
Provides common types needed by mHM, mRM and/or mpr.
Provides structures needed by mHM, mRM and/or mpr.
integer(i4), public iflag_cordinate_sys
gridding tools
Definition mo_grid.f90:12
subroutine, public mapcoordinates(level, y, x)
Generate map coordinates.
Definition mo_grid.f90:371
subroutine, public set_domain_indices(grids, indices)
TODO: add description.
Definition mo_grid.f90:205
subroutine, public init_lowres_level(highres, target_resolution, lowres, highres_lowres_remap)
Level-1 variable initialization.
Definition mo_grid.f90:59
subroutine calculate_grid_properties(nrowsin, ncolsin, xllcornerin, yllcornerin, cellsizein, aimingresolution, nrowsout, ncolsout, xllcornerout, yllcornerout, cellsizeout)
Calculates basic grid properties at a required coarser level using information of a given finer level...
Definition mo_grid.f90:491
subroutine, public geocoordinates(level, lat, lon)
Generate geographic coordinates.
Definition mo_grid.f90:434
subroutine, public l0_grid_setup(new_grid)
level 0 variable initialization
Definition mo_grid.f90:268