1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
c extraits de numerical recipies
c runge kutta d'ordre 4 adaptatif
c l'interface lsrgk a ete fait en s'inspirant de lsode
c voir lsode.f pour comprendre le sens des variables
C---------------------------------------------------------------------
subroutine lsrgk (f, neq, y, t, tout, itol, rtol, atol, itask,
1 istate, iopt, rwork, lrw, iwork, liw, jac, mf)
external f, jac,rkqc
integer neq, itol, itask, istate, iopt, lrw, iwork, liw, mf
double precision y, t, tout, rtol, atol, rwork
integer nok,nbad
dimension neq(*), y(*), rtol(*), atol(*), rwork(lrw), iwork(liw)
integer iero
common/ierode/iero
iero=0
call odeint(y,neq,t,tout,atol(1),1.0d-4,0.0d0,nok,nbad,f,rkqc)
t=tout
if (iero.gt.0) istate=-1
return
end
C---------
C subroutine de Num Recipies modifiee pour avoir le meme test
C d'arret que lsode
subroutine odeint(ystart,nvar,x1,x2,eps,h1,hmin,nok,nbad,derivs,rk
*qc)
C implicit undefined (a-z)
external derivs,rkqc
integer maxstp,nmax,kmax,kount,nvar,i,nok,nbad,nstp
double precision two,zero,tiny,dxsav,xp(200),yp(10,200),x,h
parameter (maxstp=10000,nmax=10,two=2.0,zero=0.0,tiny=1.e-30)
double precision x1,x2,eps,h1,hmin,xsav,hdid,hnext
double precision ystart(nvar),yscal(nmax),y(nmax),dydx(nmax)
character*80 messag
common /path/ kmax,kount,dxsav,xp,yp
integer iero
common/ierode/iero
iero=0
if ( abs(x2-x1).le.tiny) return
x=x1
h=sign(h1,x2-x1)
nok=0
nbad=0
kount=0
do 11 i=1,nvar
y(i)=ystart(i)
11 continue
xsav=x-dxsav*two
do 16 nstp=1,maxstp
call derivs(nvar,x,y,dydx)
if (iero.gt.0) return
do 12 i=1,nvar
yscal(i)=abs(y(i))+abs(h*dydx(i))+tiny
12 continue
if(kmax.gt.0)then
if(abs(x-xsav).gt.abs(dxsav)) then
if(kount.lt.kmax-1)then
kount=kount+1
xp(kount)=x
do 13 i=1,nvar
yp(i,kount)=y(i)
13 continue
xsav=x
endif
endif
endif
if((x+h-x2)*(x+h-x1).gt.zero) h=x2-x
call rkqc(y,dydx,nvar,x,h,eps,yscal,hdid,hnext,derivs)
if(iero.gt.0) return
if(hdid.eq.h)then
nok=nok+1
else
nbad=nbad+1
endif
if((x-x2)*(x2-x1).ge.zero)then
do 14 i=1,nvar
ystart(i)=y(i)
14 continue
if(kmax.ne.0)then
kount=kount+1
xp(kount)=x
do 15 i=1,nvar
yp(i,kount)=y(i)
15 continue
endif
return
endif
if(abs(hnext).lt.hmin) then
write(messag, 17) hnext,hmin
hnext=hmin
endif
h=hnext
16 continue
iero=-1
c print *, 'Trop d''iterations a faire pour la precision demandee.'
return
17 format('stepsize ',e10.3,' smaller than minimum ',e10.3)
end
subroutine rk4(y,dydx,n,x,h,yout,derivs)
C implicit undefined (a-z)
external derivs
integer n,i,nmax
parameter (nmax=10)
double precision x,h,hh,xh,h6
double precision y(n),dydx(n),yout(n),yt(nmax),dyt(nmax),dym(nmax)
integer iero
common/ierode/iero
iero=0
hh=h*0.5
h6=h/6.
xh=x+hh
do 11 i=1,n
yt(i)=y(i)+hh*dydx(i)
11 continue
call derivs(n,xh,yt,dyt)
if (iero.gt.0) return
do 12 i=1,n
yt(i)=y(i)+hh*dyt(i)
12 continue
call derivs(n,xh,yt,dym)
if (iero.gt.0) return
do 13 i=1,n
yt(i)=y(i)+h*dym(i)
dym(i)=dyt(i)+dym(i)
13 continue
call derivs(n,x+h,yt,dyt)
if (iero.gt.0) return
do 14 i=1,n
yout(i)=y(i)+h6*(dydx(i)+dyt(i)+2.*dym(i))
14 continue
return
end
subroutine rkqc(y,dydx,n,x,htry,eps,yscal,hdid,hnext,derivs)
C implicit undefined (a-z)
integer nmax,n,i
double precision fcor,one,safety,errcon
parameter (nmax=10,fcor=.0666666667,
$ one=1.0,safety=0.9,errcon=6.e-4)
double precision x,htry,eps,hdid,hnext,pgrow,pshrnk,xsav,hh
double precision errmax,h,dysav(nmax)
double precision y(n),dydx(n),yscal(n),ytemp(nmax),ysav(nmax)
external derivs
integer iero
common/ierode/iero
iero=0
pgrow=-0.20
pshrnk=-0.25
xsav=x
do 11 i=1,n
ysav(i)=y(i)
dysav(i)=dydx(i)
11 continue
h=htry
1 hh=0.5*h
call rk4(ysav,dysav,n,xsav,hh,ytemp,derivs)
x=xsav+hh
call derivs(n,x,ytemp,dydx)
if (iero.gt.0) return
call rk4(ytemp,dydx,n,x,hh,y,derivs)
x=xsav+h
if(x.eq.xsav) then
c print *, 'stepsize not significant in rkqc.'
iero=1
return
endif
call rk4(ysav,dysav,n,xsav,h,ytemp,derivs)
errmax=0.
do 12 i=1,n
ytemp(i)=y(i)-ytemp(i)
errmax=max(errmax,abs(ytemp(i)/(yscal(i)*eps)))
12 continue
if(errmax.gt.one) then
h=safety*h*(errmax**pshrnk)
goto 1
else
hdid=h
if(errmax.gt.errcon)then
hnext=safety*h*(errmax**pgrow)
else
hnext=4.*h
endif
endif
do 13 i=1,n
y(i)=y(i)+ytemp(i)*fcor
13 continue
return
end
|