!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! ! glint_routing.F90 - part of the Community Ice Sheet Model (CISM) ! !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! ! Copyright (C) 2005-2014 ! CISM contributors - see AUTHORS file for list of contributors ! ! This file is part of CISM. ! ! CISM is free software: you can redistribute it and/or modify it ! under the terms of the Lesser GNU General Public License as published ! by the Free Software Foundation, either version 3 of the License, or ! (at your option) any later version. ! ! 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 ! Lesser GNU General Public License for more details. ! ! You should have received a copy of the Lesser GNU General Public License ! along with CISM. If not, see . ! !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #ifdef HAVE_CONFIG_H #include "config.inc" #endif module glint_routing use glimmer_global,only: dp implicit none private public flow_router contains subroutine flow_router(surface,input,output,mask,dx,dy) ! Routes water from input field to its destination, ! according to a surface elevation field. The method used ! is by Quinn et. al. (1991) !NOTE: This subroutine will *not* work for multiple tasks. real(dp),dimension(:,:),intent(in) :: surface ! Surface elevation real(dp),dimension(:,:),intent(in) :: input ! Input water field real(dp),dimension(:,:),intent(out) :: output ! Output water field integer, dimension(:,:),intent(in) :: mask ! Masked points real(dp), intent(in) :: dx ! $x$ grid-length real(dp), intent(in) :: dy ! $y$ grid-length ! Internal variables -------------------------------------- integer :: nx,ny,k,nn,cx,cy,px,py,x,y integer, dimension(:,:),allocatable :: sorted real(dp),dimension(:,:),allocatable :: flats,surfcopy real(dp),dimension(-1:1,-1:1) :: slopes real(dp),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,:)= (/4.d0, 2.d0*dx/dy, 4.d0/) dists(0,:) = (/2.d0*dy/dx, 0.d0, 2.d0*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.d0 ! 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) then continue else ! 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 /= 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 /= 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 glint_routing