Soil Water Balance (SWB2)
Loading...
Searching...
No Matches
routing__D8.F90
Go to the documentation of this file.
2
3 use iso_c_binding, only : c_short, c_int, c_float, c_double, c_bool
7 use exceptions
8 use grid
9 use fstring
10 implicit none
11
12 private
13
17
18 type (data_catalog_entry_t), pointer :: pd8_flowdir ! data catalog object => D8 flow direction grid
19
20 integer (c_int), allocatable :: target_row(:,:)
21 integer (c_int), allocatable :: target_col(:,:)
22 logical (c_bool), allocatable :: is_downslope_target_marked(:,:)
23 integer (c_int), allocatable :: sum_of_upslope_cells(:,:)
24 integer (c_int), allocatable :: number_of_upslope_connections(:,:)
25
26 !> @TODO remove redundant data elements; row1d, col1d, etc. are now also stored in the model data structure.
27
28 integer (c_int), allocatable :: row2d(:,:)
29 integer (c_int), allocatable :: col2d(:,:)
30 integer (c_int), allocatable :: row1d(:)
31 integer (c_int), allocatable :: col1d(:)
32
33 integer (c_int), allocatable :: row_index(:)
34 integer (c_int), allocatable :: column_index(:)
35 integer (c_int), allocatable :: sort_order_l(:)
36 integer (c_int), allocatable :: target_index_l(:)
37
38 integer (c_int), parameter :: d8_east = 1
39 integer (c_int), parameter :: d8_southeast = 2
40 integer (c_int), parameter :: d8_south = 4
41 integer (c_int), parameter :: d8_southwest = 8
42 integer (c_int), parameter :: d8_west = 16
43 integer (c_int), parameter :: d8_northwest = 32
44 integer (c_int), parameter :: d8_north = 64
45 integer (c_int), parameter :: d8_northeast = 128
46
47 integer (c_int), parameter :: d8_undetermined = -999
48
49 ! idea here is to create an array of row and column numbers, then use the
50 ! PACK statement to create a vector of row-column numbers in the same order that
51 ! the rest of the vectors are packed.
52
53 ! the vector of row-column numbers may then be used to make the required D8 routing connections.
54 ! there should not be anumber_of_rows difference between ROW_INDEX, COL_INDEX, and SORT_ORDER_l
55
56contains
57
58!
59! concept:
60! ^
61! +-----+--|--+-----+
62! | -> | | <- | with cell indices of 1 2 3 d8 flow dirs of 1 64 16
63! +-----+--^--+-----+ 4 64
64! | | |
65! +-----+
66!
67! solution must be ordered upslope to downslope: cell 1, 3, 4, then 2 as one possible sort order
68!
69! iteration_index cell_index target_index
70! ----------------- ------------ --------------
71! 1 1 2
72! 2 3 2
73! 3 4 2
74! 4 2 -9999
75!
76! function 'get_cell_index' simply looks up the appropriate cell index given a predefined
77! cell sort order.
78!
79 elemental function get_cell_index( iteration_index ) result( cell_index )
80
81 integer (c_int), intent(in) :: iteration_index
82 integer (c_int) :: cell_index
83
84 ! if D8 flow routing has not been initialized, report back the iteration index
85 cell_index = iteration_index
86
87 if ( allocated( sort_order_l ) ) cell_index = sort_order_l( iteration_index )
88
89
90 end function get_cell_index
91
92!---------------------------------------------------------------------------------------------------
93
94elemental function get_target_index( iteration_index ) result( target_index )
95
96 integer (c_int), intent(in) :: iteration_index
97 integer (c_int) :: target_index
98
99 if ( allocated( target_index_l ) ) then
100
101 target_index = target_index_l( iteration_index )
102
103 else
104
105 target_index = -9999
106
107 endif
108
109end function get_target_index
110
111!---------------------------------------------------------------------------------------------------
112
113 elemental function get_sort_order( cell_index ) result( iteration_index )
114
115 integer (c_int), intent(in) :: cell_index
116 integer (c_int) :: iteration_index
117
118 ! [ LOCALS ]
119 integer (c_int) :: current_cell_index
120 logical (c_bool) :: found_match
121
122 found_match = false
123
124 if ( allocated( sort_order_l ) ) then
125
126 do iteration_index=1, ubound( sort_order_l, 1 )
127
128 current_cell_index = sort_order_l( iteration_index )
129 if ( current_cell_index == cell_index ) then
130 found_match = true
131 exit
132 endif
133
134 enddo
135
136 endif
137
138 ! if this function is called and routing is turned off, the 'sort_order'
139 ! will be the same as the cell_index
140 if ( .not. found_match ) iteration_index = cell_index
141
142 end function get_sort_order
143
144!---------------------------------------------------------------------------------------------------
145
146 subroutine routing_d8_initialize( lActive, sort_order )
147
148 logical (c_bool), intent(in) :: lactive(:,:)
149 integer (c_int), intent(inout) :: sort_order(:)
150
151 ! [ LOCALS ]
152 integer (c_int) :: number_of_cols
153 integer (c_int) :: number_of_rows
154 integer (c_int) :: istat
155 integer (c_int) :: column_num
156 integer (c_int) :: row_num
157 integer (c_int) :: iteration_index
158 integer (c_int) :: icount
159 character (len=256) :: sbuf
160
161 integer (c_int) :: col_lbound, col_ubound
162 integer (c_int) :: row_lbound, row_ubound
163 integer (c_int) :: cell_index, target_index
164 integer (c_int) :: iunitnum
165 integer (c_int) :: target_row_num, target_col_num
166
167 type (general_grid_t), pointer :: ptempgrid
168
169 col_lbound = lbound(lactive, 1)
170 col_ubound = ubound(lactive, 1)
171
172 row_lbound = lbound(lactive, 2)
173 row_ubound = ubound(lactive, 2)
174
175 icount = 0
176
177 number_of_cols = ubound(lactive, 1)
178 number_of_rows = ubound(lactive, 2)
179
180 allocate( target_row( number_of_cols, number_of_rows ), stat=istat )
181 call assert( istat==0, "Problem allocating memory", __file__, __line__ )
182
183 allocate( target_col( number_of_cols, number_of_rows ), stat=istat )
184 call assert( istat==0, "Problem allocating memory", __file__, __line__ )
185
186
187 allocate( is_downslope_target_marked( number_of_cols, number_of_rows ), stat=istat )
188 call assert( istat==0, "Problem allocating memory", __file__, __line__ )
189
190 allocate( col2d( number_of_cols, number_of_rows ), stat=istat )
191 call assert( istat==0, "Problem allocating memory", __file__, __line__ )
192
193 allocate( row2d( number_of_cols, number_of_rows ), stat=istat )
194 call assert( istat==0, "Problem allocating memory", __file__, __line__ )
195
196 allocate( col1d( count( lactive) ), stat=istat )
197 call assert( istat==0, "Problem allocating memory", __file__, __line__ )
198
199 allocate( row1d( count( lactive) ), stat=istat )
200 call assert( istat==0, "Problem allocating memory", __file__, __line__ )
201
202 allocate( sum_of_upslope_cells( number_of_cols, number_of_rows ), stat=istat )
203 call assert( istat==0, "Problem allocating memory", __file__, __line__ )
204
205 allocate( number_of_upslope_connections( number_of_cols, number_of_rows ), stat=istat )
206 call assert( istat==0, "Problem allocating memory", __file__, __line__ )
207
208 allocate( row_index( count( lactive) ), stat=istat )
209 call assert( istat==0, "Problem allocating memory", __file__, __line__ )
210
211 allocate( column_index( count( lactive) ), stat=istat )
212 call assert( istat==0, "Problem allocating memory", __file__, __line__ )
213
214 allocate( target_index_l( count( lactive) ), stat=istat )
215 call assert( istat==0, "Problem allocating memory", __file__, __line__ )
216
217 allocate( sort_order_l( count( lactive) ), stat=istat )
218 call assert( istat==0, "Problem allocating memory", __file__, __line__ )
219
220 ! locate the data structure associated with the gridded flow direction entries
221 pd8_flowdir => dat%find("FLOW_DIRECTION")
222 if ( .not. associated(pd8_flowdir) ) &
223 call die("A FLOW_DIRECTION grid must be supplied in order to make use of this option.", __file__, __line__)
224
225 call pd8_flowdir%getvalues()
226
227 ptempgrid=>grid_create( bnds%iNumCols, bnds%iNumRows, bnds%fX_ll, bnds%fY_ll, &
228 bnds%fX_ur, bnds%fY_ur, datatype_int )
229
230 ptempgrid%iData = pd8_flowdir%pGrdBase%iData
231
232 call grid_writearcgrid("D8_Flow_Direction_Grid.asc", ptempgrid)
233
235
236 do row_num=row_lbound, row_ubound
237 do column_num=col_lbound, col_ubound
238
239 col2d( column_num, row_num ) = column_num ! right-most index should vary slowest
240 row2d( column_num, row_num ) = row_num
241
242 enddo
243 enddo
244
245 ! create 1D vectors of column and row numbers for full grid
246 col1d = pack( col2d, lactive )
247 row1d = pack( row2d, lactive )
248
250
251 ptempgrid%iData = target_row
252 call grid_writearcgrid("D8_TARGET_ROW_Grid.asc", ptempgrid)
253
254 ptempgrid%iData = target_col
255 call grid_writearcgrid("D8_TARGET_COL_Grid.asc", ptempgrid)
256
257 open( newunit=iunitnum, file=trim(output_directory_name)//trim("D8_routing_table.txt"), &
258 iostat=istat, status="REPLACE")
259
260 write(iunitnum,*) "Sort_Order"//tab//"CELL_INDEX"//tab//"TARGET_INDEX"//tab//"From_COL" &
261 // tab//"From_ROW"//tab//"To_COL"//tab//"To_ROW"//tab//"D8_flowdir"//tab &
262 //"Num_Adjacent_Upslope_Connections"//tab//"Sum_of_Upslope_Contributing_Cells"
263
264 ! solution order has been determined; remaining code simply writes a summary to a
265 ! file for further analysis
266 do iteration_index = 1, ubound(col1d,1)
267
268 sbuf = ""
269
270 cell_index = get_cell_index( iteration_index )
271 target_index = get_target_index( iteration_index )
272
273 sort_order(iteration_index) = cell_index
274
275 associate( &
276 rownum => row1d( cell_index ), &
277 colnum => col1d( cell_index ), &
278! Target_row => ROW1D( target_index ), &
279! Target_col => COL1D( target_index ), &
280 d8_flowdir => pd8_flowdir%pGrdBase%iData( col1d( cell_index ), &
281 row1d( cell_index ) ), &
282 num_adjacent => number_of_upslope_connections( col1d( cell_index ), &
283 row1d( cell_index ) ), &
284 sum_upslope => sum_of_upslope_cells( col1d( cell_index ), &
285 row1d( cell_index ) ) )
286
287 write(sbuf,*) iteration_index, tab, cell_index, tab, target_index
288 write(sbuf,*) trim(sbuf)//tab//ascharacter( colnum )//tab &
289 //ascharacter( rownum )
290
291 if ( target_index > 0 .and. target_index <= ubound(col1d,1) ) then
292 target_row_num = row1d( target_index )
293 target_col_num = col1d( target_index )
294 else
295 target_row_num = -9999
296 target_col_num = -9999
297 endif
298
299 write(sbuf,*) trim(sbuf)//tab//ascharacter( target_col_num )//tab &
300 //ascharacter( target_row_num )//tab//ascharacter( d8_flowdir )//tab &
301 //ascharacter( num_adjacent )//tab//ascharacter( sum_upslope )
302
303 write(iunitnum,*) trim(sbuf)
304
305 end associate
306
307 enddo
308
309 close ( iunitnum )
310
311 end subroutine routing_d8_initialize
312
313!--------------------------------------------------------------------------------------------------
314
315 function routing_d8_get_index( iCol, iRow ) result( cell_index )
316
317 integer (c_int), intent(in) :: icol
318 integer (c_int), intent(in) :: irow
319 integer (c_int) :: cell_index
320
321 ! [ LOCALS ]
322 integer (c_int) :: iindex
323 logical (c_bool) :: lfound
324
325 iindex = -9999
326 cell_index = -9999
327 lfound = false
328
329 ! iterate over 1D vector of column numbers
330 do iindex = lbound(col1d,1), ubound(col1d,1)
331
332 if( col1d( iindex ) == icol .and. row1d( iindex ) == irow ) then
333 cell_index = iindex
334 lfound = true
335 exit
336 endif
337
338 enddo
339
340! if ( .not. lFound ) call warn("Did not find matching column and row number; col=" &
341! //asCharacter(iCol)//"; row="//asCharacter(iRow), __FILE__, __LINE__ )
342
343 end function routing_d8_get_index
344
345!--------------------------------------------------------------------------------------------------
346
348
349 logical (c_bool), intent(in) :: lActive(:,:)
350
351 ! [ LOCALS ]
352 integer (c_int) :: row_num
353 integer (c_int) :: column_num
354 integer (c_int) :: col_lbound, col_ubound
355 integer (c_int) :: row_lbound, row_ubound
356
357 col_lbound = lbound(lactive, 1)
358 col_ubound = ubound(lactive, 1)
359
360 row_lbound = lbound(lactive, 2)
361 row_ubound = ubound(lactive, 2)
362
363 associate( dir => pd8_flowdir%pGrdBase%iData )
364
365 do row_num=row_lbound, row_ubound
366 do column_num=col_lbound, col_ubound
367
368 select case ( dir( column_num, row_num ) )
369
370 case ( d8_east )
371
372 target_col(column_num, row_num) = column_num + 1
373 target_row(column_num, row_num) = row_num
374
375 case ( d8_southeast )
376
377 target_col(column_num, row_num) = column_num + 1
378 target_row(column_num, row_num) = row_num + 1
379
380 case ( d8_south )
381
382 target_col(column_num, row_num) = column_num
383 target_row(column_num, row_num) = row_num + 1
384
385 case ( d8_southwest )
386
387 target_col(column_num, row_num) = column_num - 1
388 target_row(column_num, row_num) = row_num + 1
389
390 case ( d8_west )
391
392 target_col(column_num, row_num) = column_num - 1
393 target_row(column_num, row_num) = row_num
394
395 case ( d8_northwest )
396
397 target_col(column_num, row_num) = column_num - 1
398 target_row(column_num, row_num) = row_num - 1
399
400 case ( d8_north )
401
402 target_col(column_num, row_num) = column_num
403 target_row(column_num, row_num) = row_num - 1
404
405 case ( d8_northeast )
406
407 target_col(column_num, row_num) = column_num + 1
408 target_row(column_num, row_num) = row_num - 1
409
410 case default
411
412 target_col(column_num, row_num) = d8_undetermined
413 target_row(column_num, row_num) = d8_undetermined
414
415 end select
416
417 enddo
418
419 enddo
420
421 end associate
422
423
425
426!--------------------------------------------------------------------------------------------------
427
429
430 use grid
431
432 logical (c_bool), intent(in) :: lActive(:,:)
433
434 ! [ LOCALS ]
435 integer (c_int) :: row_num
436 integer (c_int) :: column_num
437 integer (c_int) :: iColsrch
438 integer (c_int) :: iRowsrch
439 integer (c_int) :: iNumberOfChangedCells
440 integer (c_int) :: col_lbound, col_ubound
441 integer (c_int) :: row_lbound, row_ubound
442 integer (c_int) :: iUpslopeSum, iUpslopeConnections
443 logical (c_bool) :: are_there_unmarked_upslope_cells
444 logical (c_bool) :: lCircular
445 integer (c_int) :: iNumberRemaining
446 integer (c_int) :: indx, k, iCount
447 integer (c_int) :: num_cells_marked_this_iteration
448 integer (c_int) :: iPasses
449 integer (c_int) :: iPassesWithoutChange
450 type (GENERAL_GRID_T), pointer :: pTempGrid
451
452 col_lbound = lbound(lactive, 1)
453 col_ubound = ubound(lactive, 1)
454
455 row_lbound = lbound(lactive, 2)
456 row_ubound = ubound(lactive, 2)
457
459 sum_of_upslope_cells = 0_c_int
460
461 indx = 0
462 ipasses = 0
463 ipasseswithoutchange = 0
464
465 ptempgrid=>grid_create( bnds%iNumCols, bnds%iNumRows, bnds%fX_ll, bnds%fY_ll, &
466 bnds%fX_ur, bnds%fY_ur, datatype_int )
467
468
469main_loop: do
470
471 inumberofchangedcells = 0_c_int
472 num_cells_marked_this_iteration = 0_c_int
473 ipasses = ipasses + 1
474
475 ! iterate over entire model domain
476 do row_num=row_lbound, row_ubound
477 do column_num=col_lbound, col_ubound
478
479 if ( .not. lactive(column_num, row_num) ) cycle
480
481 ! we have already determined the identiy of the downslope cell; skip this one
482 if ( is_downslope_target_marked(column_num, row_num) ) cycle
483
484 inumberofchangedcells = inumberofchangedcells + 1
485 iupslopesum = 0_c_int
486 iupslopeconnections = 0_c_int
487 are_there_unmarked_upslope_cells = false
488 lcircular = false
489
490 ! search the 8 cells immediately adjacent to the current cell
491 local_search: do irowsrch=max( row_num-1, row_lbound),min( row_num+1, row_ubound)
492 do icolsrch=max( column_num-1, col_lbound),min( column_num+1, col_ubound)
493
494 ! if adjacent cell points to current cell, determine what to do with runoff
495 if ( ( target_col(icolsrch, irowsrch) == column_num ) &
496 .and. ( target_row(icolsrch, irowsrch) == row_num ) ) then
497
498 ! if adjacent cell falls outside the area of active cells,
499 ! ignore it and move on
500 if ( .not. lactive( icolsrch, irowsrch ) ) cycle
501
502 ! if the target of the current cell points back at the adjacent
503 ! cell, mark current cell as having a "circular" connection
504 if ( ( target_col( column_num, row_num ) == icolsrch ) &
505 .and. ( target_row( column_num, row_num ) == irowsrch ) ) lcircular = true
506
507 ! if the adjacent cell is marked (that is, has no unresolved
508 ! upslope contributions), add the 1 to the number of connections
509 ! and add the adjacent cells' sum of upslope cells to the
510 ! current cells' running sum of upslope cells
511 if( is_downslope_target_marked( icolsrch, irowsrch ) ) then
512
513 iupslopesum = iupslopesum + sum_of_upslope_cells(icolsrch, irowsrch)
514 iupslopeconnections = iupslopeconnections + 1
515
516 ! add number of upslope cells and connections to temporary variables
517 ! if we get to the end of the search and find no unmarked adjacent cells,
518 ! we have determined the number of upslope contributing cells and will
519 ! be able to mark the current cell
520 else
521
522 are_there_unmarked_upslope_cells = true
523
524 endif
525
526 endif
527
528 enddo
529 enddo local_search
530
531 ! OK this is the end of the local search area; did we uncover anumber_of_rows unmarked cells
532 ! contributing flow to the current cell? if so, ignore and move on. otherwise,
533 ! mark current cell as marked, update stats, and continue with next cell
534
535 if ( .not. are_there_unmarked_upslope_cells ) then
536! .or. (iUpslopeConnections == 1 .and. lCircular ) ) then
537
538 num_cells_marked_this_iteration = num_cells_marked_this_iteration + 1
539 indx = indx + 1
540
541 ! need to add one to the sum already tabulated to account for the
542 ! current cell as well
543 sum_of_upslope_cells( column_num, row_num ) = iupslopesum + 1
544 number_of_upslope_connections( column_num, row_num ) = iupslopeconnections
545 is_downslope_target_marked( column_num, row_num ) = true
546 column_index( indx ) = column_num
547 row_index( indx ) = row_num
548 sort_order_l( indx ) = routing_d8_get_index( column_num, row_num )
549 target_index_l( indx ) = routing_d8_get_index( target_col( column_num, row_num ), &
550 target_row( column_num, row_num ) )
551
552 ! print *, " ===> assigning order number: "
553 ! print *, " indx =",indx
554 ! print *, " sort_order =", SORT_ORDER_l( indx )
555 ! print *, " target_index =", TARGET_INDEX_l( indx )
556 ! print *, " target_index(SORT_ORDER_l =", TARGET_INDEX_l( SORT_ORDER_l( indx ) )
557
558 if ( lcircular ) target_index_l( sort_order_l( indx ) ) = d8_undetermined
559
560 ! if cells are not being marked, record cell as D8_UNDETERMINED
561 ! and move on
562 elseif ( ipasseswithoutchange > 10 ) then
563
564 num_cells_marked_this_iteration = num_cells_marked_this_iteration + 1
565 indx = indx + 1
566
567 sum_of_upslope_cells( column_num, row_num ) = iupslopesum
568 number_of_upslope_connections( column_num, row_num ) = iupslopeconnections
569 is_downslope_target_marked( column_num, row_num ) = true
570 column_index( indx ) = column_num
571 row_index( indx ) = row_num
572 sort_order_l( indx ) = routing_d8_get_index( column_num, row_num )
573
575
576 endif
577
578 enddo
579 enddo
580
581! if (iNumberOfChangedCells == 0) exit main_loop
582
583 inumberremaining = count( lactive ) - count( is_downslope_target_marked )
584
585 if ( inumberremaining==0 ) exit main_loop
586
587 print *, "### determining solution order... ", count( is_downslope_target_marked ), " cells marked so far " &
588 //"out of ", count( lactive ), " active cells."
589
590
591 if ( num_cells_marked_this_iteration==0 ) then
592
593 ipasseswithoutchange = ipasseswithoutchange + 1
594
595 where( is_downslope_target_marked .or. ( .not. lactive ) )
596 ptempgrid%iData = -1
597 elsewhere
598 ptempgrid%iData = pd8_flowdir%pGrdBase%iData
599 end where
600
601 write(*,"(/,1x,'Summary of remaining unmarked cells')")
602
603 ! loop over possible (legal) values of the flow direction grid
604 do k=0,128
605 icount=count( .not. is_downslope_target_marked &
606 .and. pd8_flowdir%pGrdBase%iData==k .and. lactive )
607 if( icount > 0 ) then
608 write(*,fmt="(3x,i8,' unmarked grid cells have flowdir value: ',i8)") icount, k
609 end if
610 end do
611
612 write(*,fmt="(3x,a)") repeat("-",60)
613 write(*,fmt="(3x,i8,' Total cells with nonzero flow " &
614 //"direction values')") count( pd8_flowdir%pGrdBase%iData > 0 )
615
616
617 call grid_writearcgrid("iteration"//ascharacter(ipasses)// &
618 "problem_gridcells.asc", ptempgrid)
619
620 end if
621
622
623 enddo main_loop
624
625 ptempgrid%iData = sum_of_upslope_cells
626 call grid_writearcgrid("D8_Flow_Routing__Upslope_Contributing_Area.asc", ptempgrid)
627
628 ptempgrid%iData = number_of_upslope_connections
629 call grid_writearcgrid("D8_Flow_Routing__Number_of_Adjacent_Upslope_Connections.asc", ptempgrid)
630
631 call grid_destroy( ptempgrid )
632
634
635 !------------------------------------------------------------------------------------------------
636
637 ! subroutine calculate_routing_D8( indx )
638 !
639 ! if ( ( TARGET_INDEX_l( indx ) >= lbound( SORT_ORDER_l, 1) ) &
640 ! .and. ( TARGET_INDEX_l( indx ) <= ubound( SORT_ORDER_l, 1) ) ) then
641 !
642 ! this%runon( TARGET_INDEX_l( index ) ) = this%runoff( SORT_ORDER_l( index ) )
643 !
644 ! endif
645 !
646 ! enddo
647 !
648 ! end subroutine calculate_routing_D8
649
650end module routing__d8
This module contains physical constants and convenience functions aimed at performing unit conversion...
logical(c_bool), parameter, public true
logical(c_bool), parameter, public false
character(len=:), allocatable, public output_directory_name
integer(c_int), parameter datatype_int
Defines the DATA_CATALOG_T data type, which contains type-bound procedures to add,...
type(data_catalog_t), public dat
DAT is a global to hold data catalog entries.
subroutine, public die(smessage, smodule, iline, shints, scalledby, icalledbyline)
character(len=1), parameter, public tab
Definition fstring.F90:171
Provides support for input and output of gridded ASCII data, as well as for creation and destruction ...
Definition grid.F90:8
subroutine, public grid_destroy(pgrd)
Definition grid.F90:366
subroutine, public grid_writearcgrid(sfilename, pgrd)
Definition grid.F90:1056
integer(c_int), dimension(:,:), allocatable, public number_of_upslope_connections
integer(c_int), dimension(:,:), allocatable col2d
integer(c_int), dimension(:), allocatable row_index
type(data_catalog_entry_t), pointer pd8_flowdir
integer(c_int), dimension(:,:), allocatable target_col
integer(c_int) function routing_d8_get_index(icol, irow)
integer(c_int), dimension(:), allocatable column_index
integer(c_int), parameter d8_southwest
integer(c_int), dimension(:,:), allocatable, public sum_of_upslope_cells
integer(c_int), parameter, public d8_undetermined
subroutine routing_d8_determine_solution_order(lactive)
integer(c_int), parameter d8_north
integer(c_int), dimension(:), allocatable row1d
integer(c_int), dimension(:), allocatable target_index_l
elemental integer(c_int) function, public get_target_index(iteration_index)
elemental integer(c_int) function, public get_sort_order(cell_index)
integer(c_int), parameter d8_northeast
integer(c_int), dimension(:), allocatable col1d
subroutine, public routing_d8_initialize(lactive, sort_order)
integer(c_int), dimension(:), allocatable sort_order_l
elemental integer(c_int) function, public get_cell_index(iteration_index)
integer(c_int), parameter d8_south
subroutine routing_d8_assign_downstream_row_col(lactive)
integer(c_int), parameter d8_west
integer(c_int), dimension(:,:), allocatable row2d
@TODO remove redundant data elements; row1d, col1d, etc. are now also stored in the model data struct...
integer(c_int), parameter d8_northwest
integer(c_int), parameter d8_east
integer(c_int), parameter d8_southeast
logical(c_bool), dimension(:,:), allocatable is_downslope_target_marked
integer(c_int), dimension(:,:), allocatable target_row