1 | /* #include <math.h> */ |
---|
2 | #include "mex.h" |
---|
3 | #include <stdarg.h> |
---|
4 | |
---|
5 | #define MAX_BUF 200 |
---|
6 | |
---|
7 | void Usage() |
---|
8 | { |
---|
9 | mexPrintf(" \n" |
---|
10 | "To get this help message use: KPP_ROOT ? \n" |
---|
11 | " \n" |
---|
12 | "To initialize default values use: KPP_ROOT \n" |
---|
13 | " (type who to see the variables created) \n" |
---|
14 | " \n" |
---|
15 | "To integrate the model use: \n" |
---|
16 | " [ c, m, f ] = KPP_ROOT( t, c0, k, p, fn, tfn ); \n" |
---|
17 | " \n" |
---|
18 | " input : \n" |
---|
19 | " t - Time vector, contains the time at which results \n" |
---|
20 | " should be reported; \n" |
---|
21 | " c0 - Vector with the initial concentrations for all \n" |
---|
22 | " species; \n" |
---|
23 | " k - Vector with all rate constants; \n" |
---|
24 | " p - Vector of parameters for the integration; \n" |
---|
25 | " p(1) holds the relative tolerance \n" |
---|
26 | " p(2) holds the absolute tolerance \n" |
---|
27 | " p(3) holds the minimum step size allowed \n" |
---|
28 | " p(4) holds the maximum step size allowed \n" |
---|
29 | " If any of the above is zero the default value is \n" |
---|
30 | " used; \n" |
---|
31 | " fn - (optional) Name of a matlab function to be called \n" |
---|
32 | " to update the values of k's and concentrations \n" |
---|
33 | " If not present no update is performed. \n" |
---|
34 | " \n" |
---|
35 | " tfn - (optional) Time at which the fn function should \n" |
---|
36 | " be called. If missing <t> is assumed. \n" |
---|
37 | " \n" |
---|
38 | " output: \n" |
---|
39 | " c - Matrix of concentrations of all species vs. time; \n" |
---|
40 | " m - (optional) Mass conservation of all atoms vs. time; \n" |
---|
41 | " f - (optional) Matrix of fluxes of all species vs. time; \n" |
---|
42 | " \n" |
---|
43 | ); |
---|
44 | } |
---|
45 | |
---|
46 | int giveusage; |
---|
47 | |
---|
48 | void F9Error( char *fmt, ... ) |
---|
49 | { |
---|
50 | va_list args; |
---|
51 | char buf[ MAX_BUF ]; |
---|
52 | char errmsg[ MAX_BUF ]; |
---|
53 | |
---|
54 | va_start( args, fmt ); |
---|
55 | vsprintf( buf, fmt, args ); |
---|
56 | va_end( args ); |
---|
57 | |
---|
58 | if( giveusage ) Usage(); |
---|
59 | |
---|
60 | mexPrintf("Error: %s\n", buf); |
---|
61 | mexErrMsgTxt( 0 ); |
---|
62 | } |
---|
63 | |
---|
64 | char allvars[1000]; |
---|
65 | |
---|
66 | int CreateVar(char *name, KPP_REAL val) |
---|
67 | { |
---|
68 | mxArray *GA; |
---|
69 | double *pga; |
---|
70 | |
---|
71 | sprintf(allvars, "%s %s",allvars, name); |
---|
72 | GA = mxCreateDoubleMatrix(1,1,mxREAL); |
---|
73 | pga = mxGetPr(GA); |
---|
74 | *pga = (double)val; |
---|
75 | mxSetName(GA,name); |
---|
76 | return mexPutArray(GA,"global"); |
---|
77 | } |
---|
78 | |
---|
79 | int CreateVec(char *name, int len, KPP_REAL *val) |
---|
80 | { |
---|
81 | mxArray *GA; |
---|
82 | double *pga; |
---|
83 | int i; |
---|
84 | |
---|
85 | sprintf(allvars, "%s %s",allvars, name); |
---|
86 | GA = mxCreateDoubleMatrix(1,len,mxREAL); |
---|
87 | pga = mxGetPr(GA); |
---|
88 | if( sizeof(KPP_REAL) == sizeof(double) ) { |
---|
89 | memmove( pga, val, len*sizeof(double) ); |
---|
90 | } else { |
---|
91 | for( i = 0; i < len; i++ ) pga[i] = (double)val[i]; |
---|
92 | } |
---|
93 | mxSetName(GA,name); |
---|
94 | return mexPutArray(GA,"global"); |
---|
95 | } |
---|
96 | |
---|
97 | int CreateStrVec(char *name, int len, char **val) |
---|
98 | { |
---|
99 | mxArray *GA; |
---|
100 | |
---|
101 | sprintf(allvars, "%s %s",allvars, name); |
---|
102 | GA = mxCreateCharMatrixFromStrings( len, (const char **)val ); |
---|
103 | mxSetName(GA,name); |
---|
104 | return mexPutArray(GA,"global"); |
---|
105 | } |
---|
106 | |
---|
107 | int CreateStr(char *name, char *val) |
---|
108 | { |
---|
109 | mxArray *GA; |
---|
110 | |
---|
111 | sprintf(allvars, "%s %s",allvars, name); |
---|
112 | GA = mxCreateString( val ); |
---|
113 | mxSetName(GA,name); |
---|
114 | return mexPutArray(GA,"global"); |
---|
115 | } |
---|
116 | |
---|
117 | #define T_PRM prhs[0] |
---|
118 | #define C0_PRM prhs[1] |
---|
119 | #define K_PRM prhs[2] |
---|
120 | #define P_PRM prhs[3] |
---|
121 | #define FN_PRM prhs[4] |
---|
122 | #define TFN_PRM prhs[5] |
---|
123 | |
---|
124 | #define C_PRM plhs[0] |
---|
125 | #define M_PRM plhs[1] |
---|
126 | #define F_PRM plhs[2] |
---|
127 | |
---|
128 | #define HAS_FN (nrhs >= 5) |
---|
129 | #define HAS_TFN (nrhs >= 6) |
---|
130 | |
---|
131 | #define HAS_M (nlhs >= 2) |
---|
132 | #define HAS_F (nlhs >= 3) |
---|
133 | |
---|
134 | #define DBL (sizeof(KPP_REAL) == sizeof(double)) |
---|
135 | |
---|
136 | void mexFunction( |
---|
137 | int nlhs, mxArray *plhs[], |
---|
138 | int nrhs, const mxArray *prhs[] |
---|
139 | ) |
---|
140 | { |
---|
141 | double * tp; |
---|
142 | double * c0p; |
---|
143 | double * kp; |
---|
144 | double * pp; |
---|
145 | char fnp[ MAX_BUF ]; |
---|
146 | double *tfnp; |
---|
147 | |
---|
148 | double * cp; |
---|
149 | double * mp; |
---|
150 | double * fp; |
---|
151 | double ATOLS; |
---|
152 | double dval[ NMASS+NSPEC ]; |
---|
153 | |
---|
154 | mxArray *Carr, *Karr, *Tarr; |
---|
155 | double *fcp; |
---|
156 | double *fkp; |
---|
157 | double *ftp, *ftp1; |
---|
158 | |
---|
159 | int i,j,m,n,nd,t; |
---|
160 | int nsteps, nspc, nreact, ncb; |
---|
161 | int tcb, CallBack; |
---|
162 | KPP_REAL prm[4]; |
---|
163 | |
---|
164 | giveusage = 1; |
---|
165 | |
---|
166 | if(nrhs == 0) { |
---|
167 | |
---|
168 | InitVal(); |
---|
169 | Update_RCONST(); |
---|
170 | |
---|
171 | prm[0] = 1e-4; |
---|
172 | prm[1] = 1.0E-18; |
---|
173 | prm[2] = 0.01; |
---|
174 | prm[3] = 900; |
---|
175 | |
---|
176 | sprintf(allvars,"global "); |
---|
177 | |
---|
178 | CreateVec("PRM",4, prm); |
---|
179 | |
---|
180 | CreateVar("NSPEC",NSPEC); |
---|
181 | CreateVar("NREACT",NREACT); |
---|
182 | CreateVar("NMASS",NMASS); |
---|
183 | |
---|
184 | CreateVec("C0", NSPEC, C); |
---|
185 | CreateVec("K0", NREACT, RCONST); |
---|
186 | |
---|
187 | for( i = 0; i < NLOOKAT; i++ ) |
---|
188 | CreateVar( SLOOKAT[i], (double)(i+1) ); |
---|
189 | |
---|
190 | for( i = 0; i < NMASS; i++ ) |
---|
191 | CreateVar( SMASS[i], (double)(i+1) ); |
---|
192 | |
---|
193 | CreateStrVec("SSPEC", NSPEC, SLOOKAT); |
---|
194 | CreateStrVec("SMASS", NMASS, SMASS); |
---|
195 | CreateStrVec("SEQN", NREACT, SEQN); |
---|
196 | |
---|
197 | CreateStr("GLOBALCMD", allvars); |
---|
198 | |
---|
199 | mexEvalString(allvars); |
---|
200 | /* |
---|
201 | mexPrintf("The KPP_ROOT model parameters were sucessfully initialized.\n"); |
---|
202 | */ |
---|
203 | return; |
---|
204 | } |
---|
205 | |
---|
206 | if( nrhs < 4 ) |
---|
207 | F9Error("First 4 parameters are REQUIRED only %d received.", nrhs); |
---|
208 | if( nlhs < 1 ) |
---|
209 | F9Error("At least one output parameter REQUIRED."); |
---|
210 | |
---|
211 | if(! mxIsDouble(T_PRM)) F9Error("<t> must be of type double."); |
---|
212 | if(! mxIsDouble(C0_PRM)) F9Error("<c0> must be of type double."); |
---|
213 | if(! mxIsDouble(K_PRM)) F9Error("<k> must be of type double."); |
---|
214 | if(! mxIsDouble(P_PRM)) F9Error("<p> must be of type double."); |
---|
215 | if((nrhs > 4) && (! mxIsChar(FN_PRM))) F9Error("<fn> must be of type char."); |
---|
216 | if((nrhs > 5) && (! mxIsDouble(TFN_PRM))) F9Error("<tfn> must be of type double."); |
---|
217 | |
---|
218 | nd = mxGetNumberOfDimensions( T_PRM ); |
---|
219 | m = mxGetM( T_PRM ); |
---|
220 | n = mxGetN( T_PRM ); |
---|
221 | if( !( (nd == 2) && ((m == 1) || (n == 1)) ) ) F9Error("<t> must be a column vector."); |
---|
222 | nsteps = (m == 1) ? n : m; |
---|
223 | tp = mxGetPr( T_PRM ); |
---|
224 | |
---|
225 | nd = mxGetNumberOfDimensions( C0_PRM ); |
---|
226 | m = mxGetM( C0_PRM ); |
---|
227 | n = mxGetN( C0_PRM ); |
---|
228 | if( !( (nd == 2) && ((m == 1) || (n == 1)) ) ) F9Error("<c0> must be a column vector."); |
---|
229 | nspc = (m == 1) ? n : m; |
---|
230 | c0p = mxGetPr( C0_PRM ); |
---|
231 | |
---|
232 | nd = mxGetNumberOfDimensions( K_PRM ); |
---|
233 | m = mxGetM( K_PRM ); |
---|
234 | n = mxGetN( K_PRM ); |
---|
235 | if( !( (nd == 2) && ((m == 1) || (n == 1)) ) ) F9Error("<k> must be a column vector."); |
---|
236 | nreact = (m == 1) ? n : m; |
---|
237 | kp = mxGetPr( K_PRM ); |
---|
238 | |
---|
239 | nd = mxGetNumberOfDimensions( P_PRM ); |
---|
240 | m = mxGetM( P_PRM ); |
---|
241 | n = mxGetN( P_PRM ); |
---|
242 | if( !( (nd == 2) && ((m == 1) || (n == 1)) && (n*m == 4) ) ) |
---|
243 | F9Error("<p> must be a column vectorof length 4."); |
---|
244 | pp = mxGetPr( P_PRM ); |
---|
245 | |
---|
246 | *fnp = 0; |
---|
247 | if( HAS_FN ) { |
---|
248 | nd = mxGetNumberOfDimensions( FN_PRM ); |
---|
249 | m = mxGetM( FN_PRM ); |
---|
250 | n = mxGetN( FN_PRM ); |
---|
251 | if( !( (nd == 2) && ((m == 1) || (n == 1)) ) ) F9Error("<fn> must be a character string."); |
---|
252 | if( mxGetString( FN_PRM, fnp, MAX_BUF ) ) |
---|
253 | F9Error("Can not read function mane (too long?)"); |
---|
254 | |
---|
255 | Carr = mxCreateDoubleMatrix(1,NSPEC,mxREAL); |
---|
256 | fcp = mxGetPr(Carr); |
---|
257 | mxSetName(Carr,"C"); |
---|
258 | mexPutArray(Carr,"base"); |
---|
259 | |
---|
260 | Karr = mxCreateDoubleMatrix(1,NREACT,mxREAL); |
---|
261 | fkp = mxGetPr(Karr); |
---|
262 | mxSetName(Karr,"K"); |
---|
263 | mexPutArray(Karr,"base"); |
---|
264 | |
---|
265 | Tarr = mxCreateDoubleMatrix(1,1,mxREAL); |
---|
266 | ftp = mxGetPr(Tarr); |
---|
267 | mxSetName(Tarr,"T"); |
---|
268 | mexPutArray(Tarr,"base"); |
---|
269 | } |
---|
270 | |
---|
271 | tfnp = 0; ncb = 0; |
---|
272 | if( HAS_TFN ) { |
---|
273 | nd = mxGetNumberOfDimensions( TFN_PRM ); |
---|
274 | m = mxGetM( TFN_PRM ); |
---|
275 | n = mxGetN( TFN_PRM ); |
---|
276 | if( !( (nd == 2) && ((m == 1) || (n == 1)) ) ) F9Error("<tfn> must be a column vector."); |
---|
277 | ncb = (m == 1) ? n : m; |
---|
278 | tfnp = mxGetPr( TFN_PRM ); |
---|
279 | } |
---|
280 | |
---|
281 | giveusage = 0; |
---|
282 | |
---|
283 | if( !((nspc == NSPEC) && (nreact == NREACT)) ) { |
---|
284 | F9Error("Size of parameters do not match the model:\n\n" |
---|
285 | " Number of species was %d and should be %d;\n" |
---|
286 | " Number of rections (rate constants) was %d and should be %d;\n", |
---|
287 | nspc, NSPEC, nreact, NREACT); |
---|
288 | } |
---|
289 | |
---|
290 | if( DBL ) { memmove( C, c0p, sizeof(double)*NSPEC ); |
---|
291 | memmove( RCONST, kp, sizeof(double)*NREACT ); } |
---|
292 | else { for( i = 0; i < NSPEC; i++ ) C[i] = (KPP_REAL)c0p[i]; |
---|
293 | for( i = 0; i < NREACT; i++ ) RCONST[i] = (KPP_REAL)kp[i]; } |
---|
294 | |
---|
295 | RTOLS = 1e-4; |
---|
296 | ATOLS = 1e-18; |
---|
297 | STEPMIN = 0.01; |
---|
298 | STEPMAX = 900.0; |
---|
299 | |
---|
300 | if( pp[0] ) RTOLS = pp[0]; |
---|
301 | if( pp[1] ) ATOLS = pp[1]; |
---|
302 | if( pp[2] ) STEPMIN = pp[2]; |
---|
303 | if( pp[3] ) STEPMAX = pp[3]; |
---|
304 | |
---|
305 | for( i = 0; i < NVAR; i++ ) { |
---|
306 | RTOL[i] = RTOLS; |
---|
307 | ATOL[i] = ATOLS; |
---|
308 | } |
---|
309 | |
---|
310 | C_PRM = mxCreateDoubleMatrix(NSPEC,nsteps,mxREAL); |
---|
311 | cp = mxGetPr(C_PRM); |
---|
312 | |
---|
313 | if( HAS_M ) { |
---|
314 | M_PRM = mxCreateDoubleMatrix(NMASS,nsteps,mxREAL); |
---|
315 | mp = mxGetPr(M_PRM); |
---|
316 | } |
---|
317 | |
---|
318 | if( HAS_F ) { |
---|
319 | F_PRM = mxCreateDoubleMatrix(NSPEC,nsteps,mxREAL); |
---|
320 | fp = mxGetPr(F_PRM); |
---|
321 | } |
---|
322 | |
---|
323 | tcb = 0; |
---|
324 | |
---|
325 | for( t = 0; t < nsteps; t++ ) { |
---|
326 | if( t ) { |
---|
327 | TIME = tp[t-1]; |
---|
328 | |
---|
329 | CallBack = 0; |
---|
330 | if( HAS_TFN ) { |
---|
331 | if( tcb < ncb ) |
---|
332 | if( tfnp[tcb] <= TIME ) { CallBack = 1; tcb++; } |
---|
333 | } else { |
---|
334 | CallBack = HAS_FN; |
---|
335 | } |
---|
336 | |
---|
337 | if( CallBack ) { |
---|
338 | if( DBL ) { memmove( fcp, C, sizeof(double)*NSPEC ); |
---|
339 | memmove( fkp, RCONST, sizeof(double)*NREACT ); } |
---|
340 | else { for( i = 0; i < NSPEC; i++ ) fcp[i] = (double)C[i]; |
---|
341 | for( i = 0; i < NREACT; i++ ) fkp[i] = (double)RCONST[i]; } |
---|
342 | *ftp = TIME; |
---|
343 | |
---|
344 | mexPutArray(Carr,"base"); |
---|
345 | mexPutArray(Karr,"base"); |
---|
346 | mexPutArray(Tarr,"base"); |
---|
347 | |
---|
348 | mexCallMATLAB( 0, 0, 0, 0, fnp ); |
---|
349 | |
---|
350 | mxDestroyArray(Carr); Carr = mexGetArray("C","base"); fcp = mxGetPr(Carr); |
---|
351 | mxDestroyArray(Karr); Karr = mexGetArray("K","base"); fkp = mxGetPr(Karr); |
---|
352 | mxDestroyArray(Tarr); Tarr = mexGetArray("T","base"); ftp = mxGetPr(Tarr); |
---|
353 | |
---|
354 | if( DBL ) { memmove( C, fcp, sizeof(double)*NSPEC ); |
---|
355 | memmove( RCONST, fkp, sizeof(double)*NREACT ); } |
---|
356 | else { for( i = 0; i < NSPEC; i++ ) C[i] = (KPP_REAL)fcp[i]; |
---|
357 | for( i = 0; i < NREACT; i++ ) RCONST[i] = (KPP_REAL)fkp[i]; } |
---|
358 | |
---|
359 | } |
---|
360 | |
---|
361 | INTEGRATE( tp[t-1], tp[t] ); |
---|
362 | } |
---|
363 | if( DBL ) { memmove( cp, C, sizeof(double)*NSPEC ); cp += NSPEC; } |
---|
364 | else { for( i = 0; i < NSPEC; i++ ) *cp++ = (double)C[i]; } |
---|
365 | if( HAS_M ) { |
---|
366 | if( DBL ) { GetMass( mp ); mp += NMASS; } |
---|
367 | else { GetMass( dval ); |
---|
368 | for( i = 0; i < NMASS; i++ ) *mp++ = (double)dval[i]; } |
---|
369 | } |
---|
370 | if( HAS_F ) { |
---|
371 | if( DBL ) { FLUX( fp ); fp += NSPEC; } |
---|
372 | else { FLUX( dval ); |
---|
373 | for( i = 0; i < NSPEC; i++ ) *fp++ = (double)dval[i]; } |
---|
374 | } |
---|
375 | } |
---|
376 | } |
---|
377 | |
---|