C.hr stng1.f C....*...1.........2.........3.........4.........5.........6.........7.* C C stng1.f C C Copyright (C) 1995, 2003. C C A. Ronald Gallant, P.O. Box 659, Chapel Hill NC 27514-0659, USA C C Permission to use, copy, modify, and distribute this software and C its documentation for any purpose and without fee is hereby C granted, provided that the above copyright notice appear in all C copies and that both that copyright notice and this permission C notice appear in supporting documentation. C C This software is provided "as is" without any expressed or implied C warranty. C C....*...1.........2.........3.........4.........5.........6.........7.* C.hr stng1 C@ *....*...1.........2.........3.........4.........5.........6.........7.* * * stng1 12/23/94 * * purpose * compute a realization of length n from an explicit order 1 strong * scheme for the nonautonomous Ito stochastic differential equation * * dX = A(t,X)dt + B(t,X)dW * * where X has dimension d and W has dimension m. * * usage * call stng1(drift,difuse,t,X,A,B,d,m,t0,X0,dt,iseed,n,Y) * * libf calls * unsk * * arguments * drift - subroutine with usage call drift(t,X,d,A) that is * declared external in the calling program. * input, external * difuse - subroutine with usage call difuse(t,X,d,m,B) that is * declared external in the calling program. * input, external * t - input to drift and difuse, on return t=t0+n*dt. * workspace, real*8 * X - input to drift and difuse, a vector of length d. on * return X(i)=Y(i,n) for i=1,...,d. * workspace, real*8 * A - output of drift, a vector of length d. * workspace, real*8 * B - output of difuse, a matrix of order d by m. * workspace, real*8 * d - dimension of X and A, row dimension of B and Y. d must * be less than parameter md which is currently set to 15. * input, integer*4 * m - column dimension of B. m must be less than parameter mm * which is currently set to 5. * input, integer*4 * t0 - time of initial condition. * input, real*8 * X0 - initial condition at time t=t0, a vector of length d. * input, real*8 * dt - time increment for the simulations. * input, real*8 * iseed - seed for the simulations. * input and output, integer*4 * n - number of simulations, column dimension of Y. * input, integer*4 * Y - computed simulations, a d by n matrix. * output, real*8 * * remarks * To reduce memory requirements for a computation such as * (1/T)(integral from 0 to T of func[X(t)]) where T = n*dt, * dimension as Y(d,n0) and use * do k=1,n,n0 * call stng1(drift,difuse,t0,X0,A,B,d,m,t0,X0,dt,iseed,n0,Y) * do it=1,n0 * do i=1,d * ave(i) = ave(i) + func(Y(i,it))/n * end do * end do * end do * instead of dimensioning as Y(d,n) and using * call stng1(drift,difuse,t,X,A,B,d,m,t0,X0,dt,iseed,n,Y) * do it=1,n * do i=1,d * ave(i) = ave(i) + func(Y(i,it))/n * end do * end do * * reference * Kloeden, Peter E., and Eckhard Platen (1992), Numerical Solution * of Stochastic Differential Equations, Berlin, Springer-Verlag, * p. 347 (integral approximation) and p. 376 (explicit scheme). * subroutine stng1(drift,difuse,t,X,A,B,d,m,t0,X0,dt,iseed,n,Y) implicit none * arguments external drift, difuse real*8 X, A, B, X0, Y real*8 t,t0,dt integer*4 d, m, iseed, n dimension X(d), A(d), B(d,m), X0(d), Y(d,n) * parameters real*8 pi parameter (pi=3.141592653589793d0) integer*4 p parameter (p=50) * p should be greater than 0.05/dt, 50=0.05/1.d-3 integer*4 md, mm integer*4 nout parameter (md=15, mm=5) parameter (nout=3) * local variables intrinsic DSQRT real*4 z,unsk real*8 z0,z1,z2 real*8 dW,Ip real*8 Tn,BTn real*8 sum real*8 tmp,r,left,right real*8 rdt,rho,rrho,rtwo integer*4 i,j,k,it,j1,j2 dimension z0(mm),z1(mm),z2(mm) dimension dW(mm),Ip(mm,mm) dimension Tn(md,mm),BTn(md*mm) dimension sum(md) * error traps if (m.gt.mm) then write(nout,'(a,i5)') 'Error, stng1, mm < m =', m stop end if if (d.gt.md) then write(nout,'(a,i5)') 'Error, stng1, md < d =', d stop end if * explicit order 1 strong scheme rho = 0.d0 do k=1,p r = k rho = rho + 1.d0/(r**2) end do rho = 1.d0/12.d0 - rho/(2.d0*(pi**2)) rdt = DSQRT(dt) rrho = DSQRT(rho) rtwo = DSQRT(2.d0) do i=1,d X(i)=X0(i) end do t = t0 do it=1,n call drift(t,X,d,A) call difuse(t,X,d,m,B) do j=1,m do i=1,d Tn(i,j) = X(i) + A(i)*dt + B(i,j)*rdt end do end do do j=1,m z = unsk(iseed) z0(j) = z dW(j) = rdt*z end do if (m.eq.1) then Ip(1,1) = 0.5d0*(dW(1)**2 - dt) else do j=1,m Ip(j,j) = 0.5d0*(dW(j)**2 - dt) z = unsk(iseed) z1(j) = z end do do j1=1,m do j2=1,j1-1 left = 0.5d0*z0(j1)*z0(j2) right = rrho*(z1(j1)*z0(j2) - z1(j2)*z0(j1)) Ip(j1,j2) = dt*(left + right) Ip(j2,j1) = dt*(left - right) end do end do do k=1, p r = k do j=1,m z = unsk(iseed) z1(j) = z z = unsk(iseed) z2(j) = z end do do j1=1,m do j2=1,j1-1 left = z2(j1)*(rtwo*z0(j2) + z1(j2)) right = z2(j2)*(rtwo*z0(j1) + z1(j1)) tmp = (0.5d0/pi)*(dt/r)*(left - right) Ip(j1,j2) = Ip(j1,j2) + tmp Ip(j2,j1) = Ip(j2,j1) - tmp end do end do end do end if do i=1,d sum(i) = 0.d0 end do do j=1,m do i=1,d sum(i) = sum(i) + B(i,j)*dW(j) end do end do do j1=1,m call difuse(t,Tn(1,j1),d,m,BTn) do j2=1,m do i=1,d sum(i) = sum(i) & + (Ip(j1,j2)/rdt) * ( BTn(-d+d*j2+i) - B(i,j2) ) end do end do end do do i=1,d Y(i,it) = X(i) + A(i)*dt + sum(i) end do * For a stiff system the above loop is replaced by an equation * solver to solve Y = X + A(it,Y)dt + sum for Y. See p. 407 of * Kloeden and Platen (1992). Subroutine drift should be revised * to return first derivatives with respect to its argument X to * allow use of a solver that uses analytic first derivatives. do i=1,d X(i) = Y(i,it) end do t = t + dt end do return end