/[ascend]/trunk/tcltk/generic/interface/Integrators.c
ViewVC logotype

Contents of /trunk/tcltk/generic/interface/Integrators.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 977 - (show annotations) (download) (as text)
Wed Dec 20 00:39:52 2006 UTC (17 years, 8 months ago) by johnpye
File MIME type: text/x-csrc
File size: 24472 byte(s)
Abstracted the internal integrator calls into a struct IntegratorInternals.
Fixed up compile-time list of integrators.
If IDA is not available, then 'INTEG_IDA' will not be defined.
Added ASC_ASSERT_RANGE for assertions x in [low,high).
Changed calling convention for integrator_get_engines().
1 /* ASCEND modelling environment
2 Copyright 1997, Carnegie Mellon University
3 Copyright (C) 2006 Carnegie Mellon University
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 *//**
20 @file
21 Tcl/Tk interface functions for the Integration feature
22 *//*
23 by Kirk Abbott, Ben Allan, John Pye
24 Created: 1/94
25 Last in CVS: $Revision: 1.32 $ $Date: 2003/08/23 18:43:06 $ $Author: ballan $
26 */
27
28 #define ASC_BUILDING_INTERFACE
29
30 #include <tcl.h>
31 #include <time.h>
32
33 #include <utilities/ascConfig.h>
34 #include <solver/integrator.h>
35 #include <solver/lsode.h>
36 #include <solver/samplelist.h>
37
38 #include "HelpProc.h"
39 #include "Integrators.h"
40 #include "BrowserQuery.h"
41 #include "Qlfdid.h"
42 #include "UnitsProc.h"
43 #include "BrowserProc.h"
44 #include "HelpProc.h"
45 #include "SolverGlobals.h"
46
47 #define SNULL (char *)NULL
48
49 static SampleList l_samplelist;
50
51 /*-------------------------------------------------------
52 HANDLING OF OUTPUT FILES
53 */
54
55 /* vars relating to output files */
56 static FILE *l_obs_file = NULL;
57 static char *l_obs_filename = NULL;
58
59 static FILE *l_y_file = NULL;
60 static char *l_y_filename = NULL;
61
62 static int l_print_option = 1; /* default si */
63 static int l_print_fmt = 0; /* default variable */
64
65 FILE *Asc_IntegOpenYFile(void)
66 {
67 if (l_y_filename==NULL) {
68 return NULL;
69 }
70 l_y_file = fopen(l_y_filename,"a+");
71
72 if (l_y_file==NULL) {
73 FPRINTF(ASCERR,
74 "WARNING: (integrate) Unable to open\n\t%s\nfor state output log.\n",
75 l_y_filename);
76 } else {
77 time_t t;
78 t = time((time_t *)NULL);
79 FPRINTF(l_y_file,"DATASET %s", asctime(localtime(&t)));
80 FFLUSH(l_y_file);
81 }
82 return l_y_file;
83 }
84
85 FILE *Asc_IntegOpenObsFile(void)
86 {
87 if (l_obs_filename==NULL) {
88 return NULL;
89 }
90 l_obs_file = fopen(l_obs_filename,"a+");
91 if (l_obs_file==NULL) {
92 FPRINTF(ASCERR,
93 "WARNING: (integrate) Unable to open\n\t%s\nfor observation log.\n",
94 l_obs_filename);
95 } else {
96 time_t t;
97 t = time((time_t *)NULL);
98 FPRINTF(l_obs_file,"DATASET %s", asctime(localtime(&t)));
99 FFLUSH(l_obs_file);
100 }
101 return l_obs_file;
102 }
103
104 FILE *Asc_IntegGetYFile(void)
105 {
106 return l_y_file;
107 }
108
109 FILE *Asc_IntegGetObsFile(void)
110 {
111 return l_obs_file;
112 }
113
114 void Asc_IntegReleaseYFile(void)
115 {
116 l_y_file = NULL;
117 }
118 void Asc_IntegReleaseObsFile(void)
119 {
120 l_obs_file = NULL;
121 }
122
123 /********************************************************************/
124 /* string column layout: 26 char columns if l_print_fmt else variable */
125 /* numeric format: leading space plus characters from Unit*Value */
126 /* index format: left padded long int */
127 /* headline format space plus - s */
128 #define BCOLSFMT (l_print_fmt ? "%-26s" : "\t%s")
129 #define BCOLNFMT (l_print_fmt ? " %-25s" : "\t%s")
130 #define BCOLIFMT (l_print_fmt ? " %25ld" : "\t%ld")
131 #define BCOLHFMT (l_print_fmt ? " -------------------------" : "\t---")
132
133 void Asc_IntegPrintYHeader(FILE *fp, IntegratorSystem *blsys)
134 {
135 long i,len, *yip;
136 char *name;
137 struct Instance *in;
138 int si;
139 if (fp==NULL) {
140 return;
141 }
142 if (blsys==NULL) {
143 FPRINTF(ASCERR,"WARNING: (Asc_IntegPrintYHeader: called w/o data\n");
144 return;
145 }
146 if (blsys->n_y == 0) {
147 return;
148 }
149 if (blsys->y == NULL) {
150 FPRINTF(ASCERR,"ERROR: (Asc_IntegPrintYHeader: called w/NULL data\n");
151 return;
152 }
153 len = blsys->n_y;
154 yip = blsys->y_id;
155 si = l_print_option;
156 /* output indep var name */
157 /* output dep var names */
158 FPRINTF(fp,"States: (user index) (name) (units)\n");
159 in = var_instance(blsys->x);
160 FPRINTF(fp,"{indvar}"); /* indep id name */
161 name = WriteInstanceNameString(in,g_solvinst_cur);
162 FPRINTF(fp,"\t{%s}\t{%s}\n",name,Asc_UnitString(in,si));
163 ascfree(name);
164 for (i=0; i< len; i++) {
165 in = var_instance(blsys->y[i]);
166 FPRINTF(fp,"{%ld}",yip[i]); /* user id # */
167 name = WriteInstanceNameString(in,g_solvinst_cur);
168 FPRINTF(fp,"\t{%s}\t{%s}\n",name,Asc_UnitString(in,si));
169 ascfree(name);
170 }
171 FPRINTF(fp,BCOLSFMT,"indvar");
172 for (i=0; i < len; i++) {
173 FPRINTF(fp,BCOLIFMT,yip[i]);
174 }
175 FPRINTF(fp,"\n");
176 for (i=0; i <= len; i++) {
177 FPRINTF(fp,BCOLHFMT);
178 }
179 FPRINTF(fp,"\n");
180 }
181 /********************************************************************/
182 void Asc_IntegPrintObsHeader(FILE *fp, IntegratorSystem *blsys)
183 {
184 long i,len, *obsip;
185 char *name;
186 struct Instance *in;
187 int si;
188 if (fp==NULL) {
189 return;
190 }
191 if (blsys==NULL) {
192 ERROR_REPORTER_HERE(ASC_PROG_ERR,"called without data");
193 return;
194 }
195 if (blsys->n_obs == 0) {
196 return;
197 }
198 if (blsys->obs == NULL) {
199 ERROR_REPORTER_HERE(ASC_PROG_ERR,"called with NULL data");
200 return;
201 }
202 len = blsys->n_obs;
203 obsip = blsys->obs_id;
204 si = l_print_option;
205 FPRINTF(fp,"Observations: (user index) (name) (units)\n");
206 /* output indep var name */
207 /* output obs var names */
208 in = var_instance(blsys->x);
209 FPRINTF(fp,"{indvar}"); /* indep id name */
210 name = WriteInstanceNameString(in,g_solvinst_cur);
211 FPRINTF(fp,"\t{%s}\t{%s}\n",name,Asc_UnitString(in,si));
212 ascfree(name);
213 for (i=0; i< len; i++) {
214 in = var_instance(blsys->obs[i]);
215 FPRINTF(fp,"{%ld}",obsip[i]); /* user id # */
216 name = WriteInstanceNameString(in,g_solvinst_cur);
217 FPRINTF(fp,"\t{%s}\t{%s}\n",name,Asc_UnitString(in,si));
218 ascfree(name);
219 }
220 FPRINTF(fp,BCOLSFMT,"indvar");
221 for (i=0; i < len; i++) {
222 FPRINTF(fp,BCOLIFMT,obsip[i]);
223 }
224 FPRINTF(fp,"\n");
225 for (i=0; i <= len; i++) {
226 FPRINTF(fp,BCOLHFMT);
227 }
228 FPRINTF(fp,"\n");
229 }
230
231 /********************************************************************/
232
233 /**
234 @return 1 on success
235 */
236 int Asc_IntegPrintYLine(FILE *fp, IntegratorSystem *blsys)
237 {
238 long i,len;
239 struct var_variable **vp;
240 int si;
241 if (fp==NULL) {
242 return 0;
243 }
244 if (blsys==NULL) {
245 FPRINTF(ASCERR,"WARNING: (Asc_IntegPrintYLine: called w/o data\n");
246 return 0;
247 }
248 if (blsys->n_y == 0) {
249 return 0;
250 }
251 if (blsys->y == NULL) {
252 FPRINTF(ASCERR,"ERROR: (Asc_IntegPrintYHeader: called w/NULL data\n");
253 return 0;
254 }
255 vp = blsys->y;
256 len = blsys->n_y;
257 si = l_print_option;
258 FPRINTF(fp,BCOLNFMT,Asc_UnitlessValue(var_instance(blsys->x),si));
259 for (i=0; i < len; i++) {
260 FPRINTF(fp,BCOLNFMT, Asc_UnitlessValue(var_instance(vp[i]),si));
261 }
262 FPRINTF(fp,"\n");
263 return 1;
264 }
265
266 /**
267 @return 1 on success
268 */
269 int Asc_IntegPrintObsLine(FILE *fp, IntegratorSystem *blsys){
270 long i,len;
271 struct var_variable **vp;
272 int si;
273 if (fp==NULL) {
274 return 0;
275 }
276 if (blsys==NULL) {
277 FPRINTF(ASCERR,"WARNING: (Asc_IntegPrintObsLine: called w/o data\n");
278 return 0;
279 }
280 if (blsys->n_obs == 0) {
281 return 0;
282 }
283 if (blsys->obs == NULL) {
284 FPRINTF(ASCERR,"ERROR: (Asc_IntegPrintObsHeader: called w/NULL data\n");
285 return 0;
286 }
287 vp = blsys->obs;
288 len = blsys->n_obs;
289 si = l_print_option;
290 FPRINTF(fp,BCOLNFMT,Asc_UnitlessValue(var_instance(blsys->x),si));
291 for (i=0; i < len; i++) {
292 FPRINTF(fp,BCOLNFMT, Asc_UnitlessValue(var_instance(vp[i]),si));
293 }
294 FPRINTF(fp,"\n");
295 return 1;
296 }
297
298
299 /*---------------------------------------------*/
300
301 int Asc_IntegSetYFileCmd(ClientData cdata, Tcl_Interp *interp,
302 int argc, CONST84 char *argv[])
303 {
304 size_t len;
305
306 UNUSED_PARAMETER(cdata);
307
308 if ( argc != 2 ) {
309 FPRINTF(ASCERR, "integrate_set_y_file: called without filename.\n");
310 Tcl_SetResult(interp,
311 "integrate_set_y_file <filename,""> called without arg.",
312 TCL_STATIC);
313 return TCL_ERROR;
314 }
315 if (l_y_filename != NULL) {
316 ascfree(l_y_filename);
317 }
318 len = strlen(argv[1]);
319 if (len >0 ) {
320 l_y_filename = Asc_MakeInitString((int)len);
321 sprintf(l_y_filename,"%s",argv[1]);
322 } else {
323 l_y_filename = NULL;
324 }
325 return TCL_OK;
326 }
327
328 /*---------------------------------------------*/
329
330 int Asc_IntegSetObsFileCmd(ClientData cdata, Tcl_Interp *interp,
331 int argc, CONST84 char *argv[])
332 {
333 size_t len;
334
335 UNUSED_PARAMETER(cdata);
336
337 if ( argc != 2 ) {
338 FPRINTF(ASCERR, "integrate_set_obs_file: called without filename.\n");
339 Tcl_SetResult(interp,
340 "integrate_set_obs_file <filename,""> called without arg.",
341 TCL_STATIC);
342 return TCL_ERROR;
343 }
344 if (l_obs_filename != NULL) {
345 ascfree(l_obs_filename);
346 }
347 len = strlen(argv[1]);
348 if (len >0 ) {
349 l_obs_filename = Asc_MakeInitString((int)len);
350 sprintf(l_obs_filename,"%s",argv[1]);
351 } else {
352 l_obs_filename = NULL;
353 }
354 return TCL_OK;
355 }
356
357 /*---------------------------------------------*/
358
359 int Asc_IntegSetFileUnitsCmd(ClientData cdata, Tcl_Interp *interp,
360 int argc, CONST84 char *argv[])
361 {
362 UNUSED_PARAMETER(cdata);
363
364 if ( argc != 2 ) {
365 FPRINTF(ASCERR, "integrate_logunits: called without printoption.\n");
366 Tcl_SetResult(interp,"integrate_logunits <display,si> called without arg.",
367 TCL_STATIC);
368 return TCL_ERROR;
369 }
370 switch (argv[1][0]) {
371 case 's':
372 l_print_option = 1;
373 break;
374 case 'd':
375 l_print_option = 0;
376 break;
377 default:
378 FPRINTF(ASCERR,"integrate_logunits: called with bogus argument.\n");
379 FPRINTF(ASCERR,"logunits remain set to %s.\n",
380 (l_print_option ? "si":"display"));
381 break;
382 }
383 return TCL_OK;
384 }
385
386 /*---------------------------------------------*/
387
388 int Asc_IntegSetFileFormatCmd(ClientData cdata, Tcl_Interp *interp,
389 int argc, CONST84 char *argv[])
390 {
391 UNUSED_PARAMETER(cdata);
392
393 if ( argc != 2 ) {
394 FPRINTF(ASCERR, "integrate_logformat called without printoption.\n");
395 Tcl_SetResult(interp,
396 "integrate_logformat <fixed,variable> called without arg.",
397 TCL_STATIC);
398 return TCL_ERROR;
399 }
400 switch (argv[1][0]) {
401 case 'f':
402 l_print_fmt = 1;
403 break;
404 case 'v':
405 l_print_fmt = 0;
406 break;
407 default:
408 FPRINTF(ASCERR,"integrate_logformat: called with bogus argument.\n");
409 FPRINTF(ASCERR,"logformat remains set to %s.\n",
410 (l_print_fmt ? "fixed":"variable"));
411 break;
412 }
413 return TCL_OK;
414 }
415
416
417 /*---------------------------------------------------------------
418 DEFINING THE TIMESTEPS FOR INTEGRATION
419 */
420
421 int Asc_IntegGetXSamplesCmd(ClientData cdata, Tcl_Interp *interp,
422 int argc, CONST84 char *argv[])
423 {
424 static char sval[40]; /* buffer long enough to hold a double printed */
425 struct Units *du = NULL;
426 const dim_type *dp;
427 long i,len;
428 double *uvalues = NULL;
429 char *ustring;
430 double *uv;
431 int trydu=0, prec, stat=0;
432
433 UNUSED_PARAMETER(cdata);
434
435 if (( argc < 1 ) || ( argc > 2 )) {
436 Tcl_SetResult(interp,
437 "integrate_get_samples: expected 0 or 1 args [display]",
438 TCL_STATIC);
439 return TCL_ERROR;
440 }
441 if (argc==2) {
442 trydu = 1;
443 if( argv[1][0] != 'd') {
444 Tcl_SetResult(interp, "integrate_get_samples: expected display but got ",
445 TCL_STATIC);
446 Tcl_AppendResult(interp,argv[1],".",SNULL);
447 return TCL_ERROR;
448 }
449 }
450
451 len = samplelist_length(&l_samplelist);
452 dp = samplelist_dim(&l_samplelist);
453
454 if (len <1) {
455 Tcl_SetResult(interp, "{} {}", TCL_STATIC);
456 return TCL_OK;
457 }
458
459 if (trydu) {
460
461 /* Allocate the space for the retrieved values... */
462 uvalues = ASC_NEW_ARRAY(double,len);
463 if (uvalues == NULL) {
464 Tcl_SetResult(interp, "integrate_get_samples: Insufficient memory.",
465 TCL_STATIC);
466 return TCL_ERROR;
467 }
468
469 /* Get the display units at string... */
470 ustring = Asc_UnitDimString(dp,0);
471
472 /* Get the conversion factor... */
473 du = (struct Units *)LookupUnits(ustring);
474 if (du == NULL) {
475 ERROR_REPORTER_HERE(ASC_PROG_ERR,"LookupUnits failed :-/");
476 stat = 1;
477 }else{
478 stat = 0;
479 /* fill 'uvalues' with scaled values (in output units) */
480 uv = uvalues;
481 for (i=0; i < len; i++) {
482 /* convert to output units */
483 stat = Asc_UnitConvert(du,samplelist_get(&l_samplelist,i),uv,1);
484 if (stat) {
485 /* any problems, just stop */
486 break;
487 }
488 uv++;
489 }
490 }
491 if (stat) {
492 /* there was a problem, so free the allocated space */
493 ascfree(uvalues);
494 }
495 }
496
497 /* give Tcl the units string */
498 Tcl_AppendResult(interp,"{",ustring,"} {",SNULL);
499
500 /* work out what precision we want */
501 prec = Asc_UnitGetCPrec();
502
503 len--; /* last one is a special case...? */
504 if (!trydu || stat){
505 /* no unit conversion, or failed unit conversion: use the raw values */
506 for(i=0;i<len;i++){
507 sprintf(sval,"%.*g ",prec,samplelist_get(&l_samplelist,i));
508 Tcl_AppendResult(interp,sval,SNULL);
509 }
510 }else{
511 for(i=0;i<len;i++){
512 sprintf(sval,"%.*g ",prec,uvalues[i]);
513 Tcl_AppendResult(interp,sval,SNULL);
514 }
515 ascfree(uvalues);
516 }
517 for (i=0; i<len; i++) {
518 /* print number and a blank */
519 sprintf(sval,"%.*g ",prec,uvalues[i]);
520 Tcl_AppendResult(interp,sval,SNULL);
521 }
522
523 sprintf(sval,"%.*g",prec,uvalues[len]);
524 Tcl_AppendResult(interp,sval,"}",SNULL);
525
526 if (trydu && !stat) {
527 ascfree(uvalues);
528 }
529 return TCL_OK;
530 }
531
532 int Asc_IntegSetXSamplesCmd(ClientData cdata, Tcl_Interp *interp,
533 int argc, CONST84 char *argv[])
534 {
535 struct Units *du = NULL;
536 const dim_type *dp;
537 dim_type *mydp;
538 long i,len;
539 double *uvalues = NULL;
540 double *uv;
541 int stat;
542
543 UNUSED_PARAMETER(cdata);
544
545 if (argc == 1) {
546 samplelist_assign(&l_samplelist,0L,NULL,NULL);
547 return TCL_OK;
548 }
549
550 if (argc <4) {
551 Tcl_SetResult(interp,
552 "Syntax: integrate_set_samples"
553 " <units> <value [value...] value>",
554 TCL_STATIC);
555 FPRINTF(ASCERR,"ERROR: integrate_set_samples needs at least 3 args.");
556 return TCL_ERROR;
557 }
558
559 du = (struct Units *)LookupUnits(argv[1]);
560 if (du == NULL) {
561 Tcl_SetResult(interp, "integrate_set_samples: first arg not valid units.",
562 TCL_STATIC);
563 return TCL_ERROR;
564 }
565 dp = (const dim_type *)UnitsDimensions(du);
566 #if INTDEBUG
567 FPRINTF(ASCERR,"user dimen looks like\n");
568 PrintDimen(ASCERR,dp);
569 #endif
570 mydp = ASC_NEW(dim_type); /* we are giving away */
571 if (mydp == NULL) {
572 Tcl_SetResult(interp, "integrate_set_samples: Insufficient memory",
573 TCL_STATIC);
574 return TCL_ERROR;
575 }
576 CopyDimensions(dp,mydp);
577 #if INTDEBUG
578 FPRINTF(ASCERR,"copy of user dimen looks like\n");
579 PrintDimen(ASCERR,mydp);
580 #endif
581
582 len = argc -2;
583 uvalues = ASC_NEW_ARRAY(double,len); /* we are giving away */
584 if (uvalues==NULL) {
585 Tcl_SetResult(interp, "integrate_set_samples: Insufficient memory",
586 TCL_STATIC);
587 ascfree(mydp);
588 return TCL_ERROR;
589 }
590 stat = 0;
591 uv = uvalues;
592 for (i=0; i<len; i++) {
593 if(Tcl_GetDouble(interp,argv[i+2],uv)!=TCL_OK) {
594 stat = 1;
595 break;
596 }
597 stat = Asc_UnitConvert(du,*uv,uv,0);
598 if (stat) {
599 break;
600 }
601 uv++;
602 }
603 Tcl_ResetResult(interp);
604 if (stat) {
605 Tcl_SetResult(interp, "integrate_set_samples: Invalid value given. (",
606 TCL_STATIC);
607 Tcl_AppendResult(interp,argv[i+2],")",SNULL);
608 ascfree(uvalues);
609 ascfree(mydp);
610 return TCL_ERROR;
611 }
612 if(!samplelist_assign(&l_samplelist,len,uvalues,mydp)){
613 Tcl_SetResult(interp, "integrate_set_samples: Insufficient memory.",
614 TCL_STATIC);
615 ascfree(uvalues);
616 ascfree(mydp);
617 return TCL_ERROR;
618 }
619 return TCL_OK;
620 }
621
622 /*----------------------------------------------------------------
623 FUNCTIONS THAT QUERY THE INTEGRATOR/SOLVER
624 */
625
626 /**
627 Tcl/Tk interface function: is the specified instance integrable.
628
629 There is a problem with this part of the interface. The
630 'integrator_isintegrable' function is being called before the
631 'integrator_analyse' step, which means that it really doesn't have all the
632 information that it needs to be able to say. I've reworked it so that
633 you would expect to get errors back from the 'integrator_solve' step if
634 there is any problem.
635
636 All this function now does is to check that the instance is OK, and to
637 check that a valid integrator engine is specified.
638 */
639 int Asc_IntegInstIntegrableCmd(ClientData cdata,Tcl_Interp *interp,
640 int argc, CONST84 char *argv[])
641 {
642 struct Instance *i=NULL;
643 IntegratorEngine integrator=INTEG_UNKNOWN;
644 int result=0; /* 0 = FALSE; 1 = TRUE */
645
646 UNUSED_PARAMETER(cdata);
647
648 if ( argc != 3 ) {
649 Tcl_SetResult(interp, "integrate_able <solver,current,search> <lsode>",
650 TCL_STATIC);
651 return TCL_ERROR;
652 }
653
654 if (strncmp(argv[1],"solver",3)==0) {
655 i = g_solvinst_cur;
656 } else {
657 if (strncmp(argv[1],"search",3)==0) {
658 i = g_search_inst;
659 } else {
660 if (strncmp(argv[1],"current",3)==0) {
661 i = g_curinst;
662 } else {
663 Tcl_SetResult(interp,
664 "integrate_able: arg 1 is current, search, or solver",
665 TCL_STATIC);
666 return TCL_ERROR;
667 }
668 }
669 }
670
671 if (!i) {
672 Tcl_SetResult(interp, "0", TCL_STATIC);
673 FPRINTF(ASCERR,"NULL instance sent to integrate_able.\n");
674 return TCL_OK;
675 }
676
677 integrator = INTEG_UNKNOWN;
678
679 if (strncmp(argv[2],"blsode",3)==0) {
680 integrator = INTEG_LSODE;
681 #ifdef ASC_WITH_IDA
682 }else if (strncmp(argv[2],"ida",3)==0) {
683 integrator = INTEG_IDA;
684 #endif
685 }
686
687 result = (integrator != INTEG_UNKNOWN);
688 if (result) {
689 Tcl_SetResult(interp, "1", TCL_STATIC);
690 } else {
691 Tcl_SetResult(interp, "0", TCL_STATIC);
692 }
693 return TCL_OK;
694 }
695
696 /*-----------------------------------*/
697
698 /**
699 Set up the Integrator.
700
701 switches (in Tcl/Tk)
702 -engine $name
703 -i0 $stepindex
704 -i1 $stepindex
705 -dt0 $initstepsize
706 -dtmin $minstep
707 -dtmax $maxstep
708 -moststeps $moststeps
709 */
710 int Asc_IntegSetupCmd(ClientData cdata,Tcl_Interp *interp,
711 int argc, CONST84 char *argv[])
712 {
713 IntegratorEngine integrator = INTEG_UNKNOWN;
714 char buf[MAXIMUM_NUMERIC_LENGTH]; /* string to hold integer */
715 CONST84 char *engine = NULL;
716 int result = 0; /* 0 = FALSE; 1 = TRUE */
717 long i0=(-1), i1=(-1);
718 int ifound = 0;
719 int k;
720 int moststeps=0;
721 double dt0=0, dtmin=0, dtmax=0;
722 CONST84 char *cdt0=NULL, *cdtmin=NULL, *cdtmax=NULL, *cmoststeps=NULL,
723 *ci0=NULL, *ci1=NULL;
724 IntegratorReporter *reporter;
725 IntegratorSystem *blsys;
726
727 UNUSED_PARAMETER(cdata);
728
729 k = 1;
730 while (k < (argc-1)) { /* arguments come in pairs */
731 if (strcmp(argv[k],"-engine")==0) {
732 engine = argv[k+1];
733 k+=2;
734 continue;
735 }
736 if (strcmp(argv[k],"-i1")==0) {
737 ci1 = argv[k+1];
738 k+=2;
739 continue;
740 }
741 if (strcmp(argv[k],"-i0")==0) {
742 ci0 = argv[k+1];
743 k+=2;
744 continue;
745 }
746 if (strcmp(argv[k],"-moststeps")==0) {
747 cmoststeps = argv[k+1];
748 k+=2;
749 continue;
750 }
751 if (strcmp(argv[k],"-dtmax")==0) {
752 cdtmax = argv[k+1];
753 k+=2;
754 continue;
755 }
756 if (strcmp(argv[k],"-dtmin")==0) {
757 cdtmin = argv[k+1];
758 k+=2;
759 continue;
760 }
761 if (strcmp(argv[k],"-dt0")==0) {
762 cdt0 = argv[k+1];
763 k+=2;
764 continue;
765 }
766 Tcl_AppendResult(interp,argv[0],": unrecognized option ",
767 argv[k],".",SNULL);
768 return TCL_ERROR;
769 }
770
771 if (engine != NULL && strncmp(engine,"BLSODE",3)==0) {
772 integrator = INTEG_LSODE;
773 ifound=1;
774 }
775
776 #ifdef ASC_WITH_IDA
777 if (engine != NULL && strncmp(engine,"IDA",3)==0) {
778 integrator = INTEG_IDA;
779 ifound=1;
780 }
781 #endif
782
783 if (!ifound) {
784 Tcl_SetResult(interp, "Unsupported integrator", TCL_STATIC);
785 Tcl_AppendResult(interp," ",engine,SNULL);
786 return TCL_ERROR;
787 }
788 if (ci0 != NULL && ci1 != NULL) {
789 /* get i0, i1 if both supplied. */
790 long i;
791 if (Tcl_ExprLong(interp,ci0,&i)==TCL_ERROR|| i<0) {
792 Tcl_ResetResult(interp);
793 Tcl_SetResult(interp, "integrate_setup: index i0 invalid", TCL_STATIC);
794 return TCL_ERROR;
795 }
796 i0=i;
797 if (Tcl_ExprLong(interp,ci1,&i)==TCL_ERROR|| i<i0) {
798 Tcl_ResetResult(interp);
799 Tcl_SetResult(interp, "integrate_setup: index i1 invalid", TCL_STATIC);
800 return TCL_ERROR;
801 }
802 i1=i;
803 }
804 if (cdt0 != NULL) {
805 if (Tcl_GetDouble(interp,cdt0,&dt0) != TCL_OK) {
806 Tcl_ResetResult(interp);
807 Tcl_AppendResult(interp, "integrate_setup: initial step length invalid",
808 " (",cdt0,")", SNULL);
809 return TCL_ERROR;
810 }
811 }
812 if (cdtmin != NULL) {
813 if (Tcl_GetDouble(interp,cdtmin,&dtmin) != TCL_OK || dtmin < 0) {
814 Tcl_ResetResult(interp);
815 Tcl_AppendResult(interp, "integrate_setup: minimum step length invalid",
816 " (",cdtmin,")", SNULL);
817 return TCL_ERROR;
818 }
819 }
820 if (cdtmax != NULL) {
821 if (Tcl_GetDouble(interp,cdtmax,&dtmax) != TCL_OK || dtmax < dtmin) {
822 Tcl_ResetResult(interp);
823 Tcl_AppendResult(interp, "integrate_setup: maximum step length invalid",
824 " (",cdtmax,")", SNULL);
825 return TCL_ERROR;
826 }
827 }
828 if (cmoststeps != NULL) {
829 if (Tcl_GetInt(interp,cmoststeps,&moststeps) != TCL_OK || moststeps < 0) {
830 Tcl_ResetResult(interp);
831 Tcl_AppendResult(interp, "integrate_setup: maximum internal steps bad",
832 " (",cmoststeps,")", SNULL);
833 return TCL_ERROR;
834 }
835 }
836
837 reporter = Asc_GetIntegReporter();
838
839 blsys = integrator_new(g_solvsys_cur,g_solvinst_cur);
840 integrator_set_engine(blsys, integrator);
841 integrator_set_reporter(blsys, reporter);
842 integrator_set_samples(blsys,&l_samplelist);
843 integrator_set_stepzero(blsys,dt0);
844 integrator_set_minstep(blsys,dtmin);
845 integrator_set_maxstep(blsys,dtmax);
846 integrator_set_maxsubsteps(blsys,moststeps);
847
848 result = integrator_analyse(blsys);
849
850 /* go and solve it */
851 integrator_solve(blsys, i0, i1);
852
853 /* once solution is finished, free whatever we allocated */
854 integrator_free(blsys);
855
856 sprintf(buf, "%d", result);
857 Tcl_SetResult(interp, buf, TCL_VOLATILE);
858 return TCL_OK;
859 }
860
861 /********************************************************************/
862
863 int Asc_IntegCleanupCmd(ClientData cdata,Tcl_Interp *interp,
864 int argc, CONST84 char *argv[])
865 {
866 UNUSED_PARAMETER(cdata);
867 (void)argv; /* stop gcc whine about unused parameter */
868
869 if (argc!=1) {
870 Tcl_SetResult(interp, "integrate_cleanup takes no arguments", TCL_STATIC);
871 return TCL_ERROR;
872 }
873
874 /* integrator_cleanup(); */
875 return TCL_OK;
876 }
877
878 /*-------------------------------------------------------------------
879 REPORTER FUNCTIONS
880 */
881
882 FILE *integ_y_out;
883 FILE *integ_obs_out;
884
885 IntegratorReporter *Asc_GetIntegReporter(){
886 IntegratorReporter *r;
887 r = (IntegratorReporter *)ascmalloc(sizeof(IntegratorReporter));
888 r->init = &Asc_IntegReporterInit;
889 r->write = &Asc_IntegReporterWrite;
890 r->write_obs = &Asc_IntegReporterWriteObs;
891 r->close = &Asc_IntegReporterClose;
892 CONSOLE_DEBUG("CREATED INTEGRATORREPORTER FOR TCL/TK INTERFACE");
893 return r;
894 }
895
896 int Asc_IntegReporterInit(IntegratorSystem *blsys){
897 int status = 1;
898
899 CONSOLE_DEBUG("INITIALISING REPORTER");
900
901 /* set up output files */
902 integ_y_out = Asc_IntegOpenYFile();
903 integ_obs_out = Asc_IntegOpenObsFile();
904
905 CONSOLE_DEBUG("RELEASING FILES");
906
907 Asc_IntegReleaseYFile();
908 Asc_IntegReleaseObsFile();
909
910 CONSOLE_DEBUG("WRITING HEADERS");
911
912 /* write headers to yout, obsout and initial points */
913
914 Asc_IntegPrintYHeader(integ_y_out,blsys);
915 status &= Asc_IntegPrintYLine(integ_y_out,blsys);
916 Asc_IntegPrintObsHeader(integ_obs_out,blsys);
917 status &= Asc_IntegPrintObsLine(integ_obs_out,blsys);
918
919 return status;
920 return 0;
921 }
922
923 int Asc_IntegReporterWrite(IntegratorSystem *blsys){
924 /* write out a line of stuff */
925 return Asc_IntegPrintYLine(integ_y_out,blsys);
926 }
927
928 int Asc_IntegReporterWriteObs(IntegratorSystem *blsys){
929 return Asc_IntegPrintObsLine(integ_obs_out,blsys);
930 return 0;
931 }
932
933 int Asc_IntegReporterClose(IntegratorSystem *blsys){
934 /* close the file streams */
935 if (integ_y_out!=NULL) {
936 fclose(integ_y_out);
937 }
938
939 if (integ_obs_out!=NULL) {
940 fclose(integ_obs_out);
941 }
942 return 1;
943 }
944

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22