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
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.
25 Computer Science Department
26 Virginia Polytechnic Institute and State University
28 E-mail: sandu@cs.vt.edu
30 ******************************************************************************/
39 /* NONE, ADD, SUB, MUL, DIV, POW, CONST, ELM, VELM, MELM, EELM */
40 int PRI
[] = { 10, 1, 1, 2, 2, 3, 10, 10, 10, 10, 10 };
42 void (*WriteElm
)( NODE
*n
);
43 void (*WriteSymbol
)( int op
);
44 void (*WriteAssign
)( char* lval
, char* rval
);
45 void (*WriteComment
)( char *fmt
, ... );
46 void (*Declare
)( int v
);
47 void (*ExternDeclare
)( int v
);
48 void (*GlobalDeclare
)( int v
);
49 void (*InitDeclare
)( int var
, int nv
, void * values
);
50 void (*DeclareConstant
)( int v
, char *val
);
51 void (*FunctionStart
)( int f
, int *vars
);
52 void (*FunctionPrototipe
)( int f
, ... );
53 void (*FunctionBegin
)( int f
, ... );
54 void (*FunctionEnd
)( int f
);
62 VARIABLE cnst
= { "", CONST
, REAL
, 0, 0 };
63 VARIABLE expr
= { "", EELM
, 0, 0, 0 };
64 VARIABLE
*varTable
[ MAX_VAR
] = { &cnst
, &expr
};
66 int IsConst( NODE
*n
, float val
);
67 NODE
* BinaryOp( int op
, NODE
*n1
, NODE
*n2
);
68 int NodeCmp( NODE
*n1
, NODE
*n2
);
69 NODE
* NodeCopy( NODE
*n1
);
70 void WriteNode( NODE
*n
);
71 void WriteOp( int op
);
72 void ExpandElm( NODE
* n
);
73 int ExpandNode( NODE
*n
, int lastop
);
74 NODE
* LookUpSubst( NODE
*n
);
76 FILE * param_headerFile
= 0;
77 FILE * initFile
= 0; /* mz_rs_20050117 */
78 FILE * driverFile
= 0;
79 FILE * integratorFile
= 0;
80 FILE * linalgFile
= 0;
81 FILE * functionFile
= 0;
82 FILE * jacobianFile
= 0;
84 FILE * stoichiomFile
= 0;
86 FILE * sparse_dataFile
= 0;
87 FILE * sparse_jacFile
= 0;
88 FILE * sparse_hessFile
= 0;
89 FILE * sparse_stoicmFile
= 0;
90 FILE * stochasticFile
= 0;
91 FILE * global_dataFile
= 0;
92 FILE * hessianFile
= 0;
95 FILE * monitorFile
= 0;
96 FILE * mex_funFile
= 0;
97 FILE * mex_jacFile
= 0;
98 FILE * mex_hessFile
= 0;
104 FILE * UseFile( FILE * file
)
108 printf("\n\nKPP Warning (internal): trying to UseFile NULL file pointer!\n");
115 void OpenFile( FILE **fpp
, char *name
, char * ext
, char * identity
)
123 sprintf( bufname
, "%s%s", name
, ext
);
124 if( *fpp
) fclose( *fpp
);
125 *fpp
= fopen( bufname
, "w" );
127 FatalError(3,"%s: Can't create file", bufname
);
133 WriteComment("%s",identity
);
135 WriteComment("Generated by KPP-%s symbolic chemistry Kinetics PreProcessor",
137 WriteComment(" (http://www.cs.vt.edu/~asandu/Software/KPP)");
138 WriteComment("KPP is distributed under GPL, the general public licence");
139 WriteComment(" (http://www.gnu.org/copyleft/gpl.html)");
140 WriteComment("(C) 1995-1997, V. Damian & A. Sandu, CGRER, Univ. Iowa" );
141 WriteComment("(C) 1997-2005, A. Sandu, Michigan Tech, Virginia Tech" );
142 WriteComment(" With important contributions from:" );
143 WriteComment(" M. Damian, Villanova University, USA");
144 WriteComment(" R. Sander, Max-Planck Institute for Chemistry, Mainz, Germany");
146 WriteComment("%-20s : %s", "File", bufname
);
147 strcpy( buf
, ctime( &t
) );
148 buf
[ (int)strlen(buf
) - 1 ] = 0;
149 WriteComment("%-20s : %s", "Time", buf
);
150 WriteComment("%-20s : %s", "Working directory", getcwd(buf
, 200) );
151 WriteComment("%-20s : %s", "Equation file", eqFileName
);
152 WriteComment("%-20s : %s", "Output root filename", rootFileName
);
156 /* Include Headers in .c Files, except Makefile */
157 blength
= strlen(bufname
);
158 if ( (bufname
[blength
-2]=='.')&&(bufname
[blength
-1]=='c') ) {
159 C_Inline("#include <stdio.h>");
160 C_Inline("#include <stdlib.h>");
161 C_Inline("#include <math.h>");
162 C_Inline("#include <string.h>");
163 C_Inline("#include \"%s_Parameters.h\"", rootFileName
);
164 C_Inline("#include \"%s_Global.h\"", rootFileName
);
166 C_Inline("#include \"%s_Sparse.h\"", rootFileName
);
173 *(outBuffer
-1) |= 0x80;
176 void bprintf( char *fmt
, ... )
181 Va_start( args
, fmt
);
182 vsprintf( outBuffer
, fmt
, args
);
184 outBuffer
+= strlen( outBuffer
);
194 fprintf( currentFile
, outBuf
);
199 void FlushThisBuf( char * buf
)
206 fprintf( currentFile
, buf
);
212 WriteComment("****************************************************************");
214 WriteComment("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
217 void NewLines( int n
)
225 void IncludeFile( char * fname
)
229 char line
[ MAX_LINE
];
232 fp
= fopen( fname
, "r" );
234 FatalError(3,"%s: Can't read file", fname
);
240 fgets( line
, MAX_LINE
, fp
);
241 fputs( line
, currentFile
);
247 void IncludeCode( char* fmt
, ... )
252 static char tmpfile
[] = "kppfile.tmp";
255 Va_start( args
, fmt
);
256 vsprintf( buf
, fmt
, args
);
260 case F77_LANG
: sprintf( buf
, "%s.f", buf
);
262 case F90_LANG
: sprintf( buf
, "%s.f90", buf
);
264 case C_LANG
: sprintf( buf
, "%s.c", buf
);
266 case MATLAB_LANG
: sprintf( buf
, "%s.m", buf
);
268 default: printf("\n Language '%d' not implemented!\n",useLang
);
271 fp
= fopen( buf
, "r" );
273 FatalError(3,"%s: Can't read file", buf
);
276 strcpy( cmd
, "sed " );
278 sprintf( cmd
, "%s -e 's/KPP_ROOT/%s/g'", cmd
, rootFileName
);
279 sprintf( cmd
, "%s -e 's/KPP_NVAR/%d/g'", cmd
, VarNr
);
280 sprintf( cmd
, "%s -e 's/KPP_NFIX/%d/g'", cmd
, FixNr
);
281 sprintf( cmd
, "%s -e 's/KPP_NSPEC/%d/g'", cmd
,SpcNr
);
282 sprintf( cmd
, "%s -e 's/KPP_NREACT/%d/g'", cmd
, EqnNr
);
283 sprintf( cmd
, "%s -e 's/KPP_NONZERO/%d/g'", cmd
, Jac_NZ
);
284 sprintf( cmd
, "%s -e 's/KPP_LU_NONZERO/%d/g'", cmd
, LU_Jac_NZ
);
285 sprintf( cmd
, "%s -e 's/KPP_NHESS/%d/g'", cmd
, Hess_NZ
);
289 sprintf( cmd
, "%s -e 's/KPP_REAL/%s/g'", cmd
, F77_types
[real
] );
292 sprintf( cmd
, "%s -e 's/KPP_REAL/%s/g'", cmd
, F90_types
[real
] );
295 sprintf( cmd
, "%s -e 's/KPP_REAL/%s/g'", cmd
, C_types
[real
] );
299 default: printf("\n Language '%d' not implemented!\n",useLang
);
303 sprintf( cmd
, "%s %s > %s", cmd
, buf
, tmpfile
);
306 IncludeFile( tmpfile
);
307 sprintf( cmd
, "rm %s", tmpfile
);
311 void MapFunctionComment( int f
, int *vars
)
315 oldf
= UseFile( mapFile
);
316 FunctionStart( f
, vars
);
318 CommentFncBegin( f, vars );*/
323 int DefineVariable( char * name
, int t
, int bt
, int maxi
, int maxj
, char * comment
)
328 for( i
= 0; i
< MAX_VAR
; i
++ )
329 if( varTable
[ i
] == 0 ) break;
331 if( varTable
[ i
] != 0 ) {
332 printf("\nVariable Table overflow");
336 var
= (VARIABLE
*) malloc( sizeof( VARIABLE
) );
343 var
->comment
= comment
;
349 void FreeVariable( int n
)
351 if( varTable
[ n
] ) {
352 free( varTable
[ n
] );
357 NODE
* Elm( int v
, ... )
368 n
= (NODE
*) malloc( sizeof(NODE
) );
369 elm
= (ELEMENT
*) malloc( sizeof(ELEMENT
) );
378 switch( var
->type
) {
379 case CONST
: switch( var
->baseType
) {
380 case REAL
: elm
->val
.cnst
= (float)va_arg( args
, double );
382 case INT
: elm
->val
.cnst
= (float)va_arg( args
, int );
384 if( elm
->val
.cnst
< 0 ) {
385 elm
->val
.cnst
= -elm
->val
.cnst
;
391 case VELM
: elm
->val
.idx
.i
= va_arg( args
, int );
393 case MELM
: elm
->val
.idx
.i
= va_arg( args
, int );
394 elm
->val
.idx
.j
= va_arg( args
, int );
396 case EELM
: elm
->val
.expr
= va_arg( args
, char* );
404 int IsConst( NODE
*n
, float val
)
407 ( n
->type
== CONST
) &&
408 ( n
->elm
->val
.cnst
== val
)
412 NODE
* BinaryOp( int op
, NODE
*n1
, NODE
*n2
)
416 n
= (NODE
*) malloc( sizeof(NODE
) );
425 NODE
* Add( NODE
*n1
, NODE
*n2
)
427 if( n1
== 0 ) return n2
;
428 if( n2
== 0 ) return n1
;
430 if( IsConst( n1
, 0 ) ) {
434 if( IsConst( n2
, 0 ) ) {
438 return BinaryOp( ADD
, n1
, n2
);
441 NODE
* Sub( NODE
*n1
, NODE
*n2
)
443 if( n1
== 0 ) return BinaryOp( SUB
, 0, n2
);
444 if( n2
== 0 ) return n1
;
446 if( IsConst( n1
, 0 ) ) {
448 return BinaryOp( SUB
, 0, n2
);
450 if( IsConst( n2
, 0 ) ) {
454 return BinaryOp( SUB
, n1
, n2
);
457 NODE
* Mul( NODE
*n1
, NODE
*n2
)
459 if( n1
== 0 ) return n2
;
460 if( n2
== 0 ) return n1
;
462 if( IsConst( n1
, 1 ) ) {
463 n2
->sign
*= n1
->sign
;
467 if( IsConst( n2
, 1 ) ) {
468 n2
->sign
*= n1
->sign
;
472 if( IsConst( n1
, 0 ) ) {
476 if( IsConst( n2
, 0 ) ) {
481 return BinaryOp( MUL
, n1
, n2
);
484 NODE
* Div( NODE
*n1
, NODE
*n2
)
486 if( n1
== 0 ) return BinaryOp( DIV
, Const(1), n2
);
487 if( n2
== 0 ) return n1
;
489 if( IsConst( n2
, 1 ) ) {
490 n2
->sign
*= n1
->sign
;
495 return BinaryOp( DIV
, n1
, n2
);
498 NODE
* Pow( NODE
*n1
, NODE
*n2
)
500 if( n1
== 0 ) return n2
;
501 if( n2
== 0 ) return n1
;
502 return BinaryOp( POW
, n1
, n2
);
505 void FreeNode( NODE
* n
)
509 FreeNode( n
->right
);
510 if( n
->elm
) free( n
->elm
);
514 int NodeCmp( NODE
*n1
, NODE
*n2
)
519 if( n1
== n2
) return 1;
520 if( n1
== 0 ) return 0;
521 if( n2
== 0 ) return 0;
523 if( (n1
->type
% SUBST
) != (n2
->type
% SUBST
) ) return 0;
528 if( elm1
== elm2
) return 1;
529 if( elm1
== 0 ) return 0;
530 if( elm2
== 0 ) return 0;
532 if( elm1
->var
!= elm2
->var
)return 0;
534 case CONST
: if( elm1
->val
.cnst
!= elm2
->val
.cnst
) return 0;
537 case VELM
: if( elm1
->val
.idx
.i
!= elm2
->val
.idx
.i
) return 0;
539 case MELM
: if( elm1
->val
.idx
.i
!= elm2
->val
.idx
.i
) return 0;
540 if( elm1
->val
.idx
.j
!= elm2
->val
.idx
.j
) return 0;
542 case EELM
: if( strcmp( elm1
->val
.expr
, elm2
->val
.expr
) != 0 ) return 0;
549 NODE
* NodeCopy( NODE
*n1
)
554 n
= (NODE
*) malloc( sizeof(NODE
) );
555 elm
= (ELEMENT
*) malloc( sizeof(ELEMENT
) );
562 void WriteNode( NODE
*n
)
565 ExpandNode( n
, NONE
);
568 void WriteOp( int op
)
574 void ExpandElm( NODE
* n
)
578 if( substENABLED
== 0 ) {
582 cn
= LookUpSubst( n
);
586 if( cn
->type
> SUBST
) {
590 WriteSymbol( O_PAREN
);
591 WriteNode( cn
->right
);
592 WriteSymbol( C_PAREN
);
598 int ExpandNode( NODE
*n
, int lastop
)
602 if( n
== 0 ) return lastop
;
605 ( PRI
[ n
->left
->type
] < PRI
[ n
->type
] ) )
610 WriteSymbol( O_PAREN
);
612 lastop
= ExpandNode( n
->left
, lastop
);
613 if( needParen
) WriteSymbol( C_PAREN
);
620 case POW
: crtop
= n
->type
;
622 case NONE
: printf("ERROR - null element");
630 case MUL
: case DIV
: case POW
:
632 if ( n
->sign
== -1 ) {
633 WriteSymbol( O_PAREN
);
636 WriteSymbol( C_PAREN
);
641 case ADD
: if( n
->sign
== -1 )
646 case SUB
: if( n
->sign
== -1 )
651 case NONE
: if( n
->sign
== -1 )
660 ( PRI
[ n
->right
->type
] <= PRI
[ n
->type
] ) )
665 WriteSymbol( O_PAREN
);
667 lastop
= ExpandNode( n
->right
, n
->type
);
668 if( needParen
) WriteSymbol( C_PAREN
);
672 void Assign( NODE
*lval
, NODE
*rval
)
678 ls
= (char*)malloc( MAX_OUTBUF
);
679 rs
= (char*)malloc( MAX_OUTBUF
);
688 WriteAssign( ls
, rs
);
696 NODE
* LookUpSubst( NODE
*n
)
702 if( NodeCmp( n
, cn
) )
709 void MkSubst( NODE
*n1
, NODE
*n2
)
713 n
= LookUpSubst( n1
);
719 FreeNode( n
->right
);
725 void RmSubst( NODE
*n
)
733 if( NodeCmp( n
, cn
) )
738 if( cn
== 0 ) return;
740 FreeNode( cn
->right
);
744 substList
= cn
->left
;
761 WriteNode( n
->right
);
768 void CommentFncBegin( int f
, int *vars
)
775 name
= varTable
[ f
]->name
;
776 narg
= varTable
[ f
]->maxi
;
781 WriteComment("%s - %s", var
->name
, var
->comment
);
782 WriteComment(" Arguments :");
783 for( i
= 0; i
< narg
; i
++ ) {
784 var
= varTable
[vars
[i
]];
785 WriteComment(" %-10s- %s", var
->name
, var
->comment
);
792 void CommentFunctionBegin( int f
, ... )
800 name
= varTable
[ f
]->name
;
801 narg
= varTable
[ f
]->maxi
;
804 for( i
= 0; i
< narg
; i
++ )
805 vars
[i
] = va_arg( args
, int );
808 CommentFncBegin( f
, vars
);
809 /* MapFunctionComment( f, vars ); */
812 void CommentFunctionEnd( int f
)
814 WriteComment("End of %s function", varTable
[ f
]->name
);