! +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
! + +
! + glimmer_routing.f90 - part of the Glimmer-CISM ice model +
! + +
! +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
!
! Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
! Glimmer-CISM contributors - see AUTHORS file for list of contributors
!
! This file is part of Glimmer-CISM.
!
! Glimmer-CISM is free software: you can redistribute it and/or modify
! it under the terms of the GNU General Public License as published by
! the Free Software Foundation, either version 2 of the License, or (at
! your option) any later version.
!
! Glimmer-CISM is distributed in the hope that it will be useful,
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with Glimmer-CISM. If not, see .
!
! Glimmer-CISM is hosted on BerliOS.de:
! https://developer.berlios.de/projects/glimmer-cism/
!
! +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#ifdef HAVE_CONFIG_H
#include "config.inc"
#endif
module glimmer_routing
use glimmer_global,only: rk,sp
private
public flow_router
contains
subroutine flow_router(surface,input,output,mask,dx,dy)
!*FD Routes water from input field to its destination,
!*FD according to a surface elevation field. The method used
!*FD is by Quinn et. al. (1991)
real(sp),dimension(:,:),intent(in) :: surface !*FD Surface elevation
real(rk),dimension(:,:),intent(in) :: input !*FD Input water field
real(rk),dimension(:,:),intent(out) :: output !*FD Output water field
integer, dimension(:,:),intent(in) :: mask !*FD Masked points
real(rk), intent(in) :: dx !*FD $x$ grid-length
real(rk), intent(in) :: dy !*FD $y$ grid-length
! Internal variables --------------------------------------
integer :: nx,ny,k,nn,cx,cy,px,py,x,y
integer, dimension(:,:),allocatable :: sorted
real(rk),dimension(:,:),allocatable :: flats,surfcopy
real(rk),dimension(-1:1,-1:1) :: slopes
real(rk),dimension(-1:1,-1:1) :: dists
logical :: flag
! Set up grid dimensions ----------------------------------
nx=size(surface,1) ; ny=size(surface,2)
nn=nx*ny
dists(-1,:)=(/4d0,2d0*dx/dy,4d0/)
dists(0,:)=(/2d0*dy/dx,0d0,2d0*dy/dx/)
dists(1,:)=dists(-1,:)
! Allocate internal arrays and copy data ------------------
allocate(sorted(nn,2),flats(nx,ny),surfcopy(nx,ny))
surfcopy=surface
! Fill holes in data, and sort heights --------------------
call fillholes(surfcopy,flats,mask)
call heights_sort(surfcopy,sorted)
! Initialise output with input, which will then be --------
! redistributed -------------------------------------------
output=input
! Begin loop over points, highest first -------------------
do k=nn,1,-1
! Get location of current point -------------------------
x=sorted(k,1)
y=sorted(k,2)
! Reset flags and slope arrays --------------------------
flag=.true.
slopes=0.0
! Loop over adjacent points, and calculate slopes -------
do cx=-1,1,1
do cy=-1,1,1
! If this is the centre point, ignore
if (cx==0.and.cy==0) continue
! Otherwise do slope calculation
px=x+cx ; py=y+cy
if (px>0.and.px<=nx.and.py>0.and.py<=ny) then
if (surfcopy(px,py)= pivot) .and. (ll < rr))) exit
rr=rr-1
enddo
if (ll.ne.rr) then
index(ll) = index(rr)
ll=ll+1
endif
do
if (.not.((numbers(index(ll)) <= pivot) .and. (ll < rr))) exit
ll=ll+1
enddo
if (ll.ne.rr) then
index(rr) = index(ll)
rr=rr-1
endif
enddo
index(ll) = pivpos
pv_int = ll
ll = l_hold
rr = r_hold
if (ll < pv_int) call q_sort_index(numbers, index,ll, pv_int-1)
if (rr > pv_int) call q_sort_index(numbers, index,pv_int+1, rr)
end subroutine q_sort_index
end module glimmer_routing