# 1 "../drifters/cloud_interpolator.F90"
!***********************************************************************
!* GNU Lesser General Public License
!*
!* This file is part of the GFDL Flexible Modeling System (FMS).
!*
!* FMS is free software: you can redistribute it and/or modify it under
!* the terms of the GNU Lesser General Public License as published by
!* the Free Software Foundation, either version 3 of the License, or (at
!* your option) any later version.
!*
!* FMS 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 Lesser General Public
!* License along with FMS. If not, see .
!***********************************************************************
! nf95 -r8 -g -I ~/regression/ia64/23-Jun-2005/CM2.1U_Control-1990_E1.k32pe/include/ -D_TEST_CLOUD_INTERPOLATOR -D_F95 cloud_interpolator.F90
MODULE cloud_interpolator_mod
# 1 "../include/fms_platform.h" 1
! -*-f90-*-*
!***********************************************************************
!* GNU Lesser General Public License
!*
!* This file is part of the GFDL Flexible Modeling System (FMS).
!*
!* FMS is free software: you can redistribute it and/or modify it under
!* the terms of the GNU Lesser General Public License as published by
!* the Free Software Foundation, either version 3 of the License, or (at
!* your option) any later version.
!*
!* FMS 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 Lesser General Public
!* License along with FMS. If not, see .
!***********************************************************************
!Set type kinds.
# 37
!These values are not necessarily portable.
!DEC$ MESSAGE:'Using 8-byte addressing'
!Control "pure" functions.
# 54
!DEC$ MESSAGE:'Using pure routines.'
!Control array members of derived types.
# 66
!DEC$ MESSAGE:'Using allocatable derived type array members.'
!Control use of cray pointers.
# 78
!DEC$ MESSAGE:'Using cray pointers.'
!Control size of integers that will hold address values.
!Appears for legacy reasons, but seems rather dangerous.
# 89
!If you do not want to use 64-bit integers.
# 95
!If you do not want to use 32-bit floats.
# 106
!If you want to use quad-precision.
# 115
# 25 "../drifters/cloud_interpolator.F90" 2
implicit none
private
public :: cld_ntrp_linear_cell_interp, cld_ntrp_locate_cell, cld_ntrp_get_cell_values
public :: cld_ntrp_expand_index, cld_ntrp_contract_indices
! Include variable "version" to be written to log file.
# 1 "../include/file_version.h" 1
! -*-f90-*-
!***********************************************************************
!* GNU Lesser General Public License
!*
!* This file is part of the GFDL Flexible Modeling System (FMS).
!*
!* FMS is free software: you can redistribute it and/or modify it under
!* the terms of the GNU Lesser General Public License as published by
!* the Free Software Foundation, either version 3 of the License, or (at
!* your option) any later version.
!*
!* FMS 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 Lesser General Public
!* License along with FMS. If not, see .
!***********************************************************************
# 23
character(len=*), parameter :: version = 'unknown'
# 33 "../drifters/cloud_interpolator.F90" 2
real, parameter :: tol = 10.0*epsilon(1.)
CONTAINS
!...............................................................................
pure subroutine cld_ntrp_expand_index(Ic, ie, ier)
integer, intent(in) :: Ic ! contacted index
integer, intent(out) :: ie(:) ! expanded list of indices
integer, intent(out) :: ier ! error flag (0=ok)
integer j, nd
ier = 0
nd = size(ie) ! dimension
if(Ic >= 2**nd) then
ie = -1
ier = 1 ! error
return
endif
do j = 1, nd
ie(j) = mod(Ic/2**(j-1), 2)
end do
end subroutine cld_ntrp_expand_index
!...............................................................................
!...............................................................................
pure subroutine cld_ntrp_contract_indices(ie, Ic, ier)
integer, intent(in) :: ie(:) ! expanded list of indices
integer, intent(out) :: Ic ! contacted index
integer, intent(out) :: ier ! error flag (0=ok)
integer j, nd
ier = 0
nd = size(ie) ! dimension
Ic = ie(nd)
do j = nd-1, 1, -1
Ic = Ic * 2
Ic = Ic + ie(j)
end do
if(Ic >= 2**nd) ier = 1
end subroutine cld_ntrp_contract_indices
!...............................................................................
!...............................................................................
pure subroutine cld_ntrp_linear_cell_interp(fvals, ts, f, ier)
real, intent(in) :: fvals(0:) ! values at the cell nodes
real, intent(in) :: ts(:) ! normalized [0,1]^nd cell coordinates
real, intent(out):: f ! interpolated value
integer, intent(out) :: ier ! error flag (0=ok)
integer j, nd, Ic, iflag
integer ie(size(fvals))
real basis
ier = 0
f = 0.
nd = size(ts)
if(size(fvals) /= 2**nd) then
ier = 1
return
endif
do Ic = 0, 2**nd - 1
basis = 1.
call cld_ntrp_expand_index(Ic, ie, iflag)
do j = 1, nd
basis = basis * ( (1.0-real(ie(j)))*(1.0-ts(j)) + real(ie(j))*ts(j) )
end do
f = f + fvals(Ic)*basis
end do
end subroutine cld_ntrp_linear_cell_interp
!...............................................................................
!...............................................................................
pure subroutine cld_ntrp_locate_cell(axis, x, index, ier)
real, intent(in) :: axis(:) ! axis
real, intent(in) :: x ! abscissae
integer, intent(out) :: index ! lower-left corner index
integer, intent(out) :: ier ! error flag (0=ok)
logical down
integer n, index1, is
real axis_1, axis_n, axis_min, axis_max
ier = 0
index = -1
down = .FALSE.
n = size(axis)
if(n < 2) then
ier = 3
return
endif
axis_1 = axis(1)
axis_n = axis(n)
axis_min = axis_1
axis_max = axis_n
if(axis_1 > axis_n) then
down = .TRUE.
axis_min = axis_n
axis_max = axis_1
endif
if(x < axis_min-tol) then
ier = 1
return
endif
if(x > axis_max+tol) then
ier = 2
return
endif
index = floor(real(n-1)*(x - axis_1)/(axis_n-axis_1)) + 1
index = min(n-1, index)
index1 = index+1
if(.NOT. down) then
if(axis(index) <= x+tol) then
if(x <= axis(index1)+tol) then
! axis is uniform, or nearly so. Done!
return
else
! increase index
is = index+1
do index = is, n-1
index1 = index+1
if(axis(index1) >= x-tol) return
enddo
endif
else
! decrease index
is = index - 1
do index = is, 1, -1
if(axis(index) <= x+tol) return
enddo
endif
else
! axis is pointing down
if(axis(index) >= x-tol) then
if(x >= axis(index1)-tol) then
! axis is uniform, or nearly so. Done!
return
else
! increase index
is = index + 1
do index = is, n-1
index1 = index+1
if(axis(index1) <= x+tol) return
enddo
endif
else
! decrease index
is = index - 1
do index = is, 1, -1
if(axis(index) >= x-tol) return
enddo
endif
endif
end subroutine cld_ntrp_locate_cell
!...............................................................................
!...............................................................................
pure subroutine cld_ntrp_get_flat_index(nsizes, indices, flat_index, ier)
integer, intent(in) :: nsizes(:) ! size of array along each axis
integer, intent(in) :: indices(:) ! cell indices
integer, intent(out) :: flat_index ! index into flattened array
integer, intent(out) :: ier ! error flag (0=ok)
integer nd, id
ier = 0
flat_index = -1
nd = size(nsizes)
if(nd /= size(indices)) then
! size mismatch
ier = 1
return
endif
flat_index = indices(nd)-1
do id = nd-1, 1, -1
flat_index = flat_index*nsizes(id) + indices(id)-1
enddo
flat_index = flat_index + 1
end subroutine cld_ntrp_get_flat_index
!...............................................................................
!...............................................................................
pure subroutine cld_ntrp_get_cell_values(nsizes, fnodes, indices, fvals, ier)
integer, intent(in) :: nsizes(:) ! size of fnodes along each axis
real, intent(in) :: fnodes(:) ! flattened array of node values
integer, intent(in) :: indices(:) ! cell indices
real, intent(out) :: fvals(0:) ! returned array values in the cell
integer, intent(out) :: ier ! error flag (0=ok)
integer id, nt, nd, flat_index, Ic, iflag
integer, dimension(size(nsizes)) :: cell_indices, node_indices
ier = 0
fvals = 0.
nd = size(nsizes)
if(nd /= size(indices)) then
! size mismatch
ier = 1
return
endif
if(2**nd > size(fvals)) then
! not enough elements to hold result
ier = 2
return
endif
nt = 1
do id = 1, nd
nt = nt * nsizes(id)
enddo
if(nt /= size(fnodes)) then
! not enough node values
ier = 3
return
endif
do Ic = 0, 2**nd-1
call cld_ntrp_expand_index(Ic, cell_indices, iflag)
node_indices = indices + cell_indices
call cld_ntrp_get_flat_index(nsizes, node_indices, flat_index, iflag)
fvals(Ic) = fnodes(flat_index)
enddo
end subroutine cld_ntrp_get_cell_values
end MODULE cloud_interpolator_mod
!===============================================================================