added README_changes.txt
[wrffire.git] / wrfv2_fire / chem / KPP / kpp / kpp-2.1 / src / kpp.c
blob9ff7315daa4c6356258a75d0d131d64a89c3461a
1 /******************************************************************************
3 KPP - The Kinetic PreProcessor
4 Builds simulation code for chemical kinetic systems
6 Copyright (C) 1995-1996 Valeriu Damian and Adrian Sandu
7 Copyright (C) 1997-2005 Adrian Sandu
9 KPP is free software; you can redistribute it and/or modify it under the
10 terms of the GNU General Public License as published by the Free Software
11 Foundation (http://www.gnu.org/copyleft/gpl.html); either version 2 of the
12 License, or (at your option) any later version.
14 KPP is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 details.
19 You should have received a copy of the GNU General Public License along
20 with this program; if not, consult http://www.gnu.org/copyleft/gpl.html or
21 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.
24 Adrian Sandu
25 Computer Science Department
26 Virginia Polytechnic Institute and State University
27 Blacksburg, VA 24060
28 E-mail: sandu@cs.vt.edu
30 ******************************************************************************/
33 #include <stdlib.h>
34 #include <string.h>
35 #include "gdata.h"
36 #include "scan.h"
38 char *eqFileName;
39 char *rootFileName = "ff";
40 char Home[ MAX_PATH ] = "";
42 short int linStru[ MAX_SPECIES ];
43 short int colStru[ MAX_SPECIES ];
44 short int bestStru[ MAX_SPECIES ];
45 short int *Stru;
47 enum stru_criteria { UNSORT, LINSORT, COLSORT, BESTSORT };
49 void EqCopy( EQ_VECT e1, EQ_VECT e2 )
51 int i;
53 for( i = 0; i < EqnNr; i++ ) e2[i] = e1[i];
56 int NoSort( const void *p1, const void *p2 )
58 return -1;
61 int CodeCmp( const void *p1, const void *p2 )
63 CODE *c1, *c2;
65 c1 = (CODE*)p1;
66 c2 = (CODE*)p2;
68 if ( *c1 < *c2 ) return -1;
69 if ( *c1 > *c2 ) return 1;
70 return 0;
73 int CodeRCmp( const void *p1, const void *p2 )
75 int rc1, rc2;
76 CODE *c1, *c2;
78 c1 = (CODE*)p1;
79 c2 = (CODE*)p2;
81 rc1 = Reactive[ ReverseCode[ *c1 ] ];
82 rc2 = Reactive[ ReverseCode[ *c2 ] ];
83 if ( rc1 > rc2 ) return -1;
84 if ( rc1 < rc2 ) return 1;
85 if ( *c1 < *c2 ) return -1;
86 if ( *c1 > *c2 ) return 1;
87 return 0;
90 int CodeSSCmp( const void *p1, const void *p2 )
92 return -CodeRCmp(p1,p2);
95 int CodeSCmp( const void *p1, const void *p2 )
97 CODE *c1, *c2;
98 short int sc1, sc2;
100 c1 = (CODE*)p1;
101 c2 = (CODE*)p2;
103 sc1 = Stru[ ReverseCode[ *c1 ] ];
104 sc2 = Stru[ ReverseCode[ *c2 ] ];
106 if ( sc1 > sc2 ) return 1;
107 if ( sc1 < sc2 ) return -1;
108 if ( *c1 < *c2 ) return 1;
109 if ( *c1 > *c2 ) return -1;
110 return 0;
113 void UpdateStructJ()
115 int i,j,k;
117 for ( i=0; i<VarNr; i++ )
118 for ( j=0; j<VarNr; j++ )
119 structJ[i][j]=(i==j)?1:0;
121 for (i = 0; i < VarNr; i++)
122 for (j = 0; j < VarNr; j++)
123 for (k = 0; k < EqnNr; k++)
124 if ( Stoich[i][k]*((Stoich_Left[j][k])?1:0) != 0.0 )
125 structJ[i][j]=1;
127 for ( i=0; i<VarNr; i++ )
128 for ( j=0; j<VarNr; j++ )
129 LUstructJ[i][j]=structJ[i][j];
133 int ComputeLUStructJ()
135 int i,j,k;
136 int nu,nl;
138 for (j = 0; j < VarNr-1; j++) {
139 for (i = j+1; i < VarNr; i++) {
140 if( LUstructJ[i][j] ) {
141 for (k = j; k < VarNr; k++)
142 /* LUstructJ[i][k] += LUstructJ[j][k]; */
143 if ( LUstructJ[j][k] != 0 )
144 LUstructJ[i][k] = 1;
150 nu = 0; nl = 0;
151 for (i = 0; i < VarNr; i++)
152 for (j = 0; j < VarNr; j++)
153 if( LUstructJ[i][j] ) {
154 if(i > j) nl++;
155 if(i <= j) nu++;
158 return nu+nl;
161 int LUnonZero()
163 CODE v[MAX_SPECIES];
164 CODE *var;
165 int i,j,k;
166 int nu,nl;
168 var = v;
169 if( Stru != bestStru ) {
170 for( i=0; i<VarNr; i++ )
171 var[i] = Code[i];
172 qsort( (void*)var, VarNr, sizeof(CODE), CodeSCmp );
173 } else {
174 var = bestStru;
177 for (i = 0; i < VarNr; i++)
178 for (j = 0; j < VarNr; j++)
179 LUstructJ[i][j] = structJ[ ReverseCode[var[i]] ][ ReverseCode[var[j]] ];
181 return ComputeLUStructJ();
184 void LinColSparsity()
186 int i,j,k;
187 int nlin, ncol;
188 FILE * fff;
190 for ( i=0; i<VarNr; i++ )
191 for ( j=0; j<VarNr; j++ )
192 structJ[i][j]=(i==j)?1:0;
194 for (i = 0; i < VarNr; i++)
195 for (j = 0; j < VarNr; j++)
196 for (k = 0; k < EqnNr; k++)
197 if ( Stoich[i][k]*((Stoich_Left[j][k])?1:0) != 0.0 )
198 structJ[i][j]=1;
200 for ( i=0; i<VarNr; i++ ) {
201 linStru[i] = 0;
202 for (j = 0; j < VarNr; j++)
203 linStru[i] += structJ[i][j];
206 for ( i=0; i<VarNr; i++ ) {
207 colStru[i] = 0;
208 for (j = 0; j < VarNr; j++)
209 colStru[i] += structJ[j][i];
210 colStru[i] *= linStru[i];
213 Stru = linStru;
214 nlin = LUnonZero();
215 Stru = colStru;
216 ncol = LUnonZero();
217 if( nlin <= ncol ) {
218 Stru = linStru;
219 LUnonZero();
223 void BestSparsity()
225 int i,j,k;
226 int cnz, lnz;
227 int best, crt;
228 int best_i;
229 int tmp;
230 int s;
232 UpdateStructJ();
234 for ( i=0; i<VarNr; i++ )
235 bestStru[i] = Code[i];
237 for ( s=0; s<VarNr-1; s++ ) {
238 best = MAX_SPECIES*MAX_SPECIES; best_i = 0;
239 for ( i=s; i<VarNr; i++ ) {
240 cnz = 0;lnz = 0;
241 for (j = s; j < VarNr; j++) {
242 cnz += (LUstructJ[i][j]?1:0);
243 lnz += (LUstructJ[j][i]?1:0);
245 crt = (cnz-1)*(lnz-1);
246 if( crt < best ) {
247 best = crt;
248 best_i = i;
251 for ( i=0; i<VarNr; i++ ) {
252 tmp = LUstructJ[s][i];
253 LUstructJ[s][i] = LUstructJ[best_i][i];
254 LUstructJ[best_i][i] = tmp;
256 for ( i=0; i<VarNr; i++ ) {
257 tmp = LUstructJ[i][s];
258 LUstructJ[i][s] = LUstructJ[i][best_i];
259 LUstructJ[i][best_i] = tmp;
261 tmp = bestStru[s];
262 bestStru[s] = bestStru[best_i];
263 bestStru[best_i] = tmp;
265 for (i = s+1; i < VarNr; i++) {
266 if( LUstructJ[i][s] ) {
267 for (k = s; k < VarNr; k++)
268 LUstructJ[i][k] += LUstructJ[s][k];
273 Stru = bestStru;
276 void ReorderSpecies( int criteria )
278 CODE *var;
279 CODE *fix;
280 CODE *dummy;
281 EQ_VECT *tmpStoich_Left;
282 EQ_VECT *tmpStoich_Right;
283 EQ_VECT *tmpStoich;
284 CODE *tmpCode;
285 CODE *tmpReact;
286 int i, k;
287 int new;
288 int (*cmpVar)(const void *, const void *);
289 int (*cmpFix)(const void *, const void *);
290 int dummyNr;
292 cmpVar = CodeCmp;
293 cmpFix = CodeCmp;
295 switch( criteria ) {
296 case UNSORT: cmpVar = useJacobian ? CodeRCmp : CodeCmp;
297 break;
298 case LINSORT: cmpVar = useJacobian ? CodeSCmp : CodeCmp;
299 Stru = linStru;
300 break;
301 case COLSORT: cmpVar = useJacobian ? CodeSCmp : CodeCmp;
302 Stru = colStru;
303 break;
304 case BESTSORT: cmpVar = useJacobian ? NoSort : CodeCmp;
305 break;
308 VarNr = 0;
309 VarActiveNr = 0;
310 FixNr = 0;
311 dummyNr = 0;
313 var = (CODE*)malloc( SpcNr * sizeof(CODE) );
314 fix = (CODE*)malloc( SpcNr * sizeof(CODE) );
315 dummy = (CODE*)malloc( 5 * sizeof(CODE) );
316 tmpStoich_Left = (EQ_VECT*)malloc( SpcNr * sizeof(EQ_VECT) );
317 tmpStoich_Right = (EQ_VECT*)malloc( SpcNr * sizeof(EQ_VECT) );
318 tmpStoich = (EQ_VECT*)malloc( SpcNr * sizeof(EQ_VECT) );
319 tmpCode = (CODE*)malloc( SpcNr * sizeof(CODE) );
320 tmpReact = (CODE*)malloc( SpcNr * sizeof(CODE) );
322 for( i = 0; i < SpcNr; i++ ) {
323 switch( SpeciesTable[ Code[i] ].type ) {
324 case VAR_SPC: var[ VarNr++ ] = Code[ i ];
325 break;
326 case FIX_SPC: fix[ FixNr++ ] = Code[ i ];
327 break;
328 case DUMMY_SPC:dummy[ dummyNr++ ] = Code[ i ];
329 break;
333 if( Stru != bestStru ) {
334 qsort( (void*)var, VarNr, sizeof(CODE), cmpVar );
335 } else {
336 for( i = 0; i < SpcNr; i++ )
337 var[i] = bestStru[i];
339 qsort( (void*)fix, FixNr, sizeof(CODE), cmpFix );
341 for( i = 0; i < SpcNr; i++ ) {
342 EqCopy( Stoich_Left[i], tmpStoich_Left[i] );
343 EqCopy( Stoich_Right[i], tmpStoich_Right[i] );
344 EqCopy( Stoich[i], tmpStoich[i] );
345 tmpCode[i] = Code[i];
346 tmpReact[i] = Reactive[i];
349 SpcNr -= dummyNr;
350 dummyNr = 0;
352 k = 0;
353 for( i = 0; i < VarNr; i++ ) {
354 new = ReverseCode[ var[i] ];
355 EqCopy( tmpStoich_Left[ new ], Stoich_Left[ k ] );
356 EqCopy( tmpStoich_Right[ new ], Stoich_Right[ k ] );
357 EqCopy( tmpStoich[ new ], Stoich[ k ] );
358 Code[ k ] = tmpCode[ new ];
359 Reactive[ k ] = tmpReact[ new ];
360 if( Reactive[ k ] ) VarActiveNr++;
361 k++;
363 for( i = 0; i < FixNr; i++ ) {
364 new = ReverseCode[ fix[i] ];
365 EqCopy( tmpStoich_Left[ new ], Stoich_Left[ k ] );
366 EqCopy( tmpStoich_Right[ new ], Stoich_Right[ k ] );
367 EqCopy( tmpStoich[ new ], Stoich[ k ] );
368 Code[ k ] = tmpCode[ new ];
369 Reactive[ k ] = tmpReact[ new ];
370 k++;
372 for( i = 0; i < dummyNr; i++ ) {
373 new = ReverseCode[ dummy[i] ];
374 EqCopy( tmpStoich_Left[ new ], Stoich_Left[ k ] );
375 EqCopy( tmpStoich_Right[ new ], Stoich_Right[ k ] );
376 EqCopy( tmpStoich[ new ], Stoich[ k ] );
377 Code[ k ] = tmpCode[ new ];
378 Reactive[ k ] = tmpReact[ new ];
379 k++;
383 for( i = 0; i < SpcNr+dummyNr; i++ )
384 ReverseCode[ Code[i] ] = i;
386 free( tmpReact );
387 free( tmpCode );
388 free( tmpStoich );
389 free( tmpStoich_Right );
390 free( tmpStoich_Left );
391 free( dummy );
392 free( fix );
393 free( var );
395 fflush(stdout);
398 /* Allocate Internal Arrays */
399 void AllocInternalArrays( void )
401 int i;
403 if ( (Stoich_Left =(float**)calloc(MAX_SPECIES,sizeof(float*)))==NULL )
404 FatalError(-30,"Cannot allocate Stoich_Left.\n");
406 for (i=0; i<MAX_SPECIES; i++)
407 if ( (Stoich_Left[i] = (float*)calloc(MAX_EQN,sizeof(float)))==NULL ) {
408 FatalError(-30,"Cannot allocate Stoich_Left[%d]",i);
411 if ( (Stoich_Right = (float**)calloc(MAX_SPECIES,sizeof(float*)))==NULL )
412 FatalError(-30,"Cannot allocate Stoich_Right.\n");
414 for (i=0; i<MAX_SPECIES; i++)
415 if ( (Stoich_Right[i] = (float*)calloc(MAX_EQN,sizeof(float)))==NULL ) {
416 FatalError(-30,"Cannot allocate Stoich_Right[%d].",i);
419 if ( (Stoich = (float**)calloc(MAX_SPECIES,sizeof(float*)))==NULL )
420 FatalError(-30,"Cannot allocate Stoich.\n");
422 for (i=0; i<MAX_SPECIES; i++)
423 if ( (Stoich[i] = (float*)calloc(MAX_EQN,sizeof(float)))==NULL ) {
424 FatalError(-30,"Cannot allocate Stoich[%d].",i);
430 /* Allocate Structure Arrays */
431 void AllocStructArrays( void )
433 int i;
436 if ( (structB = (int**)calloc(EqnNr,sizeof(int*)))==NULL )
437 FatalError(-30, "Cannot allocate structB.");
439 for (i=0; i<EqnNr; i++)
440 if ( (structB[i] =(int*) calloc(SpcNr,sizeof(int)))==NULL )
441 FatalError(-30, "Cannot allocate structB[%d].\n",i);
443 if ( (structJ = (int**)calloc(SpcNr,sizeof(int*)))==NULL )
444 FatalError(-30, "Cannot allocate structJ.");
446 for (i=0; i<SpcNr; i++)
447 if ( (structJ[i] =(int*) calloc(SpcNr,sizeof(int)))==NULL )
448 FatalError(-30, "Cannot allocate structJ[%d].\n",i);
450 if ( (LUstructJ = (int**)calloc(SpcNr,sizeof(int*)))==NULL )
451 FatalError(-30, "Cannot allocate LUstructJ.");
453 for (i=0; i<SpcNr; i++)
454 if ( (LUstructJ[i] = (int*)calloc(SpcNr,sizeof(int)))==NULL )
455 FatalError(-30, "Cannot allocate LUstructJ[%d].\n",i);
459 /*******************************************************************/
460 int Postprocess( char * root )
462 char buf[ 200 ];
463 char cmd[500];
464 char cmdexe[500];
465 static char tmpfile[] = "kppfile.tmp";
466 FILE * fp;
468 if ( useLang == MATLAB_LANG ) {
469 /* Add rate function definitions as internal functions to the Update_RCONST file*/
470 sprintf( buf, "cat %s_Update_RCONST.m %s_Rates.m > tmp; mv tmp %s_Update_RCONST.m;",
471 root, root, root );
472 system( buf );
475 /* Postprocessing to replace parameter names by values in the declarations
476 strcpy( cmd, "sed " );
477 sprintf( cmd, "%s -e 's/(NVAR)/(%d)/g'", cmd, VarNr );
478 sprintf( cmd, "%s -e 's/(NFIX)/(%d)/g'", cmd, FixNr );
479 sprintf( cmd, "%s -e 's/(NSPEC)/(%d)/g'", cmd,SpcNr );
480 sprintf( cmd, "%s -e 's/(NREACT)/(%d)/g'", cmd, EqnNr );
481 sprintf( cmd, "%s -e 's/(NONZERO)/(%d)/g'", cmd, Jac_NZ );
482 sprintf( cmd, "%s -e 's/(LU_NONZERO)/(%d)/g'", cmd, LU_Jac_NZ );
483 sprintf( cmd, "%s -e 's/(NHESS)/(%)/g'", cmd, Hess_NZ );
485 sprintf( buf, "%s_Function", rootFileName );
486 switch( useLang ) {
487 case F77_LANG: sprintf( buf, "%s.f", buf );
488 break;
489 case F90_LANG: sprintf( buf, "%s.f90", buf );
490 break;
491 case C_LANG: sprintf( buf, "%s.c", buf );
492 break;
493 case MATLAB_LANG: sprintf( buf, "%s.m", buf );
494 break;
495 default: printf("\n Language '%d' not implemented!\n",useLang);
496 exit(1);
498 sprintf( cmdexe, "%s %s > %s; mv %s %s;", cmd, buf, tmpfile, tmpfile, buf );
499 printf("\n\nCMDEXE='%s'\n",cmdexe);
500 system( cmdexe );
504 /*******************************************************************/
505 int main( int argc, char * argv[] )
507 int status;
508 char name[ 200 ];
509 char *p;
510 int i,j;
512 AllocInternalArrays();
514 p = getenv("KPP_HOME");
515 if( p ) strcpy( Home, p );
517 switch( argc ) {
518 case 3: eqFileName = argv[1];
519 rootFileName = argv[2];
520 break;
521 case 2: eqFileName = argv[1];
522 strcpy( name, eqFileName );
523 p = name + strlen(name);
524 while( p > name ) {
525 if( *p == '.') {
526 *p = '\0';
527 break;
529 p--;
531 rootFileName = name;
532 break;
533 default: FatalError(1,"\nUsage :"
534 "\n kpp <equations file> [output file]\n");
537 printf("\nThis is KPP-%s.\n", KPP_VERSION);
539 printf("\nKPP is parsing the equation file.");
540 status = ParseEquationFile( argv[1] );
542 if( status ) FatalError(2,"%d errors and %d warnings encountered.",
543 nError, nWarning );
544 /* Allocate some internal data structures */
545 AllocStructArrays();
547 printf("\nKPP is computing Jacobian sparsity structure.");
548 ReorderSpecies( UNSORT );
549 if (useReorder==1){
550 BestSparsity();
551 ReorderSpecies( BESTSORT );
553 UpdateStructJ();
554 ComputeLUStructJ();
556 if( initNr == -1 ) initNr = VarNr;
559 printf("\nKPP is starting the code generation.");
560 Generate( rootFileName );
562 printf("\nKPP is starting the code post-processing.");
563 Postprocess( rootFileName );
565 printf("\n\nKPP has succesfully created the model \"%s\".\n\n",rootFileName);
567 if( nError ) exit(4);
568 if( nWarning ) exit(5);
570 exit(0);