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

Contents of /trunk/pygtk/simulation.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1247 - (show annotations) (download) (as text)
Sat Jan 27 00:11:34 2007 UTC (16 years, 4 months ago) by johnpye
File MIME type: text/x-c++src
File size: 25772 byte(s)
Added 'hires.a4c' test model.
Split slv_system_structure out of slv.c and into system_impl.h.
Changed void* diffvars pointer in slv_system_structure to a typed pointer.
Moved SolverDiffVarCollectionStruct into system_impl.h.
Renamed slv_system_structure to just system_structure (in anticipation of a 'system' module separate from the actual solvers).
1 /* ASCEND modelling environment
2 Copyright (C) 2006 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 */
19 #include <iostream>
20 #include <iomanip>
21 #include <stdexcept>
22 #include <sstream>
23 using namespace std;
24
25 #include "config.h"
26
27 extern "C"{
28 #include <utilities/error.h>
29 #include <utilities/ascSignal.h>
30 #include <utilities/ascMalloc.h>
31 #include <general/dstring.h>
32 #include <general/tm_time.h>
33 #include <compiler/instance_enum.h>
34 #include <compiler/fractions.h>
35
36 #include <compiler/dimen.h>
37 #include <compiler/symtab.h>
38 #include <compiler/instance_io.h>
39 #include <compiler/instantiate.h>
40 #include <compiler/bintoken.h>
41 #include <compiler/instance_enum.h>
42 #include <compiler/instquery.h>
43 #include <compiler/check.h>
44 #include <compiler/name.h>
45 #include <compiler/pending.h>
46 #include <compiler/importhandler.h>
47 #include <linear/mtx.h>
48 #include <solver/calc.h>
49 #include <solver/relman.h>
50 #include <solver/system.h>
51 #include <solver/slv_interface.h>
52 #include <solver/slvDOF.h>
53 #include <solver/slv_stdcalls.h>
54 #include <solver/slv_server.h>
55 }
56
57 #include "simulation.h"
58 #include "solver.h"
59 #include "solverparameters.h"
60 #include "name.h"
61 #include "incidencematrix.h"
62 #include "variable.h"
63 #include "solverstatus.h"
64 #include "solverreporter.h"
65 #include "matrix.h"
66
67 /**
68 Create an instance of a type (call compiler etc)
69
70 @TODO fix mutex on compile command filenames
71 */
72 Simulation::Simulation(Instance *i, const SymChar &name) : Instanc(i, name), simroot(GetSimulationRoot(i),SymChar("simroot")){
73 CONSOLE_DEBUG("Created simulation");
74 sys = NULL;
75 //is_built = false;
76 // Create an Instance object for the 'simulation root' (we'll call
77 // it the 'simulation model') and it can be fetched using 'getModel()'
78 // any time later.
79 //simroot = Instanc(GetSimulationRoot(i),name);
80 }
81
82 Simulation::Simulation(const Simulation &old) : Instanc(old), simroot(old.simroot){
83 //is_built = old.is_built;
84 CONSOLE_DEBUG("Copying Simulation...");
85 sys = old.sys;
86 sing = NULL;
87 }
88
89 Simulation::~Simulation(){
90 CONSOLE_DEBUG("Destroying Simulation...");
91 /*
92 // FIXME removing this here, because Python overzealously seems to delete simulations
93
94 CONSOLE_DEBUG("Deleting simulation %s", getName().toString());
95 system_free_reused_mem();
96 if(sys){
97 CONSOLE_DEBUG("Destroying simulation system...");
98 system_destroy(sys);
99 }
100 */
101 sys = NULL;
102 }
103
104 Instanc &
105 Simulation::getModel(){
106 if(!simroot.getInternalType()){
107 throw runtime_error("Simulation::getModel: simroot.getInternalType()is NULL");
108 }
109 if(InstanceKind(simroot.getInternalType())!=MODEL_INST){
110 throw runtime_error("Simulation::getModel: simroot is not a MODEL instance");
111 }
112 return simroot;
113 }
114
115
116 slv_system_t
117 Simulation::getSystem(){
118 if(!sys)throw runtime_error("Can't getSystem: simulation not yet built");
119 return sys;
120 }
121
122
123 const string
124 Simulation::getInstanceName(const Instanc &i) const{
125 char *n;
126 n = WriteInstanceNameString(i.getInternalType(),simroot.getInternalType());
127 string s(n);
128 ascfree(n);
129 return s;
130 }
131
132 const int
133 Simulation::getNumVars(){
134 return slv_get_num_solvers_vars(getSystem());
135 }
136
137
138 void
139 Simulation::write(){
140 simroot.write();
141 }
142
143 //------------------------------------------------------------------------------
144 // RUNNING MODEL 'METHODS'
145
146 void
147 Simulation::run(const Method &method){
148 Instanc &model = getModel();
149 this->run(method,model);
150 }
151
152 void
153 Simulation::runDefaultMethod(){
154 const Type &type = getType();
155 Method m;
156 try{
157 m = type.getMethod(SymChar("on_load"));
158 }catch(runtime_error &e){
159 ERROR_REPORTER_NOLINE(ASC_USER_WARNING,"There is no 'on_load' method defined for type '%s'",type.getName().toString());
160 return;
161 }
162 run(m);
163 }
164
165 void
166 Simulation::run(const Method &method, Instanc &model){
167
168 // set the 'sim' pointer to our local variable...
169 CONSOLE_DEBUG("Setting shared pointer 'sim' = %p",this);
170 importhandler_setsharedpointer("sim",this);
171
172 /*if(not is_built){
173 CONSOLE_DEBUG("WARNING, SIMULATION NOT YET BUILT");
174 }*/
175
176 CONSOLE_DEBUG("Running method %s...", method.getName());
177
178 Nam name = Nam(method.getSym());
179 //cerr << "CREATED NAME '" << name.getName() << "'" << endl;
180
181 error_reporter_tree_start();
182
183 CONSOLE_DEBUG("sys = %p",sys);
184 CONSOLE_DEBUG("simroot = %p",simroot.getInternalType());
185
186 Proc_enum pe;
187 pe = Initialize(
188 &*(model.getInternalType()) ,name.getInternalType(), "__not_named__"
189 ,ASCERR
190 ,0, NULL, NULL
191 );
192
193 int haserror=0;
194 if(error_reporter_tree_has_error()){
195 haserror=1;
196 }
197 error_reporter_tree_end();
198
199 // clear out the 'sim' pointer (soon it will be invalid)
200 importhandler_setsharedpointer("sim",NULL);
201 CONSOLE_DEBUG("Cleared shared pointer 'sim'");
202
203 if(pe == Proc_all_ok){
204 if(haserror){
205 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Method '%s' had error(s).",method.getName());
206 stringstream ss;
207 ss << "Method '"<<method.getName()<<"' returned 'all_ok' status but output error(s)";
208 throw runtime_error(ss.str());
209 }else{
210 ERROR_REPORTER_NOLINE(ASC_USER_SUCCESS,"Method '%s' returned 'all_ok' and output no errors.\n",method.getName());
211 }
212 //cerr << "METHOD " << method.getName() << " COMPLETED OK" << endl;
213 }else{
214 stringstream ss;
215 ss << "Simulation::run: Method '" << method.getName() << "' returned error: ";
216 switch(pe){
217 case Proc_CallOK: ss << "Call OK"; break;
218 case Proc_CallError: ss << "Error occurred in call"; break;
219 case Proc_CallReturn: ss << "Request that caller return (OK)"; break;
220 case Proc_CallBreak: ss << "Break out of enclosing loop"; break;
221 case Proc_CallContinue: ss << "Skip to next iteration"; break;
222
223 case Proc_break: ss << "Break"; break;
224 case Proc_continue: ss << "Continue"; break;
225 case Proc_fallthru: ss << "Fall-through"; break;
226 case Proc_return: ss << "Return"; break;
227 case Proc_stop: ss << "Stop"; break;
228 case Proc_stack_exceeded: ss << "Stack exceeded"; break;
229 case Proc_stack_exceeded_this_frame: ss << "Stack exceeded this frame"; break;
230 case Proc_case_matched: ss << "Case matched"; break;
231 case Proc_case_unmatched: ss << "Case unmatched"; break;
232
233 case Proc_case_undefined_value: ss << "Undefined value in case"; break;
234 case Proc_case_boolean_mismatch: ss << "Boolean mismatch in case"; break;
235 case Proc_case_integer_mismatch: ss << "Integer mismatch in case"; break;
236 case Proc_case_symbol_mismatch: ss << "Symbol mismatch in case"; break;
237 case Proc_case_wrong_index: ss << "Wrong index in case"; break;
238 case Proc_case_wrong_value: ss << "Wrong value in case"; break;
239 case Proc_case_extra_values: ss << "Extra values in case"; break;
240 case Proc_bad_statement: ss << "Bad statement"; break;
241 case Proc_bad_name: ss << "Bad name"; break;
242 case Proc_for_duplicate_index: ss << "Duplicate index"; break;
243 case Proc_for_set_err: ss << "For set error"; break;
244 case Proc_for_not_set: ss << "For not set"; break;
245 case Proc_illegal_name_use: ss << "Illegal name use"; break;
246 case Proc_name_not_found: ss << "Name not found"; break;
247 case Proc_instance_not_found: ss << "Instance not found"; break;
248 case Proc_type_not_found: ss << "Type not found"; break;
249 case Proc_illegal_type_use: ss << "Illegal use"; break;
250 case Proc_proc_not_found: ss << "Method not found"; break;
251 case Proc_if_expr_error_typeconflict: ss << "Type conflict in 'if' expression"; break;
252 case Proc_if_expr_error_nameunfound: ss << "Name not found in 'if' expression"; break;
253 case Proc_if_expr_error_incorrectname: ss << "Incorrect name in 'if' expression"; break;
254 case Proc_if_expr_error_undefinedvalue: ss << "Undefined value in 'if' expression"; break;
255 case Proc_if_expr_error_dimensionconflict: ss << "Dimension conflict in 'if' expression"; break;
256 case Proc_if_expr_error_emptychoice: ss << "Empty choice in 'if' expression"; break;
257 case Proc_if_expr_error_emptyintersection: ss << "Empty intersection in 'if' expression"; break;
258 case Proc_if_expr_error_confused: ss << "Confused in 'if' expression"; break;
259 case Proc_if_real_expr: ss << "Real-valued result in 'if' expression"; break;
260 case Proc_if_integer_expr: ss << "Integeter-valued result in 'if' expression"; break;
261 case Proc_if_symbol_expr: ss << "Symbol-valued result in 'if' expression"; break;
262 case Proc_if_set_expr: ss << "Set-valued result in 'if' expression"; break;
263 case Proc_if_not_logical: ss << "If expression is not logical"; break;
264 case Proc_user_interrupt: ss << "User interrupt"; break;
265 case Proc_infinite_loop: ss << "Infinite loop"; break;
266 case Proc_declarative_constant_assignment: ss << "Declarative constant assignment"; break;
267 case Proc_nonsense_assignment: ss << "Nonsense assginment (bogus)"; break;
268 case Proc_nonconsistent_assignment: ss << "Inconsistent assignment"; break;
269 case Proc_nonatom_assignment: ss << "Non-atom assignment"; break;
270 case Proc_nonboolean_assignment: ss << "Non-boolean assignment"; break;
271 case Proc_noninteger_assignment: ss << "Non-integer assignment"; break;
272 case Proc_nonreal_assignment: ss << "Non-real assignment"; break;
273 case Proc_nonsymbol_assignment: ss << "Non-symbol assignment"; break;
274 case Proc_lhs_error: ss << "Left-hand-side error"; break;
275 case Proc_rhs_error: ss << "Right-hand-side error"; break;
276 case Proc_unknown_error: ss << "Unknown error"; break;
277 default:
278 ss << "Invalid error code";
279 }
280
281 ss << " (" << int(pe) << ")";
282 throw runtime_error(ss.str());
283 }
284 }
285
286 //-----------------------------------------------------------------------------
287 // CHECKING METHODS
288
289 /**
290 Check that all the analysis went OK: solver lists are all there, etc...?
291
292 Can't return anything here because of limitations in the C API
293
294 @TODO there's something wrong with this at the moment: even after 'FIX'
295 methods are run, check shows them as not fixed, up until the point that 'SOLVE'
296 successfully completes. Something's not being synchronised properly...
297 */
298 void
299 Simulation::checkInstance(){
300 //cerr << "CHECKING SIMULATION INSTANCE" << endl;
301 /*if(!is_built){
302 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Simulation has not been built");
303 return;
304 }*/
305 Instance *i1 = getModel().getInternalType();
306 CheckInstance(stderr, &*i1);
307 //cerr << "DONE CHECKING INSTANCE" << endl;
308 }
309
310 /**
311 @return 1 = underspecified, 2 = square, 3 = structurally singular, 4 = overspecified
312 */
313 enum StructuralStatus
314 Simulation::checkDoF() const{
315 int dof, status;
316
317 if(!sys){
318 throw runtime_error("System is not built");
319 }
320
321 /*if(!is_built){
322 throw runtime_error("System not yet built");
323 }*/
324 CONSOLE_DEBUG("Calling slvDOF_status...");
325 slvDOF_status(sys, &status, &dof);
326 switch(status){
327 case ASCXX_DOF_UNDERSPECIFIED:
328 case ASCXX_DOF_SQUARE:
329 case ASCXX_DOF_OVERSPECIFIED:
330 case ASCXX_DOF_STRUCT_SINGULAR:
331 return (enum StructuralStatus)status;
332 case 5:
333 throw runtime_error("Unable to resolve degrees of freedom"); break;
334 default:
335 throw runtime_error("Invalid return status from slvDOF_status");
336 }
337 }
338
339 /**
340 Check consistency
341
342 @TODO what is the difference between this and checkStructuralSingularity?
343
344 @return list of freeable variables. List will be empty if sys is consistent.
345 */
346 vector<Variable>
347 Simulation::getFreeableVariables(){
348 vector<Variable> v;
349
350 //cerr << "CHECKING CONSISTENCY..." << endl;
351 int *fixedarrayptr=NULL;
352
353 if(!sys){
354 throw runtime_error("System not yet built");
355 }
356
357 int res = consistency_analysis(sys, &fixedarrayptr);
358
359 if(res==1){
360 cerr << "STRUCTURALLY CONSISTENT" << endl;
361 }else{
362 if(fixedarrayptr ==NULL){
363 ERROR_REPORTER_HERE(ASC_USER_ERROR,"STRUCTURALLY INCONSISTENT");
364 throw runtime_error("Invalid consistency analysis result returned!");
365 }
366
367 struct var_variable **vp = slv_get_master_var_list(sys);
368 for(int i=0; fixedarrayptr[i]!=-1; ++i){
369 v.push_back( Variable(this, vp[fixedarrayptr[i]]) );
370 }
371 }
372 return v;
373 }
374
375 /** Returns TRUE if all is OK (not singular) */
376 bool
377 Simulation::checkStructuralSingularity(){
378 int *vil;
379 int *ril;
380 int *fil;
381
382 if(this->sing){
383 cerr << "DELETING OLD SINGULATING INFO" << endl;
384 delete this->sing;
385 this->sing = NULL;
386 }
387
388 cerr << "RETRIEVING slfDOF_structsing INFO" << endl;
389
390 int res = slvDOF_structsing(sys, mtx_FIRST, &vil, &ril, &fil);
391
392
393 if(res==1){
394 throw runtime_error("Unable to determine singularity lists");
395 }
396
397 if(res!=0){
398 throw runtime_error("Invalid return from slvDOF_structsing.");
399 }
400
401
402 CONSOLE_DEBUG("processing singularity data...");
403 sing = new SingularityInfo();
404
405 struct var_variable **varlist = slv_get_solvers_var_list(sys);
406 struct rel_relation **rellist = slv_get_solvers_rel_list(sys);
407
408 // pull in the lists of vars and rels, and the freeable vars:
409 for(int i=0; ril[i]!=-1; ++i){
410 sing->rels.push_back( Relation(this, rellist[ril[i]]) );
411 }
412
413 for(int i=0; vil[i]!=-1; ++i){
414 sing->vars.push_back( Variable(this, varlist[vil[i]]) );
415 }
416
417 for(int i=0; fil[i]!=-1; ++i){
418 sing->freeablevars.push_back( Variable(this, varlist[fil[i]]) );
419 }
420
421 // we're done with those lists now
422 ASC_FREE(vil);
423 ASC_FREE(ril);
424 ASC_FREE(fil);
425
426 if(sing->isSingular()){
427 CONSOLE_DEBUG("singularity found");
428 this->sing = sing;
429 return FALSE;
430 }
431 CONSOLE_DEBUG("no singularity");
432 delete sing;
433 return TRUE;
434 }
435
436 /**
437 If the checkStructuralSingularity analysis has been done,
438 this funciton will let you access the SingularityInfo data that was
439 stored.
440 */
441 const SingularityInfo &
442 Simulation::getSingularityInfo() const{
443 if(sing==NULL){
444 throw runtime_error("No singularity info present");
445 }
446 return *sing;
447 }
448
449 //------------------------------------------
450 // ASSIGNING SOLVER TO SIMULATION
451
452 void
453 Simulation::setSolver(Solver &solver){
454 /* CONSOLE_DEBUG("Setting solver on sim %p, root inst %p",this,this->simroot.getInternalType()); */
455
456 try{
457 // build the system (if not built already)
458 build();
459 }catch(runtime_error &e){
460 stringstream ss;
461 ss << "Couldn't prepare system for solving:";
462 ss << e.what();
463 throw runtime_error(ss.str());
464 }
465
466 CONSOLE_DEBUG("Selecting solver '%s'",solver.getName().c_str());
467 int selected = slv_select_solver(sys, solver.getIndex());
468 //cerr << "Simulation::setSolver: slv_select_solver returned " << selected << endl;
469
470 if(selected<0){
471 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Failed to select solver");
472 throw runtime_error("Failed to select solver");
473 }
474
475 if(selected!=solver.getIndex()){
476 solver = Solver(slv_solver_name(selected));
477 ERROR_REPORTER_NOLINE(ASC_PROG_NOTE,"Substitute solver '%s' (index %d) selected.\n", solver.getName().c_str(), selected);
478 }
479
480 if( slv_eligible_solver(sys) <= 0){
481 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Inelegible solver '%s'", solver.getName().c_str() );
482 throw runtime_error("Inelegible solver");
483 }
484 }
485
486 const Solver
487 Simulation::getSolver() const{
488 int index = slv_get_selected_solver(sys);
489 //cerr << "Simulation::getSolver: index = " << index << endl;
490 if(index<0)throw runtime_error("No solver selected");
491
492 return Solver(slv_solver_name(index));
493 }
494
495 //------------------------------------------------------------------------------
496 // BUILD THE SYSTEM
497
498 /**
499 Build the system (send it to the solver)
500 */
501 void
502 Simulation::build(){
503 if(sys){
504 CONSOLE_DEBUG("System is already built (%p)",sys);
505 return;
506 }
507
508 if(simroot.getKind() != MODEL_INST){
509 throw runtime_error("Simulation does not contain a MODEL_INST");
510 }
511
512 if(NumberPendingInstances(simroot.getInternalType())){
513 throw runtime_error("System has pending instances; can't yet send to solver.");
514 }
515
516 CONSOLE_DEBUG("============== REALLY building system...");
517 sys = system_build(simroot.getInternalType());
518 if(!sys){
519 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed to build system");
520 throw runtime_error("Unable to build system");
521 }
522
523 CONSOLE_DEBUG("System built OK");
524 }
525
526
527 //------------------------------------------------------------------------------
528 // SOLVER CONFIGURATION PARAMETERS
529
530 /**
531 Get solver parameters struct wrapped up as a SolverParameters class.
532 */
533 SolverParameters
534 Simulation::getParameters() const{
535 //if(!is_built)throw runtime_error("Can't getSolverParameters: Simulation system has not been built yet.");
536 if(!sys)throw runtime_error("Can't getSolverParameters: Simulation system has no 'sys' assigned.");
537
538 slv_parameters_t p;
539 slv_get_parameters(sys,&p);
540 return SolverParameters(p);
541 }
542
543 /**
544 Update the solver parameters by passing a new set back
545 */
546 void
547 Simulation::setParameters(SolverParameters &P){
548 if(!sys)throw runtime_error("Can't set solver parameters: simulation has not been built yet.");
549 CONSOLE_DEBUG("Calling slv_set_parameters");
550 slv_set_parameters(sys, &(P.getInternalType()));
551 }
552
553 //------------------------------------------------------------------------------
554 // PRE-SOLVE DIAGNOSTICS
555
556 /**
557 Get a list of variables to fix to make an underspecified system
558 become square. Also seems to return stuff when you have a structurally
559 singuler system.
560 */
561 vector<Variable>
562 Simulation::getFixableVariables(){
563 //cerr << "GETTING FIXABLE VARIABLES..." << endl;
564 vector<Variable> vars;
565
566 if(!sys){
567 throw runtime_error("Simulation system not yet built");
568 }
569
570 int32 *vip; /** TODO ensure 32 bit integers are used */
571
572 // Get IDs of elegible variables in array at vip...
573 CONSOLE_DEBUG("Calling slvDOF_eligible");
574 if(!slvDOF_eligible(sys,&vip)){
575 ERROR_REPORTER_NOLINE(ASC_USER_NOTE,"No fixable variables found.");
576 }else{
577 struct var_variable **vp = slv_get_solvers_var_list(sys);
578
579 if(vp==NULL){
580 throw runtime_error("Simulation variable list is null");
581 }
582
583 // iterate through this list until we find a -1:
584 int i=0;
585 int var_index = vip[i];
586 while(var_index >= 0){
587 struct var_variable *var = vp[var_index];
588 vars.push_back( Variable(this, var) );
589 ++i;
590 var_index = vip[i];
591 }
592 ERROR_REPORTER_NOLINE(ASC_USER_NOTE,"Found %d fixable variables.",i);
593 ascfree(vip);
594 }
595
596 return vars;
597 }
598
599 /**
600 Return a list of ALL the fixed variables in the solver's variable list
601 */
602 vector<Variable>
603 Simulation::getFixedVariables(){
604 if(!sys)throw runtime_error("Simulation system not build yet");
605 vector<Variable> vars;
606 var_variable **vlist = slv_get_solvers_var_list(sys);
607 unsigned long nvars = slv_get_num_solvers_vars(sys);
608 for(unsigned long i=0;i<nvars;++i){
609 if(!var_fixed(vlist[i]))continue;
610 vars.push_back(Variable(this,vlist[i]));
611 }
612 return vars;
613 }
614
615 /**
616 For solvers that store a big matrix for the system, return a pointer to that
617 matrix (struct mtx_header*) as a C++-wrapped object of class Matrix.
618 */
619 Matrix
620 Simulation::getMatrix(){
621 if(!sys)throw runtime_error("Simulation system not built yet");
622 mtx_matrix_t M = slv_get_sys_mtx(sys);
623 if(M==NULL)throw runtime_error("Simulation system does not possess a matrix");
624 return Matrix(M);
625 }
626
627 /**
628 Get the list of variables near their bounds. Helps to indentify why
629 you might be having non-convergence problems.
630 */
631 vector<Variable>
632 Simulation::getVariablesNearBounds(const double &epsilon){
633 //cerr << "GETTING VARIABLES NEAR BOUNDS..." << endl;
634 vector<Variable> vars;
635
636 if(!sys){
637 throw runtime_error("Simulation system not yet built");
638 }
639
640 int *vip;
641 CONSOLE_DEBUG("Calling slv_near_bounds...");
642 if(slv_near_bounds(sys,epsilon,&vip)){
643 struct var_variable **vp = slv_get_solvers_var_list(sys);
644 struct var_variable *var;
645 cerr << "VARS FOUND NEAR BOUNDS" << endl;
646 int nlow = vip[0];
647 int nhigh = vip[1];
648 int lim1 = 2 + nlow;
649 for(int i=2; i<lim1; ++i){
650 var = vp[vip[i]];
651 char *var_name = var_make_name(sys,var);
652 cerr << "AT LOWER BOUND: " << var_name << endl;
653 ascfree(var_name);
654 vars.push_back(Variable(this,var));
655 };
656 int lim2 = lim1 + nhigh;
657 for(int i=lim1; i<lim2; ++i){
658 var = vp[vip[i]];
659 char *var_name = var_make_name(sys,var);
660 cerr << "AT UPPER BOUND: " << var_name << endl;
661 ascfree(var_name);
662 vars.push_back(Variable(this,var));
663 }
664 }
665 ASC_FREE(vip);
666 return vars;
667 }
668
669 vector<Variable>
670 Simulation::getVariablesFarFromNominals(const double &bignum){
671 vector<Variable> vars;
672
673 if(!sys){
674 throw runtime_error("Simulation system not yet built");
675 }
676
677 int *vip;
678 int nv;
679 CONSOLE_DEBUG("Calling slv_far_from_nominals...");
680 if((nv=slv_far_from_nominals(sys, bignum, &vip))){
681 struct var_variable **vp = slv_get_solvers_var_list(sys);
682 struct var_variable *var;
683 cerr << "VARS FAR FROM NOMINAL" << endl;
684 for(int i=0; i<nv; ++i){
685 var = vp[vip[i]];
686 char *varname = var_make_name(sys,var);
687 cerr << "FAR FROM NOMINAL: " << varname << endl;
688 ASC_FREE(varname);
689 vars.push_back(Variable(this,var));
690 };
691 }
692 ASC_FREE(vip);
693 return vars;
694 }
695
696 bool
697 SingularityInfo::isSingular() const{
698 if(vars.size()||rels.size()){
699 return true;
700 }
701 return false;
702 }
703
704 //------------------------------------------------------------------------------
705 // SOLVING
706
707 /**
708 Solve the system through to convergence. This function is hardwired with
709 a maximum of 1000 iterations, but will interrupt itself when the 'stop'
710 condition comes back from the SolverReporter.
711 */
712 void
713 Simulation::solve(Solver solver, SolverReporter &reporter){
714 int res;
715
716 cerr << "-----------------set solver----------------" << endl;
717 CONSOLE_DEBUG("Setting solver to '%s'",solver.getName().c_str());
718 setSolver(solver);
719
720 cerr << "-----------------presolve----------------" << endl;
721
722 //cerr << "PRESOLVING SYSTEM...";
723 CONSOLE_DEBUG("Calling slv_presolve...");
724
725 res = slv_presolve(sys);
726 CONSOLE_DEBUG("slv_presolve returns %d",res);
727 if(res!=0){
728 throw runtime_error("Error in slv_presolve");
729 }
730
731 cerr << "-----------------solve----------------" << endl;
732 //cerr << "DONE" << endl;
733
734 //cerr << "SOLVING SYSTEM..." << endl;
735 // Add some stuff here for cleverer iteration....
736 unsigned niter = 1000;
737 //double updateinterval = 0.02;
738
739 double starttime = tm_cpu_time();
740 //double lastupdate = starttime;
741 SolverStatus status;
742 //int solved_vars=0;
743 bool stop=false;
744
745 status.getSimulationStatus(*this);
746 reporter.report(&status);
747
748 for(unsigned iter = 1; iter <= niter && !stop; ++iter){
749
750 if(status.isReadyToSolve()){
751 /* CONSOLE_DEBUG("Calling slv_iterate..."); */
752 res = slv_iterate(sys);
753 }
754
755 if(res)CONSOLE_DEBUG("slv_iterate returns %d",res);
756
757 status.getSimulationStatus(*this);
758
759 if(res || reporter.report(&status)){
760 stop = true;
761 }
762 }
763
764 double elapsed = tm_cpu_time() - starttime;
765 CONSOLE_DEBUG("Elapsed time: %0.3f", elapsed);
766
767 activeblock = status.getCurrentBlockNum();
768
769 // reporter can do output of num of iterations etc, if it wants to.
770 reporter.finalise(&status);
771
772 // communicate solver variable status back to the instance tree
773 processVarStatus();
774
775 if(res){
776 stringstream ss;
777 ss << "Error in solving (res = " << res << ")";
778 throw runtime_error(ss.str());
779 }
780 if(!status.isOK()){
781 if(status.isDiverged())throw runtime_error("Solution diverged");
782 if(status.isInconsistent())throw runtime_error("System is inconsistent");
783 if(status.hasExceededIterationLimit())throw runtime_error("Solver exceeded iteration limit");
784 if(status.hasExceededTimeLimit())throw runtime_error("Solver exceeded time limit");
785 if(status.isOverDefined())throw runtime_error("Solver system is over-defined");
786 if(status.isUnderDefined())throw runtime_error("Solver system is under-defined");
787 throw runtime_error("Error in solver (status.isOK()==FALSE but can't see why)");
788 }
789 }
790
791 //------------------------------------------------------------------------------
792 // POST-SOLVE DIAGNOSTICS
793
794 const int
795 Simulation::getActiveBlock() const{
796 return activeblock;
797 }
798
799 /**
800 Return an IncidenceMatrix built from the current state of the solver system.
801
802 This will actually return something meaningful even before solve.
803 */
804 IncidenceMatrix
805 Simulation::getIncidenceMatrix(){
806 return IncidenceMatrix(*this);
807 }
808
809 /**
810 This function looks at all the variables in the solve's list and updates
811 the variable status for the corresponding instances.
812
813 It does this by using the 'interface pointer' in the Instance, see
814 the C-API function GetInterfacePtr.
815
816 This is used to display visually which variables have been solved, which
817 ones have not yet been attempted, and which ones were active when the solver
818 failed (ASCXX_VAR_ACTIVE).
819 */
820 void
821 Simulation::processVarStatus(){
822 if(!sys)throw runtime_error("No system built");
823
824 CONSOLE_DEBUG("Getting var status");
825
826 // this is a cheap function call:
827 const mtx_block_t *bb = slv_get_solvers_blocks(getSystem());
828
829 var_variable **vlist = slv_get_solvers_var_list(getSystem());
830 int nvars = slv_get_num_solvers_vars(getSystem());
831
832 slv_status_t status;
833 if(slv_get_status(sys, &status)){
834 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to update var status (get_status returns error)");
835 return;
836 }
837
838 if(status.block.number_of == 0){
839 cerr << "Variable statuses can't be set: block structure not yet determined." << endl;
840 return;
841 }
842
843 int activeblock = status.block.current_block;
844 int low = bb->block[activeblock].col.low;
845 int high = bb->block[activeblock].col.high;
846 bool allsolved = status.converged;
847 for(int c=0; c < nvars; ++c){
848 var_variable *v = vlist[c];
849 Instanc i((Instance *)var_instance(v));
850 VarStatus s = ASCXX_VAR_STATUS_UNKNOWN;
851 if(i.isFixed()){
852 s = ASCXX_VAR_FIXED;
853 }else if(var_incident(v) && var_active(v)){
854 if(allsolved || c < low){
855 s = ASCXX_VAR_SOLVED;
856 }else if(c <= high){
857 s = ASCXX_VAR_ACTIVE;
858 }else{
859 s = ASCXX_VAR_UNSOLVED;
860 }
861 }
862 i.setVarStatus(s);
863 }
864
865 CONSOLE_DEBUG(" ...done var status");
866 }
867

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