/[ascend]/trunk/pygtk/interface/simulation.cpp
ViewVC logotype

Contents of /trunk/pygtk/interface/simulation.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 290 - (show annotations) (download) (as text)
Fri Feb 10 03:30:05 2006 UTC (18 years, 4 months ago) by johnpye
File MIME type: text/x-c++src
File size: 16389 byte(s)
Fixable vars added to interface (outputs to console)
Added 'next big' and 'prev big' to move between 'big blocks' in the diagnose window.
1 #include <iostream>
2 #include <iomanip>
3 #include <stdexcept>
4 #include <sstream>
5 using namespace std;
6
7 extern "C"{
8 #include <utilities/ascConfig.h>
9 #include <utilities/ascSignal.h>
10 #include <utilities/ascMalloc.h>
11 #include <general/dstring.h>
12 #include <general/tm_time.h>
13 #include <compiler/instance_enum.h>
14 #include <compiler/fractions.h>
15 #include <compiler/compiler.h>
16 #include <compiler/dimen.h>
17 #include <compiler/symtab.h>
18 #include <compiler/instance_io.h>
19 #include <compiler/instantiate.h>
20 #include <compiler/bintoken.h>
21 #include <compiler/instance_enum.h>
22 #include <compiler/instquery.h>
23 #include <compiler/check.h>
24 #include <compiler/name.h>
25 #include <compiler/pending.h>
26
27 #include <utilities/readln.h>
28 #include <solver/mtx.h>
29 #include <solver/slv_types.h>
30 #include <solver/var.h>
31 #include <solver/rel.h>
32 #include <solver/discrete.h>
33 #include <solver/conditional.h>
34 #include <solver/logrel.h>
35 #include <solver/bnd.h>
36 #include <solver/calc.h>
37 #include <solver/relman.h>
38 #include <solver/slv_common.h>
39 #include <solver/linsol.h>
40 #include <solver/linsolqr.h>
41 #include <solver/slv_client.h>
42 #include <solver/system.h>
43 #include <solver/slv_interface.h>
44 #include <solver/slvDOF.h>
45 #include <solver/slv3.h>
46 #include <solver/slv_stdcalls.h>
47 }
48
49 #include "simulation.h"
50 #include "solver.h"
51 #include "solverparameters.h"
52 #include "name.h"
53 #include "incidencematrix.h"
54 #include "variable.h"
55
56 /**
57 Create an instance of a type (call compiler etc)
58
59 @TODO fix mutex on compile command filenames
60 */
61 Simulation::Simulation(Instance *i, const SymChar &name) : Instanc(i, name), simroot(GetSimulationRoot(i),SymChar("simroot")){
62 is_built = false;
63 // Create an Instance object for the 'simulation root' (we'll call
64 // it the 'simulation model') and it can be fetched using 'getModel()'
65 // any time later.
66 //simroot = Instanc(GetSimulationRoot(i),name);
67 }
68
69 Simulation::Simulation(const Simulation &old) : Instanc(old), simroot(old.simroot){
70 is_built = old.is_built;
71 sys = old.sys;
72 bin_srcname = old.bin_srcname;
73 bin_objname = old.bin_objname;
74 bin_libname = old.bin_libname;
75 bin_cmd = old.bin_cmd;
76 bin_rm = old.bin_rm;
77 }
78
79 Simulation::~Simulation(){
80 //CONSOLE_DEBUG("Deleting simulation %s", getName().toString());
81 }
82
83 Instanc &
84 Simulation::getModel(){
85 if(!simroot.getInternalType()){
86 throw runtime_error("Simulation::getModel: simroot.getInternalType()is NULL");
87 }
88 return simroot;
89 }
90
91 void
92 Simulation::checkDoF() const{
93 cerr << "CHECKING DOF..." << endl;
94 int dof, status;
95 if(!sys){
96 throw runtime_error("System not yet built");
97 }
98 slvDOF_status(sys, &status, &dof);
99 switch(status){
100 case 1: ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Underspecified; %d degrees of freedom",dof); break;
101 case 2: ERROR_REPORTER_NOLINE(ASC_USER_NOTE,"Square"); break;
102 case 3: ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Structurally singular"); break;
103 case 4: ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Overspecified"); break;
104 case 5:
105 throw runtime_error("Unable to resolve degrees of freedom"); break;
106 default:
107 throw runtime_error("Invalid return status from slvDOF_status");
108 }
109 }
110
111 void
112 Simulation::run(const Method &method){
113 cerr << "RUNNING PROCEDURE " << method.getName() << endl;
114 Nam name = Nam(method.getSym());
115 //cerr << "CREATED NAME '" << name.getName() << "'" << endl;
116 Proc_enum pe;
117 pe = Initialize(
118 &*(getModel().getInternalType()) ,name.getInternalType(), "__not_named__"
119 ,ASCERR
120 ,0, NULL, NULL
121 );
122
123 if(pe == Proc_all_ok){
124 ERROR_REPORTER_NOLINE(ASC_PROG_NOTE,"Method '%s' was run (check above for errors)\n",method.getName());
125 //cerr << "METHOD " << method.getName() << " COMPLETED OK" << endl;
126 }else{
127 stringstream ss;
128 ss << "Simulation::run: Method '" << method.getName() << "' returned error: ";
129 switch(pe){
130 case Proc_CallOK: ss << "Call OK"; break;
131 case Proc_CallError: ss << "Error occurred in call"; break;
132 case Proc_CallReturn: ss << "Request that caller return (OK)"; break;
133 case Proc_CallBreak: ss << "Break out of enclosing loop"; break;
134 case Proc_CallContinue: ss << "Skip to next iteration"; break;
135
136 case Proc_break: ss << "Break"; break;
137 case Proc_continue: ss << "Continue"; break;
138 case Proc_fallthru: ss << "Fall-through"; break;
139 case Proc_return: ss << "Return"; break;
140 case Proc_stop: ss << "Stop"; break;
141 case Proc_stack_exceeded: ss << "Stack exceeded"; break;
142 case Proc_stack_exceeded_this_frame: ss << "Stack exceeded this frame"; break;
143 case Proc_case_matched: ss << "Case matched"; break;
144 case Proc_case_unmatched: ss << "Case unmatched"; break;
145
146 case Proc_case_undefined_value: ss << "Undefined value in case"; break;
147 case Proc_case_boolean_mismatch: ss << "Boolean mismatch in case"; break;
148 case Proc_case_integer_mismatch: ss << "Integer mismatch in case"; break;
149 case Proc_case_symbol_mismatch: ss << "Symbol mismatch in case"; break;
150 case Proc_case_wrong_index: ss << "Wrong index in case"; break;
151 case Proc_case_wrong_value: ss << "Wrong value in case"; break;
152 case Proc_case_extra_values: ss << "Extra values in case"; break;
153 case Proc_bad_statement: ss << "Bad statement"; break;
154 case Proc_bad_name: ss << "Bad name"; break;
155 case Proc_for_duplicate_index: ss << "Duplicate index"; break;
156 case Proc_for_set_err: ss << "For set error"; break;
157 case Proc_for_not_set: ss << "For not set"; break;
158 case Proc_illegal_name_use: ss << "Illegal name use"; break;
159 case Proc_name_not_found: ss << "Name not found"; break;
160 case Proc_instance_not_found: ss << "Instance not found"; break;
161 case Proc_type_not_found: ss << "Type not found"; break;
162 case Proc_illegal_type_use: ss << "Illegal use"; break;
163 case Proc_proc_not_found: ss << "Method not found"; break;
164 case Proc_if_expr_error_typeconflict: ss << "Type conflict in 'if' expression"; break;
165 case Proc_if_expr_error_nameunfound: ss << "Name not found in 'if' expression"; break;
166 case Proc_if_expr_error_incorrectname: ss << "Incorrect name in 'if' expression"; break;
167 case Proc_if_expr_error_undefinedvalue: ss << "Undefined value in 'if' expression"; break;
168 case Proc_if_expr_error_dimensionconflict: ss << "Dimension conflict in 'if' expression"; break;
169 case Proc_if_expr_error_emptychoice: ss << "Empty choice in 'if' expression"; break;
170 case Proc_if_expr_error_emptyintersection: ss << "Empty intersection in 'if' expression"; break;
171 case Proc_if_expr_error_confused: ss << "Confused in 'if' expression"; break;
172 case Proc_if_real_expr: ss << "Real-valued result in 'if' expression"; break;
173 case Proc_if_integer_expr: ss << "Integeter-valued result in 'if' expression"; break;
174 case Proc_if_symbol_expr: ss << "Symbol-valued result in 'if' expression"; break;
175 case Proc_if_set_expr: ss << "Set-valued result in 'if' expression"; break;
176 case Proc_if_not_logical: ss << "If expression is not logical"; break;
177 case Proc_user_interrupt: ss << "User interrupt"; break;
178 case Proc_infinite_loop: ss << "Infinite loop"; break;
179 case Proc_declarative_constant_assignment: ss << "Declarative constant assignment"; break;
180 case Proc_nonsense_assignment: ss << "Nonsense assginment (bogus)"; break;
181 case Proc_nonconsistent_assignment: ss << "Inconsistent assignment"; break;
182 case Proc_nonatom_assignment: ss << "Non-atom assignment"; break;
183 case Proc_nonboolean_assignment: ss << "Non-boolean assignment"; break;
184 case Proc_noninteger_assignment: ss << "Non-integer assignment"; break;
185 case Proc_nonreal_assignment: ss << "Non-real assignment"; break;
186 case Proc_nonsymbol_assignment: ss << "Non-symbol assignment"; break;
187 case Proc_lhs_error: ss << "Left-hand-side error"; break;
188 case Proc_rhs_error: ss << "Right-hand-side error"; break;
189 case Proc_unknown_error: ss << "Unknown error"; break;
190 default:
191 ss << "Invalid error code";
192 }
193
194
195 ss << " (" << int(pe) << ")";
196 throw runtime_error(ss.str());
197 }
198 }
199
200 const bool
201 Simulation::check(){
202 cerr << "CHECKING SIMULATION" << endl;
203 Instance *i1 = getModel().getInternalType();
204 CheckInstance(stderr, &*i1);
205 cerr << "...DONE CHECKING" << endl;
206 }
207
208 void
209 Simulation::build(){
210 cerr << "BUILDING SIMULATION..." << endl;
211 Instance *i1 = getModel().getInternalType();
212 sys = system_build(&*i1);
213 if(!sys){
214 throw runtime_error("Unable to build system");
215 }
216 is_built = true;
217 cerr << "...DONE BUILDING" << endl;
218 }
219
220 vector<Variable>
221 Simulation::getFixableVariables(){
222 cerr << "GETTING FIXABLE VARIABLES..." << endl;
223 vector<Variable> vars;
224
225 if(!sys){
226 throw runtime_error("Simulation system not yet built");
227 }
228
229 int32 **vip; /** TODO ensure 32 bit integers are used */
230
231 // Get IDs of elegible variables in array at vip...
232 if(!slvDOF_eligible(sys,vip)){
233 ERROR_REPORTER_NOLINE(ASC_USER_NOTE,"No fixable variables found.");
234 }else{
235 //cerr << "FIXABLE VARS FOUND" << endl;
236 struct var_variable **vp = slv_get_solvers_var_list(sys);
237
238 /*struct var_variable *first_var = vp[0];
239 char *first_var_name = var_make_name(sys,first_var);
240 cerr << "FIRST SYS VAR IS NAMED " << var_make_name(s,first_var) << endl;
241 ascfree(first_var_name);*/
242
243 if(vp==NULL){
244 throw runtime_error("Simulation variable list is null");
245 }
246
247 // iterate through this list until we find a -1:
248 int i=0;
249 int var_index = (*vip)[i];
250 while(var_index >= 0){
251 //cerr << "FOUND VARIABLE var_index = " << var_index << endl;
252 struct var_variable *var = vp[var_index];
253 //cerr << "VARIABLE " << var_index << " IS ELIGIBLE" << endl;
254 char *var_name = var_make_name(sys,var);
255 //cerr << "ELIGIBLE VAR: " << var_name << endl;
256 ascfree(var_name);
257 vars.push_back( Variable(this, var) );
258 ++i;
259 var_index = (*vip)[i];
260 }
261 ERROR_REPORTER_NOLINE(ASC_USER_NOTE,"Found %d fixable variables.",i);
262 //cerr << "END ELEGIBLE VARS LIST" << endl;
263 ascfree(*vip);
264 //cerr << "FREED VIP LIST" << endl;
265 }
266
267 //cerr << "FINISHED WITH FINDING ELEGIBLE VARIABLES" << endl;
268 return vars;
269 }
270
271
272 void
273 Simulation::solve(Solver solver){
274 if(!is_built){
275 throw runtime_error("Simulation::solver: simulation is not yet built, can't start solving.");
276 }
277
278 cerr << "SIMULATION::SOLVE STARTING..." << endl;
279 enum inst_t k = getModel().getKind();
280 if(k!=MODEL_INST)throw runtime_error("Can't solve: not an instance of type MODEL_INST");
281
282 Instance *i1 = getInternalType();
283 int npend = NumberPendingInstances(&*i1);
284 if(npend)throw runtime_error("Can't solve: There are still %d pending instances");
285
286 if(!sys)throw runtime_error("Can't solve: Simulation system has not been built yet.");
287
288 cerr << "SIMULATION::SOLVE: SET SOLVER..." << endl;
289 setSolver(solver);
290
291
292 cerr << "PRESOLVING SYSTEM...";
293 slv_presolve(sys);
294 cerr << "DONE" << endl;
295
296 cerr << "SOLVING SYSTEM..." << endl;
297 // Add some stuff here for cleverer iteration....
298 unsigned niter = 1000;
299 double updateinterval = 0.02;
300
301 double starttime = tm_cpu_time();
302 double lastupdate = starttime;
303 slv_status_t status;
304 int solved_vars=0;
305 bool stop=false;
306
307 for(int iter = 1; iter <= niter && !stop; ++iter){
308 slv_get_status(sys,&status);
309
310 if(status.ready_to_solve){
311 slv_iterate(sys);
312 }
313 if(tm_cpu_time() - lastupdate > updateinterval && iter > 0){
314 if(solved_vars < status.block.previous_total_size){
315 solved_vars = status.block.previous_total_size;
316 CONSOLE_DEBUG("Solved %5d vars. Now block %3d/%-3d...", solved_vars, status.block.current_block, status.block.number_of);
317 }else{
318 CONSOLE_DEBUG("Total %5d iterations (%5d in current block of %d vars)", iter, status.block.iteration, status.block.current_size);
319 }
320 lastupdate = tm_cpu_time();
321 }
322 }
323 double elapsed = tm_cpu_time() - starttime;
324
325 activeblock = status.block.current_block;
326
327 if(status.ok){
328 cerr << "... SOLVED, STATUS OK" << endl;
329 }else{
330 ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Solver failed");
331 }
332
333 cerr << "SOLVER PERFORMED " << status.iteration << " ITERATIONS IN " << elapsed << "s" << endl;
334
335 if(status.iteration_limit_exceeded){
336 ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Exceeded interation limit");
337 }
338
339 if(status.converged){
340 ERROR_REPORTER_NOLINE(ASC_USER_SUCCESS,"Solver converged: %d iterations (%.2f s)"
341 ,status.iteration,elapsed);
342 }else{
343 ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Solver not converged in block %d after overall %d iterations (see console)"
344 " (%.2f s).",status.block.current_block,status.iteration,elapsed);
345 IncidenceMatrix inc = getIncidenceMatrix();
346
347 /*
348 cerr << "VARIABLES IN NON-CONVERGED BLOCK:" << endl;
349 vector<Variable> v = inc.getBlockVars(status.block.current_block);
350 for(vector<Variable>::iterator vi = v.begin(); vi < v.end(); ++vi){
351 cerr << vi->getName() << " = " << vi->getValue() << endl;
352 }
353
354 cerr << "RELATIONS IN NON-CONVERGED BLOCK:" << endl;
355 vector<Relation> r = inc.getBlockRels(status.block.current_block);
356 for(vector<Relation>::iterator ri = r.begin(); ri < r.end(); ++ri){
357 cerr << ri->getName() << endl;
358 }
359 */
360 }
361
362 }
363
364 void
365 Simulation::write(){
366 simroot.write();
367 }
368
369 //------------------------------------------
370 // ASSIGNING SOLVER TO SIMULATION
371
372 void
373 Simulation::setSolver(Solver &solver){
374 cerr << "SETTING SOLVER ON SIMULATION TO " << solver.getName() << endl;
375
376 if(!sys)throw runtime_error("Can't solve: Simulation system has not been built yet.");
377 // Update the solver object because sometimes an alternative solver can be returned, apparently.
378
379 int selected = slv_select_solver(sys, solver.getIndex());
380 //cerr << "Simulation::setSolver: slv_select_solver returned " << selected << endl;
381
382 if(selected<0){
383 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Failed to select solver");
384 throw runtime_error("Failed to select solver");
385 }
386
387 if(selected!=solver.getIndex()){
388 solver = Solver(slv_solver_name(selected));
389 ERROR_REPORTER_NOLINE(ASC_PROG_NOTE,"Substitute solver '%s' (index %d) selected.\n", solver.getName().c_str(), selected);
390 }
391
392 if( slv_eligible_solver(sys) <= 0){
393 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Inelegible solver '%s'", solver.getName().c_str() );
394 throw runtime_error("Inelegible solver");
395 }
396 }
397
398 const Solver
399 Simulation::getSolver() const{
400 int index = slv_get_selected_solver(sys);
401 //cerr << "Simulation::getSolver: index = " << index << endl;
402 if(index<0)throw runtime_error("No solver selected");
403
404 return Solver(slv_solver_name(index));
405 }
406
407
408 /**
409 Get solver parameters struct wrapped up as a SolverParameters class.
410 */
411 SolverParameters
412 Simulation::getSolverParameters() const{
413 if(!sys)throw runtime_error("Can't getSolverParameters: Simulation system has not been built yet.");
414
415 slv_parameters_t p;
416 slv_get_parameters(sys,&p);
417 return SolverParameters(p);
418 }
419
420 /**
421 Update the solver parameters by passing a new set back
422 */
423 void
424 Simulation::setSolverParameters(SolverParameters &P){
425 if(!sys)throw runtime_error("Can't set solver parameters: simulation has not been built yet.");
426 slv_set_parameters(sys, &(P.getInternalType()));
427 }
428
429 slv_system_structure *
430 Simulation::getSystem(){
431 if(!sys)throw runtime_error("Can't getSystem: simulation not yet built");
432 return sys;
433 }
434
435 IncidenceMatrix
436 Simulation::getIncidenceMatrix(){
437 return IncidenceMatrix(*this);
438 }
439
440 const string
441 Simulation::getInstanceName(const Instanc &i) const{
442 char *n;
443 n = WriteInstanceNameString(i.getInternalType(),simroot.getInternalType());
444 string s(n);
445 ascfree(n);
446 return s;
447 }
448
449 void
450 Simulation::processVarStatus(){
451 if(!sys)throw runtime_error("Not yet build");
452
453 // this is a cheap function call:
454 const mtx_block_t *bb = slv_get_solvers_blocks(getSystem());
455 var_variable **vlist = slv_get_solvers_var_list(getSystem());
456 int nvars = slv_get_num_solvers_vars(getSystem());
457
458 slv_status_t status;
459 slv_get_status(getSystem(), &status);
460
461 int activeblock = status.block.current_block;
462 int low = bb->block[activeblock].col.low;
463 int high = bb->block[activeblock].col.high;
464 bool allsolved = status.converged;
465 for(int c=0; c < nvars; ++c){
466 var_variable *v = vlist[c];
467 Instanc i((Instance *)var_instance(v));
468 VarStatus s = ASCXX_VAR_STATUS_UNKNOWN;
469 if(i.isFixed()){
470 s = ASCXX_VAR_FIXED;
471 }else if(var_incident(v) && var_active(v)){
472 if(allsolved || c < low){
473 s = ASCXX_VAR_SOLVED;
474 }else if(c <= high){
475 s = ASCXX_VAR_ACTIVE;
476 }else{
477 s = ASCXX_VAR_UNSOLVED;
478 }
479 }
480 i.setVarStatus(s);
481 }
482 }
483
484 const int
485 Simulation::getActiveBlock() const{
486 return activeblock;
487 }

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