MPI-AMRVAC  3.0
The MPI - Adaptive Mesh Refinement - Versatile Advection Code
mod_odeint.t
Go to the documentation of this file.
1 !> This module packages odeint from numerical recipes.
2 module mod_odeint
3  implicit none
4  integer :: maxstp, nmax, kmaxx
5  parameter(maxstp=10000,nmax=50,kmaxx=200)
6  double precision :: tiny
7  parameter(tiny=1.d-30)
8 
9 contains
10 
11  subroutine odeint(ystart,nvar,x1,x2,eps,h1,hmin,nok,nbad,derivs,rkqs,ierror)
12 
13  INTEGER nbad,nok,nvar
14  double precision eps,h1,hmin,x1,x2,ystart(nvar)
15  INTEGER i,nstp
16  double precision h,hdid,hnext,x,xsav,dydx(NMAX),y(NMAX),yscal(NMAX)
17  integer kmax, kount
18  double precision dxsav, yp(NMAX,KMAXX), xp(KMAXX)
19  ! Can be 0: success, 1: hmin too small, 2: MAXSTP exceeded
20  integer, intent(out) :: ierror
21 
22  EXTERNAL derivs,rkqs
23 
24  COMMON /path/ kmax,kount,dxsav,xp,yp
25 
26  x = x1
27  h = sign(h1,x2-x1)
28  nok = 0
29  nbad = 0
30  kount = 0
31  xsav = 0.d0
32 
33  do i=1,nvar
34  y(i)=ystart(i)
35  end do
36 
37  if (kmax.gt.0) xsav=x-2.d0*dxsav
38 
39  do nstp=1,maxstp
40  call derivs(x,y,dydx)
41  do i=1,nvar
42  yscal(i)=abs(y(i))+abs(h*dydx(i))+tiny
43  end do
44 
45  if(kmax.gt.0)then
46  if(abs(x-xsav).gt.abs(dxsav)) then
47  if(kount.lt.kmax-1)then
48  kount=kount+1
49  xp(kount)=x
50  do i=1,nvar
51  yp(i,kount)=y(i)
52  end do
53  xsav=x
54  end if
55  end if
56  end if
57 
58  if((x+h-x2)*(x+h-x1).gt.0.d0) h=x2-x
59 
60  if (any(y(1:nvar) .ne. y(1:nvar)) .or. any(dydx(1:nvar) .ne. dydx(1:nvar)) .or. x .ne. x) then
61  write(*,*) "ODEINT BEFORE CALL RKQS: NaN in x, dydx, or y!"
62  write(*,*) "x",x
63  write(*,*) "y",y
64  write(*,*) "dydx",dydx
65  write(*,*) "exiting..."
66  ierror = 2
67  return
68  end if
69 
70  call rkqs(y,dydx,nvar,x,h,eps,yscal,hdid,hnext,derivs)
71 
72  if (any(y(1:nvar) .ne. y(1:nvar)) .or. any(dydx(1:nvar) .ne. dydx(1:nvar)) .or. x .ne. x) then
73  write(*,*) "ODEINT AFTER CALL RKQS: NaN in x, dydx, or y!"
74  write(*,*) "x",x
75  write(*,*) "y",y
76  write(*,*) "dydx",dydx
77  write(*,*) "exiting..."
78  ierror = 2
79  return
80  end if
81 
82  if(hdid.eq.h)then
83  nok=nok+1
84  else
85  nbad=nbad+1
86  end if
87 
88  if((x-x2)*(x2-x1).ge.0.d0)then
89  do i=1,nvar
90  ystart(i)=y(i)
91  end do
92  if(kmax.ne.0)then
93  kount=kount+1
94  xp(kount)=x
95  do i=1,nvar
96  yp(i,kount)=y(i)
97  end do
98  end if
99 
100  ierror = 0
101  return
102  end if
103 
104  if(abs(hnext).lt.hmin) then
105  ierror = 1
106  end if
107 
108  h=hnext
109  end do
110 
111  ierror = 2
112  end subroutine odeint
113 
114  SUBROUTINE rkqs(y,dydx,n,x,htry,eps,yscal,hdid,hnext,derivs)
115 
116  INTEGER n,NMAX
117  double precision eps,hdid,hnext,htry,x,dydx(n),y(n),yscal(n)
118  EXTERNAL derivs
119  parameter(nmax=50)
120 ! CU USES derivs,rkck
121  INTEGER i
122  double precision errmax,h,xnew,yerr(NMAX),ytemp(NMAX),SAFETY,PGROW,PSHRNK,ERRCON
123  parameter(safety=0.9d0,pgrow=-.2d0,pshrnk=-.25d0,errcon=1.89d-4)
124 
125  h=htry
126 
127  if (any(y(1:n) .ne. y(1:n)) .or. any(dydx(1:n) .ne. dydx(1:n)) .or. x .ne. x) then
128  write(*,*) "RKQS BEFORE CALL RKCK: NaN in x, dydx, or y!"
129  write(*,*) "x",x
130  write(*,*) "y",y
131  write(*,*) "dydx",dydx
132  write(*,*) "exiting..."
133  return
134  end if
135 
136  1 call rkck(y,dydx,n,x,h,ytemp,yerr,derivs)
137  if (any(y(1:n) .ne. y(1:n)) .or. any(dydx(1:n) .ne. dydx(1:n)) .or. x .ne. x) then
138  write(*,*) "RKQS AFTER CALL RKCK: NaN in x, dydx, or y!"
139  write(*,*) "x",x
140  write(*,*) "y",y
141  write(*,*) "dydx",dydx
142  write(*,*) "exiting..."
143  return
144  end if
145 
146  errmax=0.d0
147  do 11 i=1,n
148  errmax=max(errmax,abs(yerr(i)/yscal(i)))
149  11 continue
150  errmax=errmax/eps
151  if(errmax.gt.1.d0)then
152  h=safety*h*(errmax**pshrnk)
153  if(h.lt.0.1d0*h)then
154  h=.1d0*h
155  end if
156  xnew=x+h
157  if(xnew.eq.x) call stop('stepsize underflow in rkqs')
158  goto 1
159  else
160  if(errmax.gt.errcon)then
161  hnext=safety*h*(errmax**pgrow)
162  else
163  hnext=5.d0*h
164  end if
165  hdid=h
166  x=x+h
167  do 12 i=1,n
168  y(i)=ytemp(i)
169  12 continue
170  return
171  end if
172  END subroutine rkqs
173 !C (C) Copr. 1986-92 Numerical Recipes Software Vs1&v%1jw#<?4210(9p#.
174 
175  SUBROUTINE rkck(y,dydx,n,x,h,yout,yerr,derivs)
176 
177  INTEGER n,NMAX
178  double precision h,x,dydx(n),y(n),yerr(n),yout(n)
179  EXTERNAL derivs
180  parameter(nmax=50)
181 !CU USES derivs
182  INTEGER i
183  double precision ak2(NMAX),ak3(NMAX),ak4(NMAX),ak5(NMAX),ak6(NMAX),ytemp(NMAX),A2,A3,A4,A5,A6,B21,B31,B32,B41,B42,B43,B51, &
184  B52,B53,&
185  B54,B61,B62,B63,B64,B65,C1,C3,C4,C6,DC1,DC3,DC4,DC5,DC6
186  parameter(a2=.2d0,a3=.3d0,a4=.6d0,a5=1.d0, &
187  a6=.875d0,b21=.2d0,b31=3.d0/40.d0,&
188  b32=9.d0/40.d0,b41=.3d0,b42=-.9d0,b43=1.2d0,&
189  b51=-11.d0/54.d0,b52=2.5d0,&
190  b53=-70.d0/27.d0,b54=35.d0/27.d0,b61=1631.d0/55296.d0, &
191  b62=175.d0/512.d0, &
192  b63=575.d0/13824.d0,b64=44275.d0/110592.d0, &
193  b65=253.d0/4096.d0,c1=37.d0/378.d0,&
194  c3=250.d0/621.d0,c4=125.d0/594.d0,c6=512.d0/1771.d0,&
195  dc1=c1-2825.d0/27648.d0,&
196  dc3=c3-18575.d0/48384.d0,dc4=c4-13525.d0/55296.d0,&
197  dc5=-277.d0/14336.d0,&
198  dc6=c6-.25d0)
199  if (any(y(1:n) .ne. y(1:n)) .or. any(dydx(1:n) .ne. dydx(1:n))) then
200  write(*,*) "NaNs IN RKCK, STEP 0!"
201  write(*,*) "y0",y(1:n)
202  write(*,*) "derivs",dydx(1:n)
203  write(*,*) "ABORTING..."
204  call mpistop()
205  end if
206  do 11 i=1,n
207  ytemp(i)=y(i)+b21*h*dydx(i)
208  11 continue
209  call derivs(x+a2*h,ytemp,ak2)
210  if (any(ytemp(1:n) .ne. ytemp(1:n)) .or. any(ak2(1:n) .ne. ak2(1:n))) then
211  write(*,*) "NaNs IN RKCK, STEP 1!"
212  write(*,*) "y1",ytemp(1:n)
213  write(*,*) "derivs",ak2(1:n)
214  write(*,*) "ABORTING..."
215  call mpistop()
216  end if
217  do 12 i=1,n
218  ytemp(i)=y(i)+h*(b31*dydx(i)+b32*ak2(i))
219  12 continue
220  call derivs(x+a3*h,ytemp,ak3)
221  if (any(ytemp(1:n) .ne. ytemp(1:n)) .or. any(ak3(1:n) .ne. ak3(1:n))) then
222  write(*,*) "NaNs IN RKCK, STEP 2!"
223  write(*,*) "y2",ytemp(1:n)
224  write(*,*) "derivs",ak3(1:n)
225  write(*,*) "ABORTING..."
226  call mpistop()
227  end if
228  do 13 i=1,n
229  ytemp(i)=y(i)+h*(b41*dydx(i)+b42*ak2(i)+b43*ak3(i))
230  13 continue
231  call derivs(x+a4*h,ytemp,ak4)
232  if (any(ytemp(1:n) .ne. ytemp(1:n)) .or. any(ak4(1:n) .ne. ak4(1:n))) then
233  write(*,*) "NaNs IN RKCK, STEP 3!"
234  write(*,*) "y3",ytemp(1:n)
235  write(*,*) "derivs",ak4(1:n)
236  write(*,*) "ABORTING..."
237  call mpistop()
238  end if
239  do 14 i=1,n
240  ytemp(i)=y(i)+h*(b51*dydx(i)+b52*ak2(i)+b53*ak3(i)+b54*ak4(i))
241  14 continue
242  call derivs(x+a5*h,ytemp,ak5)
243  if (any(ytemp(1:n) .ne. ytemp(1:n)) .or. any(ak5(1:n) .ne. ak5(1:n))) then
244  write(*,*) "NaNs IN RKCK, STEP 4!"
245  write(*,*) "y4",ytemp(1:n)
246  write(*,*) "derivs",ak5(1:n)
247  write(*,*) "ABORTING..."
248  call mpistop()
249  end if
250  do 15 i=1,n
251  ytemp(i)=y(i)+h*(b61*dydx(i)+b62*ak2(i)+b63*ak3(i)+b64*ak4(i)+b65*ak5(i))
252  15 continue
253  call derivs(x+a6*h,ytemp,ak6)
254  if (any(ytemp(1:n) .ne. ytemp(1:n)) .or. any(ak6(1:n) .ne. ak6(1:n))) then
255  write(*,*) "NaNs IN RKCK, STEP 1!"
256  write(*,*) "y15",ytemp(1:n)
257  write(*,*) "derivs",ak6(1:n)
258  write(*,*) "ABORTING..."
259  call mpistop()
260  end if
261  do 16 i=1,n
262  yout(i)=y(i)+h*(c1*dydx(i)+c3*ak3(i)+c4*ak4(i)+c6*ak6(i))
263  16 continue
264  do 17 i=1,n
265  yerr(i)=h*(dc1*dydx(i)+dc3*ak3(i)+dc4*ak4(i)+dc5*ak5(i)+dc6*ak6(i))
266  17 continue
267  return
268  END subroutine rkck
269 !C (C) Copr. 1986-92 Numerical Recipes Software Vs1&v%1jw#<?4210(9p#.
270  subroutine stop(text)
271  character(len=*), intent(in) :: text
272  print*, text
273  stop
274  end subroutine stop
275 
276 end module mod_odeint
subroutine mpistop(message)
Exit MPI-AMRVAC with an error message.
Definition: comm_lib.t:194
This module packages odeint from numerical recipes.
Definition: mod_odeint.t:2
subroutine odeint(ystart, nvar, x1, x2, eps, h1, hmin, nok, nbad, derivs, rkqs, ierror)
Definition: mod_odeint.t:12
integer nmax
Definition: mod_odeint.t:4
subroutine stop(text)
Definition: mod_odeint.t:271
integer maxstp
Definition: mod_odeint.t:4
integer kmaxx
Definition: mod_odeint.t:4
subroutine rkqs(y, dydx, n, x, htry, eps, yscal, hdid, hnext, derivs)
Definition: mod_odeint.t:115
subroutine rkck(y, dydx, n, x, h, yout, yerr, derivs)
Definition: mod_odeint.t:176
double precision tiny
Definition: mod_odeint.t:6