Line data Source code
1 : !> \file mo_mrm_net_startup.f90
2 : !> \brief \copybrief mo_mrm_net_startup
3 : !> \details \copydetails mo_mrm_net_startup
4 :
5 : !> \brief Startup drainage network for mHM.
6 : !> \details This module initializes the drainage network at L11 in mHM.
7 : !! - Delineation of drainage network at level 11.
8 : !! - Setting network topology (i.e. nodes and link).
9 : !! - Determining routing order.
10 : !! - Determining cell locations for network links.
11 : !! - Find drainage outlet.
12 : !! - Determine stream (links) features.
13 : !!
14 : !> \changelog
15 : !! - Rohini Kumar May 2014
16 : !! - cell area calulation based on a regular lat-lon grid or on a regular X-Y coordinate system
17 : !! - Robert Schweppe Jun 2018
18 : !! - refactoring and reformatting
19 : !> \authors Luis Samaniego
20 : !> \date Dec 2012
21 : !> \copyright Copyright 2005-\today, the mHM Developers, Luis Samaniego, Sabine Attinger: All rights reserved.
22 : !! mHM is released under the LGPLv3+ license \license_note
23 : !> \ingroup f_mrm
24 : module mo_mrm_net_startup
25 : use mo_kind, only : i4, dp
26 : use mo_message, only : message, error_message
27 :
28 : implicit none
29 :
30 : PUBLIC :: L11_L1_mapping
31 : PUBLIC :: L11_flow_direction
32 : PUBLIC :: L11_set_network_topology
33 : PUBLIC :: L11_routing_order
34 : PUBLIC :: L11_link_location
35 : PUBLIC :: L11_set_drain_outlet_gauges
36 : PUBLIC :: L11_stream_features
37 : PUBLIC :: L11_fraction_sealed_floodplain
38 : PUBLIC :: get_distance_two_lat_lon_points
39 : PUBLIC :: L11_flow_accumulation
40 : PUBLIC :: L11_calc_celerity
41 : contains
42 :
43 : ! NAME
44 : ! L11_L1_mapping
45 :
46 : ! PURPOSE
47 : !> \brief TODO: add description
48 :
49 : !> \details TODO: add description
50 :
51 : ! INTENT(IN)
52 : !> \param[in] "integer(i4) :: iDomain" domain
53 :
54 : ! HISTORY
55 : !> \authors Robert Schweppe
56 :
57 : !> \date Jun 2018
58 :
59 : ! Modifications:
60 :
61 24 : subroutine L11_L1_mapping(iDomain)
62 :
63 : use mo_append, only : append
64 : use mo_common_constants, only : nodata_i4
65 : use mo_common_variables, only : level1
66 : use mo_mrm_global_variables, only : L11_L1_ID, L1_L11_ID, level11
67 :
68 : implicit none
69 :
70 : ! domain
71 : integer(i4), intent(in) :: iDomain
72 :
73 : integer(i4) :: nrows1, ncols1
74 :
75 : integer(i4) :: nrows11, ncols11
76 :
77 : integer(i4) :: kk
78 :
79 : integer(i4) :: icc, jcc
80 :
81 : integer(i4) :: iu, id, jl, jr
82 :
83 : ! mapping of L11 Id on L1
84 24 : integer(i4), dimension(:, :), allocatable :: L11Id_on_L1
85 :
86 : ! mapping of L1 Id on L11
87 24 : integer(i4), dimension(:, :), allocatable :: L1Id_on_L11
88 :
89 : ! dummy ID
90 24 : integer(i4), dimension(:, :), allocatable :: dummy_2d_id
91 :
92 24 : real(dp) :: cellFactorRbyH
93 :
94 : integer(i4) :: cellFactorRbyH_inv
95 :
96 :
97 24 : nrows1 = level1(iDomain)%nrows
98 24 : nrows11 = level11(iDomain)%nrows
99 24 : ncols1 = level1(iDomain)%ncols
100 24 : ncols11 = level11(iDomain)%ncols
101 :
102 : ! allocate variables for mapping L11 Ids and L1 Ids
103 96 : allocate (L11Id_on_L1 (nrows1, ncols1))
104 96 : allocate (L1Id_on_L11 (nrows11, ncols11))
105 1983 : L11Id_on_L1(:, :) = nodata_i4
106 1812 : L1Id_on_L11(:, :) = nodata_i4
107 :
108 : ! set cell factor for routing
109 24 : cellFactorRbyH = level11(iDomain)%cellsize / level1(iDomain)%cellsize
110 :
111 : ! set mapping
112 : ! create mapping between L11 and L1 for L11 resolution higher than L1 resolution
113 24 : if (cellFactorRbyH .lt. 1._dp) then
114 0 : allocate (dummy_2d_id (nrows1, ncols1))
115 0 : dummy_2d_id = unpack(level1(iDomain)%Id, level1(iDomain)%mask, nodata_i4)
116 0 : cellFactorRbyH_inv = int(1. / cellFactorRbyH, i4)
117 0 : kk = 0
118 0 : do jcc = 1, ncols1
119 0 : do icc = 1, nrows1
120 0 : if(.not. level1(iDomain)%mask(icc, jcc)) cycle
121 0 : kk = kk + 1
122 : !
123 0 : iu = (icc - 1) * cellFactorRbyH_inv + 1
124 0 : id = min(icc * cellFactorRbyH_inv, nrows11)
125 0 : jl = (jcc - 1) * cellFactorRbyH_inv + 1
126 0 : jr = min(jcc * cellFactorRbyH_inv, ncols11)
127 :
128 0 : L1Id_on_L11(iu : id, jl : jr) = merge(dummy_2d_id(icc, jcc), nodata_i4, level11(iDomain)%mask(iu : id, jl : jr))
129 : end do
130 : end do
131 : else
132 72 : allocate (dummy_2d_id (nrows11, ncols11))
133 24 : dummy_2d_id = unpack(level11(iDomain)%Id, level11(iDomain)%mask, nodata_i4)
134 :
135 24 : kk = 0
136 250 : do jcc = 1, ncols11
137 1812 : do icc = 1, nrows11
138 1562 : if(.not. level11(iDomain)%mask(icc, jcc)) cycle
139 936 : kk = kk + 1
140 :
141 : ! coord. of all corners L11 -> of finer scale level-1
142 936 : iu = (icc - 1) * nint(cellFactorRbyH, i4) + 1
143 936 : id = icc * nint(cellFactorRbyH, i4)
144 936 : jl = (jcc - 1) * nint(cellFactorRbyH, i4) + 1
145 936 : jr = jcc * nint(cellFactorRbyH, i4)
146 :
147 : ! constrain the range of up, down, left, and right boundaries
148 936 : if(iu < 1) iu = 1
149 936 : if(id > nrows1) id = nrows1
150 936 : if(jl < 1) jl = 1
151 936 : if(jr > ncols1) jr = ncols1
152 :
153 : ! Delimitation of level-11 cells on level-1 for L11 resolution lower than L1 resolution
154 3170 : L11Id_on_L1(iu : id, jl : jr) = merge(dummy_2d_id(icc, jcc), nodata_i4, level1(iDomain)%mask(iu : id, jl : jr))
155 : end do
156 : end do
157 : end if
158 :
159 : ! L1 data sets
160 24 : call append(L1_L11_Id, pack (L11Id_on_L1(:, :), level1(iDomain)%mask))
161 : ! L11 data sets
162 24 : call append(L11_L1_Id, pack (L1Id_on_L11(:, :), level11(iDomain)%mask))
163 : ! free space
164 24 : deallocate(L11Id_on_L1, L1Id_on_L11, dummy_2d_id)
165 :
166 24 : end subroutine L11_L1_mapping
167 : ! --------------------------------------------------------------------------
168 :
169 : ! NAME
170 : ! L11_flow_direction
171 :
172 : ! PURPOSE
173 : !> \brief Determine the flow direction of the upscaled river
174 : !> network at level L11.
175 :
176 : !> \details The hydrographs generated at each cell are routed
177 : !> through the drainage network at level-11 towards their
178 : !> outlets. The drainage network at level-11 is conceptualized as a
179 : !> graph whose nodes are hypothetically located at the center of
180 : !> each grid cell connected by links that represent the river
181 : !> reaches. The flow direction of a link correspond to the
182 : !> direction towards a neighboring cell in which the net flow
183 : !> accumulation (outflows minus inflows) attains its maximum
184 : !> value. The net flow accumulation across a cell's boundary at
185 : !> level-11 is estimated based on flow direction and flow
186 : !> accumulation obtained at level-0 (\ref fig_routing "Routing
187 : !> Network"). Note: level-1 denotes the modeling level, whereas
188 : !> level-L11 is at least as coarse as level-1. Experience has
189 : !> shown that routing can be done at a coarser resolution as
190 : !> level-1, hence the level-11 was introduced.
191 : !> \image html routing.png "Upscaling routing network from L0 to L1 (or L11)"
192 : !> \anchor fig_routing \image latex routing.pdf "Upscaling routing network from L0 to L1 (or L11)" width=14cm
193 : !> The left panel depicts a schematic derivation of a drainage
194 : !> network at the level-11 based on level-0 flow direction and
195 : !> flow accumulation. The dotted line circle denotes the point
196 : !> with the highest flow accumulation within a grid cell. The
197 : !> topology of a tipical drainage routing network at level-11 is
198 : !> shown in the right panel. Gray color areas denote the flood
199 : !> plains estimated in mo_init_mrm, where the network
200 : !> upscaling is also carried out.
201 : !> For the sake of simplicity, it is assumed that all runoff leaving
202 : !> a given cell would exit through a major direction.
203 : !> Note that multiple outlets can exist within the modelling domain.
204 : !> If a variable is added or removed here, then it also has to
205 : !> be added or removed in the subroutine L11_config_set in
206 : !> module mo_restart and in the subroutine set_L11_config in module
207 : !> mo_set_netcdf_restart
208 : !> ADDITIONAL INFORMATION
209 : !> L11_flow_direction
210 :
211 : ! INTENT(IN)
212 : !> \param[in] "integer(i4) :: iDomain" Domain Id
213 :
214 : ! HISTORY
215 : !> \authors Luis Samaniego
216 :
217 : !> \date Dec 2005
218 :
219 : ! Modifications:
220 : ! Luis Samaniego Jan 2013 - modular version
221 : ! Rohini Kumar Apr 2014 - Case of L0 is same as L11 implemented
222 : ! Stephan Thober Aug 2015 - ported to mRM
223 : ! Stephan Thober Sep 2015 - create mapping between L11 and L1 if L11 resolution is higher than L1 resolution
224 : ! Stephan Thober May 2016 - introducing multiple outlets
225 : ! Robert Schweppe Jun 2018 - refactoring and reformatting
226 :
227 24 : subroutine L11_flow_direction(iDomain)
228 :
229 24 : use mo_append, only : append
230 : use mo_common_constants, only : nodata_i4
231 : use mo_common_types, only: Grid
232 : use mo_common_variables, only : domainMeta, level0
233 : use mo_mrm_global_variables, only : L0_draSC, L0_fAcc, L0_fDir, L0_l11_remap, L11_colOut, L11_fDir, &
234 : L11_nOutlets, L11_rowOut, domain_mrm, level11
235 : use mo_string_utils, only : num2str
236 :
237 : implicit none
238 :
239 : ! Domain Id
240 : integer(i4), intent(in) :: iDomain
241 :
242 : integer(i4) :: nCells0
243 :
244 : integer(i4) :: nrows0, ncols0
245 :
246 : integer(i4) :: s0, e0
247 :
248 : integer(i4) :: nrows11, ncols11
249 :
250 : ! = ncells11
251 : integer(i4) :: nNodes
252 :
253 : integer(i4) :: ii, jj, kk, ic, jc
254 :
255 : integer(i4) :: iu, id
256 :
257 : integer(i4) :: jl, jr
258 :
259 : integer(i4) :: iRow, jCol
260 :
261 24 : integer(i4), dimension(:, :), allocatable :: iD0
262 :
263 24 : integer(i4), dimension(:, :), allocatable :: fDir0
264 :
265 24 : integer(i4), dimension(:, :), allocatable :: fAcc0
266 :
267 24 : integer(i4), dimension(:, :), allocatable :: fDir11
268 :
269 : ! northing cell loc. of the Outlet
270 24 : integer(i4), dimension(:), allocatable :: rowOut
271 :
272 : ! easting cell loc. of the Outlet
273 24 : integer(i4), dimension(:), allocatable :: colOut
274 :
275 24 : integer(i4), dimension(:, :), allocatable :: draSC0
276 :
277 : ! output location in L0
278 24 : integer(i4), dimension(:, :), allocatable :: oLoc
279 :
280 : integer(i4) :: side
281 :
282 : integer(i4) :: fAccMax, idMax
283 :
284 : ! Number of outlet found
285 : integer(i4) :: Noutlet
286 :
287 : ! Number of outlets before this Domain
288 : integer(i4) :: old_Noutlet
289 :
290 : ! flag whether outlet is found
291 : logical :: is_outlet
292 :
293 : type(Grid), pointer :: level0_iDomain => null()
294 :
295 :
296 : !--------------------------------------------------------
297 : ! STEPS:
298 : ! 1) Estimate each variable locally for a given Domain
299 : ! 2) Pad each variable to its corresponding global one
300 : !--------------------------------------------------------
301 : ! initialize
302 24 : Noutlet = 0_i4
303 24 : level0_iDomain => level0(domainMeta%L0DataFrom(iDomain))
304 : !------------------------------------------------------------------
305 : ! Set Flow Direction at Level 11
306 : ! Searching order
307 : ! jl jr
308 : ! iu + 4 +
309 : ! 3 1
310 : ! id + 2 +
311 : !------------------------------------------------------------------
312 :
313 : ! flow direction at level-11
314 :
315 : ! allocate
316 24 : nrows0 = level0_iDomain%nrows
317 24 : ncols0 = level0_iDomain%ncols
318 24 : nCells0 = level0_iDomain%ncells
319 24 : nrows11 = level11(iDomain)%nrows
320 24 : ncols11 = level11(iDomain)%ncols
321 24 : nNodes = level11(iDomain)%ncells
322 24 : s0 = level0_iDomain%iStart
323 24 : e0 = level0_iDomain%iEnd
324 :
325 96 : allocate (iD0 (nrows0, ncols0))
326 72 : allocate (fAcc0 (nrows0, ncols0))
327 72 : allocate (fDir0 (nrows0, ncols0))
328 72 : allocate (draSC0 (nrows0, ncols0))
329 96 : allocate (fDir11 (nrows11, ncols11))
330 72 : allocate (rowOut (nNodes))
331 48 : allocate (colOut (nNodes))
332 24 : allocate (oLoc (1, 2))
333 :
334 : ! initialize
335 2862360 : iD0(:, :) = nodata_i4
336 2862360 : fAcc0(:, :) = nodata_i4
337 2862360 : fDir0(:, :) = nodata_i4
338 2862360 : draSC0(:, :) = nodata_i4
339 1812 : fDir11(:, :) = nodata_i4
340 960 : rowOut(:) = nodata_i4
341 960 : colOut(:) = nodata_i4
342 120 : oLoc(:, :) = nodata_i4
343 :
344 :
345 : ! get iD, fAcc, fDir at L0
346 24 : iD0(:, :) = UNPACK(level0_iDomain%Id, level0_iDomain%mask, nodata_i4)
347 24 : fAcc0(:, :) = UNPACK(L0_fAcc (s0 : e0), level0_iDomain%mask, nodata_i4)
348 24 : fDir0(:, :) = UNPACK(L0_fDir (s0 : e0), level0_iDomain%mask, nodata_i4)
349 :
350 : ! case where routing and input data scale is similar
351 24 : IF(nCells0 .EQ. nNodes) THEN
352 0 : oLoc(1, :) = maxloc(fAcc0, level0_iDomain%mask)
353 0 : kk = L0_L11_remap(iDomain)%lowres_id_on_highres(oLoc(1, 1), oLoc(1, 2))
354 : ! for a single node model run
355 0 : if(nCells0 .EQ. 1) then
356 0 : fDir11(1, 1) = fDir0(oLoc(1, 1), oLoc(1, 2))
357 : else
358 0 : fDir11(:, :) = fDir0(:, :)
359 : end if
360 0 : fDir11 (level11(iDomain)%CellCoor(kk, 1), level11(iDomain)%CellCoor(kk, 2)) = 0
361 : ! set location of main outlet in L11
362 0 : do kk = 1, nNodes
363 0 : ii = level11(iDomain)%CellCoor(kk, 1)
364 0 : jj = level11(iDomain)%CellCoor(kk, 2)
365 0 : rowOut(kk) = ii
366 0 : colOut(kk) = jj
367 : end do
368 0 : do kk = 1, ncells0
369 0 : ii = level0_iDomain%CellCoor(kk, 1)
370 0 : jj = level0_iDomain%CellCoor(kk, 2)
371 0 : draSC0(ii, jj) = kk
372 : end do
373 :
374 : ! case where routing and input data scale differs
375 : ELSE
376 : ! =======================================================================
377 : ! ST: find all cells whose downstream cells are outside the domain
378 : ! =======================================================================
379 1066064 : do ii = 1, nCells0
380 1066040 : iRow = level0_iDomain%CellCoor(ii, 1)
381 1066040 : jCol = level0_iDomain%CellCoor(ii, 2)
382 1066040 : call moveDownOneCell(fDir0(iRow, jCol), iRow, jCol)
383 : ! check whether new location is inside bound
384 1066040 : is_outlet = .False.
385 : if ((iRow .le. 0_i4) .or. (iRow .gt. nrows0) .or. &
386 1066040 : (jCol .le. 0_i4) .or. (jCol .gt. ncols0)) then
387 : is_outlet = .True.
388 : else
389 1066040 : if (fdir0(iRow, jCol) .le. 0) is_outlet = .True.
390 : end if
391 : !
392 1066064 : if (is_outlet) then
393 24 : Noutlet = Noutlet + 1_i4
394 : ! cell is an outlet
395 24 : if (Noutlet .eq. 1) then
396 72 : oLoc(1, :) = level0_iDomain%CellCoor(ii, :)
397 : else
398 0 : call append(oLoc, level0_iDomain%CellCoor(ii : ii, :))
399 : end if
400 : ! drain this cell into corresponding L11 cell
401 24 : kk = L0_L11_remap(iDomain)%lowres_id_on_highres(oLoc(Noutlet, 1), oLoc(Noutlet, 2))
402 24 : draSC0(oLoc(Noutlet, 1), oLoc(Noutlet, 2)) = kk
403 : ! check whether cell has maximum flow accumulation
404 : ! coord. of all corners
405 24 : iu = l0_l11_remap(iDomain)%upper_bound (kk)
406 24 : id = l0_l11_remap(iDomain)%lower_bound (kk)
407 24 : jl = l0_l11_remap(iDomain)%left_bound (kk)
408 24 : jr = l0_l11_remap(iDomain)%right_bound(kk)
409 52992 : if (maxval(facc0(iu : id, jl : jr)) .eq. facc0(oLoc(Noutlet, 1), oLoc(Noutlet, 2))) then
410 : ! set location of outlet at L11
411 24 : rowOut(kk) = oLoc(Noutlet, 1)
412 24 : colOut(kk) = oLoc(Noutlet, 2)
413 24 : fdir11(level11(iDomain)%CellCoor(kk, 1), level11(iDomain)%CellCoor(kk, 2)) = 0
414 : end if
415 : end if
416 : end do
417 :
418 : ! finding cell L11 outlets - using L0_fAcc
419 :
420 960 : do kk = 1, nNodes
421 :
422 : ! exclude outlet L11
423 936 : if (rowOut(kk) > 0) cycle
424 :
425 912 : ic = level11(iDomain)%CellCoor(kk, 1)
426 912 : jc = level11(iDomain)%CellCoor(kk, 2)
427 :
428 : ! coord. of all corners
429 912 : iu = l0_l11_remap(iDomain)%upper_bound (kk)
430 912 : id = l0_l11_remap(iDomain)%lower_bound (kk)
431 912 : jl = l0_l11_remap(iDomain)%left_bound (kk)
432 912 : jr = l0_l11_remap(iDomain)%right_bound(kk)
433 :
434 912 : fAccMax = -9
435 912 : idMax = 0
436 912 : side = -1
437 : ! searching on side 4
438 39504 : do jj = jl, jr
439 38592 : if ((fAcc0(iu, jj) > fAccMax) .and. &
440 : (fDir0(iu, jj) == 32 .or. &
441 : fDir0(iu, jj) == 64 .or. &
442 912 : fDir0(iu, jj) == 128)) then
443 1858 : fAccMax = fAcc0(iu, jj)
444 1858 : idMax = id0(iu, jj)
445 1858 : side = 4
446 : end if
447 : end do
448 :
449 : ! searching on side 1
450 39504 : do ii = iu, id
451 38592 : if ((fAcc0(ii, jr) > fAccMax) .and. &
452 : (fDir0(ii, jr) == 1 .or. &
453 : fDir0(ii, jr) == 2 .or. &
454 912 : fDir0(ii, jr) == 128)) then
455 418 : fAccMax = fAcc0(ii, jr)
456 418 : idMax = id0(ii, jr)
457 418 : side = 1
458 : end if
459 : end do
460 :
461 : ! searching on side 2
462 39504 : do jj = jl, jr
463 38592 : if ((fAcc0(id, jj) > fAccMax) .and. &
464 : (fDir0(id, jj) == 2 .or. &
465 : fDir0(id, jj) == 4 .or. &
466 912 : fDir0(id, jj) == 8)) then
467 546 : fAccMax = fAcc0(id, jj)
468 546 : idMax = id0(id, jj)
469 546 : side = 2
470 : end if
471 : end do
472 :
473 : ! searching on side 3
474 39504 : do ii = iu, id
475 38592 : if ((fAcc0(ii, jl) > fAccMax) .and. &
476 : (fDir0(ii, jl) == 8 .or. &
477 : fDir0(ii, jl) == 16 .or. &
478 912 : fDir0(ii, jl) == 32)) then
479 628 : fAccMax = fAcc0(ii, jl)
480 628 : idMax = id0(ii, jl)
481 628 : side = 3
482 : end if
483 : end do
484 :
485 : ! set location of the cell-outlet (row, col) in L0
486 912 : ii = level0_iDomain%CellCoor(idMax, 1)
487 912 : jj = level0_iDomain%CellCoor(idMax, 2)
488 912 : rowOut(kk) = ii
489 912 : colOut(kk) = jj
490 912 : draSC0(ii, jj) = kk
491 :
492 : ! set fDir at L11
493 936 : if (ii == iu .and. jj == jl) then
494 4 : select case (fDir0(ii, jj))
495 : case (8, 16)
496 0 : fDir11(ic, jc) = 16
497 : case (32)
498 0 : fDir11(ic, jc) = 32
499 : case (64, 128)
500 4 : fDir11(ic, jc) = 64
501 : end select
502 908 : elseif (ii == iu .and. jj == jr) then
503 4 : select case (fDir0(ii, jj))
504 : case (32, 64)
505 2 : fDir11(ic, jc) = 64
506 : case (128)
507 0 : fDir11(ic, jc) = 128
508 : case (1, 2)
509 2 : fDir11(ic, jc) = 1
510 : end select
511 906 : elseif (ii == id .and. jj == jl) then
512 62 : select case (fDir0(ii, jj))
513 : case (2, 4)
514 6 : fDir11(ic, jc) = 4
515 : case (8)
516 2 : fDir11(ic, jc) = 8
517 : case (16, 32)
518 56 : fDir11(ic, jc) = 16
519 : end select
520 850 : elseif (ii == id .and. jj == jr) then
521 2 : select case (fDir0(ii, jj))
522 : case (128, 1)
523 0 : fDir11(ic, jc) = 1
524 : case (2)
525 0 : fDir11(ic, jc) = 2
526 : case (4, 8)
527 2 : fDir11(ic, jc) = 4
528 : end select
529 : else
530 : ! cell on one side
531 50 : select case (side)
532 : case (1)
533 50 : fDir11(ic, jc) = 1
534 : case (2)
535 130 : fDir11(ic, jc) = 4
536 : case (3)
537 354 : fDir11(ic, jc) = 16
538 : case (4)
539 314 : fDir11(ic, jc) = 64
540 : case default
541 872 : call error_message('Error L11_flow_direction: side = -1')
542 : end select
543 : end if
544 :
545 : end do
546 :
547 : END IF
548 : !--------------------------------------------------------
549 : ! Start padding up local variables to global variables
550 : !--------------------------------------------------------
551 :
552 : ! allocate space for row and col Outlet
553 24 : allocate(domain_mrm(iDomain)%L0_rowOutlet(1))
554 24 : allocate(domain_mrm(iDomain)%L0_colOutlet(1))
555 24 : domain_mrm(iDomain)%L0_Noutlet = nodata_i4
556 72 : domain_mrm(iDomain)%L0_rowOutlet = nodata_i4
557 72 : domain_mrm(iDomain)%L0_colOutlet = nodata_i4
558 :
559 : ! L0 data sets
560 : ! check whether L0 data is shared
561 : !ToDo: check if change is correct
562 24 : if (iDomain .eq. 1) then
563 12 : call append(L0_draSC, PACK (draSC0(:, :), level0_iDomain%mask))
564 12 : else if (domainMeta%L0DataFrom(iDomain) == iDomain) then
565 9 : call append(L0_draSC, PACK (draSC0(:, :), level0_iDomain%mask))
566 : end if
567 :
568 24 : domain_mrm(iDomain)%L0_Noutlet = Noutlet
569 : ! set L0 outlet coordinates
570 24 : old_Noutlet = size(domain_mrm(iDomain)%L0_rowOutlet, dim = 1)
571 24 : if (Noutlet .le. old_Noutlet) then
572 48 : domain_mrm(iDomain)%L0_rowOutlet(: Noutlet) = oLoc(:, 1)
573 48 : domain_mrm(iDomain)%L0_colOutlet(: Noutlet) = oLoc(:, 2)
574 : else
575 : ! store up to size of old_Noutlet
576 0 : domain_mrm(iDomain)%L0_rowOutlet(: old_Noutlet) = oLoc(: old_Noutlet, 1)
577 0 : domain_mrm(iDomain)%L0_colOutlet(: old_Noutlet) = oLoc(: old_Noutlet, 2)
578 : ! enlarge rowOutlet and colOutlet in domain_mrm structure
579 : !TODO: do other domains also need to be enlarged accordingly???
580 0 : call append(domain_mrm(iDomain)%L0_rowOutlet, oLoc(old_Noutlet + 1 :, 1))
581 0 : call append(domain_mrm(iDomain)%L0_colOutlet, oLoc(old_Noutlet + 1 :, 2))
582 : end if
583 :
584 : ! L11 data sets
585 1812 : call append(L11_nOutlets, count(fdir11 .eq. 0_i4))
586 24 : call append(L11_fDir, PACK (fDir11(:, :), level11(iDomain)%mask))
587 24 : call append(L11_rowOut, rowOut(:))
588 24 : call append(L11_colOut, colOut(:))
589 :
590 : ! communicate
591 24 : call message('')
592 24 : call message(' Domain: ' // num2str(iDomain, '(i3)'))
593 24 : call message(' Number of outlets found at Level 0:.. ' // num2str(Noutlet, '(i7)'))
594 1812 : call message(' Number of outlets found at Level 11:. ' // num2str(count(fdir11 .eq. 0_i4), '(i7)'))
595 :
596 : ! free space
597 24 : deallocate(fDir0, fAcc0, fDir11, rowOut, colOut, draSC0)
598 :
599 24 : end subroutine L11_flow_direction
600 :
601 : ! ------------------------------------------------------------------
602 :
603 : ! NAME
604 : ! L11_set_network_topology
605 :
606 : ! PURPOSE
607 : !> \brief Set network topology
608 :
609 : !> \details Set network topology from and to node for all links
610 : !> at level-11 (\ref fig_routing "Routing Network").
611 : !> If a variable is added or removed here, then it also has to
612 : !> be added or removed in the subroutine L11_config_set in
613 : !> module mo_restart and in the subroutine set_L11_config in module
614 : !> mo_set_netcdf_restart.
615 :
616 : ! INTENT(IN)
617 : !> \param[in] "integer(i4) :: iDomain" Domain Id
618 :
619 : ! HISTORY
620 : !> \authors Luis Samaniego
621 :
622 : !> \date Dec 2005
623 :
624 : ! Modifications:
625 : ! Luis Samaniego Jan 2013 - modular version
626 : ! Stephan Thober Aug 2015 - ported to mRM
627 : ! Stephan Thober May 2016 - moved calculation of sink here
628 : ! Robert Schweppe Jun 2018 - refactoring and reformatting
629 :
630 24 : subroutine L11_set_network_topology(iDomain)
631 :
632 24 : use mo_append, only : append
633 : use mo_common_constants, only : nodata_i4
634 : use mo_mrm_global_variables, only : L11_fDir, L11_fromN, L11_toN, level11
635 :
636 : implicit none
637 :
638 : ! Domain Id
639 : integer(i4), intent(in) :: iDomain
640 :
641 24 : integer(i4), dimension(:, :), allocatable :: fDir11
642 :
643 24 : integer(i4), dimension(:, :), allocatable :: dummy_2d_id
644 :
645 : integer(i4) :: jj, kk, ic, jc
646 :
647 : integer(i4) :: fn, tn
648 :
649 24 : integer(i4), dimension(:), allocatable :: nLinkFromN, nLinkToN
650 :
651 :
652 : ! Routing network vectors have nNodes size instead of nLinks to
653 : ! avoid the need of having two extra indices to identify a Domain.
654 : ! allocate
655 72 : allocate (nLinkFromN (level11(iDomain)%nCells)) ! valid from (1 : nLinks)
656 48 : allocate (nLinkToN (level11(iDomain)%nCells)) ! "
657 96 : allocate (fDir11 (level11(iDomain)%nrows, level11(iDomain)%ncols))
658 72 : allocate (dummy_2d_id(level11(iDomain)%nrows, level11(iDomain)%ncols))
659 24 : dummy_2d_id = unpack(level11(iDomain)%Id, level11(iDomain)%mask, nodata_i4)
660 :
661 :
662 : ! initialize
663 960 : nLinkFromN(:) = nodata_i4
664 960 : nLinkToN(:) = nodata_i4
665 1812 : fDir11(:, :) = nodata_i4
666 :
667 : ! get grids of L11
668 24 : fDir11(:, :) = UNPACK(L11_fDir (level11(iDomain)%iStart : level11(iDomain)%iEnd), level11(iDomain)%mask, nodata_i4)
669 :
670 : ! ------------------------------------------------------------------
671 : ! network topology
672 : ! ------------------------------------------------------------------
673 :
674 24 : jj = 0
675 960 : do kk = 1, level11(iDomain)%nCells
676 936 : ic = level11(iDomain)%CellCoor(kk, 1)
677 936 : jc = level11(iDomain)%CellCoor(kk, 2)
678 936 : fn = kk
679 936 : call moveDownOneCell(fDir11(ic, jc), ic, jc)
680 936 : tn = dummy_2d_id(ic, jc)
681 936 : if (fn == tn) cycle
682 912 : jj = jj + 1
683 912 : nLinkFromN(jj) = fn
684 1872 : nLinkToN(jj) = tn
685 : end do
686 :
687 : !--------------------------------------------------------
688 : ! Start padding up local variables to global variables
689 : !--------------------------------------------------------
690 :
691 : ! L11 data sets
692 24 : call append(L11_fromN, nLinkFromN(:)) ! sinks are at the end
693 24 : call append(L11_toN, nLinkToN(:))
694 :
695 : ! free space
696 24 : deallocate (fDir11, nLinkFromN, nLinkToN)
697 :
698 24 : end subroutine L11_set_network_topology
699 :
700 : ! ------------------------------------------------------------------
701 :
702 : ! NAME
703 : ! L11_routing_order
704 :
705 : ! PURPOSE
706 : !> \brief Find routing order, headwater cells and sink
707 :
708 : !> \details Find routing order, headwater cells and sink.
709 : !> If a variable is added or removed here, then it also has to
710 : !> be added or removed in the subroutine L11_config_set in
711 : !> module mo_restart and in the subroutine set_L11_config in module
712 : !> mo_set_netcdf_restart
713 :
714 : ! INTENT(IN)
715 : !> \param[in] "integer(i4) :: iDomain" Domain Id
716 :
717 : ! HISTORY
718 : !> \authors Luis Samaniego
719 :
720 : !> \date Dec 2005
721 :
722 : ! Modifications:
723 : ! Luis Samaniego Jan 2013 - modular version
724 : ! Sa. Ku. Jan 2015 - corrected initialization of nLinkSink
725 : ! Stephan Thober Aug 2015 - ported to mRM
726 : ! Robert Schweppe Jun 2018 - refactoring and reformatting
727 :
728 24 : subroutine L11_routing_order(iDomain)
729 :
730 24 : use mo_append, only : append
731 : use mo_common_constants, only : nodata_i4
732 : use mo_mrm_global_variables, only : L11_fDir, L11_fromN, L11_label, L11_nOutlets, L11_netPerm, L11_rOrder, L11_sink, L11_toN, &
733 : level11, sink_cells
734 :
735 : implicit none
736 :
737 : ! Domain Id
738 : integer(i4), intent(in) :: iDomain
739 :
740 : integer(i4) :: nLinks
741 :
742 : ! from node
743 24 : integer(i4), dimension(:), allocatable :: nLinkFromN
744 :
745 : ! to node
746 24 : integer(i4), dimension(:), allocatable :: nLinkToN
747 :
748 : ! network routing order
749 24 : integer(i4), dimension(:), allocatable :: nLinkROrder
750 :
751 : ! label Id [0='', 1=HeadWater, 2=Sink]
752 24 : integer(i4), dimension(:), allocatable :: nLinkLabel
753 :
754 : ! == .true. if sink node reached
755 24 : logical, dimension(:), allocatable :: nLinkSink
756 :
757 : ! routing order (permutation)
758 24 : integer(i4), dimension(:), allocatable :: netPerm
759 :
760 : integer(i4) :: ii, jj, kk
761 :
762 : logical :: flag
763 :
764 :
765 24 : nLinks = level11(iDomain)%nCells - L11_nOutlets(iDomain)
766 : ! Routing network vectors have nNodes size instead of nLinks to
767 : ! avoid the need of having two extra indices to identify a Domain.
768 :
769 : ! allocate
770 72 : allocate (nLinkFromN (level11(iDomain)%nCells)) ! all vectors valid from (1 : nLinks)
771 48 : allocate (nLinkToN (level11(iDomain)%nCells))
772 48 : allocate (nLinkROrder (level11(iDomain)%nCells))
773 48 : allocate (nLinkLabel (level11(iDomain)%nCells))
774 48 : allocate (nLinkSink (level11(iDomain)%nCells))
775 48 : allocate (netPerm (level11(iDomain)%nCells))
776 : ! initialize
777 960 : nLinkFromN(:) = nodata_i4
778 960 : nLinkToN(:) = nodata_i4
779 960 : nLinkROrder(1 : nLinks) = 1
780 24 : nLinkROrder(level11(iDomain)%nCells) = nodata_i4
781 936 : nLinkLabel(1 : nLinks) = 0
782 24 : nLinkLabel(level11(iDomain)%nCells) = nodata_i4
783 960 : nLinkSink(:) = .FALSE.
784 960 : netPerm(:) = nodata_i4
785 :
786 : ! for a single node model run
787 24 : if(level11(iDomain)%nCells .GT. 1) then
788 : ! get network vectors of L11
789 960 : nLinkFromN(:) = L11_fromN (level11(iDomain)%iStart : level11(iDomain)%iEnd)
790 960 : nLinkToN(:) = L11_toN (level11(iDomain)%iStart : level11(iDomain)%iEnd)
791 :
792 936 : loop1 : do ii = 1, nLinks
793 31812 : loop2 : do jj = 1, nLinks
794 31474 : if (jj == ii) cycle loop2
795 30714 : if (nLinkFromN(ii) == nLinkToN(jj)) then
796 598 : nLinkROrder(ii) = -9
797 : end if
798 31028 : if (nLinkROrder(ii) == -9) cycle loop1
799 : end do loop2
800 : end do loop1
801 : ! counting headwaters
802 : kk = 0
803 936 : do ii = 1, nLinks
804 936 : if (nLinkROrder(ii) == 1) then
805 314 : kk = kk + 1
806 314 : nLinkROrder(ii) = kk
807 314 : nLinkLabel(ii) = 1 ! 'Head Water'
808 : end if
809 : end do
810 : ! counting downstream
811 11748 : do while (minval(nLinkROrder(1 : nLinks)) < 0)
812 : !! print *, count(nLinkROrder .lt. 0), minval(nLinkROrder)
813 10836 : loop3 : do ii = 1, nLinks
814 10584 : if (.NOT. nLinkROrder(ii) == -9) cycle loop3
815 76524 : flag = .TRUE.
816 76524 : loop4 : do jj = 1, nLinks
817 76524 : if (jj == ii .OR. nLinkFromN(ii) /= nLinkToN(jj)) then
818 : cycle loop4
819 3716 : else if (.NOT. (nLinkFromN(ii) == nLinkToN(jj) .AND. nLinkROrder(jj) > 0)) then
820 : flag = .FALSE.
821 : exit loop4
822 : else
823 : end if
824 : end do loop4
825 :
826 2508 : if (flag) then
827 598 : kk = kk + 1
828 598 : nLinkROrder(ii) = kk
829 : end if
830 : end do loop3
831 : end do
832 :
833 : ! identify sink cells
834 936 : do ii = 1, nLinks
835 936 : if (L11_fdir(level11(iDomain)%iStart + nLinkToN(ii) - 1_i4) .eq. 0_i4) then
836 26 : nlinksink(ii) = .True.
837 : ! add sink target cell to sink_cells if not already present (in case of multiple inflows (rare case))
838 98 : if (.not.any(sink_cells(iDomain)%ids == nLinkToN(ii))) sink_cells(iDomain)%ids = [sink_cells(iDomain)%ids, nLinkToN(ii)]
839 : end if
840 : end do
841 960 : where(nlinksink) nLinkLabel = 2 ! 'Sink'
842 :
843 : ! keep routing order
844 936 : do ii = 1, nLinks
845 936 : netPerm(nLinkROrder(ii)) = ii
846 : end do
847 :
848 : ! end of multi-node network design loop
849 : end if
850 :
851 : !--------------------------------------------------------
852 : ! Start padding up local variables to global variables
853 : !--------------------------------------------------------
854 : ! L11 network data sets
855 24 : call append(L11_rOrder, nLinkROrder(:))
856 24 : call append(L11_label, nLinkLabel(:))
857 24 : call append(L11_sink, nLinkSink(:))
858 24 : call append(L11_netPerm, netPerm(:))
859 :
860 : ! free space
861 24 : deallocate (nLinkFromN, nLinkToN, nLinkROrder, nLinkLabel, nLinkSink, netPerm)
862 :
863 24 : end subroutine L11_routing_order
864 :
865 : ! ------------------------------------------------------------------
866 :
867 : ! NAME
868 : ! L11_link_location
869 :
870 : ! PURPOSE
871 : !> \brief Estimate the LO (row,col) location for each routing link at level L11
872 :
873 : !> \details If a variable is added or removed here, then it also has to
874 : !> be added or removed in the subroutine L11_config_set in
875 : !> module mo_restart and in the subroutine set_L11_config in module
876 : !> mo_set_netcdf_restart
877 :
878 : ! INTENT(IN)
879 : !> \param[in] "integer(i4) :: iDomain" Domain Id
880 :
881 : ! HISTORY
882 : !> \authors Luis Samaniego
883 :
884 : !> \date Dec 2005
885 :
886 : ! Modifications:
887 : ! Luis Samaniego Jan 2013 - modular version
888 : ! Stephan Thober Aug 2015 - ported to mRM
889 : ! Robert Schweppe Jun 2018 - refactoring and reformatting
890 :
891 24 : subroutine L11_link_location(iDomain)
892 :
893 24 : use mo_append, only : append
894 : use mo_common_constants, only : nodata_i4
895 : use mo_common_types, only: Grid
896 : use mo_common_variables, only : domainMeta, level0
897 : use mo_mrm_global_variables, only : L0_draSC, L0_fDir, L11_colOut, L11_fCol, L11_fRow, L11_fromN, &
898 : L11_nOutlets, L11_netPerm, L11_rowOut, L11_tCol, L11_tRow, domain_mrm, level11
899 : use mo_string_utils, only : num2str
900 :
901 : implicit none
902 :
903 : ! Domain Id
904 : integer(i4), intent(in) :: iDomain
905 :
906 : integer(i4) :: nLinks
907 :
908 : ! northing cell loc. of the Outlet
909 24 : integer(i4), dimension(:), allocatable :: rowOut
910 :
911 : ! easting cell loc. of the Outlet
912 24 : integer(i4), dimension(:), allocatable :: colOut
913 :
914 24 : integer(i4), dimension(:), allocatable :: nLinkFromN
915 :
916 24 : integer(i4), dimension(:), allocatable :: netPerm
917 :
918 24 : integer(i4), dimension(:), allocatable :: nLinkFromRow
919 :
920 24 : integer(i4), dimension(:), allocatable :: nLinkFromCol
921 :
922 24 : integer(i4), dimension(:), allocatable :: nLinkToRow
923 :
924 24 : integer(i4), dimension(:), allocatable :: nLinkToCol
925 :
926 24 : integer(i4), dimension(:, :), allocatable :: fDir0
927 :
928 24 : integer(i4), dimension(:, :), allocatable :: draSC0
929 :
930 : integer(i4) :: ii, rr, kk, s0, e0
931 :
932 : integer(i4) :: iNode, iRow, jCol, prevRow, prevCol
933 :
934 : ! output location in L0
935 24 : integer(i4), dimension(:, :), allocatable :: oLoc
936 :
937 : ! number of outlets in Domain
938 : integer(i4) :: nOutlets
939 :
940 : ! flag for finding outlet
941 : logical :: is_outlet
942 :
943 : type(Grid), pointer :: level0_iDomain => null()
944 :
945 :
946 24 : level0_iDomain => level0(domainMeta%L0DataFrom(iDomain))
947 24 : s0 = level0_iDomain%iStart
948 24 : e0 = level0_iDomain%iEnd
949 :
950 24 : nOutlets = L11_nOutlets(iDomain)
951 :
952 24 : nLinks = level11(iDomain)%nCells - nOutlets
953 :
954 : ! Routing network vectors have level11(iDomain)%nCells size instead of nLinks to
955 : ! avoid the need of having two extra indices to identify a Domain.
956 : ! allocate
957 72 : allocate (rowOut (level11(iDomain)%nCells))
958 48 : allocate (colOut (level11(iDomain)%nCells))
959 48 : allocate (nLinkFromN (level11(iDomain)%nCells)) ! all network vectors valid from (1 : nLinks)
960 48 : allocate (netPerm (level11(iDomain)%nCells))
961 48 : allocate (nLinkFromRow (level11(iDomain)%nCells))
962 48 : allocate (nLinkFromCol (level11(iDomain)%nCells))
963 48 : allocate (nLinkToRow (level11(iDomain)%nCells))
964 48 : allocate (nLinkToCol (level11(iDomain)%nCells))
965 96 : allocate (fDir0 (level0_iDomain%nrows, level0_iDomain%ncols))
966 72 : allocate (draSC0 (level0_iDomain%nrows, level0_iDomain%ncols))
967 :
968 : ! initialize
969 984 : rowOut = nodata_i4
970 984 : colOut = nodata_i4
971 984 : nLinkFromN = nodata_i4
972 984 : netPerm = nodata_i4
973 984 : nLinkFromRow = nodata_i4
974 984 : nLinkFromCol = nodata_i4
975 984 : nLinkToRow = nodata_i4
976 984 : nLinkToCol = nodata_i4
977 2862384 : fDir0 = nodata_i4
978 2862384 : draSC0 = nodata_i4
979 :
980 : ! for a single node model run
981 24 : if(level11(iDomain)%nCells .GT. 1) then
982 : ! get fDir at L0
983 24 : fDir0(:, :) = UNPACK(L0_fDir (s0 : e0), level0_iDomain%mask, nodata_i4)
984 24 : draSC0(:, :) = UNPACK(L0_draSC (s0 : e0), level0_iDomain%mask, nodata_i4)
985 :
986 : ! get network vectors of L11
987 960 : nLinkFromN(:) = L11_fromN (level11(iDomain)%iStart : level11(iDomain)%iEnd)
988 960 : netPerm(:) = L11_netPerm (level11(iDomain)%iStart : level11(iDomain)%iEnd)
989 960 : rowOut(:) = L11_rowOut (level11(iDomain)%iStart : level11(iDomain)%iEnd)
990 960 : colOut(:) = L11_colOut (level11(iDomain)%iStart : level11(iDomain)%iEnd)
991 :
992 : ! finding main outlet (row, col) in L0
993 72 : allocate(oLoc(Noutlets, 2))
994 48 : oLoc(:, 1) = domain_mrm(iDomain)%L0_rowOutlet(: Noutlets)
995 48 : oLoc(:, 2) = domain_mrm(iDomain)%L0_colOutlet(: Noutlets)
996 :
997 : ! Location of the stream-joint cells (row, col)
998 936 : do rr = 1, nLinks
999 :
1000 912 : ii = netPerm(rr)
1001 912 : iNode = nLinkFromN(ii)
1002 912 : iRow = rowOut(iNode)
1003 912 : jCol = colOut(iNode)
1004 912 : call moveDownOneCell(fDir0(iRow, jcol), iRow, jcol)
1005 : ! set "from" cell
1006 912 : nLinkFromRow(ii) = iRow
1007 912 : nLinkFromCol(ii) = jCol
1008 :
1009 : ! check whether this location is an outlet
1010 912 : is_outlet = .False.
1011 1824 : do kk = 1, Noutlets
1012 1824 : if (iRow .eq. oLoc(kk, 1) .and. jCol .eq. oLoc(kk, 2)) is_outlet = .True.
1013 : end do
1014 :
1015 1848 : if (is_outlet) then
1016 :
1017 0 : nLinkToRow(ii) = iRow
1018 0 : nLinkToCol(ii) = jCol
1019 :
1020 : else
1021 :
1022 35952 : do while (.not. (draSC0(iRow, jCol) > 0))
1023 35040 : prevRow = iRow
1024 35040 : prevCol = jCol
1025 : call moveDownOneCell(fDir0(iRow, jcol), iRow, jCol)
1026 : ! check whether this location is an outlet and exit
1027 70056 : do kk = 1, Noutlets
1028 70056 : if (iRow .eq. oLoc(kk, 1) .and. jCol .eq. oLoc(kk, 2)) exit
1029 : end do
1030 35952 : if (prevRow .eq. iRow .and. prevCol .eq. jCol) then
1031 : call error_message('Something went wrong during L11_link_location, ', &
1032 : 'movedownonecell got stuck in infinite loop at cell (', num2str(iRow), ' ', &
1033 0 : num2str(jCol))
1034 : end if
1035 : end do
1036 : ! set "to" cell (when an outlet is reached)
1037 912 : nLinkToRow(ii) = iRow
1038 912 : nLinkToCol(ii) = jCol
1039 :
1040 : end if
1041 : end do
1042 :
1043 : ! end of multi-node network design loop
1044 : end if
1045 :
1046 : !--------------------------------------------------------
1047 : ! Start padding up local variables to global variables
1048 : !--------------------------------------------------------
1049 : ! L11 network data sets
1050 24 : call append(L11_fRow, nLinkFromRow(:))
1051 24 : call append(L11_fCol, nLinkFromCol(:))
1052 24 : call append(L11_tRow, nLinkToRow(:))
1053 24 : call append(L11_tCol, nLinkToCol(:))
1054 :
1055 : ! free space
1056 : deallocate (rowOut, colOut, nLinkFromN, netPerm, nLinkFromRow, &
1057 24 : nLinkFromCol, nLinkToRow, nLinkToCol, fDir0, draSC0)
1058 :
1059 24 : end subroutine L11_link_location
1060 :
1061 : ! ------------------------------------------------------------------
1062 :
1063 : ! NAME
1064 : ! L11_set_drain_outlet_gauges
1065 :
1066 : ! PURPOSE
1067 : !> \brief Draining cell identification and Set gauging node
1068 :
1069 : !> \details Perform the following tasks:
1070 : !> - Draining cell identification (cell at L0 to draining cell outlet at L11).
1071 : !> - Set gauging nodes
1072 : !> If a variable is added or removed here, then it also has to
1073 : !> be added or removed in the subroutine L11_config_set in
1074 : !> module mo_restart and in the subroutine set_L11_config in module
1075 : !> mo_set_netcdf_restart
1076 :
1077 : ! INTENT(IN)
1078 : !> \param[in] "integer(i4) :: iDomain" Domain Id
1079 :
1080 : ! HISTORY
1081 : !> \authors Luis Samaniego
1082 :
1083 : !> \date Dec 2005
1084 :
1085 : ! Modifications:
1086 : ! Luis Samaniego Jan 2013 - modular version
1087 : ! Matthias Zink Mar 2014 - bugfix, added inflow gauge
1088 : ! Rohini Kumar Apr 2014 - variable index is changed to index_gauge
1089 : ! Stephan Thober Aug 2015 - ported to mRM
1090 : ! Robert Schweppe Jun 2018 - refactoring and reformatting
1091 :
1092 24 : subroutine L11_set_drain_outlet_gauges(iDomain)
1093 :
1094 24 : use mo_append, only : append
1095 : use mo_common_constants, only : nodata_i4
1096 : use mo_common_types, only: Grid
1097 : use mo_common_variables, only : domainMeta, level0
1098 : use mo_mrm_global_variables, only : L0_InflowgaugeLoc, L0_draCell, L0_draSC, L0_fDir, L0_gaugeLoc, domain_mrm, &
1099 : l0_l11_remap
1100 :
1101 : implicit none
1102 :
1103 : ! Domain Id
1104 : integer(i4), intent(in) :: iDomain
1105 :
1106 24 : integer(i4), dimension(:, :), allocatable :: draSC0
1107 :
1108 24 : integer(i4), dimension(:, :), allocatable :: fDir0
1109 :
1110 24 : integer(i4), dimension(:, :), allocatable :: gaugeLoc0
1111 :
1112 24 : integer(i4), dimension(:, :), allocatable :: InflowGaugeLoc0
1113 :
1114 24 : integer(i4), dimension(:, :), allocatable :: draCell0
1115 :
1116 : integer(i4) :: ii, jj, kk, ll, s0, e0
1117 :
1118 : integer(i4) :: iSc
1119 :
1120 : integer(i4) :: iRow, jCol
1121 :
1122 : type(Grid), pointer :: level0_iDomain => null()
1123 :
1124 :
1125 24 : level0_iDomain => level0(domainMeta%L0DataFrom(iDomain))
1126 24 : s0 = level0_iDomain%iStart
1127 24 : e0 = level0_iDomain%iEnd
1128 :
1129 :
1130 : ! allocate
1131 96 : allocate (draSC0 (level0_iDomain%nrows, level0_iDomain%ncols))
1132 72 : allocate (fDir0 (level0_iDomain%nrows, level0_iDomain%ncols))
1133 72 : allocate (gaugeLoc0 (level0_iDomain%nrows, level0_iDomain%ncols))
1134 72 : allocate (InflowGaugeLoc0 (level0_iDomain%nrows, level0_iDomain%ncols))
1135 72 : allocate (draCell0 (level0_iDomain%nrows, level0_iDomain%ncols))
1136 :
1137 : ! initialize
1138 2862360 : draSC0(:, :) = nodata_i4
1139 2862360 : fDir0(:, :) = nodata_i4
1140 2862360 : gaugeLoc0(:, :) = nodata_i4
1141 2862360 : InflowGaugeLoc0(:, :) = nodata_i4
1142 2862360 : draCell0(:, :) = nodata_i4
1143 :
1144 0 : draSC0(:, :) = UNPACK(L0_draSC (s0 : e0), &
1145 24 : level0_iDomain%mask, nodata_i4)
1146 0 : fDir0(:, :) = UNPACK(L0_fDir (s0 : e0), &
1147 24 : level0_iDomain%mask, nodata_i4)
1148 0 : gaugeLoc0(:, :) = UNPACK(L0_gaugeLoc (s0 : e0), &
1149 24 : level0_iDomain%mask, nodata_i4)
1150 0 : InflowGaugeLoc0(:, :) = UNPACK(L0_InflowgaugeLoc (s0 : e0), &
1151 24 : level0_iDomain%mask, nodata_i4)
1152 :
1153 1066064 : do kk = 1, level0_iDomain%nCells
1154 1066040 : ii = level0_iDomain%CellCoor(kk, 1)
1155 1066040 : jj = level0_iDomain%CellCoor(kk, 2)
1156 1066040 : iSc = draSC0(ii, jj)
1157 : ! find drainage path
1158 1066040 : iRow = ii
1159 1066040 : jCol = jj
1160 43644186 : do while (.NOT. iSC > 0)
1161 : ! move downstream
1162 42578146 : call moveDownOneCell(fDir0(iRow, jCol), iRow, jCol)
1163 42578146 : iSC = draSC0(iRow, jCol)
1164 : end do
1165 1066040 : draCell0(ii, jj) = iSC
1166 :
1167 : ! find cell at L11 corresponding to gauges in Domain at L0 ! >> L11_on_L0 is Id of
1168 : ! the routing cell at level-11
1169 1066040 : if (gaugeLoc0(ii, jj) .NE. nodata_i4) then
1170 : ! evaluation gauges
1171 76 : do ll = 1, domain_mrm(iDomain)%nGauges
1172 : ! search for gaugeID in L0 grid and save ID on L11
1173 76 : if (domain_mrm(iDomain)%gaugeIdList(ll) .EQ. gaugeLoc0(ii, jj)) then
1174 21 : domain_mrm(iDomain)%gaugeNodeList(ll) = L0_L11_remap(iDomain)%lowres_id_on_highres(ii, jj)
1175 : end if
1176 : end do
1177 : end if
1178 :
1179 1066064 : if (InflowGaugeLoc0(ii, jj) .NE. nodata_i4) then
1180 : ! inflow gauges
1181 39 : do ll = 1, domain_mrm(iDomain)%nInflowGauges
1182 : ! search for gaugeID in L0 grid and save ID on L11
1183 4 : if (domain_mrm(iDomain)%InflowGaugeIdList(ll) .EQ. InflowGaugeLoc0(ii, jj)) &
1184 37 : domain_mrm(iDomain)%InflowGaugeNodeList(ll) = L0_L11_remap(iDomain)%lowres_id_on_highres(ii, jj)
1185 : end do
1186 : end if
1187 : end do
1188 :
1189 : !--------------------------------------------------------
1190 : ! Start padding up local variables to global variables
1191 : !--------------------------------------------------------
1192 : ! L0 data sets
1193 : ! check whether L0 data is shared
1194 : ! ToDo: check if change is correct
1195 24 : if (iDomain .eq. 1) then
1196 12 : call append(L0_draCell, PACK(draCell0(:, :), level0_iDomain%mask))
1197 12 : else if (domainMeta%L0DataFrom(iDomain) == iDomain) then
1198 9 : call append(L0_draCell, PACK(draCell0(:, :), level0_iDomain%mask))
1199 : end if
1200 :
1201 : ! free space
1202 24 : deallocate (draSC0, fDir0, gaugeLoc0, draCell0)
1203 :
1204 24 : end subroutine L11_set_drain_outlet_gauges
1205 :
1206 : ! ------------------------------------------------------------------
1207 :
1208 : ! NAME
1209 : ! L11_stream_features
1210 :
1211 : ! PURPOSE
1212 : !> \brief Stream features (stream network and floodplain)
1213 :
1214 : !> \details Stream features (stream network and floodplain)
1215 : !> If a variable is added or removed here, then it also has to
1216 : !> be added or removed in the subroutine L11_config_set in
1217 : !> module mo_restart and in the subroutine set_L11_config in module
1218 : !> mo_set_netcdf_restart
1219 :
1220 : ! INTENT(IN)
1221 : !> \param[in] "integer(i4) :: iDomain" Domain Id
1222 :
1223 : ! HISTORY
1224 : !> \authors Luis Samaniego
1225 :
1226 : !> \date Dec 2005
1227 :
1228 : ! Modifications:
1229 : ! Luis Samaniego Jan 2013 - modular version
1230 : ! R. Kumar Oct 2013 - stack size increased from nNodes to 100
1231 : ! Stephan Thober Aug 2015 - ported to mRM
1232 : ! Stephan Thober Nov 2016 - only read flood plain area if processMatrix for routing equals 1
1233 : ! Robert Schweppe Jun 2018 - refactoring and reformatting
1234 : ! Stephan Thober Jul 2018 - introduced cut off Length at 40 percentile to neglect short paths in headwaters for adaptive timesteps
1235 : ! Stephan Thober, Pallav Kumar Shrestha, Sep 2020 - bug fix in cut off Length at 40 percentile, neglecting links with -9999. that occur if multiple outlets are present
1236 :
1237 24 : subroutine L11_stream_features(iDomain)
1238 :
1239 24 : use mo_append, only : append
1240 : use mo_common_constants, only : nodata_dp, nodata_i4
1241 : use mo_common_types, only: Grid
1242 : use mo_common_variables, only : domainMeta, L0_elev, iFlag_cordinate_sys, level0, processMatrix
1243 : use mo_mrm_global_variables, only : L0_fDir, &
1244 : L0_floodPlain, L0_streamNet, L11_aFloodPlain, L11_fCol, L11_fRow, L11_length, &
1245 : L11_nOutlets, L11_netPerm, L11_slope, L11_tCol, L11_tRow, level11
1246 : use mo_percentile, only: percentile
1247 :
1248 : implicit none
1249 :
1250 : ! Domain Id
1251 : integer(i4), intent(in) :: iDomain
1252 :
1253 : integer(i4) :: nLinks
1254 :
1255 24 : integer(i4), dimension(:, :), allocatable :: iD0
1256 :
1257 24 : integer(i4), dimension(:, :), allocatable :: fDir0
1258 :
1259 24 : real(dp), dimension(:, :), allocatable :: elev0
1260 :
1261 24 : real(dp), dimension(:, :), allocatable :: cellarea0
1262 :
1263 24 : integer(i4), dimension(:, :), allocatable :: streamNet0
1264 :
1265 24 : integer(i4), dimension(:, :), allocatable :: floodPlain0
1266 :
1267 : ! routing order (permutation)
1268 24 : integer(i4), dimension(:), allocatable :: netPerm
1269 :
1270 24 : integer(i4), dimension(:), allocatable :: nLinkFromRow
1271 :
1272 24 : integer(i4), dimension(:), allocatable :: nLinkFromCol
1273 :
1274 24 : integer(i4), dimension(:), allocatable :: nLinkToRow
1275 :
1276 24 : integer(i4), dimension(:), allocatable :: nLinkToCol
1277 :
1278 24 : real(dp), dimension(:), allocatable :: nLinkLength
1279 :
1280 24 : real(dp), dimension(:), allocatable :: nLinkAFloodPlain
1281 :
1282 24 : real(dp), dimension(:), allocatable :: nLinkSlope
1283 :
1284 : integer(i4) :: ii, rr, ns, s0, e0
1285 :
1286 : integer(i4) :: frow, fcol
1287 :
1288 : integer(i4) :: fId, tId
1289 :
1290 24 : integer(i4), dimension(:, :), allocatable :: stack, append_chunk
1291 :
1292 24 : integer(i4), dimension(:), allocatable :: dummy_1d
1293 :
1294 24 : real(dp) :: length
1295 :
1296 24 : integer(i4), dimension(:, :), allocatable :: nodata_i4_tmp
1297 :
1298 24 : real(dp), dimension(:, :), allocatable :: nodata_dp_tmp
1299 :
1300 : type(Grid), pointer :: level0_iDomain => null()
1301 :
1302 :
1303 24 : level0_iDomain => level0(domainMeta%L0DataFrom(iDomain))
1304 24 : s0 = level0_iDomain%iStart
1305 24 : e0 = level0_iDomain%iEnd
1306 24 : nLinks = level11(iDomain)%nCells - L11_nOutlets(iDomain)
1307 :
1308 :
1309 : ! allocate
1310 96 : allocate (iD0 (level0_iDomain%nrows, level0_iDomain%ncols))
1311 96 : allocate (elev0 (level0_iDomain%nrows, level0_iDomain%ncols))
1312 96 : allocate (fDir0 (level0_iDomain%nrows, level0_iDomain%ncols))
1313 96 : allocate (cellarea0 (level0_iDomain%nrows, level0_iDomain%ncols))
1314 96 : allocate (streamNet0 (level0_iDomain%nrows, level0_iDomain%ncols))
1315 72 : allocate (floodPlain0 (level0_iDomain%nrows, level0_iDomain%ncols))
1316 :
1317 : ! Routing network vectors have nNodes size instead of nLinks to
1318 : ! avoid the need of having two extra indices to identify a Domain.
1319 96 : allocate (stack (level11(iDomain)%nCells, 2)) ! >> stack(nNodes, 2)
1320 24 : allocate (dummy_1d (2))
1321 24 : allocate (append_chunk (8, 2))
1322 72 : allocate (netPerm (level11(iDomain)%nCells))
1323 48 : allocate (nLinkFromRow (level11(iDomain)%nCells))
1324 48 : allocate (nLinkFromCol (level11(iDomain)%nCells))
1325 48 : allocate (nLinkToRow (level11(iDomain)%nCells))
1326 48 : allocate (nLinkToCol (level11(iDomain)%nCells))
1327 72 : allocate (nLinkLength (level11(iDomain)%nCells))
1328 48 : allocate (nLinkAFloodPlain (level11(iDomain)%nCells))
1329 48 : allocate (nLinkSlope (level11(iDomain)%nCells))
1330 :
1331 96 : allocate (nodata_i4_tmp (level0_iDomain%nrows, level0_iDomain%ncols))
1332 96 : allocate (nodata_dp_tmp (level0_iDomain%nrows, level0_iDomain%ncols))
1333 :
1334 : ! initialize
1335 2862360 : iD0(:, :) = nodata_i4
1336 2862360 : elev0(:, :) = nodata_dp
1337 2862360 : fDir0(:, :) = nodata_i4
1338 2862360 : cellarea0(:, :) = nodata_dp
1339 2862360 : streamNet0(:, :) = nodata_i4
1340 2862360 : floodPlain0(:, :) = nodata_i4
1341 :
1342 1944 : stack(:, :) = nodata_i4
1343 456 : append_chunk(:, :) = nodata_i4
1344 960 : netPerm(:) = nodata_i4
1345 960 : nLinkFromRow(:) = nodata_i4
1346 960 : nLinkFromCol(:) = nodata_i4
1347 960 : nLinkToRow(:) = nodata_i4
1348 960 : nLinkToCol(:) = nodata_i4
1349 960 : nLinkLength(:) = nodata_dp
1350 960 : nLinkAFloodPlain(:) = nodata_dp
1351 960 : nLinkSlope(:) = nodata_dp
1352 :
1353 2862360 : nodata_i4_tmp(:, :) = nodata_i4
1354 2862360 : nodata_dp_tmp(:, :) = nodata_dp
1355 :
1356 : ! for a single node model run
1357 24 : if(level11(iDomain)%nCells .GT. 1) then
1358 : ! get L0 fields
1359 24 : iD0(:, :) = UNPACK(level0_iDomain%Id, level0_iDomain%mask, nodata_i4_tmp)
1360 0 : elev0(:, :) = UNPACK(L0_elev (s0 : e0), &
1361 24 : level0_iDomain%mask, nodata_dp_tmp)
1362 0 : fDir0(:, :) = UNPACK(L0_fDir (s0 : e0), &
1363 24 : level0_iDomain%mask, nodata_i4_tmp)
1364 24 : cellarea0(:, :) = UNPACK(level0_iDomain%CellArea, level0_iDomain%mask, nodata_dp_tmp)
1365 :
1366 : ! get network vectors of L11
1367 960 : netPerm(:) = L11_netPerm (level11(iDomain)%iStart : level11(iDomain)%iEnd)
1368 960 : nLinkFromRow(:) = L11_fRow (level11(iDomain)%iStart : level11(iDomain)%iEnd)
1369 960 : nLinkFromCol(:) = L11_fCol (level11(iDomain)%iStart : level11(iDomain)%iEnd)
1370 960 : nLinkToRow(:) = L11_tRow (level11(iDomain)%iStart : level11(iDomain)%iEnd)
1371 960 : nLinkToCol(:) = L11_tCol (level11(iDomain)%iStart : level11(iDomain)%iEnd)
1372 :
1373 : ! Flood plains: stream network delineation
1374 2862360 : streamNet0(:, :) = nodata_i4
1375 2862360 : floodPlain0(:, :) = nodata_i4
1376 :
1377 936 : do rr = 1, nLinks
1378 :
1379 912 : ii = netPerm(rr)
1380 912 : frow = nLinkFromRow(ii)
1381 912 : fcol = nLinkFromCol(ii)
1382 :
1383 : ! Init
1384 912 : streamNet0(frow, fcol) = ii
1385 912 : floodPlain0(frow, fcol) = ii
1386 126872 : stack = 0
1387 18240 : append_chunk = 0
1388 912 : ns = 1
1389 912 : stack(ns, 1) = frow
1390 912 : stack(ns, 2) = fcol
1391 :
1392 912 : call cellLength(iDomain, fDir0(frow, fcol), fRow, fCol, iFlag_cordinate_sys, nLinkLength(ii))
1393 912 : nLinkSlope(ii) = elev0(frow, fcol)
1394 :
1395 912 : fId = iD0(frow, fcol)
1396 912 : tId = iD0(nLinkToRow(ii), nLinkToCol(ii))
1397 :
1398 35952 : do while (.NOT. (fId == tId))
1399 :
1400 : ! Search flood plain from point(frow,fcol) upwards, keep co-ordinates in STACK
1401 :
1402 : ! flood plain calculation is expensive and only required for processCase = 1
1403 35040 : if (processMatrix(8,1) == 1) then
1404 4673474 : do while (ns > 0)
1405 4649970 : if (ns + 8 .gt. size(stack, 1)) then
1406 78 : call append(stack, append_chunk)
1407 : end if
1408 4649970 : call moveUp(elev0, fDir0, frow, fcol, stack, ns)
1409 4649970 : stack(1, 1) = 0
1410 4649970 : stack(1, 2) = 0
1411 : ! stack = cshift(stack, SHIFT = 1, DIM = 1)
1412 : ! substitute cshift <<<
1413 18599880 : dummy_1d = stack(1, :)
1414 1466468700 : stack(: size(stack, dim = 1) - 1, :) = stack(2 :, :)
1415 13949910 : stack(size(stack, dim = 1), :) = dummy_1d
1416 : ! substitute cshift >>>
1417 4649970 : if (stack(1, 1) > 0 .and. stack(1, 2) > 0) floodPlain0(stack(1, 1), stack(1, 2)) = ii
1418 742557794 : ns = count(stack > 0) / 2
1419 : end do
1420 : end if
1421 :
1422 : ! move downstream
1423 35040 : call moveDownOneCell(fDir0(frow, fcol), frow, fcol)
1424 35040 : streamNet0(frow, fcol) = ii
1425 35040 : floodPlain0(frow, fcol) = ii
1426 35040 : fId = iD0(frow, fcol)
1427 4519784 : stack = 0
1428 35040 : ns = 1
1429 35040 : stack(ns, 1) = frow
1430 35040 : stack(ns, 2) = fcol
1431 35040 : call cellLength(iDomain, fDir0(fRow, fCol), fRow, fCol, iFlag_cordinate_sys, length)
1432 35040 : nLinkLength(ii) = nLinkLength(ii) + length
1433 :
1434 : end do
1435 :
1436 : ! stream bed slope
1437 912 : nLinkSlope(ii) = (nLinkSlope(ii) - elev0(frow, fcol)) / nLinkLength(ii)
1438 :
1439 912 : if (nLinkSlope(ii) < 0.0001_dp) nLinkSlope(ii) = 0.0001_dp
1440 :
1441 : ! calculate area of floodplains (avoid overwriting)
1442 111450936 : nLinkAFloodPlain(ii) = sum (cellarea0(:, :), mask = (floodPlain0(:, :) == ii))
1443 : ! old > real( count( floodPlain0(:,:,) == i), dp ) * cellarea0
1444 :
1445 : end do
1446 :
1447 : ! end of multi-node network design loop
1448 : end if
1449 :
1450 : ! cut off Length at 40 percentile to neglect short paths in headwaters
1451 24 : if ((processMatrix(8, 1) .eq. 2) .or. (processMatrix(8, 1) .eq. 3)) then
1452 280 : if (count(nLinkLength(:) .ge. 0._dp) .gt. 2) then
1453 280 : length = percentile(pack(nLinkLength(:), nLinkLength(:) .ge. 0._dp), 40._dp)
1454 280 : nLinkLength(:) = merge(nLinkLength(:), length, (nLinkLength(:) .gt. length))
1455 : end if
1456 : end if
1457 :
1458 : !--------------------------------------------------------
1459 : ! Start padding up local variables to global variables
1460 : !--------------------------------------------------------
1461 :
1462 : ! L0 data sets
1463 : ! check whether L0 data is shared
1464 : ! ToDo: check if change is correct
1465 24 : if (iDomain .eq. 1) then
1466 12 : call append(L0_streamNet, PACK (streamNet0(:, :), level0_iDomain%mask))
1467 12 : call append(L0_floodPlain, PACK (floodPlain0(:, :), level0_iDomain%mask))
1468 12 : else if (domainMeta%L0DataFrom(iDomain) == iDomain) then
1469 9 : call append(L0_streamNet, PACK (streamNet0(:, :), level0_iDomain%mask))
1470 9 : call append(L0_floodPlain, PACK (floodPlain0(:, :), level0_iDomain%mask))
1471 : end if
1472 :
1473 :
1474 : ! L11 network data sets
1475 24 : call append(L11_length, nLinkLength(:))
1476 24 : call append(L11_aFloodPlain, nLinkAFloodPlain(:))
1477 24 : call append(L11_slope, nLinkSlope(:))
1478 :
1479 : ! free space
1480 0 : deallocate (&
1481 0 : iD0, elev0, fDir0, streamNet0, floodPlain0, &
1482 0 : cellarea0, stack, netPerm, nLinkFromRow, nLinkFromCol, nLinkToRow, nLinkToCol, &
1483 24 : nLinkLength, nLinkAFloodPlain, nLinkSlope, dummy_1d)
1484 24 : deallocate(nodata_i4_tmp, nodata_dp_tmp)
1485 :
1486 24 : end subroutine L11_stream_features
1487 :
1488 : ! ------------------------------------------------------------------
1489 :
1490 : ! NAME
1491 : ! L11_fraction_sealed_floodplain
1492 :
1493 : ! PURPOSE
1494 : !> \brief Fraction of the flood plain with impervious cover
1495 :
1496 : !> \details Fraction of the flood plain with impervious cover (\ref fig_routing "Routing
1497 : !> Network"). This proportion is used to regionalize the Muskingum parameters.
1498 : !> Samaniego et al. \cite SB05 found out that this fraction is one of the statistically
1499 : !> significant predictor variables of peak discharge in mesoscale Domains.
1500 : !> If a variable is added or removed here, then it also has to
1501 : !> be added or removed in the subroutine L11_config_set in
1502 : !> module mo_restart and in the subroutine set_L11_config in module
1503 : !> mo_set_netcdf_restart
1504 :
1505 : ! INTENT(IN)
1506 : !> \param[in] "integer(i4) :: LCClassImp" Impervious land cover class Id, e.g. = 2 (old code)
1507 : !> \param[in] "logical :: do_init"
1508 :
1509 : ! HISTORY
1510 : !> \authors Luis Samaniego
1511 :
1512 : !> \date Dec 2005
1513 :
1514 : ! Modifications:
1515 : ! Luis Samaniego Jan 2013 - modular version
1516 : ! Stephan Thober Aug 2015 - ported to mRM
1517 : ! Robert Schweppe Jun 2018 - refactoring and reformatting
1518 :
1519 13 : subroutine L11_fraction_sealed_floodplain(LCClassImp, do_init)
1520 :
1521 24 : use mo_append, only : append
1522 : use mo_common_constants, only : nodata_dp
1523 : use mo_common_types, only: Grid
1524 : use mo_common_variables, only : domainMeta, L0_LCover, level0, domainMeta, nLCoverScene
1525 : use mo_mrm_global_variables, only : L0_floodPlain, L11_aFloodPlain, &
1526 : L11_nLinkFracFPimp, L11_nOutlets, level11
1527 :
1528 : implicit none
1529 :
1530 : ! Impervious land cover class Id, e.g. = 2 (old code)
1531 : integer(i4), intent(in) :: LCClassImp
1532 :
1533 : logical, intent(in) :: do_init
1534 :
1535 : integer(i4) :: nLinks
1536 :
1537 : real(dp), dimension(:), pointer :: nLinkAFloodPlain => null()
1538 :
1539 13 : real(dp), dimension(:,:), allocatable :: temp_array
1540 :
1541 : integer(i4) :: ii, iDomain, iiLC, s0, e0
1542 :
1543 : type(Grid), pointer :: level0_iDomain => null()
1544 :
1545 :
1546 : ! initialization
1547 38 : do iDomain = 1, domainMeta%nDomains
1548 100 : allocate(temp_array(level11(iDomain)%nCells, nLCoverScene))
1549 2040 : temp_array = nodata_dp
1550 25 : if (do_init) then
1551 16 : level0_iDomain => level0(domainMeta%L0DataFrom(iDomain))
1552 :
1553 16 : s0 = level0_iDomain%iStart
1554 16 : e0 = level0_iDomain%iEnd
1555 16 : nLinks = level11(iDomain)%nCells + 1 - L11_nOutlets(iDomain)
1556 16 : nLinkAFloodPlain => L11_aFloodPlain(level11(iDomain)%iStart : level11(iDomain)%iEnd)
1557 :
1558 48 : do iiLC = 1, nLCoverScene
1559 : ! for a single node model run
1560 48 : if(nLinks .GT. 0) then
1561 1360 : do ii = 1, nLinks
1562 2656 : temp_array(ii, iiLC) = sum(level0_iDomain%CellArea(:), &
1563 0 : mask = (L0_floodPlain(s0 : e0) == ii .and. L0_LCover(s0 : e0, iiLC) == LCClassImp)) &
1564 59876256 : / nLinkAFloodPlain(ii)
1565 : end do
1566 : end if
1567 : end do
1568 : end if
1569 25 : call append(L11_nLinkFracFPimp, temp_array(:,:))
1570 38 : deallocate(temp_array)
1571 : end do
1572 :
1573 13 : end subroutine L11_fraction_sealed_floodplain
1574 :
1575 : ! ------------------------------------------------------------------
1576 : ! MOVE UPSTREAM FROM-TO
1577 : ! ------------------------------------------------------------------
1578 : ! NAME
1579 : ! moveUp
1580 :
1581 : ! PURPOSE
1582 : !> \brief TODO: add description
1583 :
1584 : !> \details TODO: add description
1585 :
1586 : ! INTENT(IN)
1587 : !> \param[in] "real(dp), dimension(:, :) :: elev0"
1588 : !> \param[in] "integer(i4), dimension(:, :) :: fDir0"
1589 : !> \param[in] "integer(i4) :: fi, fj" co-ordinate of the stream bed
1590 : !> \param[in] "integer(i4) :: fi, fj" co-ordinate of the stream bed
1591 :
1592 : ! INTENT(INOUT)
1593 : !> \param[inout] "integer(i4), dimension(:, :) :: ss"
1594 : !> \param[inout] "integer(i4) :: nn"
1595 :
1596 : ! HISTORY
1597 : !> \authors Robert Schweppe
1598 :
1599 : !> \date Jun 2018
1600 :
1601 : ! Modifications:
1602 : ! Robert Schweppe Jun 2018 - refactoring and reformatting
1603 :
1604 4649970 : subroutine moveUp(elev0, fDir0, fi, fj, ss, nn)
1605 :
1606 13 : use mo_mrm_constants, only : deltaH
1607 : use mo_utils, only : ge, le
1608 :
1609 : implicit none
1610 :
1611 : real(dp), dimension(:, :), allocatable, intent(IN) :: elev0
1612 :
1613 : integer(i4), dimension(:, :), allocatable, intent(IN) :: fDir0
1614 :
1615 : ! co-ordinate of the stream bed
1616 : integer(i4), intent(IN) :: fi, fj
1617 :
1618 : integer(i4), dimension(:, :), intent(INOUT) :: ss
1619 :
1620 : integer(i4), intent(INOUT) :: nn
1621 :
1622 : integer(i4) :: ii, jj, ip, im, jp, jm
1623 :
1624 : integer(i4) :: nrows, ncols
1625 :
1626 :
1627 4649970 : ii = ss(1, 1)
1628 4649970 : jj = ss(1, 2)
1629 4649970 : ip = ii + 1
1630 4649970 : im = ii - 1
1631 4649970 : jp = jj + 1
1632 4649970 : jm = jj - 1
1633 :
1634 4649970 : nrows = size(fDir0, 1)
1635 4649970 : ncols = size(fDir0, 2)
1636 :
1637 : !E
1638 4649970 : if (jp <= ncols) then
1639 9299940 : if ((fdir0(ii, jp) == 16) .and. &
1640 18599880 : (le((elev0(ii, jp) - elev0(fi, fj)), deltaH)) .and. &
1641 4649970 : (ge((elev0(ii, jp) - elev0(fi, fj)), 0.0_dp)) &
1642 : ) then
1643 970916 : nn = nn + 1
1644 970916 : ss(nn, 1) = ii
1645 970916 : ss(nn, 2) = jp
1646 : !print *, i,jp
1647 : end if
1648 : end if
1649 :
1650 : !SE
1651 4649970 : if ((ip <= nrows) .and. &
1652 : (jp <= ncols)) then
1653 0 : if ((fdir0(ip, jp) == 32) .and. &
1654 9299940 : (le((elev0(ip, jp) - elev0(fi, fj)), deltaH)) .and. &
1655 4649970 : (ge((elev0(ii, jp) - elev0(fi, fj)), 0.0_dp)) &
1656 : ) then
1657 321576 : nn = nn + 1
1658 321576 : ss(nn, 1) = ip
1659 321576 : ss(nn, 2) = jp
1660 : !print *, ip,jp
1661 : end if
1662 : end if
1663 :
1664 : !S
1665 4649970 : if ((ip <= nrows) .and. &
1666 : (jp <= ncols)) then
1667 0 : if ((fdir0(ip, jj) == 64) .and. &
1668 9299940 : (le((elev0(ip, jj) - elev0(fi, fj)), deltaH)) .and. &
1669 4649970 : (ge((elev0(ii, jp) - elev0(fi, fj)), 0.0_dp)) &
1670 : ) then
1671 787164 : nn = nn + 1
1672 787164 : ss(nn, 1) = ip
1673 787164 : ss(nn, 2) = jj
1674 : !print *, ip,j
1675 : end if
1676 : end if
1677 :
1678 : !SW
1679 : if ((ip <= nrows) .and. &
1680 4649970 : (jp <= ncols) .and. &
1681 : (jm >= 1)) then
1682 0 : if ((fdir0(ip, jm) == 128) .and. &
1683 9299940 : (le((elev0(ip, jm) - elev0(fi, fj)), deltaH)) .and. &
1684 4649970 : (ge((elev0(ii, jp) - elev0(fi, fj)), 0.0_dp)) &
1685 : ) then
1686 249878 : nn = nn + 1
1687 249878 : ss(nn, 1) = ip
1688 249878 : ss(nn, 2) = jm
1689 : !print *, ip,jm
1690 : end if
1691 : end if
1692 :
1693 : !W
1694 4649970 : if ((jm >= 1) .and. &
1695 : (jp <= ncols)) then
1696 0 : if ((fdir0(ii, jm) == 1) .and. &
1697 9299940 : (le((elev0(ii, jm) - elev0(fi, fj)), deltaH)) .and. &
1698 4649970 : (ge((elev0(ii, jp) - elev0(fi, fj)), 0.0_dp)) &
1699 : ) then
1700 663334 : nn = nn + 1
1701 663334 : ss(nn, 1) = ii
1702 663334 : ss(nn, 2) = jm
1703 : !print *, i,jm
1704 : end if
1705 : end if
1706 :
1707 : !NW
1708 : if ((im >= 1) .and. &
1709 4649970 : (jp <= ncols) .and. &
1710 : (jm >= 1)) then
1711 0 : if ((fdir0(im, jm) == 2) .and. &
1712 9299940 : (le((elev0(im, jm) - elev0(fi, fj)), deltaH)) .and. &
1713 4649970 : (ge((elev0(ii, jp) - elev0(fi, fj)), 0.0_dp)) &
1714 : ) then
1715 354012 : nn = nn + 1
1716 354012 : ss(nn, 1) = im
1717 354012 : ss(nn, 2) = jm
1718 : !print *, im,jm
1719 : end if
1720 : end if
1721 :
1722 : !N
1723 4649970 : if ((im >= 1) .and. &
1724 : (jp <= ncols)) then
1725 0 : if ((fdir0(im, jj) == 4) .and. &
1726 9299940 : (le((elev0(im, jj) - elev0(fi, fj)), deltaH)) .and. &
1727 4649970 : (ge((elev0(ii, jp) - elev0(fi, fj)), 0.0_dp)) &
1728 : ) then
1729 822956 : nn = nn + 1
1730 822956 : ss(nn, 1) = im
1731 822956 : ss(nn, 2) = jj
1732 : !print *, im,j
1733 : end if
1734 : end if
1735 :
1736 : !NE
1737 4649970 : if ((im >= 1) .and. &
1738 : (jp <= ncols)) then
1739 0 : if ((fdir0(im, jp) == 8) .and. &
1740 9299940 : (le((elev0(im, jp) - elev0(fi, fj)), deltaH)) .and. &
1741 4649970 : (ge((elev0(ii, jp) - elev0(fi, fj)), 0.0_dp)) &
1742 : ) then
1743 456630 : nn = nn + 1
1744 456630 : ss(nn, 1) = im
1745 456630 : ss(nn, 2) = jp
1746 : !print *, im,jp
1747 : end if
1748 : end if
1749 :
1750 4649970 : end subroutine moveUp
1751 :
1752 : ! ------------------------------------------------------------------
1753 : ! MOVE DOWNSTREAM
1754 : ! ------------------------------------------------------------------
1755 : ! NAME
1756 : ! moveDownOneCell
1757 :
1758 : ! PURPOSE
1759 : !> \brief TODO: add description
1760 :
1761 : !> \details TODO: add description
1762 :
1763 : ! INTENT(IN)
1764 : !> \param[in] "integer(i4) :: fDir"
1765 :
1766 : ! INTENT(INOUT)
1767 : !> \param[inout] "integer(i4) :: iRow, jCol"
1768 : !> \param[inout] "integer(i4) :: iRow, jCol"
1769 :
1770 : ! HISTORY
1771 : !> \authors Robert Schweppe
1772 :
1773 : !> \date Jun 2018
1774 :
1775 : ! Modifications:
1776 :
1777 43740628 : subroutine moveDownOneCell(fDir, iRow, jCol)
1778 : implicit none
1779 :
1780 : integer(i4), intent(IN) :: fDir
1781 :
1782 : integer(i4), intent(INOUT) :: iRow, jCol
1783 :
1784 :
1785 45179838 : select case (fDir)
1786 : case(1) !E
1787 1439210 : jCol = jCol + 1
1788 : case(2) !SE
1789 1682387 : iRow = iRow + 1
1790 1682387 : jCol = jCol + 1
1791 : case(4) !S
1792 3804397 : iRow = iRow + 1
1793 : case(8) !SW
1794 5753487 : iRow = iRow + 1
1795 5753487 : jCol = jCol - 1
1796 : case(16) !W
1797 11095532 : jCol = jCol - 1
1798 : case(32) !NW
1799 10002909 : iRow = iRow - 1
1800 10002909 : jCol = jCol - 1
1801 : case(64) !N
1802 7261091 : iRow = iRow - 1
1803 : case(128) !NE
1804 2701591 : iRow = iRow - 1
1805 2701591 : jCol = jCol + 1
1806 : case default !sink
1807 : ! do nothing
1808 : end select
1809 :
1810 4649970 : end subroutine moveDownOneCell
1811 :
1812 : ! ------------------------------------------------------------------
1813 : ! CELL LENGTH
1814 : ! ------------------------------------------------------------------
1815 : ! NAME
1816 : ! cellLength
1817 :
1818 : ! PURPOSE
1819 : !> \brief TODO: add description
1820 :
1821 : !> \details TODO: add description
1822 :
1823 : ! INTENT(IN)
1824 : !> \param[in] "integer(i4) :: iDomain"
1825 : !> \param[in] "integer(i4) :: fDir"
1826 : !> \param[in] "integer(i4) :: iRow"
1827 : !> \param[in] "integer(i4) :: jCol"
1828 : !> \param[in] "integer(i4) :: iCoorSystem"
1829 :
1830 : ! INTENT(OUT)
1831 : !> \param[out] "real(dp) :: length"
1832 :
1833 : ! HISTORY
1834 : !> \authors Robert Schweppe
1835 :
1836 : !> \date Jun 2018
1837 :
1838 : ! Modifications:
1839 :
1840 35952 : subroutine cellLength(iDomain, fDir, iRow, jCol, iCoorSystem, length)
1841 :
1842 43740628 : use mo_common_types, only: Grid
1843 : use mo_common_variables, only : domainMeta, level0
1844 : use mo_constants, only : SQRT2_dp
1845 :
1846 : implicit none
1847 :
1848 : integer(i4), intent(IN) :: iDomain
1849 :
1850 : integer(i4), intent(IN) :: fDir
1851 :
1852 : integer(i4), intent(IN) :: iRow
1853 :
1854 : integer(i4), intent(IN) :: jCol
1855 :
1856 : integer(i4), intent(IN) :: iCoorSystem
1857 :
1858 : real(dp), intent(OUT) :: length
1859 :
1860 : integer(i4) :: iRow_to, jCol_to
1861 :
1862 35952 : real(dp) :: lat_1, long_1, lat_2, long_2
1863 :
1864 : type(Grid), pointer :: level0_iDomain => null()
1865 :
1866 :
1867 35952 : level0_iDomain => level0(domainMeta%L0DataFrom(iDomain))
1868 :
1869 : ! regular X-Y cordinate system
1870 35952 : IF(iCoorSystem .EQ. 0) THEN
1871 :
1872 54786 : select case (fDir)
1873 : case(1, 4, 16, 64) ! E, S, W, N
1874 18834 : length = 1.0_dp
1875 : case(2, 8, 32, 128) ! SE, SW, NW, NE
1876 35952 : length = SQRT2_dp
1877 : end select
1878 35952 : length = length * level0_iDomain%cellsize
1879 :
1880 : ! regular lat-lon cordinate system
1881 0 : ELSE IF(iCoorSystem .EQ. 1) THEN
1882 0 : iRow_to = iRow
1883 0 : jCol_to = jCol
1884 :
1885 : ! move in the direction of flow
1886 0 : call moveDownOneCell(fDir, iRow_to, jCol_to)
1887 :
1888 : ! estimate lat-lon points
1889 : lat_1 = level0_iDomain%yllcorner + real((level0_iDomain%ncols - jCol), dp) * level0_iDomain%cellsize + &
1890 0 : 0.5_dp * level0_iDomain%cellsize
1891 : long_1 = level0_iDomain%xllcorner + real((iRow - 1), dp) * level0_iDomain%cellsize + &
1892 0 : 0.5_dp * level0_iDomain%cellsize
1893 :
1894 : lat_2 = level0_iDomain%yllcorner + real((level0_iDomain%ncols - jCol_to), dp) * level0_iDomain%cellsize + &
1895 0 : 0.5_dp * level0_iDomain%cellsize
1896 : long_2 = level0_iDomain%xllcorner + real((iRow_to - 1), dp) * level0_iDomain%cellsize + &
1897 0 : 0.5_dp * level0_iDomain%cellsize
1898 : ! get distance between two points
1899 0 : call get_distance_two_lat_lon_points(lat_1, long_1, lat_2, long_2, length)
1900 :
1901 : END IF
1902 : !
1903 35952 : end subroutine cellLength
1904 :
1905 :
1906 : ! --------------------------------------------------------------------------
1907 :
1908 : ! NAME
1909 : ! get_distance_two_lat_lon_points
1910 :
1911 : ! PURPOSE
1912 : !> \brief estimate distance in [m] between two points in a lat-lon
1913 :
1914 : !> \details estimate distance in [m] between two points in a lat-lon
1915 : !> Code is based on one that is implemented in the VIC-3L model
1916 :
1917 : ! INTENT(IN)
1918 : !> \param[in] "real(dp) :: lat1, long1, lat2, long2" latitude of point-1
1919 : !> \param[in] "real(dp) :: lat1, long1, lat2, long2" longitude of point-1
1920 : !> \param[in] "real(dp) :: lat1, long1, lat2, long2" latitude of point-2
1921 : !> \param[in] "real(dp) :: lat1, long1, lat2, long2" longitude of point-2
1922 :
1923 : ! INTENT(OUT)
1924 : !> \param[out] "real(dp) :: distance_out" distance between two points [m]
1925 :
1926 : ! HISTORY
1927 : !> \authors Rohini Kumar
1928 :
1929 : !> \date May 2014
1930 :
1931 : ! Modifications:
1932 : ! Stephan Thober Aug 2015 - ported to mRM
1933 : ! Robert Schweppe Jun 2018 - refactoring and reformatting
1934 :
1935 0 : subroutine get_distance_two_lat_lon_points(lat1, long1, lat2, long2, distance_out)
1936 :
1937 35952 : use mo_constants, only : RadiusEarth_dp, TWOPI_dp
1938 :
1939 : implicit none
1940 :
1941 : ! longitude of point-2
1942 : real(dp), intent(in) :: lat1, long1, lat2, long2
1943 :
1944 : ! distance between two points [m]
1945 : real(dp), intent(out) :: distance_out
1946 :
1947 0 : real(dp) :: theta1
1948 :
1949 0 : real(dp) :: phi1
1950 :
1951 0 : real(dp) :: theta2
1952 :
1953 0 : real(dp) :: phi2
1954 :
1955 : real(dp) :: dtor
1956 :
1957 0 : real(dp) :: term1
1958 :
1959 0 : real(dp) :: term2
1960 :
1961 0 : real(dp) :: term3
1962 :
1963 0 : real(dp) :: temp
1964 :
1965 :
1966 0 : dtor = TWOPI_dp / 360.0_dp
1967 0 : theta1 = dtor * long1
1968 0 : phi1 = dtor * lat1
1969 0 : theta2 = dtor * long2
1970 0 : phi2 = dtor * lat2
1971 :
1972 0 : term1 = cos(phi1) * cos(theta1) * cos(phi2) * cos(theta2)
1973 0 : term2 = cos(phi1) * sin(theta1) * cos(phi2) * sin(theta2)
1974 0 : term3 = sin(phi1) * sin(phi2)
1975 0 : temp = term1 + term2 + term3
1976 0 : if(temp .GT. 1.0_dp) temp = 1.0_dp
1977 :
1978 0 : distance_out = RadiusEarth_dp * acos(temp);
1979 :
1980 0 : end subroutine get_distance_two_lat_lon_points
1981 :
1982 : ! --------------------------------------------------------------------------
1983 :
1984 : ! NAME
1985 : ! L11_flow_accumulation
1986 :
1987 : ! PURPOSE
1988 :
1989 : !> \brief Calculates L11 flow accumulation per grid cell
1990 : !> \details Calculates L11 flow accumulation per grid cell using L11_fDir
1991 : !> and L11_cellarea. L11_flow_accumulation contains the recursiv subroutine
1992 : !> calculate_L11_flow_accumulation
1993 :
1994 : ! INTENT(IN)
1995 : !> iDomain
1996 :
1997 : ! INTENT(INOUT)
1998 : ! None
1999 :
2000 : ! INTENT(OUT)
2001 : ! L11_fAcc, L11_LinkIn_fAcc
2002 :
2003 : ! INTENT(IN), OPTIONAL
2004 : ! None
2005 :
2006 : ! INTENT(INOUT), OPTIONAL
2007 : ! None
2008 :
2009 : ! INTENT(OUT), OPTIONAL
2010 : ! None
2011 :
2012 : ! RETURN
2013 : ! None
2014 :
2015 : ! RESTRICTIONS
2016 : ! None
2017 :
2018 : ! EXAMPLE
2019 : ! None
2020 :
2021 : ! LITERATURE
2022 : ! None
2023 :
2024 : ! HISTORY
2025 : !> \author Matthias Kelbling
2026 : !> \date Aug 2017
2027 : ! Modified
2028 : ! Stephan Thober, Jun 2018 - refactored to fit MPR_extract
2029 :
2030 : ! --------------------------------------------------------------------------
2031 24 : subroutine L11_flow_accumulation(iDomain)
2032 :
2033 : use mo_mrm_global_variables, only: &
2034 0 : L11_fDir, & ! IN: flow direction at L11 (standard notation)
2035 : L11_fAcc ! OUT: flow accumulation at L11 [km^2]
2036 : use mo_mrm_global_variables, only : level11
2037 : use mo_common_constants, only : nodata_i4, nodata_dp
2038 : use mo_append, only : append
2039 :
2040 : implicit none
2041 :
2042 : ! local variables
2043 : integer(i4), intent(in) :: iDomain
2044 24 : real(dp), dimension(:,:), allocatable :: fAcc11 ! L11_fAcc array
2045 : integer(i4) :: ii, jj ! row and col index
2046 : integer(i4) :: s11, e11 ! Vec. position iDomain - fAcc
2047 : integer(i4) :: nrows11, ncols11 ! array size Domain
2048 24 : integer(i4), dimension(:,:), allocatable :: fDir11 ! L11_fDir array
2049 24 : logical, dimension(:,:), allocatable :: mask11 ! Domain mask
2050 :
2051 : ! initialize Domain info
2052 24 : nrows11 = level11(iDomain)%nrows
2053 24 : ncols11 = level11(iDomain)%ncols
2054 24 : s11 = level11(iDomain)%iStart
2055 24 : e11 = level11(iDomain)%iEnd
2056 1860 : mask11 = level11(iDomain)%mask
2057 :
2058 : ! allocate arrays
2059 96 : allocate(fDir11 (nrows11, ncols11))
2060 96 : allocate(fAcc11 (nrows11, ncols11))
2061 :
2062 : ! initialize
2063 1812 : fDir11(:,:) = nodata_i4
2064 :
2065 : ! get data
2066 24 : fDir11(:,:) = UNPACK( L11_fDir(s11:e11), mask11, nodata_i4 )
2067 :
2068 : ! initialize fAcc11 with cell area
2069 960 : fAcc11 = UNPACK( level11(iDomain)%cellarea * 1.e-6, mask11, nodata_dp )
2070 :
2071 : ! For each sink call "calculate_L11_flow_accumulation"
2072 250 : do jj=1, ncols11
2073 1812 : do ii=1, nrows11
2074 1788 : if (fDir11(ii,jj) .eq. 0) then
2075 : call calculate_L11_flow_accumulation(fDir = fDir11, &
2076 : fAcc = fAcc11, &
2077 : ii = ii, &
2078 : jj = jj, &
2079 : nrow = nrows11, &
2080 24 : ncol = ncols11)
2081 : end if
2082 : end do
2083 : end do
2084 :
2085 : ! Append
2086 24 : call append( L11_fAcc, pack(fAcc11(:,:),mask11))
2087 :
2088 : ! free space
2089 24 : deallocate(fDir11, fAcc11, mask11)
2090 :
2091 : contains
2092 :
2093 936 : recursive subroutine calculate_L11_flow_accumulation(fDir, fAcc, ii, jj, nrow, ncol)
2094 :
2095 : implicit none
2096 :
2097 : integer(i4), intent(in) :: fDir(:,:) ! flow Direction
2098 : real(dp), intent (inout) :: fAcc(:,:) ! flow accumulation
2099 : integer(i4), intent(in) :: ii, jj ! row and col index
2100 : integer(i4), intent(in) :: nrow, ncol ! number of rows,cols in array
2101 :
2102 : ! Scan order:
2103 : !
2104 : ! 6 7 8
2105 : ! 5 x 1
2106 : ! 4 3 2
2107 : !
2108 : ! Each:
2109 : ! 1. Check if cell is inflow cell to current grid
2110 : ! 2. If yes: Call calculate_subroutine and add result
2111 :
2112 936 : if (jj+1 .le. ncol) then
2113 912 : if (fDir(ii,jj+1) .eq. 16_i4) then
2114 402 : call calculate_L11_flow_accumulation(fDir, fAcc, ii, jj+1, nrow, ncol)
2115 402 : fAcc(ii,jj) = fAcc(ii,jj) + fAcc(ii,jj+1)
2116 : end if
2117 : end if
2118 :
2119 936 : if ((ii+1 .le. nrow) .and. (jj+1 .le. ncol)) then
2120 798 : if (fDir(ii+1,jj+1) .eq. 32_i4) then
2121 0 : call calculate_L11_flow_accumulation(fDir, fAcc, ii+1, jj+1, nrow, ncol)
2122 0 : fAcc(ii,jj) = fAcc(ii,jj) + fAcc(ii+1,jj+1)
2123 : end if
2124 : end if
2125 :
2126 936 : if (ii+1 .le. nrow) then
2127 822 : if (fDir(ii+1,jj) .eq. 64_i4) then
2128 320 : call calculate_L11_flow_accumulation(fDir, fAcc, ii+1, jj, nrow, ncol)
2129 320 : fAcc(ii,jj) = fAcc(ii,jj) + fAcc(ii+1,jj)
2130 : end if
2131 : end if
2132 :
2133 936 : if ((ii+1 .le. nrow) .and. (jj-1 .ge. 1)) then
2134 770 : if (fDir(ii+1,jj-1) .eq. 128_i4) then
2135 0 : call calculate_L11_flow_accumulation(fDir, fAcc, ii+1, jj-1, nrow, ncol)
2136 0 : fAcc(ii,jj) = fAcc(ii,jj) + fAcc(ii+1,jj-1)
2137 : end if
2138 : end if
2139 :
2140 936 : if (jj-1 .ge. 1) then
2141 884 : if (fDir(ii,jj-1) .eq. 1_i4) then
2142 50 : call calculate_L11_flow_accumulation(fDir, fAcc, ii, jj-1, nrow, ncol)
2143 50 : fAcc(ii,jj) = fAcc(ii,jj) + fAcc(ii,jj-1)
2144 : end if
2145 : end if
2146 :
2147 936 : if ((ii-1 .ge. 1) .and. (jj-1 .ge. 1)) then
2148 842 : if (fDir(ii-1,jj-1) .eq. 2_i4) then
2149 0 : call calculate_L11_flow_accumulation(fDir, fAcc, ii-1, jj-1, nrow, ncol)
2150 0 : fAcc(ii,jj) = fAcc(ii,jj) + fAcc(ii-1,jj-1)
2151 : end if
2152 : end if
2153 :
2154 936 : if (ii-1 .ge. 1) then
2155 892 : if (fDir(ii-1,jj) .eq. 4_i4) then
2156 138 : call calculate_L11_flow_accumulation(fDir, fAcc, ii-1, jj, nrow, ncol)
2157 138 : fAcc(ii,jj) = fAcc(ii,jj) + fAcc(ii-1,jj)
2158 : end if
2159 : end if
2160 :
2161 936 : if ((ii-1 .ge. 1) .and. (jj+1 .le. ncol)) then
2162 868 : if (fDir11(ii-1,jj+1) .eq. 8_i4) then
2163 2 : call calculate_L11_flow_accumulation(fDir, fAcc, ii-1, jj+1, nrow, ncol)
2164 2 : fAcc(ii,jj) = fAcc(ii,jj) + fAcc(ii-1,jj+1)
2165 : end if
2166 : end if
2167 :
2168 : ! print *, ii, jj, nrow, ncol, fAcc(ii, jj)
2169 :
2170 24 : end subroutine calculate_L11_flow_accumulation
2171 :
2172 : end subroutine L11_flow_accumulation
2173 :
2174 :
2175 : ! ------------------------------------------------------------------
2176 :
2177 : ! NAME
2178 : ! L11_calc_celerity
2179 :
2180 : ! PURPOSE
2181 : !> \brief L11 celerity based on L0 elevation and L0 fAcc
2182 :
2183 : !> \details L11 celerity based on L0 elevation and L0 fAcc
2184 :
2185 : ! INTENT(IN)
2186 : !> \param[in]
2187 :
2188 : ! INTENT(INOUT)
2189 : ! None
2190 :
2191 : ! INTENT(OUT)
2192 : ! None
2193 :
2194 : ! INTENT(IN), OPTIONAL
2195 : ! None
2196 :
2197 : ! INTENT(INOUT), OPTIONAL
2198 : ! None
2199 :
2200 : ! INTENT(OUT), OPTIONAL
2201 : ! None
2202 :
2203 : ! RETURN
2204 : ! None
2205 :
2206 : ! RESTRICTIONS
2207 : ! None
2208 :
2209 : ! EXAMPLE
2210 : ! None
2211 :
2212 : ! LITERATURE
2213 : ! None
2214 :
2215 : ! HISTORY
2216 : !> \author Matthias Kelbling
2217 : !> \date Oct 2017
2218 :
2219 : ! ------------------------------------------------------------------
2220 :
2221 17 : subroutine L11_calc_celerity(iDomain, param)
2222 : use mo_common_constants, only: nodata_i4, nodata_dp
2223 : use mo_mad, only: mad
2224 : use mo_append, only: append
2225 : use mo_mpr_global_variables, only: &
2226 : L0_slope ! IN: slope [%]
2227 : use mo_common_types, only: Grid
2228 : use mo_common_variables, only: &
2229 : domainMeta, & ! IN: for L0 Domain indexer
2230 : level0 ! IN: level 0 grid
2231 : use mo_mrm_global_variables, only: &
2232 : L0_fDir, & ! IN: flow direction (standard notation) L0
2233 : L0_fAcc, & ! IN: flow accumulation (number of cells)?
2234 : L0_streamNet, & ! IN: stream Network at Level 0
2235 : level11, & ! IN: level 11 grid
2236 : L11_fRow, & ! IN: from row in L0 grid
2237 : L11_fCol, & ! IN: from col in L0 grid
2238 : L11_tRow, & ! IN: to row in L0 grid
2239 : L11_tCol, & ! IN: to col in L0 grid
2240 : L11_netPerm, & ! IN: routing order (permutation)
2241 : L11_nOutlets, & ! IN: Number of Outlets/Sinks
2242 : L11_celerity, & ! INOUT: averaged celerity
2243 : L0_celerity ! INOUT
2244 :
2245 : implicit none
2246 :
2247 : integer(i4), intent(in) :: iDomain ! Domain
2248 : real(dp), dimension(:), intent(in) :: param
2249 :
2250 : ! local
2251 : integer(i4) :: nCells0
2252 : integer(i4) :: nNodes
2253 : integer(i4) :: nLinks
2254 : integer(i4) :: nrows0, ncols0
2255 : integer(i4) :: iStart0, iEnd0
2256 : integer(i4) :: nrows11, ncols11
2257 : integer(i4) :: iStart11, iEnd11
2258 17 : logical, dimension(:,:), allocatable :: mask0
2259 17 : integer(i4), dimension(:,:), allocatable :: iD0
2260 17 : integer(i4), dimension(:,:), allocatable :: fDir0
2261 17 : integer(i4), dimension(:,:), allocatable :: fAcc0
2262 17 : real(dp), dimension(:,:), allocatable :: slope0
2263 17 : real(dp), dimension(:), allocatable :: slope_tmp
2264 17 : real(dp), dimension(:,:), allocatable :: cellarea0
2265 17 : integer(i4), dimension(:), allocatable :: netPerm ! routing order (permutation)
2266 17 : integer(i4), dimension(:), allocatable :: nLinkFromRow
2267 17 : integer(i4), dimension(:), allocatable :: nLinkFromCol
2268 17 : integer(i4), dimension(:), allocatable :: nLinkToRow
2269 17 : integer(i4), dimension(:), allocatable :: nLinkToCol
2270 : integer(i4) :: ii, rr, ns
2271 : integer(i4) :: frow, fcol
2272 : integer(i4) :: fId, tId
2273 17 : real(dp), dimension(:), allocatable :: stack, append_chunk ! Stacks celerity along the L0 river-path
2274 17 : integer(i4), dimension(:), allocatable :: dummy_1d
2275 :
2276 17 : real(dp) :: L0_link_slope
2277 17 : real(dp), dimension(:), allocatable :: celerity11
2278 17 : real(dp), dimension(:,:), allocatable :: celerity0
2279 :
2280 17 : integer(i4), dimension(:,:), allocatable :: nodata_i4_tmp
2281 17 : real(dp), dimension(:,:), allocatable :: nodata_dp_tmp
2282 17 : logical, dimension(:), allocatable :: slopemask0
2283 :
2284 : type(Grid), pointer :: level0_iDomain
2285 :
2286 : ! level-0 information
2287 17 : level0_iDomain => level0(domainMeta%L0DataFrom(iDomain))
2288 17 : nrows0 = level0_iDomain%nrows
2289 17 : ncols0 = level0_iDomain%ncols
2290 17 : nCells0 = level0_iDomain%ncells
2291 17 : iStart0 = level0_iDomain%iStart
2292 17 : iEnd0 = level0_iDomain%iEnd
2293 2122467 : mask0 = level0_iDomain%mask
2294 :
2295 : ! level-11 information
2296 17 : iStart11 = level11(iDomain)%iStart
2297 17 : iEnd11 = level11(iDomain)%iEnd
2298 17 : nrows11 = level11(iDomain)%nrows
2299 17 : ncols11 = level11(iDomain)%ncols
2300 17 : nNodes = level11(iDomain)%ncells
2301 :
2302 17 : nLinks = nNodes - L11_nOutlets(iDomain)
2303 :
2304 : ! allocate
2305 68 : allocate ( iD0 ( nrows0, ncols0 ) )
2306 68 : allocate ( slope0 ( nrows0, ncols0 ) )
2307 51 : allocate ( fDir0 ( nrows0, ncols0 ) )
2308 51 : allocate ( fAcc0 ( nrows0, ncols0 ) )
2309 51 : allocate ( cellarea0 ( nrows0, ncols0 ) )
2310 51 : allocate ( celerity0 ( nrows0, ncols0 ) )
2311 51 : allocate ( slopemask0 ( ncells0 ) )
2312 :
2313 : ! Routing network vectors have nNodes size instead of nLinks to
2314 : ! avoid the need of having two extra indices to identify a Domain.
2315 17 : allocate ( stack ( 1 ) )
2316 17 : allocate ( append_chunk( 1 ) )
2317 17 : allocate ( dummy_1d ( 2 ))
2318 51 : allocate ( netPerm ( nNodes ) )
2319 34 : allocate ( nLinkFromRow( nNodes ) )
2320 34 : allocate ( nLinkFromCol( nNodes ) )
2321 34 : allocate ( nLinkToRow ( nNodes ) )
2322 34 : allocate ( nLinkToCol ( nNodes ) )
2323 51 : allocate ( celerity11 ( nNodes ) )
2324 34 : allocate ( slope_tmp ( nNodes ) )
2325 :
2326 51 : allocate (nodata_i4_tmp( nrows0, ncols0 ) )
2327 51 : allocate (nodata_dp_tmp( nrows0, ncols0 ) )
2328 :
2329 : ! initialize
2330 2122433 : iD0(:,:) = nodata_i4
2331 2122433 : fDir0(:,:) = nodata_i4
2332 2122433 : fAcc0(:,:) = nodata_i4
2333 2122433 : cellarea0(:,:) = nodata_dp
2334 2122433 : slope0(:,:) = nodata_dp
2335 :
2336 34 : stack(:) = nodata_dp
2337 34 : append_chunk(:) = nodata_dp
2338 595 : netPerm(:) = nodata_i4
2339 595 : nLinkFromRow(:) = nodata_i4
2340 595 : nLinkFromCol(:) = nodata_i4
2341 595 : nLinkToRow(:) = nodata_i4
2342 595 : nLinkToCol(:) = nodata_i4
2343 595 : celerity11(:) = nodata_dp
2344 2122433 : celerity0(:,:) = nodata_dp
2345 791282 : slopemask0(:) = .False.
2346 :
2347 2122433 : nodata_i4_tmp(:,:) = nodata_i4
2348 2122433 : nodata_dp_tmp(:,:) = nodata_dp
2349 :
2350 : ! for a single node model run
2351 :
2352 17 : if(nNodes .GT. 1) then
2353 : ! get L0 fields
2354 17 : iD0(:,:) = UNPACK(level0_iDomain%Id(1:nCells0), mask0, nodata_i4_tmp)
2355 17 : fDir0(:,:) = UNPACK(L0_fDir(iStart0:iEnd0), mask0, nodata_i4_tmp)
2356 17 : fAcc0(:,:) = UNPACK(L0_fAcc(iStart0:iEnd0), mask0, nodata_i4_tmp)
2357 17 : cellarea0(:,:) = UNPACK(level0_iDomain%cellarea(1:nCells0), mask0, nodata_dp_tmp)
2358 :
2359 : ! smoothing river slope
2360 791299 : slope_tmp = L0_slope(iStart0:iEnd0)
2361 791282 : where ( slope_tmp .lt. 0.1_dp ) slope_tmp = 0.1_dp
2362 :
2363 791282 : slopemask0(:) = (L0_streamNet(iStart0:iEnd0) .ne. nodata_i4)
2364 :
2365 : ! smooth river cells if there is more than one cell
2366 791282 : if( count(slopemask0) .GT. 1) then
2367 1582564 : slope_tmp = mad(arr = slope_tmp, z = 2.25_dp, mask = slopemask0, tout='u', mval=0.1_dp)
2368 : end if
2369 17 : slope0(:,:) = UNPACK(slope_tmp, mask0, nodata_dp_tmp )
2370 :
2371 : ! get network vectors of L11
2372 595 : netPerm(:) = L11_netPerm ( iStart11 : iEnd11 )
2373 595 : nLinkFromRow(:) = L11_fRow ( iStart11 : iEnd11 )
2374 595 : nLinkFromCol(:) = L11_fCol ( iStart11 : iEnd11 )
2375 595 : nLinkToRow(:) = L11_tRow ( iStart11 : iEnd11 )
2376 595 : nLinkToCol(:) = L11_tCol ( iStart11 : iEnd11 )
2377 :
2378 578 : do rr = 1, nLinks
2379 :
2380 561 : ii = netPerm(rr)
2381 561 : frow = nLinkFromRow(ii)
2382 561 : fcol = nLinkFromCol(ii)
2383 :
2384 : ! Init
2385 1122 : stack(:) = 0_dp
2386 561 : ns = 1
2387 :
2388 561 : fId = iD0( frow, fcol )
2389 561 : tId = iD0( nLinkToRow(ii) , nLinkToCol(ii) )
2390 24514 : do
2391 25075 : L0_link_slope = slope0(frow, fcol) / 100._dp
2392 :
2393 : ! celerity parametrization
2394 25075 : stack(ns) = param(1) * sqrt(L0_link_slope)
2395 :
2396 25075 : celerity0(frow, fcol) = stack(ns)
2397 25075 : ns = ns + 1
2398 25075 : fId = iD0(frow, fcol)
2399 25075 : if( .NOT. (fID == tID)) then
2400 24514 : call append(stack, append_chunk)
2401 : else
2402 : exit
2403 : end if
2404 : ! move downstream
2405 24514 : call moveDownOneCell( fDir0(frow,fcol), frow, fcol )
2406 : end do
2407 :
2408 25636 : celerity11(ii) = size(stack) / sum(1/stack(:))
2409 561 : deallocate(stack)
2410 578 : allocate(stack(1))
2411 :
2412 : end do
2413 :
2414 : else
2415 :
2416 : ! There is only one cell, so no routing is taking place
2417 : ! set dummy value of 1 m / s
2418 0 : celerity11(:) = 1._dp
2419 :
2420 : end if
2421 :
2422 : ! Write celerity
2423 595 : L11_celerity(iStart11:iEnd11) = celerity11(:)
2424 17 : L0_celerity(iStart0:iEnd0) = PACK(celerity0(:,:), mask0)
2425 :
2426 : ! free space
2427 0 : deallocate (&
2428 0 : mask0, iD0, slope_tmp, slopemask0, &
2429 0 : slope0, fDir0, cellarea0, &
2430 17 : stack, netPerm, nLinkFromRow, nLinkFromCol, nLinkToRow, nLinkToCol)
2431 :
2432 17 : end subroutine L11_calc_celerity
2433 :
2434 : end module mo_mrm_net_startup
|