Merge remote-tracking branch 'origin/release-v4.6.1'
[WRF.git] / chem / KPP / kpp / kpp-2.1 / int / oldies / rodas3.c
blob92754698f0c059efe3497743fa7d206ce9020491
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 dabs(y) (double)abs(y)
6 #define DSQRT(d) (double)pow(d,0.5)
8 void (*forfun)(int,KPP_REAL,KPP_REAL [],KPP_REAL []);
9 void (*forjac)(int,KPP_REAL,KPP_REAL [],KPP_REAL []);
12 void FUNC_CHEM(int N,KPP_REAL T,KPP_REAL Y[NVAR],KPP_REAL P[NVAR])
14 KPP_REAL Told;
15 Told = TIME;
16 TIME = T;
17 Update_SUN();
18 Update_PHOTO();
19 Fun( Y, FIX, RCONST, P );
20 TIME = Told;
21 } /* function fun ends here */
23 void JAC_CHEM(int N,KPP_REAL T,KPP_REAL Y[NVAR],KPP_REAL J[LU_NONZERO])
25 KPP_REAL Told;
26 Told = TIME;
27 TIME = T;
28 Update_SUN();
29 Update_PHOTO();
30 Jac_SP( Y, FIX, RCONST, J );
31 TIME = Told;
32 } /* function jac_sp ends here */
35 INTEGRATE( KPP_REAL TIN, KPP_REAL TOUT )
37 /* TIN - Start Time */
38 /* TOUT - End Time */
40 int INFO[5];
42 forfun = &FUNC_CHEM;
43 forjac = &JAC_CHEM;
44 INFO[0] = Autonomous;
46 RODAS3( NVAR,TIN,TOUT,STEPMIN,STEPMAX,STEPMIN,VAR,ATOL,RTOL,INFO
47 ,forfun ,forjac );
53 int RODAS3(int N,KPP_REAL T, KPP_REAL Tnext,KPP_REAL Hmin,KPP_REAL Hmax,
54 KPP_REAL Hstart,KPP_REAL y[NVAR],KPP_REAL AbsTol[NVAR],KPP_REAL RelTol[NVAR],
55 int INFO[5],void (*forfun)(int,KPP_REAL,KPP_REAL [],KPP_REAL []),
56 void (*forjac)(int,KPP_REAL,KPP_REAL [],KPP_REAL []) )
59 Stiffly accurate Rosenbrock 3(2), with
60 stiffly accurate embedded formula for error control.
62 All the arguments aggree with the KPP syntax.
64 INPUT ARGUMENTS:
65 y = Vector of (NVAR) concentrations, contains the
66 initial values on input
67 [T, Tnext] = the integration interval
68 Hmin, Hmax = lower and upper bounds for the selected step-size.
69 Note that for Step = Hmin the current computed
70 solution is unconditionally accepted by the error
71 control mechanism.
72 AbsTol, RelTol = (NVAR) dimensional vectors of
73 componentwise absolute and relative tolerances.
74 FUNC_CHEM = name of routine of derivatives. KPP syntax.
75 See the header below.
76 JAC_CHEM = name of routine that computes the Jacobian, in
77 sparse format. KPP syntax. See the header below.
78 Info(1) = 1 for autonomous system
79 = 0 for nonautonomous system
81 OUTPUT ARGUMENTS:
82 y = the values of concentrations at Tend.
83 T = equals Tend on output.
84 Info(2) = # of FUNC_CHEM calls.
85 Info(3) = # of JAC_CHEM calls.
86 Info(4) = # of accepted steps.
87 Info(5) = # of rejected steps.
89 Adrian Sandu, March 1996
90 The Center for Global and Regional Environmental Research
92 KPP_REAL K1[NVAR], K2[NVAR], K3[NVAR], K4[NVAR];
93 KPP_REAL F1[NVAR], JAC[LU_NONZERO];
94 KPP_REAL ghinv,uround,c43,x1,x2,ytol;
95 KPP_REAL ynew[NVAR];
96 KPP_REAL H, Hold, Tplus,tau,tau1,tau2,tau3;
97 KPP_REAL ERR, factor, facmax;
98 int n,nfcn,njac,Naccept,Nreject,i,j,ier;
99 char IsReject,Autonomous;
103 /* Initialization of counters, etc. */
104 Autonomous = (INFO[0] == 1);
105 uround = (double)1e-15;
106 c43 = (double)(-8.e0/3.e0);
107 H = MAX( (double)1e-8, Hstart );
108 Hmin = MAX(Hmin,uround*(Tnext-T));
109 Hmax = MIN(Hmax,Tnext-T);
110 Tplus = T;
111 IsReject = 0;
112 Naccept = 0;
113 Nreject = 0;
114 nfcn = 0;
115 njac = 0;
118 /* === Starting the time loop === */
120 while(T<Tnext)
122 ten :
123 Tplus = T + H;
125 if ( Tplus > Tnext )
127 H = Tnext - T;
128 Tplus = Tnext;
131 (*forjac)(NVAR, T, y,JAC );
133 njac = njac+1;
134 ghinv = (double)-2.0e0/H;
135 for(j=0;j<NVAR;j++)
136 JAC[LU_DIAG[j]] = JAC[LU_DIAG[j]] + ghinv;
139 ier = KppDecomp (JAC);
141 if ( ier != 0)
143 if( H > Hmin )
145 H = (double)5.0e-1*H;
146 goto ten;
148 else
149 printf("IER <> 0 , H = %d", H);
150 }/* main ier if ends*/
153 (*forfun)(NVAR , T, y, F1 ) ;
156 /* ====== NONAUTONOMOUS CASE =============== */
158 if( Autonomous == 0)
160 tau = DSQRT( uround*MAX( (double)1.0e-5, dabs(T) ) );
161 (*forfun)(NVAR , T+tau , y ,K2 );
162 nfcn=nfcn+1;
163 for(j=0;j<NVAR;j++)
164 K3[j] = ( K2[j]-F1[j] )/tau;
167 /* ----- STAGE 1 (NONAUTONOMOUS) ----- */
168 x1 = (double)0.5*H;
170 for(j=0;j<NVAR;j++)
171 K1[j] = F1[j] + x1*K3[j];
173 KppSolve (JAC, K1);
175 /* ----- STAGE 2 (NONAUTONOMOUS) ----- */
177 x1 = (double)4.e0/H;
179 x2 = (double)1.5e0*H;
181 for(j=0;j<NVAR;j++)
182 K2[j] = F1[j] - x1*K1[j] + x2*K3[j];
184 KppSolve (JAC, K2);
185 }/* if nonautonomous case ends here */
188 /* ====== AUTONOMOUS CASE =============== */
189 else
191 /* ----- STAGE 1 (AUTONOMOUS) ----- */
192 for(j=0;j<NVAR;j++)
193 K1[j] = F1[j];
195 KppSolve (JAC, K1);
197 /* ----- STAGE 2 (AUTONOMOUS) ----- */
199 x1 = (double)4.e0/H;
201 for(j=0;j<NVAR;j++)
202 K2[j] = F1[j] - x1*K1[j];
204 KppSolve(JAC,K2);
206 } /* else autonomous case ends here */
209 /* ----- STAGE 3 ----- */
211 for(j=0;j<NVAR;j++)
212 ynew[j] = y[j] - 2.0e0*K1[j];
215 (*forfun)(NVAR , T+H , ynew ,F1 );
217 nfcn=nfcn+1;
219 for(j=0;j<NVAR;j++)
220 K3[j] = F1[j] + ( -K1[j] + K2[j] )/H;
222 KppSolve (JAC, K3);
226 /* ----- STAGE 4 ----- */
228 for(j=0;j<NVAR;j++)
229 ynew[j] = y[j] - 2.0e0*K1[j] - K3[j];
231 (*forfun)(NVAR, T+H , ynew, F1 );
233 nfcn=nfcn+1;
234 for(j=0;j<NVAR;j++)
235 K4[j] = F1[j] + ( -K1[j] + K2[j] - c43*K3[j] )/H;
237 KppSolve (JAC, K4);
240 /* ---- The Solution --- */
241 for(j=0;j<NVAR;j++)
242 ynew[j] = y[j] - (double)2.0e0*K1[j] - K3[j] - K4[j];
246 /* ====== Error estimation ======== */
248 ERR=(double)0.e0;
250 for(i=0;i<NVAR;i++)
252 ytol = AbsTol[i] + RelTol[i]*dabs(ynew[i]);
253 ERR = (double)(ERR + pow( K4[i]/ytol,2 ));
256 ERR = MAX( uround, DSQRT( ERR/NVAR ) );
258 /* ======= Choose the stepsize =============================== */
260 factor = (double)0.9/pow(ERR,1.e0/3.e0);
262 if(IsReject == 1)
263 facmax = (double)1.0;
264 else
265 facmax = (double)10.0;
267 factor =(double) MAX( 1.0e-1, MIN(factor,facmax) );
269 Hold = H;
270 H = (double)MIN( Hmax, MAX(Hmin,factor*H) );
273 /* ======= Rejected/Accepted Step ============================ */
275 if( (ERR>1) && (Hold>Hmin) )
277 IsReject = 1;
278 Nreject = Nreject + 1;
280 else
282 IsReject = 0;
284 for(i=0;i<NVAR;i++)
286 y[i] = ynew[i];
288 T = Tplus;
289 Naccept = Naccept+1;
290 } /* else should end here */
293 /* ======= End of the time loop =============================== */
296 }/* while loop (T < Tnext) ends here */
300 /* ======= Output Information ================================= */
302 INFO[1] = nfcn;
303 INFO[2] = njac;
304 INFO[3] = Naccept;
305 INFO[4] = Nreject;
307 return 0;
310 } /* function rodas ends here */