6 |
# include <solver/diffvars.h> |
# include <solver/diffvars.h> |
7 |
# include <solver/slv_stdcalls.h> |
# include <solver/slv_stdcalls.h> |
8 |
# include <solver/block.h> |
# include <solver/block.h> |
9 |
# include <solver/system_impl.h> |
# include <solver/diffvars_impl.h> |
10 |
#include <solver/slvDOF.h> |
#include <solver/slvDOF.h> |
11 |
#endif |
#endif |
12 |
|
|
13 |
#define ANALYSE_DEBUG |
#define ANALYSE_DEBUG |
14 |
|
|
15 |
|
#define VARMSG(MSG) \ |
16 |
|
varname = var_make_name(sys->system,v); \ |
17 |
|
CONSOLE_DEBUG(MSG,varname); \ |
18 |
|
ASC_FREE(varname) |
19 |
|
|
20 |
static int integrator_ida_check_partitioning(IntegratorSystem *sys); |
static int integrator_ida_check_partitioning(IntegratorSystem *sys); |
21 |
static int integrator_ida_check_diffindex(IntegratorSystem *sys); |
static int integrator_ida_check_diffindex(IntegratorSystem *sys); |
22 |
static int integrator_ida_rebuild_diffindex(IntegratorSystem *sys); |
/* static int integrator_ida_rebuild_diffindex(IntegratorSystem *sys); */ |
23 |
|
|
24 |
/** |
/** |
25 |
A var can be non-incident. If it *is* non incident and we're going to |
A var can be non-incident. If it *is* non incident and we're going to |
59 |
SolverDiffVarSequence seq; |
SolverDiffVarSequence seq; |
60 |
int vok; |
int vok; |
61 |
|
|
|
#define VARMSG(MSG) \ |
|
|
varname = var_make_name(sys->system,v); \ |
|
|
CONSOLE_DEBUG(MSG,varname); \ |
|
|
ASC_FREE(varname) |
|
|
|
|
62 |
CONSOLE_DEBUG("BEFORE CHECKING VARS"); |
CONSOLE_DEBUG("BEFORE CHECKING VARS"); |
63 |
integrator_ida_analyse_debug(sys,stderr); |
integrator_ida_analyse_debug(sys,stderr); |
64 |
|
|
68 |
asc_assert(sys->n_y==0); |
asc_assert(sys->n_y==0); |
69 |
|
|
70 |
/* get the the dervative chains from the system */ |
/* get the the dervative chains from the system */ |
71 |
diffvars = sys->system->diffvars; |
diffvars = system_get_diffvars(sys->system); |
72 |
if(diffvars==NULL){ |
if(diffvars==NULL){ |
73 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Derivative structure is empty"); |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Derivative structure is empty"); |
74 |
return 1; |
return 1; |
213 |
asc_assert(sys->ydot==NULL); |
asc_assert(sys->ydot==NULL); |
214 |
asc_assert(sys->y_id== NULL); |
asc_assert(sys->y_id== NULL); |
215 |
|
|
|
CONSOLE_DEBUG("BEFORE MAKING LISTS"); |
|
|
integrator_ida_analyse_debug(sys,stderr); |
|
|
|
|
216 |
/* get the the dervative chains from the system */ |
/* get the the dervative chains from the system */ |
217 |
diffvars = sys->system->diffvars; |
diffvars = system_get_diffvars(sys->system); |
218 |
if(diffvars==NULL){ |
if(diffvars==NULL){ |
219 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Derivative structure is empty"); |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Derivative structure is empty"); |
220 |
return 1; |
return 1; |
268 |
j++; |
j++; |
269 |
} |
} |
270 |
|
|
|
CONSOLE_DEBUG("AFTER MAKING LISTS"); |
|
|
integrator_ida_analyse_debug(sys,stderr); |
|
|
|
|
271 |
return 0; |
return 0; |
272 |
} |
} |
273 |
|
|
321 |
CONSOLE_DEBUG("Creating lists"); |
CONSOLE_DEBUG("Creating lists"); |
322 |
#endif |
#endif |
323 |
|
|
324 |
|
CONSOLE_DEBUG("BEFORE MAKING LISTS"); |
325 |
|
integrator_ida_debug(sys,stderr); |
326 |
|
|
327 |
res = integrator_ida_create_lists(sys); |
res = integrator_ida_create_lists(sys); |
328 |
if(res){ |
if(res){ |
329 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Problem creating lists"); |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Problem creating lists"); |
331 |
} |
} |
332 |
|
|
333 |
#ifdef ANALYSE_DEBUG |
#ifdef ANALYSE_DEBUG |
334 |
CONSOLE_DEBUG("Checking"); |
CONSOLE_DEBUG("Checking lists"); |
335 |
#endif |
#endif |
336 |
|
|
337 |
asc_assert(sys->y); |
asc_assert(sys->y); |
338 |
asc_assert(sys->ydot); |
asc_assert(sys->ydot); |
339 |
asc_assert(sys->y_id); |
asc_assert(sys->y_id); |
340 |
|
|
341 |
integrator_ida_analyse_debug(sys,stderr); |
integrator_ida_debug(sys,stderr); |
342 |
|
|
343 |
if(integrator_ida_check_diffindex(sys)){ |
if(integrator_ida_check_diffindex(sys)){ |
344 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Error with diffindex"); |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Error with diffindex"); |
385 |
#endif |
#endif |
386 |
|
|
387 |
/* get the the dervative chains from the system */ |
/* get the the dervative chains from the system */ |
388 |
diffvars = sys->system->diffvars; |
diffvars = system_get_diffvars(sys->system); |
389 |
|
|
390 |
/* check the indep var is same as was located elsewhere */ |
/* check the indep var is same as was located elsewhere */ |
391 |
if(diffvars->nindep>1){ |
if(diffvars->nindep>1){ |
399 |
return 5; |
return 5; |
400 |
} |
} |
401 |
|
|
402 |
|
#ifdef ANALYSE_DEBUG |
403 |
|
CONSOLE_DEBUG("Collecting observed variables"); |
404 |
|
#endif |
405 |
|
|
406 |
/* get the observations */ |
/* get the observations */ |
407 |
/** @TODO this should use a 'problem provider' API instead of static data |
/** @TODO this should use a 'problem provider' API instead of static data |
408 |
from the system object */ |
from the system object */ |
415 |
ASC_FREE(varname); |
ASC_FREE(varname); |
416 |
} |
} |
417 |
|
|
|
/* - 'y' list as [ya|yd] */ |
|
|
/* - sparsity pattern for dF/dy and dF/dy' */ |
|
|
/* - sparsity pattern for union of above */ |
|
|
/* - block decomposition based on above */ |
|
|
/* - block decomposition results in reordering of y and y' */ |
|
|
/* - boundaries (optional) */ |
|
|
/* ERROR_REPORTER_HERE(ASC_PROG_ERR,"Implementation incomplete"); |
|
|
return -1; */ |
|
|
|
|
418 |
return 0; |
return 0; |
419 |
} |
} |
420 |
|
|
522 |
return res; |
return res; |
523 |
} |
} |
524 |
|
|
525 |
|
/* return 0 on succes */ |
526 |
|
static int check_dups(struct var_variable **list,int n,int allownull){ |
527 |
|
int i,j; |
528 |
|
struct var_variable *v; |
529 |
|
for(i=0; i< n; ++i){ |
530 |
|
v=list[i]; |
531 |
|
if(v==NULL){ |
532 |
|
if(allownull)continue; |
533 |
|
else return 2; |
534 |
|
} |
535 |
|
for(j=0; j<i-1;++j){ |
536 |
|
if(list[j]==NULL)continue; |
537 |
|
if(v==list[j])return 1; |
538 |
|
} |
539 |
|
} |
540 |
|
return 0; |
541 |
|
} |
542 |
|
|
543 |
|
/* |
544 |
|
We are going to check that |
545 |
|
|
546 |
|
- n_y in range (0,n_vars) |
547 |
|
- no duplicates anywhere in the varlist |
548 |
|
- no duplicates in non-NULL elements of ydot |
549 |
|
|
550 |
|
- first n_y vars in solver's var list match those in vector y and match the non-deriv filter. |
551 |
|
- var_sindex for first n_y vars match their position the the solver's var list |
552 |
|
|
553 |
|
- ydot contains n_ydot non-NULL elements, each match the deriv filter. |
554 |
|
- vars in solver's var list positions [n_y,n_y+n_ydot) all match deriv filter |
555 |
|
|
556 |
|
- y_id contains n_ydot elements, with int values in range [0,n_y) |
557 |
|
- var_sindex(ydot[y_id[i]]) - n_y == i for i in [0,n_ydot) |
558 |
|
|
559 |
|
- all the vars [n_y+n_ydot,n_vars) fail the non-deriv filter and fail the deriv filter. |
560 |
|
*/ |
561 |
static int integrator_ida_check_diffindex(IntegratorSystem *sys){ |
static int integrator_ida_check_diffindex(IntegratorSystem *sys){ |
562 |
int i, nv, err = 0; |
int i, n_vars, n_ydot=0; |
563 |
struct var_variable **vlist; |
struct var_variable **list, *v; |
564 |
|
char *varname; |
565 |
int diffindex; |
int diffindex; |
566 |
|
const char *msg; |
567 |
|
|
568 |
CONSOLE_DEBUG("Checking diffindex vector"); |
CONSOLE_DEBUG("Checking diffindex vector"); |
569 |
|
|
570 |
if(sys->y_id == NULL){ |
if(sys->y_id == NULL || sys->y == NULL || sys->ydot == NULL){ |
571 |
CONSOLE_DEBUG("y_id not allocated"); |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"list(s) NULL"); |
572 |
|
return 1; |
573 |
|
} |
574 |
|
|
575 |
|
list = slv_get_solvers_var_list(sys->system); |
576 |
|
n_vars = slv_get_num_solvers_vars(sys->system); |
577 |
|
|
578 |
|
if(check_dups(list,n_vars,FALSE)){ |
579 |
|
ERROR_REPORTER_HERE(ASC_PROG_ERR,"duplicates or NULLs in solver's var list"); |
580 |
return 1; |
return 1; |
581 |
} |
} |
582 |
|
|
583 |
vlist = slv_get_solvers_var_list(sys->system); |
if(check_dups(sys->ydot,n_vars,TRUE)){ |
584 |
nv = slv_get_num_solvers_vars(sys->system); |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"duplicates in ydot vector"); |
585 |
|
return 1; |
586 |
|
} |
587 |
|
|
588 |
for(i=0; i<nv; ++i){ |
/* check n_y in range */ |
589 |
if(var_deriv(vlist[i])){ |
if(sys->n_y <= 0 || sys->n_y >= n_vars){ |
590 |
if(i < sys->n_y){ |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"n_y = %d invalid (n_vars = %d)",sys->n_y, n_vars); |
591 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Deriv in wrong position"); |
return 1; |
592 |
err++; |
} |
593 |
}else{ |
|
594 |
if(var_sindex(vlist[i])!=i){ |
/* check first n_y vars */ |
595 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Deriv var with incorrect sindex"); |
for(i=0; i < sys->n_y; ++i){ |
596 |
err++; |
v = list[i]; |
597 |
} |
if(!var_apply_filter(v, &integrator_ida_nonderiv)){ |
598 |
diffindex = sys->y_id[i - sys->n_y]; |
msg = "'%s' (in first n_y vars) fails non-deriv filter"; goto finish; |
599 |
if(diffindex >= sys->n_y){ |
}else if(v != sys->y[i]){ |
600 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Diff y_id[%d] value too big",i-sys->n_y); |
msg = "'%s' not matched in y vector"; goto finish; |
601 |
err++; |
}else if(var_sindex(v) != i){ |
602 |
} |
msg = "'%s' has wrong var_sindex"; goto finish; |
603 |
if(var_sindex(vlist[diffindex])!=diffindex){ |
} |
604 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Diff var with incorrect sindex"); |
/* meets filter, matches in y vector, has correct var_sindex. */ |
605 |
err++; |
} |
606 |
} |
|
607 |
} |
/* count non-NULLs in ydot */ |
608 |
}else{ |
for(i=0; i < sys->n_y; ++i){ |
609 |
if(i!=var_sindex(vlist[i])){ |
v = sys->ydot[i]; |
610 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"var_sindex incorrect"); |
if(v!=NULL){ |
611 |
err++; |
if(var_sindex(v) < sys->n_y){ |
612 |
|
msg = "'%s' has var_sindex < n_y"; goto finish; |
613 |
|
}else if(!var_apply_filter(v,&integrator_ida_deriv)){ |
614 |
|
msg = "'%s' (in next n_ydot vars) fails deriv filter"; goto finish; |
615 |
} |
} |
616 |
|
/* lies beyond first n_y vars, match deriv filter */ |
617 |
|
n_ydot++; |
618 |
} |
} |
619 |
} |
} |
620 |
if(err){ |
|
621 |
CONSOLE_DEBUG("Errors found in diffindex"); |
/* check that vars [n_y, n_y+n_ydot) in solver's var list match the deriv filter */ |
622 |
|
for(i=sys->n_y; i< sys->n_y + n_ydot; ++i){ |
623 |
|
v = list[i]; |
624 |
|
if(!var_apply_filter(v,&integrator_ida_deriv)){ |
625 |
|
msg = "'%s', in range [n_y,n_y+n_ydot), fails deriv filter"; goto finish; |
626 |
|
} |
627 |
|
} |
628 |
|
|
629 |
|
/* check values in y_id are ints int range [0,n_y), and that they point to correct vars */ |
630 |
|
for(i=0; i<n_ydot; ++i){ |
631 |
|
if(sys->y_id[i] < 0 || sys->y_id[i] >= sys->n_y){ |
632 |
|
ERROR_REPORTER_HERE(ASC_PROG_ERR,"value of y_id[%d] is out of range",i); |
633 |
|
return 1; |
634 |
|
} |
635 |
|
v = sys->ydot[sys->y_id[i]]; |
636 |
|
if(var_sindex(v) - sys->n_y != i){ |
637 |
|
msg = "'%s' not index correctly from y_id"; goto finish; |
638 |
|
} |
639 |
|
} |
640 |
|
|
641 |
|
/* check remaining vars fail both filters */ |
642 |
|
for(i=sys->n_y + n_ydot; i<n_vars; ++i){ |
643 |
|
v = list[i]; |
644 |
|
if(var_apply_filter(v,&integrator_ida_nonderiv)){ |
645 |
|
msg = "Var '%s' at end meets non-deriv filter, but shouldn't"; goto finish; |
646 |
|
} |
647 |
|
if(var_apply_filter(v,&integrator_ida_deriv)){ |
648 |
|
CONSOLE_DEBUG("position = %d",i); |
649 |
|
msg = "Var '%s' at end meets deriv filter, but shouldn't"; goto finish; |
650 |
|
} |
651 |
} |
} |
652 |
return err; |
|
653 |
|
return 0; |
654 |
|
finish: |
655 |
|
varname = var_make_name(sys->system,v); |
656 |
|
ERROR_REPORTER_HERE(ASC_PROG_ERR,msg,varname); |
657 |
|
ASC_FREE(varname); |
658 |
|
return 1; |
659 |
} |
} |
660 |
|
|
661 |
/** |
/** |