83 |
struct Integ_var_t { |
struct Integ_var_t { |
84 |
long index; |
long index; |
85 |
long type; |
long type; |
86 |
struct var_variable *i; |
struct Integ_var_t *derivative; |
87 |
struct Integ_var_t *derivative_of; |
struct Integ_var_t *derivative_of; |
88 |
struct var_variable *derivative; |
struct var_variable *i; |
89 |
int varindx; /**< index into slv_get_master_vars_list, or -1 if not there */ |
int varindx; /**< index into slv_get_master_vars_list, or -1 if not there */ |
90 |
int isstate; |
int isstate; |
91 |
}; |
}; |
334 |
int i, j; |
int i, j; |
335 |
int numstates; |
int numstates; |
336 |
int numy, nrels; |
int numy, nrels; |
337 |
|
int yindex; |
338 |
int maxderiv; |
int maxderiv; |
339 |
|
|
340 |
CONSOLE_DEBUG("Starting DAE analysis"); |
CONSOLE_DEBUG("Starting DAE analysis"); |
378 |
info = (struct Integ_var_t *)gl_fetch(sys->dynvars, i); |
info = (struct Integ_var_t *)gl_fetch(sys->dynvars, i); |
379 |
if(info->type==1 || info->type==0)numstates++; |
if(info->type==1 || info->type==0)numstates++; |
380 |
if(maxderiv < info->type - 1)maxderiv = info->type - 1; |
if(maxderiv < info->type - 1)maxderiv = info->type - 1; |
381 |
varname = var_make_name(sys->system,info->i); |
/* varname = var_make_name(sys->system,info->i); |
382 |
/* CONSOLE_DEBUG("var[%d] = \"%s\": ode_index = %ld",i,varname,info->type); */ |
CONSOLE_DEBUG("var[%d] = \"%s\": ode_index = %ld",i,varname,info->type); |
383 |
ASC_FREE(varname); |
ASC_FREE(varname); */ |
384 |
} |
} |
385 |
if(maxderiv == 0){ |
if(maxderiv == 0){ |
386 |
ERROR_REPORTER_HERE(ASC_USER_ERROR,"No derivatives found (check 'ode_type' values for your vars)."); |
ERROR_REPORTER_HERE(ASC_USER_ERROR,"No derivatives found (check 'ode_type' values for your vars)."); |
387 |
return 0; |
return 0; |
388 |
} |
} |
389 |
if(numstates == 0){ |
if(maxderiv > 1){ |
390 |
ERROR_REPORTER_HERE(ASC_USER_ERROR,"No states found (check 'odetype' values for your vars)."); |
ERROR_REPORTER_HERE(ASC_USER_ERROR,"Higher-order derivatives found. You must provide a reduced order formulation for your model."); |
391 |
return 0; |
return 0; |
392 |
} |
} |
393 |
|
|
|
|
|
394 |
if(!integrator_check_indep_var(sys))return 0; |
if(!integrator_check_indep_var(sys))return 0; |
395 |
|
|
396 |
gl_sort(sys->dynvars,(CmpFunc)Integ_CmpDynVars); |
gl_sort(sys->dynvars,(CmpFunc)Integ_CmpDynVars); |
397 |
|
|
398 |
/* |
fprintf(stderr,"\n\n\nSORTED VARS\n"); |
399 |
for(i=1; i<=gl_length(sys->dynvars); ++i){ |
for(i=1; i<=gl_length(sys->dynvars); ++i){ |
400 |
info = (struct Integ_var_t *)gl_fetch(sys->dynvars, i); |
info = (struct Integ_var_t *)gl_fetch(sys->dynvars, i); |
401 |
varname = var_make_name(sys->system,info->i); |
varname = var_make_name(sys->system,info->i); |
402 |
// CONSOLE_DEBUG("var[%d] = \"%s\": ode_type = %ld",i,varname,info->type); |
CONSOLE_DEBUG("var[%d] = \"%s\": ode_type = %ld",i,varname,info->type); |
403 |
ASC_FREE(varname); |
ASC_FREE(varname); |
404 |
}*/ |
} |
|
|
|
|
/* link up derivative chains */ |
|
405 |
|
|
406 |
|
/* link up variables with their derivatives */ |
407 |
prev = NULL; |
prev = NULL; |
408 |
for(i=1; i<=gl_length(sys->dynvars); ++i){ /* why does gl_list index with base 1??? */ |
for(i=1; i<=gl_length(sys->dynvars); ++i){ /* why does gl_list index with base 1??? */ |
409 |
info = (struct Integ_var_t *)gl_fetch(sys->dynvars, i); |
info = (struct Integ_var_t *)gl_fetch(sys->dynvars, i); |
410 |
info->derivative = NULL; |
|
|
|
|
|
derivname = var_make_name(sys->system,info->i); |
|
|
if(prev!=NULL){ |
|
|
varname = var_make_name(sys->system,prev->i); |
|
|
}else{ |
|
|
varname = NULL; |
|
|
} |
|
|
/* CONSOLE_DEBUG("current = \"%s\", previous = \"%s\"",derivname,varname); */ |
|
|
ASC_FREE(derivname); |
|
|
if(varname)ASC_FREE(varname); |
|
|
|
|
411 |
if(info->type == INTEG_STATE_VAR || info->type == INTEG_ALGEBRAIC_VAR){ |
if(info->type == INTEG_STATE_VAR || info->type == INTEG_ALGEBRAIC_VAR){ |
412 |
varname = var_make_name(sys->system,info->i); |
varname = var_make_name(sys->system,info->i); |
413 |
/* CONSOLE_DEBUG("Var \"%s\" is not a derivative",varname); */ |
CONSOLE_DEBUG("Var \"%s\" is an algebraic variable",varname); |
414 |
ASC_FREE(varname); |
ASC_FREE(varname); |
|
info->derivative_of = NULL; |
|
415 |
info->type = INTEG_STATE_VAR; |
info->type = INTEG_STATE_VAR; |
416 |
|
info->derivative_of = NULL; |
417 |
}else{ |
}else{ |
418 |
if(prev==NULL || info->index != prev->index){ |
if(prev==NULL || info->index != prev->index){ |
419 |
/* CONSOLE_DEBUG("current current type = %ld",info->type); */ |
/* derivative, but without undifferentiated var present in model */ |
|
/* if(prev!=NULL){ |
|
|
CONSOLE_DEBUG("current index = %ld, previous = %ld",info->index,prev->index); |
|
|
}else{ |
|
|
CONSOLE_DEBUG("current index = %ld, current type = %ld",info->index,info->type); |
|
|
} */ |
|
420 |
varname = var_make_name(sys->system,info->i); |
varname = var_make_name(sys->system,info->i); |
421 |
ERROR_REPORTER_HERE(ASC_USER_ERROR,"Derivative %d of \"%s\" is present without its un-differentiated equivalent" |
ERROR_REPORTER_HERE(ASC_USER_ERROR,"Derivative %d of \"%s\" is present without its un-differentiated equivalent" |
422 |
, info->type-1 |
, info->type-1 |
425 |
ASC_FREE(varname); |
ASC_FREE(varname); |
426 |
return 0; |
return 0; |
427 |
}else if(info->type != prev->type + 1){ |
}else if(info->type != prev->type + 1){ |
428 |
|
/* derivative, but missing the next-lower-order derivative */ |
429 |
derivname = var_make_name(sys->system,info->i); |
derivname = var_make_name(sys->system,info->i); |
430 |
varname = var_make_name(sys->system,prev->i); |
varname = var_make_name(sys->system,prev->i); |
431 |
ERROR_REPORTER_HERE(ASC_USER_ERROR |
ERROR_REPORTER_HERE(ASC_USER_ERROR |
438 |
ASC_FREE(derivname); |
ASC_FREE(derivname); |
439 |
return 0; |
return 0; |
440 |
}else{ |
}else{ |
441 |
|
/* variable with derivative */ |
442 |
varname = var_make_name(sys->system,prev->i); |
varname = var_make_name(sys->system,prev->i); |
443 |
derivname = var_make_name(sys->system,info->i); |
derivname = var_make_name(sys->system,info->i); |
444 |
CONSOLE_DEBUG("Var \"%s\" is the derivative of \"%s\"",derivname,varname); |
CONSOLE_DEBUG("Var \"%s\" is the derivative of \"%s\"",derivname,varname); |
445 |
ASC_FREE(varname); |
ASC_FREE(varname); |
446 |
ASC_FREE(derivname); |
ASC_FREE(derivname); |
447 |
info->derivative_of = prev; |
info->derivative_of = prev; |
|
numy++; |
|
448 |
} |
} |
449 |
} |
} |
450 |
prev = info; |
prev = info; |
451 |
} |
} |
452 |
|
|
453 |
/* record which vars have derivatives and which don't */ |
/* record which vars have derivatives and which don't, and count 'states' */ |
|
for(i=1; i<=gl_length(sys->dynvars); ++i){ |
|
|
info = (struct Integ_var_t *)gl_fetch(sys->dynvars, i); |
|
|
if(info->derivative_of){ |
|
|
info->derivative_of->derivative = info->i; |
|
|
/* varname = var_make_name(sys->system,info->derivative_of->i); |
|
|
derivname = var_make_name(sys->system,info->derivative_of->derivative); |
|
|
CONSOLE_DEBUG("Var \"%s\" is the derivative of \"%s\"",derivname,varname); |
|
|
ASC_FREE(varname); |
|
|
ASC_FREE(derivname); */ |
|
|
} |
|
|
} |
|
|
|
|
|
CONSOLE_DEBUG("Indentifying states..."); |
|
|
|
|
|
/* count numy: either it's a state, or it has a higher-order derivative */ |
|
454 |
numy = 0; |
numy = 0; |
455 |
for(i=1; i<=gl_length(sys->dynvars); ++i){ |
for(i=1; i<=gl_length(sys->dynvars); ++i){ |
456 |
info = (struct Integ_var_t *)gl_fetch(sys->dynvars, i); |
info = (struct Integ_var_t *)gl_fetch(sys->dynvars, i); |
457 |
if(info->type == INTEG_STATE_VAR || info->type == INTEG_ALGEBRAIC_VAR || info->derivative != NULL){ |
if(info->derivative_of){ |
458 |
varname = var_make_name(sys->system,info->i); |
info->derivative_of->derivative = info; |
|
if(var_fixed(info->i)){ |
|
|
CONSOLE_DEBUG("Var \"%s\" is a FIXED state variable",varname); |
|
|
}else{ |
|
|
CONSOLE_DEBUG("Var \"%s\" is a state variable",varname); |
|
|
} |
|
|
ASC_FREE(varname); |
|
|
info->isstate = 1; |
|
|
numy++; |
|
459 |
}else{ |
}else{ |
460 |
varname = var_make_name(sys->system,info->i); |
numy++; |
|
CONSOLE_DEBUG("Var \"%s\" is a NON-STATE derivative",varname); |
|
|
ASC_FREE(varname); |
|
|
info->isstate = 0; |
|
461 |
} |
} |
462 |
} |
} |
463 |
|
|
464 |
/* |
/* allocate storage for the 'y' and 'ydot' arrays */ |
|
create lists 'y' and 'ydot'. some elements of ydot don't correspond |
|
|
to variables in our model: these are the algebraic vars. |
|
|
*/ |
|
|
|
|
|
CONSOLE_DEBUG("Identified %d state variables", numy); |
|
|
|
|
465 |
sys->y = ASC_NEW_ARRAY(struct var_variable *,numy); |
sys->y = ASC_NEW_ARRAY(struct var_variable *,numy); |
466 |
sys->ydot = ASC_NEW_ARRAY(struct var_variable *,numy); |
sys->ydot = ASC_NEW_ARRAY(struct var_variable *,numy); |
467 |
|
sys->y_id = ASC_NEW_ARRAY(int, slv_get_num_master_vars(sys->system)); |
468 |
|
|
469 |
/* |
/* now add variables and their derivatives to 'ydot' and 'y' */ |
470 |
at this point we know there are no missing derivatives etc, so we |
yindex = 0; |
471 |
can use (i-1) as the index into y and ydot. any variable with |
|
472 |
'derivative_of' set to null is a state variable... but it might already |
for(i=1; i<=gl_length(sys->dynvars); ++i){ |
|
be getting added |
|
|
*/ |
|
|
for(j=0, i=1; i<=gl_length(sys->dynvars); ++i){ |
|
|
info = (struct Integ_var_t *)gl_fetch(sys->dynvars, i); |
|
|
if(!info->isstate)continue; |
|
|
varname = var_make_name(sys->system,info->i); |
|
|
if(info->derivative == NULL){ |
|
|
CONSOLE_DEBUG("Pure algebraic: %s",varname); |
|
|
sys->y[j] = info->i; /* a pure algebraic variable */ |
|
|
sys->ydot[j] = NULL; |
|
|
}else{ |
|
|
CONSOLE_DEBUG("Differential variable: %s",varname); |
|
|
sys->y[j] = info->i; /* a variable whose derivative is present in the model */ |
|
|
sys->ydot[j] = info->derivative; |
|
|
} |
|
|
ASC_FREE(varname); |
|
|
++j; |
|
|
} |
|
|
|
|
|
/* |
|
|
set up the y_id table so that given a 'variable number' from relman_diff2, |
|
|
we can work out where that fits in our y and ydot vectors. |
|
|
|
|
|
There's something a bit fishy about fetching the varlist at this late stage... |
|
|
*/ |
|
|
|
|
|
varlist = slv_get_solvers_var_list(sys->system); |
|
|
nvarlist = slv_get_num_solvers_vars(sys->system); |
|
|
|
|
|
CONSOLE_DEBUG("WORKING THROUGH THE SOLVER'S VAR LIST %d",nvarlist); |
|
|
|
|
|
sys->y_id = ASC_NEW_ARRAY(long, nvarlist); |
|
|
for(i=0; i< nvarlist; ++i){ |
|
|
sys->y_id[i] = -2; |
|
|
} |
|
|
|
|
|
CONSOLE_DEBUG("WORKING THROUGH %ld DYNVARS",gl_length(sys->dynvars)); |
|
|
|
|
|
for(i=1; i <= gl_length(sys->dynvars); ++i){ |
|
473 |
info = (struct Integ_var_t *)gl_fetch(sys->dynvars, i); |
info = (struct Integ_var_t *)gl_fetch(sys->dynvars, i); |
474 |
sys->y_id[info->varindx] = i; |
if(info->derivative_of)continue; |
475 |
varname = var_make_name(sys->system,info->i); |
if(info->derivative){ |
476 |
if(info->varindx > 0){ |
sys->y[yindex] = info->i; |
477 |
CONSOLE_DEBUG("Variable dynvars[%d] = y_id[%d] = '%s'",i,info->varindx,varname); |
sys->ydot[yindex] = info->derivative->i; |
478 |
|
if(info->varindx >= 0){ |
479 |
|
sys->y_id[info->varindx] = yindex; |
480 |
|
CONSOLE_DEBUG("y_id[%d] = %d",info->varindx,yindex); |
481 |
|
} |
482 |
|
if(info->derivative->varindx >= 0){ |
483 |
|
sys->y_id[info->derivative->varindx] = -1-yindex; |
484 |
|
CONSOLE_DEBUG("y_id[%d] = %d",info->derivative->varindx,-1-yindex); |
485 |
|
} |
486 |
}else{ |
}else{ |
487 |
CONSOLE_DEBUG("VARIABLE dynvars[%d] = y_id[%d] = '%s' NOT FOUND IN VARLIST",i,info->varindx,varname); |
sys->y[yindex] = info ->i; |
488 |
} |
sys->ydot[yindex] = NULL; |
489 |
ASC_FREE(varname); |
if(info->varindx >= 0){ |
490 |
} |
sys->y_id[info->varindx] = yindex; |
491 |
for(i=0; i< nvarlist; ++i){ |
CONSOLE_DEBUG("y_id[%d] = %d",info->varindx,yindex); |
492 |
if(sys->y_id[i] < 0){ |
} |
|
varname = var_make_name(sys->system,varlist[i]); |
|
|
CONSOLE_DEBUG("UNCONNECTED SOLVER VAR varlist[%d] = '%s' (%s)",i,varname,var_fixed(varlist[i])?"fixed":"not fixed"); |
|
|
ASC_FREE(varname); |
|
493 |
} |
} |
494 |
|
yindex++; |
495 |
} |
} |
496 |
|
|
497 |
nrels = slv_get_num_solvers_rels(sys->system); |
nrels = slv_get_num_solvers_rels(sys->system); |
503 |
return 0; |
return 0; |
504 |
} |
} |
505 |
|
|
506 |
|
CONSOLE_DEBUG("THERE ARE %d VARIABLES IN THE INTEGRATION SYSTEM",numy); |
507 |
|
|
508 |
sys->n_y = numy; |
sys->n_y = numy; |
509 |
|
|
510 |
if(!integrator_sort_obs_vars(sys))return 0; |
if(!integrator_sort_obs_vars(sys))return 0; |
717 |
} |
} |
718 |
|
|
719 |
/** |
/** |
720 |
|
Check sanity of the independent variable. |
721 |
|
|
722 |
@return 1 on success |
@return 1 on success |
723 |
*/ |
*/ |
724 |
static int integrator_check_indep_var(IntegratorSystem *sys){ |
static int integrator_check_indep_var(IntegratorSystem *sys){ |
803 |
CONSOLE_DEBUG("VARIABLE IS NOT ACTIVE"); |
CONSOLE_DEBUG("VARIABLE IS NOT ACTIVE"); |
804 |
return; |
return; |
805 |
} |
} |
806 |
|
|
807 |
|
/* only non-fixed variables are accepted */ |
808 |
if(!var_fixed(var)){ |
if(!var_fixed(var)){ |
809 |
/* get the ode_type and ode_id of this solver_var */ |
/* get the ode_type and ode_id of this solver_var */ |
810 |
type = DynamicVarInfo(var,&index); |
type = DynamicVarInfo(var,&index); |
818 |
INTEG_ADD_TO_LIST(info,type,index,var,varindx,sys->dynvars); |
INTEG_ADD_TO_LIST(info,type,index,var,varindx,sys->dynvars); |
819 |
} |
} |
820 |
} |
} |
821 |
#if 1 |
#if 0 |
822 |
else{ |
else{ |
823 |
/* fixed variable, only include it if ode_type == 1 */ |
/* fixed variable, only include it if ode_type == 1 */ |
824 |
type = DynamicVarInfo(var,&index); |
type = DynamicVarInfo(var,&index); |
825 |
if(type==INTEG_STATE_VAR){ |
if(type==INTEG_STATE_VAR){ |