/[ascend]/trunk/base/generic/integrator/idaanalyse.c
ViewVC logotype

Contents of /trunk/base/generic/integrator/idaanalyse.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1250 - (show annotations) (download) (as text)
Sat Jan 27 04:50:35 2007 UTC (16 years, 4 months ago) by johnpye
File MIME type: text/x-csrc
File size: 19158 byte(s)
Fixed idaanalyse some more. Maybe it's even right now :-)
1 #include "idaanalyse.h"
2
3 #include <utilities/ascPanic.h>
4
5 #ifdef ASC_IDA_NEW_ANALYSE
6 # include <solver/diffvars.h>
7 # include <solver/slv_stdcalls.h>
8 # include <solver/block.h>
9 # include <solver/diffvars_impl.h>
10 #include <solver/slvDOF.h>
11 #endif
12
13 #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);
21 static int integrator_ida_check_diffindex(IntegratorSystem *sys);
22 /* 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
26 keep it, it will have to have derivative that *is* incident, and that
27 meets the following filter.
28
29 If it doesn't have a valid derivative (eg the derivative is fixed, or
30 the variable doesn't HAVE a derivative), we will mark the non-deriv
31 var non-ACTIVE, so anyway it will end up meeting this filter after we've
32 run integrator_ida_check_vars.
33 */
34 const var_filter_t integrator_ida_nonderiv = {
35 VAR_SVAR | VAR_ACTIVE | VAR_FIXED | VAR_DERIV,
36 VAR_SVAR | VAR_ACTIVE | 0 | 0
37 };
38
39 const var_filter_t integrator_ida_deriv = {
40 VAR_SVAR | VAR_INCIDENT | VAR_ACTIVE | VAR_FIXED | VAR_DERIV,
41 VAR_SVAR | VAR_INCIDENT | VAR_ACTIVE | 0 | VAR_DERIV
42 };
43
44 const rel_filter_t integrator_ida_rel = {
45 REL_INCLUDED | REL_EQUALITY | REL_ACTIVE,
46 REL_INCLUDED | REL_EQUALITY | REL_ACTIVE
47 };
48
49 /**
50 Check derivative chains: if a var or derivative is inelligible,
51 follow down the chain fixing & setting zero any derivatives.
52 */
53 static int integrator_ida_check_vars(IntegratorSystem *sys){
54 const SolverDiffVarCollection *diffvars;
55 char *varname;
56 int n_y = 0;
57 int i, j;
58 struct var_variable *v;
59 SolverDiffVarSequence seq;
60 int vok;
61
62 CONSOLE_DEBUG("BEFORE CHECKING VARS");
63 integrator_ida_analyse_debug(sys,stderr);
64
65 /* we shouldn't have allocated these yet: just be sure */
66 asc_assert(sys->y==NULL);
67 asc_assert(sys->ydot==NULL);
68 asc_assert(sys->n_y==0);
69
70 /* get the the dervative chains from the system */
71 diffvars = system_get_diffvars(sys->system);
72 if(diffvars==NULL){
73 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Derivative structure is empty");
74 return 1;
75 }
76
77 system_var_list_debug(sys->system);
78
79 /* add the variables from the derivative chains */
80 for(i=0; i<diffvars->nseqs; ++i){
81 seq = diffvars->seqs[i];
82 asc_assert(seq.n >= 1);
83 v = seq.vars[0];
84
85 vok = var_apply_filter(v,&integrator_ida_nonderiv);
86
87 if(vok && !var_incident(v)){
88 VARMSG("good var '%s' is not incident");
89 /* var meets our filter, but perhaps it's not incident? */
90 if(seq.n == 1 || var_apply_filter(seq.vars[1],&integrator_ida_nonderiv)){
91 VARMSG("DEACTIVATING NON-INCIDENT VAR '%s' (NO DERIVATIVE)");
92 var_set_active(v,0);
93 vok = 0;
94 }else{
95 VARMSG("'%s' has a derivative that's OK");
96 ERROR_REPORTER_HERE(ASC_USER_ERROR,"Non-incident var with an incident derivative. ASCEND can't handle this case at the moment, but we hope to fix it.");
97 return 1;
98 }
99 }
100
101 if(!vok){
102 VARMSG("'%s' fails non-deriv filter");
103 for(j=1;j<seq.n;++j){
104 v = seq.vars[j];
105 var_set_active(v,FALSE);
106 var_set_value(v,0);
107 VARMSG("Derivative '%s' SET ZERO AND INACTIVE");
108 }
109 continue;
110 }
111
112 VARMSG("We will use var '%s'");
113 if(seq.n > 2){
114 varname = var_make_name(sys->system,v);
115 ERROR_REPORTER_HERE(ASC_USER_ERROR,"Too-long derivative chain with var '%s'",varname);
116 ASC_FREE(varname);
117 return 2;
118 }else if(seq.n==2){
119 /* diff var */
120 if(var_apply_filter(seq.vars[1],&integrator_ida_deriv)){
121 /* add the diff & deriv vars to the lists */
122 n_y++;
123 VARMSG("Added diff var '%s'");
124 v = seq.vars[1]; VARMSG("and its derivative '%s'");
125 continue;
126 }
127 VARMSG("Diff var '%s' being converted to alg var...");
128 v = seq.vars[1]; VARMSG("...because deriv var '%s' fails filter");
129 /* fall through */
130 }
131
132 VARMSG("Adding '%s' to algebraic");
133 n_y++;
134 }
135
136 /* we assert that all vars in y meet the integrator_ida_nonderiv filter */
137 /* we assert that all vars in ydot meet the integrator_ida_deriv filter */
138
139 CONSOLE_DEBUG("Found %d good non-derivative vars", n_y);
140 sys->n_y = n_y;
141
142 return 0;
143 }
144
145
146 /**
147 Sort the lists. First we will put the non-derivative vars, then we will
148 put the derivative vars. Then we will put all the others.
149 */
150 static int integrator_ida_sort_rels_and_vars(IntegratorSystem *sys){
151 int ny1, nydot, nr;
152
153
154 CONSOLE_DEBUG("BEFORE SORTING RELS AND VARS");
155 integrator_ida_analyse_debug(sys,stderr);
156
157 /* we should not have allocated y or ydot yet */
158 asc_assert(sys->y==NULL && sys->ydot==NULL);
159
160 /* but we should have found some variables (and know how many) */
161 asc_assert(sys->n_y);
162
163 if(system_cut_vars(sys->system, 0, &integrator_ida_nonderiv, &ny1)){
164 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Problem cutting non-derivs");
165 return 1;
166 }
167
168 CONSOLE_DEBUG("cut_vars: ny1 = %d, sys->n_y = %d",ny1,sys->n_y);
169 asc_assert(ny1 == sys->n_y);
170
171 if(system_cut_vars(sys->system, ny1, &integrator_ida_deriv, &nydot)){
172 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Problem cutting derivs");
173 return 1;
174 }
175
176 if(system_cut_rels(sys->system, 0, &integrator_ida_rel, &nr)){
177 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Problem cutting derivs");
178 return 1;
179 }
180
181 if(ny1 != nr){
182 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Problem is not square (ny = %d, nr = %d)",ny1,nr);
183 return 2;
184 }
185
186 return 0;
187 }
188
189 /**
190 Build up the lists 'ydot' and 'y_id.
191 'ydot' allows us to find the derivative of a variable given its sindex.
192 'y_id' allows us to locate the variable of a derivative given its sindex.
193
194 Hence
195 y_id[var_sindex(derivvar)-sys->n_y] = var_sindex(diffvar)
196 ydot[var_sindex(diffvar)] = derivvar (or NULL if diffvar is algebraic)
197
198 Note that there is 'shifting' required when looking up y_id.
199
200 Note that we want to get rid of 'y' but for the moment we are also assigning
201 that. We want to be rid of it because if the vars are ordered correctly
202 it shouldn't be needed.
203 */
204 static int integrator_ida_create_lists(IntegratorSystem *sys){
205 const SolverDiffVarCollection *diffvars;
206 int i, j;
207 struct var_variable *v;
208 char *varname;
209
210 SolverDiffVarSequence seq;
211
212 asc_assert(sys->y==NULL);
213 asc_assert(sys->ydot==NULL);
214 asc_assert(sys->y_id== NULL);
215
216 /* get the the dervative chains from the system */
217 diffvars = system_get_diffvars(sys->system);
218 if(diffvars==NULL){
219 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Derivative structure is empty");
220 return 1;
221 }
222
223 /* allocate space (more than enough) */
224 sys->y = ASC_NEW_ARRAY(struct var_variable *,sys->n_y);
225 sys->ydot = ASC_NEW_ARRAY_CLEAR(struct var_variable *,sys->n_y);
226 sys->n_ydot = 0;
227
228 CONSOLE_DEBUG("Passing through chains...");
229
230 /* create the lists y and ydot, ignoring 'bad' vars */
231 for(i=0; i<diffvars->nseqs; ++i){
232 CONSOLE_DEBUG("i = %d",i);
233
234 seq = diffvars->seqs[i];
235 asc_assert(seq.n >= 1);
236 v = seq.vars[0];
237 j = var_sindex(v);
238
239 if(!var_apply_filter(v,&integrator_ida_nonderiv)){
240 continue;
241 }
242
243 sys->y[j] = v;
244 VARMSG("'%s' is good non-deriv");
245
246 if(seq.n > 1 && var_apply_filter(seq.vars[1],&integrator_ida_deriv)){
247 v = seq.vars[1];
248 asc_assert(var_sindex(v) >= sys->n_y);
249 asc_assert(var_sindex(v)-sys->n_y < sys->n_y);
250
251 sys->ydot[j] = v;
252 sys->n_ydot++;
253 VARMSG("'%s' is good deriv");
254 }else{
255 asc_assert(sys->ydot[j]==NULL);
256 }
257 }
258
259 CONSOLE_DEBUG("Found %d good non-derivs",j);
260
261 /* create the list y_id by looking at non-NULLs from ydot */
262 sys->y_id = ASC_NEW_ARRAY(int,sys->n_ydot);
263 for(i=0,j=0; i < sys->n_y; ++i){
264 if(sys->ydot[i]==NULL)continue;
265 v = sys->ydot[i]; VARMSG("deriv '%s'...");
266 v = sys->y[i]; VARMSG("diff '%s'...");
267 sys->y_id[var_sindex(sys->ydot[i]) - sys->n_y] = i;
268 j++;
269 }
270
271 asc_assert(j==sys->n_ydot);
272
273 return 0;
274 }
275
276 /**
277 Perform additional problem analysis to prepare problem for integration with
278 IDA.
279
280 We assume that the analyse_generate_diffvars routine has been called, so
281 that we just need to call slv_get_diffvars to access the derivative
282 chains.
283
284 We can also assume that the independent variable has been found.
285
286 See mailing list, ~Jan 2007.
287
288 Note, the stuff for identifying the static and output sub-problems should
289 be part of integrator.c, not this file. We will assume this is handled
290
291 @return 0 on success
292 @see integrator_analyse
293 */
294 int integrator_ida_analyse(IntegratorSystem *sys){
295 int res;
296 const SolverDiffVarCollection *diffvars;
297 char *varname;
298 int i;
299
300 asc_assert(sys->engine==INTEG_IDA);
301
302 #ifdef ANALYSE_DEBUG
303 CONSOLE_DEBUG("Starting IDA analysis");
304 #endif
305
306 res = integrator_ida_check_vars(sys);
307 if(res){
308 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Problem with vars");
309 return 1;
310 }
311
312 #ifdef ANALYSE_DEBUG
313 CONSOLE_DEBUG("Sorting rels and vars");
314 #endif
315
316 res = integrator_ida_sort_rels_and_vars(sys);
317 if(res){
318 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Problem sorting rels and vars");
319 return 1;
320 }
321
322 #ifdef ANALYSE_DEBUG
323 CONSOLE_DEBUG("Creating lists");
324 #endif
325
326 CONSOLE_DEBUG("BEFORE MAKING LISTS");
327 integrator_ida_debug(sys,stderr);
328
329 res = integrator_ida_create_lists(sys);
330 if(res){
331 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Problem creating lists");
332 return 1;
333 }
334
335 #ifdef ANALYSE_DEBUG
336 CONSOLE_DEBUG("Checking lists");
337 #endif
338
339 asc_assert(sys->y);
340 asc_assert(sys->ydot);
341 asc_assert(sys->y_id);
342
343 integrator_ida_debug(sys,stderr);
344
345 if(integrator_ida_check_diffindex(sys)){
346 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Error with diffindex");
347 return 360;
348 }
349
350 /* the following causes TestIDA.testincidence3 to fail:
351 if(sys->n_y != slv_get_num_solvers_rels(sys->system)){
352 ERROR_REPORTER_HERE(ASC_USER_ERROR,"Problem is not square");
353 return 2;
354 }*/
355
356 #if 0
357 /* check structural singularity for the two IDACalcIC scenarios */
358
359 /* ...(1) FIX the derivatives */
360 CONSOLE_DEBUG("Checking system with derivatives fixed...");
361 for(i=0;i<n_y;++i){
362 if(sys->ydot[i])var_set_fixed(sys->ydot[i],1);
363 }
364
365 slv_block_partition(sys->system);
366 res = integrator_ida_block_check(sys);
367 if(res)return 100 + res;
368
369 /* ...(2) FREE the derivatives, FIX the diffvars */
370 CONSOLE_DEBUG("Checking system with differential variables fixed...");
371 for(i=0;i<n_y;++i){
372 if(sys->ydot[i]){
373 var_set_fixed(sys->ydot[i],0);
374 var_set_fixed(sys->y[i],1);
375 }
376 }
377 slv_block_partition(sys->system);
378 res = integrator_ida_block_check(sys);
379 if(res)return 200 + res;
380
381 /* ...(3) restore as it was, FREE the diffvars */
382 for(i=0;i<n_y;++i){
383 if(sys->ydot[i]){
384 var_set_fixed(sys->y[i],0);
385 }
386 }
387 #endif
388
389 /* get the the dervative chains from the system */
390 diffvars = system_get_diffvars(sys->system);
391
392 /* check the indep var is same as was located elsewhere */
393 if(diffvars->nindep>1){
394 ERROR_REPORTER_HERE(ASC_USER_ERROR,"Multiple variables specified as independent (ode_type=-1)");
395 return 3;
396 }else if(diffvars->nindep<1){
397 ERROR_REPORTER_HERE(ASC_USER_ERROR,"Independent var not set (ode_type=-1)");
398 return 4;
399 }else if(diffvars->indep[0]!=sys->x){
400 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Indep var doesn't match");
401 return 5;
402 }
403
404 #ifdef ANALYSE_DEBUG
405 CONSOLE_DEBUG("Collecting observed variables");
406 #endif
407
408 /* get the observations */
409 /** @TODO this should use a 'problem provider' API instead of static data
410 from the system object */
411 sys->n_obs = diffvars->nobs;
412 sys->obs = ASC_NEW_ARRAY(struct var_variable *,sys->n_obs);
413 for(i=0;i<sys->n_obs;++i){
414 sys->obs[i] = diffvars->obs[i];
415 varname = var_make_name(sys->system,sys->obs[i]);
416 CONSOLE_DEBUG("'%s' is observation",varname);
417 ASC_FREE(varname);
418 }
419
420 return 0;
421 }
422
423 /*------------------------------------------------------------------------------
424 ANALYSIS ROUTINE (new implementation)
425 */
426
427 static int integrator_ida_check_partitioning(IntegratorSystem *sys){
428 long i, nv;
429 int err=0;
430 char *varname;
431 struct var_variable **vlist, *v;
432 nv = slv_get_num_solvers_vars(sys->system);
433 vlist = slv_get_solvers_var_list(sys->system);
434 var_filter_t vf = {VAR_SVAR|VAR_ACTIVE|VAR_INCIDENT|VAR_FIXED
435 ,VAR_SVAR|VAR_ACTIVE|VAR_INCIDENT|0 };
436 for(i=0;i<nv;++i){
437 v=vlist[i];
438 if(!var_apply_filter(v,&vf))continue;
439 varname = var_make_name(sys->system,v);
440 if(!var_deriv(v)){
441 fprintf(stderr,"vlist[%ld] = '%s' (nonderiv)\n",i,varname);
442 if(i>=sys->n_y){
443 ERROR_REPORTER_HERE(ASC_PROG_ERR,"non-deriv var '%s' is not at the start",varname);
444 err++;
445 }
446 }else{
447 fprintf(stderr,"vlist[%ld] = '%s' (derivative)\n",i,varname);
448 if(i<sys->n_y){
449 ERROR_REPORTER_HERE(ASC_PROG_ERR,"deriv var '%s' is not at the end (n_y = %d, i = %d)"
450 ,varname, sys->n_y, i
451 );
452 err++;
453 }
454 }
455 ASC_FREE(varname);
456 }
457 if(err){
458 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Error in IDA partitioning");
459 return 1;
460 }
461 return 0;
462 }
463
464 int integrator_ida_block_check(IntegratorSystem *sys){
465 int res;
466 int dof;
467 #ifdef ANALYSE_DEBUG
468 int *vlist, *vp, i, nv, nv_ok;
469 char *varname;
470 struct var_variable **solversvars;
471
472 var_filter_t vfilt = {
473 VAR_ACTIVE | VAR_INCIDENT | VAR_FIXED,
474 VAR_ACTIVE | VAR_INCIDENT | 0
475 };
476
477 nv = slv_get_num_solvers_vars(sys->system);
478 solversvars = slv_get_solvers_var_list(sys->system);
479 CONSOLE_DEBUG("-------------- nv = %d -------------",nv);
480 for(nv_ok=0, i=0; i < nv; ++i){
481 if(var_apply_filter(solversvars[i],&vfilt)){
482 varname = var_make_name(sys->system,solversvars[i]);
483 fprintf(stderr,"%s\n",varname);
484 ASC_FREE(varname);
485 nv_ok++;
486 }
487 }
488 CONSOLE_DEBUG("----------- got %d ok -------------",nv_ok);
489 #endif
490
491 if(!slvDOF_status(sys->system, &res, &dof)){
492 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to determine DOF status");
493 return -1;
494 }
495 switch(res){
496 case 1: CONSOLE_DEBUG("System is underspecified (%d degrees of freedom)",dof);break;
497 case 2: CONSOLE_DEBUG("System is square"); return 0; /* all OK */
498 case 3: CONSOLE_DEBUG("System is structurally singular"); break;
499 case 4: CONSOLE_DEBUG("System is overspecified"); break;
500 default:
501 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unrecognised slfDOF_status");
502 return -2;
503 }
504
505 #ifdef ANALYSE_DEBUG
506 /* if it was underspecified, what vars could be fixed? */
507 if(res==1){
508 CONSOLE_DEBUG("Need to FIX %d of the following vars:",dof);
509 solversvars = slv_get_solvers_var_list(sys->system);
510 if(!slvDOF_eligible(sys->system, &vlist)){
511 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to det slvDOF_eligble list");
512 return -3;
513 }
514 for(vp=vlist;*vp!=-1;++vp){
515 varname = var_make_name(sys->system, solversvars[*vp]);
516 CONSOLE_DEBUG("Fixable var: %s",varname);
517 ASC_FREE(varname);
518 }
519 CONSOLE_DEBUG("(Found %d fixable vars)",(int)(vp-vlist));
520 return 1;
521 }
522 #endif
523
524 return res;
525 }
526
527 /* return 0 on succes */
528 static int check_dups(struct var_variable **list,int n,int allownull){
529 int i,j;
530 struct var_variable *v;
531 for(i=0; i< n; ++i){
532 v=list[i];
533 if(v==NULL){
534 if(allownull)continue;
535 else return 2;
536 }
537 for(j=0; j<i-1;++j){
538 if(list[j]==NULL)continue;
539 if(v==list[j])return 1;
540 }
541 }
542 return 0;
543 }
544
545 /*
546 We are going to check that
547
548 - n_y in range (0,n_vars)
549 - no duplicates anywhere in the varlist
550 - no duplicates in non-NULL elements of ydot
551
552 - first n_y vars in solver's var list match those in vector y and match the non-deriv filter.
553 - var_sindex for first n_y vars match their position the the solver's var list
554
555 - ydot contains n_ydot non-NULL elements, each match the deriv filter.
556 - vars in solver's var list positions [n_y,n_y+n_ydot) all match deriv filter
557
558 - y_id contains n_ydot elements, with int values in range [0,n_y)
559 - var_sindex(ydot[y_id[i]]) - n_y == i for i in [0,n_ydot)
560
561 - all the vars [n_y+n_ydot,n_vars) fail the non-deriv filter and fail the deriv filter.
562 */
563 static int integrator_ida_check_diffindex(IntegratorSystem *sys){
564 int i, n_vars, n_ydot=0;
565 struct var_variable **list, *v;
566 char *varname;
567 int diffindex;
568 const char *msg;
569
570 CONSOLE_DEBUG("Checking diffindex vector");
571
572 if(sys->y_id == NULL || sys->y == NULL || sys->ydot == NULL){
573 ERROR_REPORTER_HERE(ASC_PROG_ERR,"list(s) NULL");
574 return 1;
575 }
576
577 list = slv_get_solvers_var_list(sys->system);
578 n_vars = slv_get_num_solvers_vars(sys->system);
579
580 if(check_dups(list,n_vars,FALSE)){
581 ERROR_REPORTER_HERE(ASC_PROG_ERR,"duplicates or NULLs in solver's var list");
582 return 1;
583 }
584
585 if(check_dups(sys->ydot,n_vars,TRUE)){
586 ERROR_REPORTER_HERE(ASC_PROG_ERR,"duplicates in ydot vector");
587 return 1;
588 }
589
590 /* check n_y in range */
591 if(sys->n_y <= 0 || sys->n_y >= n_vars){
592 ERROR_REPORTER_HERE(ASC_PROG_ERR,"n_y = %d invalid (n_vars = %d)",sys->n_y, n_vars);
593 return 1;
594 }
595
596 /* check first n_y vars */
597 for(i=0; i < sys->n_y; ++i){
598 v = list[i];
599 if(!var_apply_filter(v, &integrator_ida_nonderiv)){
600 msg = "'%s' (in first n_y vars) fails non-deriv filter"; goto finish;
601 }else if(var_sindex(v) != i){
602 msg = "'%s' has wrong var_sindex"; goto finish;
603 }else if(v != sys->y[i]){
604 msg = "'%s' not matched in y vector"; goto finish;
605 }
606 /* meets filter, matches in y vector, has correct var_sindex. */
607 }
608
609 /* count non-NULLs in ydot */
610 for(i=0; i < sys->n_y; ++i){
611 v = sys->ydot[i];
612 if(v!=NULL){
613 if(var_sindex(v) < sys->n_y){
614 msg = "'%s' has var_sindex < n_y"; goto finish;
615 }else if(!var_apply_filter(v,&integrator_ida_deriv)){
616 msg = "'%s' (in next n_ydot vars) fails deriv filter"; goto finish;
617 }
618 /* lies beyond first n_y vars, match deriv filter */
619 n_ydot++;
620 }
621 }
622
623 /* check that vars [n_y, n_y+n_ydot) in solver's var list match the deriv filter */
624 for(i=sys->n_y; i< sys->n_y + n_ydot; ++i){
625 v = list[i];
626 if(!var_apply_filter(v,&integrator_ida_deriv)){
627 msg = "'%s', in range [n_y,n_y+n_ydot), fails deriv filter"; goto finish;
628 }
629 }
630
631 /* check values in y_id are ints int range [0,n_y), and that they point to correct vars */
632 for(i=0; i<n_ydot; ++i){
633 if(sys->y_id[i] < 0 || sys->y_id[i] >= sys->n_y){
634 ERROR_REPORTER_HERE(ASC_PROG_ERR,"value of y_id[%d] is out of range",i);
635 return 1;
636 }
637 v = sys->ydot[sys->y_id[i]];
638 if(var_sindex(v) - sys->n_y != i){
639 msg = "'%s' not index correctly from y_id"; goto finish;
640 }
641 }
642
643 /* check remaining vars fail both filters */
644 for(i=sys->n_y + n_ydot; i<n_vars; ++i){
645 v = list[i];
646 if(var_apply_filter(v,&integrator_ida_nonderiv)){
647 msg = "Var '%s' at end meets non-deriv filter, but shouldn't"; goto finish;
648 }
649 if(var_apply_filter(v,&integrator_ida_deriv)){
650 CONSOLE_DEBUG("position = %d",i);
651 msg = "Var '%s' at end meets deriv filter, but shouldn't"; goto finish;
652 }
653 }
654
655 return 0;
656 finish:
657 varname = var_make_name(sys->system,v);
658 ERROR_REPORTER_HERE(ASC_PROG_ERR,msg,varname);
659 ASC_FREE(varname);
660 return 1;
661 }
662
663 /**
664 Given a derivative variable, return the index of its corresponding differential
665 variable in the y vector (and equivalently the var_sindex of the diff var)
666 */
667 int integrator_ida_diffindex(const IntegratorSystem *sys, const struct var_variable *deriv){
668 asc_assert(var_sindex(deriv) >= sys->n_y);
669 asc_assert(var_sindex(deriv) < sys->n_y + sys->n_ydot);
670 return sys->y_id[var_sindex(deriv) - sys->n_y];
671 }
672
673
674 /**
675 This function will output the data structures provided to use BY THE
676 SYSTEM -- not the ones we're working with here IN THE SOLVER.
677 */
678 int integrator_ida_analyse_debug(const IntegratorSystem *sys,FILE *fp){
679 return system_diffvars_debug(sys->system,fp);
680 }
681

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