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 char *MATLAB_types
[] = { "", /* VOID */
42 /*"REAL(dp)", */ /* DOUBLE */
43 "DOUBLE PRECISION", /* DOUBLE */
44 "CHARACTER(LEN=12)", /* STRING */
45 "CHARACTER(LEN=100)" /* DOUBLESTRING */
48 /*************************************************************************************************/
49 void MATLAB_WriteElm( NODE
* n
)
57 name
= varTable
[ elm
->var
]->name
;
60 case CONST
: bprintf("%g", elm
->val
.cnst
);
62 case ELM
: bprintf("%s", name
);
64 case VELM
: if( elm
->val
.idx
.i
>= 0 ) sprintf( maxi
, "%d", elm
->val
.idx
.i
+1 );
65 else sprintf( maxi
, "%s", varTable
[ -elm
->val
.idx
.i
]->name
);
66 bprintf("%s(%s)", name
, maxi
);
68 case MELM
: if( elm
->val
.idx
.i
>= 0 ) sprintf( maxi
, "%d", elm
->val
.idx
.i
+1 );
69 else sprintf( maxi
, "%s", varTable
[ -elm
->val
.idx
.i
]->name
);
70 if( elm
->val
.idx
.j
>= 0 ) sprintf( maxj
, "%d", elm
->val
.idx
.j
+1 );
71 else sprintf( maxj
, "%s", varTable
[ -elm
->val
.idx
.j
]->name
);
72 bprintf("%s(%s,%s)", name
, maxi
, maxj
);
74 case EELM
: bprintf("(%s)", elm
->val
.expr
);
79 /*************************************************************************************************/
80 void MATLAB_WriteSymbol( int op
)
83 case ADD
: bprintf("+");
86 case SUB
: bprintf("-");
89 case MUL
: bprintf("*");
92 case DIV
: bprintf("/");
95 case POW
: bprintf("^");
97 case O_PAREN
: bprintf("(");
100 case C_PAREN
: bprintf(")");
107 /*************************************************************************************************/
108 void MATLAB_WriteAssign( char *ls
, char *rs
)
118 /* Max no of continuation lines in F95 standard is 39 */
119 int number_of_lines
= 1, MAX_NO_OF_LINES
= 36;
121 /* Operator Mapping: 0xaa = '*' | 0xab = '+' | 0xac = ','
122 0xad = '-' | 0xae ='.' | 0xaf = '/' */
123 char op_mult
=0xaa, op_plus
=0xab, op_minus
=0xad, op_dot
=0xae, op_div
=0xaf;
125 crtident
= 3 + ident
* 2;
126 bprintf("%*s%s = ", crtident
, "", ls
);
127 start
= strlen( ls
) + 2;
128 linelg
= 70 - crtident
- start
- 1;
131 while( strlen(rs
) > linelg
) {
132 ifound
= 0; jfound
= 0;
133 if ( number_of_lines
>= MAX_NO_OF_LINES
) {
134 /* If a new line needs to be started.
135 Note: the approach below will create erroneous code if the +/- is within a subexpression, e.g. for
136 A*(B+C) one cannot start a new continuation line by splitting at the + sign */
137 for( j
=linelg
; j
>5; j
-- ) /* split row here if +, -, or comma */
138 if ( ( rs
[j
] == op_plus
)||( rs
[j
] == op_minus
)||( rs
[j
]==',' ) ) {
139 jfound
= 1; i
=j
; break;
142 if ( ( number_of_lines
< MAX_NO_OF_LINES
)||( !jfound
) ) {
143 for( i
=linelg
; i
>10; i
-- ) /* split row here if operator or comma */
144 if ( ( rs
[i
] & 0x80 )||( rs
[i
]==',' ) ) {
148 printf("\n Warning: possible error in continuation lines for %s = ...",ls
);
152 while ( rs
[i
-1] & 0x80 ) i
--; /* put all operators on the next row */
153 while ( rs
[i
] == ',' ) i
++; /* put commas on the current row */
158 if ( first
) { /* first line in a split row */
162 } else {/* continuation line in a split row - but not last line*/
163 bprintf(" ...\n %*s%s", start
, "", rs
);
165 bprintf(" ;\n%*s%s = %s", crtident
, "", ls
, ls
);
170 rs
+= i
; /* jump to the first not-yet-written character */
174 if ( number_of_lines
> MAX_NO_OF_LINES
) {
175 printf("\n Warning: %d continuation lines for %s = ...",number_of_lines
,ls
);
178 if ( first
) bprintf("%s ;\n", rs
); /* non-split row */
179 else bprintf(" ...\n %*s%s;\n", start
, "", rs
); /* last line in a split row */
186 /*************************************************************************************************/
187 void MATLAB_WriteComment( char *fmt
, ... )
190 char buf
[ MAX_LINE
];
192 va_start( args
, fmt
);
193 vsprintf( buf
, fmt
, args
);
196 fprintf( currentFile
, "%c ", '%' );
197 bprintf( "%-65s\n", buf
);
202 /*************************************************************************************************/
203 char * MATLAB_Decl( int v
)
205 static char buf
[120];
211 buf
[0] = 0; return buf
; /* Nothing to declare in matlab */
213 baseType
= MATLAB_types
[ var
->baseType
];
217 switch( var
->type
) {
218 case ELM
: sprintf( buf
, "%s :: %s",
219 baseType
, var
->name
);
222 if( var
->maxi
> 0 ) sprintf( maxi
, "%d", var
->maxi
);
223 else sprintf( maxi
, "%s", varTable
[ -var
->maxi
]->name
);
224 if( (var
->maxi
== 0) ||
225 ((var
->maxi
< 0) && (varTable
[ -var
->maxi
]->maxi
== 0)) )
227 sprintf( buf
, "%s, DIMENSION(%s) :: %s",
228 baseType
, maxi
, var
->name
);
230 case MELM
: if( var
->maxi
> 0 ) sprintf( maxi
, "%d", var
->maxi
);
231 else sprintf( maxi
, "%s", varTable
[ -var
->maxi
]->name
);
232 if( (var
->maxi
== 0) ||
233 ((var
->maxi
< 0) && (varTable
[ -var
->maxi
]->maxi
== 0)) )
235 if( var
->maxj
> 0 ) sprintf( maxj
, "%d", var
->maxj
);
236 else sprintf( maxj
, "%s", varTable
[ -var
->maxj
]->name
);
237 if( (var
->maxj
== 0) ||
238 ((var
->maxj
< 0 ) && (varTable
[ -var
->maxj
]->maxi
== 0)) )
240 sprintf( buf
, "%s, DIMENSION(%s,%s) :: %s",
241 baseType
, maxi
, maxj
,var
->name
);
244 printf( "Can not declare type %d\n", var
->type
);
250 /*************************************************************************************************/
251 char * MATLAB_DeclareData( int v
, void * values
, int n
)
256 static char buf
[120];
264 int maxCols
= MAX_COLS
;
276 ival
= (int*) values
;
277 dval
= (double *) values
;
278 cval
= (char **) values
;
283 var
-> maxi
= max( n
, 1 );
285 baseType
= MATLAB_types
[ var
->baseType
];
289 switch( var
->type
) { /* changed here */
291 /* bprintf( " %s :: %s = ", baseType, var->name );
292 switch ( var->baseType ) {
293 case INT: bprintf( "%d", *ival ); break;
294 case DOUBLE: bprintf( "%f", *dval); break;
295 case REAL: bprintf( "%lg", *dval ); break;
296 case STRING: bprintf( "'%3s'", *cval ); break;
300 splitsize
= 36; /*elements*/
301 maxi_mod
= var
->maxi
% splitsize
;
302 maxi_div
= var
->maxi
/ splitsize
;
304 if( var
->maxi
> 0 ) sprintf( maxi
, "%d", var
->maxi
);
305 else sprintf( maxi
, "%s", varTable
[ -var
->maxi
]->name
);
306 if( (var
->maxi
== 0) ||
307 ((var
->maxi
< 0) && (varTable
[ -var
->maxi
]->maxi
== 0)) )
309 if( var
->maxj
> 0 ) sprintf( maxj
, "%d", var
->maxj
);
310 else sprintf( maxj
, "%s", varTable
[ -var
->maxj
]->name
);
311 if( (var
->maxj
== 0) ||
312 ((var
->maxj
< 0 ) && (varTable
[ -var
->maxj
]->maxi
== 0)) )
314 /* now list values */
315 /* if ( (var->baseType==STRING)||(var->baseType==DOUBLESTRING) ) {
316 bprintf( "%s(1:%s,:) = [ ... \n", var->name, maxi) ;
318 bprintf( "%s(1:%s) = [ ... \n", var->name, maxi) ;
320 if ( (var
->baseType
==STRING
)||(var
->baseType
==DOUBLESTRING
) ) {
321 bprintf( "%s = [ ... \n", var
->name
, maxi
) ;
323 bprintf( "%s = [ ... \n", var
->name
, maxi
) ;
326 /* if the array is defined in one piece, then the for loop will
327 go from 0 to n. Otherwise, there will be partial arrays from
328 i_from to i_to which are of size splitsize except for the
329 last one which is usually smaller and contains the rest */
330 for ( i
=0; i
< n
; i
++ ) {
331 switch( var
-> baseType
) {
333 bprintf( "%4d", ival
[i
] ); maxCols
=12; break;
335 sprintf(mynumber
, "%12.6e",dval
[i
]);
336 bprintf( " %s", mynumber
); maxCols
= 5; break;
338 bprintf( "%12.6e", dval
[i
] ); maxCols
= 5; break;
340 bprintf( "'%12s'", cval
[i
] ); maxCols
= 3; break;
342 strncpy( dsbuf
, cval
[i
], 54 ); dsbuf
[54]='\0';
343 bprintf( "'%48s'", dsbuf
); maxCols
=1; break;
347 if( (i
+1) % maxCols
== 0 ) {
348 bprintf( " ... \n" );
356 case MELM
: if( var
->maxi
> 0 ) sprintf( maxi
, "%d", var
->maxi
);
357 else sprintf( maxi
, "%s", varTable
[ -var
->maxi
]->name
);
358 if( (var
->maxi
== 0) ||
359 ((var
->maxi
< 0) && (varTable
[ -var
->maxi
]->maxi
== 0)) )
361 if( var
->maxj
> 0 ) sprintf( maxj
, "%d", var
->maxj
);
362 else sprintf( maxj
, "%s", varTable
[ -var
->maxj
]->name
);
363 if( (var
->maxj
== 0) ||
364 ((var
->maxj
< 0 ) && (varTable
[ -var
->maxj
]->maxi
== 0)) )
366 sprintf( buf
, "%s, DIMENSION(%s,%s) :: %s\n", /* changed here */
367 baseType
, maxi
, maxj
,var
->name
);
370 printf( "Can not declare type %d", var
->type
);
376 /*************************************************************************************************/
377 void MATLAB_Declare( int v
)
379 if( varTable
[ v
]->comment
) {
380 MATLAB_WriteComment( "%s - %s",
381 varTable
[ v
]->name
, varTable
[ v
]->comment
);
384 bprintf(" %s\n", MATLAB_Decl(v
) );
389 /*************************************************************************************************/
390 void MATLAB_ExternDeclare( int v
)
392 if( varTable
[ v
]->comment
) {
393 MATLAB_WriteComment( "%s - %s",
394 varTable
[ v
]->name
, varTable
[ v
]->comment
);
397 bprintf(" global %s;\n", varTable
[ v
]->name
);
402 /*************************************************************************************************/
403 void MATLAB_GlobalDeclare( int v
)
408 /*************************************************************************************************/
409 void MATLAB_DeclareConstant( int v
, char *val
)
413 char dummy_val
[100]; /* used just to avoid strange behaviour of
414 sscanf when compiled with gcc */
416 strcpy(dummy_val
,val
);val
= dummy_val
;
420 if( sscanf(val
, "%d", &ival
) == 1 )
421 if( ival
== 0 ) var
->maxi
= 0;
427 MATLAB_WriteComment( "%s - %s", var
->name
, var
->comment
);
429 switch( var
->type
) {
430 case CONST
: bprintf(" global %s;",var
->name
, val
);
431 bprintf(" %s = %s; \n", var
->name
, val
);
434 printf( "Invalid constant %d", var
->type
);
442 /*************************************************************************************************/
443 void MATLAB_WriteVecData( VARIABLE
* var
, int min
, int max
, int split
)
449 sprintf( buf
, "%6sdata( %s(i), i = %d, %d ) / &\n%5s",
450 " ", var
->name
, min
, max
, " " );
452 sprintf( buf
, "%6sdata %s / &\n%5s",
453 " ", var
->name
, " " );
456 bprintf( " / \n\n" );
460 /*************************************************************************************************/
461 void MATLAB_DeclareDataOld( int v
, int * values
, int n
)
464 int nlines
, min
, max
;
470 int maxCols
= MAX_COLS
;
474 ival
= (int*) values
;
475 dval
= (double*) values
;
476 cval
= (char**) values
;
482 switch( var
->type
) {
483 case VELM
: if( n
<= 0 ) break;
484 for( i
= 0; i
< n
; i
++ ) {
485 switch( var
->baseType
) {
486 case INT
: bprintf( "%3d", ival
[i
] ); maxCols
=12; break;
488 case REAL
:bprintf( "%5lg", dval
[i
] ); maxCols
=8; break;
489 case STRING
:bprintf( "'%s'", cval
[i
] ); maxCols
=5; break;
491 strncpy( dsbuf
, cval
[i
], 54 ); dsbuf
[54]='\0';
492 bprintf( "'%48s'", dsbuf
); maxCols
=1; break;
494 if( ( (i
+1) % 12 == 0 ) && ( nlines
> MAX_LINES
) ) {
495 split
= 1; nlines
= 1;
496 MATLAB_WriteVecData( var
, min
, max
, split
);
500 if( i
< n
-1 ) bprintf( "," );
501 if( (i
+1) % maxCols
== 0 ) {
502 bprintf( "\n%5s", " " );
508 MATLAB_WriteVecData( var
, min
, max
-1, split
);
511 case ELM
: bprintf( "%6sdata %s / ", " ", var
->name
);
512 switch( var
->baseType
) {
513 case INT
: bprintf( "%d", *ival
); break;
515 case REAL
:bprintf( "%lg", *dval
); break;
516 case STRING
:bprintf( "'%s'", *cval
); break;
518 strncpy( dsbuf
, *cval
, 54 ); dsbuf
[54]='\0';
519 bprintf( "'%s'", dsbuf
); maxCols
=1; break;
520 /* bprintf( "'%50s'", *cval ); break; */
526 printf( "\n Function not defined !\n" );
531 /*************************************************************************************************/
532 void MATLAB_InitDeclare( int v
, int n
, void * values
)
538 var
->maxi
= max( n
, 1 );
541 MATLAB_DeclareData( v
, values
, n
);
544 /*************************************************************************************************/
545 void MATLAB_FunctionStart( int f
, int *vars
)
552 name
= varTable
[ f
]->name
;
553 narg
= varTable
[ f
]->maxi
;
555 bprintf("function " );
558 bprintf("[ %s ] = ", varTable
[ v
]->name
);
560 bprintf(" %s_%s ( ", rootFileName
, name
);
561 for( i
= 0; i
< narg
-1; i
++ ) {
563 bprintf("%s ", varTable
[ v
]->name
);
564 if (i
<narg
-2) bprintf(", ");
571 /*************************************************************************************************/
572 void MATLAB_FunctionPrototipe( int f
, ... )
577 name
= varTable
[ f
]->name
;
578 narg
= varTable
[ f
]->maxi
;
580 bprintf(" EXTERNAL %s\n", name
);
585 /*************************************************************************************************/
586 void MATLAB_FunctionBegin( int f
, ... )
595 char buf
[200], bufname
[200];
598 name
= varTable
[ f
]->name
;
599 narg
= varTable
[ f
]->maxi
;
601 /*Adi - each Matlab functin requires a separate file*/
602 sprintf( buf
, "%s_%s.m", rootFileName
, varTable
[ f
]->name
);
603 mex_funFile
= fopen(buf
, "w");
604 if( mex_funFile
== 0 ) {
605 FatalError(3,"%s: Can't create file", buf
);
607 UseFile( mex_funFile
);
612 for( i
= 0; i
< narg
; i
++ )
613 vars
[ i
] = va_arg( args
, int );
616 CommentFncBegin( f
, vars
);
620 WriteComment("Generated by KPP - symbolic chemistry Kinetics PreProcessor" );
621 WriteComment(" KPP is developed at CGRER labs University of Iowa by" );
622 WriteComment(" Valeriu Damian & Adrian Sandu" );
624 WriteComment("%-20s : %s", "File", buf
);
625 strcpy( buf
, (char*)ctime( &t
) );
626 buf
[ (int)strlen(buf
) - 1 ] = 0;
627 WriteComment("%-20s : %s", "Time", buf
);
628 WriteComment("%-20s : %s", "Working directory", getcwd(buf
, 200) );
629 WriteComment("%-20s : %s", "Equation file", eqFileName
);
630 WriteComment("%-20s : %s", "Output root filename", rootFileName
);
635 MATLAB_FunctionStart( f
, vars
);
640 MapFunctionComment( f
, vars
);
643 /*************************************************************************************************/
644 void MATLAB_FunctionEnd( int f
)
646 bprintf(" \nreturn\n\n");
650 CommentFunctionEnd( f
);
658 /*************************************************************************************************/
659 void MATLAB_Inline( char *fmt
, ... )
664 if( useLang
!= MATLAB_LANG
) return;
666 Va_start( args
, fmt
);
667 vsprintf( buf
, fmt
, args
);
669 bprintf( "%s\n", buf
);
674 /*************************************************************************************************/
677 WriteElm
= MATLAB_WriteElm
;
678 WriteSymbol
= MATLAB_WriteSymbol
;
679 WriteAssign
= MATLAB_WriteAssign
;
680 WriteComment
= MATLAB_WriteComment
;
681 DeclareConstant
= MATLAB_DeclareConstant
;
682 Declare
= MATLAB_Declare
;
683 ExternDeclare
= MATLAB_ExternDeclare
;
684 GlobalDeclare
= MATLAB_GlobalDeclare
;
685 InitDeclare
= MATLAB_InitDeclare
;
687 FunctionStart
= MATLAB_FunctionStart
;
688 FunctionPrototipe
= MATLAB_FunctionPrototipe
;
689 FunctionBegin
= MATLAB_FunctionBegin
;
690 FunctionEnd
= MATLAB_FunctionEnd
;
692 OpenFile( ¶m_headerFile
, rootFileName
, "_Parameters.m","Parameter Definition File" );
693 OpenFile( &driverFile
, rootFileName
, "_Main.m", "Main Program File" );
694 OpenFile( &rateFile
, rootFileName
, "_Rates.m",
695 "The Reaction Rates File" );
697 OpenFile( &stoichiomFile
, rootFileName
, "_Stoichiom.m",
698 "The Stoichiometric Chemical Model File" );
699 OpenFile( &sparse_stoicmFile
, rootFileName
, "_StoichiomSP.m",
700 "Sparse Stoichiometric Data Structures File" );
702 OpenFile( &utilFile
, rootFileName
, "_Util.m",
703 "Auxiliary Routines File" );
704 OpenFile( &sparse_dataFile
, rootFileName
, "_Sparse.m",
705 "Sparse Data Definition File" );
706 OpenFile( &global_dataFile
, rootFileName
, "_Global_defs.m", "Global Data Definition File" );
707 if ( useJacSparse
) {
708 OpenFile( &sparse_jacFile
, rootFileName
, "_JacobianSP.m",
709 "Sparse Jacobian Data Structures File" );
712 OpenFile( &sparse_hessFile
, rootFileName
, "_HessianSP.m",
713 "Sparse Hessian Data Structures File" );
715 OpenFile( &mapFile
, rootFileName
, ".map",
716 "Map File with Human-Readable Information" );
717 OpenFile( &monitorFile
, rootFileName
, "_Monitor.m",
718 "Utility Data Definition File" );