You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3857 lines
146 KiB
Fortran
3857 lines
146 KiB
Fortran
! INTMODULE contains the modules:
|
|
! - ADAPTMOD
|
|
! - RCRUDEMOD
|
|
! - KROBOVMOD
|
|
! - KRBVRCMOD
|
|
! - DKBVRCMOD
|
|
!
|
|
! which contains several different Multidimensional Integration Subroutines
|
|
!
|
|
! See descriptions below
|
|
!
|
|
* ADAPTMOD is a module containing a:
|
|
*
|
|
* Adaptive Multidimensional Integration Subroutine
|
|
*
|
|
* Author: Alan Genz
|
|
* Department of Mathematics
|
|
* Washington State University
|
|
* Pullman, WA 99164-3113 USA
|
|
*
|
|
* Revised pab 21.11.2000
|
|
* A bug found by Igor in dksmrc: VK was not correctly randomized
|
|
* is now fixed
|
|
* Revised pab 07.10.2000,
|
|
* 1) Removed LENWRK and WORK from input in ADAPT.
|
|
* 2) Defined LENWRK internally and Put a save statement before WORK instead
|
|
* 3) Bug fix in ADBASE: DIVAXN was undetermined when MINCLS<0. Solution:
|
|
* put a save statement on DIVAXN in order to save/keep its last value.
|
|
* 4) MAXDIM is now a global variable defining the maximum number of dimensions
|
|
* it is possible to integrate.
|
|
*
|
|
* revised pab 07.09.2000
|
|
* - solaris compiler complained on the DATA statements
|
|
* for the P and C matrices in the krbvrc and krobov routine
|
|
* => made separate DATA statements for P and C and moved them
|
|
* to right after the variable definitions.
|
|
* revised pab 10.03.2000
|
|
* - updated to f90 (i.e. changed to assumed shape arrays + changing integers to DBLE)
|
|
* - put it into a module
|
|
*
|
|
* This subroutine computes an approximation to the integral
|
|
*
|
|
* 1 1 1
|
|
* I I ... I FUNCTN(NDIM,X) dx(NDIM)...dx(2)dx(1)
|
|
* 0 0 0
|
|
*
|
|
*************** Parameters for SADAPT ********************************
|
|
*
|
|
********Input Parameters
|
|
*
|
|
* N INTEGER, the number of variables.
|
|
* MAXPTS INTEGER, maximum number of function values allowed. This
|
|
* parameter can be used to limit the time taken. A
|
|
* sensible strategy is to start with MAXPTS = 1000*N, and then
|
|
* increase MAXPTS if ERROR is too large.
|
|
* FUNCTN Externally declared real user defined integrand. Its
|
|
* parameters must be (N, Z), where Z is a real array of
|
|
* length N.
|
|
* ABSEPS REAL absolute error tolerance.
|
|
* RELEPS REAL relative error tolerance.
|
|
*
|
|
*******Output Parameters
|
|
*
|
|
* ERROR REAL estimated absolute error, with 99% confidence level.
|
|
* VALUE REAL estimated value for the integral
|
|
* INFORM INTEGER, termination status parameter:
|
|
* if INFORM = 0, normal completion with ERROR < EPS;
|
|
* if INFORM = 1, completion with ERROR > EPS and MAXPTS
|
|
* function vaules used; increase MAXPTS to
|
|
* decrease ERROR;
|
|
* if INFORM = 2, N > 20 or N < 1.
|
|
*
|
|
*************** Parameters for ADAPT ********************************
|
|
*
|
|
****** Input Parameters
|
|
*
|
|
* NDIM Integer number of integration variables.
|
|
* MINCLS Integer minimum number of FUNCTN calls to be allowed; MINCLS
|
|
* must not exceed MAXCLS. If MINCLS < 0, then ADAPT assumes
|
|
* that a previous call of ADAPT has been made with the same
|
|
* integrand and continues that calculation.
|
|
* MAXCLS Integer maximum number of FUNCTN calls to be used; MAXCLS
|
|
* must be >= RULCLS, the number of function calls required for
|
|
* one application of the basic integration rule.
|
|
* IF ( NDIM .EQ. 1 ) THEN
|
|
* RULCLS = 11
|
|
* ELSE IF ( NDIM .LT. 15 ) THEN
|
|
* RULCLS = 2**NDIM + 2*NDIM*(NDIM+3) + 1
|
|
* ELSE
|
|
* RULCLS = 1 + NDIM*(24-NDIM*(6-NDIM*4))/3
|
|
* ENDIF
|
|
* FUNCTN Externally declared real user defined integrand. Its
|
|
* parameters must be (NDIM, Z), where Z is a real array of
|
|
* length NDIM.
|
|
* ABSREQ Real required absolute accuracy.
|
|
* RELREQ Real required relative accuracy.
|
|
*
|
|
****** Output Parameters
|
|
*
|
|
* MINCLS Actual number of FUNCTN calls used by ADAPT.
|
|
* ABSEST Real estimated absolute accuracy.
|
|
* FINEST Real estimated value of integral.
|
|
* INFORM INFORM = 0 for normal exit, when ABSEST <= ABSREQ or
|
|
* ABSEST <= |FINEST|*RELREQ with MINCLS <= MAXCLS.
|
|
* INFORM = 1 if MAXCLS was too small for ADAPT to obtain the
|
|
* result FINEST to within the requested accuracy.
|
|
* INFORM = 2 if MINCLS > MAXCLS, LENWRK < 16*NDIM + 27 or
|
|
* RULCLS > MAXCLS.
|
|
*
|
|
*
|
|
*
|
|
* ADAPT revised by pab 07.10.2000,
|
|
* 1) Removed LENWRK and WORK from input.
|
|
* 2) Defined LENWRK internally and Put a save statement before WORK instead
|
|
*
|
|
* WORK Real array (length LENWRK) of working storage. This contains
|
|
* information that is needed for additional calls of ADAPT
|
|
* using the same integrand (input MINCLS < 0).
|
|
* LENWRK Integer length of real array WORK (working storage); ADAPT
|
|
* needs LENWRK >= 16*NDIM + 27. For maximum efficiency LENWRK
|
|
* should be about 2*NDIM*MAXCLS/RULCLS if MAXCLS FUNCTN
|
|
* calls are needed. If LENWRK is significantly less than this,
|
|
* ADAPT may be less efficient.
|
|
MODULE ADAPTMOD
|
|
IMPLICIT NONE
|
|
INTEGER,PRIVATE, PARAMETER :: MAXDIM=20
|
|
PRIVATE
|
|
PUBLIC :: ADAPT, SADAPT
|
|
|
|
INTERFACE SADAPT
|
|
MODULE PROCEDURE SADAPT
|
|
END INTERFACE
|
|
|
|
INTERFACE ADAPT
|
|
MODULE PROCEDURE ADAPT
|
|
END INTERFACE
|
|
|
|
INTERFACE ADBASE
|
|
MODULE PROCEDURE ADBASE
|
|
END INTERFACE
|
|
|
|
INTERFACE BSINIT
|
|
MODULE PROCEDURE BSINIT
|
|
END INTERFACE
|
|
|
|
INTERFACE RULNRM
|
|
MODULE PROCEDURE RULNRM
|
|
END INTERFACE
|
|
|
|
INTERFACE DIFFER
|
|
MODULE PROCEDURE DIFFER
|
|
END INTERFACE
|
|
|
|
INTERFACE BASRUL
|
|
MODULE PROCEDURE BASRUL
|
|
END INTERFACE
|
|
|
|
INTERFACE FULSUM
|
|
MODULE PROCEDURE FULSUM
|
|
END INTERFACE
|
|
|
|
INTERFACE TRESTR
|
|
MODULE PROCEDURE TRESTR
|
|
END INTERFACE
|
|
!--------------------------------
|
|
CONTAINS
|
|
|
|
!***********************************************************
|
|
! MAIN INTEGRATION ROUTINE SADAPT
|
|
!***********************************************************
|
|
|
|
SUBROUTINE SADAPT(N,MAXPTS,FUNCTN,ABSEPS,
|
|
& RELEPS,ERROR,VALUE,INFORM)
|
|
IMPLICIT NONE
|
|
*
|
|
* A subroutine for computing multivariate integrals
|
|
* This subroutine uses an algorithm given in the paper
|
|
* "Numerical Computation of Multivariate Normal Probabilities", in
|
|
* J. of Computational and Graphical Stat., 1(1992), pp. 141-149, by
|
|
* Alan Genz
|
|
* Department of Mathematics
|
|
* Washington State University
|
|
* Pullman, WA 99164-3113
|
|
* Email : alangenz@wsu.edu
|
|
*
|
|
* revised pab 15.03.2000
|
|
* - changed name from SADMVN to SADAPT
|
|
* - Made it general for any integral not just the multivariate normal integral
|
|
*
|
|
********Input Parameters
|
|
*
|
|
* N INTEGER, the number of variables.
|
|
* MAXPTS INTEGER, maximum number of function values allowed. This
|
|
* parameter can be used to limit the time taken. A
|
|
* sensible strategy is to start with MAXPTS = 1000*N, and then
|
|
* increase MAXPTS if ERROR is too large.
|
|
* FUNCTN Externally declared real user defined integrand. Its
|
|
* parameters must be (N, Z), where Z is a real array of
|
|
* length N.
|
|
* ABSEPS REAL absolute error tolerance.
|
|
* RELEPS REAL relative error tolerance.
|
|
*
|
|
*******Output Parameters
|
|
*
|
|
* ERROR REAL estimated absolute error, with 99% confidence level.
|
|
* VALUE REAL estimated value for the integral
|
|
* INFORM INTEGER, termination status parameter:
|
|
* if INFORM = 0, normal completion with ERROR < EPS;
|
|
* if INFORM = 1, completion with ERROR > EPS and MAXPTS
|
|
* function vaules used; increase MAXPTS to
|
|
* decrease ERROR;
|
|
* if INFORM = 2, N > 20 or N < 1.
|
|
*
|
|
INTEGER, INTENT(IN) :: N, MAXPTS
|
|
INTEGER, INTENT(OUT) :: INFORM
|
|
!INTEGER :: NL, LENWRK,
|
|
INTEGER :: RULCLS, TOTCLS, NEWCLS, MAXCLS
|
|
DOUBLE PRECISION, INTENT(IN) :: ABSEPS, RELEPS
|
|
DOUBLE PRECISION, INTENT(OUT) :: ERROR, VALUE
|
|
DOUBLE PRECISION :: OLDVAL
|
|
!PARAMETER ( NL = 20 )
|
|
!PARAMETER ( LENWRK = 20*NL**2 )
|
|
!DOUBLE PRECISION, DIMENSION(LENWRK) :: WORK
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
IF ( N .GT. MAXDIM .OR. N .LT. 1 ) THEN
|
|
INFORM = 2
|
|
VALUE = 0.d0
|
|
ERROR = 1.d0
|
|
RETURN
|
|
ENDIF
|
|
INFORM = 1
|
|
*
|
|
* Call the subregion adaptive integration subroutine
|
|
*
|
|
RULCLS = 1
|
|
CALL ADAPT( N, RULCLS, 0, FUNCTN, ABSEPS, RELEPS,
|
|
& ERROR, VALUE, INFORM )
|
|
MAXCLS = MIN( 10*RULCLS, MAXPTS )
|
|
TOTCLS = 0
|
|
CALL ADAPT(N, TOTCLS, MAXCLS, FUNCTN, ABSEPS, RELEPS,
|
|
& ERROR, VALUE, INFORM)
|
|
IF ( ERROR .GT. MAX( ABSEPS, RELEPS*ABS(VALUE) ) ) THEN
|
|
10 OLDVAL = VALUE
|
|
MAXCLS = MAX( 2*RULCLS,MIN(INT(3*MAXCLS/2),MAXPTS-TOTCLS))
|
|
NEWCLS = -1
|
|
CALL ADAPT(N, NEWCLS, MAXCLS, FUNCTN, ABSEPS, RELEPS,
|
|
& ERROR, VALUE, INFORM)
|
|
TOTCLS = TOTCLS + NEWCLS
|
|
ERROR = ABS(VALUE-OLDVAL) +
|
|
& SQRT(DBLE(RULCLS)*ERROR**2/DBLE(TOTCLS))
|
|
IF ( ERROR .GT. MAX( ABSEPS, RELEPS*ABS(VALUE) ) ) THEN
|
|
IF ( MAXPTS - TOTCLS .GT. 2*RULCLS ) GO TO 10
|
|
ELSE
|
|
INFORM = 0
|
|
END IF
|
|
ENDIF
|
|
|
|
END SUBROUTINE SADAPT
|
|
|
|
|
|
|
|
!***********************************************************
|
|
! MAIN INTEGRATION ROUTINE ADAPT
|
|
!***********************************************************
|
|
|
|
|
|
SUBROUTINE ADAPT(NDIM, MINCLS, MAXCLS, FUNCTN,
|
|
& ABSREQ, RELREQ, ABSEST, FINEST, INFORM)
|
|
IMPLICIT NONE
|
|
*
|
|
* Adaptive Multidimensional Integration Subroutine
|
|
*
|
|
* Author: Alan Genz
|
|
* Department of Mathematics
|
|
* Washington State University
|
|
* Pullman, WA 99164-3113 USA
|
|
*
|
|
* This subroutine computes an approximation to the integral
|
|
*
|
|
* 1 1 1
|
|
* I I ... I FUNCTN(NDIM,X) dx(NDIM)...dx(2)dx(1)
|
|
* 0 0 0
|
|
*
|
|
*************** Parameters for ADAPT ********************************
|
|
*
|
|
****** Input Parameters
|
|
*
|
|
* NDIM Integer number of integration variables.
|
|
* MINCLS Integer minimum number of FUNCTN calls to be allowed; MINCLS
|
|
* must not exceed MAXCLS. If MINCLS < 0, then ADAPT assumes
|
|
* that a previous call of ADAPT has been made with the same
|
|
* integrand and continues that calculation.
|
|
* MAXCLS Integer maximum number of FUNCTN calls to be used; MAXCLS
|
|
* must be >= RULCLS, the number of function calls required for
|
|
* one application of the basic integration rule.
|
|
* IF ( NDIM .EQ. 1 ) THEN
|
|
* RULCLS = 11
|
|
* ELSE IF ( NDIM .LT. 15 ) THEN
|
|
* RULCLS = 2**NDIM + 2*NDIM*(NDIM+3) + 1
|
|
* ELSE
|
|
* RULCLS = 1 + NDIM*(24-NDIM*(6-NDIM*4))/3
|
|
* ENDIF
|
|
* FUNCTN Externally declared real user defined integrand. Its
|
|
* parameters must be (NDIM, Z), where Z is a real array of
|
|
* length NDIM.
|
|
* ABSREQ Real required absolute accuracy.
|
|
* RELREQ Real required relative accuracy.
|
|
*
|
|
****** Output Parameters
|
|
*
|
|
* MINCLS Actual number of FUNCTN calls used by ADAPT.
|
|
* ABSEST Real estimated absolute accuracy.
|
|
* FINEST Real estimated value of integral.
|
|
* INFORM INFORM = 0 for normal exit, when ABSEST <= ABSREQ or
|
|
* ABSEST <= |FINEST|*RELREQ with MINCLS <= MAXCLS.
|
|
* INFORM = 1 if MAXCLS was too small for ADAPT to obtain the
|
|
* result FINEST to within the requested accuracy.
|
|
* INFORM = 2 if MINCLS > MAXCLS, LENWRK < 16*NDIM + 27 or
|
|
* RULCLS > MAXCLS.
|
|
*
|
|
************************************************************************
|
|
*
|
|
* Begin driver routine. This routine partitions the working storage
|
|
* array and then calls the main subroutine ADBASE.
|
|
*
|
|
* Revised pab 07.10.2000,
|
|
* 1) Removed LENWRK and WORK from input.
|
|
* 2) Defined LENWRK internally and Put a save statement before WORK instead
|
|
*
|
|
* LENWRK Integer length of real array WORK (working storage); ADAPT
|
|
* needs LENWRK >= 16*NDIM + 27. For maximum efficiency LENWRK
|
|
* should be about 2*NDIM*MAXCLS/RULCLS if MAXCLS FUNCTN
|
|
* calls are needed. If LENWRK is significantly less than this,
|
|
* ADAPT may be less efficient.
|
|
*
|
|
* WORK Real array (length LENWRK) of working storage. This contains
|
|
* information that is needed for additional calls of ADAPT
|
|
* using the same integrand (input MINCLS < 0).
|
|
*
|
|
INTEGER, INTENT(IN) :: NDIM, MAXCLS
|
|
INTEGER, INTENT(INOUT) :: MINCLS
|
|
INTEGER, INTENT(OUT) :: INFORM
|
|
DOUBLE PRECISION, INTENT(IN) :: ABSREQ, RELREQ
|
|
DOUBLE PRECISION, INTENT(OUT) :: ABSEST, FINEST
|
|
* Local variables
|
|
INTEGER, PARAMETER :: LENWRK=20*MAXDIM*MAXDIM
|
|
DOUBLE PRECISION, DIMENSION(LENWRK) :: WORK ! length lenwrk
|
|
DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: POINTS,WEGHTS,LUM
|
|
INTEGER :: SBRGNS, MXRGNS, RULCLS, LENRUL,
|
|
& INERRS, INVALS, INPTRS, INLWRS, INUPRS, INMSHS, INPNTS, INWGTS,
|
|
& INLOWR, INUPPR, INWDTH, INMESH, INWORK
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
SAVE WORK
|
|
! print *,'adapt, ndim', ndim
|
|
IF ( NDIM .EQ. 1 ) THEN
|
|
LENRUL = 5
|
|
RULCLS = 9
|
|
ELSE IF ( NDIM .LT. 12 ) THEN
|
|
LENRUL = 6
|
|
RULCLS = 2**NDIM + 2*NDIM*(NDIM+2) + 1
|
|
ELSE
|
|
LENRUL = 6
|
|
! RULCLS = 1 + 2*NDIM*(1+2*NDIM) ! old call pab 15.03.2003
|
|
RULCLS = 1851 + 2*NDIM*(1+2*NDIM)
|
|
ENDIF
|
|
IF ( LENWRK .GE. LENRUL*(NDIM+4) + 10*NDIM + 3 .AND.
|
|
& RULCLS. LE. MAXCLS .AND. MINCLS .LE. MAXCLS ) THEN
|
|
MXRGNS = ( LENWRK - LENRUL*(NDIM+4) - 7*NDIM )/( 3*NDIM + 3 )
|
|
INERRS = 1
|
|
INVALS = INERRS + MXRGNS
|
|
INPTRS = INVALS + MXRGNS
|
|
INLWRS = INPTRS + MXRGNS
|
|
INUPRS = INLWRS + MXRGNS*NDIM
|
|
INMSHS = INUPRS + MXRGNS*NDIM
|
|
INWGTS = INMSHS + MXRGNS*NDIM
|
|
INPNTS = INWGTS + LENRUL*4
|
|
INLOWR = INPNTS + LENRUL*NDIM
|
|
INUPPR = INLOWR + NDIM
|
|
INWDTH = INUPPR + NDIM
|
|
INMESH = INWDTH + NDIM
|
|
INWORK = INMESH + NDIM
|
|
|
|
ALLOCATE(POINTS(NDIM,LENRUL))
|
|
ALLOCATE(WEGHTS(LENRUL,4))
|
|
ALLOCATE(LUM(NDIM,MXRGNS*3))
|
|
|
|
IF (MINCLS .LT. 0 ) THEN
|
|
SBRGNS = WORK(LENWRK)
|
|
LUM = reshape(WORK(INLWRS:INWGTS-1),(/ NDIM,MXRGNS*3/))
|
|
WEGHTS = reshape(WORK(INWGTS:INPNTS-1),(/ LENRUL , 4 /))
|
|
POINTS = reshape(WORK(INPNTS:INLOWR-1),(/ NDIM, LENRUL/))
|
|
!ELSE
|
|
! WORK=0.D0;LUM=0.D0;WEGHTS=0.D0;POINTS=0.D0
|
|
ENDIF
|
|
CALL ADBASE(NDIM, MINCLS, MAXCLS, FUNCTN, ABSREQ, RELREQ,
|
|
& ABSEST, FINEST, SBRGNS, MXRGNS, RULCLS, LENRUL,
|
|
& WORK(INERRS:INVALS-1), WORK(INVALS:INPTRS-1),
|
|
& WORK(INPTRS:INLWRS-1), LUM(:,1:MXRGNS),
|
|
& LUM(:,MXRGNS+1:2*MXRGNS),LUM(:,2*MXRGNS+1:3*MXRGNS),
|
|
& WEGHTS,POINTS,WORK(INLOWR:INUPPR-1),WORK(INUPPR:INWDTH-1),
|
|
& WORK(INWDTH:INMESH-1), WORK(INMESH:INWORK-1),
|
|
& WORK(INWORK:INWORK+2*NDIM-1), INFORM)
|
|
WORK(LENWRK) = SBRGNS
|
|
! LUM = LOWERS UPPERS MESHES
|
|
WORK(INLWRS:INWGTS-1) = reshape(LUM ,(/ NDIM*MXRGNS*3/))
|
|
WORK(INWGTS:INPNTS-1) = reshape(WEGHTS,(/ LENRUL*4 /))
|
|
WORK(INPNTS:INLOWR-1) = reshape(POINTS,(/ NDIM*LENRUL/))
|
|
DEALLOCATE(POINTS)
|
|
DEALLOCATE(WEGHTS)
|
|
DEALLOCATE(LUM)
|
|
ELSE
|
|
INFORM = 2
|
|
MINCLS = RULCLS
|
|
ENDIF
|
|
RETURN
|
|
END SUBROUTINE ADAPT
|
|
SUBROUTINE BSINIT(NDIM, W, LENRUL, G)
|
|
IMPLICIT NONE
|
|
*
|
|
* For initializing basic rule weights and symmetric sum parameters.
|
|
*
|
|
INTEGER, INTENT(IN) :: NDIM, LENRUL
|
|
DOUBLE PRECISION , DIMENSION(:,:), INTENT(OUT) :: W, G
|
|
* DOUBLE PRECISION W(LENRUL,4), G(NDIM,LENRUL)
|
|
* Local variables
|
|
INTEGER :: I, J
|
|
INTEGER, PARAMETER :: NUMNUL=4, SDIM=12
|
|
INTEGER, DIMENSION(6) :: RULPTS
|
|
DOUBLE PRECISION LAM1, LAM2, LAM3, LAM4, LAMP, RULCON
|
|
*
|
|
* The following code determines rule parameters and weights for a
|
|
* degree 7 rule (W(1,1),...,W(5,1)), two degree 5 comparison rules
|
|
* (W(1,2),...,W(5,2) and W(1,3),...,W(5,3)) and a degree 3
|
|
* comparison rule (W(1,4),...W(5,4)).
|
|
*
|
|
* If NDIM = 1, then LENRUL = 5 and total points = 9.
|
|
* If NDIM < SDIM, then LENRUL = 6 and
|
|
* total points = 1+2*NDIM*(NDIM+2)+2**NDIM.
|
|
* If NDIM > = SDIM, then LENRUL = 6 and
|
|
* total points = 1+2*NDIM*(1+2*NDIM).
|
|
*
|
|
! print *,'BSINIT, ndim', ndim
|
|
! DO I = 1,LENRUL
|
|
! DO J = 1,NDIM
|
|
! G(J,I) = 0.d0
|
|
! END DO
|
|
! DO J = 1,NUMNUL
|
|
! W(I,J) = 0.d0
|
|
! END DO
|
|
! END DO
|
|
G = 0.D0
|
|
W = 0.D0
|
|
I = 2*NDIM
|
|
RULPTS(5) = I*(NDIM-1)
|
|
RULPTS(4) = I
|
|
RULPTS(3) = I
|
|
RULPTS(2) = I
|
|
RULPTS(1) = 1
|
|
LAMP = 0.85d0
|
|
LAM3 = 0.4707d0
|
|
LAM2 = 4d0/(15.d0 - 5.d0/LAM3)
|
|
LAM4 = 1.D0/(27.D0*LAM3*LAM3*LAM3)
|
|
W(5,1) = ( 3.d0 - 5.d0*LAM3 )/( 180.d0*(LAM2-LAM3)*LAM2*LAM2)
|
|
IF ( NDIM .LT. SDIM ) THEN
|
|
RULPTS(LENRUL) = 2**NDIM
|
|
LAM1 = 8.d0*LAM3*(31.d0*LAM3-15.d0)/
|
|
& ( (3.d0*LAM3-1.d0)*(5.d0*LAM3-3.d0)*35.d0 )
|
|
W(LENRUL,1) = LAM4/DBLE(RULPTS(LENRUL))
|
|
ELSE
|
|
LAM1 = ( LAM3*(15.d0 - 21.d0*LAM2) +
|
|
& 35.d0*DBLE(NDIM-1)*(LAM2-LAM3)/9.d0 )
|
|
& / ( LAM3*(21.d0 - 35.d0*LAM2) +
|
|
& 35.d0*DBLE(NDIM-1)*(LAM2/LAM3-1.d0)/9.d0 )
|
|
W(6,1) = LAM4*0.25D0
|
|
RULPTS(6) = 2*NDIM*(NDIM-1)
|
|
ENDIF
|
|
W(3,1) = ( 15.d0 - 21.d0*(LAM3+LAM1) + 35.d0*LAM3*LAM1 )
|
|
& /(210.d0*LAM2*(LAM2-LAM3)*(LAM2-LAM1))-DBLE(2*(NDIM-1))*W(5,1)
|
|
W(2,1) = ( 15.d0 - 21.d0*(LAM3+LAM2) + 35.d0*LAM3*LAM2 )
|
|
& /( 210.d0*LAM1*(LAM1-LAM3)*(LAM1-LAM2) )
|
|
LAM3 = SQRT(LAM3)
|
|
IF ( NDIM .LT. SDIM ) THEN
|
|
G(1:NDIM,LENRUL) = LAM3
|
|
ELSE
|
|
G(1,6) = LAM3
|
|
G(2,6) = LAM3
|
|
ENDIF
|
|
IF ( NDIM .GT. 1 ) THEN
|
|
W(5,2) = 1.d0/(6.d0*LAM2)**2
|
|
W(5,3) = W(5,2)
|
|
ENDIF
|
|
W(3,2) = ( 3.d0 - 5.d0*LAM1 )/( 30.d0*LAM2*(LAM2-LAM1) )
|
|
& - DBLE(2*(NDIM-1))*W(5,2)
|
|
W(2,2) = ( 3.d0 - 5.d0*LAM2 )/( 30.d0*LAM1*(LAM1-LAM2) )
|
|
W(4,3) = ( 3.d0 - 5.d0*LAM2 )/( 30.d0*LAMP*(LAMP-LAM2) )
|
|
W(3,3) = ( 3.d0 - 5.d0*LAMP )/( 30.d0*LAM2*(LAM2-LAMP) )
|
|
& - DBLE(2*(NDIM-1))*W(5,3)
|
|
W(2,4) = 1.d0/(6.d0*LAM1)
|
|
LAMP = SQRT(LAMP)
|
|
LAM2 = SQRT(LAM2)
|
|
LAM1 = SQRT(LAM1)
|
|
G(1,2) = LAM1
|
|
G(1,3) = LAM2
|
|
G(1,4) = LAMP
|
|
IF ( NDIM .GT. 1 ) THEN
|
|
G(1,5) = LAM2
|
|
G(2,5) = LAM2
|
|
ENDIF
|
|
DO J = 1, NUMNUL
|
|
W(1,J) = 1.d0
|
|
DO I = 2,LENRUL
|
|
W(1,J) = W(1,J) - DBLE(RULPTS(I))*W(I,J)
|
|
END DO
|
|
END DO
|
|
RULCON = 0.5d0
|
|
CALL RULNRM( LENRUL, NUMNUL, RULPTS, W, RULCON )
|
|
END SUBROUTINE BSINIT
|
|
!
|
|
!
|
|
SUBROUTINE RULNRM( LENRUL, NUMNUL, RULPTS, W, RULCON )
|
|
IMPLICIT NONE
|
|
INTEGER, INTENT(IN) :: LENRUL, NUMNUL
|
|
INTEGER, DIMENSION(:), INTENT(IN) :: RULPTS
|
|
DOUBLE PRECISION, DIMENSION(:,:), INTENT(INOUT) :: W !(LENRUL, *),
|
|
DOUBLE PRECISION, INTENT(IN) :: RULCON
|
|
* Local variables
|
|
INTEGER :: I, J, K
|
|
DOUBLE PRECISION :: ALPHA, NORMCF, NORMNL
|
|
|
|
*
|
|
* Compute orthonormalized null rules.
|
|
*
|
|
! print *,'RULNRM, lenrul, numnul', lenrul,NUMNUL
|
|
NORMCF = 0.d0
|
|
DO I = 1,LENRUL
|
|
NORMCF = NORMCF + DBLE(RULPTS(I))*W(I,1)*W(I,1)
|
|
END DO
|
|
DO K = 2,NUMNUL
|
|
DO I = 1,LENRUL
|
|
W(I,K) = W(I,K) - W(I,1)
|
|
END DO
|
|
DO J = 2,K-1
|
|
ALPHA = 0.d0
|
|
DO I = 1,LENRUL
|
|
ALPHA = ALPHA + DBLE(RULPTS(I))*W(I,J)*W(I,K)
|
|
END DO
|
|
ALPHA = -ALPHA/NORMCF
|
|
DO I = 1,LENRUL
|
|
W(I,K) = W(I,K) + ALPHA*W(I,J)
|
|
END DO
|
|
END DO
|
|
NORMNL = 0.d0
|
|
DO I = 1,LENRUL
|
|
NORMNL = NORMNL + DBLE(RULPTS(I))*W(I,K)*W(I,K)
|
|
END DO
|
|
ALPHA = SQRT(NORMCF/NORMNL)
|
|
DO I = 1,LENRUL
|
|
W(I,K) = ALPHA*W(I,K)
|
|
END DO
|
|
END DO
|
|
DO J = 2, NUMNUL
|
|
DO I = 1,LENRUL
|
|
W(I,J) = W(I,J)*RULCON
|
|
END DO
|
|
END DO
|
|
RETURN
|
|
END SUBROUTINE RULNRM
|
|
!
|
|
!
|
|
SUBROUTINE ADBASE(NDIM, MINCLS, MAXCLS, FUNCTN, ABSREQ, RELREQ,
|
|
& ABSEST, FINEST, SBRGNS, MXRGNS, RULCLS, LENRUL,
|
|
& ERRORS, VALUES, PONTRS, LOWERS,
|
|
& UPPERS, MESHES, WEGHTS, POINTS,
|
|
& LOWER, UPPER, WIDTH, MESH, WORK, INFORM)
|
|
IMPLICIT NONE
|
|
*
|
|
* Main adaptive integration subroutine
|
|
*
|
|
INTEGER,INTENT(IN) :: NDIM, MAXCLS, MXRGNS,LENRUL, RULCLS
|
|
INTEGER, INTENT(INOUT) :: MINCLS, SBRGNS
|
|
INTEGER, INTENT(OUT) :: INFORM
|
|
DOUBLE PRECISION, INTENT(IN) :: ABSREQ, RELREQ
|
|
DOUBLE PRECISION, INTENT(OUT) :: ABSEST, FINEST
|
|
DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: ERRORS, VALUES,
|
|
& PONTRS, LOWER, UPPER, WIDTH, MESH, WORK
|
|
DOUBLE PRECISION, DIMENSION(:,:), INTENT(INOUT) :: WEGHTS, POINTS
|
|
! shape (LENRUL,4) and (NDIM,LENRUL)
|
|
DOUBLE PRECISION, DIMENSION(:,:), INTENT(INOUT) :: LOWERS, UPPERS,
|
|
& MESHES !SHAPE (NDIM,MXRGNS),
|
|
INTEGER :: I, J,NWRGNS, DIVAXN, TOP, RGNCLS, FUNCLS, DIFCLS
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
*
|
|
* Initialization of subroutine
|
|
*
|
|
! print *,'ADBASE, ndim', ndim, shape(POINTS)
|
|
SAVE DIVAXN ! added pab 07.11.2000 (divaxn may have negative values otherwise)
|
|
INFORM = 2
|
|
FUNCLS = 0
|
|
CALL BSINIT(NDIM, WEGHTS, LENRUL, POINTS)
|
|
IF ( MINCLS .GE. 0) THEN
|
|
*
|
|
* When MINCLS >= 0 determine initial subdivision of the
|
|
* integration region and apply basic rule to each subregion.
|
|
*
|
|
SBRGNS = 0
|
|
DO I = 1,NDIM
|
|
LOWER(I) = 0.d0
|
|
MESH(I) = 1.d0
|
|
WIDTH(I) = 1.d0/(2.d0*MESH(I))
|
|
UPPER(I) = 1.d0
|
|
END DO
|
|
DIVAXN = 0
|
|
RGNCLS = RULCLS
|
|
NWRGNS = 1
|
|
10 CONTINUE
|
|
!IF (abs(DIVAXN).GT.NDIM) PRINT *,'adbase DIVAXN1',DIVAXN
|
|
CALL DIFFER(NDIM, LOWER, UPPER, WIDTH, WORK(1:NDIM),
|
|
& WORK(NDIM+1:2*NDIM), FUNCTN, DIVAXN, DIFCLS)
|
|
FUNCLS = FUNCLS + DIFCLS
|
|
IF (DBLE(RGNCLS)*(MESH(DIVAXN)+1.d0)/MESH(DIVAXN)
|
|
& .LE. DBLE(MINCLS-FUNCLS) ) THEN
|
|
RGNCLS = NINT(DBLE(RGNCLS)*(MESH(DIVAXN)+1.d0)/MESH(DIVAXN))
|
|
NWRGNS = NINT(DBLE(NWRGNS)*(MESH(DIVAXN)+1.d0)/MESH(DIVAXN))
|
|
MESH(DIVAXN) = MESH(DIVAXN) + 1.d0
|
|
WIDTH(DIVAXN) = 1.d0/( 2.d0*MESH(DIVAXN) )
|
|
GO TO 10
|
|
ENDIF
|
|
IF ( NWRGNS .LE. MXRGNS ) THEN
|
|
DO I = 1,NDIM
|
|
UPPER(I) = LOWER(I) + 2.d0*WIDTH(I)
|
|
MESH(I) = 1.d0
|
|
END DO
|
|
ENDIF
|
|
*
|
|
* Apply basic rule to subregions and store results in heap.
|
|
*
|
|
20 SBRGNS = SBRGNS + 1
|
|
CALL BASRUL(NDIM, LOWER, UPPER, WIDTH, FUNCTN,
|
|
& WEGHTS, LENRUL, POINTS, WORK(1:NDIM), WORK(NDIM+1:2*NDIM),
|
|
& ERRORS(SBRGNS),VALUES(SBRGNS))
|
|
CALL TRESTR(SBRGNS, SBRGNS, PONTRS, ERRORS)
|
|
DO I = 1,NDIM
|
|
LOWERS(I,SBRGNS) = LOWER(I)
|
|
UPPERS(I,SBRGNS) = UPPER(I)
|
|
MESHES(I,SBRGNS) = MESH(I)
|
|
END DO
|
|
DO I = 1,NDIM
|
|
LOWER(I) = UPPER(I)
|
|
UPPER(I) = LOWER(I) + 2.d0*WIDTH(I)
|
|
IF (LOWER(I)+WIDTH(I) .LT. 1.D0) GO TO 20
|
|
LOWER(I) = 0.d0
|
|
UPPER(I) = LOWER(I) + 2.d0*WIDTH(I)
|
|
END DO
|
|
FUNCLS = FUNCLS + SBRGNS*RULCLS
|
|
ENDIF
|
|
*
|
|
* Check for termination
|
|
*
|
|
30 FINEST = 0.d0
|
|
ABSEST = 0.d0
|
|
DO I = 1, SBRGNS
|
|
FINEST = FINEST + VALUES(I)
|
|
ABSEST = ABSEST + ERRORS(I)
|
|
END DO
|
|
IF ( ABSEST .GT. MAX( ABSREQ, RELREQ*ABS(FINEST) )
|
|
& .OR. FUNCLS .LT. MINCLS ) THEN
|
|
*
|
|
* Prepare to apply basic rule in (parts of) subregion with
|
|
* largest error.
|
|
*
|
|
TOP = PONTRS(1)
|
|
RGNCLS = RULCLS
|
|
DO I = 1,NDIM
|
|
LOWER(I) = LOWERS(I,TOP)
|
|
UPPER(I) = UPPERS(I,TOP)
|
|
MESH(I) = MESHES(I,TOP)
|
|
WIDTH(I) = (UPPER(I)-LOWER(I))/(2.D0*MESH(I))
|
|
RGNCLS = NINT(DBLE(RGNCLS)*MESH(I))
|
|
END DO
|
|
!IF (abs(DIVAXN).GT.NDIM) PRINT *,'adbase DIVAXN2',DIVAXN
|
|
CALL DIFFER(NDIM, LOWER, UPPER, WIDTH, WORK(1:NDIM),
|
|
& WORK(NDIM+1:2*NDIM), FUNCTN, DIVAXN, DIFCLS)
|
|
FUNCLS = FUNCLS + DIFCLS
|
|
RGNCLS = NINT(DBLE(RGNCLS)*(MESH(DIVAXN)+1.D0))/MESH(DIVAXN)
|
|
IF ( FUNCLS + RGNCLS .LE. MAXCLS ) THEN
|
|
IF ( SBRGNS + 1 .LE. MXRGNS ) THEN
|
|
*
|
|
* Prepare to subdivide into two pieces.
|
|
*
|
|
NWRGNS = 1
|
|
WIDTH(DIVAXN) = 0.5d0*WIDTH(DIVAXN)
|
|
ELSE
|
|
NWRGNS = 0
|
|
WIDTH(DIVAXN) = WIDTH(DIVAXN)
|
|
& *MESH(DIVAXN)/( MESH(DIVAXN) + 1.d0 )
|
|
MESHES(DIVAXN,TOP) = MESH(DIVAXN) + 1.d0
|
|
ENDIF
|
|
IF ( NWRGNS .GT. 0 ) THEN
|
|
*
|
|
* Only allow local subdivision when space is available.
|
|
*
|
|
DO J = SBRGNS+1,SBRGNS+NWRGNS
|
|
DO I = 1,NDIM
|
|
LOWERS(I,J) = LOWER(I)
|
|
UPPERS(I,J) = UPPER(I)
|
|
MESHES(I,J) = MESH(I)
|
|
END DO
|
|
END DO
|
|
UPPERS(DIVAXN,TOP) = LOWER(DIVAXN) + 2.d0*WIDTH(DIVAXN)
|
|
LOWERS(DIVAXN,SBRGNS+1) = UPPERS(DIVAXN,TOP)
|
|
ENDIF
|
|
FUNCLS = FUNCLS + RGNCLS
|
|
CALL BASRUL(NDIM, LOWERS(:,TOP), UPPERS(:,TOP), WIDTH,
|
|
& FUNCTN, WEGHTS, LENRUL, POINTS, WORK(1:NDIM),
|
|
& WORK(NDIM+1:2*NDIM),ERRORS(TOP), VALUES(TOP))
|
|
CALL TRESTR(TOP, SBRGNS, PONTRS, ERRORS)
|
|
DO I = SBRGNS+1, SBRGNS+NWRGNS
|
|
*
|
|
* Apply basic rule and store results in heap.
|
|
*
|
|
CALL BASRUL(NDIM, LOWERS(:,I), UPPERS(:,I), WIDTH,
|
|
& FUNCTN, WEGHTS, LENRUL, POINTS, WORK(1:NDIM),
|
|
& WORK(NDIM+1:2*NDIM),ERRORS(I), VALUES(I))
|
|
CALL TRESTR(I, I, PONTRS, ERRORS)
|
|
END DO
|
|
SBRGNS = SBRGNS + NWRGNS
|
|
GO TO 30
|
|
ELSE
|
|
INFORM = 1
|
|
ENDIF
|
|
ELSE
|
|
INFORM = 0
|
|
ENDIF
|
|
MINCLS = FUNCLS
|
|
RETURN
|
|
END SUBROUTINE ADBASE
|
|
SUBROUTINE BASRUL( NDIM, A, B, WIDTH, FUNCTN, W, LENRUL, G,
|
|
& CENTER, Z, RGNERT, BASEST )
|
|
IMPLICIT NONE
|
|
*
|
|
* For application of basic integration rule
|
|
*
|
|
INTEGER, INTENT(IN) :: LENRUL, NDIM
|
|
DOUBLE PRECISION, DIMENSION(: ), INTENT(IN) :: A, B, WIDTH !(NDIM)
|
|
DOUBLE PRECISION, DIMENSION(:,:), INTENT(IN) :: W !(LENRUL,4),
|
|
DOUBLE PRECISION, DIMENSION(:,:), INTENT(INOUT) :: G !(NDIM,LENRUL),
|
|
DOUBLE PRECISION, DIMENSION(: ), INTENT(INOUT) :: CENTER, Z !(NDIM)
|
|
DOUBLE PRECISION, INTENT(OUT) :: RGNERT, BASEST
|
|
INTEGER :: I
|
|
DOUBLE PRECISION :: FSYMSM, RGNCMP, RGNVAL,
|
|
& RGNVOL, RGNCPT, RGNERR
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
*
|
|
* Compute Volume and Center of Subregion
|
|
*
|
|
! print *,'BASRULE, ndim', ndim
|
|
RGNVOL = 1.d0
|
|
DO I = 1,NDIM
|
|
RGNVOL = 2.d0*RGNVOL*WIDTH(I)
|
|
CENTER(I) = A(I) + WIDTH(I)
|
|
END DO
|
|
BASEST = 0.d0
|
|
RGNERT = 0.d0
|
|
*
|
|
* Compute basic rule and error
|
|
*
|
|
10 RGNVAL = 0.d0
|
|
RGNERR = 0.d0
|
|
RGNCMP = 0.d0
|
|
RGNCPT = 0.d0
|
|
DO I = 1,LENRUL
|
|
FSYMSM = FULSUM(NDIM, CENTER, WIDTH, Z, G(:,I), FUNCTN)
|
|
* Basic Rule
|
|
RGNVAL = RGNVAL + W(I,1)*FSYMSM
|
|
* First comparison rule
|
|
RGNERR = RGNERR + W(I,2)*FSYMSM
|
|
* Second comparison rule
|
|
RGNCMP = RGNCMP + W(I,3)*FSYMSM
|
|
* Third Comparison rule
|
|
RGNCPT = RGNCPT + W(I,4)*FSYMSM
|
|
END DO
|
|
*
|
|
* Error estimation
|
|
*
|
|
RGNERR = SQRT(RGNCMP*RGNCMP + RGNERR*RGNERR)
|
|
RGNCMP = SQRT(RGNCPT*RGNCPT + RGNCMP*RGNCMP)
|
|
IF ( 4.d0*RGNERR .LT. RGNCMP ) RGNERR = 0.5d0*RGNERR
|
|
IF ( 2.d0*RGNERR .GT. RGNCMP ) RGNERR = MAX( RGNERR, RGNCMP )
|
|
RGNERT = RGNERT + RGNVOL*RGNERR
|
|
BASEST = BASEST + RGNVOL*RGNVAL
|
|
*
|
|
* When subregion has more than one piece, determine next piece and
|
|
* loop back to apply basic rule.
|
|
*
|
|
DO I = 1,NDIM
|
|
CENTER(I) = CENTER(I) + 2.d0*WIDTH(I)
|
|
IF ( CENTER(I) .LT. B(I) ) GO TO 10
|
|
CENTER(I) = A(I) + WIDTH(I)
|
|
END DO
|
|
RETURN
|
|
END SUBROUTINE BASRUL
|
|
DOUBLE PRECISION FUNCTION FULSUM(S, CENTER, HWIDTH, X, G, F)
|
|
IMPLICIT NONE
|
|
*
|
|
**** To compute fully symmetric basic rule sum
|
|
*
|
|
INTEGER, INTENT(IN) :: S
|
|
DOUBLE PRECISION, DIMENSION(:), INTENT(IN) :: CENTER, HWIDTH
|
|
DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: X, G ! shape S
|
|
INTEGER :: IXCHNG, LXCHNG, I, L
|
|
DOUBLE PRECISION :: INTSUM, GL, GI
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION F(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION F
|
|
END INTERFACE
|
|
! print *,'FULSUM, S', S, shape(X)
|
|
FULSUM = 0.d0
|
|
*
|
|
* Compute centrally symmetric sum for permutation of G
|
|
*
|
|
10 INTSUM = 0.d0
|
|
!DO I = 1,S
|
|
! X(I) = CENTER(I) + G(I)*HWIDTH(I)
|
|
!END DO
|
|
X = CENTER + G*HWIDTH
|
|
20 INTSUM = INTSUM + F(S,X)
|
|
DO I = 1,S
|
|
G(I) = -G(I)
|
|
X(I) = CENTER(I) + G(I)*HWIDTH(I)
|
|
IF ( G(I) .LT. 0.d0 ) GO TO 20
|
|
END DO
|
|
FULSUM = FULSUM + INTSUM
|
|
*
|
|
* Find next distinct permuation of G and loop back for next sum
|
|
*
|
|
DO I = 2,S
|
|
IF ( G(I-1) .GT. G(I) ) THEN
|
|
GI = G(I)
|
|
IXCHNG = I - 1
|
|
DO L = 1,(I-1)/2
|
|
GL = G(L)
|
|
G(L) = G(I-L)
|
|
G(I-L) = GL
|
|
IF ( GL .LE. GI ) IXCHNG = IXCHNG - 1
|
|
IF ( G(L) .GT. GI ) LXCHNG = L
|
|
END DO
|
|
IF ( G(IXCHNG) .LE. GI ) IXCHNG = LXCHNG
|
|
G(I) = G(IXCHNG)
|
|
G(IXCHNG) = GI
|
|
GO TO 10
|
|
ENDIF
|
|
END DO
|
|
*
|
|
* End loop for permutations of G and associated sums
|
|
*
|
|
* Restore original order to G's
|
|
*
|
|
DO I = 1,S/2
|
|
GI = G(I)
|
|
G(I) = G(S+1-I)
|
|
G(S+1-I) = GI
|
|
END DO
|
|
RETURN
|
|
END FUNCTION FULSUM
|
|
SUBROUTINE DIFFER(NDIM, A, B, WIDTH, Z, DIF, FUNCTN,
|
|
& DIVAXN, DIFCLS)
|
|
IMPLICIT NONE
|
|
*
|
|
* Compute fourth differences and subdivision axes
|
|
*
|
|
INTEGER, INTENT(IN) :: NDIM
|
|
INTEGER, INTENT(INOUT) :: DIVAXN
|
|
INTEGER, INTENT(OUT) :: DIFCLS
|
|
DOUBLE PRECISION, DIMENSION(:), INTENT(IN) :: A, B, WIDTH ! (NDIM)
|
|
DOUBLE PRECISION, DIMENSION(:),INTENT(OUT) :: Z, DIF ! (NDIM)
|
|
DOUBLE PRECISION :: FRTHDF, FUNCEN, WIDTHI
|
|
INTEGER :: I
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
! print *,'DIFFER, ndim', ndim, shape(Z)
|
|
DIFCLS = 0
|
|
! IF (abs(DIVAXN).GT.NDIM) PRINT *,'DIFFER DIVAXN1',DIVAXN
|
|
|
|
DIVAXN = MOD(DIVAXN, NDIM ) + 1
|
|
!print *,'DIFFER, divaxn2', divaxn
|
|
IF ( NDIM .GT. 1 ) THEN
|
|
!DO I = 1,NDIM
|
|
! DIF(I) = 0.d0
|
|
! Z(I) = A(I) + WIDTH(I)
|
|
!END DO
|
|
DIF = 0.D0
|
|
Z(1:NDIM) = A(1:NDIM) + WIDTH(1:NDIM)
|
|
! print *,'Z', Z
|
|
10 FUNCEN = FUNCTN(NDIM, Z)
|
|
DO I = 1,NDIM
|
|
WIDTHI = 0.2d0*WIDTH(I)
|
|
FRTHDF = 6.d0*FUNCEN
|
|
Z(I) = Z(I) - 4.d0*WIDTHI
|
|
FRTHDF = FRTHDF + FUNCTN(NDIM,Z)
|
|
Z(I) = Z(I) + 2.d0*WIDTHI
|
|
FRTHDF = FRTHDF - 4.d0*FUNCTN(NDIM,Z)
|
|
Z(I) = Z(I) + 4.d0*WIDTHI
|
|
FRTHDF = FRTHDF - 4.d0*FUNCTN(NDIM,Z)
|
|
Z(I) = Z(I) + 2.d0*WIDTHI
|
|
FRTHDF = FRTHDF + FUNCTN(NDIM,Z)
|
|
* Do not include differences below roundoff
|
|
! IF ( FUNCEN + FRTHDF/8.d0 .NE. FUNCEN )
|
|
IF ( FUNCEN + FRTHDF*0.125D0 .NE. FUNCEN )
|
|
& DIF(I) = DIF(I) + ABS(FRTHDF)*WIDTH(I)
|
|
Z(I) = Z(I) - 4.d0*WIDTHI
|
|
END DO
|
|
DIFCLS = DIFCLS + 4*NDIM + 1
|
|
DO I = 1,NDIM
|
|
Z(I) = Z(I) + 2.D0*WIDTH(I)
|
|
IF ( Z(I) .LT. B(I) ) GO TO 10
|
|
Z(I) = A(I) + WIDTH(I)
|
|
END DO
|
|
!IF (abs(DIVAXN).GT.NDIM) PRINT *,'DIFFER DIVAXN',DIVAXN,shape(dif),ndim
|
|
DO I = 1,NDIM
|
|
IF ( DIF(DIVAXN) .LT. DIF(I) ) DIVAXN = I
|
|
END DO
|
|
ENDIF
|
|
RETURN
|
|
END SUBROUTINE DIFFER
|
|
SUBROUTINE TRESTR(POINTR, SBRGNS, PONTRS, RGNERS)
|
|
IMPLICIT NONE
|
|
****BEGIN PROLOGUE TRESTR
|
|
****PURPOSE TRESTR maintains a heap for subregions.
|
|
****DESCRIPTION TRESTR maintains a heap for subregions.
|
|
* The subregions are ordered according to the size of the
|
|
* greatest error estimates of each subregion (RGNERS).
|
|
*
|
|
* PARAMETERS
|
|
*
|
|
* POINTR Integer.
|
|
* The index for the subregion to be inserted in the heap.
|
|
* SBRGNS Integer.
|
|
* Number of subregions in the heap.
|
|
* PONTRS Real array of dimension SBRGNS.
|
|
* Used to store the indices for the greatest estimated errors
|
|
* for each subregion.
|
|
* RGNERS Real array of dimension SBRGNS.
|
|
* Used to store the greatest estimated errors for each
|
|
* subregion.
|
|
*
|
|
****ROUTINES CALLED NONE
|
|
****END PROLOGUE TRESTR
|
|
*
|
|
* Global variables.
|
|
*
|
|
INTEGER, INTENT(IN) ::POINTR, SBRGNS
|
|
DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: PONTRS
|
|
DOUBLE PRECISION, DIMENSION(:), INTENT(IN) :: RGNERS
|
|
*
|
|
* Local variables.
|
|
*
|
|
* RGNERR Intermediate storage for the greatest error of a subregion.
|
|
* SUBRGN Position of child/parent subregion in the heap.
|
|
* SUBTMP Position of parent/child subregion in the heap.
|
|
*
|
|
INTEGER SUBRGN, SUBTMP
|
|
DOUBLE PRECISION RGNERR
|
|
*
|
|
****FIRST PROCESSING STATEMENT TRESTR
|
|
*
|
|
! print *,'TRESTR'
|
|
RGNERR = RGNERS(POINTR)
|
|
IF ( POINTR.EQ.NINT(PONTRS(1))) THEN
|
|
*
|
|
* Move the new subregion inserted at the top of the heap
|
|
* to its correct position in the heap.
|
|
*
|
|
SUBRGN = 1
|
|
10 SUBTMP = 2*SUBRGN
|
|
IF ( SUBTMP .LE. SBRGNS ) THEN
|
|
IF ( SUBTMP .NE. SBRGNS ) THEN
|
|
*
|
|
* Find maximum of left and right child.
|
|
*
|
|
IF ( RGNERS(NINT(PONTRS(SUBTMP))) .LT.
|
|
& RGNERS(NINT(PONTRS(SUBTMP+1))) ) SUBTMP = SUBTMP + 1
|
|
ENDIF
|
|
*
|
|
* Compare maximum child with parent.
|
|
* If parent is maximum, then done.
|
|
*
|
|
IF ( RGNERR .LT. RGNERS(NINT(PONTRS(SUBTMP))) ) THEN
|
|
*
|
|
* Move the pointer at position subtmp up the heap.
|
|
*
|
|
PONTRS(SUBRGN) = PONTRS(SUBTMP)
|
|
SUBRGN = SUBTMP
|
|
GO TO 10
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
*
|
|
* Insert new subregion in the heap.
|
|
*
|
|
SUBRGN = SBRGNS
|
|
20 SUBTMP = SUBRGN/2
|
|
IF ( SUBTMP .GE. 1 ) THEN
|
|
*
|
|
* Compare child with parent. If parent is maximum, then done.
|
|
*
|
|
IF ( RGNERR .GT. RGNERS(NINT(PONTRS(SUBTMP))) ) THEN
|
|
*
|
|
* Move the pointer at position subtmp down the heap.
|
|
*
|
|
PONTRS(SUBRGN) = PONTRS(SUBTMP)
|
|
SUBRGN = SUBTMP
|
|
GO TO 20
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
PONTRS(SUBRGN) = DBLE(POINTR)
|
|
*
|
|
****END TRESTR
|
|
*
|
|
RETURN
|
|
END SUBROUTINE TRESTR
|
|
END MODULE ADAPTMOD
|
|
|
|
|
|
|
|
* RCRUDEMOD is a module containing two:
|
|
*
|
|
* Automatic Multidimensional Integration Subroutines
|
|
*
|
|
* AUTHOR: Alan Genz
|
|
* Department of Mathematics
|
|
* Washington State University
|
|
* Pulman, WA 99164-3113
|
|
* Email: AlanGenz@wsu.edu
|
|
*
|
|
* Last Change: 5/15/98
|
|
* revised pab 10.03.2000
|
|
* - updated to f90 (i.e. changed to assumed shape arrays + changing integers to DBLE)
|
|
* - put it into a module
|
|
* - added ranlhmc
|
|
*
|
|
* RCRUDEMOD computes an approximation to the integral
|
|
*
|
|
* 1 1 1
|
|
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
|
|
* 0 0 0
|
|
! References:
|
|
! Alan Genz (1992)
|
|
! 'Numerical Computation of Multivariate Normal Probabilites'
|
|
! J. computational Graphical Statistics, Vol.1, pp 141--149 (RANMC)
|
|
!
|
|
! William H. Press, Saul Teukolsky,
|
|
! William T. Wetterling and Brian P. Flannery (1997)
|
|
! "Numerical recipes in Fortran 77", Vol. 1, pp 55-63 (SVDCMP,PYTHAG)
|
|
!
|
|
! Donald E. Knuth (1973) "The art of computer programming,",
|
|
! Vol. 3, pp 84- (sorting and searching) (SORTRE)
|
|
|
|
|
|
! You may initialize the random generator before you
|
|
! call RANLHMC or RANMC by the following lines:
|
|
!
|
|
! call random_seed(SIZE=seed_size)
|
|
! allocate(seed(seed_size))
|
|
! call random_seed(GET=seed(1:seed_size)) ! get current seed
|
|
! seed(1)=seed1 ! change seed
|
|
! call random_seed(PUT=seed(1:seed_size))
|
|
! deallocate(seed)
|
|
|
|
|
|
|
|
MODULE RCRUDEMOD
|
|
IMPLICIT NONE
|
|
PRIVATE
|
|
PUBLIC :: RANMC
|
|
INTEGER :: NDIMMAX
|
|
|
|
INTERFACE RANMC
|
|
MODULE PROCEDURE RANMC
|
|
END INTERFACE
|
|
|
|
INTERFACE RCRUDE
|
|
MODULE PROCEDURE RCRUDE
|
|
END INTERFACE
|
|
|
|
INTERFACE SVDCMP
|
|
MODULE PROCEDURE SVDCMP
|
|
END INTERFACE
|
|
|
|
INTERFACE PYTHAG
|
|
MODULE PROCEDURE PYTHAG
|
|
END INTERFACE
|
|
|
|
INTERFACE SPEARCORR
|
|
MODULE PROCEDURE SPEARCORR
|
|
END INTERFACE
|
|
|
|
INTERFACE SORTRE
|
|
MODULE PROCEDURE SORTRE
|
|
END INTERFACE
|
|
|
|
INTERFACE BINSORT
|
|
MODULE PROCEDURE BINSORT
|
|
END INTERFACE
|
|
|
|
INTERFACE SWAPRE
|
|
MODULE PROCEDURE SWAPRE
|
|
END INTERFACE
|
|
|
|
INTERFACE SWAPINT
|
|
MODULE PROCEDURE SWAPINT
|
|
END INTERFACE
|
|
|
|
PARAMETER (NDIMMAX=1000)
|
|
!--------------------------------
|
|
CONTAINS
|
|
SUBROUTINE RANMC( N, MAXPTS, FUNCTN, ABSEPS,
|
|
& RELEPS, ERROR, VALUE, INFORM )
|
|
IMPLICIT NONE
|
|
*
|
|
* A subroutine for computing multivariate integrals.
|
|
* This subroutine uses the Monte-Carlo algorithm given in the paper
|
|
* "Numerical Computation of Multivariate Normal Probabilities", in
|
|
* J. of Computational and Graphical Stat., 1(1992), pp. 141-149, by
|
|
* Alan Genz
|
|
* Department of Mathematics
|
|
* Washington State University
|
|
* Pullman, WA 99164-3113
|
|
* Email : alangenz@wsu.edu
|
|
*
|
|
* This subroutine computes an approximation to the integral
|
|
*
|
|
* 1 1 1
|
|
* I I ... I FUNCTN(NDIM,X) dx(NDIM)...dx(2)dx(1)
|
|
* 0 0 0
|
|
*
|
|
*************** Parameters for RANMC ********************************
|
|
*
|
|
****** Input Parameters
|
|
*
|
|
* N INTEGER, the number of variables.
|
|
* MAXPTS INTEGER, maximum number of function values allowed. This
|
|
* parameter can be used to limit the time taken. A
|
|
* sensible strategy is to start with MAXPTS = 1000*N, and then
|
|
* increase MAXPTS if ERROR is too large.
|
|
* ABSEPS REAL absolute error tolerance.
|
|
* RELEPS REAL relative error tolerance.
|
|
*
|
|
****** Output Parameters
|
|
*
|
|
* ERROR REAL estimated absolute error, with 99% confidence level.
|
|
* VALUE REAL estimated value for the integral
|
|
* INFORM INTEGER, termination status parameter:
|
|
* if INFORM = 0, normal completion with ERROR < EPS;
|
|
* if INFORM = 1, completion with ERROR > EPS and MAXPTS
|
|
* function vaules used; increase MAXPTS to
|
|
* decrease ERROR;
|
|
* if INFORM = 2, N > 100 or N < 1.
|
|
*
|
|
INTEGER :: N, MAXPTS, MPT, INFORM, IVLS
|
|
DOUBLE PRECISION :: ABSEPS, RELEPS, ERROR, VALUE, EPS
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
INFORM=0
|
|
IF ( N .GT. NDIMMAX .OR. N .LT. 1 ) THEN
|
|
INFORM = 2
|
|
VALUE = 0.d0
|
|
ERROR = 1.d0
|
|
RETURN
|
|
ENDIF
|
|
*
|
|
* Call then Monte-Carlo integration subroutine
|
|
*
|
|
MPT = 25 + 10*N
|
|
CALL RCRUDE(N, MPT, FUNCTN, ERROR, VALUE, 0)
|
|
IVLS = MPT
|
|
10 EPS = MAX( ABSEPS, RELEPS*ABS(VALUE) )
|
|
IF ( ERROR .GT. EPS .AND. IVLS .LT. MAXPTS ) THEN
|
|
MPT = MAX( MIN( INT(MPT*(ERROR/(EPS))**2),
|
|
& MAXPTS-IVLS ), 10 )
|
|
CALL RCRUDE(N, MPT, FUNCTN, ERROR, VALUE, 1)
|
|
IVLS = IVLS + MPT
|
|
GO TO 10
|
|
ENDIF
|
|
IF ( ERROR. GT. EPS .AND. IVLS .GE. MAXPTS ) INFORM = 1
|
|
!IF (INFORM.EQ.1) print *,'ranmc eps',EPS
|
|
END SUBROUTINE RANMC
|
|
SUBROUTINE RCRUDE(NDIM, MAXPTS, FUNCTN, ABSEST, FINEST, IR)
|
|
IMPLICIT NONE
|
|
*
|
|
* Crude Monte-Carlo Algorithm with simple antithetic variates
|
|
* and weighted results on restart
|
|
*
|
|
INTEGER :: NDIM, MAXPTS, M, IR, NPTS
|
|
DOUBLE PRECISION :: FINEST, ABSEST, FUN,
|
|
& VARSQR, VAREST, VARPRD, FINDIF, FINVAL
|
|
DOUBLE PRECISION, DIMENSION(NDIMMAX) :: X
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
SAVE VAREST
|
|
IF ( IR .LE. 0 ) THEN
|
|
VAREST = 0.d0
|
|
FINEST = 0.d0
|
|
ENDIF
|
|
FINVAL = 0.d0
|
|
VARSQR = 0.d0
|
|
NPTS = INT(MAXPTS/2)
|
|
DO M = 1,NPTS
|
|
CALL random_number(X(1:NDIM))
|
|
FUN = FUNCTN(NDIM, X(1:NDIM))
|
|
X(1:NDIM) = 1.d0 - X(1:NDIM)
|
|
FUN = (FUNCTN(NDIM, X(1:NDIM)) + FUN )*0.5d0
|
|
FINDIF = ( FUN - FINVAL )/DBLE(M)
|
|
VARSQR = DBLE( M - 2 )*VARSQR/DBLE(M) + FINDIF*FINDIF
|
|
FINVAL = FINVAL + FINDIF
|
|
END DO
|
|
VARPRD = VAREST*VARSQR
|
|
FINEST = FINEST + ( FINVAL - FINEST )/(1.d0 + VARPRD)
|
|
IF ( VARSQR .GT. 0 ) VAREST = (1.d0 + VARPRD)/VARSQR
|
|
ABSEST = 3.d0*SQRT( VARSQR/( 1.d0 + VARPRD ) )
|
|
MAXPTS=2*NPTS
|
|
END SUBROUTINE RCRUDE
|
|
|
|
SUBROUTINE BINSORT(indices,rarray)
|
|
IMPLICIT NONE
|
|
TYPE ENTRY
|
|
DOUBLE PRECISION, POINTER :: VAL
|
|
INTEGER :: IX
|
|
TYPE( ENTRY), POINTER :: NEXT
|
|
END TYPE ENTRY
|
|
DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: rarray
|
|
INTEGER, DIMENSION(:), INTENT(inout) :: indices
|
|
DOUBLE PRECISION, DIMENSION(SIZE(rarray)),TARGET :: A
|
|
TYPE(ENTRY), DIMENSION(:), ALLOCATABLE,TARGET :: B
|
|
TYPE(ENTRY), POINTER :: FIRST,CURRENT
|
|
|
|
! local variables
|
|
INTEGER :: i,im,n
|
|
DOUBLE PRECISION :: mx, mn
|
|
! Bucket sort:
|
|
! This subroutine sorts the indices according to rarray. The Assumption is that rarray consists of
|
|
! uniformly distributed numbers. If the assumption holds it runs in O(n) time
|
|
n=size(indices)
|
|
IF (n.EQ.1) RETURN
|
|
!indices=(/(i,i=1,n)/)
|
|
mx = MAXVAL(rarray)
|
|
mn = MINVAL(rarray)
|
|
A=(rarray-mn)/(mx-mn) ! make sure the numbers are between 0 and 1
|
|
|
|
!print *,'binsort ind=',indices
|
|
!print *,'binsort rar=',rarray
|
|
!print *,'binsort rar=',A
|
|
ALLOCATE(B(0:n-1))
|
|
!IF (ASSOCIATED(B(0)%VAL)) print *,'binsort B(0)=',B(0)%VAL
|
|
DO I=0,n-1
|
|
NULLIFY(B(I)%VAL)
|
|
NULLIFY(B(I)%NEXT)
|
|
ENDDO
|
|
|
|
DO I=1,n
|
|
IM=min(ABS(FLOOR(n*A(I))),N-1)
|
|
IF (ASSOCIATED(B(IM)%VAL)) THEN ! insert the new item by insertion sorting
|
|
ALLOCATE(CURRENT)
|
|
IF (A(I).LT.B(IM)%VAL) THEN
|
|
CURRENT = B(IM)
|
|
B(IM) = ENTRY(A(I),indices(I),CURRENT)
|
|
ELSE
|
|
FIRST => B(IM)
|
|
DO WHILE(ASSOCIATED(FIRST%NEXT).AND.
|
|
& FIRST%NEXT%VAL.LT.A(I))
|
|
FIRST=FIRST%NEXT
|
|
END DO
|
|
|
|
CURRENT = ENTRY(A(I),indices(I),FIRST%NEXT)
|
|
FIRST%NEXT => CURRENT
|
|
ENDIF
|
|
ELSE
|
|
B(IM)%VAL => A(I)
|
|
B(IM)%IX = indices(I)
|
|
ENDIF
|
|
END DO
|
|
IM=0
|
|
I=0
|
|
DO WHILE (IM.LT.N .AND. I.LT.N)
|
|
IF (ASSOCIATED(B(I)%VAL)) THEN
|
|
IM=IM+1
|
|
indices(IM)=B(I)%IX
|
|
DO WHILE (ASSOCIATED(B(I)%NEXT))
|
|
CURRENT => B(I)%NEXT
|
|
B(I)%NEXT => B(I)%NEXT%NEXT
|
|
IM=IM+1
|
|
indices(IM)=CURRENT%IX
|
|
DEALLOCATE(CURRENT)
|
|
END DO
|
|
ENDIF
|
|
I=I+1
|
|
END DO
|
|
DEALLOCATE(B)
|
|
!print *,'binsort ind=',indices
|
|
RETURN
|
|
END SUBROUTINE BINSORT
|
|
|
|
SUBROUTINE SORTRE(indices,rarray)
|
|
IMPLICIT NONE
|
|
DOUBLE PRECISION, DIMENSION(:), INTENT(inout) :: rarray
|
|
INTEGER, DIMENSION(:), INTENT(inout) :: indices
|
|
! local variables
|
|
INTEGER :: i,im,j,k,m,n
|
|
|
|
! diminishing increment sort as described by
|
|
! Donald E. Knuth (1973) "The art of computer programming,",
|
|
! Vol. 3, pp 84- (sorting and searching)
|
|
n=size(indices)
|
|
! if the below is commented out then assume indices are already initialized
|
|
!indices=(/(i,i=1,n)/)
|
|
!100 continue
|
|
if (n.le.1) goto 800
|
|
m=1
|
|
200 continue
|
|
m=m+m
|
|
if (m.lt.n) goto 200
|
|
m=m-1
|
|
300 continue
|
|
m=m/2
|
|
if (m.eq.0) goto 800
|
|
k=n-m
|
|
j=1
|
|
400 continue
|
|
i=j
|
|
500 continue
|
|
im=i+m
|
|
if (rarray(i).gt.rarray(im)) goto 700
|
|
600 continue
|
|
j=j+1
|
|
if (j.gt.k) goto 300
|
|
goto 400
|
|
700 continue
|
|
CALL swapre(rarray(i),rarray(im))
|
|
CALL swapint(indices(i),indices(im))
|
|
i=i-m
|
|
if (i.lt.1) goto 600
|
|
goto 500
|
|
800 continue
|
|
RETURN
|
|
END SUBROUTINE SORTRE
|
|
|
|
SUBROUTINE swapRe(m,n)
|
|
IMPLICIT NONE
|
|
DOUBLE PRECISION, INTENT(inout) :: m,n
|
|
DOUBLE PRECISION :: tmp
|
|
tmp=m
|
|
m=n
|
|
n=tmp
|
|
END SUBROUTINE swapRe
|
|
|
|
SUBROUTINE swapint(m,n)
|
|
IMPLICIT NONE
|
|
INTEGER, INTENT(inout) :: m,n
|
|
INTEGER :: tmp
|
|
tmp=m
|
|
m=n
|
|
n=tmp
|
|
END SUBROUTINE swapint
|
|
!______________________________________________________
|
|
|
|
SUBROUTINE spearcorr(C,D)
|
|
IMPLICIT NONE
|
|
DOUBLE PRECISION, dimension(:,:), INTENT(out) :: C
|
|
integer, dimension(:,:),intent(in) :: D ! rank matrix
|
|
double precision, dimension(:,:),allocatable :: DD !,DDT
|
|
double precision, dimension(:),allocatable :: tmp
|
|
INTEGER :: N,M,ix,iy
|
|
DOUBLE PRECISION :: dN
|
|
! this procedure calculates spearmans correlation coefficient
|
|
! between the columns of D
|
|
|
|
N=size(D,dim=1);M=SIZE(D,dim=2)
|
|
dN=dble(N)
|
|
allocate(DD(1:N,1:M))
|
|
DD=dble(D)
|
|
! if (.false.) then ! old call
|
|
! allocate(DDt(1:M,1:N))
|
|
! DDT=transpose(DD)
|
|
! C = matmul(DDt,DD)*12.d0/(dn*(dn*dn-1.d0))
|
|
! C=(C-3.d0*(dn+1.d0)/(dn-1.d0))
|
|
! deallocate(DDT)
|
|
! else
|
|
allocate(tmp(1:N))
|
|
do ix=1, m-1
|
|
do iy=ix+1,m
|
|
tmp= DD(1:N,ix)-DD(1:N,iy)
|
|
C(ix,iy)=1.d0-6.d0*SUM(tmp*tmp)/dn/(dn*dn-1.d0)
|
|
C(iy,ix)=C(ix,iy)
|
|
enddo
|
|
C(ix,ix) = 1.d0
|
|
enddo
|
|
C(m,m)=1.d0
|
|
deallocate(tmp)
|
|
! endif
|
|
deallocate(DD)
|
|
return
|
|
END SUBROUTINE spearcorr
|
|
|
|
SUBROUTINE SVDCMP(A,W,V)
|
|
IMPLICIT NONE
|
|
DOUBLE PRECISION, DIMENSION(: ), INTENT(out) :: W
|
|
DOUBLE PRECISION, DIMENSION(:,:), INTENT(inout) :: A
|
|
DOUBLE PRECISION, DIMENSION(:,:), INTENT(OUT) :: V
|
|
!LOCAL VARIABLES
|
|
DOUBLE PRECISION, DIMENSION(:), allocatable :: RV1
|
|
DOUBLE PRECISION :: G,S,SCALE,ANORM,F,H,C,X,Y,Z
|
|
INTEGER M,N,NM,I,J,K,L,ITS
|
|
|
|
!PARAMETER (NMAX=100)
|
|
C Maximum anticipated values of N
|
|
|
|
C DIMENSION A(MP,NP),W(NP),V(NP,NP),RV1(NMAX)
|
|
C Given a matrix A, with logical dimensions M by N and physical
|
|
C dimensions MP by NP, this routine computes its singular value
|
|
C decomposition, A=U.W.V^T, see Numerical Recipes, by Press W.,H.
|
|
C Flannery, B. P., Teukolsky S.A. and Vetterling W., T. Cambrige
|
|
C University Press 1986, Chapter 2.9. The matrix U replaces A on
|
|
C output. The diagonal matrix of singular values W is output as a vector
|
|
C W. The matrix V (not the transpose V^T) is output as V. M must be
|
|
C greater or equal to N; if it is smaller, then A should be filled up
|
|
C to square with zero rows.
|
|
C
|
|
|
|
M=size(A,dim=1);N=size(A,dim=2)
|
|
!Mp=M;Np=N
|
|
allocate(RV1(1:N))
|
|
IF (M.LT.N) then
|
|
! Print *,'SVDCMP: You must augment A with extra zero rows.'
|
|
endif
|
|
C Householder reduction to bidiagonal form
|
|
G=0.d0
|
|
SCALE=0.d0
|
|
ANORM=0.d0
|
|
DO 25 I=1,N
|
|
L=I+1
|
|
RV1(I)=SCALE*G
|
|
G=0.D0
|
|
S=0.D0
|
|
SCALE=0.D0
|
|
IF (I.LE.M) THEN
|
|
DO K=I,M
|
|
SCALE=SCALE+ABS(A(K,I))
|
|
enddo
|
|
IF (SCALE.NE.0.D0) THEN
|
|
DO K=I,M
|
|
A(K,I)=A(K,I)/SCALE
|
|
S=S+A(K,I)*A(K,I)
|
|
enddo
|
|
F=A(I,I)
|
|
G=-SIGN(SQRT(S),F)
|
|
H=F*G-S
|
|
A(I,I)=F-G
|
|
IF (I.NE.N) THEN
|
|
DO J=L,N
|
|
S=0.D0
|
|
DO K=I,M
|
|
S=S+A(K,I)*A(K,J)
|
|
enddo
|
|
F=S/H
|
|
DO K=I,M
|
|
A(K,J)=A(K,J)+F*A(K,I)
|
|
enddo
|
|
enddo
|
|
ENDIF
|
|
DO K=I,M
|
|
A(K,I)=SCALE*A(K,I)
|
|
enddo
|
|
ENDIF
|
|
ENDIF
|
|
W(I)=SCALE*G
|
|
G=0.d0
|
|
S=0.d0
|
|
SCALE=0.d0
|
|
IF ((I.LE.M).AND.(I.NE.N)) THEN
|
|
DO K=L,N
|
|
SCALE=SCALE+ABS(A(I,K))
|
|
enddo
|
|
IF (SCALE.NE.0.0) THEN
|
|
DO K=L,N
|
|
A(I,K)=A(I,K)/SCALE
|
|
S=S+A(I,K)*A(I,K)
|
|
enddo
|
|
F=A(I,L)
|
|
G=-SIGN(SQRT(S),F)
|
|
H=F*G-S
|
|
A(I,L)=F-G
|
|
DO K=L,N
|
|
RV1(K)=A(I,K)/H
|
|
enddo
|
|
IF (I.NE.M) THEN
|
|
DO J=L,M
|
|
S=0.D0
|
|
DO K=L,N
|
|
S=S+A(J,K)*A(I,K)
|
|
enddo
|
|
DO K=L,N
|
|
A(J,K)=A(J,K)+S*RV1(K)
|
|
enddo
|
|
enddo
|
|
ENDIF
|
|
DO K=L,N
|
|
A(I,K)=SCALE*A(I,K)
|
|
enddo
|
|
ENDIF
|
|
ENDIF
|
|
ANORM=MAX(ANORM,(ABS(W(I))+ABS(RV1(I))))
|
|
25 CONTINUE
|
|
c print *,'25'
|
|
C Accumulation of right-hand transformations.
|
|
DO I=N,1,-1
|
|
IF (I.LT.N) THEN
|
|
IF (G.NE.0.d0) THEN
|
|
DO J=L,N
|
|
V(J,I)=(A(I,J)/A(I,L))/G
|
|
C Double division to avoid possible underflow.
|
|
enddo
|
|
DO J=L,N
|
|
S=0.d0
|
|
DO K=L,N
|
|
S=S+A(I,K)*V(K,J)
|
|
enddo
|
|
DO K=L,N
|
|
V(K,J)=V(K,J)+S*V(K,I)
|
|
enddo
|
|
enddo
|
|
ENDIF
|
|
DO J=L,N
|
|
V(I,J)=0.d0
|
|
V(J,I)=0.d0
|
|
enddo
|
|
ENDIF
|
|
V(I,I)=1.d0
|
|
G=RV1(I)
|
|
L=I
|
|
enddo
|
|
c print *,'32'
|
|
|
|
C Accumulation of the left-hang transformation
|
|
DO 39 I=N,1,-1
|
|
L=I+1
|
|
G=W(I)
|
|
IF (I.LT.N) THEN
|
|
DO J=L,N
|
|
A(I,J)=0.d0
|
|
enddo
|
|
ENDIF
|
|
IF (G.NE.0.d0) THEN
|
|
G=1.d0/G
|
|
IF (I.NE.N) THEN
|
|
DO J=L,N
|
|
S=0.d0
|
|
DO K=L,M
|
|
S=S+A(K,I)*A(K,J)
|
|
enddo
|
|
F=(S/A(I,I))*G
|
|
DO K=I,M
|
|
A(K,J)=A(K,J)+F*A(K,I)
|
|
enddo
|
|
enddo
|
|
ENDIF
|
|
DO J=I,M
|
|
A(J,I)=A(J,I)*G
|
|
enddo
|
|
ELSE
|
|
DO J=I,M
|
|
A(J,I)=0.d0
|
|
enddo
|
|
ENDIF
|
|
A(I,I)=A(I,I)+1.d0
|
|
39 CONTINUE
|
|
c print *,'39'
|
|
|
|
C Diagonalization of the bidiagonal form
|
|
C Loop over singular values
|
|
DO 49 K=N,1,-1
|
|
C Loop allowed iterations
|
|
DO 48 ITS=1,30
|
|
C Test for spliting
|
|
DO L=K,1,-1
|
|
NM=L-1
|
|
C Note that RV1(1) is always zero
|
|
! old call which may cause inconsistent results
|
|
! IF((ABS(RV1(L))+ANORM).EQ.ANORM) GO TO 2
|
|
! IF((ABS(W(NM))+ANORM).EQ.ANORM) GO TO 1
|
|
! NEW CALL
|
|
IF (((ABS(RV1(L))+ANORM).GE.NEAREST(ANORM,-1.d0)).AND.
|
|
& ((ABS(RV1(L))+ANORM).LE.NEAREST(ANORM,1.d0)) ) GO TO 2
|
|
IF (((ABS(W(NM))+ANORM).GE.NEAREST(ANORM,-1.d0)).AND.
|
|
& ((ABS(W(NM))+ANORM).LE.NEAREST(ANORM,1.d0)) ) GO TO 1
|
|
|
|
enddo
|
|
c print *,'41'
|
|
1 C=0.d0
|
|
S=1.d0
|
|
DO I=L,K
|
|
F=S*RV1(I)
|
|
! old call which may cause inconsistent results
|
|
|
|
IF (((ABS(F)+ANORM).LT.ANORM).OR.
|
|
& ((ABS(F)+ANORM).GT.ANORM)) THEN
|
|
G=W(I)
|
|
H=SQRT(F*F+G*G)
|
|
W(I)=H
|
|
H=1.D0/H
|
|
C= (G*H)
|
|
S=-(F*H)
|
|
DO J=1,M
|
|
Y=A(J,NM)
|
|
Z=A(J,I)
|
|
A(J,NM)=(Y*C)+(Z*S)
|
|
A(J,I)=-(Y*S)+(Z*C)
|
|
enddo
|
|
ENDIF
|
|
enddo
|
|
c print *,'43'
|
|
2 Z=W(K)
|
|
IF (L.EQ.K) THEN
|
|
C Convergence
|
|
IF (Z.LT.0.d0) THEN
|
|
C Singular values are made nonnegative
|
|
W(K)=-Z
|
|
DO J=1,N
|
|
V(J,K)=-V(J,K)
|
|
enddo
|
|
ENDIF
|
|
GO TO 3
|
|
ENDIF
|
|
IF (ITS.EQ.30) then
|
|
! print *,'SVDCMP: No convergence in 30 iterations'
|
|
endif
|
|
X=W(L)
|
|
NM=K-1
|
|
Y=W(NM)
|
|
G=RV1(NM)
|
|
H=RV1(K)
|
|
F=((Y-Z)*(Y+Z)+(G-H)*(G+H))/(2.d0*H*Y)
|
|
G=SQRT(F*F+1.D0)
|
|
F=((X-Z)*(X+Z)+H*((Y/(F+SIGN(G,F)))-H))/X
|
|
C Next QR transformation
|
|
C=1.d0
|
|
S=1.d0
|
|
DO 47 J=L,NM
|
|
I=J+1
|
|
G=RV1(I)
|
|
Y=W(I)
|
|
H=S*G
|
|
G=C*G
|
|
Z=SQRT(F*F+H*H)
|
|
RV1(J)=Z
|
|
C=F/Z
|
|
S=H/Z
|
|
F= (X*C)+(G*S)
|
|
G=-(X*S)+(G*C)
|
|
H=Y*S
|
|
Y=Y*C
|
|
DO NM=1,N
|
|
X=V(NM,J)
|
|
Z=V(NM,I)
|
|
V(NM,J)= (X*C)+(Z*S)
|
|
V(NM,I)=-(X*S)+(Z*C)
|
|
enddo
|
|
c print *,'45',F,H
|
|
Z=pythag(F,H)
|
|
W(J)=Z
|
|
C Rotation can be arbitrary if Z=0.
|
|
IF (Z.NE.0.d0) THEN
|
|
c print *,1/Z
|
|
Z=1.d0/Z
|
|
c print *,'*'
|
|
C=F*Z
|
|
S=H*Z
|
|
ENDIF
|
|
F= (C*G)+(S*Y)
|
|
X=-(S*G)+(C*Y)
|
|
DO NM=1,M
|
|
Y=A(NM,J)
|
|
Z=A(NM,I)
|
|
A(NM,J)= (Y*C)+(Z*S)
|
|
A(NM,I)=-(Y*S)+(Z*C)
|
|
enddo
|
|
c print *,'46'
|
|
|
|
47 CONTINUE
|
|
c print *,'47'
|
|
RV1(L)=0.D0
|
|
RV1(K)=F
|
|
W(K)=X
|
|
48 CONTINUE
|
|
3 CONTINUE
|
|
49 CONTINUE
|
|
c print *,'49'
|
|
deallocate(RV1)
|
|
RETURN
|
|
END SUBROUTINE SVDCMP
|
|
|
|
FUNCTION pythag(a,b) RESULT (VALUE)
|
|
DOUBLE PRECISION, INTENT(IN) :: a,b
|
|
DOUBLE PRECISION :: VALUE
|
|
DOUBLE PRECISION :: absa,absb
|
|
absa=abs(a)
|
|
absb=abs(b)
|
|
IF (absa.GT.absb) THEN
|
|
VALUE=absa*SQRT(1.d0+(absb/absa)**2)
|
|
ELSE
|
|
IF (absb.EQ.0) THEN
|
|
VALUE=0.D0
|
|
ELSE
|
|
VALUE=absb*SQRT(1.d0+(absa/absb)**2)
|
|
ENDIF
|
|
ENDIF
|
|
RETURN
|
|
END FUNCTION PYTHAG
|
|
END MODULE RCRUDEMOD
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* KRBVRCMOD is a module containing a:
|
|
*
|
|
* Automatic Multidimensional Integration Subroutine
|
|
*
|
|
* AUTHOR: Alan Genz
|
|
* Department of Mathematics
|
|
* Washington State University
|
|
* Pulman, WA 99164-3113
|
|
* Email: AlanGenz@wsu.edu
|
|
*
|
|
* Last Change: 5/15/98
|
|
* revised pab 10.03.2000
|
|
* - updated to f90 (i.e. changed to assumed shape arrays + changing integers to DBLE)
|
|
* - put it into a module
|
|
*
|
|
* KRBVRC computes an approximation to the integral
|
|
*
|
|
* 1 1 1
|
|
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
|
|
* 0 0 0
|
|
*
|
|
*
|
|
* KRBVRC uses randomized Korobov rules for the first 20 variables.
|
|
* The primary references are
|
|
* "Randomization of Number Theoretic Methods for Multiple Integration"
|
|
* R. Cranley and T.N.L. Patterson, SIAM J Numer Anal, 13, pp. 904-14,
|
|
* and
|
|
* "Optimal Parameters for Multidimensional Integration",
|
|
* P. Keast, SIAM J Numer Anal, 10, pp.831-838.
|
|
* If there are more than 20 variables, the remaining variables are
|
|
* integrated using Richtmeyer rules. A reference is
|
|
* "Methods of Numerical Integration", P.J. Davis and P. Rabinowitz,
|
|
* Academic Press, 1984, pp. 482-483.
|
|
*
|
|
*************** Parameters for KRBVRC ********************************************
|
|
****** Input parameters
|
|
* NDIM Number of variables, must exceed 1, but not exceed 100
|
|
* MINVLS Integer minimum number of function evaluations allowed.
|
|
* MINVLS must not exceed MAXVLS. If MINVLS < 0 then the
|
|
* routine assumes a previous call has been made with
|
|
* the same integrand and continues that calculation.
|
|
* MAXVLS Integer maximum number of function evaluations allowed.
|
|
* FUNCTN EXTERNALly declared user defined function to be integrated.
|
|
* It must have parameters (NDIM,Z), where Z is a real array
|
|
* of dimension NDIM.
|
|
*
|
|
* ABSEPS Required absolute accuracy.
|
|
* RELEPS Required relative accuracy.
|
|
*
|
|
****** Output parameters
|
|
*
|
|
* MINVLS Actual number of function evaluations used.
|
|
* ABSERR Estimated absolute accuracy of FINEST.
|
|
* FINEST Estimated value of integral.
|
|
* INFORM INFORM = 0 for normal exit, when
|
|
* ABSERR <= MAX(ABSEPS, RELEPS*ABS(FINEST))
|
|
* and
|
|
* INTVLS <= MAXCLS.
|
|
* INFORM = 1 If MAXVLS was too small to obtain the required
|
|
* accuracy. In this case a value FINEST is returned with
|
|
* estimated absolute accuracy ABSERR.
|
|
************************************************************************
|
|
! William H. Press, Saul Teukolsky,
|
|
! William T. Wetterling and Brian P. Flannery (1997)
|
|
! "Numerical recipes in Fortran 77", Vol. 1, pp 299--305 (SOBSEQ)
|
|
|
|
! You may initialize the random generator before you
|
|
! call KRBVRC by the following lines:
|
|
!
|
|
! call random_seed(SIZE=seed_size)
|
|
! allocate(seed(seed_size))
|
|
! call random_seed(GET=seed(1:seed_size)) ! get current seed
|
|
! seed(1)=seed1 ! change seed
|
|
! call random_seed(PUT=seed(1:seed_size))
|
|
! deallocate(seed)
|
|
!
|
|
MODULE KRBVRCMOD
|
|
IMPLICIT NONE
|
|
PRIVATE
|
|
PUBLIC :: KRBVRC
|
|
!
|
|
INTERFACE KRBVRC
|
|
MODULE PROCEDURE KRBVRC
|
|
END INTERFACE
|
|
!
|
|
INTERFACE DKSMRC
|
|
MODULE PROCEDURE DKSMRC
|
|
END INTERFACE
|
|
!
|
|
INTERFACE DKRCHT
|
|
MODULE PROCEDURE DKRCHT
|
|
END INTERFACE
|
|
|
|
INTERFACE SOBSEQ
|
|
MODULE PROCEDURE SOBSEQ
|
|
END INTERFACE
|
|
!
|
|
CONTAINS
|
|
|
|
!***********************************************************
|
|
! MAIN INTEGRATION ROUTINE KRBVRC
|
|
!***********************************************************
|
|
|
|
SUBROUTINE KRBVRC( NDIM, MINVLS, MAXVLS, FUNCTN, ABSEPS, RELEPS,
|
|
& ABSERR, FINEST, INFORM )
|
|
*
|
|
* Automatic Multidimensional Integration Subroutine
|
|
*
|
|
* AUTHOR: Alan Genz
|
|
* Department of Mathematics
|
|
* Washington State University
|
|
* Pulman, WA 99164-3113
|
|
* Email: AlanGenz@wsu.edu
|
|
*
|
|
* Last Change: 5/15/98
|
|
*
|
|
* KRBVRC computes an approximation to the integral
|
|
*
|
|
* 1 1 1
|
|
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
|
|
* 0 0 0
|
|
*
|
|
*
|
|
* KRBVRC uses randomized Korobov rules for the first 20 variables.
|
|
* The primary references are
|
|
* "Randomization of Number Theoretic Methods for Multiple Integration"
|
|
* R. Cranley and T.N.L. Patterson, SIAM J Numer Anal, 13, pp. 904-14,
|
|
* and
|
|
* "Optimal Parameters for Multidimensional Integration",
|
|
* P. Keast, SIAM J Numer Anal, 10, pp.831-838.
|
|
* If there are more than 20 variables, the remaining variables are
|
|
* integrated using Richtmeyer rules. A reference is
|
|
* "Methods of Numerical Integration", P.J. Davis and P. Rabinowitz,
|
|
* Academic Press, 1984, pp. 482-483.
|
|
*
|
|
*************** Parameters ********************************************
|
|
****** Input parameters
|
|
* NDIM Number of variables, must exceed 1, but not exceed 100
|
|
* MINVLS Integer minimum number of function evaluations allowed.
|
|
* MINVLS must not exceed MAXVLS. If MINVLS < 0 then the
|
|
* routine assumes a previous call has been made with
|
|
* the same integrand and continues that calculation.
|
|
* MAXVLS Integer maximum number of function evaluations allowed.
|
|
* FUNCTN EXTERNALly declared user defined function to be integrated.
|
|
* It must have parameters (NDIM,Z), where Z is a real array
|
|
* of dimension NDIM.
|
|
*
|
|
* ABSEPS Required absolute accuracy.
|
|
* RELEPS Required relative accuracy.
|
|
****** Output parameters
|
|
* MINVLS Actual number of function evaluations used.
|
|
* ABSERR Estimated absolute accuracy of FINEST.
|
|
* FINEST Estimated value of integral.
|
|
* INFORM INFORM = 0 for normal exit, when
|
|
* ABSERR <= MAX(ABSEPS, RELEPS*ABS(FINEST))
|
|
* and
|
|
* INTVLS <= MAXCLS.
|
|
* INFORM = 1 If MAXVLS was too small to obtain the required
|
|
* accuracy. In this case a value FINEST is returned with
|
|
* estimated absolute accuracy ABSERR.
|
|
* INFORM = 2 If NDIM>100 or NDIM<1
|
|
************************************************************************
|
|
INTEGER, INTENT(IN) :: NDIM, MAXVLS
|
|
INTEGER, INTENT(INOUT) :: MINVLS
|
|
INTEGER, INTENT(OUT) :: INFORM
|
|
DOUBLE PRECISION, INTENT(IN) :: ABSEPS, RELEPS
|
|
DOUBLE PRECISION, INTENT(OUT) :: FINEST, ABSERR
|
|
INTEGER :: NP,PLIM,NLIM,KLIM,KLIMI,SAMPLS,I,INTVLS,MINSMP,NK
|
|
PARAMETER ( PLIM = 25, NLIM = 100, KLIM = 20, MINSMP = 8 )
|
|
INTEGER , DIMENSION(PLIM) :: P
|
|
INTEGER , DIMENSION(PLIM,KLIM-1) :: C
|
|
DOUBLE PRECISION :: DIFINT,FINVAL,VARSQR,VAREST,VARPRD,VALUE
|
|
DOUBLE PRECISION, PARAMETER :: ONE = 1.D0 , ZERO = 0.D0
|
|
DOUBLE PRECISION, DIMENSION(2*NLIM) :: X = 0.d0
|
|
DOUBLE PRECISION, DIMENSION(KLIM ) :: VK = 0.d0
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
DATA P / 31, 47, 73, 113, 173, 263, 397, 593, 907, 1361,
|
|
& 2053, 3079, 4621, 6947, 10427, 15641, 23473, 35221,
|
|
& 52837, 79259, 118891, 178349, 267523, 401287, 601943/
|
|
DATA (C( 1,I), I = 1, 19)/ 12, 9, 9,
|
|
& 13, 12, 12, 12, 12, 12, 12, 12,
|
|
& 12, 3, 3, 3, 12, 7, 7, 12/
|
|
DATA (C( 2,I), I = 1, 19)/ 13, 11, 17,
|
|
& 10, 15, 15, 15, 15, 15, 15, 22,
|
|
& 15, 15, 6, 6, 6, 15, 15, 9/
|
|
DATA (C( 3,I), I = 1, 19)/ 27, 28, 10,
|
|
& 11, 11, 20, 11, 11, 28, 13, 13,
|
|
& 28, 13, 13, 13, 14, 14, 14, 14/
|
|
DATA (C( 4,I), I = 1, 19)/ 35, 27, 27,
|
|
& 36, 22, 29, 29, 20, 45, 5, 5,
|
|
& 5, 21, 21, 21, 21, 21, 21, 21/
|
|
DATA (C( 5,I), I = 1, 19)/ 64, 66, 28,
|
|
& 28, 44, 44, 55, 67, 10, 10, 10,
|
|
& 10, 10, 10, 38, 38, 10, 10, 10/
|
|
DATA (C( 6,I), I = 1, 19)/ 111, 42, 54,
|
|
& 118, 20, 31, 31, 72, 17, 94, 14,
|
|
& 14, 11, 14, 14, 14, 94, 10, 10/
|
|
DATA (C( 7,I), I = 1, 19)/ 163, 154, 83,
|
|
& 43, 82, 92, 150, 59, 76, 76, 47,
|
|
& 11, 11, 100, 131, 116, 116, 116, 116/
|
|
DATA (C( 8,I), I = 1, 19)/ 246, 189, 242,
|
|
& 102, 250, 250, 102, 250, 280, 118, 196,
|
|
& 118, 191, 215, 121, 121, 49, 49, 49/
|
|
DATA (C( 9,I), I = 1, 19)/ 347, 402, 322,
|
|
& 418, 215, 220, 339, 339, 339, 337, 218,
|
|
& 315, 315, 315, 315, 167, 167, 167, 167/
|
|
DATA (C(10,I), I = 1, 19)/ 505, 220, 601,
|
|
& 644, 612, 160, 206, 206, 206, 422, 134,
|
|
& 518, 134, 134, 518, 652, 382, 206, 158/
|
|
DATA (C(11,I), I = 1, 19)/ 794, 325, 960,
|
|
& 528, 247, 247, 338, 366, 847, 753, 753,
|
|
& 236, 334, 334, 461, 711, 652, 381, 381/
|
|
DATA (C(12,I), I = 1, 19)/ 1189, 888, 259,
|
|
& 1082, 725, 811, 636, 965, 497, 497, 1490,
|
|
& 1490, 392, 1291, 508, 508, 1291, 1291, 508/
|
|
DATA (C(13,I), I = 1, 19)/ 1763, 1018, 1500,
|
|
& 432, 1332, 2203, 126, 2240, 1719, 1284, 878,
|
|
& 1983, 266, 266, 266, 266, 747, 747, 127/
|
|
DATA (C(14,I), I = 1, 19)/ 2872, 3233, 1534,
|
|
& 2941, 2910, 393, 1796, 919, 446, 919, 919,
|
|
& 1117, 103, 103, 103, 103, 103, 103, 103/
|
|
DATA (C(15,I), I = 1, 19)/ 4309, 3758, 4034,
|
|
& 1963, 730, 642, 1502, 2246, 3834, 1511, 1102,
|
|
& 1102, 1522, 1522, 3427, 3427, 3928, 915, 915/
|
|
DATA (C(16,I), I = 1, 19)/ 6610, 6977, 1686,
|
|
& 3819, 2314, 5647, 3953, 3614, 5115, 423, 423,
|
|
& 5408, 7426, 423, 423, 487, 6227, 2660, 6227/
|
|
DATA (C(17,I), I = 1, 19)/ 9861, 3647, 4073,
|
|
& 2535, 3430, 9865, 2830, 9328, 4320, 5913, 10365,
|
|
& 8272, 3706, 6186, 7806, 7806, 7806, 8610, 2563/
|
|
DATA (C(18,I), I = 1, 19)/ 10327, 7582, 7124,
|
|
& 8214, 9600, 10271, 10193, 10800, 9086, 2365, 4409,
|
|
& 13812, 5661, 9344, 9344, 10362, 9344, 9344, 8585/
|
|
DATA (C(19,I), I = 1, 19)/ 19540, 19926, 11582,
|
|
& 11113, 24585, 8726, 17218, 419, 4918, 4918, 4918,
|
|
& 15701, 17710, 4037, 4037, 15808, 11401, 19398, 25950/
|
|
DATA (C(20,I), I = 1, 19)/ 34566, 9579, 12654,
|
|
& 26856, 37873, 38806, 29501, 17271, 3663, 10763, 18955,
|
|
& 1298, 26560, 17132, 17132, 4753, 4753, 8713, 18624/
|
|
DATA (C(21,I), I = 1, 19)/ 31929, 49367, 10982,
|
|
& 3527, 27066, 13226, 56010, 18911, 40574, 20767, 20767,
|
|
& 9686, 47603, 47603, 11736, 11736, 41601, 12888, 32948/
|
|
DATA (C(22,I), I = 1, 19)/ 40701, 69087, 77576,
|
|
& 64590, 39397, 33179, 10858, 38935, 43129, 35468, 35468,
|
|
& 2196, 61518, 61518, 27945, 70975, 70975, 86478, 86478/
|
|
DATA (C(23,I), I = 1, 19)/ 103650, 125480, 59978,
|
|
& 46875, 77172, 83021, 126904, 14541, 56299, 43636, 11655,
|
|
& 52680, 88549, 29804, 101894, 113675, 48040, 113675, 34987/
|
|
DATA (C(24,I), I = 1, 19)/ 165843, 90647, 59925,
|
|
& 189541, 67647, 74795, 68365, 167485, 143918, 74912, 167289,
|
|
& 75517, 8148, 172106, 126159, 35867, 35867, 35867, 121694/
|
|
DATA (C(25,I), I = 1, 19)/ 130365, 236711, 110235,
|
|
& 125699, 56483, 93735, 234469, 60549, 1291, 93937, 245291,
|
|
& 196061, 258647, 162489, 176631, 204895, 73353, 172319, 28881/
|
|
*
|
|
SAVE P, C, SAMPLS, NP, VAREST
|
|
IF ( NDIM .GT. NLIM .OR. NDIM .LT. 1 ) THEN
|
|
INFORM = 2
|
|
FINEST = ZERO
|
|
ABSERR = ONE
|
|
RETURN
|
|
ENDIF
|
|
INFORM = 1
|
|
INTVLS = 0
|
|
KLIMI = KLIM
|
|
IF ( MINVLS .GE. 0 ) THEN
|
|
FINEST = ZERO
|
|
VAREST = ZERO
|
|
SAMPLS = MINSMP
|
|
DO I = 1, PLIM
|
|
NP = I
|
|
IF ( MINVLS .LT. 2*SAMPLS*P(I) ) GO TO 10
|
|
END DO
|
|
SAMPLS = MAX( MINSMP, MINVLS/( 2*P(NP) ) )
|
|
ENDIF
|
|
10 VK(1) = ONE/DBLE(P(NP))
|
|
NK = MIN( NDIM, KLIM )
|
|
DO I = 2, NK
|
|
VK(I) = MOD(DBLE(C(NP,NK-1))*VK(I-1), ONE )
|
|
END DO
|
|
FINVAL = ZERO
|
|
VARSQR = ZERO
|
|
DO I = 1, SAMPLS
|
|
CALL DKSMRC( NDIM, KLIMI, VALUE, P(NP), VK, FUNCTN, X )
|
|
DIFINT = ( VALUE - FINVAL )/DBLE(I)
|
|
FINVAL = FINVAL + DIFINT
|
|
VARSQR = DBLE( I - 2 )*VARSQR/DBLE(I) + DIFINT*DIFINT
|
|
END DO
|
|
INTVLS = INTVLS + 2*SAMPLS*P(NP)
|
|
VARPRD = VAREST*VARSQR
|
|
FINEST = FINEST + ( FINVAL - FINEST )/( ONE + VARPRD )
|
|
IF ( VARSQR .GT. ZERO ) VAREST = ( ONE + VARPRD )/VARSQR
|
|
ABSERR = 3.d0*SQRT( VARSQR/( ONE + VARPRD ) )
|
|
IF ( ABSERR .GT. MAX( ABSEPS, ABS(FINEST)*RELEPS ) ) THEN
|
|
IF ( NP .LT. PLIM ) THEN
|
|
NP = NP + 1
|
|
ELSE
|
|
SAMPLS = MIN( 3*SAMPLS/2, ( MAXVLS - INTVLS )/( 2*P(NP) ) )
|
|
SAMPLS = MAX( MINSMP, SAMPLS )
|
|
ENDIF
|
|
IF ( INTVLS + 2*SAMPLS*P(NP) .LE. MAXVLS ) GO TO 10
|
|
ELSE
|
|
INFORM = 0
|
|
ENDIF
|
|
MINVLS = INTVLS
|
|
*
|
|
END SUBROUTINE KRBVRC
|
|
*
|
|
SUBROUTINE DKSMRC( NDIM, KLIM, SUMKRO, PRIME, VK, FUNCTN, X )
|
|
INTEGER, INTENT(IN):: NDIM, KLIM, PRIME
|
|
DOUBLE PRECISION, INTENT(OUT) :: SUMKRO
|
|
DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: VK,X
|
|
INTEGER :: K, J, JP, NK
|
|
DOUBLE PRECISION :: ONE, XT, MVNUNI
|
|
PARAMETER ( ONE = 1.d0 )
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
SUMKRO = 0.d0
|
|
*
|
|
* Randomize Variable Order
|
|
*
|
|
NK = MIN( NDIM, KLIM )
|
|
DO J = 1, NK-1
|
|
CALL random_number(MVNUNI)
|
|
! JP = J + NINT(MVNUNI*DBLE( NK + 1 - J ))
|
|
JP = J + NINT(MVNUNI*DBLE( NK - J )) ! pab 21.11.2000
|
|
XT = VK(J)
|
|
VK(J) = VK(JP)
|
|
VK(JP) = XT
|
|
END DO
|
|
*
|
|
* Determine Random Shifts for each Variable
|
|
*
|
|
CALL random_number(X(NDIM+1:2*NDIM))
|
|
*
|
|
* Compute periodized and symmetrized lattice rule sum
|
|
*
|
|
DO K = 1, PRIME
|
|
X(1:NK) = MOD( DBLE(K)*VK(1:NK), ONE )
|
|
IF ( NDIM. GT. KLIM ) CALL DKRCHT(KLIM, NDIM-KLIM, X) !X(KLIM+1:NDIM) )
|
|
DO J = 1, NDIM
|
|
XT = X(J) + X(NDIM+J)
|
|
IF ( XT .GT. ONE ) XT = XT - 1.d0
|
|
X(J) = ABS( 2.d0*XT - 1.d0 )
|
|
END DO
|
|
SUMKRO = SUMKRO+(FUNCTN(NDIM,X)-SUMKRO)/DBLE(2*K-1)
|
|
X(1:NDIM) = 1.d0 - X(1:NDIM)
|
|
SUMKRO = SUMKRO+(FUNCTN(NDIM,X)-SUMKRO)/DBLE(2*K)
|
|
END DO
|
|
END SUBROUTINE DKSMRC
|
|
*
|
|
SUBROUTINE DKRCHT(KLIM, S, QUASI )
|
|
*
|
|
* This subroutine generates a new quasi-random Richtmeyer vector.
|
|
* A reference is
|
|
* "Methods of Numerical Integration", P.J. Davis and P. Rabinowitz,
|
|
* Academic Press, 1984, pp. 482-483.
|
|
*
|
|
* INPUTS:
|
|
* KLIM - Lower start value
|
|
* S - the number of dimensions;
|
|
* DKRCHT is initialized for each new S or S < 1.
|
|
*
|
|
* OUTPUTS:
|
|
* QUASI - a new quasi-random S-vector
|
|
*
|
|
* revised pab 28.05.2003
|
|
* - added klim in order to avoid copying of arrays in and out
|
|
* revised pab 01.11.1999
|
|
* updated to fortran 90
|
|
INTEGER, INTENT(IN) :: S,KLIM
|
|
DOUBLE PRECISION , DIMENSION(:) :: QUASI
|
|
INTEGER :: MXDIM, MXHSUM, B
|
|
PARAMETER ( MXDIM = 80, MXHSUM = 48, B = 2 )
|
|
INTEGER :: HISUM, I, OLDS
|
|
DOUBLE PRECISION , DIMENSION(MXDIM) :: PSQT
|
|
INTEGER, DIMENSION(MXDIM ) :: PRIME
|
|
INTEGER, DIMENSION(0:MXHSUM) :: N
|
|
|
|
|
|
DOUBLE PRECISION :: ONE, RN
|
|
PARAMETER ( ONE = 1.D0 )
|
|
PARAMETER ( PRIME = (/
|
|
& 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
|
|
& 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
|
|
& 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
|
|
& 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
|
|
& 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
|
|
& 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
|
|
& 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
|
|
& 353, 359, 367, 373, 379, 383, 389, 397, 401, 409/))
|
|
* Primes to continue
|
|
* 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499
|
|
* 503 509 521 523 541 547 557 563 569 571 577 587 593 599
|
|
SAVE OLDS, PSQT, HISUM, N
|
|
DATA OLDS / 0 /
|
|
IF ( S .NE. OLDS .OR. S .LT. 1 ) THEN
|
|
OLDS = ABS(S) ! pab 14.03.2000
|
|
N(0) = 0
|
|
HISUM = 0
|
|
DO I = 1, OLDS
|
|
RN = DBLE(PRIME(I))
|
|
PSQT(I) = SQRT( RN )
|
|
END DO
|
|
END IF
|
|
DO I = 0, HISUM
|
|
N(I) = N(I) + 1
|
|
IF ( N(I) .LT. B ) GO TO 10
|
|
N(I) = 0
|
|
END DO
|
|
HISUM = HISUM + 1
|
|
IF ( HISUM .GT. MXHSUM ) HISUM = 0
|
|
N(HISUM) = 1
|
|
10 RN = 0.d0
|
|
DO I = HISUM, 0, -1
|
|
RN = DBLE(N(I)) + DBLE(B)*RN
|
|
END DO
|
|
DO I = 1, OLDS
|
|
QUASI(KLIM+I) = MOD( RN*PSQT(I), ONE )
|
|
END DO
|
|
END SUBROUTINE DKRCHT
|
|
!
|
|
! SOBSEQ is not taken in to use:
|
|
!
|
|
SUBROUTINE SOBSEQ(N,X)
|
|
IMPLICIT NONE
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(OUT):: X
|
|
INTEGER, INTENT(IN) :: N
|
|
INTEGER,PARAMETER ::MAXBIT=30,MAXDIM=6
|
|
INTEGER :: I,IM, IN,IPP,J,K,L, OLDN
|
|
INTEGER, DIMENSION(MAXDIM) :: IP,MDEG,IX
|
|
INTEGER, DIMENSION(MAXDIM,MAXBIT) ::IU
|
|
INTEGER, DIMENSION(MAXDIM*MAXBIT) ::IV
|
|
DOUBLE PRECISION :: FAC
|
|
SAVE IP,MDEG,IX,IV,IN,FAC, OLDN
|
|
DATA OLDN / 0 /
|
|
DATA IP /0,1,1,2,1,4 /, MDEG /1,2,3,3,4,4 /
|
|
DATA IX /0,0,0,0,0,0 /
|
|
DATA IV /1,1,1,1,1,1,3,1,3,3,1,1,5,
|
|
& 7,7,3,3,5,15,11,5,15,13,9,156*0/
|
|
!(MAXDIM*MAXBIT-24)
|
|
EQUIVALENCE (IV,IU) ! to allow both 1D and 2D addressing
|
|
! returns sobols sequence of quasi-random numbers between 0 1
|
|
! When n is new or is negative, internally initializes a set of MAXBIT
|
|
! direction numbers for each of MAXDIM different sobol
|
|
! sequences. When n is positive (but < MAXDIM)
|
|
! returns as the vector x(1:n) the next values from n of these sequences
|
|
! (n must not be changed between initializations)
|
|
!
|
|
! This routine is initialised for maximum of n=6 dimensions
|
|
! and a word length of 30 bits. These parameter may be increased by
|
|
!changing MAXBIT and MAXDIM and add more initializing data to
|
|
! ip (primitive polynomials), mdeg (their degrees) and iv
|
|
! (the starting value for the recurrence relation)
|
|
|
|
!reference
|
|
! William H. Press, Saul Teukolsky, William T. Wetterling and Brian P. Flannery (1997)
|
|
! "Numerical recipes in Fortran 77", Vol. 1, pp 299--305
|
|
|
|
|
|
IF (N.LT.0 .OR. OLDN.NE.N ) THEN ! INITIALIZE, DO NOT RETURN VECTOR
|
|
OLDN = ABS(N)
|
|
IX=0
|
|
IN=0 ! RANDOM STARTPOINT: CALL RANDOM_NUMBER(P); IN=P*2^MAXBIT
|
|
! AND REMOVE WARNING MESSAGE BELOW
|
|
!IF (IV(1).NE.1) RETURN
|
|
|
|
IF (IV(1).EQ.1) THEN
|
|
FAC=1.D0/2.D0**MAXBIT
|
|
DO K=1,MAXDIM
|
|
DO J=1,MDEG(K) ! STORED VALUES NEED NORMALIZATION
|
|
IU(K,J)=IU(K,J)*2**(MAXBIT-J)
|
|
ENDDO
|
|
DO J=1,MDEG(K)+1,MAXBIT ! USE RECCURENCE TO GET OTHER VALUES
|
|
IPP=IP(K)
|
|
I=IU(K,J-MDEG(K))
|
|
I=IEOR(I,I/2**MDEG(K))
|
|
DO L=MDEG(K)-1,1,-1
|
|
IF (IAND(IPP,1).NE.0) I=IEOR(I,IU(K,J-L))
|
|
IPP=IPP/2
|
|
ENDDO
|
|
IU(K,J)=I
|
|
ENDDO
|
|
ENDDO
|
|
ENDIF
|
|
ENDIF ! CALCULATE THE NEXT VECTOR IN THE SEQUENCE
|
|
IM=IN
|
|
DO J=1,MAXBIT ! FIND THE RIGHTMOST ZERO BIT
|
|
IF (IAND(IM,1).EQ.0) GOTO 1
|
|
IM=IM/2
|
|
ENDDO
|
|
! PRINT *,'MAXBIT TOO SMALL IN SOBSEQ'
|
|
1 IM=(J-1)*MAXDIM
|
|
DO K=1,MIN(OLDN,MAXDIM) !XOR THE
|
|
IX(K)=IEOR(IX(K),IV(IM+K))
|
|
X(K)=IX(K)*FAC
|
|
ENDDO
|
|
IN=IN+1 ! INCREMENT COUNTER
|
|
|
|
RETURN
|
|
END SUBROUTINE SOBSEQ
|
|
END MODULE KRBVRCMOD
|
|
|
|
MODULE DKBVRCMOD
|
|
IMPLICIT NONE
|
|
PRIVATE
|
|
PUBLIC :: DKBVRC
|
|
!
|
|
INTERFACE DKBVRC
|
|
MODULE PROCEDURE DKBVRC
|
|
END INTERFACE
|
|
!
|
|
INTERFACE DKSMRC
|
|
MODULE PROCEDURE DKSMRC
|
|
END INTERFACE
|
|
!
|
|
CONTAINS
|
|
SUBROUTINE DKBVRC( NDIM, MINVLS, MAXVLS, FUNCTN, ABSEPS, RELEPS,
|
|
& ABSERR, FINEST, INFORM )
|
|
*
|
|
* Automatic Multidimensional Integration Subroutine
|
|
*
|
|
* AUTHOR: Alan Genz
|
|
* Department of Mathematics
|
|
* Washington State University
|
|
* Pulman, WA 99164-3113
|
|
* Email: AlanGenz@wsu.edu
|
|
*
|
|
* Last Change: 1/15/03
|
|
*
|
|
! revised pab June 2004
|
|
! updated to F90
|
|
*
|
|
* DKBVRC computes an approximation to the integral
|
|
*
|
|
* 1 1 1
|
|
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
|
|
* 0 0 0
|
|
*
|
|
*
|
|
* DKBVRC uses randomized Korobov rules for the first 100 variables.
|
|
* The primary references are
|
|
* "Randomization of Number Theoretic Methods for Multiple Integration"
|
|
* R. Cranley and T.N.L. Patterson, SIAM J Numer Anal, 13, pp. 904-14,
|
|
* and
|
|
* "Optimal Parameters for Multidimensional Integration",
|
|
* P. Keast, SIAM J Numer Anal, 10, pp.831-838.
|
|
* If there are more than 100 variables, the remaining variables are
|
|
* integrated using the rules described in the reference
|
|
* "On a Number-Theoretical Integration Method"
|
|
* H. Niederreiter, Aequationes Mathematicae, 8(1972), pp. 304-11.
|
|
*
|
|
*************** Parameters ********************************************
|
|
****** Input parameters
|
|
* NDIM Number of variables, must exceed 1, but not exceed 1000
|
|
* MINVLS Integer minimum number of function evaluations allowed.
|
|
* MINVLS must not exceed MAXVLS. If MINVLS < 0 then the
|
|
* routine assumes a previous call has been made with
|
|
* the same integrand and continues that calculation.
|
|
* MAXVLS Integer maximum number of function evaluations allowed.
|
|
* FUNCTN EXTERNALly declared user defined function to be integrated.
|
|
* It must have parameters (NDIM,Z), where Z is a real array
|
|
* of dimension NDIM.
|
|
*
|
|
* ABSEPS Required absolute accuracy.
|
|
* RELEPS Required relative accuracy.
|
|
****** Output parameters
|
|
* MINVLS Actual number of function evaluations used.
|
|
* ABSERR Estimated absolute accuracy of FINEST.
|
|
* FINEST Estimated value of integral.
|
|
* INFORM INFORM = 0 for normal exit, when
|
|
* ABSERR <= MAX(ABSEPS, RELEPS*ABS(FINEST))
|
|
* and
|
|
* INTVLS <= MAXCLS.
|
|
* INFORM = 1 If MAXVLS was too small to obtain the required
|
|
* accuracy. In this case a value FINEST is returned with
|
|
* estimated absolute accuracy ABSERR.
|
|
* INFORM = 2 If NDIM>1000 or NDIM<1
|
|
************************************************************************
|
|
INTEGER, INTENT(IN) :: NDIM, MAXVLS
|
|
INTEGER, INTENT(INOUT) :: MINVLS
|
|
INTEGER, INTENT(OUT) :: INFORM
|
|
DOUBLE PRECISION, INTENT(IN) :: ABSEPS, RELEPS
|
|
DOUBLE PRECISION, INTENT(OUT) :: FINEST, ABSERR
|
|
INTEGER :: NP,PLIM,NLIM,KLIM,KLIMI,SAMPLS,I,INTVLS,MINSMP
|
|
PARAMETER ( PLIM = 28, NLIM = 1000, KLIM = 100, MINSMP = 8 )
|
|
INTEGER P(PLIM), C(PLIM,KLIM-1)
|
|
DOUBLE PRECISION :: DIFINT, FINVAL, VARSQR, VAREST, VARPRD, VALUE
|
|
DOUBLE PRECISION, PARAMETER :: ONE= 1.D0,ZERO = 0.D0
|
|
DOUBLE PRECISION X(2*NLIM), VK(NLIM)
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
SAVE P, C, SAMPLS, NP, VAREST
|
|
IF ( NDIM .GT. NLIM .OR. NDIM .LT. 1 ) THEN
|
|
INFORM = 2
|
|
FINEST = ZERO
|
|
ABSERR = ONE
|
|
RETURN
|
|
ENDIF
|
|
INFORM = 1
|
|
INTVLS = 0
|
|
KLIMI = KLIM
|
|
IF ( MINVLS .GE. 0 ) THEN
|
|
FINEST = ZERO
|
|
VAREST = ZERO
|
|
SAMPLS = MINSMP
|
|
DO I = 1, PLIM
|
|
NP = I
|
|
IF ( MINVLS .LT. 2*SAMPLS*P(I) ) GO TO 10
|
|
END DO
|
|
SAMPLS = MAX( MINSMP, MINVLS/( 2*P(NP) ) )
|
|
ENDIF
|
|
10 VK(1) = ONE/P(NP)
|
|
DO I = 2, NDIM
|
|
IF ( I .LE. KLIM ) THEN
|
|
VK(I) = MOD( C(NP, MIN(NDIM-1,KLIM-1))*VK(I-1), ONE )
|
|
ELSE
|
|
VK(I) = INT( P(NP)*2**(DBLE(I-KLIM)/(NDIM-KLIM+1)) )
|
|
VK(I) = MOD( VK(I)/P(NP), ONE )
|
|
END IF
|
|
END DO
|
|
FINVAL = ZERO
|
|
VARSQR = ZERO
|
|
DO I = 1, SAMPLS
|
|
CALL DKSMRC( NDIM, KLIMI, VALUE, P(NP), VK, FUNCTN, X )
|
|
DIFINT = ( VALUE - FINVAL )/DBLE(I)
|
|
FINVAL = FINVAL + DIFINT
|
|
VARSQR = DBLE( I - 2 )*VARSQR/DBLE(I) + DIFINT**2
|
|
END DO
|
|
INTVLS = INTVLS + 2*SAMPLS*P(NP)
|
|
VARPRD = VAREST*VARSQR
|
|
FINEST = FINEST + ( FINVAL - FINEST )/( ONE + VARPRD )
|
|
IF ( VARSQR .GT. ZERO ) VAREST = ( ONE + VARPRD )/VARSQR
|
|
ABSERR = 3.0D0*SQRT( VARSQR/( ONE + VARPRD ) )
|
|
IF ( ABSERR .GT. MAX( ABSEPS, ABS(FINEST)*RELEPS ) ) THEN
|
|
IF ( NP .LT. PLIM ) THEN
|
|
NP = NP + 1
|
|
ELSE
|
|
SAMPLS = MIN( 3*SAMPLS/2, ( MAXVLS - INTVLS )/( 2*P(NP) ) )
|
|
SAMPLS = MAX( MINSMP, SAMPLS )
|
|
ENDIF
|
|
IF ( INTVLS + 2*SAMPLS*P(NP) .LE. MAXVLS ) GO TO 10
|
|
ELSE
|
|
INFORM = 0
|
|
ENDIF
|
|
MINVLS = INTVLS
|
|
*
|
|
* Optimal Parameters for Lattice Rules
|
|
*
|
|
DATA P( 1),(C( 1,I),I = 1,99)/ 31, 12, 2*9, 13, 8*12, 3*3, 12,
|
|
& 2*7, 9*12, 3*3, 12, 2*7, 9*12, 3*3, 12, 2*7, 9*12, 3*3, 12, 2*7,
|
|
& 8*12, 7, 3*3, 3*7, 21*3/
|
|
DATA P( 2),(C( 2,I),I = 1,99)/ 47, 13, 11, 17, 10, 6*15,
|
|
& 22, 2*15, 3*6, 2*15, 9, 13, 3*2, 13, 2*11, 10, 9*15, 3*6, 2*15,
|
|
& 9, 13, 3*2, 13, 2*11, 10, 9*15, 3*6, 2*15, 9, 13, 3*2, 13, 2*11,
|
|
& 2*10, 8*15, 6, 2, 3, 2, 3, 12*2/
|
|
DATA P( 3),(C( 3,I),I = 1,99)/ 73, 27, 28, 10, 2*11, 20,
|
|
& 2*11, 28, 2*13, 28, 3*13, 16*14, 2*31, 3*5, 31, 13, 6*11, 7*13,
|
|
& 16*14, 2*31, 3*5, 11, 13, 7*11, 2*13, 11, 13, 4*5, 14, 13, 8*5/
|
|
DATA P( 4),(C( 4,I),I = 1,99)/ 113, 35, 2*27, 36, 22, 2*29,
|
|
& 20, 45, 3*5, 16*21, 29, 10*17, 12*23, 21, 27, 3*3, 24, 2*27,
|
|
& 17, 3*29, 17, 4*5, 16*21, 3*17, 6, 2*17, 6, 3, 2*6, 5*3/
|
|
DATA P( 5),(C( 5,I),I = 1,99)/ 173, 64, 66, 2*28, 2*44, 55,
|
|
& 67, 6*10, 2*38, 5*10, 12*49, 2*38, 31, 2*4, 31, 64, 3*4, 64,
|
|
& 6*45, 19*66, 11, 9*66, 45, 11, 7, 3, 3*2, 27, 5, 2*3, 2*5, 7*2/
|
|
DATA P( 6),(C( 6,I),I = 1,99)/ 263, 111, 42, 54, 118, 20,
|
|
& 2*31, 72, 17, 94, 2*14, 11, 3*14, 94, 4*10, 7*14, 3*11, 7*8,
|
|
& 5*18, 113, 2*62, 2*45, 17*113, 2*63, 53, 63, 15*67, 5*51, 12,
|
|
& 51, 12, 51, 5, 2*3, 2*2, 5/
|
|
DATA P( 7),(C( 7,I),I = 1,99)/ 397, 163, 154, 83, 43, 82,
|
|
& 92, 150, 59, 2*76, 47, 2*11, 100, 131, 6*116, 9*138, 21*101,
|
|
& 6*116, 5*100, 5*138, 19*101, 8*38, 5*3/
|
|
DATA P( 8),(C( 8,I),I = 1,99)/ 593, 246, 189, 242, 102,
|
|
& 2*250, 102, 250, 280, 118, 196, 118, 191, 215, 2*121,
|
|
& 12*49, 34*171, 8*161, 17*14, 6*10, 103, 4*10, 5/
|
|
DATA P( 9),(C( 9,I),I = 1,99)/ 907, 347, 402, 322, 418,
|
|
& 215, 220, 3*339, 337, 218, 4*315, 4*167, 361, 201, 11*124,
|
|
& 2*231, 14*90, 4*48, 23*90, 10*243, 9*283, 16, 283, 16, 2*283/
|
|
DATA P(10),(C(10,I),I = 1,99)/ 1361, 505, 220, 601, 644,
|
|
& 612, 160, 3*206, 422, 134, 518, 2*134, 518, 652, 382,
|
|
& 206, 158, 441, 179, 441, 56, 2*559, 14*56, 2*101, 56,
|
|
& 8*101, 7*193, 21*101, 17*122, 4*101/
|
|
DATA P(11),(C(11,I),I = 1,99)/ 2053, 794, 325, 960, 528,
|
|
& 2*247, 338, 366, 847, 2*753, 236, 2*334, 461, 711, 652,
|
|
& 3*381, 652, 7*381, 226, 7*326, 126, 10*326, 2*195, 19*55,
|
|
& 7*195, 11*132, 13*387/
|
|
DATA P(12),(C(12,I),I = 1,99)/ 3079, 1189, 888, 259, 1082, 725,
|
|
& 811, 636, 965, 2*497, 2*1490, 392, 1291, 2*508, 2*1291, 508,
|
|
& 1291, 2*508, 4*867, 934, 7*867, 9*1284, 4*563, 3*1010, 208,
|
|
& 838, 3*563, 2*759, 564, 2*759, 4*801, 5*759, 8*563, 22*226/
|
|
DATA P(13),(C(13,I),I = 1,99)/ 4621, 1763, 1018, 1500, 432,
|
|
& 1332, 2203, 126, 2240, 1719, 1284, 878, 1983, 4*266,
|
|
& 2*747, 2*127, 2074, 127, 2074, 1400, 10*1383, 1400, 7*1383,
|
|
& 507, 4*1073, 5*1990, 9*507, 17*1073, 6*22, 1073, 6*452, 318,
|
|
& 4*301, 2*86, 15/
|
|
DATA P(14),(C(14,I),I = 1,99)/ 6947, 2872, 3233, 1534, 2941,
|
|
& 2910, 393, 1796, 919, 446, 2*919, 1117, 7*103, 2311, 3117, 1101,
|
|
& 2*3117, 5*1101, 8*2503, 7*429, 3*1702, 5*184, 34*105, 13*784/
|
|
DATA P(15),(C(15,I),I = 1,99)/ 10427, 4309, 3758, 4034, 1963,
|
|
& 730, 642, 1502, 2246, 3834, 1511, 2*1102, 2*1522, 2*3427,
|
|
& 3928, 2*915, 4*3818, 3*4782, 3818, 4782, 2*3818, 7*1327, 9*1387,
|
|
& 13*2339, 18*3148, 3*1776, 3*3354, 925, 2*3354, 5*925, 8*2133/
|
|
DATA P(16),(C(16,I),I = 1,99)/ 15641, 6610, 6977, 1686, 3819,
|
|
& 2314, 5647, 3953, 3614, 5115, 2*423, 5408, 7426, 2*423,
|
|
& 487, 6227, 2660, 6227, 1221, 3811, 197, 4367, 351,
|
|
& 1281, 1221, 3*351, 7245, 1984, 6*2999, 3995, 4*2063, 1644,
|
|
& 2063, 2077, 3*2512, 4*2077, 19*754, 2*1097, 4*754, 248, 754,
|
|
& 4*1097, 4*222, 754,11*1982/
|
|
DATA P(17),(C(17,I),I = 1,99)/ 23473, 9861, 3647, 4073, 2535,
|
|
& 3430, 9865, 2830, 9328, 4320, 5913, 10365, 8272, 3706, 6186,
|
|
& 3*7806, 8610, 2563, 2*11558, 9421, 1181, 9421, 3*1181, 9421,
|
|
& 2*1181, 2*10574, 5*3534, 3*2898, 3450, 7*2141, 15*7055, 2831,
|
|
& 24*8204, 3*4688, 8*2831/
|
|
DATA P(18),(C(18,I),I = 1,99)/ 35221, 10327, 7582, 7124, 8214,
|
|
& 9600, 10271, 10193, 10800, 9086, 2365, 4409, 13812,
|
|
& 5661, 2*9344, 10362, 2*9344, 8585, 11114, 3*13080, 6949,
|
|
& 3*3436, 13213, 2*6130, 2*8159, 11595, 8159, 3436, 18*7096,
|
|
& 4377, 7096, 5*4377, 2*5410, 32*4377, 2*440, 3*1199/
|
|
DATA P(19),(C(19,I),I = 1,99)/ 52837, 19540, 19926, 11582,
|
|
& 11113, 24585, 8726, 17218, 419, 3*4918, 15701, 17710,
|
|
& 2*4037, 15808, 11401, 19398, 2*25950, 4454, 24987, 11719,
|
|
& 8697, 5*1452, 2*8697, 6436, 21475, 6436, 22913, 6434, 18497,
|
|
& 4*11089, 2*3036, 4*14208, 8*12906, 4*7614, 6*5021, 24*10145,
|
|
& 6*4544, 4*8394/
|
|
DATA P(20),(C(20,I),I = 1,99)/ 79259, 34566, 9579, 12654,
|
|
& 26856, 37873, 38806, 29501, 17271, 3663, 10763, 18955,
|
|
& 1298, 26560, 2*17132, 2*4753, 8713, 18624, 13082, 6791,
|
|
& 1122, 19363, 34695, 4*18770, 15628, 4*18770, 33766, 6*20837,
|
|
& 5*6545, 14*12138, 5*30483, 19*12138, 9305, 13*11107, 2*9305/
|
|
DATA P(21),(C(21,I),I = 1,99)/118891, 31929, 49367, 10982, 3527,
|
|
& 27066, 13226, 56010, 18911, 40574, 2*20767, 9686, 2*47603,
|
|
& 2*11736, 41601, 12888, 32948, 30801, 44243, 2*53351, 16016,
|
|
& 2*35086, 32581, 2*2464, 49554, 2*2464, 2*49554, 2464, 81, 27260,
|
|
& 10681, 7*2185, 5*18086, 2*17631, 3*18086, 37335, 3*37774,
|
|
& 13*26401, 12982, 6*40398, 3*3518, 9*37799, 4*4721, 4*7067/
|
|
DATA P(22),(C(22,I),I = 1,99)/178349, 40701, 69087, 77576, 64590,
|
|
& 39397, 33179, 10858, 38935, 43129, 2*35468, 5279, 2*61518, 27945,
|
|
& 2*70975, 2*86478, 2*20514, 2*73178, 2*43098, 4701,
|
|
& 2*59979, 58556, 69916, 2*15170, 2*4832, 43064, 71685, 4832,
|
|
& 3*15170, 3*27679, 2*60826, 2*6187, 5*4264, 45567, 4*32269,
|
|
& 9*62060, 13*1803, 12*51108, 2*55315, 5*54140, 13134/
|
|
DATA P(23),(C(23,I),I = 1,99)/267523, 103650, 125480, 59978,
|
|
& 46875, 77172, 83021, 126904, 14541, 56299, 43636, 11655,
|
|
& 52680, 88549, 29804, 101894, 113675, 48040, 113675,
|
|
& 34987, 48308, 97926, 5475, 49449, 6850, 2*62545, 9440,
|
|
& 33242, 9440, 33242, 9440, 33242, 9440, 62850, 3*9440,
|
|
& 3*90308, 9*47904, 7*41143, 5*36114, 24997, 14*65162, 7*47650,
|
|
& 7*40586, 4*38725, 5*88329/
|
|
DATA P(24),(C(24,I),I = 1,99)/401287, 165843, 90647, 59925,
|
|
& 189541, 67647, 74795, 68365, 167485, 143918, 74912,
|
|
& 167289, 75517, 8148, 172106, 126159,3*35867, 121694,
|
|
& 52171, 95354, 2*113969, 76304, 2*123709, 144615, 123709,
|
|
& 2*64958, 32377, 2*193002, 25023, 40017, 141605, 2*189165,
|
|
& 141605, 2*189165, 3*141605, 189165, 20*127047, 10*127785,
|
|
& 6*80822, 16*131661, 7114, 131661/
|
|
DATA P(25),(C(25,I),I = 1,99)/601943, 130365, 236711, 110235,
|
|
& 125699, 56483, 93735, 234469, 60549, 1291, 93937,
|
|
& 245291, 196061, 258647, 162489, 176631, 204895, 73353,
|
|
& 172319, 28881, 136787,2*122081, 275993, 64673, 3*211587,
|
|
& 2*282859, 211587, 242821, 3*256865, 122203, 291915, 122203,
|
|
& 2*291915, 122203, 2*25639, 291803, 245397, 284047,
|
|
& 7*245397, 94241, 2*66575, 19*217673, 10*210249, 15*94453/
|
|
DATA P(26),(C(26,I),I = 1,99)/902933, 333459, 375354, 102417,
|
|
& 383544, 292630, 41147, 374614, 48032, 435453, 281493, 358168,
|
|
& 114121, 346892, 238990, 317313, 164158, 35497, 2*70530, 434839,
|
|
& 3*24754, 393656, 2*118711, 148227, 271087, 355831, 91034,
|
|
& 2*417029, 2*91034, 417029, 91034, 2*299843, 2*413548, 308300,
|
|
& 3*413548, 3*308300, 413548, 5*308300, 4*15311, 2*176255, 6*23613,
|
|
& 172210, 4* 204328, 5*121626, 5*200187, 2*121551, 12*248492,
|
|
& 5*13942/
|
|
DATA P(27), (C(27,I), I = 1,99)/ 1354471, 500884, 566009, 399251,
|
|
& 652979, 355008, 430235, 328722, 670680, 2*405585, 424646,
|
|
& 2*670180, 641587, 215580, 59048, 633320, 81010, 20789, 2*389250,
|
|
& 2*638764, 2*389250, 398094, 80846, 2*147776, 296177, 2*398094,
|
|
& 2*147776, 396313, 3*578233, 19482, 620706, 187095, 620706,
|
|
& 187095, 126467, 12*241663, 321632, 2*23210, 3*394484, 3*78101,
|
|
& 19*542095, 3*277743, 12*457259/
|
|
DATA P(28), (C(28,I), I = 1, 99)/ 2031713, 858339, 918142, 501970,
|
|
& 234813, 460565, 31996, 753018, 256150, 199809, 993599, 245149,
|
|
& 794183, 121349, 150619, 376952, 2*809123, 804319, 67352, 969594,
|
|
& 434796, 969594, 804319, 391368, 761041, 754049, 466264, 2*754049,
|
|
& 466264, 2*754049, 282852, 429907, 390017, 276645, 994856, 250142,
|
|
& 144595, 907454, 689648, 4*687580, 978368, 687580, 552742, 105195,
|
|
& 942843, 768249, 4*307142, 7*880619, 11*117185, 11*60731,
|
|
& 4*178309, 8*74373, 3*214965/
|
|
*
|
|
END SUBROUTINE DKBVRC
|
|
*
|
|
SUBROUTINE DKSMRC( NDIM, KLIM, SUMKRO, PRIME, VK, FUNCTN, X )
|
|
INTEGER, INTENT(IN):: NDIM, KLIM, PRIME
|
|
DOUBLE PRECISION, INTENT(OUT) :: SUMKRO
|
|
DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: VK,X
|
|
INTEGER :: K, J, JP, NK
|
|
DOUBLE PRECISION :: ONE, XT, MVNUNI
|
|
PARAMETER ( ONE = 1.d0 )
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
SUMKRO = 0.D0
|
|
*
|
|
* Randomize Variable Order
|
|
*
|
|
NK = MIN( NDIM, KLIM )
|
|
DO J = 1, NK - 1
|
|
CALL random_number(MVNUNI)
|
|
! JP = J + MVNUNI()*( NK + 1 - J )
|
|
JP = J + NINT(MVNUNI*DBLE( NK - J )) ! pab 12 May 2004
|
|
|
|
XT = VK(J)
|
|
VK(J) = VK(JP)
|
|
VK(JP) = XT
|
|
END DO
|
|
*
|
|
* Determine Random Shifts for each Variable
|
|
*
|
|
CALL random_number(X(NDIM+1:2*NDIM))
|
|
DO K = 1, PRIME
|
|
X(1:NDIM) = ABS( 2.d0*MOD( DBLE(K)*VK(1:NDIM) +
|
|
& X(NDIM+1:2*NDIM), ONE ) - ONE )
|
|
! DO J = 1, NDIM
|
|
! X(J) = ABS( 2*MOD( K*VK(J) + X(NDIM+J), ONE ) - ONE )
|
|
! END DO
|
|
SUMKRO = SUMKRO + ( FUNCTN(NDIM,X) - SUMKRO )/DBLE( 2*K - 1 )
|
|
X(1:NDIM) = ONE - X(1:NDIM)
|
|
SUMKRO = SUMKRO + ( FUNCTN(NDIM,X) - SUMKRO )/DBLE( 2*K )
|
|
END DO
|
|
END SUBROUTINE DKSMRC
|
|
END MODULE DKBVRCMOD
|
|
|
|
MODULE PRECISIONMOD
|
|
IMPLICIT NONE
|
|
PUBLIC
|
|
! Note double precision is the fastest choice for x86 machines
|
|
! double (15,307) single (6,37) precision constants
|
|
INTEGER, PARAMETER :: gP = SELECTED_REAL_KIND(15,307)
|
|
END MODULE PRECISIONMOD
|
|
|
|
MODULE SSOBOLMOD
|
|
USE PRECISIONMOD
|
|
IMPLICIT NONE
|
|
PRIVATE
|
|
PUBLIC :: initSobol, sobolSeq, sobnied
|
|
|
|
! BLOCK DATA BDSOBL
|
|
!
|
|
! INITIALIZES LABELLED COMMON /SOBDAT/
|
|
! FOR "INSOBL".
|
|
!
|
|
! THE ARRAY POLY GIVES SUCCESSIVE PRIMITIVE
|
|
! POLYNOMIALS CODED IN BINARY, E.G.
|
|
! 45 = 100101
|
|
! HAS BITS 5, 2, AND 0 SET (COUNTING FROM THE
|
|
! RIGHT) AND THEREFORE REPRESENTS
|
|
! X**5 + X**2 + X**0
|
|
!
|
|
! THESE POLYNOMIALS ARE IN THE ORDER USED BY
|
|
! SOBOL IN USSR COMPUT. MATHS. MATH. PHYS. 16 (1977),
|
|
! 236-242. A MORE COMPLETE TABLE IS GIVEN IN SOBOL AND
|
|
! LEVITAN, THE PRODUCTION OF POINTS UNIFORMLY
|
|
! DISTRIBUTED IN A MULTIDIMENSIONAL CUBE (IN RUSSIAN),
|
|
! PREPRINT IPM AKAD. NAUK SSSR, NO. 40, MOSCOW 1976.
|
|
!
|
|
! THE INITIALIZATION OF THE ARRAY mVINIT IS FROM THE
|
|
! LATTER PAPER. FOR A POLYNOMIAL OF DEGREE M, M INITIAL
|
|
! VALUES ARE NEEDED : THESE ARE THE VALUES GIVEN HERE.
|
|
! SUBSEQUENT VALUES ARE CALCULATED IN "INSOBL".
|
|
!
|
|
! ASSUME WE ARE WORKING ON A COMPUTER WITH
|
|
! WORD LENGTH AT LEAST mMaxBit BITS EXCLUDING SIGN.
|
|
integer :: mI
|
|
integer, parameter :: mMaxBit = 31
|
|
integer, parameter :: mMaxDim = 40
|
|
integer, parameter :: mMaxAtMost = 2**(mMaxBit-1)
|
|
!COMMON SOBOL
|
|
! mSV TABLE OF DIRECTION NUMBERS
|
|
! mS DIMENSION
|
|
! mMAXCOL LAST COLUMN OF V TO BE USED
|
|
! mCOUNT SEQUENCE NUMBER OF THIS CALL
|
|
! mLASTQ NUMERATORS FOR LAST VECTOR GENERATED
|
|
! mRECIPD (1/DENOMINATOR) FOR THESE NUMERATORS
|
|
INTEGER, dimension(mMaxDim,mMaxBit), SAVE :: mSV
|
|
INTEGER, dimension(mMaxDim), SAVE :: mLASTQ
|
|
INTEGER, SAVE :: mS,mMAXCOL,mCOUNT,mATMOST
|
|
REAL(KIND=gP), save :: mRECIPD
|
|
! COMMON SOBDAT
|
|
INTEGER, save, dimension(2:mMaxDim) :: mPOLY
|
|
integer, save, dimension(2:mMaxDim,8) :: mVINIT
|
|
|
|
DATA mPOLY /3,7,11,13,19,25,37,59,47,
|
|
& 61,55,41,67,97,91,109,103,115,131,
|
|
& 193,137,145,143,241,157,185,167,229,171,
|
|
& 213,191,253,203,211,239,247,285,369,299/
|
|
!
|
|
DATA (mVINIT(mI,1),mI=2,40) /39*1/
|
|
DATA (mVINIT(mI,2),mI=3,40) /1,3,1,3,1,3,3,1,
|
|
& 3,1,3,1,3,1,1,3,1,3,
|
|
& 1,3,1,3,3,1,3,1,3,1,
|
|
& 3,1,1,3,1,3,1,3,1,3/
|
|
DATA (mVINIT(mI,3),mI=4,40) /7,5,1,3,3,7,5,
|
|
& 5,7,7,1,3,3,7,5,1,1,
|
|
& 5,3,3,1,7,5,1,3,3,7,
|
|
& 5,1,1,5,7,7,5,1,3,3/
|
|
DATA (mVINIT(mI,4),mI=6,40) /1,7,9,13,11,
|
|
& 1,3,7,9,5,13,13,11,3,15,
|
|
& 5,3,15,7,9,13,9,1,11,7,
|
|
& 5,15,1,15,11,5,3,1,7,9/
|
|
DATA (mVINIT(mI,5),mI=8,40) /9,3,27,
|
|
& 15,29,21,23,19,11,25,7,13,17,
|
|
& 1,25,29,3,31,11,5,23,27,19,
|
|
& 21,5,1,17,13,7,15,9,31,9/
|
|
DATA (mVINIT(mI,6),mI=14,40) /37,33,7,5,11,39,63,
|
|
& 27,17,15,23,29,3,21,13,31,25,
|
|
& 9,49,33,19,29,11,19,27,15,25/
|
|
DATA (mVINIT(mI,7),mI=20,40) /13,
|
|
& 33,115,41,79,17,29,119,75,73,105,
|
|
& 7,59,65,21,3,113,61,89,45,107/
|
|
DATA (mVINIT(mI,8),mI=38,40) /7,23,39/
|
|
|
|
INTERFACE getMSBP
|
|
MODULE PROCEDURE getMSBP
|
|
END INTERFACE
|
|
|
|
INTERFACE initSobol
|
|
MODULE PROCEDURE initSobol
|
|
END INTERFACE
|
|
|
|
INTERFACE GENSCRML
|
|
MODULE PROCEDURE GENSCRML
|
|
END INTERFACE
|
|
|
|
INTERFACE GENSCRMU
|
|
MODULE PROCEDURE GENSCRMU
|
|
END INTERFACE
|
|
|
|
INTERFACE sobolSeq
|
|
MODULE PROCEDURE sobolSeq
|
|
END INTERFACE
|
|
|
|
INTERFACE sobnied
|
|
MODULE PROCEDURE sobnied
|
|
END INTERFACE
|
|
|
|
INTERFACE dksmrc
|
|
MODULE PROCEDURE dksmrc
|
|
END INTERFACE
|
|
|
|
INTERFACE uni
|
|
MODULE PROCEDURE uni
|
|
END INTERFACE
|
|
|
|
CONTAINS
|
|
|
|
FUNCTION getMSBP(J) result (nb)
|
|
!getMSBP Returns the Most Significant Bit position
|
|
!
|
|
! CALL ix = getMSBP(x);
|
|
!
|
|
! ix = Most Significant Bit position
|
|
! x = number
|
|
!
|
|
! getMSBP calculates the most significant bit position in X that contains a
|
|
! one, i.e.,
|
|
! MSB(X) = max(i|2^i<=x) for X~=0
|
|
!
|
|
integer, intent(in) :: J
|
|
integer :: nb
|
|
integer :: I
|
|
nb = 0
|
|
I = J/2
|
|
DO WHILE (I>0)
|
|
nb = nb + 1
|
|
I = I / 2
|
|
ENDDO
|
|
end function getMSBP
|
|
|
|
SUBROUTINE initSobol(INFORM,TAUS,NDIM, ATMOST,
|
|
* NUMDS,IFLAG)
|
|
! InitSobol Initializes the sobol sequence
|
|
! Inputs:
|
|
! NDIM : Number of dimensions
|
|
! ATMOST : Maximum sequence length, i.e., upper bound on the number
|
|
! of calls the user intends to make on "ssobseq"
|
|
! NUMDS : Number of Digits to Scramble if IFLAG==1 or IFLAG==3
|
|
! IFLAG : integer defining scrambling of sequences:
|
|
! 0 : No Scrambling
|
|
! 1 : Owen type Scrambling
|
|
! 2 : Faure-Tezuka type Scrambling
|
|
! 3 : Owen + Faure-Tezuka type Scrambling
|
|
! Uses the member variables: mPOLY and mVINIT
|
|
! Outputs:
|
|
! INFORM = 0 If no error occurred otherwise
|
|
! 2 If NDIM < 1 .OR. mMaxDim < NDIM
|
|
! 3 If ATMOST < 1 .OR. mMaxAtMost <= ATMOST
|
|
! 4 If ((IFLAG==1 OR IFLAG==3) AND (mMaxBit < NUMDS))
|
|
! TAUS = Defines "FAVORABLE" values as
|
|
! discussed in BRATLEY/FOX. These have the form
|
|
! N = 2**K WHERE K .GE. (TAUS+NDIM-1) for integration
|
|
! and k .gt. taus for global optimization.
|
|
! If NDIM>12 then TAUS = -1
|
|
! Initializes the member variables:
|
|
! mSV, mS, mMAXCOL, mCOUNT, mLASTQ, mRECIPD, mATMOST
|
|
! Used in SOBOLSEQ
|
|
!
|
|
! InitSobol initializes member variables for scrambled sobol sequence
|
|
!
|
|
!
|
|
! THIS IS MODIFIED ROUTINE OF "INSOBL".
|
|
!
|
|
! NEXT CHECK "ATMOST", AN UPPER BOUND ON THE NUMBER
|
|
! OF CALLS THE USER INTENDS TO MAKE ON "GOSOBL". IF
|
|
! THIS IS POSITIVE AND LESS THAN mMaxAtMost = 2**(mMaxBit-1),
|
|
! THEN FLAG(2) = .TRUE.
|
|
! (WE ASSUME WE ARE WORKING ON A COMPUTER WITH
|
|
! WORD LENGTH AT LEAST mMaxBit BITS EXCLUDING SIGN.)
|
|
! THE NUMBER OF COLUMNS OF THE ARRAY V WHICH
|
|
! ARE INITIALIZED IS
|
|
! mMAXCOL = NUMBER OF BITS IN ATMOST.
|
|
! IN "GOSOBL" WE CHECK THAT THIS IS NOT EXCEEDED.
|
|
!
|
|
! THE LEADING ELEMENTS OF EACH ROW OF V ARE
|
|
! INITIALIZED USING "mVINIT" FROM "BDSOBL".
|
|
! EACH ROW CORRESPONDS TO A PRIMITIVE POLYNOMIAL
|
|
! (AGAIN, SEE "BDSOBL"). IF THE POLYNOMIAL HAS
|
|
! DEGREE M, ELEMENTS AFTER THE FIRST M ARE CALCULATED.
|
|
!
|
|
! THE NUMBERS IN V ARE ACTUALLY BINARY FRACTIONS.
|
|
! LSM ARE LOWER TRIAUGULAR SCRAMBLING MATRICES.
|
|
! USM ARE UPPER TRIAUGULAR SCRMABLING MATRIX.
|
|
! mSV ARE SCAMBLING GENERATING MATRICES AND THE NUMBERS
|
|
! ARE BINARY FRACTIONS.
|
|
! "mRECIPD" HOLDS 1/(THE COMMON DENOMINATOR OF ALL
|
|
! OF THEM).
|
|
!
|
|
!
|
|
! "INSSOBL" IMPLICITLY COMPUTES THE FIRST SHIFTED
|
|
! VECTOR "mLASTQ", AND RETURN IT TO THE CALLING
|
|
! PROGRAM. SUBSEQUENT VECTORS COME FROM "GOSSOBL".
|
|
! "mLASTQ" HOLDS NUMERATORS OF THE LAST VECTOR GENERATED.
|
|
!
|
|
!
|
|
integer, intent(in) :: NDIM,ATMOST,NUMDS,IFLAG
|
|
INTEGER, INTENT(OUT) :: INFORM,TAUS
|
|
! REAL(kind=gP), dimension(:), intent(out) :: QUASI
|
|
INTEGER, dimension(mMaxDim,mMaxBit) :: V, LSM
|
|
integer, dimension(mMaxBit,mMaxBit) :: USM
|
|
integer, dimension(mMaxDim,mMaxBit,mMaxBit) :: TV
|
|
integer, dimension(mMaxDim) :: SHIFT
|
|
integer, dimension(mMaxBit) :: USHIFT
|
|
INTEGER, dimension(13),save :: TAU
|
|
INTEGER I,J,K,P,M,NEWV,L,PP
|
|
INTEGER TEMP1,TEMP2,TEMP3,TEMP4,MAXX
|
|
REAL(KIND=gP) :: LL
|
|
LOGICAL, dimension(8) :: INCLUD
|
|
! EXTERNAL IEOR
|
|
! COMMON /SOBDAT/ mPOLY,mVINIT
|
|
! COMMON /SOBOL/ mS,mMAXCOL,mSV,mCOUNT,mLASTQ,mRECIPD
|
|
! SAVE /SOBDAT/,/SOBOL/
|
|
DATA TAU /0,0,1,3,5,8,11,15,19,23,27,31,35/
|
|
inform = 0
|
|
mMAXCOL = 0
|
|
mS = NDIM
|
|
mATMOST = ATMOST
|
|
IF (mS < 1 .OR. mMaxDim < mS) THEN
|
|
INFORM = 2
|
|
RETURN
|
|
ENDIF
|
|
IF ( mATMOST < 1 .OR. mMaxAtMost <= mATMOST) THEN
|
|
INFORM = 3
|
|
RETURN
|
|
ENDIF
|
|
if ((IFLAG.EQ.1 .or. IFLAG.EQ.3) .AND. (mMaxBit < NUMDS)) then
|
|
INFORM = 4
|
|
return
|
|
endif
|
|
IF (mS .LE. 13) THEN
|
|
TAUS = TAU(mS)
|
|
ELSE
|
|
TAUS = -1
|
|
! RETURN A DUMMY VALUE TO THE CALLING PROGRAM
|
|
ENDIF
|
|
|
|
! FIND NUMBER OF BITS IN ATMOST
|
|
mMAXCOL = getMSBP(mATMOST)+1
|
|
|
|
|
|
! INITIALIZE V
|
|
V(1,1:mMAXCOL) = 1
|
|
DO I = 2, mS ! 100
|
|
! FIND DEGREE OF POLYNOMIAL I FROM BINARY ENCODING
|
|
|
|
J = mPOLY(I)
|
|
M = getMSBP(J)
|
|
|
|
! WE EXPAND THIS BIT PATTERN TO SEPARATE COMPONENTS
|
|
! OF THE LOGICAL ARRAY INCLUD.
|
|
|
|
DO K = M, 1, -1
|
|
INCLUD(K) = (MOD(J,2) .EQ. 1)
|
|
J = J / 2
|
|
enddo ! K
|
|
|
|
! THE LEADING ELEMENTS OF ROW I COME FROM mVINIT
|
|
V(I,1:M) = mVINIT(I, 1:M)
|
|
!
|
|
! CALCULATE REMAINING ELEMENTS OF ROW I AS EXPLAINED
|
|
! IN BRATLEY AND FOX, SECTION 2
|
|
DO J = M+1, mMAXCOL
|
|
NEWV = V(I, J-M)
|
|
L = 1
|
|
DO K = 1, M
|
|
L = 2 * L
|
|
IF (INCLUD(K)) NEWV = IEOR(NEWV, L * V(I, J-K))
|
|
enddo ! K
|
|
V(I,J) = NEWV
|
|
enddo ! J
|
|
enddo ! I
|
|
!
|
|
! MULTIPLY COLUMNS OF V BY APPROPRIATE POWER OF 2
|
|
!
|
|
L = 1
|
|
DO J = mMAXCOL-1, 1, -1
|
|
L = 2 * L
|
|
V(1:mS,J) = V(1:mS,J) * L
|
|
enddo ! J
|
|
!
|
|
! COMPUTING GENERATOR MATRICES OF USER CHOICE
|
|
!
|
|
IF (IFLAG .EQ. 0) THEN
|
|
FORALL (I = 1:mS, J = 1:mMAXCOL) mSV(I,J) = V(I,J)
|
|
SHIFT(1:mS) = 0
|
|
LL = DBLE(2**(mMAXCOL))
|
|
ELSE
|
|
IF ((IFLAG .EQ. 1) .OR. (IFLAG .EQ. 3)) THEN
|
|
CALL GENSCRML(NUMDS,LSM,SHIFT)
|
|
DO I = 1,mS
|
|
DO J = 1,mMAXCOL
|
|
L = 1
|
|
TEMP2 = 0
|
|
DO P = NUMDS,1,-1
|
|
TEMP1 = 0
|
|
DO K = 1,mMAXCOL
|
|
TEMP1 = TEMP1+
|
|
& (IBITS(LSM(I,P),K-1,1)*IBITS(V(I,J),K-1,1))
|
|
enddo ! K
|
|
TEMP1 = MOD(TEMP1,2)
|
|
TEMP2 = TEMP2+TEMP1*L
|
|
L = 2 * L
|
|
enddo ! P
|
|
mSV(I,J) = TEMP2
|
|
enddo ! J
|
|
enddo ! I
|
|
LL= DBLE(2**(NUMDS))
|
|
ENDIF
|
|
IF ((IFLAG .EQ. 2) .OR. (IFLAG .EQ. 3)) THEN
|
|
CALL GENSCRMU(USM,USHIFT)
|
|
IF (IFLAG .EQ. 2) THEN
|
|
MAXX = mMAXCOL
|
|
ELSE
|
|
MAXX = NUMDS
|
|
ENDIF
|
|
DO I = 1,mS
|
|
DO J = 1,mMAXCOL
|
|
P = MAXX
|
|
DO K = 1,MAXX
|
|
IF (IFLAG .EQ. 2) THEN
|
|
TV(I,P,J) = IBITS(V(I,J),K-1,1)
|
|
ELSE
|
|
TV(I,P,J) = IBITS(mSV(I,J),K-1,1)
|
|
ENDIF
|
|
P = P-1
|
|
enddo ! K
|
|
enddo ! J
|
|
DO PP = 1,mMAXCOL
|
|
TEMP2 = 0
|
|
TEMP4 = 0
|
|
L = 1
|
|
DO J = MAXX,1,-1
|
|
TEMP1 = 0
|
|
TEMP3 = 0
|
|
DO P = 1,mMAXCOL
|
|
TEMP1 = TEMP1 + TV(I,J,P)*USM(P,PP)
|
|
IF (PP .EQ. 1) THEN
|
|
TEMP3 = TEMP3 + TV(I,J,P)*USHIFT(P)
|
|
ENDIF
|
|
enddo ! P
|
|
TEMP1 = MOD(TEMP1,2)
|
|
TEMP2 = TEMP2 + TEMP1*L
|
|
IF (PP .EQ. 1) THEN
|
|
TEMP3 = MOD(TEMP3,2)
|
|
TEMP4 = TEMP4 + TEMP3*L
|
|
ENDIF
|
|
L = 2*L
|
|
enddo ! J
|
|
mSV(I,PP) = TEMP2
|
|
IF (PP .EQ. 1) THEN
|
|
IF (IFLAG .EQ. 3) THEN
|
|
SHIFT(I) = IEOR(TEMP4, SHIFT(I))
|
|
ELSE
|
|
SHIFT(I) = TEMP4
|
|
ENDIF
|
|
ENDIF
|
|
enddo ! PP
|
|
enddo ! I
|
|
LL = DBLE(2**(MAXX))
|
|
ENDIF
|
|
ENDIF
|
|
!
|
|
! mRECIPD IS 1/(COMMON DENOMINATOR OF THE ELEMENTS IN V)
|
|
!
|
|
mRECIPD = 1.0_gP / LL
|
|
|
|
! SET UP FIRST VECTOR AND VALUES FOR "SOBOLSEQ"
|
|
mCOUNT = 0
|
|
mLASTQ(1:mS) = SHIFT(1:mS)
|
|
! QUASI(1:mS) = DBLE(mLASTQ(1:mS))*mRECIPD
|
|
RETURN
|
|
END subroutine initSobol
|
|
FUNCTION UNI() result (val)
|
|
*
|
|
* Random number generator, adapted from F. James
|
|
* "A Review of Random Number Generators"
|
|
* Comp. Phys. Comm. 60(1990), pp. 329-344.
|
|
*
|
|
real(kind=gP) SEEDS(24), TWOM24, CARRY,val
|
|
PARAMETER ( TWOM24 = 1.0_gP/16777216.0_gP )
|
|
INTEGER I, J
|
|
SAVE I, J, CARRY, SEEDS
|
|
DATA I, J, CARRY / 24, 10, 0.0 /
|
|
DATA SEEDS /
|
|
& 0.8804418, 0.2694365, 0.0367681, 0.4068699, 0.4554052, 0.2880635,
|
|
& 0.1463408, 0.2390333, 0.6407298, 0.1755283, 0.7132940, 0.4913043,
|
|
& 0.2979918, 0.1396858, 0.3589528, 0.5254809, 0.9857749, 0.4612127,
|
|
& 0.2196441, 0.7848351, 0.4096100, 0.9807353, 0.2689915, 0.5140357/
|
|
! & 0.8804418_gP, 0.2694365_gP, 0.0367681_gP, 0.4068699_gP,
|
|
! & 0.4554052_gP, 0.2880635_gP,
|
|
! & 0.1463408_gP, 0.2390333_gP, 0.6407298_gP, 0.1755283_gP,
|
|
! & 0.7132940_gP, 0.4913043_gP,
|
|
! & 0.2979918_gP, 0.1396858_gP, 0.3589528_gP, 0.5254809_gP,
|
|
! & 0.9857749_gP, 0.4612127_gP,
|
|
! & 0.2196441_gP, 0.7848351_gP, 0.4096100_gP, 0.9807353_gP,
|
|
! & 0.2689915_gP, 0.5140357_gP/
|
|
|
|
CALL random_number(val)
|
|
return
|
|
val = SEEDS(I) - SEEDS(J) - CARRY
|
|
IF ( val .LT. 0.0_gP ) THEN
|
|
val = val + 1.0_gP
|
|
CARRY = TWOM24
|
|
ELSE
|
|
CARRY = 0.0_gP
|
|
ENDIF
|
|
SEEDS(I) = val
|
|
I = 24 - MOD( 25-I, 24 )
|
|
J = 24 - MOD( 25-J, 24 )
|
|
RETURN
|
|
END function uni
|
|
SUBROUTINE GENSCRML(NUMDS,LSM,SHIFT)
|
|
! GENERATING LOWER TRIANGULAR SCRMABLING MATRICES AND SHIFT VECTORS.
|
|
! INPUTS :
|
|
! FROM INSSOBL : NUMDS
|
|
! FROM BLOCK DATA "SOBOL" : mS, mMAXCOL,
|
|
!
|
|
! OUTPUTS :
|
|
! TO initSobol : LSM, SHIFT
|
|
integer,intent(in) :: NUMDS
|
|
integer, dimension(mMaxDim,mMaxBit), intent(inout) :: LSM
|
|
integer, dimension(mMaxDim), intent(inout) :: SHIFT
|
|
INTEGER :: P,I,J,TEMP,STEMP,L,LL
|
|
! REAL(KIND=gP) :: UNI
|
|
! COMMON /SOBOL/ mS,mMAXCOL
|
|
! SAVE /SOBOL/
|
|
|
|
DO 10 P = 1,mS
|
|
SHIFT(P) = 0
|
|
L = 1
|
|
DO 20 I = NUMDS,1,-1
|
|
LSM(P,I) = 0
|
|
! CALL random_number(UNI)
|
|
STEMP = MOD((int(UNI()*1000.0_gP)),2)
|
|
SHIFT(P) = SHIFT(P)+STEMP*L
|
|
L = 2 * L
|
|
LL = 1
|
|
DO 30 J = mMAXCOL,1,-1
|
|
IF (J .EQ. I) THEN
|
|
TEMP = 1
|
|
ELSE IF (J .LT. I) THEN
|
|
! CALL random_number(UNI)
|
|
TEMP = MOD((int(UNI()*1000.0_gP)),2)
|
|
ELSE
|
|
TEMP = 0
|
|
ENDIF
|
|
LSM(P,I) = LSM(P,I) + TEMP*LL
|
|
LL = 2 * LL
|
|
30 CONTINUE
|
|
20 CONTINUE
|
|
10 CONTINUE
|
|
RETURN
|
|
END SUBROUTINE GENSCRML
|
|
|
|
SUBROUTINE GENSCRMU(USM,USHIFT)
|
|
|
|
! GENERATING UPPER TRIANGULAR SCRMABLING MATRICES AND
|
|
! SHIFT VECTORS.
|
|
! INPUTS :
|
|
! FROM BLOCK DATA "SOBOL" : mS, mMAXCOL,
|
|
!
|
|
! OUTPUTS :
|
|
! TO INSSOBL : USM, USHIFT
|
|
integer, dimension(mMaxBit,mMaxBit), intent(inout) :: USM
|
|
integer, dimension(mMaxBit), intent(inout) :: USHIFT
|
|
INTEGER I,J,TEMP
|
|
! REAL(KIND=gP) :: UNI
|
|
! COMMON /SOBOL/ mS,mMAXCOL
|
|
! SAVE /SOBOL/
|
|
|
|
DO 20 I = 1,mMAXCOL
|
|
! CALL random_number(UNI)
|
|
USHIFT(I) = MOD((int(UNI()*1000.0_gP)),2)
|
|
DO 30 J = 1,mMAXCOL
|
|
IF (J .EQ. I) THEN
|
|
TEMP = 1
|
|
ELSE IF (J .GT. I) THEN
|
|
! CALL random_number(UNI)
|
|
TEMP = MOD((int(UNI()*1000.0_gP)),2)
|
|
ELSE
|
|
TEMP = 0
|
|
ENDIF
|
|
USM(I,J) = TEMP
|
|
30 CONTINUE
|
|
20 CONTINUE
|
|
RETURN
|
|
END SUBROUTINE GENSCRMU
|
|
|
|
SUBROUTINE sobolSeq(QUASI,INFORM)
|
|
!SOBOLSEQ GENERATES A NEW QUASIRANDOM VECTOR WITH EACH CALL
|
|
!
|
|
! IT ADAPTS THE IDEAS OF ANTONOV AND SALEEV,
|
|
! USSR COMPUT. MATHS. MATH. PHYS. 19 (1980),
|
|
! 252 - 256
|
|
!
|
|
! The user must call "initSobol" before calling
|
|
! "sobolSeq". After calling "initsobol", test
|
|
! if inform == 0. if inform>0 then
|
|
! do not call "sobolSeq".
|
|
! "sobolSeq" checks that the user does not make more calls
|
|
! than he said he would : see the comments
|
|
! to "initSobol".
|
|
!
|
|
! INPUTS:
|
|
! FROM USER'S CALLING PROGRAM:
|
|
! NONE
|
|
!
|
|
! FROM LABELLED COMMON /SOBOL/:
|
|
! mSV TABLE OF DIRECTION NUMBERS
|
|
! mS DIMENSION
|
|
! mMAXCOL LAST COLUMN OF mSV TO BE USED
|
|
! mCOUNT SEQUENCE NUMBER OF THIS CALL
|
|
! mLASTQ NUMERATORS FOR LAST VECTOR GENERATED
|
|
! mRECIPD (1/DENOMINATOR) FOR THESE NUMERATORS
|
|
!
|
|
REAL(KIND=gP), dimension(:), intent(out) :: QUASI
|
|
integer, intent(inout) :: inform
|
|
INTEGER :: I,L
|
|
! INTEGER mSV(40,31),mS,mMAXCOL,mCOUNT,mLASTQ(40)
|
|
! COMMON /SOBOL/ S,mMAXCOL,mSV,mCOUNT,mLASTQ,mRECIPD
|
|
! SAVE /SOBOL/
|
|
!
|
|
|
|
! FORALL ( I = 1:mS)
|
|
! QUASI(I) = DBLE(mLASTQ(I)) * mRECIPD
|
|
! END FORALL
|
|
QUASI(1:mS) = DBLE(mLASTQ(1:mS))*mRECIPD
|
|
! FIND POSITION OF RIGHTMOST ZERO BIT IN mCOUNT
|
|
L = 1
|
|
I = mCOUNT
|
|
do while (MOD(I,2) .EQ. 1)
|
|
I = I / 2
|
|
L = L + 1
|
|
ENDDO
|
|
! CHECK THAT THE USER IS NOT CHEATING
|
|
IF (L > mMAXCOL) THEN
|
|
INFORM = 4
|
|
! WARNING: Reached the end of the sobol sequence
|
|
! Next call will wrap around and return the same numbers
|
|
! as for mCOUNT = 0
|
|
! Call initSobol to increase mATMOST before calling sobolseq again.
|
|
else
|
|
INFORM = 0
|
|
! Calculate the new components of quasi,
|
|
! first the numerators
|
|
FORALL ( I = 1:mS)
|
|
mLASTQ(I) = IEOR(mLASTQ(I), mSV(I,L))
|
|
END FORALL
|
|
mCOUNT = mCOUNT + 1
|
|
ENDIF
|
|
RETURN
|
|
END SUBROUTINE sobolSeq
|
|
|
|
|
|
!***********************************************************
|
|
! MAIN INTEGRATION ROUTINE SOBNIED
|
|
!***********************************************************
|
|
|
|
SUBROUTINE SOBNIED( NDIM, MINVLS, MAXVLS, FUNCTN, ABSEPS, RELEPS,
|
|
& ABSERR, FINEST, INFORM )
|
|
use precisionmod
|
|
implicit none
|
|
*
|
|
* Automatic Multidimensional Integration Subroutine
|
|
*
|
|
* AUTHOR: Per A. Brodtkorb
|
|
! Norwegian Defence Research Establishment
|
|
! P.O. Box 115
|
|
! N-3191 Horten
|
|
! Norway
|
|
! Email: Per.Brodtkorb@ffi.no
|
|
!
|
|
* Last Change: 6/19/2004
|
|
*
|
|
* SOBNIED computes an approximation to the integral
|
|
*
|
|
* 1 1 1
|
|
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
|
|
* 0 0 0
|
|
*
|
|
*
|
|
* SOBNIED uses scrambled SOBOL sequences for the first 40 variables.
|
|
* The primary reference is
|
|
|
|
* If there are more than 40 variables, the remaining variables are
|
|
* integrated using the rule described in the reference
|
|
* "On a Number-Theoretical Integration Method"
|
|
* H. Niederreiter, Aequationes Mathematicae, 8(1972), pp. 304-11.
|
|
*
|
|
*************** Parameters ********************************************
|
|
****** Input parameters
|
|
* NDIM Number of variables, must exceed 1, but not exceed 100
|
|
* MINVLS Integer minimum number of function evaluations allowed.
|
|
* MINVLS must not exceed MAXVLS. If MINVLS < 0 then the
|
|
* routine assumes a previous call has been made with
|
|
* the same integrand and continues that calculation.
|
|
* MAXVLS Integer maximum number of function evaluations allowed.
|
|
* FUNCTN EXTERNALly declared user defined function to be integrated.
|
|
* It must have parameters (NDIM,Z), where Z is a real array
|
|
* of dimension NDIM.
|
|
*
|
|
* ABSEPS Required absolute accuracy.
|
|
* RELEPS Required relative accuracy.
|
|
****** Output parameters
|
|
* MINVLS Actual number of function evaluations used.
|
|
* ABSERR Estimated absolute accuracy of FINEST.
|
|
* FINEST Estimated value of integral.
|
|
* INFORM INFORM = 0 for normal exit, when
|
|
* ABSERR <= MAX(ABSEPS, RELEPS*ABS(FINEST))
|
|
* and
|
|
* INTVLS <= MAXCLS.
|
|
* INFORM = 1 If MAXVLS was too small to obtain the required
|
|
* accuracy. In this case a value FINEST is returned with
|
|
* estimated absolute accuracy ABSERR.
|
|
* INFORM = 2 If NDIM>1040 or NDIM<1
|
|
************************************************************************
|
|
INTEGER, INTENT(IN) :: NDIM, MAXVLS
|
|
INTEGER, INTENT(INOUT) :: MINVLS
|
|
INTEGER, INTENT(OUT) :: INFORM
|
|
REAL(KIND=gP), INTENT(IN) :: ABSEPS, RELEPS
|
|
REAL(KIND=gP), INTENT(OUT) :: FINEST, ABSERR
|
|
INTEGER :: NP,PLIM,NLIM,KLIM,KLIMI,SAMPLS,I,INTVLS,MINSMP,NK
|
|
integer :: numRep, J, TAUS
|
|
INTEGER, parameter :: NUMDS=30,IFLAG=1
|
|
PARAMETER ( PLIM = 28, NLIM = 1040, KLIM = mMaxDim, MINSMP = 8 )
|
|
INTEGER , DIMENSION(PLIM) :: P
|
|
REAL(KIND=gP) :: DIFINT,FINVAL,VARSQR,VAREST,VARPRD,VALUE
|
|
REAL(KIND=gP), PARAMETER :: ONE = 1.D0 , ZERO = 0.D0
|
|
REAL(KIND=gP), DIMENSION(2*NLIM) :: X = 0.d0
|
|
REAL(KIND=gP), DIMENSION(NLIM) :: VK = 0.d0
|
|
logical :: NPtooSmall,errorTooLarge,numSamplesOk
|
|
INTERFACE
|
|
REAL(KIND=gP) FUNCTION FUNCTN(N,Z)
|
|
use precisionmod
|
|
REAL(KIND=gP),DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
DATA P / 31, 47, 73, 113, 173, 263, 397, 593, 907, 1361,
|
|
& 2053, 3079, 4621, 6947, 10427, 15641, 23473, 35221,
|
|
& 52837, 79259, 118891, 178349, 267523, 401287, 601943,
|
|
& 902933,1354471,2031713/
|
|
SAVE P, SAMPLS, NP, VAREST
|
|
IF ( NDIM .GT. NLIM .OR. NDIM .LT. 1 ) THEN
|
|
INFORM = 2
|
|
FINEST = ZERO
|
|
ABSERR = ONE
|
|
RETURN
|
|
ENDIF
|
|
NK = MIN( NDIM, KLIM )
|
|
|
|
|
|
IF ( MINVLS >= 0 ) THEN
|
|
FINEST = ZERO
|
|
VAREST = ZERO
|
|
SAMPLS = MINSMP
|
|
NP = 1
|
|
NPtooSmall = ( MINVLS >= 2*SAMPLS*P(NP) )
|
|
do while(NPtooSmall .AND. NP<PLIM)
|
|
NP = NP + 1
|
|
NPtooSmall = ( MINVLS >= 2*SAMPLS*P(NP) )
|
|
enddo
|
|
if (NPtooSmall) then
|
|
SAMPLS = MAX( MINSMP, MINVLS/( 2*P(NP) ) )
|
|
endif
|
|
ENDIF
|
|
numRep = 1 !max(1,nint(MAXVLS/mMaxAtMost))
|
|
|
|
INFORM = 1
|
|
INTVLS = 0
|
|
KLIMI = KLIM
|
|
errorTooLarge = .TRUE.
|
|
do J = 1,numRep
|
|
CALL initSobol(inform,TAUS,NK,MAXVLS/numRep,NUMDS,IFLAG)
|
|
if (inform.ne.0) then
|
|
FINEST = ZERO
|
|
ABSERR = ONE
|
|
RETURN
|
|
endif
|
|
INFORM = 1
|
|
numSamplesOk = ( INTVLS + 2*SAMPLS*P(NP) <= MAXVLS )
|
|
do while (errorTooLarge .and. numSamplesOk)
|
|
DO I = 1, NDIM-NK
|
|
VK(I) = INT( P(NP)*2**(DBLE(I)/(NDIM-KLIM+1)) )
|
|
VK(I) = MOD( VK(I)/P(NP), ONE )
|
|
END DO
|
|
FINVAL = ZERO
|
|
VARSQR = ZERO
|
|
DO I = 1, SAMPLS
|
|
CALL DKSMRC( NDIM, KLIMI, VALUE, P(NP),VK, FUNCTN, X )
|
|
DIFINT = ( VALUE - FINVAL )/DBLE(I)
|
|
FINVAL = FINVAL + DIFINT
|
|
VARSQR = DBLE( I - 2 )*VARSQR/DBLE(I) + DIFINT*DIFINT
|
|
END DO
|
|
INTVLS = INTVLS + 2*SAMPLS*P(NP)
|
|
VARPRD = VAREST*VARSQR
|
|
FINEST = FINEST + ( FINVAL - FINEST )/( ONE + VARPRD )
|
|
IF ( VARSQR > ZERO ) VAREST = ( ONE + VARPRD )/VARSQR
|
|
ABSERR = 3.0_gP*SQRT( VARSQR/( ONE + VARPRD ) )
|
|
errorTooLarge = (ABSERR > MAX(ABSEPS, ABS(FINEST)*RELEPS))
|
|
IF ( errorTooLarge ) THEN
|
|
IF ( NP < PLIM ) THEN
|
|
NP = NP + 1
|
|
ELSE
|
|
SAMPLS = MIN(3*SAMPLS/2, (MAXVLS - INTVLS)/(2*P(NP)))
|
|
SAMPLS = MAX( MINSMP, SAMPLS )
|
|
ENDIF
|
|
numSamplesOk = ( INTVLS + 2*SAMPLS*P(NP) <= MAXVLS )
|
|
ELSE
|
|
INFORM = 0
|
|
ENDIF
|
|
enddo
|
|
enddo
|
|
MINVLS = INTVLS
|
|
END SUBROUTINE SOBNIED
|
|
SUBROUTINE DKSMRC( NDIM, KLIM, SUMKRO, PRIME, VK,FUNCTN, X )
|
|
use precisionmod
|
|
implicit none
|
|
INTEGER, INTENT(IN):: NDIM, KLIM, PRIME
|
|
REAL(KIND=gP), INTENT(OUT) :: SUMKRO
|
|
REAL(KIND=gP), DIMENSION(:), INTENT(INOUT) :: VK,X
|
|
INTEGER :: K, NK, inform
|
|
REAL(KIND=gP) :: ONE, XT, MVNUNI
|
|
PARAMETER ( ONE = 1.0_gP )
|
|
INTERFACE
|
|
REAL(KIND=gP) FUNCTION FUNCTN(N,Z)
|
|
use precisionmod
|
|
REAL(KIND=gP),DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
SUMKRO = 0.0_gP
|
|
NK = MIN( NDIM, KLIM )
|
|
* Determine Random Shifts for each Variable
|
|
if (NK<NDIM) THEN
|
|
CALL random_number(X(NDIM+NK:2*NDIM))
|
|
ENDIF
|
|
DO K = 1, PRIME
|
|
CALL sobolSeq(X,inform)
|
|
if (NK<NDIM) THEN
|
|
X(NK+1:NDIM) = ABS( 2.0_gP*MOD( DBLE(K)*VK(1:NDIM-NK) +
|
|
& X(NDIM+1+NK:2*NDIM), ONE ) - ONE )
|
|
endif
|
|
SUMKRO = SUMKRO + ( FUNCTN(NDIM,X) - SUMKRO )/DBLE( 2*K - 1 )
|
|
! X(1:NDIM) = ONE - X(1:NDIM)
|
|
CALL sobolSeq(X,inform)
|
|
if (NK<NDIM) THEN
|
|
X(NK+1:NDIM) = ONE - X(NK+1:NDIM)
|
|
endif
|
|
SUMKRO = SUMKRO + ( FUNCTN(NDIM,X) - SUMKRO )/DBLE( 2*K )
|
|
END DO
|
|
END SUBROUTINE DKSMRC
|
|
END MODULE SSOBOLMOD
|
|
|
|
* KROBOVMOD is a module containing a:
|
|
*
|
|
* Automatic Multidimensional Integration Subroutine
|
|
*
|
|
* AUTHOR: Alan Genz
|
|
* Department of Mathematics
|
|
* Washington State University
|
|
* Pulman, WA 99164-3113
|
|
* Email: AlanGenz@wsu.edu
|
|
*
|
|
* Last Change: 4/15/98
|
|
*
|
|
* revised pab 10.03.2000
|
|
* - updated to f90 (i.e. changed to assumed shape arrays + changing integers to DBLE)
|
|
* - put it into a module
|
|
*
|
|
* KROBOV computes an approximation to the integral
|
|
*
|
|
* 1 1 1
|
|
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
|
|
* 0 0 0
|
|
*
|
|
*
|
|
* KROBOV uses randomized Korobov rules. The primary references are
|
|
* "Randomization of Number Theoretic Methods for Multiple Integration"
|
|
* R. Cranley and T.N.L. Patterson, SIAM J Numer Anal, 13, pp. 904-14,
|
|
* and
|
|
* "Optimal Parameters for Multidimensional Integration",
|
|
* P. Keast, SIAM J Numer Anal, 10, pp.831-838.
|
|
*
|
|
*************** Parameters ********************************************
|
|
****** Input parameters
|
|
* NDIM Number of variables, must exceed 1, but not exceed 100
|
|
* MINVLS Integer minimum number of function evaluations allowed.
|
|
* MINVLS must not exceed MAXVLS. If MINVLS < 0 then the
|
|
* routine assumes a previous call has been made with
|
|
* the same integrand and continues that calculation.
|
|
* MAXVLS Integer maximum number of function evaluations allowed.
|
|
* FUNCTN EXTERNALly declared user defined function to be integrated.
|
|
* It must have parameters (NDIM,Z), where Z is a real array
|
|
* of dimension NDIM.
|
|
* ABSEPS Required absolute accuracy.
|
|
* RELEPS Required relative accuracy.
|
|
****** Output parameters
|
|
* MINVLS Actual number of function evaluations used.
|
|
* ABSERR Estimated absolute accuracy of FINEST.
|
|
* FINEST Estimated value of integral.
|
|
* INFORM INFORM = 0 for normal exit, when
|
|
* ABSERR <= MAX(ABSEPS, RELEPS*ABS(FINEST))
|
|
* and
|
|
* INTVLS <= MAXCLS.
|
|
* INFORM = 1 If MAXVLS was too small to obtain the required
|
|
* accuracy. In this case a value FINEST is returned with
|
|
* estimated absolute accuracy ABSERR.
|
|
************************************************************************
|
|
! You may initialize the random generator before you
|
|
! call KROBOV by the following lines:
|
|
!
|
|
! call random_seed(SIZE=seed_size)
|
|
! allocate(seed(seed_size))
|
|
! call random_seed(GET=seed(1:seed_size)) ! get current seed
|
|
! seed(1)=seed1 ! change seed
|
|
! call random_seed(PUT=seed(1:seed_size))
|
|
! deallocate(seed)
|
|
|
|
|
|
MODULE KROBOVMOD
|
|
IMPLICIT NONE
|
|
PRIVATE
|
|
PUBLIC :: KROBOV
|
|
|
|
INTERFACE KROBOV
|
|
MODULE PROCEDURE KROBOV
|
|
END INTERFACE
|
|
|
|
INTERFACE KROSUM
|
|
MODULE PROCEDURE KROSUM
|
|
END INTERFACE
|
|
|
|
CONTAINS
|
|
|
|
!***********************************************************
|
|
! MAIN INTEGRATION ROUTINE KROBOV
|
|
!***********************************************************
|
|
SUBROUTINE KROBOV( NDIM, MINVLS, MAXVLS, FUNCTN, ABSEPS, RELEPS,
|
|
& ABSERR, FINEST, INFORM )
|
|
*
|
|
* Automatic Multidimensional Integration Subroutine
|
|
*
|
|
* AUTHOR: Alan Genz
|
|
* Department of Mathematics
|
|
* Washington State University
|
|
* Pulman, WA 99164-3113
|
|
* Email: AlanGenz@wsu.edu
|
|
*
|
|
* Last Change: 4/15/98
|
|
*
|
|
* KROBOV computes an approximation to the integral
|
|
*
|
|
* 1 1 1
|
|
* I I ... I F(X) dx(NDIM)...dx(2)dx(1)
|
|
* 0 0 0
|
|
*
|
|
*
|
|
* KROBOV uses randomized Korobov rules. The primary references are
|
|
* "Randomization of Number Theoretic Methods for Multiple Integration"
|
|
* R. Cranley and T.N.L. Patterson, SIAM J Numer Anal, 13, pp. 904-14,
|
|
* and
|
|
* "Optimal Parameters for Multidimensional Integration",
|
|
* P. Keast, SIAM J Numer Anal, 10, pp.831-838.
|
|
*
|
|
*************** Parameters ********************************************
|
|
****** Input parameters
|
|
* NDIM Number of variables, must exceed 1, but not exceed 100
|
|
* MINVLS Integer minimum number of function evaluations allowed.
|
|
* MINVLS must not exceed MAXVLS. If MINVLS < 0 then the
|
|
* routine assumes a previous call has been made with
|
|
* the same integrand and continues that calculation.
|
|
* MAXVLS Integer maximum number of function evaluations allowed.
|
|
* FUNCTN EXTERNALly declared user defined function to be integrated.
|
|
* It must have parameters (NDIM,Z), where Z is a real array
|
|
* of dimension NDIM.
|
|
* ABSEPS Required absolute accuracy.
|
|
* RELEPS Required relative accuracy.
|
|
****** Output parameters
|
|
* MINVLS Actual number of function evaluations used.
|
|
* ABSERR Estimated absolute accuracy of FINEST.
|
|
* FINEST Estimated value of integral.
|
|
* INFORM INFORM = 0 for normal exit, when
|
|
* ABSERR <= MAX(ABSEPS, RELEPS*ABS(FINEST))
|
|
* and
|
|
* INTVLS <= MAXCLS.
|
|
* INFORM = 1 If MAXVLS was too small to obtain the required
|
|
* accuracy. In this case a value FINEST is returned with
|
|
* estimated absolute accuracy ABSERR.
|
|
* INFORM = 2 If NDIM>100 or NDIM<1
|
|
************************************************************************
|
|
IMPLICIT NONE
|
|
INTEGER, INTENT(IN) :: NDIM, MAXVLS
|
|
INTEGER, INTENT(INOUT) ::MINVLS
|
|
INTEGER, INTENT(OUT) ::INFORM
|
|
DOUBLE PRECISION, INTENT(IN) :: ABSEPS, RELEPS
|
|
DOUBLE PRECISION, INTENT(OUT) :: FINEST, ABSERR
|
|
! Local variables:
|
|
INTEGER :: NP, PLIM, NLIM, SAMPLS, I, INTVLS, MINSMP
|
|
PARAMETER ( PLIM = 20, NLIM = 100, MINSMP = 6 )
|
|
INTEGER, DIMENSION(PLIM,NLIM) :: C
|
|
INTEGER, DIMENSION(PLIM) :: P
|
|
DOUBLE PRECISION :: DIFINT, FINVAL, VARSQR, VAREST, VARPRD, VALUE
|
|
DOUBLE PRECISION, DIMENSION(NLIM) :: ALPHA, X, VK
|
|
DOUBLE PRECISION :: ONE
|
|
PARAMETER ( ONE = 1.d0 )
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
DATA P /113, 173, 263,397,593,907,1361,2053,3079,4621,6947,
|
|
& 10427, 15641,23473, 35221, 52837, 79259,
|
|
& 118891, 178349, 267523 /
|
|
DATA ( C( 1,I), I = 1, 99 ) /
|
|
& 42, 54, 55, 32, 13, 26, 26, 13, 26,
|
|
& 14, 13, 26, 35, 2, 2, 2, 2, 56,
|
|
& 28, 7, 7, 28, 4, 49, 4, 40, 48,
|
|
& 5, 35, 27, 16, 16, 2, 2, 7, 28,
|
|
& 4, 49, 4, 56, 8, 2, 2, 56, 7,
|
|
& 16, 28, 7, 7, 28, 4, 49, 4, 37,
|
|
& 55, 21, 33, 40, 16, 16, 28, 7, 16,
|
|
& 28, 4, 49, 4, 56, 35, 2, 2, 2,
|
|
& 16, 16, 28, 4, 16, 28, 4, 49, 4,
|
|
& 40, 40, 5, 42, 27, 16, 16, 28, 4,
|
|
& 16, 28, 4, 49, 4, 8, 8, 2, 2/
|
|
DATA ( C( 2,I), I = 1, 99 ) /
|
|
& 64, 34, 57, 9, 72, 86, 16, 75, 75,
|
|
& 70, 42, 2, 86, 62, 62, 30, 30, 5,
|
|
& 42, 70, 70, 70, 53, 70, 70, 53, 42,
|
|
& 62, 53, 53, 53, 69, 75, 5, 53, 86,
|
|
& 2, 5, 30, 75, 59, 2, 69, 5, 5,
|
|
& 63, 62, 5, 69, 30, 44, 30, 86, 86,
|
|
& 2, 69, 5, 5, 2, 2, 61, 69, 17,
|
|
& 2, 2, 2, 53, 69, 2, 2, 86, 69,
|
|
& 13, 2, 2, 37, 43, 65, 2, 2, 30,
|
|
& 86, 45, 16, 32, 18, 86, 86, 86, 9,
|
|
& 63, 63, 11, 76, 76, 76, 63, 60, 70/
|
|
DATA ( C( 3,I), I = 1, 99 ) /
|
|
& 111, 67, 98, 36, 48, 110, 2, 131, 2,
|
|
& 2, 124, 124, 48, 2, 2, 124, 124, 70,
|
|
& 70, 48, 126, 48, 126, 56, 65, 48, 48,
|
|
& 70, 2, 92, 124, 92, 126, 131, 124, 70,
|
|
& 70, 70, 20, 105, 70, 2, 2, 27, 108,
|
|
& 27, 39, 2, 131, 131, 92, 92, 48, 2,
|
|
& 126, 20, 126, 2, 2, 131, 38, 117, 2,
|
|
& 131, 68, 58, 38, 90, 38, 108, 38, 2,
|
|
& 131, 131, 131, 68, 14, 94, 131, 131, 131,
|
|
& 108, 18, 131, 56, 85, 117, 117, 9, 131,
|
|
& 131, 55, 92, 92, 92, 131, 131, 48, 48/
|
|
DATA ( C( 4,I), I = 1, 99 ) /
|
|
& 151, 168, 46, 197, 69, 64, 2, 198, 191,
|
|
& 134, 134, 167, 124, 16, 124, 124, 124, 124,
|
|
& 141, 134, 128, 2, 2, 32, 32, 32, 31,
|
|
& 31, 64, 64, 99, 4, 4, 167, 124, 124,
|
|
& 124, 124, 124, 124, 107, 85, 79, 85, 111,
|
|
& 85, 128, 31, 31, 31, 31, 64, 167, 4,
|
|
& 107, 167, 124, 124, 124, 124, 124, 124, 107,
|
|
& 183, 2, 2, 2, 62, 32, 31, 31, 31,
|
|
& 31, 31, 167, 4, 107, 167, 124, 124, 124,
|
|
& 124, 124, 124, 107, 142, 184, 184, 65, 65,
|
|
& 183, 31, 31, 31, 31, 31, 167, 4, 107/
|
|
DATA ( C( 5,I), I = 1, 99 ) /
|
|
& 229, 40, 268, 42, 153, 294, 71, 2, 130,
|
|
& 199, 199, 199, 149, 199, 149, 153, 130, 149,
|
|
& 149, 15, 119, 294, 31, 82, 260, 122, 209,
|
|
& 209, 122, 296, 130, 130, 260, 260, 30, 206,
|
|
& 94, 209, 94, 122, 209, 209, 122, 122, 209,
|
|
& 130, 2, 130, 130, 38, 38, 79, 82, 94,
|
|
& 82, 122, 122, 209, 209, 122, 122, 168, 220,
|
|
& 62, 60, 168, 282, 282, 82, 209, 122, 94,
|
|
& 209, 122, 122, 122, 122, 258, 148, 286, 256,
|
|
& 256, 62, 62, 82, 122, 82, 82, 122, 122,
|
|
& 122, 209, 122, 15, 79, 79, 79, 79, 168/
|
|
DATA ( C( 6,I), I = 1, 99 ) /
|
|
& 264, 402, 406, 147, 452, 153, 224, 2, 2,
|
|
& 224, 224, 449, 101, 182, 449, 101, 451, 181,
|
|
& 181, 101, 101, 377, 85, 453, 453, 453, 85,
|
|
& 197, 451, 2, 2, 101, 449, 449, 449, 173,
|
|
& 173, 2, 453, 453, 2, 426, 66, 367, 426,
|
|
& 101, 453, 2, 32, 32, 32, 101, 2, 2,
|
|
& 453, 223, 147, 449, 290, 2, 453, 2, 83,
|
|
& 223, 101, 453, 2, 83, 83, 147, 2, 453,
|
|
& 147, 147, 147, 147, 147, 147, 147, 453, 153,
|
|
& 153, 147, 2, 224, 290, 320, 453, 147, 431,
|
|
& 383, 290, 290, 2, 162, 162, 147, 2, 162/
|
|
DATA ( C( 7,I), I = 1, 99 ) /
|
|
& 505, 220, 195, 410, 199, 248, 460, 471, 2,
|
|
& 331, 662, 547, 209, 547, 547, 209, 2, 680,
|
|
& 680, 629, 370, 574, 63, 63, 259, 268, 259,
|
|
& 547, 209, 209, 209, 547, 547, 209, 209, 547,
|
|
& 547, 108, 63, 63, 108, 63, 63, 108, 259,
|
|
& 268, 268, 547, 209, 209, 209, 209, 547, 209,
|
|
& 209, 209, 547, 108, 63, 63, 63, 405, 285,
|
|
& 234, 259, 259, 259, 259, 209, 209, 209, 209,
|
|
& 209, 209, 209, 209, 547, 289, 289, 234, 285,
|
|
& 316, 2, 410, 259, 259, 259, 268, 209, 209,
|
|
& 209, 209, 547, 547, 209, 209, 209, 285, 316/
|
|
DATA ( C( 8,I), I = 1, 99 ) /
|
|
& 468, 635, 849, 687, 948, 37, 1014, 513, 2,
|
|
& 2, 2, 2, 2, 1026, 2, 2, 1026, 201,
|
|
& 201, 2, 1026, 413, 1026, 1026, 2, 2, 703,
|
|
& 703, 2, 2, 393, 393, 678, 413, 1026, 2,
|
|
& 2, 1026, 1026, 2, 405, 953, 2, 1026, 123,
|
|
& 123, 953, 953, 123, 405, 794, 123, 647, 613,
|
|
& 1026, 647, 768, 953, 405, 953, 405, 918, 918,
|
|
& 123, 953, 953, 918, 953, 536, 405, 70, 124,
|
|
& 1005, 529, 207, 405, 405, 953, 953, 123, 918,
|
|
& 918, 953, 405, 918, 953, 468, 405, 794, 794,
|
|
& 647, 613, 548, 405, 953, 405, 953, 123, 918/
|
|
DATA ( C( 9,I), I = 1, 99 ) /
|
|
& 1189, 1423, 287, 186, 341, 77, 733, 733, 1116,
|
|
& 2, 1539, 2, 2, 2, 2, 2, 1116, 847,
|
|
& 1174, 2, 827, 713, 910, 944, 139, 1174, 1174,
|
|
& 1539, 1397, 1397, 1174, 370, 33, 1210, 2, 370,
|
|
& 1423, 370, 370, 1423, 1423, 1423, 434, 1423, 901,
|
|
& 139, 1174, 427, 427, 200, 1247, 114, 114, 1441,
|
|
& 139, 728, 1116, 1174, 139, 113, 113, 113, 1406,
|
|
& 1247, 200, 200, 200, 200, 1247, 1247, 27, 427,
|
|
& 427, 1122, 1122, 696, 696, 427, 1539, 435, 1122,
|
|
& 758, 1247, 1247, 1247, 200, 200, 200, 1247, 114,
|
|
& 27, 118, 118, 113, 118, 453, 453, 1084, 1406/
|
|
DATA ( C(10,I), I = 1, 99 ) /
|
|
& 1764, 1349, 1859, 693, 78, 438, 531, 68, 2234,
|
|
& 2310, 2310, 2310, 2, 2310, 2310, 2102, 2102, 178,
|
|
& 314, 921, 1074, 1074, 1074, 2147, 314, 1869, 178,
|
|
& 178, 1324, 1324, 510, 2309, 1541, 1541, 1541, 1541,
|
|
& 342, 1324, 1324, 1324, 1324, 510, 570, 570, 2197,
|
|
& 173, 1202, 998, 1324, 1324, 178, 1324, 1324, 1541,
|
|
& 1541, 1541, 342, 1541, 886, 178, 1324, 1324, 1324,
|
|
& 510, 784, 784, 501, 652, 1541, 1541, 1324, 178,
|
|
& 1324, 178, 1324, 1541, 342, 1541, 2144, 784, 2132,
|
|
& 1324, 1324, 1324, 1324, 510, 652, 1804, 1541, 1541,
|
|
& 1541, 2132, 1324, 1324, 1324, 178, 510, 1541, 652/
|
|
DATA ( C(11,I), I = 1, 99 ) /
|
|
& 2872, 1238, 387, 2135, 235, 1565, 221, 1515, 2950,
|
|
& 486, 3473, 2, 2950, 982, 2950, 3122, 2950, 3172,
|
|
& 2091, 2091, 9, 3449, 3122, 2846, 3122, 3122, 1947,
|
|
& 2846, 3122, 772, 1387, 2895, 1387, 3, 3, 3,
|
|
& 1320, 1320, 2963, 2963, 1320, 1320, 2380, 108, 1284,
|
|
& 702, 1429, 907, 3220, 3125, 1320, 2963, 1320, 1320,
|
|
& 2963, 1320, 1639, 3168, 1660, 2895, 2895, 2895, 2895,
|
|
& 1639, 1297, 1639, 404, 3168, 2963, 2943, 2943, 550,
|
|
& 1387, 1387, 2895, 2895, 2895, 1387, 2895, 1387, 2895,
|
|
& 1320, 1320, 2963, 1320, 1320, 1320, 2963, 1320, 2,
|
|
& 3473, 2, 3473, 772, 2550, 9, 1320, 2963, 1320/
|
|
DATA ( C(12,I), I = 1, 99 ) /
|
|
& 4309, 2339, 4154, 4480, 4967, 630, 5212, 2592, 4715,
|
|
& 1808, 1808, 5213, 2, 216, 4014, 3499, 3499, 4204,
|
|
& 2701, 2701, 5213, 4157, 1209, 4157, 4460, 335, 4460,
|
|
& 1533, 4575, 4013, 4460, 1881, 2701, 4030, 4030, 1881,
|
|
& 4030, 1738, 249, 335, 57, 2561, 2561, 2561, 1533,
|
|
& 1533, 1533, 4013, 4013, 4013, 4013, 4013, 1533, 856,
|
|
& 856, 468, 468, 468, 2561, 468, 2022, 2022, 2434,
|
|
& 138, 4605, 1100, 2561, 2561, 57, 57, 3249, 468,
|
|
& 468, 468, 57, 468, 1738, 313, 856, 6, 3877,
|
|
& 468, 557, 468, 57, 468, 4605, 2022, 2, 4605,
|
|
& 138, 1100, 57, 2561, 57, 57, 2022, 5213, 3249/
|
|
DATA ( C(13,I), I = 1, 99 ) /
|
|
& 6610, 1658, 3022, 2603, 5211, 265, 4985, 3, 4971,
|
|
& 2127, 1877, 1877, 2, 2925, 3175, 3878, 1940, 1940,
|
|
& 1940, 5117, 5117, 5771, 5117, 5117, 5117, 5117, 5117,
|
|
& 5771, 5771, 5117, 3658, 3658, 3658, 3658, 3658, 3658,
|
|
& 5255, 2925, 2619, 1714, 4100, 6718, 6718, 4100, 2322,
|
|
& 842, 4100, 6718, 5119, 4728, 5255, 5771, 5771, 5771,
|
|
& 5117, 5771, 5117, 5117, 5117, 5117, 5117, 5117, 5771,
|
|
& 5771, 1868, 4483, 4728, 3658, 5255, 3658, 5255, 3658,
|
|
& 3658, 5255, 5255, 3658, 6718, 6718, 842, 2322, 6718,
|
|
& 4100, 6718, 4100, 4100, 5117, 5771, 5771, 5117, 5771,
|
|
& 5771, 5771, 5771, 5117, 5117, 5117, 5771, 5771, 1868/
|
|
DATA ( C(14,I), I = 1, 99 ) /
|
|
& 9861, 7101, 6257, 7878, 11170, 11638, 7542, 2592, 2591,
|
|
& 6074, 1428, 8925, 11736, 8925, 5623, 5623, 1535, 6759,
|
|
& 9953, 9953, 11459, 9953, 7615, 7615, 11377, 11377, 2762,
|
|
& 11734, 11459, 6892, 1535, 6759, 4695, 1535, 6892, 2,
|
|
& 2, 6892, 6892, 4177, 4177, 6339, 6950, 1226, 1226,
|
|
& 1226, 4177, 6892, 6890, 3640, 3640, 1226, 10590, 10590,
|
|
& 6950, 6950, 6950, 1226, 6950, 6950, 7586, 7586, 7565,
|
|
& 7565, 3640, 3640, 6950, 7565, 6950, 3599, 3599, 3599,
|
|
& 2441, 4885, 4885, 4885, 7565, 7565, 1226, 1226, 1226,
|
|
& 6950, 7586, 1346, 2441, 6339, 3640, 6950, 10590, 6339,
|
|
& 6950, 6950, 6950, 1226, 1226, 6950, 836, 6891, 7565/
|
|
DATA ( C(15,I), I = 1, 99 ) /
|
|
& 13482, 5629, 6068, 11974, 4732, 14946, 12097, 17609, 11740,
|
|
& 15170, 10478, 10478, 17610, 2, 2, 7064, 7064, 7064,
|
|
& 5665, 1771, 2947, 4453, 12323, 17610, 14809, 14809, 5665,
|
|
& 5665, 2947, 2947, 2947, 2947, 12323, 12323, 4453, 4453,
|
|
& 2026, 11772, 2026, 11665, 12323, 12323, 3582, 2940, 2940,
|
|
& 6654, 4449, 9254, 11470, 304, 304, 11470, 304, 11470,
|
|
& 6156, 9254, 11772, 6654, 11772, 6156, 11470, 11470, 11772,
|
|
& 11772, 11772, 11470, 11470, 304, 11470, 11470, 304, 11470,
|
|
& 304, 11470, 304, 304, 304, 6654, 11508, 304, 304,
|
|
& 6156, 3582, 11470, 11470, 11470, 17274, 6654, 6654, 6744,
|
|
& 6711, 6654, 6156, 3370, 6654, 12134, 3370, 6654, 3582/
|
|
DATA ( C(16,I), I = 1, 99 ) /
|
|
& 13482, 5629, 6068, 11974, 4732, 14946, 12097, 17609, 11740,
|
|
& 15170, 10478, 10478, 17610, 2, 2, 7064, 7064, 7064,
|
|
& 5665, 1771, 2947, 4453, 12323, 17610, 14809, 14809, 5665,
|
|
& 5665, 2947, 2947, 2947, 2947, 12323, 12323, 4453, 4453,
|
|
& 2026, 11772, 2026, 11665, 12323, 12323, 3582, 2940, 2940,
|
|
& 6654, 4449, 9254, 11470, 304, 304, 11470, 304, 11470,
|
|
& 6156, 9254, 11772, 6654, 11772, 6156, 11470, 11470, 11772,
|
|
& 11772, 11772, 11470, 11470, 304, 11470, 11470, 304, 11470,
|
|
& 304, 11470, 304, 304, 304, 6654, 11508, 304, 304,
|
|
& 6156, 3582, 11470, 11470, 11470, 17274, 6654, 6654, 6744,
|
|
& 6711, 6654, 6156, 3370, 6654, 12134, 3370, 6654, 3582/
|
|
DATA ( C(17,I), I = 1, 99 ) /
|
|
& 34566, 38838, 23965, 17279, 35325, 33471, 330, 36050, 26419,
|
|
& 3012, 38428, 36430, 36430, 36755, 39629, 5749, 5749, 36755,
|
|
& 5749, 14353, 14353, 14353, 32395, 32395, 32395, 32395, 32396,
|
|
& 32396, 32396, 32396, 27739, 14353, 36430, 36430, 36430, 15727,
|
|
& 38428, 28987, 28987, 27739, 38428, 27739, 18786, 14353, 15727,
|
|
& 28987, 19151, 19757, 19757, 19757, 14353, 22876, 19151, 24737,
|
|
& 24737, 4412, 30567, 30537, 19757, 30537, 19757, 30537, 30537,
|
|
& 4412, 24737, 28987, 19757, 19757, 19757, 30537, 30537, 33186,
|
|
& 4010, 4010, 4010, 17307, 15217, 32789, 37709, 4010, 4010,
|
|
& 4010, 33186, 33186, 4010, 11057, 39388, 33186, 1122, 15089,
|
|
& 39629, 2, 2, 23899, 16466, 16466, 17038, 9477, 9260/
|
|
DATA ( C(18,I), I = 1, 99 ) /
|
|
& 31929, 40295, 2610, 5177, 17271, 23770, 9140, 952, 39631,
|
|
& 3, 11424, 49719, 38267, 25172, 2, 2, 59445, 2,
|
|
& 59445, 38267, 44358, 14673, 53892, 14674, 14673, 14674, 41368,
|
|
& 17875, 17875, 30190, 20444, 55869, 15644, 25499, 15644, 20983,
|
|
& 44358, 15644, 15644, 485, 41428, 485, 485, 485, 41428,
|
|
& 53798, 50230, 53798, 50253, 50253, 35677, 35677, 17474, 7592,
|
|
& 4098, 17474, 485, 41428, 485, 41428, 485, 41428, 485,
|
|
& 41428, 41428, 41428, 41428, 41428, 9020, 22816, 4098, 4098,
|
|
& 4098, 7592, 42517, 485, 50006, 50006, 22816, 22816, 9020,
|
|
& 485, 41428, 41428, 41428, 41428, 50006, 485, 41428, 41428,
|
|
& 41428, 41428, 22816, 41428, 41428, 485, 485, 485, 9020/
|
|
DATA ( C(19,I), I = 1, 99 ) /
|
|
& 73726, 16352, 16297, 74268, 60788, 8555, 1077, 25486, 86595,
|
|
& 59450, 19958, 62205, 62205, 4825, 4825, 89174, 89174, 62205,
|
|
& 19958, 62205, 19958, 27626, 63080, 62205, 62205, 62205, 19958,
|
|
& 8914, 83856, 30760, 47774, 47774, 19958, 62205, 39865, 39865,
|
|
& 74988, 75715, 75715, 74988, 34522, 74988, 74988, 25101, 44621,
|
|
& 44621, 44621, 25101, 25101, 25101, 44621, 47768, 41547, 44621,
|
|
& 10273, 74988, 74988, 74988, 74988, 74988, 74988, 34522, 34522,
|
|
& 67796, 67796, 30208, 2, 67062, 18500, 29251, 29251, 2,
|
|
& 67796, 67062, 38649, 59302, 6225, 67062, 6475, 6225, 46772,
|
|
& 38649, 67062, 46772, 46772, 67062, 46772, 25372, 67062, 6475,
|
|
& 25372, 67062, 67062, 67062, 6225, 67062, 67062, 68247, 80676/
|
|
DATA ( C(20,I), I = 1, 99 )/
|
|
& 103650, 50089, 70223, 41805, 74847,112775, 40889, 64866, 44053,
|
|
& 1754,129471, 13630, 53467, 53467, 61378,133761, 2,133761,
|
|
& 2,133761,133761, 65531, 65531, 65531, 38080,133761,133761,
|
|
& 131061, 5431, 65531, 78250, 11397, 38841, 38841,107233,107233,
|
|
& 111286, 19065, 38841, 19065, 19065, 16099,127638, 82411, 96659,
|
|
& 96659, 82411, 96659, 82411, 51986,101677, 39264, 39264,101677,
|
|
& 39264, 39264, 47996, 96659, 82411, 47996, 10971, 10004, 82411,
|
|
& 96659, 82411, 82411, 82411, 96659, 96659, 96659, 82411, 96659,
|
|
& 51986,110913, 51986, 51986,110913, 82411, 54713, 54713, 22360,
|
|
& 117652, 22360, 78250, 78250, 91996, 22360, 91996, 97781, 91996,
|
|
& 97781, 91996, 97781, 97781, 91996, 97781, 97781, 36249, 39779/
|
|
SAVE P, C, SAMPLS, NP, VAREST
|
|
IF ( NDIM .GT. NLIM .OR. NDIM .LT. 1 ) THEN
|
|
INFORM = 2
|
|
FINEST = 0.d0
|
|
ABSERR = 1.d0
|
|
RETURN
|
|
ENDIF
|
|
INFORM = 1
|
|
INTVLS = 0
|
|
IF ( MINVLS .GE. 0 ) THEN
|
|
FINEST = 0.d0
|
|
VAREST = 0.d0
|
|
SAMPLS = MINSMP
|
|
DO I = 1, PLIM
|
|
NP = I
|
|
IF ( MINVLS .LT. 2*SAMPLS*P(I) ) GO TO 10
|
|
END DO
|
|
SAMPLS = MAX( MINSMP, INT(MINVLS/( 2*P(NP)) ) )
|
|
ENDIF
|
|
10 VK(1) = ONE/DBLE(P(NP))
|
|
DO I = 2, NDIM
|
|
VK(I) = MOD( DBLE(C(NP,NDIM-1))*VK(I-1), ONE )
|
|
END DO
|
|
FINVAL = 0.d0
|
|
VARSQR = 0.d0
|
|
*
|
|
* Compute mean and standard error for SAMPLS randomized lattice rules
|
|
*
|
|
DO I = 1, SAMPLS
|
|
CALL KROSUM( NDIM, VALUE, P(NP), VK, FUNCTN, ALPHA, X )
|
|
DIFINT = ( VALUE - FINVAL )/DBLE(I)
|
|
FINVAL = FINVAL + DIFINT
|
|
VARSQR = DBLE(I - 2)*VARSQR/DBLE(I) + DIFINT*DIFINT
|
|
END DO
|
|
INTVLS = INTVLS + 2*SAMPLS*P(NP)
|
|
VARPRD = VAREST*VARSQR
|
|
FINEST = FINEST + ( FINVAL - FINEST )/( 1.d0 + VARPRD )
|
|
IF ( VARSQR .GT. 0.d0 ) VAREST = ( 1.d0 + VARPRD )/VARSQR
|
|
ABSERR = 3.d0*SQRT( VARSQR/( 1.d0 + VARPRD ) )
|
|
IF ( ABSERR .GT. MAX( ABSEPS, ABS(FINEST)*RELEPS ) ) THEN
|
|
IF ( NP .LT. PLIM ) THEN
|
|
NP = NP + 1
|
|
ELSE
|
|
SAMPLS = MIN( 3*SAMPLS/2, ( MAXVLS - INTVLS )/( 2*P(NP) ) )
|
|
SAMPLS = MAX( MINSMP, SAMPLS )
|
|
ENDIF
|
|
IF ( INTVLS + 2*SAMPLS*P(NP) .LE. MAXVLS ) GO TO 10
|
|
ELSE
|
|
INFORM = 0
|
|
ENDIF
|
|
MINVLS = INTVLS
|
|
END SUBROUTINE KROBOV
|
|
*
|
|
SUBROUTINE KROSUM( NDIM, SUMKRO, PRIME, VK, FUNCTN, ALPHA, X )
|
|
INTEGER, INTENT(IN):: NDIM, PRIME
|
|
DOUBLE PRECISION, INTENT(OUT) :: SUMKRO
|
|
DOUBLE PRECISION, DIMENSION(:), INTENT(INOUT) :: ALPHA,X ! size NDIM
|
|
INTEGER :: K !, J
|
|
DOUBLE PRECISION :: ONE
|
|
DOUBLE PRECISION, DIMENSION(:), INTENT(IN) :: VK
|
|
INTERFACE
|
|
DOUBLE PRECISION FUNCTION FUNCTN(N,Z)
|
|
DOUBLE PRECISION,DIMENSION(:), INTENT(IN) :: Z
|
|
INTEGER, INTENT(IN) :: N
|
|
END FUNCTION FUNCTN
|
|
END INTERFACE
|
|
PARAMETER ( ONE = 1.d0 )
|
|
SUMKRO = 0.d0
|
|
CALL random_number(ALPHA(1:NDIM))
|
|
DO K = 1, PRIME
|
|
X(1:NDIM) = MOD( DBLE(K)*VK(1:NDIM) + ALPHA(1:NDIM), ONE )
|
|
X(1:NDIM) = ABS( 2.d0*X(1:NDIM) - ONE )
|
|
! PRINT *,'KROSUM W=',X(1:NDIM)
|
|
SUMKRO = SUMKRO+(FUNCTN(NDIM,X)-SUMKRO)/DBLE(2*K-1)
|
|
X(1:NDIM) = ONE - X(1:NDIM)
|
|
SUMKRO = SUMKRO+(FUNCTN(NDIM,X)-SUMKRO)/DBLE(2*K)
|
|
END DO
|
|
END SUBROUTINE KROSUM
|
|
END MODULE KROBOVMOD
|
|
|