41 |
@TODO this needs to go away. |
@TODO this needs to go away. |
42 |
*/ |
*/ |
43 |
#define INTEG_DEBUG TRUE |
#define INTEG_DEBUG TRUE |
44 |
/* #define ANALYSE_DEBUG */ |
#define ANALYSE_DEBUG |
45 |
|
|
46 |
/** |
/** |
47 |
Print a debug message with value if INTEG_DEBUG is TRUE. |
Print a debug message with value if INTEG_DEBUG is TRUE. |
79 |
* that maintains this info by backpointers, but oh well until then. |
* that maintains this info by backpointers, but oh well until then. |
80 |
*/ |
*/ |
81 |
#define OBSINDEX g_symbols[2] |
#define OBSINDEX g_symbols[2] |
82 |
/* Integer child. All variables with OBSINDEX !=0 will be recorded in |
/* Integer child. All variables with OBSINDEX !=0 will be sent to the |
83 |
* the blsode output file. Tis someone else's job to grok this output. |
IntegratorOutputWriteObsFn allowing output to a file, graph, console, etc. |
84 |
*/ |
*/ |
85 |
|
|
86 |
|
|
103 |
void integrator_create_engine(IntegratorSystem *sys); |
void integrator_create_engine(IntegratorSystem *sys); |
104 |
void integrator_free_engine(IntegratorSystem *sys); |
void integrator_free_engine(IntegratorSystem *sys); |
105 |
|
|
106 |
static int integrator_analyse_ode(IntegratorSystem *sys); |
IntegratorAnalyseFn integrator_analyse_ode; |
107 |
static int integrator_analyse_dae(IntegratorSystem *sys); |
IntegratorAnalyseFn integrator_analyse_dae; |
108 |
|
|
109 |
typedef void (IntegratorVarVisitorFn)(IntegratorSystem *sys, struct var_variable *var, const int *varindx); |
typedef void (IntegratorVarVisitorFn)(IntegratorSystem *sys, struct var_variable *var, const int *varindx); |
110 |
static void integrator_visit_system_vars(IntegratorSystem *sys,IntegratorVarVisitorFn *visitor); |
static void integrator_visit_system_vars(IntegratorSystem *sys,IntegratorVarVisitorFn *visitor); |
144 |
sys->system = slvsys; |
sys->system = slvsys; |
145 |
sys->instance = inst; |
sys->instance = inst; |
146 |
|
|
147 |
|
sys->engine = INTEG_UNKNOWN; |
148 |
|
sys->internals = NULL; |
149 |
|
|
150 |
sys->states = NULL; sys->derivs = NULL; |
sys->states = NULL; sys->derivs = NULL; |
151 |
sys->dynvars = NULL; sys->obslist = NULL; sys->indepvars = NULL; |
sys->dynvars = NULL; sys->obslist = NULL; sys->indepvars = NULL; |
152 |
|
|
210 |
At present, integrators are all present at compile-time so this is a static |
At present, integrators are all present at compile-time so this is a static |
211 |
list; we just return the list. |
list; we just return the list. |
212 |
*/ |
*/ |
213 |
void integrator_get_engines(IntegratorLookup **listptr){ |
const IntegratorLookup *integrator_get_engines(){ |
214 |
#define S , |
#define S , |
215 |
#define I(N) {INTEG_##N, #N} |
#define I(N,P) {INTEG_##N, P.name} |
216 |
static const IntegratorLookup lookup[] = { |
static const IntegratorLookup list[] = { |
217 |
INTEG_LIST |
INTEG_LIST |
218 |
,{INTEG_UNKNOWN,NULL} |
,{INTEG_UNKNOWN,NULL} |
219 |
}; |
}; |
|
*listptr = lookup; |
|
220 |
#undef S |
#undef S |
221 |
#undef I |
#undef I |
222 |
|
return list; |
223 |
} |
} |
224 |
|
|
225 |
/* return 0 on success */ |
/* return 0 on success */ |
226 |
int integrator_set_engine(IntegratorSystem *sys, IntegratorEngine engine){ |
int integrator_set_engine(IntegratorSystem *sys, IntegratorEngine engine){ |
227 |
|
|
228 |
|
CONSOLE_DEBUG("Setting engine..."); |
229 |
|
|
230 |
/* verify integrator type ok. always passes for nonNULL inst. */ |
/* verify integrator type ok. always passes for nonNULL inst. */ |
231 |
if(engine==INTEG_UNKNOWN){ |
if(engine==INTEG_UNKNOWN){ |
232 |
ERROR_REPORTER_NOLINE(ASC_USER_ERROR |
ERROR_REPORTER_NOLINE(ASC_USER_ERROR |
244 |
integrator_free_engine(sys); |
integrator_free_engine(sys); |
245 |
} |
} |
246 |
sys->engine = engine; |
sys->engine = engine; |
247 |
|
switch(sys->engine){ |
248 |
|
#ifdef ASC_WITH_IDA |
249 |
|
case INTEG_IDA: sys->internals = &integrator_ida_internals; break; |
250 |
|
#endif |
251 |
|
case INTEG_LSODE: sys->internals = &integrator_lsode_internals; break; |
252 |
|
case INTEG_AWW: sys->internals = &integrator_aww_internals; break; |
253 |
|
default: |
254 |
|
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unknown integrator engine"); |
255 |
|
sys->internals = NULL; |
256 |
|
return 1; |
257 |
|
}; |
258 |
|
|
259 |
|
asc_assert(sys->internals); |
260 |
integrator_create_engine(sys); |
integrator_create_engine(sys); |
|
|
|
261 |
return 0; |
return 0; |
262 |
} |
} |
263 |
|
|
270 |
this system. Note that this data is pointed to by sys->enginedata. |
this system. Note that this data is pointed to by sys->enginedata. |
271 |
*/ |
*/ |
272 |
void integrator_free_engine(IntegratorSystem *sys){ |
void integrator_free_engine(IntegratorSystem *sys){ |
273 |
switch(sys->engine){ |
if(sys->engine==INTEG_UNKNOWN)return; |
274 |
case INTEG_LSODE: integrator_lsode_free(sys->enginedata); break; |
if(sys->enginedata){ |
275 |
#ifdef ASC_WITH_IDA |
if(sys->internals){ |
276 |
case INTEG_IDA: integrator_ida_free(sys->enginedata); break; |
(sys->internals->freefn)(sys->enginedata); |
277 |
#endif |
sys->enginedata=NULL; |
278 |
case INTEG_AWW: integrator_aww_free(sys->enginedata); break; |
}else{ |
279 |
default: break; |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to free engine data: no sys->internals"); |
280 |
|
} |
281 |
} |
} |
|
sys->enginedata=NULL; |
|
282 |
} |
} |
283 |
|
|
284 |
/** |
/** |
289 |
during the solve stage (and freed inside integrator_free_engine) |
during the solve stage (and freed inside integrator_free_engine) |
290 |
*/ |
*/ |
291 |
void integrator_create_engine(IntegratorSystem *sys){ |
void integrator_create_engine(IntegratorSystem *sys){ |
292 |
if(sys->enginedata!=NULL)return; |
asc_assert(sys->engine!=INTEG_UNKNOWN); |
293 |
switch(sys->engine){ |
asc_assert(sys->internals); |
294 |
case INTEG_LSODE: integrator_lsode_create(sys); break; |
asc_assert(sys->enginedata==NULL); |
295 |
#ifdef ASC_WITH_IDA |
(sys->internals->createfn)(sys); |
|
case INTEG_IDA: integrator_ida_create(sys); break; |
|
|
#endif |
|
|
case INTEG_AWW: integrator_aww_create(sys); break; |
|
|
default: break; |
|
|
} |
|
296 |
} |
} |
297 |
|
|
298 |
/*------------------------------------------------------------------------------ |
/*------------------------------------------------------------------------------ |
305 |
|
|
306 |
@return 0 on success, 1 on error |
@return 0 on success, 1 on error |
307 |
*/ |
*/ |
308 |
static int integrator_params_default(IntegratorSystem *sys){ |
int integrator_params_default(IntegratorSystem *sys){ |
309 |
switch(sys->engine){ |
asc_assert(sys->engine!=INTEG_UNKNOWN); |
310 |
case INTEG_LSODE: return integrator_lsode_params_default(sys); |
asc_assert(sys->internals); |
311 |
#ifdef ASC_WITH_IDA |
return (sys->internals->paramsdefaultfn)(sys); |
|
case INTEG_IDA: return integrator_ida_params_default(sys); |
|
|
#endif |
|
|
case INTEG_AWW: return integrator_aww_params_default(sys); |
|
|
default: return 0; |
|
|
} |
|
312 |
} |
} |
313 |
|
|
314 |
int integrator_params_get(const IntegratorSystem *sys, slv_parameters_t *parameters){ |
int integrator_params_get(const IntegratorSystem *sys, slv_parameters_t *parameters){ |
371 |
@return 1 on success |
@return 1 on success |
372 |
*/ |
*/ |
373 |
int integrator_analyse(IntegratorSystem *sys){ |
int integrator_analyse(IntegratorSystem *sys){ |
374 |
switch(sys->engine){ |
CONSOLE_DEBUG("Analysing integration system..."); |
375 |
case INTEG_LSODE: return integrator_analyse_ode(sys); |
asc_assert(sys); |
376 |
#ifdef ASC_WITH_IDA |
if(sys->engine==INTEG_UNKNOWN){ |
377 |
case INTEG_IDA: return integrator_analyse_dae(sys); |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"No engine selected: can't analyse"); |
378 |
#endif |
return 0; |
|
case INTEG_AWW: return integrator_aww_analyse(sys); |
|
|
case INTEG_UNKNOWN: |
|
|
ERROR_REPORTER_HERE(ASC_PROG_ERR,"No engine selected: can't analyse"); |
|
|
default: |
|
|
ERROR_REPORTER_HERE(ASC_PROG_ERR |
|
|
,"The selected integration engine (%d) is not available" |
|
|
,sys->engine |
|
|
); |
|
379 |
} |
} |
380 |
return 0; |
asc_assert(sys->engine!=INTEG_UNKNOWN); |
381 |
|
asc_assert(sys->internals); |
382 |
|
return (sys->internals->analysefn)(sys); |
383 |
} |
} |
384 |
|
|
385 |
/** |
/** |
547 |
for(i=0; i<numy; ++i){ |
for(i=0; i<numy; ++i){ |
548 |
asc_assert(sys->ydot[i]==NULL); |
asc_assert(sys->ydot[i]==NULL); |
549 |
} |
} |
550 |
|
|
551 |
|
for(i=0; i<numy; ++i){ |
552 |
|
sys->y_id[i] = 9999999L; |
553 |
|
} |
554 |
|
|
555 |
/* now add variables and their derivatives to 'ydot' and 'y' */ |
/* now add variables and their derivatives to 'ydot' and 'y' */ |
556 |
yindex = 0; |
yindex = 0; |
566 |
assert(info->derivative); |
assert(info->derivative); |
567 |
sys->ydot[yindex] = info->derivative->i; |
sys->ydot[yindex] = info->derivative->i; |
568 |
if(info->varindx >= 0){ |
if(info->varindx >= 0){ |
569 |
|
ASC_ASSERT_RANGE(yindex, -1e7L, 1e7L); |
570 |
sys->y_id[info->varindx] = yindex; |
sys->y_id[info->varindx] = yindex; |
571 |
#ifdef ANALYSE_DEBUG |
#ifdef ANALYSE_DEBUG |
572 |
CONSOLE_DEBUG("y_id[%d] = %d",info->varindx,yindex); |
CONSOLE_DEBUG("y_id[%d] = %d",info->varindx,yindex); |
574 |
} |
} |
575 |
if(info->derivative->varindx >= 0){ |
if(info->derivative->varindx >= 0){ |
576 |
sys->y_id[info->derivative->varindx] = -1-yindex; |
sys->y_id[info->derivative->varindx] = -1-yindex; |
577 |
|
ASC_ASSERT_RANGE(-1-yindex,-numy,0); |
578 |
#ifdef ANALYSE_DEBUG |
#ifdef ANALYSE_DEBUG |
579 |
CONSOLE_DEBUG("y_id[%d] = %d",info->derivative->varindx,-1-yindex); |
CONSOLE_DEBUG("y_id[%d] = %d",info->derivative->varindx,-1-yindex); |
580 |
#endif |
#endif |
584 |
sys->ydot[yindex] = NULL; |
sys->ydot[yindex] = NULL; |
585 |
if(info->varindx >= 0){ |
if(info->varindx >= 0){ |
586 |
sys->y_id[info->varindx] = yindex; |
sys->y_id[info->varindx] = yindex; |
587 |
|
ASC_ASSERT_RANGE(yindex,0,numy); |
588 |
#ifdef ANALYSE_DEBUG |
#ifdef ANALYSE_DEBUG |
589 |
CONSOLE_DEBUG("y_id[%d] = %d",info->varindx,yindex); |
CONSOLE_DEBUG("y_id[%d] = %d",info->varindx,yindex); |
590 |
#endif |
#endif |
639 |
, struct var_variable *var, const int *varindx |
, struct var_variable *var, const int *varindx |
640 |
){ |
){ |
641 |
char *varname; |
char *varname; |
642 |
int y_id; |
long y_id; |
643 |
varname = var_make_name(sys->system, var); |
varname = var_make_name(sys->system, var); |
644 |
if(varindx==NULL){ |
if(varindx==NULL){ |
645 |
fprintf(stderr,".\t%s\n",varname); |
fprintf(stderr,".\t%s\n",varname); |
647 |
return; |
return; |
648 |
} |
} |
649 |
y_id = sys->y_id[*varindx]; |
y_id = sys->y_id[*varindx]; |
650 |
fprintf(stderr,"%d\t%s\t%d", *varindx, varname,y_id); |
|
651 |
|
fprintf(stderr,"%d\t%s\t%ld", *varindx, varname,y_id); |
652 |
ASC_FREE(varname); |
ASC_FREE(varname); |
653 |
if(y_id >= 0){ |
if(y_id >= 0){ |
654 |
fprintf(stderr,"\ty[%d]\t.\n",y_id); |
fprintf(stderr,"\ty[%ld]\t.\n",y_id); |
655 |
}else{ |
}else{ |
656 |
fprintf(stderr,"\t.\tydot[%d]\n",-y_id-1); |
fprintf(stderr,"\t.\tydot[%ld]\n",-y_id-1); |
657 |
} |
} |
658 |
|
|
659 |
|
ASC_ASSERT_LT(*varindx,1e7L); |
660 |
|
ASC_ASSERT_LT(y_id, 9999999L); |
661 |
|
ASC_ASSERT_LT(-9999999L, y_id); |
662 |
} |
} |
663 |
|
|
664 |
void integrator_visit_system_vars(IntegratorSystem *sys,IntegratorVarVisitorFn *visitfn){ |
void integrator_visit_system_vars(IntegratorSystem *sys,IntegratorVarVisitorFn *visitfn){ |
1134 |
unsigned long start_index=0, finish_index=0; |
unsigned long start_index=0, finish_index=0; |
1135 |
assert(sys!=NULL); |
assert(sys!=NULL); |
1136 |
|
|
1137 |
|
assert(sys->internals); |
1138 |
|
assert(sys->engine!=INTEG_UNKNOWN); |
1139 |
|
|
1140 |
nstep = integrator_getnsamples(sys)-1; |
nstep = integrator_getnsamples(sys)-1; |
1141 |
/* check for at least 2 steps and dimensionality of x vs steps here */ |
/* check for at least 2 steps and dimensionality of x vs steps here */ |
1142 |
|
|
1170 |
|
|
1171 |
CONSOLE_DEBUG("RUNNING INTEGRATION..."); |
CONSOLE_DEBUG("RUNNING INTEGRATION..."); |
1172 |
|
|
1173 |
/* now go and run the integrator */ |
return (sys->internals->solvefn)(sys,start_index,finish_index); |
|
switch (sys->engine) { |
|
|
case INTEG_LSODE: |
|
|
return integrator_lsode_solve(sys, start_index, finish_index); break; |
|
|
#ifdef ASC_WITH_IDA |
|
|
case INTEG_IDA: |
|
|
return integrator_ida_solve(sys,start_index, finish_index); break; |
|
|
#endif |
|
|
case INTEG_AWW: |
|
|
return integrator_aww_solve(sys,start_index, finish_index); break; |
|
|
default: |
|
|
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unknown integrator (invalid, or not implemented yet)"); |
|
|
return 0; |
|
|
} |
|
1174 |
} |
} |
1175 |
|
|
1176 |
/*--------------------------------------------------------------- |
/*--------------------------------------------------------------- |