! +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! + + ! + glimmer_integrate.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 !> integration of functions using Romberg integration module glimmer_integrate use glimmer_global, only : dp,sp private :: dp, sp !> interface to integration routines interface romberg_int module procedure sromberg_int, sromberg_int_prms, dromberg_int, dromberg_int_prms end interface contains !> single precision function to perform Romberg Integration on function. !! !! The precision of the routine is !! determined by the value of \texttt{ord}, an internal variable. !! !! This routine is an implementation of ACM algorithm 60, by F. L. Bauer. !! (Comm. ACM, vol. 4, issue 6, June 1961). recursive real(sp) function sromberg_int(fct,lgr,rgr) implicit none interface !> function to be integrated function fct(x) use glimmer_global, only : sp implicit none real(sp), intent(in) :: x !< the argument real(sp) :: fct end function fct end interface real(sp),intent(in) :: lgr !< Lower bound real(sp),intent(in) :: rgr !< Upper bound integer,parameter :: ord = 6 real(sp),dimension(ord+1) :: t real(sp) :: l,u,m integer :: f,h,j,n l=rgr-lgr t(1)=(fct(lgr)+fct(rgr))/2.0 n=1 do h=1,ord u=0 m=l/(2*n) do j=1,2*n-1,2 u=u+fct(lgr+j*m) end do t(h+1)=((u/n)+t(h))/2.0 f=1 do j=h,1,-1 f=f*4 t(j)=t(j+1)+(t(j+1)-t(j))/(f-1) end do n=2*n end do sromberg_int=t(1)*l end function sromberg_int !> single precision function to perform Romberg Integration on function. !! !! The precision of the routine is !! determined by the value of \texttt{ord}, an internal variable. !! !! This routine is an implementation of ACM algorithm 60, by F. L. Bauer. !! (Comm. ACM, vol. 4, issue 6, June 1961). recursive real(sp) function sromberg_int_prms(fct,lgr,rgr,params) implicit none interface !> function to be integrated function fct(x,params) use glimmer_global, only : sp implicit none real(sp), intent(in) :: x !< the argument real(sp), intent(in), dimension(:) :: params !< an array of function parameters real(sp) :: fct end function fct end interface real(sp),intent(in) :: lgr !< Lower bound real(sp),intent(in) :: rgr !< Upper bound real(sp),intent(in),dimension(:) :: params !< parameters for function integer,parameter :: ord = 6 real(sp),dimension(ord+1) :: t real(sp) :: l,u,m integer :: f,h,j,n l=rgr-lgr t(1)=(fct(lgr,params)+fct(rgr,params))/2.0 n=1 do h=1,ord u=0 m=l/(2*n) do j=1,2*n-1,2 u=u+fct(lgr+j*m,params) end do t(h+1)=((u/n)+t(h))/2.0 f=1 do j=h,1,-1 f=f*4 t(j)=t(j+1)+(t(j+1)-t(j))/(f-1) end do n=2*n end do sromberg_int_prms=t(1)*l end function sromberg_int_prms !> double precision function to perform Romberg Integration on function. !! !! The precision of the routine is !! determined by the value of \texttt{ord}, an internal variable. !! !! This routine is an implementation of ACM algorithm 60, by F. L. Bauer. !! (Comm. ACM, vol. 4, issue 6, June 1961). recursive real(dp) function dromberg_int(fct,lgr,rgr) implicit none interface !> function to be integrated function fct(x) use glimmer_global, only : dp implicit none real(dp), intent(in) :: x !< the argument real(dp) :: fct end function fct end interface real(dp),intent(in) :: lgr !< Lower bound real(dp),intent(in) :: rgr !< Upper bound integer,parameter :: ord = 6 real(dp),dimension(ord+1) :: t real(dp) :: l,u,m integer :: f,h,j,n l=rgr-lgr t(1)=(fct(lgr)+fct(rgr))/2.0 n=1 do h=1,ord u=0 m=l/(2*n) do j=1,2*n-1,2 u=u+fct(lgr+j*m) end do t(h+1)=((u/n)+t(h))/2.0 f=1 do j=h,1,-1 f=f*4 t(j)=t(j+1)+(t(j+1)-t(j))/(f-1) end do n=2*n end do dromberg_int=t(1)*l end function dromberg_int !> double precision function to perform Romberg Integration on function. !! !! The precision of the routine is !! determined by the value of \texttt{ord}, an internal variable. !! !! This routine is an implementation of ACM algorithm 60, by F. L. Bauer. !! (Comm. ACM, vol. 4, issue 6, June 1961). recursive real(dp) function dromberg_int_prms(fct,lgr,rgr,params) implicit none interface !> the function to be integrated function fct(x,params) use glimmer_global, only : dp implicit none real(dp), intent(in) :: x !< the argument real(dp), intent(in), dimension(:) :: params !< an array of function parameters real(dp) :: fct end function fct end interface real(dp),intent(in) :: lgr !< Lower bound real(dp),intent(in) :: rgr !< Upper bound real(dp),intent(in),dimension(:) :: params !< parameters for function integer,parameter :: ord = 6 real(dp),dimension(ord+1) :: t real(dp) :: l,u,m integer :: f,h,j,n l=rgr-lgr t(1)=(fct(lgr,params)+fct(rgr,params))/2.0 n=1 do h=1,ord u=0 m=l/(2*n) do j=1,2*n-1,2 u=u+fct(lgr+j*m,params) end do t(h+1)=((u/n)+t(h))/2.0 f=1 do j=h,1,-1 f=f*4 t(j)=t(j+1)+(t(j+1)-t(j))/(f-1) end do n=2*n end do dromberg_int_prms=t(1)*l end function dromberg_int_prms end module glimmer_integrate