/[ascend]/trunk/ascend/system/diffvars.c
ViewVC logotype

Contents of /trunk/ascend/system/diffvars.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2386 - (show annotations) (download) (as text)
Fri Feb 11 05:18:50 2011 UTC (9 years, 5 months ago) by jpye
File MIME type: text/x-csrc
File size: 8477 byte(s)
Add missing #include in diffvars.c
Change 'BLSODE' to 'LSODE' in dyn_tank.a4s (for Tcl/Tk GUI only)
1 /* ASCEND modelling environment
2 Copyright (C) 2007 Carnegie Mellon University
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18 *//** @file
19 Routines for creating 'derivative chains' during system build.
20 *//*
21 By John Pye, Jan 2007
22 */
23 #include "diffvars.h"
24 #include "diffvars_impl.h"
25
26 #include <ascend/general/ascMalloc.h>
27 #include <ascend/general/panic.h>
28 #include <ascend/utilities/error.h>
29
30 #include <ascend/compiler/instance_io.h>
31
32 #include "analyse_impl.h"
33 #include "system_impl.h"
34
35 /* #define DIFFVARS_DEBUG */
36
37 /*------------------------------------------------------------------------------
38 DERIVATIVES & DIFFERENTIAL VARIABLES
39 */
40
41 SolverDiffVarCollection *system_get_diffvars(slv_system_t sys){
42 return sys->diffvars;
43 }
44
45 static
46 int CmpDiffVars(const struct solver_ipdata *a, const struct solver_ipdata *b){
47 if(a->u.v.odeid < b->u.v.odeid)return -1;
48 if(a->u.v.odeid > b->u.v.odeid)return 1;
49 /* now, the ode_id is equal: next level of sorting... */
50 if(a->u.v.deriv < b->u.v.deriv)return -1;
51 if(a->u.v.deriv > b->u.v.deriv)return 1;
52 return 0;
53 }
54
55 /**
56 This function steals a lot of what was in integrator.c, but we try to make
57 it more general and capable of extracting info about high-order derivative
58 chains. One eye open to the possibility of doing Pantelides (or other?)
59 style index reduction.
60
61 Also, note that we try to only use data from the struct problem_t, NOT
62 to go back to the instance hierarchy. The idea is that we have already got
63 what we need in classify_instance, etc.
64
65 @return 0 on success
66 */
67 int system_generate_diffvars(slv_system_t sys, struct problem_t *prob){
68 SolverDiffVarCollection *diffvars = NULL;
69 struct solver_ipdata *vip, *vipnext;
70 SolverDiffVarSequence *seq;
71 struct gl_list_t *seqs;
72 long i, seqstart, nalg, ndiff;
73 short j;
74 char cont;
75 short maxorder = 0;
76
77 asc_assert(prob);
78
79 if(gl_length(prob->diffvars)==0){
80 CONSOLE_DEBUG("No differential variables were seen. Skipping generation of diffvars struct.");
81 return 0;
82 }
83
84 seqs = gl_create(prob->nr);
85
86 /* add the list of algebraic variables to the structure too */
87 asc_assert(prob->algebvars);
88 nalg = gl_length(prob->algebvars);
89 for(i=0; i<nalg; ++i){
90 vip = (struct solver_ipdata *)gl_fetch(prob->algebvars,i+1);
91 seq = ASC_NEW(SolverDiffVarSequence);
92 seq->n = 1;
93 seq->ode_id = 0;
94 seq->vars = ASC_NEW_ARRAY(struct var_variable*,1);
95 seq->vars[0] = vip->u.v.data;
96 gl_append_ptr(seqs,(void *)seq);
97 }
98 #ifdef DIFFVARS_DEBUG
99 CONSOLE_DEBUG("Added %ld algebraic vars to chains",nalg);
100 CONSOLE_DEBUG("Sorting %ld differential & derivative vars...",gl_length(prob->diffvars));
101 #endif
102
103 /* first sort the list of diffvars */
104 gl_sort(prob->diffvars, (CmpFunc)CmpDiffVars);
105
106 /* scan the list for derivs that are missing vars */
107 i = 1; cont = TRUE; seqstart =1; ndiff = 0;
108 vip = (struct solver_ipdata *)gl_fetch(prob->diffvars,i);
109 if(vip->u.v.deriv > 1){
110 ERROR_REPORTER_START_NOLINE(ASC_USER_ERROR);
111 FPRINTF(ASCERR,"Missing ode_type %d for ode_id %d (check var '",vip->u.v.deriv+1,vip->u.v.odeid);
112 WriteInstanceName(ASCERR,vip->i,prob->root);
113 FPRINTF(ASCERR,"')");
114 error_reporter_end_flush();
115 return 2;
116 }
117 while(cont){
118 /* CONSOLE_DEBUG("Working, seqstart=%ld",seqstart); */
119 if(i >= gl_length(prob->diffvars))cont = FALSE;
120 else vipnext = (struct solver_ipdata *)gl_fetch(prob->diffvars,i+1);
121
122 if(cont && vipnext->u.v.odeid == vip->u.v.odeid){
123 /* same sequence, check that it's the next derivative */
124 asc_assert(vip->u.v.deriv >= vip->u.v.deriv);
125
126 if(vipnext->u.v.deriv == vip->u.v.deriv){
127 ERROR_REPORTER_START_NOLINE(ASC_USER_ERROR);
128 FPRINTF(ASCERR,"Repeated ode_type %d for ode_id %d (var '",vip->u.v.deriv,vip->u.v.odeid);
129 WriteInstanceName(ASCERR,vip->i,prob->root);
130 FPRINTF(ASCERR,"')");
131 error_reporter_end_flush();
132 return 1;
133 }else if(vipnext->u.v.deriv > vip->u.v.deriv + 1){
134 ERROR_REPORTER_START_NOLINE(ASC_USER_ERROR);
135 FPRINTF(ASCERR,"Missing ode_type %d for ode_id %d (check var '",vip->u.v.deriv+1,vip->u.v.odeid);
136 WriteInstanceName(ASCERR,vip->i,prob->root);
137 FPRINTF(ASCERR,"')");
138 error_reporter_end_flush();
139 return 2;
140 }
141
142 /* allow this var into the sequence, loop again */
143 vip = vipnext; ++i; continue;
144 }
145
146 /* close the current sequence */
147 if(i == seqstart){
148 ERROR_REPORTER_START_NOLINE(ASC_USER_ERROR);
149 FPRINTF(ASCERR,"Variable '");
150 WriteInstanceName(ASCWAR,vip->i,prob->root);
151 FPRINTF(ASCERR,"' declared differential without derivative being identified (ode_id=%d)",vip->u.v.odeid);
152 error_reporter_end_flush();
153 return 3;
154 }
155 seq = ASC_NEW(SolverDiffVarSequence);
156 seq->n = i - seqstart + 1;
157 seq->ode_id = vip->u.v.odeid;
158 seq->vars = ASC_NEW_ARRAY(struct var_variable*,seq->n);
159 #ifdef DIFFVARS_DEBUG
160 CONSOLE_DEBUG("Saving sequence ode_id = %ld, n = %d",seq->ode_id,seq->n);
161 #endif
162 for(j=0;j<seq->n;++j){
163 vip = (struct solver_ipdata *)gl_fetch(prob->diffvars,seqstart+j);
164 seq->vars[j]=vip->u.v.data;
165 /* set the VAR_ALGEB flag as req */
166 var_set_diff(seq->vars[j],j==0 && seq->n > 1);
167 #ifdef DIFFVARS_DEBUG
168 CONSOLE_DEBUG("seq, j=%d: is %s",j
169 ,(var_diff(seq->vars[j]) ? "DIFF" :
170 (var_deriv(seq->vars[j]) ? "deriv" : "alg")
171 )
172 );
173 #endif
174 }
175 gl_append_ptr(seqs,(void *)seq);
176 ndiff++;
177 #ifdef DIFFVARS_DEBUG
178 CONSOLE_DEBUG("Completed seq %ld",gl_length(seqs));
179 #endif
180
181 if(vip->u.v.deriv > maxorder){
182 maxorder = vip->u.v.deriv;
183 /* CONSOLE_DEBUG("maxorder increased to %d",maxorder); */
184 }
185
186 ++i; seqstart=i; vip=vipnext;
187 if(cont && vip->u.v.deriv != 1){
188 ERROR_REPORTER_START_NOLINE(ASC_USER_ERROR);
189 FPRINTF(ASCERR,"Missing undifferentiated form of var '");
190 WriteInstanceName(ASCWAR,vip->i,prob->root);
191 FPRINTF(ASCERR,"' (ode_id = %d, ode_type = %d)",vip->u.v.odeid,vip->u.v.deriv);
192 error_reporter_end_flush();
193 return 4;
194 }
195 continue;
196 }
197
198 #ifdef DIFFVARS_DEBUG
199 CONSOLE_DEBUG("Identified %ld derivative chains, maximum length %d...",gl_length(seqs),maxorder);
200 #endif
201
202 diffvars = ASC_NEW(SolverDiffVarCollection);
203 diffvars->maxorder = maxorder;
204 diffvars->nseqs = gl_length(seqs);
205 diffvars->seqs = ASC_NEW_ARRAY(SolverDiffVarSequence,diffvars->nseqs);
206 for(i=0;i<diffvars->nseqs;++i){
207 diffvars->seqs[i] = *(SolverDiffVarSequence *)gl_fetch(seqs,i+1);
208 }
209 gl_destroy(seqs);
210 diffvars->nalg = nalg;
211 diffvars->ndiff = ndiff;
212
213 diffvars->nindep = gl_length(prob->indepvars);
214 diffvars->indep = ASC_NEW_ARRAY(struct var_variable *,diffvars->nindep);
215 for(i=0;i<diffvars->nindep;++i){
216 vip = (struct solver_ipdata *)gl_fetch(prob->indepvars,i+1);
217 diffvars->indep[i] = vip->u.v.data;
218 }
219 #ifdef DIFFVARS_DEBUG
220 CONSOLE_DEBUG("Identified %ld indep vars",diffvars->nindep);
221 #endif
222
223 /* I know, I know, this might not be the best place for this... */
224 diffvars->nobs = gl_length(prob->obsvars);
225 diffvars->obs = ASC_NEW_ARRAY(struct var_variable *,diffvars->nobs);
226 for(i=0;i<diffvars->nobs;++i){
227 vip = (struct solver_ipdata *)gl_fetch(prob->obsvars,i+1);
228 diffvars->obs[i] = vip->u.v.data;
229 }
230 #ifdef DIFFVARS_DEBUG
231 CONSOLE_DEBUG("Identified %ld obs vers",diffvars->nobs);
232 CONSOLE_DEBUG("There were %ld rels",prob->nr);
233 #endif
234
235 slv_set_diffvars(sys,(void *)diffvars);
236
237 return 0;
238 }
239
240
241 int system_diffvars_debug(slv_system_t sys,FILE *fp){
242 int i, j;
243 char *varname;
244 const SolverDiffVarCollection *diffvars;
245 SolverDiffVarSequence seq;
246 diffvars = sys->diffvars;
247 if(diffvars==NULL){
248 fprintf(fp,"NO DIFFVARS (NULL)");
249 return 0;
250 }
251 fprintf(fp,"Derivative chains in slv_system...\n");
252 for(i=0; i<diffvars->nseqs;++i){
253 seq = diffvars->seqs[i];
254 fprintf(fp,"%d: ",i);
255 for(j=0; j<seq.n; ++j){
256 if(j)fprintf(fp," <-- ");
257 fprintf(fp,"%d: (%p)",var_sindex(seq.vars[j]),seq.vars[j]);
258 varname = var_make_name(sys,seq.vars[j]);
259 fprintf(fp,"'%s'",varname);
260 ASC_FREE(varname);
261 }
262 fprintf(fp,"\n");
263 }
264 return 0;
265 }
266

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