2 #define MAX(a,b) ( ((a) >= (b)) ?(a):(b) )
3 #define MIN(b,c) ( ((b) < (c)) ?(b):(c) )
4 #define ABS(x) ( ((x) >= 0 ) ?(x):(-x) )
5 #define SQRT(d) ( pow((d),0.5) )
6 #define SIGN(x) ( ((x) >= 0 ) ?[0]:(-1) )
8 /*~~> Numerical constants */
9 #define ZERO (KPP_REAL)0.0
10 #define ONE (KPP_REAL)1.0
11 #define HALF (KPP_REAL)0.5
12 #define DeltaMin (KPP_REAL)1.0e-6
14 /*~~~> Collect statistics: global variables */
15 int Nfun
,Njac
,Nstp
,Nacc
,Nrej
,Ndec
,Nsol
,Nsng
;
18 /*~~~> Function headers */
19 void FunTemplate(KPP_REAL
, KPP_REAL
[], KPP_REAL
[]);
20 void JacTemplate(KPP_REAL
, KPP_REAL
[], KPP_REAL
[]) ;
21 int Rosenbrock(KPP_REAL Y
[], KPP_REAL Tstart
, KPP_REAL Tend
,
22 KPP_REAL AbsTol
[], KPP_REAL RelTol
[],
23 void (*ode_Fun
)(KPP_REAL
, KPP_REAL
[], KPP_REAL
[]),
24 void (*ode_Jac
)(KPP_REAL
, KPP_REAL
[], KPP_REAL
[]),
25 KPP_REAL RPAR
[], int IPAR
[]);
26 int RosenbrockIntegrator(
27 KPP_REAL Y
[], KPP_REAL Tstart
, KPP_REAL Tend
,
28 KPP_REAL AbsTol
[], KPP_REAL RelTol
[],
29 void (*ode_Fun
)(KPP_REAL
, KPP_REAL
[], KPP_REAL
[]),
30 void (*ode_Jac
)(KPP_REAL
, KPP_REAL
[], KPP_REAL
[]),
32 KPP_REAL ros_M
[], KPP_REAL ros_E
[],
33 KPP_REAL ros_A
[], KPP_REAL ros_C
[],
34 KPP_REAL ros_Alpha
[],KPP_REAL ros_Gamma
[],
35 KPP_REAL ros_ELO
, char ros_NewF
[],
36 char Autonomous
, char VectorTol
, int Max_no_steps
,
37 KPP_REAL Roundoff
, KPP_REAL Hmin
, KPP_REAL Hmax
, KPP_REAL Hstart
,
38 KPP_REAL FacMin
, KPP_REAL FacMax
, KPP_REAL FacRej
, KPP_REAL FacSafe
,
39 KPP_REAL
*Texit
, KPP_REAL
*Hexit
);
40 char ros_PrepareMatrix (
42 int Direction
, KPP_REAL gam
, KPP_REAL Jac0
[],
43 KPP_REAL Ghimj
[], int Pivot
[] );
44 KPP_REAL
ros_ErrorNorm (
45 KPP_REAL Y
[], KPP_REAL Ynew
[], KPP_REAL Yerr
[],
46 KPP_REAL AbsTol
[], KPP_REAL RelTol
[],
48 int ros_ErrorMsg(int Code
, KPP_REAL T
, KPP_REAL H
);
49 void ros_FunTimeDerivative (
50 KPP_REAL T
, KPP_REAL Roundoff
,
51 KPP_REAL Y
[], KPP_REAL Fcn0
[],
52 void ode_Fun(KPP_REAL
, KPP_REAL
[], KPP_REAL
[]),
54 void Fun( KPP_REAL Y
[], KPP_REAL FIX
[], KPP_REAL RCONST
[], KPP_REAL Ydot
[] );
55 void Jac_SP( KPP_REAL Y
[], KPP_REAL FIX
[], KPP_REAL RCONST
[], KPP_REAL Ydot
[] );
56 void FunTemplate( KPP_REAL T
, KPP_REAL Y
[], KPP_REAL Ydot
[] );
57 void JacTemplate( KPP_REAL T
, KPP_REAL Y
[], KPP_REAL Ydot
[] );
58 void DecompTemplate( KPP_REAL A
[], int Pivot
[], int* ising
);
59 void SolveTemplate( KPP_REAL A
[], int Pivot
[], KPP_REAL b
[] );
60 void WCOPY(int N
, KPP_REAL X
[], int incX
, KPP_REAL Y
[], int incY
);
61 void WAXPY(int N
, KPP_REAL Alpha
, KPP_REAL X
[], int incX
, KPP_REAL Y
[], int incY
);
62 void WSCAL(int N
, KPP_REAL Alpha
, KPP_REAL X
[], int incX
);
63 KPP_REAL
WLAMCH( char C
);
64 void Ros2 ( int *ros_S
, KPP_REAL ros_A
[], KPP_REAL ros_C
[],
65 KPP_REAL ros_M
[], KPP_REAL ros_E
[],
66 KPP_REAL ros_Alpha
[], KPP_REAL ros_Gamma
[],
67 char ros_NewF
[], KPP_REAL
*ros_ELO
, char* ros_Name
);
68 void Ros3 ( int *ros_S
, KPP_REAL ros_A
[], KPP_REAL ros_C
[],
69 KPP_REAL ros_M
[], KPP_REAL ros_E
[],
70 KPP_REAL ros_Alpha
[], KPP_REAL ros_Gamma
[],
71 char ros_NewF
[], KPP_REAL
*ros_ELO
, char* ros_Name
);
72 void Ros4 ( int *ros_S
, KPP_REAL ros_A
[], KPP_REAL ros_C
[],
73 KPP_REAL ros_M
[], KPP_REAL ros_E
[],
74 KPP_REAL ros_Alpha
[], KPP_REAL ros_Gamma
[],
75 char ros_NewF
[], KPP_REAL
*ros_ELO
, char* ros_Name
);
76 void Rodas3 ( int *ros_S
, KPP_REAL ros_A
[], KPP_REAL ros_C
[],
77 KPP_REAL ros_M
[], KPP_REAL ros_E
[],
78 KPP_REAL ros_Alpha
[], KPP_REAL ros_Gamma
[],
79 char ros_NewF
[], KPP_REAL
*ros_ELO
, char* ros_Name
);
80 void Rodas4 ( int *ros_S
, KPP_REAL ros_A
[], KPP_REAL ros_C
[],
81 KPP_REAL ros_M
[], KPP_REAL ros_E
[],
82 KPP_REAL ros_Alpha
[], KPP_REAL ros_Gamma
[],
83 char ros_NewF
[], KPP_REAL
*ros_ELO
, char* ros_Name
);
84 int KppDecomp( KPP_REAL A
[] );
85 void KppSolve ( KPP_REAL A
[], KPP_REAL b
[] );
89 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
90 void INTEGRATE( KPP_REAL TIN
, KPP_REAL TOUT
)
91 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
93 static KPP_REAL RPAR
[20];
94 static int i
, IERR
, IPAR
[20];
95 static int Ns
=0, Na
=0, Nr
=0, Ng
=0;
97 for ( i
= 0; i
< 20; i
++ ) {
103 IPAR
[0] = 0; /* non-autonomous */
104 IPAR
[1] = 1; /* vector tolerances */
105 RPAR
[2] = STEPMIN
; /* starting step */
106 IPAR
[3] = 5; /* choice of the method */
108 IERR
= Rosenbrock(VAR
, TIN
, TOUT
,
110 &FunTemplate
, &JacTemplate
,
118 printf("\n Step=%d Acc=%d Rej=%d Singular=%d\n",
123 printf("\n Rosenbrock: Unsucessful step at T=%g: IERR=%d\n",
126 TIN
= RPAR
[10]; /* Exit time */
127 STEPMIN
= RPAR
[11]; /* Last step */
132 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
133 int Rosenbrock(KPP_REAL Y
[], KPP_REAL Tstart
, KPP_REAL Tend
,
134 KPP_REAL AbsTol
[], KPP_REAL RelTol
[],
135 void (*ode_Fun
)(KPP_REAL
, KPP_REAL
[], KPP_REAL
[]),
136 void (*ode_Jac
)(KPP_REAL
, KPP_REAL
[], KPP_REAL
[]),
137 KPP_REAL RPAR
[], int IPAR
[])
138 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
140 Solves the system y'=F(t,y) using a Rosenbrock method defined by:
142 G = 1/(H*gamma[0]) - ode_Jac(t0,Y0)
143 T_i = t0 + Alpha(i)*H
144 Y_i = Y0 + \sum_{j=1}^{i-1} A(i,j)*K_j
145 G * K_i = ode_Fun( T_i, Y_i ) + \sum_{j=1}^S C(i,j)/H * K_j +
146 gamma(i)*dF/dT(t0, Y0)
147 Y1 = Y0 + \sum_{j=1}^S M(j)*K_j
149 For details on Rosenbrock methods and their implementation consult:
150 E. Hairer and G. Wanner
151 "Solving ODEs II. Stiff and differential-algebraic problems".
152 Springer series in computational mathematics, Springer-Verlag, 1996.
153 The codes contained in the book inspired this implementation.
155 (C) Adrian Sandu, August 2004
156 Virginia Polytechnic Institute and State University
157 Contact: sandu@cs.vt.edu
158 This implementation is part of KPP - the Kinetic PreProcessor
159 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
161 *~~~> INPUT ARGUMENTS:
163 - Y(NVAR) = vector of initial conditions (at T=Tstart)
164 - [Tstart,Tend] = time range of integration
165 (if Tstart>Tend the integration is performed backwards in time)
166 - RelTol, AbsTol = user precribed accuracy
167 - void ode_Fun( T, Y, Ydot ) = ODE function,
168 returns Ydot = Y' = F(T,Y)
169 - void ode_Fun( T, Y, Ydot ) = Jacobian of the ODE function,
171 - IPAR(1:10) = int inputs parameters
172 - RPAR(1:10) = real inputs parameters
173 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
175 *~~~> OUTPUT ARGUMENTS:
177 - Y(NVAR) -> vector of final states (at T->Tend)
178 - IPAR(11:20) -> int output parameters
179 - RPAR(11:20) -> real output parameters
180 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
182 *~~~> RETURN VALUE (int):
184 - IERR -> job status upon return
185 - succes (positive value) or failure (negative value) -
187 = -1 : Improper value for maximal no of steps
188 = -2 : Selected Rosenbrock method not implemented
189 = -3 : Hmin/Hmax/Hstart must be positive
190 = -4 : FacMin/FacMax/FacRej must be positive
191 = -5 : Improper tolerance values
192 = -6 : No of steps exceeds maximum bound
193 = -7 : Step size too small
194 = -8 : Matrix is repeatedly singular
195 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
197 *~~~> INPUT PARAMETERS:
199 Note: For input parameters equal to zero the default values of the
200 corresponding variables are used.
202 IPAR[0] = 1: F = F(y) Independent of T (AUTONOMOUS)
203 = 0: F = F(t,y) Depends on T (NON-AUTONOMOUS)
204 IPAR[1] = 0: AbsTol, RelTol are NVAR-dimensional vectors
205 = 1: AbsTol, RelTol are scalars
206 IPAR[2] -> maximum number of integration steps
207 For IPAR[2]=0) the default value of 100000 is used
209 IPAR[3] -> selection of a particular Rosenbrock method
210 = 0 : default method is Rodas3
214 = 4 : method is Rodas3
215 = 5: method is Rodas4
217 RPAR[0] -> Hmin, lower bound for the integration step size
218 It is strongly recommended to keep Hmin = ZERO
219 RPAR[1] -> Hmax, upper bound for the integration step size
220 RPAR[2] -> Hstart, starting value for the integration step size
222 RPAR[3] -> FacMin, lower bound on step decrease factor (default=0.2)
223 RPAR[4] -> FacMin,upper bound on step increase factor (default=6)
224 RPAR[5] -> FacRej, step decrease factor after multiple rejections
226 RPAR[6] -> FacSafe, by which the new step is slightly smaller
227 than the predicted value (default=0.9)
228 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
230 *~~~> OUTPUT PARAMETERS:
232 Note: each call to Rosenbrock adds the corrent no. of fcn calls
233 to previous value of IPAR[10], and similar for the other params.
234 Set IPAR(11:20) = 0 before call to avoid this accumulation.
236 IPAR[10] = No. of function calls
237 IPAR[11] = No. of jacobian calls
238 IPAR[12] = No. of steps
239 IPAR[13] = No. of accepted steps
240 IPAR[14] = No. of rejected steps (except at the beginning)
241 IPAR[15] = No. of LU decompositions
242 IPAR[16] = No. of forward/backward substitutions
243 IPAR[17] = No. of singular matrix decompositions
245 RPAR[10] -> Texit, the time corresponding to the
246 computed Y upon return
247 RPAR[11] -> Hexit, last accepted step before exit
248 For multiple restarts, use Hexit as Hstart in the following run
249 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
252 /*~~~> The method parameters */
255 KPP_REAL ros_M
[Smax
], ros_E
[Smax
];
256 KPP_REAL ros_A
[Smax
*(Smax
-1)/2], ros_C
[Smax
*(Smax
-1)/2];
257 KPP_REAL ros_Alpha
[Smax
], ros_Gamma
[Smax
], ros_ELO
;
258 char ros_NewF
[Smax
], ros_Name
[12];
259 /*~~~> Local variables */
260 int Max_no_steps
, IERR
, i
, UplimTol
;
261 char Autonomous
, VectorTol
;
262 KPP_REAL Roundoff
,FacMin
,FacMax
,FacRej
,FacSafe
;
263 KPP_REAL Hmin
, Hmax
, Hstart
, Hexit
, Texit
;
264 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
266 /*~~~> Initialize statistics */
276 /*~~~> Autonomous or time dependent ODE. Default is time dependent. */
277 Autonomous
= !(IPAR
[0] == 0);
279 /*~~~> For Scalar tolerances (IPAR[1] != 0) the code uses AbsTol[0] and RelTol[0]
280 ! For Vector tolerances (IPAR[1] == 0) the code uses AbsTol(1:NVAR) and RelTol(1:NVAR) */
282 VectorTol
= 1; UplimTol
= KPP_NVAR
;
284 VectorTol
= 0; UplimTol
= 1;
287 /*~~~> The maximum number of steps admitted */
289 Max_no_steps
= 100000;
291 Max_no_steps
=IPAR
[2];
292 if (Max_no_steps
< 0) {
293 printf("\n User-selected max no. of steps: IPAR[2]=%d\n",IPAR
[2]);
294 return ros_ErrorMsg(-1,Tstart
,ZERO
);
297 /*~~~> The particular Rosenbrock method chosen */
302 if ( (IPAR
[3] < 1) || (IPAR
[3] > 5) ){
303 printf("\n User-selected Rosenbrock method: IPAR[3]=%d\n",IPAR
[3]);
304 return ros_ErrorMsg(-2,Tstart
,ZERO
);
307 /*~~~> Unit Roundoff (1+Roundoff>1) */
308 Roundoff
= WLAMCH('E');
310 /*~~~> Lower bound on the step size: (positive value) */
312 if (RPAR
[0] < ZERO
) {
313 printf("\n User-selected Hmin: RPAR[0]=%e\n", RPAR
[0]);
314 return ros_ErrorMsg(-3,Tstart
,ZERO
);
316 /*~~~> Upper bound on the step size: (positive value) */
318 Hmax
= ABS(Tend
-Tstart
);
320 Hmax
= MIN(ABS(RPAR
[1]),ABS(Tend
-Tstart
));
321 if (RPAR
[1] < ZERO
) {
322 printf("\n User-selected Hmax: RPAR[1]=%e\n", RPAR
[1]);
323 return ros_ErrorMsg(-3,Tstart
,ZERO
);
325 /*~~~> Starting step size: (positive value) */
327 Hstart
= MAX(Hmin
,DeltaMin
);
329 Hstart
= MIN(ABS(RPAR
[2]),ABS(Tend
-Tstart
));
330 if (RPAR
[2] < ZERO
) {
331 printf("\n User-selected Hstart: RPAR[2]=%e\n", RPAR
[2]);
332 return ros_ErrorMsg(-3,Tstart
,ZERO
);
334 /*~~~> Step size can be changed s.t. FacMin < Hnew/Hexit < FacMax */
336 FacMin
= (KPP_REAL
)0.2;
339 if (RPAR
[3] < ZERO
) {
340 printf("\n User-selected FacMin: RPAR[3]=%e\n", RPAR
[3]);
341 return ros_ErrorMsg(-4,Tstart
,ZERO
);
344 FacMax
= (KPP_REAL
)6.0;
347 if (RPAR
[4] < ZERO
) {
348 printf("\n User-selected FacMax: RPAR[4]=%e\n", RPAR
[4]);
349 return ros_ErrorMsg(-4,Tstart
,ZERO
);
351 /*~~~> FacRej: Factor to decrease step after 2 succesive rejections */
353 FacRej
= (KPP_REAL
)0.1;
356 if (RPAR
[5] < ZERO
) {
357 printf("\n User-selected FacRej: RPAR[5]=%e\n", RPAR
[5]);
358 return ros_ErrorMsg(-4,Tstart
,ZERO
);
360 /*~~~> FacSafe: Safety Factor in the computation of new step size */
362 FacSafe
= (KPP_REAL
)0.9;
365 if (RPAR
[6] < ZERO
) {
366 printf("\n User-selected FacSafe: RPAR[6]=%e\n", RPAR
[6]);
367 return ros_ErrorMsg(-4,Tstart
,ZERO
);
369 /*~~~> Check if tolerances are reasonable */
370 for (i
= 0; i
< UplimTol
; i
++) {
371 if ( (AbsTol
[i
] <= ZERO
) || (RelTol
[i
] <= 10.0*Roundoff
)
372 || (RelTol
[i
] >= ONE
) ) {
373 printf("\n AbsTol[%d] = %e\n",i
,AbsTol
[i
]);
374 printf("\n RelTol[%d] = %e\n",i
,RelTol
[i
]);
375 return ros_ErrorMsg(-5,Tstart
,ZERO
);
380 /*~~~> Initialize the particular Rosenbrock method */
383 Ros2(&ros_S
, ros_A
, ros_C
, ros_M
, ros_E
,
384 ros_Alpha
, ros_Gamma
, ros_NewF
, &ros_ELO
, ros_Name
);
387 Ros3(&ros_S
, ros_A
, ros_C
, ros_M
, ros_E
,
388 ros_Alpha
, ros_Gamma
, ros_NewF
, &ros_ELO
, ros_Name
);
391 Ros4(&ros_S
, ros_A
, ros_C
, ros_M
, ros_E
,
392 ros_Alpha
, ros_Gamma
, ros_NewF
, &ros_ELO
, ros_Name
);
395 Rodas3(&ros_S
, ros_A
, ros_C
, ros_M
, ros_E
,
396 ros_Alpha
, ros_Gamma
, ros_NewF
, &ros_ELO
, ros_Name
);
399 Rodas4(&ros_S
, ros_A
, ros_C
, ros_M
, ros_E
,
400 ros_Alpha
, ros_Gamma
, ros_NewF
, &ros_ELO
, ros_Name
);
403 printf("\n Unknown Rosenbrock method: IPAR[3]= %d", Method
);
404 return ros_ErrorMsg(-2,Tstart
,ZERO
);
407 /*~~~> Rosenbrock method */
408 IERR
= RosenbrockIntegrator( Y
,Tstart
,Tend
,
411 /* Rosenbrock method coefficients */
412 ros_S
, ros_M
, ros_E
, ros_A
, ros_C
,
413 ros_Alpha
, ros_Gamma
, ros_ELO
, ros_NewF
,
414 /* Integration parameters */
415 Autonomous
, VectorTol
, Max_no_steps
,
416 Roundoff
, Hmin
, Hmax
, Hstart
,
417 FacMin
, FacMax
, FacRej
, FacSafe
,
418 /* Output parameters */
422 /*~~~> Collect run statistics */
431 /*~~~> Last T and H */
440 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
441 int RosenbrockIntegrator(
442 /*~~~> Input: the initial condition at Tstart; Output: the solution at T */
444 /*~~~> Input: integration interval */
445 KPP_REAL Tstart
, KPP_REAL Tend
,
446 /*~~~> Input: tolerances */
447 KPP_REAL AbsTol
[], KPP_REAL RelTol
[],
448 /*~~~> Input: ode function and its Jacobian */
449 void (*ode_Fun
)(KPP_REAL
, KPP_REAL
[], KPP_REAL
[]),
450 void (*ode_Jac
)(KPP_REAL
, KPP_REAL
[], KPP_REAL
[]) ,
451 /*~~~> Input: The Rosenbrock method parameters */
453 KPP_REAL ros_M
[], KPP_REAL ros_E
[],
454 KPP_REAL ros_A
[], KPP_REAL ros_C
[],
455 KPP_REAL ros_Alpha
[],KPP_REAL ros_Gamma
[],
456 KPP_REAL ros_ELO
, char ros_NewF
[],
457 /*~~~> Input: integration parameters */
458 char Autonomous
, char VectorTol
,
460 KPP_REAL Roundoff
, KPP_REAL Hmin
, KPP_REAL Hmax
, KPP_REAL Hstart
,
461 KPP_REAL FacMin
, KPP_REAL FacMax
, KPP_REAL FacRej
, KPP_REAL FacSafe
,
462 /*~~~> Output: time at which the solution is returned (T=Tend if success)
463 and last accepted step */
464 KPP_REAL
*Texit
, KPP_REAL
*Hexit
)
465 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
466 Template for the implementation of a generic Rosenbrock method
467 defined by ros_S (no of stages) and coefficients ros_{A,C,M,E,Alpha,Gamma}
469 returned value: IERR, indicator of success (if positive)
470 or failure (if negative)
471 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
473 KPP_REAL Ynew
[KPP_NVAR
], Fcn0
[KPP_NVAR
], Fcn
[KPP_NVAR
],
475 Jac0
[KPP_LU_NONZERO
], Ghimj
[KPP_LU_NONZERO
];
476 KPP_REAL K
[KPP_NVAR
*ros_S
];
477 KPP_REAL H
, T
, Hnew
, HC
, HG
, Fac
, Tau
;
478 KPP_REAL Err
, Yerr
[KPP_NVAR
];
479 int Pivot
[KPP_NVAR
], Direction
, ioffset
, j
, istage
;
480 char RejectLastH
, RejectMoreH
;
482 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
484 /*~~~> INITIAL PREPARATIONS */
487 H
= MIN(Hstart
,Hmax
);
488 if (ABS(H
) <= 10.0*Roundoff
)
491 if (Tend
>= Tstart
) {
497 RejectLastH
=0; RejectMoreH
=0;
499 /*~~~> Time loop begins below */
501 while ( ( (Direction
> 0) && ((T
-Tend
)+Roundoff
<= ZERO
) )
502 || ( (Direction
< 0) && ((Tend
-T
)+Roundoff
<= ZERO
) ) ) {
504 if ( Nstp
> Max_no_steps
) { /* Too many steps */
506 return ros_ErrorMsg(-6,T
,H
);
508 if ( ((T
+0.1*H
) == T
) || (H
<= Roundoff
) ) { /* Step size too small */
510 return ros_ErrorMsg(-7,T
,H
);
513 /*~~~> Limit H if necessary to avoid going beyond Tend */
515 H
= MIN(H
,ABS(Tend
-T
));
517 /*~~~> Compute the function at current time */
518 (*ode_Fun
)(T
,Y
,Fcn0
);
520 /*~~~> Compute the function derivative with respect to T */
522 ros_FunTimeDerivative ( T
, Roundoff
, Y
, Fcn0
, ode_Fun
, dFdT
);
524 /*~~~> Compute the Jacobian at current time */
525 (*ode_Jac
)(T
,Y
,Jac0
);
527 /*~~~> Repeat step calculation until current step accepted */
528 while (1) { /* WHILE STEP NOT ACCEPTED */
531 if( ros_PrepareMatrix( &H
, Direction
, ros_Gamma
[0],
532 Jac0
, Ghimj
, Pivot
) ) { /* More than 5 consecutive failed decompositions */
534 return ros_ErrorMsg(-8,T
,H
);
537 /*~~~> Compute the stages */
538 for (istage
= 1; istage
<= ros_S
; istage
++) {
540 /* Current istage offset. Current istage vector is K[ioffset:ioffset+KPP_NVAR-1] */
541 ioffset
= KPP_NVAR
*(istage
-1);
543 /* For the 1st istage the function has been computed previously */
545 WCOPY(KPP_NVAR
,Fcn0
,1,Fcn
,1);
546 else { /* istage>1 and a new function evaluation is needed at current istage */
547 if ( ros_NewF
[istage
-1] ) {
548 WCOPY(KPP_NVAR
,Y
,1,Ynew
,1);
549 for (j
= 1; j
<= istage
-1; j
++)
550 WAXPY(KPP_NVAR
,ros_A
[(istage
-1)*(istage
-2)/2+j
-1],
551 &K
[KPP_NVAR
*(j
-1)],1,Ynew
,1);
552 Tau
= T
+ ros_Alpha
[istage
-1]*Direction
*H
;
553 (*ode_Fun
)(Tau
,Ynew
,Fcn
);
554 } /*end if ros_NewF(istage)*/
555 } /* end if istage */
557 WCOPY(KPP_NVAR
,Fcn
,1,&K
[ioffset
],1);
558 for (j
= 1; j
<= istage
-1; j
++) {
559 HC
= ros_C
[(istage
-1)*(istage
-2)/2+j
-1]/(Direction
*H
);
560 WAXPY(KPP_NVAR
,HC
,&K
[KPP_NVAR
*(j
-1)],1,&K
[ioffset
],1);
563 if ((!Autonomous
) && (ros_Gamma
[istage
-1])) {
564 HG
= Direction
*H
*ros_Gamma
[istage
-1];
565 WAXPY(KPP_NVAR
,HG
,dFdT
,1,&K
[ioffset
],1);
566 } /* end if !Autonomous */
568 SolveTemplate(Ghimj
, Pivot
, &K
[ioffset
]);
573 /*~~~> Compute the new solution */
574 WCOPY(KPP_NVAR
,Y
,1,Ynew
,1);
575 for (j
=1; j
<=ros_S
; j
++)
576 WAXPY(KPP_NVAR
,ros_M
[j
-1],&K
[KPP_NVAR
*(j
-1)],1,Ynew
,1);
578 /*~~~> Compute the error estimation */
579 WSCAL(KPP_NVAR
,ZERO
,Yerr
,1);
580 for (j
=1; j
<=ros_S
; j
++)
581 WAXPY(KPP_NVAR
,ros_E
[j
-1],&K
[KPP_NVAR
*(j
-1)],1,Yerr
,1);
582 Err
= ros_ErrorNorm ( Y
, Ynew
, Yerr
, AbsTol
, RelTol
, VectorTol
);
584 /*~~~> New step size is bounded by FacMin <= Hnew/H <= FacMax */
585 Fac
= MIN(FacMax
,MAX(FacMin
,FacSafe
/pow(Err
,ONE
/ros_ELO
)));
588 /*~~~> Check the error magnitude and adjust step size */
590 if ( (Err
<= ONE
) || (H
<= Hmin
) ) { /*~~~> Accept step */
592 WCOPY(KPP_NVAR
,Ynew
,1,Y
,1);
594 Hnew
= MAX(Hmin
,MIN(Hnew
,Hmax
));
595 /* No step size increase after a rejected step */
598 RejectLastH
= 0; RejectMoreH
= 0;
600 break; /* EXIT THE LOOP: WHILE STEP NOT ACCEPTED */
601 } else { /*~~~> Reject step */
606 RejectMoreH
= RejectLastH
; RejectLastH
= 1;
608 } /* end if Err <= 1 */
610 } /* while LOOP: WHILE STEP NOT ACCEPTED */
612 } /* while: time loop */
614 /*~~~> The integration was successful */
618 } /* RosenbrockIntegrator */
622 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
623 KPP_REAL
ros_ErrorNorm (
624 /*~~~> Input arguments */
625 KPP_REAL Y
[], KPP_REAL Ynew
[], KPP_REAL Yerr
[],
626 KPP_REAL AbsTol
[], KPP_REAL RelTol
[],
628 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
629 Computes and returns the "scaled norm" of the error vector Yerr
630 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
632 /*~~~> Local variables */
633 KPP_REAL Err
, Scale
, Ymax
;
637 for (i
=0; i
<KPP_NVAR
; i
++) {
638 Ymax
= MAX(ABS(Y
[i
]),ABS(Ynew
[i
]));
640 Scale
= AbsTol
[i
]+RelTol
[i
]*Ymax
;
642 Scale
= AbsTol
[0]+RelTol
[0]*Ymax
;
644 Err
= Err
+(Yerr
[i
]*Yerr
[i
])/(Scale
*Scale
);
646 Err
= SQRT(Err
/(KPP_REAL
)KPP_NVAR
);
650 } /* ros_ErrorNorm */
653 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
654 void ros_FunTimeDerivative (
655 /*~~~> Input arguments: */
656 KPP_REAL T
, KPP_REAL Roundoff
,
657 KPP_REAL Y
[], KPP_REAL Fcn0
[],
658 void (*ode_Fun
)(KPP_REAL
, KPP_REAL
[], KPP_REAL
[]),
659 /*~~~> Output arguments: */
661 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
662 The time partial derivative of the function by finite differences
663 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
665 /*~~~> Local variables */
668 Delta
= SQRT(Roundoff
)*MAX(DeltaMin
,ABS(T
));
669 (*ode_Fun
)(T
+Delta
,Y
,dFdT
);
670 WAXPY(KPP_NVAR
,(-ONE
),Fcn0
,1,dFdT
,1);
671 WSCAL(KPP_NVAR
,(ONE
/Delta
),dFdT
,1);
673 } /* ros_FunTimeDerivative */
676 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
677 char ros_PrepareMatrix (
678 /* Inout argument: (step size is decreased when LU fails) */
680 /* Input arguments: */
681 int Direction
, KPP_REAL gam
, KPP_REAL Jac0
[],
682 /* Output arguments: */
683 KPP_REAL Ghimj
[], int Pivot
[] )
684 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
685 Prepares the LHS matrix for stage calculations
686 1. Construct Ghimj = 1/(H*ham) - Jac0
687 "(Gamma H) Inverse Minus Jacobian"
688 2. Repeat LU decomposition of Ghimj until successful.
689 -half the step size if LU decomposition fails and retry
690 -exit after 5 consecutive fails
692 Return value: Singular (true=1=failed_LU or false=0=successful_LU)
693 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
695 /*~~~> Local variables */
696 int i
, ising
, Nconsecutive
;
701 while (1) { /* while Singular */
703 /*~~~> Construct Ghimj = 1/(H*ham) - Jac0 */
704 WCOPY(KPP_LU_NONZERO
,Jac0
,1,Ghimj
,1);
705 WSCAL(KPP_LU_NONZERO
,(-ONE
),Ghimj
,1);
706 ghinv
= ONE
/(Direction
*(*H
)*gam
);
707 for (i
=0; i
<KPP_NVAR
; i
++) {
708 Ghimj
[LU_DIAG
[i
]] = Ghimj
[LU_DIAG
[i
]]+ghinv
;
710 /*~~~> Compute LU decomposition */
711 DecompTemplate( Ghimj
, Pivot
, &ising
);
713 /*~~~> if successful done */
714 return 0; /* Singular = false */
715 } else { /* ising .ne. 0 */
716 /*~~~> if unsuccessful half the step size; if 5 consecutive fails return */
717 Nsng
++; Nconsecutive
++;
718 printf("\nWarning: LU Decomposition returned ising = %d\n",ising
);
719 if (Nconsecutive
<= 5) { /* Less than 5 consecutive failed LUs */
721 } else { /* More than 5 consecutive failed LUs */
722 return 1; /* Singular = true */
723 } /* end if Nconsecutive */
726 } /* while Singular */
728 } /* ros_PrepareMatrix */
731 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
732 int ros_ErrorMsg(int Code
, KPP_REAL T
, KPP_REAL H
)
733 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
734 Handles all error messages and returns IERR = error Code
735 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
737 printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
738 printf("\nForced exit from Rosenbrock due to the following error:\n");
742 printf("--> Improper value for maximal no of steps"); break;
744 printf("--> Selected Rosenbrock method not implemented"); break;
746 printf("--> Hmin/Hmax/Hstart must be positive"); break;
748 printf("--> FacMin/FacMax/FacRej must be positive"); break;
750 printf("--> Improper tolerance values"); break;
752 printf("--> No of steps exceeds maximum bound"); break;
754 printf("--> Step size too small (T + H/10 = T) or H < Roundoff"); break;
756 printf("--> Matrix is repeatedly singular"); break;
758 printf("Unknown Error code: %d ",Code
);
761 printf("\n Time = %15.7e, H = %15.7e",T
,H
);
762 printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
769 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
770 void Ros2 ( int *ros_S
, KPP_REAL ros_A
[], KPP_REAL ros_C
[],
771 KPP_REAL ros_M
[], KPP_REAL ros_E
[],
772 KPP_REAL ros_Alpha
[], KPP_REAL ros_Gamma
[],
773 char ros_NewF
[], KPP_REAL
*ros_ELO
, char* ros_Name
)
774 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
775 AN L-STABLE METHOD, 2 stages, order 2
776 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
778 double g
= (KPP_REAL
)1.70710678118655; /* 1.0 + 1.0/SQRT(2.0) */
780 /*~~~> Name of the method */
781 strcpy(ros_Name
, "ROS-2");
783 /*~~~> Number of stages */
786 /*~~~> The coefficient matrices A and C are strictly lower triangular.
787 The lower triangular (subdiagonal) elements are stored in row-wise order:
788 A(2,1) = ros_A[0], A(3,1)=ros_A[1], A(3,2)=ros_A[2], etc.
789 The general mapping formula is:
790 A_{i,j} = ros_A[ (i-1)*(i-2)/2 + j -1 ] */
793 /*~~~> C_{i,j} = ros_C[ (i-1)*(i-2)/2 + j -1] */
796 /*~~~> does the stage i require a new function evaluation (ros_NewF(i)=TRUE)
797 or does it re-use the function evaluation from stage i-1 (ros_NewF(i)=FALSE) */
801 /*~~~> M_i = Coefficients for new step solution */
802 ros_M
[0]= (3.0)/(2.0*g
);
803 ros_M
[1]= (1.0)/(2.0*g
);
805 /*~~~> E_i = Coefficients for error estimator */
806 ros_E
[0] = 1.0/(2.0*g
);
807 ros_E
[1] = 1.0/(2.0*g
);
809 /*~~~> ros_ELO = estimator of local order - the minimum between the
810 ! main and the embedded scheme orders plus one */
811 *ros_ELO
= (KPP_REAL
)2.0;
813 /*~~~> Y_stage_i ~ Y( T + H*Alpha_i ) */
814 ros_Alpha
[0] = (KPP_REAL
)0.0;
815 ros_Alpha
[1] = (KPP_REAL
)1.0;
817 /*~~~> Gamma_i = \sum_j gamma_{i,j} */
824 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
825 void Ros3 ( int *ros_S
, KPP_REAL ros_A
[], KPP_REAL ros_C
[],
826 KPP_REAL ros_M
[], KPP_REAL ros_E
[],
827 KPP_REAL ros_Alpha
[], KPP_REAL ros_Gamma
[],
828 char ros_NewF
[], KPP_REAL
*ros_ELO
, char* ros_Name
)
829 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
830 AN L-STABLE METHOD, 3 stages, order 3, 2 function evaluations
831 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
833 /*~~~> Name of the method */
834 strcpy(ros_Name
, "ROS-3");
836 /*~~~> Number of stages */
839 /*~~~> The coefficient matrices A and C are strictly lower triangular.
840 The lower triangular (subdiagonal) elements are stored in row-wise order:
841 A(2,1) = ros_A[0], A(3,1)=ros_A[1], A(3,2)=ros_A[2], etc.
842 The general mapping formula is:
843 A_{i,j} = ros_A[ (i-1)*(i-2)/2 + j -1 ] */
844 ros_A
[0]= (KPP_REAL
)1.0;
845 ros_A
[1]= (KPP_REAL
)1.0;
846 ros_A
[2]= (KPP_REAL
)0.0;
848 /*~~~> C_{i,j} = ros_C[ (i-1)*(i-2)/2 + j -1] */
849 ros_C
[0] = (KPP_REAL
)(-1.0156171083877702091975600115545);
850 ros_C
[1] = (KPP_REAL
)4.0759956452537699824805835358067;
851 ros_C
[2] = (KPP_REAL
)9.2076794298330791242156818474003;
853 /*~~~> does the stage i require a new function evaluation (ros_NewF(i)=TRUE)
854 or does it re-use the function evaluation from stage i-1 (ros_NewF(i)=FALSE) */
859 /*~~~> M_i = Coefficients for new step solution */
860 ros_M
[0] = (KPP_REAL
)1.0;
861 ros_M
[1] = (KPP_REAL
)6.1697947043828245592553615689730;
862 ros_M
[2] = (KPP_REAL
)(-0.4277225654321857332623837380651);
864 /*~~~> E_i = Coefficients for error estimator */
865 ros_E
[0] = (KPP_REAL
)0.5;
866 ros_E
[1] = (KPP_REAL
)(-2.9079558716805469821718236208017);
867 ros_E
[2] = (KPP_REAL
)0.2235406989781156962736090927619;
869 /*~~~> ros_ELO = estimator of local order - the minimum between the
870 ! main and the embedded scheme orders plus 1 */
871 *ros_ELO
= (KPP_REAL
)3.0;
873 /*~~~> Y_stage_i ~ Y( T + H*Alpha_i ) */
874 ros_Alpha
[0]= (KPP_REAL
)0.0;
875 ros_Alpha
[1]= (KPP_REAL
)0.43586652150845899941601945119356;
876 ros_Alpha
[2]= (KPP_REAL
)0.43586652150845899941601945119356;
878 /*~~~> Gamma_i = \sum_j gamma_{i,j} */
879 ros_Gamma
[0]= (KPP_REAL
)0.43586652150845899941601945119356;
880 ros_Gamma
[1]= (KPP_REAL
)0.24291996454816804366592249683314;
881 ros_Gamma
[2]= (KPP_REAL
)2.1851380027664058511513169485832;
885 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
888 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
889 void Ros4 ( int *ros_S
, KPP_REAL ros_A
[], KPP_REAL ros_C
[],
890 KPP_REAL ros_M
[], KPP_REAL ros_E
[],
891 KPP_REAL ros_Alpha
[], KPP_REAL ros_Gamma
[],
892 char ros_NewF
[], KPP_REAL
*ros_ELO
, char* ros_Name
)
893 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
894 L-STABLE ROSENBROCK METHOD OF ORDER 4, WITH 4 STAGES
895 L-STABLE EMBEDDED ROSENBROCK METHOD OF ORDER 3
897 E. HAIRER AND G. WANNER, SOLVING ORDINARY DIFFERENTIAL
898 EQUATIONS II. STIFF AND DIFFERENTIAL-ALGEBRAIC PROBLEMS.
899 SPRINGER SERIES IN COMPUTATIONAL MATHEMATICS,
900 SPRINGER-VERLAG (1990)
901 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
903 /*~~~> Name of the method */
904 strcpy(ros_Name
, "ROS-4");
906 /*~~~> Number of stages */
909 /*~~~> The coefficient matrices A and C are strictly lower triangular.
910 The lower triangular (subdiagonal) elements are stored in row-wise order:
911 A(2,1) = ros_A[0], A(3,1)=ros_A[1], A(3,2)=ros_A[2], etc.
912 The general mapping formula is:
913 A_{i,j} = ros_A[ (i-1)*(i-2)/2 + j -1 ] */
914 ros_A
[0] = (KPP_REAL
)0.2000000000000000e+01;
915 ros_A
[1] = (KPP_REAL
)0.1867943637803922e+01;
916 ros_A
[2] = (KPP_REAL
)0.2344449711399156;
919 ros_A
[5] = (KPP_REAL
)0.0;
921 /*~~~> C(i,j) = (KPP_REAL)ros_C( (i-1)*(i-2)/2 + j ) */
922 ros_C
[0] = (KPP_REAL
)(-0.7137615036412310e+01);
923 ros_C
[1] = (KPP_REAL
)( 0.2580708087951457e+01);
924 ros_C
[2] = (KPP_REAL
)( 0.6515950076447975);
925 ros_C
[3] = (KPP_REAL
)(-0.2137148994382534e+01);
926 ros_C
[4] = (KPP_REAL
)(-0.3214669691237626);
927 ros_C
[5] = (KPP_REAL
)(-0.6949742501781779);
929 /*~~~> does the stage i require a new function evaluation (ros_NewF(i)=TRUE)
930 or does it re-use the function evaluation from stage i-1 (ros_NewF(i)=FALSE) */
936 /*~~~> M_i = Coefficients for new step solution */
937 ros_M
[0] = (KPP_REAL
)0.2255570073418735e+01;
938 ros_M
[1] = (KPP_REAL
)0.2870493262186792;
939 ros_M
[2] = (KPP_REAL
)0.4353179431840180;
940 ros_M
[3] = (KPP_REAL
)0.1093502252409163e+01;
942 /*~~~> E_i = Coefficients for error estimator */
943 ros_E
[0] = (KPP_REAL
)(-0.2815431932141155);
944 ros_E
[1] = (KPP_REAL
)(-0.7276199124938920e-01);
945 ros_E
[2] = (KPP_REAL
)(-0.1082196201495311);
946 ros_E
[3] = (KPP_REAL
)(-0.1093502252409163e+01);
948 /*~~~> ros_ELO = estimator of local order - the minimum between the
949 ! main and the embedded scheme orders plus 1 */
950 *ros_ELO
= (KPP_REAL
)4.0;
952 /*~~~> Y_stage_i ~ Y( T + H*Alpha_i ) */
953 ros_Alpha
[0] = (KPP_REAL
)0.0;
954 ros_Alpha
[1] = (KPP_REAL
)0.1145640000000000e+01;
955 ros_Alpha
[2] = (KPP_REAL
)0.6552168638155900;
956 ros_Alpha
[3] = (KPP_REAL
)ros_Alpha
[2];
958 /*~~~> Gamma_i = \sum_j gamma_{i,j} */
959 ros_Gamma
[0] = (KPP_REAL
)( 0.5728200000000000);
960 ros_Gamma
[1] = (KPP_REAL
)(-0.1769193891319233e+01);
961 ros_Gamma
[2] = (KPP_REAL
)( 0.7592633437920482);
962 ros_Gamma
[3] = (KPP_REAL
)(-0.1049021087100450);
966 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
967 void Rodas3 ( int *ros_S
, KPP_REAL ros_A
[], KPP_REAL ros_C
[],
968 KPP_REAL ros_M
[], KPP_REAL ros_E
[],
969 KPP_REAL ros_Alpha
[], KPP_REAL ros_Gamma
[],
970 char ros_NewF
[], KPP_REAL
*ros_ELO
, char* ros_Name
)
971 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
972 --- A STIFFLY-STABLE METHOD, 4 stages, order 3
973 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
975 /*~~~> Name of the method */
976 strcpy(ros_Name
, "RODAS-3");
978 /*~~~> Number of stages */
981 /*~~~> The coefficient matrices A and C are strictly lower triangular.
982 The lower triangular (subdiagonal) elements are stored in row-wise order:
983 A(2,1) = ros_A[0], A(3,1)=ros_A[1], A(3,2)=ros_A[2], etc.
984 The general mapping formula is:
985 A_{i,j} = ros_A[ (i-1)*(i-2)/2 + j -1 ] */
986 ros_A
[0] = (KPP_REAL
)0.0;
987 ros_A
[1] = (KPP_REAL
)2.0;
988 ros_A
[2] = (KPP_REAL
)0.0;
989 ros_A
[3] = (KPP_REAL
)2.0;
990 ros_A
[4] = (KPP_REAL
)0.0;
991 ros_A
[5] = (KPP_REAL
)1.0;
993 /*~~~> C_{i,j} = ros_C[ (i-1)*(i-2)/2 + j -1] */
994 ros_C
[0] = (KPP_REAL
)4.0;
995 ros_C
[1] = (KPP_REAL
)1.0;
996 ros_C
[2] = (KPP_REAL
)(-1.0);
997 ros_C
[3] = (KPP_REAL
)1.0;
998 ros_C
[4] = (KPP_REAL
)(-1.0);
999 ros_C
[5] = (KPP_REAL
)(-2.66666666666667); /* -8/3 */
1001 /*~~~> does the stage i require a new function evaluation (ros_NewF(i)=TRUE)
1002 or does it re-use the function evaluation from stage i-1 (ros_NewF(i)=FALSE) */
1008 /*~~~> M_i = Coefficients for new step solution */
1009 ros_M
[0] = (KPP_REAL
)2.0;
1010 ros_M
[1] = (KPP_REAL
)0.0;
1011 ros_M
[2] = (KPP_REAL
)1.0;
1012 ros_M
[3] = (KPP_REAL
)1.0;
1014 /*~~~> E_i = Coefficients for error estimator */
1015 ros_E
[0] = (KPP_REAL
)0.0;
1016 ros_E
[1] = (KPP_REAL
)0.0;
1017 ros_E
[2] = (KPP_REAL
)0.0;
1018 ros_E
[3] = (KPP_REAL
)1.0;
1020 /*~~~> ros_ELO = estimator of local order - the minimum between the
1021 ! main and the embedded scheme orders plus 1 */
1022 *ros_ELO
= (KPP_REAL
)3.0;
1024 /*~~~> Y_stage_i ~ Y( T + H*Alpha_i ) */
1025 ros_Alpha
[0] = (KPP_REAL
)0.0;
1026 ros_Alpha
[1] = (KPP_REAL
)0.0;
1027 ros_Alpha
[2] = (KPP_REAL
)1.0;
1028 ros_Alpha
[3] = (KPP_REAL
)1.0;
1030 /*~~~> Gamma_i = \sum_j gamma_{i,j} */
1031 ros_Gamma
[0] = (KPP_REAL
)0.5;
1032 ros_Gamma
[1] = (KPP_REAL
)1.5;
1033 ros_Gamma
[2] = (KPP_REAL
)0.0;
1034 ros_Gamma
[3] = (KPP_REAL
)0.0;
1038 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1039 void Rodas4 ( int *ros_S
, KPP_REAL ros_A
[], KPP_REAL ros_C
[],
1040 KPP_REAL ros_M
[], KPP_REAL ros_E
[],
1041 KPP_REAL ros_Alpha
[], KPP_REAL ros_Gamma
[],
1042 char ros_NewF
[], KPP_REAL
*ros_ELO
, char* ros_Name
)
1043 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1044 STIFFLY-STABLE ROSENBROCK METHOD OF ORDER 4, WITH 6 STAGES
1046 E. HAIRER AND G. WANNER, SOLVING ORDINARY DIFFERENTIAL
1047 EQUATIONS II. STIFF AND DIFFERENTIAL-ALGEBRAIC PROBLEMS.
1048 SPRINGER SERIES IN COMPUTATIONAL MATHEMATICS,
1049 SPRINGER-VERLAG (1996)
1050 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1052 /*~~~> Name of the method */
1053 strcpy(ros_Name
, "RODAS-4");
1055 /*~~~> Number of stages */
1058 /*~~~> Y_stage_i ~ Y( T + H*Alpha_i ) */
1059 ros_Alpha
[0] = (KPP_REAL
)0.000;
1060 ros_Alpha
[1] = (KPP_REAL
)0.386;
1061 ros_Alpha
[2] = (KPP_REAL
)0.210;
1062 ros_Alpha
[3] = (KPP_REAL
)0.630;
1063 ros_Alpha
[4] = (KPP_REAL
)1.000;
1064 ros_Alpha
[5] = (KPP_REAL
)1.000;
1066 /*~~~> Gamma_i = \sum_j gamma_{i,j} */
1067 ros_Gamma
[0] = (KPP_REAL
)0.2500000000000000;
1068 ros_Gamma
[1] = (KPP_REAL
)(-0.1043000000000000);
1069 ros_Gamma
[2] = (KPP_REAL
)0.1035000000000000;
1070 ros_Gamma
[3] = (KPP_REAL
)(-0.3620000000000023e-01);
1071 ros_Gamma
[4] = (KPP_REAL
)0.0;
1072 ros_Gamma
[5] = (KPP_REAL
)0.0;
1074 /*~~~> The coefficient matrices A and C are strictly lower triangular.
1075 The lower triangular (subdiagonal) elements are stored in row-wise order:
1076 A(2,1) = ros_A[0], A(3,1)=ros_A[1], A(3,2)=ros_A[2], etc.
1077 The general mapping formula is: A_{i,j} = ros_A[ (i-1)*(i-2)/2 + j -1 ] */
1078 ros_A
[0] = (KPP_REAL
)0.1544000000000000e+01;
1079 ros_A
[1] = (KPP_REAL
)0.9466785280815826;
1080 ros_A
[2] = (KPP_REAL
)0.2557011698983284;
1081 ros_A
[3] = (KPP_REAL
)0.3314825187068521e+01;
1082 ros_A
[4] = (KPP_REAL
)0.2896124015972201e+01;
1083 ros_A
[5] = (KPP_REAL
)0.9986419139977817;
1084 ros_A
[6] = (KPP_REAL
)0.1221224509226641e+01;
1085 ros_A
[7] = (KPP_REAL
)0.6019134481288629e+01;
1086 ros_A
[8] = (KPP_REAL
)0.1253708332932087e+02;
1087 ros_A
[9] = (KPP_REAL
)(-0.6878860361058950);
1088 ros_A
[10] = ros_A
[6];
1089 ros_A
[11] = ros_A
[7];
1090 ros_A
[12] = ros_A
[8];
1091 ros_A
[13] = ros_A
[9];
1092 ros_A
[14] = (KPP_REAL
)1.0;
1094 /*~~~> C_{i,j} = ros_C[ (i-1)*(i-2)/2 + j -1] */
1095 ros_C
[0] = (KPP_REAL
)(-0.5668800000000000e+01);
1096 ros_C
[1] = (KPP_REAL
)(-0.2430093356833875e+01);
1097 ros_C
[2] = (KPP_REAL
)(-0.2063599157091915);
1098 ros_C
[3] = (KPP_REAL
)(-0.1073529058151375);
1099 ros_C
[4] = (KPP_REAL
)(-0.9594562251023355e+01);
1100 ros_C
[5] = (KPP_REAL
)(-0.2047028614809616e+02);
1101 ros_C
[6] = (KPP_REAL
)( 0.7496443313967647e+01);
1102 ros_C
[7] = (KPP_REAL
)(-0.1024680431464352e+02);
1103 ros_C
[8] = (KPP_REAL
)(-0.3399990352819905e+02);
1104 ros_C
[9] = (KPP_REAL
)( 0.1170890893206160e+02);
1105 ros_C
[10] = (KPP_REAL
)( 0.8083246795921522e+01);
1106 ros_C
[11] = (KPP_REAL
)(-0.7981132988064893e+01);
1107 ros_C
[12] = (KPP_REAL
)(-0.3152159432874371e+02);
1108 ros_C
[13] = (KPP_REAL
)( 0.1631930543123136e+02);
1109 ros_C
[14] = (KPP_REAL
)(-0.6058818238834054e+01);
1111 /*~~~> M_i = Coefficients for new step solution */
1112 ros_M
[0] = ros_A
[6];
1113 ros_M
[1] = ros_A
[7];
1114 ros_M
[2] = ros_A
[8];
1115 ros_M
[3] = ros_A
[9];
1116 ros_M
[4] = (KPP_REAL
)1.0;
1117 ros_M
[5] = (KPP_REAL
)1.0;
1119 /*~~~> E_i = Coefficients for error estimator */
1120 ros_E
[0] = (KPP_REAL
)0.0;
1121 ros_E
[1] = (KPP_REAL
)0.0;
1122 ros_E
[2] = (KPP_REAL
)0.0;
1123 ros_E
[3] = (KPP_REAL
)0.0;
1124 ros_E
[4] = (KPP_REAL
)0.0;
1125 ros_E
[5] = (KPP_REAL
)1.0;
1127 /*~~~> does the stage i require a new function evaluation (ros_NewF(i)=TRUE)
1128 or does it re-use the function evaluation from stage i-1 (ros_NewF(i)=FALSE) */
1136 /*~~~> ros_ELO = estimator of local order - the minimum between the
1137 ! main and the embedded scheme orders plus 1 */
1138 *ros_ELO
= (KPP_REAL
)4.0;
1144 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1145 void DecompTemplate( KPP_REAL A
[], int Pivot
[], int* ising
)
1146 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1147 Template for the LU decomposition
1148 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1150 *ising
= KppDecomp ( A
);
1151 /*~~~> Note: for a full matrix use Lapack:
1152 DGETRF( KPP_NVAR, KPP_NVAR, A, KPP_NVAR, Pivot, ising ) */
1156 } /* DecompTemplate */
1158 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1159 void SolveTemplate( KPP_REAL A
[], int Pivot
[], KPP_REAL b
[] )
1160 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1161 Template for the forward/backward substitution (using pre-computed LU decomposition)
1162 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1165 /*~~~> Note: for a full matrix use Lapack:
1167 DGETRS( 'N', KPP_NVAR , NRHS, A, KPP_NVAR, Pivot, b, KPP_NVAR, INFO ) */
1171 } /* SolveTemplate */
1174 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1175 void FunTemplate( KPP_REAL T
, KPP_REAL Y
[], KPP_REAL Ydot
[] )
1176 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1177 Template for the ODE function call.
1178 Updates the rate coefficients (and possibly the fixed species) at each call
1179 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1187 Fun( Y
, FIX
, RCONST
, Ydot
);
1195 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1196 void JacTemplate( KPP_REAL T
, KPP_REAL Y
[], KPP_REAL Jcb
[] )
1197 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1198 Template for the ODE Jacobian call.
1199 Updates the rate coefficients (and possibly the fixed species) at each call
1200 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1202 /*~~~> Local variables */
1209 Jac_SP( Y
, FIX
, RCONST
, Jcb
);