xref: /petsc/src/ts/impls/explicit/rk/rk.c (revision 193ac0bc5128976c4ec2c1a67f3f9cb026b77f22)
1e4dd521cSBarry Smith /*
226edb414Sasbjorn  * Code for Timestepping with Runge Kutta
326edb414Sasbjorn  *
426edb414Sasbjorn  * Written by
526edb414Sasbjorn  * Asbjorn Hoiland Aarrestad
626edb414Sasbjorn  * asbjorn@aarrestad.com
726edb414Sasbjorn  * http://asbjorn.aarrestad.com/
826edb414Sasbjorn  *
9e4dd521cSBarry Smith  */
10c6db04a5SJed Brown #include <private/tsimpl.h>                /*I   "petscts.h"   I*/
11c6db04a5SJed Brown #include <time.h>
12e4dd521cSBarry Smith 
13e4dd521cSBarry Smith typedef struct {
14e4dd521cSBarry Smith    Vec          y1,y2;  /* work wectors for the two rk permuations */
15a7cc72afSBarry Smith    PetscInt     nok,nnok; /* counters for ok and not ok steps */
16e4dd521cSBarry Smith    PetscReal    maxerror; /* variable to tell the maxerror allowed */
17e4dd521cSBarry Smith    PetscReal    ferror; /* variable to tell (global maxerror)/(total time) */
18262ff7bbSBarry Smith    PetscReal    tolerance; /* initial value set for maxerror by user */
19e4dd521cSBarry Smith    Vec          tmp,tmp_y,*k; /* two temp vectors and the k vectors for rk */
20e4dd521cSBarry Smith    PetscScalar  a[7][6]; /* rk scalars */
21e4dd521cSBarry Smith    PetscScalar  b1[7],b2[7]; /* rk scalars */
22e4dd521cSBarry Smith    PetscReal    c[7]; /* rk scalars */
23a7cc72afSBarry Smith    PetscInt     p,s; /* variables to tell the size of the runge-kutta solver */
245f70b478SJed Brown } TS_RK;
25e4dd521cSBarry Smith 
26262ff7bbSBarry Smith EXTERN_C_BEGIN
27262ff7bbSBarry Smith #undef __FUNCT__
28262ff7bbSBarry Smith #define __FUNCT__ "TSRKSetTolerance_RK"
297087cfbeSBarry Smith PetscErrorCode  TSRKSetTolerance_RK(TS ts,PetscReal aabs)
30262ff7bbSBarry Smith {
315f70b478SJed Brown   TS_RK *rk = (TS_RK*)ts->data;
32262ff7bbSBarry Smith 
33262ff7bbSBarry Smith   PetscFunctionBegin;
34262ff7bbSBarry Smith   rk->tolerance = aabs;
35262ff7bbSBarry Smith   PetscFunctionReturn(0);
36262ff7bbSBarry Smith }
37262ff7bbSBarry Smith EXTERN_C_END
38262ff7bbSBarry Smith 
39262ff7bbSBarry Smith #undef __FUNCT__
40262ff7bbSBarry Smith #define __FUNCT__ "TSRKSetTolerance"
41262ff7bbSBarry Smith /*@
42262ff7bbSBarry Smith    TSRKSetTolerance - Sets the total error the RK explicit time integrators
43262ff7bbSBarry Smith                       will allow over the given time interval.
44262ff7bbSBarry Smith 
453f9fe445SBarry Smith    Logically Collective on TS
46262ff7bbSBarry Smith 
47262ff7bbSBarry Smith    Input parameters:
48262ff7bbSBarry Smith +    ts  - the time-step context
49262ff7bbSBarry Smith -    aabs - the absolute tolerance
50262ff7bbSBarry Smith 
51262ff7bbSBarry Smith    Level: intermediate
52262ff7bbSBarry Smith 
53262ff7bbSBarry Smith .keywords: RK, tolerance
54262ff7bbSBarry Smith 
550f3b3ca1SHong Zhang .seealso: TSSundialsSetTolerance()
56262ff7bbSBarry Smith 
57262ff7bbSBarry Smith @*/
587087cfbeSBarry Smith PetscErrorCode  TSRKSetTolerance(TS ts,PetscReal aabs)
59262ff7bbSBarry Smith {
604ac538c5SBarry Smith   PetscErrorCode ierr;
61262ff7bbSBarry Smith 
62262ff7bbSBarry Smith   PetscFunctionBegin;
63c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(ts,aabs,2);
644ac538c5SBarry Smith   ierr = PetscTryMethod(ts,"TSRKSetTolerance_C",(TS,PetscReal),(ts,aabs));CHKERRQ(ierr);
65262ff7bbSBarry Smith   PetscFunctionReturn(0);
66262ff7bbSBarry Smith }
67e4dd521cSBarry Smith 
68e4dd521cSBarry Smith 
69e4dd521cSBarry Smith #undef __FUNCT__
705f70b478SJed Brown #define __FUNCT__ "TSSetUp_RK"
715f70b478SJed Brown static PetscErrorCode TSSetUp_RK(TS ts)
72e4dd521cSBarry Smith {
735f70b478SJed Brown   TS_RK          *rk = (TS_RK*)ts->data;
74a7cc72afSBarry Smith   PetscErrorCode ierr;
75e4dd521cSBarry Smith 
76e4dd521cSBarry Smith   PetscFunctionBegin;
77e4dd521cSBarry Smith   rk->nok      = 0;
78e4dd521cSBarry Smith   rk->nnok     = 0;
79262ff7bbSBarry Smith   rk->maxerror = rk->tolerance;
80e4dd521cSBarry Smith 
81e4dd521cSBarry Smith   /* fixing maxerror: global vs local */
82e4dd521cSBarry Smith   rk->ferror = rk->maxerror / (ts->max_time - ts->ptime);
83e4dd521cSBarry Smith 
84e4dd521cSBarry Smith   /* 34.0/45.0 gives double precision division */
85e4dd521cSBarry Smith   /* defining variables needed for Runge-Kutta computing */
86e4dd521cSBarry Smith   /* when changing below, please remember to change a, b1, b2 and c above! */
87e4dd521cSBarry Smith   /* Found in table on page 171: Dormand-Prince 5(4) */
88e4dd521cSBarry Smith 
89e4dd521cSBarry Smith   /* are these right? */
90e4dd521cSBarry Smith   rk->p=6;
91e4dd521cSBarry Smith   rk->s=7;
92e4dd521cSBarry Smith 
93e4dd521cSBarry Smith   rk->a[1][0]=1.0/5.0;
94e4dd521cSBarry Smith   rk->a[2][0]=3.0/40.0;
95e4dd521cSBarry Smith   rk->a[2][1]=9.0/40.0;
96e4dd521cSBarry Smith   rk->a[3][0]=44.0/45.0;
97e4dd521cSBarry Smith   rk->a[3][1]=-56.0/15.0;
98e4dd521cSBarry Smith   rk->a[3][2]=32.0/9.0;
99e4dd521cSBarry Smith   rk->a[4][0]=19372.0/6561.0;
100e4dd521cSBarry Smith   rk->a[4][1]=-25360.0/2187.0;
101e4dd521cSBarry Smith   rk->a[4][2]=64448.0/6561.0;
102e4dd521cSBarry Smith   rk->a[4][3]=-212.0/729.0;
103e4dd521cSBarry Smith   rk->a[5][0]=9017.0/3168.0;
104e4dd521cSBarry Smith   rk->a[5][1]=-355.0/33.0;
105e4dd521cSBarry Smith   rk->a[5][2]=46732.0/5247.0;
106e4dd521cSBarry Smith   rk->a[5][3]=49.0/176.0;
107e4dd521cSBarry Smith   rk->a[5][4]=-5103.0/18656.0;
108e4dd521cSBarry Smith   rk->a[6][0]=35.0/384.0;
109e4dd521cSBarry Smith   rk->a[6][1]=0.0;
110e4dd521cSBarry Smith   rk->a[6][2]=500.0/1113.0;
111e4dd521cSBarry Smith   rk->a[6][3]=125.0/192.0;
112e4dd521cSBarry Smith   rk->a[6][4]=-2187.0/6784.0;
113e4dd521cSBarry Smith   rk->a[6][5]=11.0/84.0;
114e4dd521cSBarry Smith 
115e4dd521cSBarry Smith 
116e4dd521cSBarry Smith   rk->c[0]=0.0;
117e4dd521cSBarry Smith   rk->c[1]=1.0/5.0;
118e4dd521cSBarry Smith   rk->c[2]=3.0/10.0;
119e4dd521cSBarry Smith   rk->c[3]=4.0/5.0;
120e4dd521cSBarry Smith   rk->c[4]=8.0/9.0;
121e4dd521cSBarry Smith   rk->c[5]=1.0;
122e4dd521cSBarry Smith   rk->c[6]=1.0;
123e4dd521cSBarry Smith 
124e4dd521cSBarry Smith   rk->b1[0]=35.0/384.0;
125e4dd521cSBarry Smith   rk->b1[1]=0.0;
126e4dd521cSBarry Smith   rk->b1[2]=500.0/1113.0;
127e4dd521cSBarry Smith   rk->b1[3]=125.0/192.0;
128e4dd521cSBarry Smith   rk->b1[4]=-2187.0/6784.0;
129e4dd521cSBarry Smith   rk->b1[5]=11.0/84.0;
130e4dd521cSBarry Smith   rk->b1[6]=0.0;
131e4dd521cSBarry Smith 
132e4dd521cSBarry Smith   rk->b2[0]=5179.0/57600.0;
133e4dd521cSBarry Smith   rk->b2[1]=0.0;
134e4dd521cSBarry Smith   rk->b2[2]=7571.0/16695.0;
135e4dd521cSBarry Smith   rk->b2[3]=393.0/640.0;
136e4dd521cSBarry Smith   rk->b2[4]=-92097.0/339200.0;
137e4dd521cSBarry Smith   rk->b2[5]=187.0/2100.0;
138e4dd521cSBarry Smith   rk->b2[6]=1.0/40.0;
139e4dd521cSBarry Smith 
140e4dd521cSBarry Smith 
141e4dd521cSBarry Smith   /* Found in table on page 170: Fehlberg 4(5) */
142e4dd521cSBarry Smith   /*
143e4dd521cSBarry Smith   rk->p=5;
144e4dd521cSBarry Smith   rk->s=6;
145e4dd521cSBarry Smith 
146e4dd521cSBarry Smith   rk->a[1][0]=1.0/4.0;
147e4dd521cSBarry Smith   rk->a[2][0]=3.0/32.0;
148e4dd521cSBarry Smith   rk->a[2][1]=9.0/32.0;
149e4dd521cSBarry Smith   rk->a[3][0]=1932.0/2197.0;
150e4dd521cSBarry Smith   rk->a[3][1]=-7200.0/2197.0;
151e4dd521cSBarry Smith   rk->a[3][2]=7296.0/2197.0;
152e4dd521cSBarry Smith   rk->a[4][0]=439.0/216.0;
153e4dd521cSBarry Smith   rk->a[4][1]=-8.0;
154e4dd521cSBarry Smith   rk->a[4][2]=3680.0/513.0;
155e4dd521cSBarry Smith   rk->a[4][3]=-845.0/4104.0;
156e4dd521cSBarry Smith   rk->a[5][0]=-8.0/27.0;
157e4dd521cSBarry Smith   rk->a[5][1]=2.0;
158e4dd521cSBarry Smith   rk->a[5][2]=-3544.0/2565.0;
159e4dd521cSBarry Smith   rk->a[5][3]=1859.0/4104.0;
160e4dd521cSBarry Smith   rk->a[5][4]=-11.0/40.0;
161e4dd521cSBarry Smith 
162e4dd521cSBarry Smith   rk->c[0]=0.0;
163e4dd521cSBarry Smith   rk->c[1]=1.0/4.0;
164e4dd521cSBarry Smith   rk->c[2]=3.0/8.0;
165e4dd521cSBarry Smith   rk->c[3]=12.0/13.0;
166e4dd521cSBarry Smith   rk->c[4]=1.0;
167e4dd521cSBarry Smith   rk->c[5]=1.0/2.0;
168e4dd521cSBarry Smith 
169e4dd521cSBarry Smith   rk->b1[0]=25.0/216.0;
170e4dd521cSBarry Smith   rk->b1[1]=0.0;
171e4dd521cSBarry Smith   rk->b1[2]=1408.0/2565.0;
172e4dd521cSBarry Smith   rk->b1[3]=2197.0/4104.0;
173e4dd521cSBarry Smith   rk->b1[4]=-1.0/5.0;
174e4dd521cSBarry Smith   rk->b1[5]=0.0;
175e4dd521cSBarry Smith 
176e4dd521cSBarry Smith   rk->b2[0]=16.0/135.0;
177e4dd521cSBarry Smith   rk->b2[1]=0.0;
178e4dd521cSBarry Smith   rk->b2[2]=6656.0/12825.0;
179e4dd521cSBarry Smith   rk->b2[3]=28561.0/56430.0;
180e4dd521cSBarry Smith   rk->b2[4]=-9.0/50.0;
181e4dd521cSBarry Smith   rk->b2[5]=2.0/55.0;
182e4dd521cSBarry Smith   */
183e4dd521cSBarry Smith   /* Found in table on page 169: Merson 4("5") */
184e4dd521cSBarry Smith   /*
185e4dd521cSBarry Smith   rk->p=4;
186e4dd521cSBarry Smith   rk->s=5;
187e4dd521cSBarry Smith   rk->a[1][0] = 1.0/3.0;
188e4dd521cSBarry Smith   rk->a[2][0] = 1.0/6.0;
189e4dd521cSBarry Smith   rk->a[2][1] = 1.0/6.0;
190e4dd521cSBarry Smith   rk->a[3][0] = 1.0/8.0;
191e4dd521cSBarry Smith   rk->a[3][1] = 0.0;
192e4dd521cSBarry Smith   rk->a[3][2] = 3.0/8.0;
193e4dd521cSBarry Smith   rk->a[4][0] = 1.0/2.0;
194e4dd521cSBarry Smith   rk->a[4][1] = 0.0;
195e4dd521cSBarry Smith   rk->a[4][2] = -3.0/2.0;
196e4dd521cSBarry Smith   rk->a[4][3] = 2.0;
197e4dd521cSBarry Smith 
198e4dd521cSBarry Smith   rk->c[0] = 0.0;
199e4dd521cSBarry Smith   rk->c[1] = 1.0/3.0;
200e4dd521cSBarry Smith   rk->c[2] = 1.0/3.0;
201e4dd521cSBarry Smith   rk->c[3] = 0.5;
202e4dd521cSBarry Smith   rk->c[4] = 1.0;
203e4dd521cSBarry Smith 
204e4dd521cSBarry Smith   rk->b1[0] = 1.0/2.0;
205e4dd521cSBarry Smith   rk->b1[1] = 0.0;
206e4dd521cSBarry Smith   rk->b1[2] = -3.0/2.0;
207e4dd521cSBarry Smith   rk->b1[3] = 2.0;
208e4dd521cSBarry Smith   rk->b1[4] = 0.0;
209e4dd521cSBarry Smith 
210e4dd521cSBarry Smith   rk->b2[0] = 1.0/6.0;
211e4dd521cSBarry Smith   rk->b2[1] = 0.0;
212e4dd521cSBarry Smith   rk->b2[2] = 0.0;
213e4dd521cSBarry Smith   rk->b2[3] = 2.0/3.0;
214e4dd521cSBarry Smith   rk->b2[4] = 1.0/6.0;
215e4dd521cSBarry Smith   */
216e4dd521cSBarry Smith 
217e4dd521cSBarry Smith   /* making b2 -> e=b1-b2 */
218e4dd521cSBarry Smith   /*
219e4dd521cSBarry Smith     for(i=0;i<rk->s;i++){
22026edb414Sasbjorn      rk->b2[i] = (rk->b1[i]) - (rk->b2[i]);
221e4dd521cSBarry Smith   }
222e4dd521cSBarry Smith   */
22326edb414Sasbjorn   rk->b2[0]=71.0/57600.0;
22426edb414Sasbjorn   rk->b2[1]=0.0;
22526edb414Sasbjorn   rk->b2[2]=-71.0/16695.0;
22626edb414Sasbjorn   rk->b2[3]=71.0/1920.0;
22726edb414Sasbjorn   rk->b2[4]=-17253.0/339200.0;
22826edb414Sasbjorn   rk->b2[5]=22.0/525.0;
22926edb414Sasbjorn   rk->b2[6]=-1.0/40.0;
23026edb414Sasbjorn 
231e4dd521cSBarry Smith   /* initializing vectors */
232e4dd521cSBarry Smith   ierr = VecDuplicate(ts->vec_sol,&rk->y1);CHKERRQ(ierr);
233e4dd521cSBarry Smith   ierr = VecDuplicate(ts->vec_sol,&rk->y2);CHKERRQ(ierr);
234e4dd521cSBarry Smith   ierr = VecDuplicate(rk->y1,&rk->tmp);CHKERRQ(ierr);
235e4dd521cSBarry Smith   ierr = VecDuplicate(rk->y1,&rk->tmp_y);CHKERRQ(ierr);
236e4dd521cSBarry Smith   ierr = VecDuplicateVecs(rk->y1,rk->s,&rk->k);CHKERRQ(ierr);
237e4dd521cSBarry Smith 
238e4dd521cSBarry Smith   PetscFunctionReturn(0);
239e4dd521cSBarry Smith }
240e4dd521cSBarry Smith 
241db046809SBarry Smith /*------------------------------------------------------------*/
242db046809SBarry Smith #undef __FUNCT__
2435f70b478SJed Brown #define __FUNCT__ "TSRKqs"
2445f70b478SJed Brown PetscErrorCode TSRKqs(TS ts,PetscReal t,PetscReal h)
245db046809SBarry Smith {
2465f70b478SJed Brown   TS_RK          *rk = (TS_RK*)ts->data;
2476849ba73SBarry Smith   PetscErrorCode ierr;
248a7cc72afSBarry Smith   PetscInt       j,l;
249db046809SBarry Smith   PetscReal      tmp_t=t;
250b05257ddSBarry Smith   PetscScalar    hh=h;
251db046809SBarry Smith 
252db046809SBarry Smith   PetscFunctionBegin;
253db046809SBarry Smith   /* k[0]=0  */
254b05257ddSBarry Smith   ierr = VecSet(rk->k[0],0.0);CHKERRQ(ierr);
255db046809SBarry Smith 
256db046809SBarry Smith   /* k[0] = derivs(t,y1) */
257db046809SBarry Smith   ierr = TSComputeRHSFunction(ts,t,rk->y1,rk->k[0]);CHKERRQ(ierr);
258db046809SBarry Smith   /* looping over runge-kutta variables */
259db046809SBarry Smith   /* building the k - array of vectors */
260db046809SBarry Smith   for(j = 1 ; j < rk->s ; j++){
261db046809SBarry Smith 
262db046809SBarry Smith      /* rk->tmp = 0 */
263b05257ddSBarry Smith      ierr = VecSet(rk->tmp,0.0);CHKERRQ(ierr);
264db046809SBarry Smith 
265db046809SBarry Smith      for(l=0;l<j;l++){
266db046809SBarry Smith         /* tmp += a(j,l)*k[l] */
2672dcb1b2aSMatthew Knepley        ierr = VecAXPY(rk->tmp,rk->a[j][l],rk->k[l]);CHKERRQ(ierr);
268db046809SBarry Smith      }
269db046809SBarry Smith 
270db046809SBarry Smith      /* ierr = VecView(rk->tmp,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */
271db046809SBarry Smith 
272db046809SBarry Smith      /* k[j] = derivs(t+c(j)*h,y1+h*tmp,k(j)) */
273db046809SBarry Smith      /* I need the following helpers:
274db046809SBarry Smith         PetscScalar  tmp_t=t+c(j)*h
275db046809SBarry Smith         Vec          tmp_y=h*tmp+y1
276db046809SBarry Smith      */
277db046809SBarry Smith 
278db046809SBarry Smith      tmp_t = t + rk->c[j] * h;
279db046809SBarry Smith 
280db046809SBarry Smith      /* tmp_y = h * tmp + y1 */
2812dcb1b2aSMatthew Knepley      ierr = VecWAXPY(rk->tmp_y,hh,rk->tmp,rk->y1);CHKERRQ(ierr);
282db046809SBarry Smith 
283db046809SBarry Smith      /* rk->k[j]=0 */
284b05257ddSBarry Smith      ierr = VecSet(rk->k[j],0.0);CHKERRQ(ierr);
285db046809SBarry Smith      ierr = TSComputeRHSFunction(ts,tmp_t,rk->tmp_y,rk->k[j]);CHKERRQ(ierr);
286db046809SBarry Smith   }
287db046809SBarry Smith 
288db046809SBarry Smith   /* tmp=0 and tmp_y=0 */
289b05257ddSBarry Smith   ierr = VecSet(rk->tmp,0.0);CHKERRQ(ierr);
290b05257ddSBarry Smith   ierr = VecSet(rk->tmp_y,0.0);CHKERRQ(ierr);
291db046809SBarry Smith 
292db046809SBarry Smith   for(j = 0 ; j < rk->s ; j++){
293db046809SBarry Smith      /* tmp=b1[j]*k[j]+tmp  */
2942dcb1b2aSMatthew Knepley     ierr = VecAXPY(rk->tmp,rk->b1[j],rk->k[j]);CHKERRQ(ierr);
295db046809SBarry Smith      /* tmp_y=b2[j]*k[j]+tmp_y */
2962dcb1b2aSMatthew Knepley     ierr = VecAXPY(rk->tmp_y,rk->b2[j],rk->k[j]);CHKERRQ(ierr);
297db046809SBarry Smith   }
298db046809SBarry Smith 
299db046809SBarry Smith   /* y2 = hh * tmp_y */
300b05257ddSBarry Smith   ierr = VecSet(rk->y2,0.0);CHKERRQ(ierr);
3012dcb1b2aSMatthew Knepley   ierr = VecAXPY(rk->y2,hh,rk->tmp_y);CHKERRQ(ierr);
302db046809SBarry Smith   /* y1 = hh*tmp + y1 */
3032dcb1b2aSMatthew Knepley   ierr = VecAXPY(rk->y1,hh,rk->tmp);CHKERRQ(ierr);
304db046809SBarry Smith   /* Finding difference between y1 and y2 */
305db046809SBarry Smith   PetscFunctionReturn(0);
306db046809SBarry Smith }
307db046809SBarry Smith 
308e4dd521cSBarry Smith #undef __FUNCT__
309*193ac0bcSJed Brown #define __FUNCT__ "TSSolve_RK"
310*193ac0bcSJed Brown static PetscErrorCode TSSolve_RK(TS ts)
311e4dd521cSBarry Smith {
3125f70b478SJed Brown   TS_RK          *rk = (TS_RK*)ts->data;
313b0dd9724SMatthew Knepley   PetscReal      norm=0.0,dt_fac=0.0,fac = 0.0/*,ttmp=0.0*/;
314186e87acSLisandro Dalcin   PetscInt       i;
315186e87acSLisandro Dalcin   PetscErrorCode ierr;
316e4dd521cSBarry Smith 
317e4dd521cSBarry Smith   PetscFunctionBegin;
318186e87acSLisandro Dalcin   ierr = VecCopy(ts->vec_sol,rk->y1);CHKERRQ(ierr);
319186e87acSLisandro Dalcin 
320e4dd521cSBarry Smith   /* while loop to get from start to stop */
321186e87acSLisandro Dalcin   for (i = 0; i < ts->max_steps; i++) {
3223f2090d5SJed Brown     ierr = TSPreStep(ts);CHKERRQ(ierr); /* Note that this is called once per STEP, not once per STAGE. */
323186e87acSLisandro Dalcin 
324e4dd521cSBarry Smith    /* calling rkqs */
325e4dd521cSBarry Smith      /*
326e4dd521cSBarry Smith        -- input
327e4dd521cSBarry Smith        ts        - pointer to ts
328e4dd521cSBarry Smith        ts->ptime - current time
329b05257ddSBarry Smith        ts->time_step        - try this timestep
330e4dd521cSBarry Smith        y1        - solution for this step
331e4dd521cSBarry Smith 
332e4dd521cSBarry Smith        --output
333e4dd521cSBarry Smith        y1        - suggested solution
334e4dd521cSBarry Smith        y2        - check solution (runge - kutta second permutation)
335e4dd521cSBarry Smith      */
3365f70b478SJed Brown      ierr = TSRKqs(ts,ts->ptime,ts->time_step);CHKERRQ(ierr);
337e3caeda6SBarry Smith      /* counting steps */
338e3caeda6SBarry Smith      ts->steps++;
339e4dd521cSBarry Smith    /* checking for maxerror */
340e4dd521cSBarry Smith      /* comparing difference to maxerror */
341e4dd521cSBarry Smith      ierr = VecNorm(rk->y2,NORM_2,&norm);CHKERRQ(ierr);
342e4dd521cSBarry Smith      /* modifying maxerror to satisfy this timestep */
343b05257ddSBarry Smith      rk->maxerror = rk->ferror * ts->time_step;
344b05257ddSBarry Smith      /* ierr = PetscPrintf(PETSC_COMM_WORLD,"norm err: %f maxerror: %f dt: %f",norm,rk->maxerror,ts->time_step);CHKERRQ(ierr); */
345e4dd521cSBarry Smith 
346e4dd521cSBarry Smith    /* handling ok and not ok */
347e4dd521cSBarry Smith      if (norm < rk->maxerror){
348e4dd521cSBarry Smith         /* if ok: */
349e4dd521cSBarry Smith         ierr=VecCopy(rk->y1,ts->vec_sol);CHKERRQ(ierr); /* saves the suggested solution to current solution */
350b05257ddSBarry Smith         ts->ptime += ts->time_step; /* storing the new current time */
351e4dd521cSBarry Smith         rk->nok++;
352e4dd521cSBarry Smith         fac=5.0;
353e4dd521cSBarry Smith         /* trying to save the vector */
3543f2090d5SJed Brown         ierr = TSPostStep(ts);CHKERRQ(ierr);
355e4dd521cSBarry Smith         ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
356e3caeda6SBarry Smith         if (ts->ptime >= ts->max_time) break;
357e4dd521cSBarry Smith      } else{
358e4dd521cSBarry Smith         /* if not OK */
359e4dd521cSBarry Smith         rk->nnok++;
360e4dd521cSBarry Smith         fac=1.0;
361e4dd521cSBarry Smith         ierr=VecCopy(ts->vec_sol,rk->y1);CHKERRQ(ierr);  /* restores old solution */
362e4dd521cSBarry Smith      }
363e4dd521cSBarry Smith 
364e4dd521cSBarry Smith      /*Computing next stepsize. See page 167 in Solving ODE 1
365e4dd521cSBarry Smith       *
366e4dd521cSBarry Smith       * h_new = h * min( facmax , max( facmin , fac * (tol/err)^(1/(p+1)) ) )
367e4dd521cSBarry Smith       * facmax set above
368e4dd521cSBarry Smith       * facmin
369e4dd521cSBarry Smith       */
370e4dd521cSBarry Smith      dt_fac = exp(log((rk->maxerror) / norm) / ((rk->p) + 1) ) * 0.9 ;
371e4dd521cSBarry Smith 
372e4dd521cSBarry Smith      if (dt_fac > fac){
3732cdf8120Sasbjorn         /*ierr = PetscPrintf(PETSC_COMM_WORLD,"changing fac %f\n",fac);*/
374e4dd521cSBarry Smith         dt_fac = fac;
375e4dd521cSBarry Smith      }
376e4dd521cSBarry Smith 
377b05257ddSBarry Smith      /* computing new ts->time_step */
378b05257ddSBarry Smith      ts->time_step = ts->time_step * dt_fac;
379e4dd521cSBarry Smith 
380b05257ddSBarry Smith      if (ts->ptime+ts->time_step > ts->max_time){
381b05257ddSBarry Smith         ts->time_step = ts->max_time - ts->ptime;
382e4dd521cSBarry Smith      }
383e4dd521cSBarry Smith 
384b05257ddSBarry Smith      if (ts->time_step < 1e-14){
385b05257ddSBarry Smith         ierr = PetscPrintf(PETSC_COMM_WORLD,"Very small steps: %f\n",ts->time_step);CHKERRQ(ierr);
386b05257ddSBarry Smith         ts->time_step = 1e-14;
387e4dd521cSBarry Smith      }
388e4dd521cSBarry Smith 
389e4dd521cSBarry Smith      /* trying to purify h */
390e4dd521cSBarry Smith      /* (did not give any visible result) */
391b05257ddSBarry Smith      /* ttmp = ts->ptime + ts->time_step;
392b05257ddSBarry Smith         ts->time_step = ttmp - ts->ptime; */
393e4dd521cSBarry Smith 
394e4dd521cSBarry Smith   }
395e4dd521cSBarry Smith 
396e4dd521cSBarry Smith   ierr=VecCopy(rk->y1,ts->vec_sol);CHKERRQ(ierr);
397e4dd521cSBarry Smith   PetscFunctionReturn(0);
398e4dd521cSBarry Smith }
399e4dd521cSBarry Smith 
400e4dd521cSBarry Smith /*------------------------------------------------------------*/
401e4dd521cSBarry Smith #undef __FUNCT__
402277b19d0SLisandro Dalcin #define __FUNCT__ "TSReset_RK"
403277b19d0SLisandro Dalcin static PetscErrorCode TSReset_RK(TS ts)
404e4dd521cSBarry Smith {
4055f70b478SJed Brown   TS_RK          *rk = (TS_RK*)ts->data;
4066849ba73SBarry Smith   PetscErrorCode ierr;
407e4dd521cSBarry Smith 
408e4dd521cSBarry Smith   PetscFunctionBegin;
4096bf464f9SBarry Smith   ierr = VecDestroy(&rk->y1);CHKERRQ(ierr);
4106bf464f9SBarry Smith   ierr = VecDestroy(&rk->y2);CHKERRQ(ierr);
4116bf464f9SBarry Smith   ierr = VecDestroy(&rk->tmp);CHKERRQ(ierr);
4126bf464f9SBarry Smith   ierr = VecDestroy(&rk->tmp_y);CHKERRQ(ierr);
413277b19d0SLisandro Dalcin   if (rk->k) {ierr = VecDestroyVecs(rk->s,&rk->k);CHKERRQ(ierr);}
414277b19d0SLisandro Dalcin   PetscFunctionReturn(0);
415e4dd521cSBarry Smith }
416277b19d0SLisandro Dalcin 
417277b19d0SLisandro Dalcin #undef __FUNCT__
418277b19d0SLisandro Dalcin #define __FUNCT__ "TSDestroy_RK"
419277b19d0SLisandro Dalcin static PetscErrorCode TSDestroy_RK(TS ts)
420277b19d0SLisandro Dalcin {
421277b19d0SLisandro Dalcin   PetscErrorCode ierr;
422277b19d0SLisandro Dalcin 
423277b19d0SLisandro Dalcin   PetscFunctionBegin;
424277b19d0SLisandro Dalcin   ierr = TSReset_RK(ts);CHKERRQ(ierr);
425277b19d0SLisandro Dalcin   ierr = PetscFree(ts->data);CHKERRQ(ierr);
426e4dd521cSBarry Smith   PetscFunctionReturn(0);
427e4dd521cSBarry Smith }
428e4dd521cSBarry Smith /*------------------------------------------------------------*/
429e4dd521cSBarry Smith 
430e4dd521cSBarry Smith #undef __FUNCT__
4315f70b478SJed Brown #define __FUNCT__ "TSSetFromOptions_RK"
4325f70b478SJed Brown static PetscErrorCode TSSetFromOptions_RK(TS ts)
433e4dd521cSBarry Smith {
4345f70b478SJed Brown   TS_RK          *rk = (TS_RK*)ts->data;
435dfbe8321SBarry Smith   PetscErrorCode ierr;
436262ff7bbSBarry Smith 
437e4dd521cSBarry Smith   PetscFunctionBegin;
438262ff7bbSBarry Smith   ierr = PetscOptionsHead("RK ODE solver options");CHKERRQ(ierr);
439262ff7bbSBarry Smith     ierr = PetscOptionsReal("-ts_rk_tol","Tolerance for convergence","TSRKSetTolerance",rk->tolerance,&rk->tolerance,PETSC_NULL);CHKERRQ(ierr);
440262ff7bbSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
441e4dd521cSBarry Smith   PetscFunctionReturn(0);
442e4dd521cSBarry Smith }
443e4dd521cSBarry Smith 
444e4dd521cSBarry Smith #undef __FUNCT__
4455f70b478SJed Brown #define __FUNCT__ "TSView_RK"
4465f70b478SJed Brown static PetscErrorCode TSView_RK(TS ts,PetscViewer viewer)
447e4dd521cSBarry Smith {
4485f70b478SJed Brown    TS_RK          *rk = (TS_RK*)ts->data;
449dfbe8321SBarry Smith    PetscErrorCode ierr;
4502cdf8120Sasbjorn 
451e4dd521cSBarry Smith    PetscFunctionBegin;
45277431f27SBarry Smith    ierr = PetscPrintf(PETSC_COMM_WORLD,"  number of ok steps: %D\n",rk->nok);CHKERRQ(ierr);
45377431f27SBarry Smith    ierr = PetscPrintf(PETSC_COMM_WORLD,"  number of rejected steps: %D\n",rk->nnok);CHKERRQ(ierr);
454e4dd521cSBarry Smith    PetscFunctionReturn(0);
455e4dd521cSBarry Smith }
456e4dd521cSBarry Smith 
457e4dd521cSBarry Smith /* ------------------------------------------------------------ */
458ebe3b25bSBarry Smith /*MC
45996f5712cSJed Brown       TSRK - ODE solver using the explicit Runge-Kutta methods
460ebe3b25bSBarry Smith 
461ebe3b25bSBarry Smith    Options Database:
462ebe3b25bSBarry Smith .  -ts_rk_tol <tol> Tolerance for convergence
463ebe3b25bSBarry Smith 
464ebe3b25bSBarry Smith   Contributed by: Asbjorn Hoiland Aarrestad, asbjorn@aarrestad.com, http://asbjorn.aarrestad.com/
465ebe3b25bSBarry Smith 
466d41222bbSBarry Smith   Level: beginner
467d41222bbSBarry Smith 
4689596e0b4SJed Brown .seealso:  TSCreate(), TS, TSSetType(), TSEULER, TSRKSetTolerance()
469ebe3b25bSBarry Smith 
470ebe3b25bSBarry Smith M*/
471ebe3b25bSBarry Smith 
472e4dd521cSBarry Smith EXTERN_C_BEGIN
473e4dd521cSBarry Smith #undef __FUNCT__
4745f70b478SJed Brown #define __FUNCT__ "TSCreate_RK"
4757087cfbeSBarry Smith PetscErrorCode  TSCreate_RK(TS ts)
476e4dd521cSBarry Smith {
4775f70b478SJed Brown   TS_RK          *rk;
478dfbe8321SBarry Smith   PetscErrorCode ierr;
479e4dd521cSBarry Smith 
480e4dd521cSBarry Smith   PetscFunctionBegin;
4815f70b478SJed Brown   ts->ops->setup           = TSSetUp_RK;
482*193ac0bcSJed Brown   ts->ops->solve           = TSSolve_RK;
4835f70b478SJed Brown   ts->ops->destroy         = TSDestroy_RK;
4845f70b478SJed Brown   ts->ops->setfromoptions  = TSSetFromOptions_RK;
4855f70b478SJed Brown   ts->ops->view            = TSView_RK;
486e4dd521cSBarry Smith 
4875f70b478SJed Brown   ierr = PetscNewLog(ts,TS_RK,&rk);CHKERRQ(ierr);
488e4dd521cSBarry Smith   ts->data = (void*)rk;
489e4dd521cSBarry Smith 
490a7cc72afSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRKSetTolerance_C","TSRKSetTolerance_RK",TSRKSetTolerance_RK);CHKERRQ(ierr);
491262ff7bbSBarry Smith 
492e4dd521cSBarry Smith   PetscFunctionReturn(0);
493e4dd521cSBarry Smith }
494e4dd521cSBarry Smith EXTERN_C_END
495