/[ascend]/trunk/ascxx/ascpy.i
ViewVC logotype

Contents of /trunk/ascxx/ascpy.i

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2327 - (show annotations) (download)
Wed Dec 22 07:17:24 2010 UTC (13 years, 8 months ago) by jpye
File size: 13843 byte(s)
Merging in refactor of the C++ code, which is moved out of 'pygtk' and into 'ascxx'.
Adding support for IPOPT 3.9.1, the current latest version.
Support in dtar for parallel builds (possibly needs some testing still).
1 /* : set syntax=cpp : */
2 /*
3 SWIG interface routines to read a file into the library
4 */
5
6 %module(directors=1) ascpy
7
8 %include <python/std_string.i>
9 %include <python/std_except.i>
10 %include <python/std_vector.i>
11 %include <python/std_map.i>
12 %include <python/std_set.i>
13
14 %{
15 #include "library.h"
16 #include "compiler.h"
17 #include "type.h"
18 #include "instance.h"
19 #include "variable.h"
20 #include "relation.h"
21 #include "name.h"
22 #include "reporter.h"
23 #include "simulation.h"
24 #include "solver.h"
25 #include "symchar.h"
26 #include "set.h"
27 #include "dimensions.h"
28 #include "units.h"
29 #include "extmethod.h"
30 #include "plot.h"
31 #include "curve.h"
32 #include "solverparameters.h"
33 #include "solverstatus.h"
34 #include "solverreporter.h"
35 #include "incidencematrix.h"
36 #include "registry.h"
37 #include "annotation.h"
38 #include "simulation.h"
39
40 extern "C"{
41 #include <ascend/compiler/importhandler.h>
42 #include <ascend/general/ascMalloc.h>
43 }
44
45 #ifdef ASC_WITH_DMALLOC
46 # include <dmalloc.h>
47 #endif
48
49 %}
50
51 // All STL runtime_errors caught to Python
52
53 %exception {
54 try {
55 $action
56 }
57 catch (std::range_error &e) {
58 SWIG_exception(SWIG_IndexError,e.what());
59 }
60 catch (std::runtime_error &e) {
61 SWIG_exception(SWIG_RuntimeError,e.what());
62 }
63 }
64
65 // Import the preferences module
66 %pythoncode {
67 import preferences;
68 }
69
70 // Set-valued instance variable
71 %pythoncode {
72 class SetIter:
73 def __init__(self,set):
74 self.set=set
75 self.index=0
76 def next(self):
77 if self.index==self.set.length():
78 raise StopIteration
79 self.index = self.index + 1
80 return self.set[self.index]
81 }
82
83 template<class T>
84 class ASCXX_Set{
85 private:
86 ASCXX_Set();
87 public:
88 const T at(const unsigned long&) const;
89 const unsigned long length() const;
90 };
91 %extend ASCXX_Set<long>{
92 %pythoncode {
93 def __getitem__(self, index):
94 return self.at(index)
95 def __iter__(self):
96 return SetIter(self)
97 }
98 }
99 %extend ASCXX_Set<SymChar>{
100 %pythoncode {
101 def __getitem__(self, index):
102 return self.at(index)
103 def __iter__(self):
104 return SetIter(self)
105 }
106 }
107
108
109 %template(ModuleVector) std::vector<Module>;
110 %template(TypeVector) std::vector<Type>;
111 %template(MethodVector) std::vector<Method>;
112 %template(InstancVector) std::vector<Instanc>;
113 %template(ExtMethodVector) std::vector<ExtMethod>;
114 %template(SetInt) ASCXX_Set<long>;
115 %template(SetString) ASCXX_Set<SymChar>;
116 %template(DoubleVector) std::vector<double>;
117 %template(IntVector) std::vector<int>;
118 %template(CurveVector) std::vector<Curve>;
119 %template(StringVector) std::vector<std::string>;
120 %template(IntStringMap) std::map<int,std::string>;
121 %template(AnnotationVector) std::vector<Annotation>;
122 %template(UnitsVector) std::vector<UnitsM>;
123 %template(TypeSet) std::set<Type>;
124
125 %rename(Instance) Instanc;
126 %rename(Name) Nam;
127 %rename(getSetIntValue) Instanc::getSetValue<long>;
128 %rename(getSetStringValue) Instanc::getSetValue<SymChar>;
129 %rename(Units) UnitsM;
130
131 // Grab a Python function object as a Python object.
132 %typemap(in) PyObject *pyfunc {
133 if (!PyCallable_Check($input)) {
134 PyErr_SetString(PyExc_TypeError, "Need a callable object!");
135 return NULL;
136 }
137 $1 = $input;
138 }
139
140 //----------------------------
141 // REPORTER: callbacks to python
142 class Reporter{
143 private:
144 ~Reporter();
145 Reporter();
146 public:
147 // use 'getReporter' instead of 'Reporter::Instance()' in python
148 void setErrorCallback(error_reporter_callback_t callback, void *client_data);
149 void setPythonErrorCallback(PyObject *pyfunc);
150 void clearPythonErrorCallback();
151 };
152
153 %extend Reporter {
154 void reportError(const char *msg){
155 ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"%s", msg);
156 }
157 void reportNote(const char *msg){
158 ERROR_REPORTER_NOLINE(ASC_USER_NOTE,"%s",msg);
159 }
160 void reportWarning(const char *msg){
161 ERROR_REPORTER_NOLINE(ASC_USER_WARNING,"%s",msg);
162 }
163 void reportSuccess(const char *msg){
164 ERROR_REPORTER_NOLINE(ASC_USER_SUCCESS,"%s",msg);
165 }
166 }
167
168 // There are problems with Instance(), so use this instead:
169 Reporter *getReporter();
170
171 //----------------------------------------
172 // UNITS AND DIMENSIONS
173
174
175 class UnitsM;
176
177 %include "dimensions.h"
178 %include "units.h"
179
180 %extend UnitsM{
181 %pythoncode{
182 def getConvertedValue(self,si_value):
183 """Return an SI value converted to self's units of measurement."""
184 _v = si_value / self.getConversion()
185 _s = str(_v)
186 _n = self.getName().toString()
187 if _n=="1":
188 return _s
189 elif _n=="?":
190 return _s
191 else:
192 return _s + " " + _n;
193 }
194 }
195
196 /*
197 This function creates default (SI) units for any dimension given. Most
198 of the time you will want to use custom units in place of these, eg
199 'N' instead of 'kg*m/s^2'.
200 */
201
202 %rename(__str__) Dimensions::toString;
203
204 %extend Dimensions{
205 %pythoncode {
206
207 def __str__(self):
208 return self.toString()
209
210 def getDefaultUnits(self):
211 """Return the default (SI) units for a specific set of dimensions."""
212 if self.isWild():
213 return Units("?");
214
215 # create a string representation of the current dimensions
216 numparts=[]
217 denparts=[]
218 for i in range(0, self.MAX_DIMS):
219 baseunit = self.getBaseUnit(i);
220 num = self.getFractionNumerator(i)
221 den = self.getFractionDenominator(i)
222 if num > 0:
223 if den == 1:
224 if num == 1:
225 numparts.append(baseunit)
226 else:
227 numparts.append("%s^%d" % (baseunit, num) )
228 else:
229 numparts.append("%s^(%d/%d)" % (baseunit, num, den) )
230 elif num < 0:
231 if den == 1:
232 if num == -1:
233 denparts.append(baseunit)
234 else:
235 denparts.append("%s^%d" % (baseunit, -num) )
236 else:
237 denparts.append("%s^(%d/%d)" % (baseunit, -num, den) )
238
239 if len(numparts):
240 str = "*".join(numparts)
241 else:
242 str = "1"
243
244 if len(denparts):
245 str = str + "/" + "/".join(denparts)
246
247 return Units(str)
248
249 }
250 }
251
252 /*
253 some python code for nice unicode unit strings, need to extend the units.c code as well though.
254
255 elif num == 2:
256 numparts.append(baseunit + ur'\u00b2')
257 elif num == 3:
258 numparts.append(baseunit + ur'\u00b3')
259
260 str = ur'\u00b7'.join(numparts)
261 */
262 //----------------------------
263
264 %typemap(in) const SymChar& {
265 $1 = new SymChar(PyString_AsString($input));
266 }
267
268 %include "library.h"
269
270 class SymChar{
271 public:
272 SymChar(const std::string &);
273 const char *toString() const;
274 };
275 %extend SymChar{
276 const char *__repr__(){
277 return self->toString();
278 }
279 }
280
281 class Module{
282 public:
283 const char *getName() const;
284 const char *getFilename() const;
285 const struct tm *getMtime() const;
286 };
287
288 %include "method.h"
289
290 %ignore Method::getInternalType;
291 %ignore Method::getSym;
292
293 // Renamed in python as 'Name'
294 class Nam{
295 public:
296 Nam(const SymChar &);
297 const std::string getName() const;
298 };
299
300 %include "compiler.h"
301 /* we can always disown Compiler * as it's a singleton */
302 %apply SWIGTYPE *DISOWN { Compiler * };
303 %apply SWIGTYPE *DISOWN { Simulation * };
304
305 %include "type.h"
306
307 %extend Type{
308 const char *__repr__(){
309 return self->getName().toString();
310 }
311
312 %pythoncode{
313 def getPreferredUnits(self):
314 """Return preferred units for an instance, which is done by lookup per atom type."""
315 if not self.isRefinedReal():
316 return None
317
318 _pref = preferences.Preferences()
319 #print "Checking for preferred units for %s" % self.getName()
320 _u = _pref.getPreferredUnits(self.getName().toString())
321 if _u is None:
322 # no preferred units set
323 return None
324 _units = Units(_u);
325
326 if _units.getDimensions() != self.getDimensions():
327 getReporter().reportWarning("Preferred units '%s' for type '%s' are not dimensionally correct: ignoring." % (_u, self.getName()) );
328 return None
329
330 return _units;
331 }
332 }
333
334 typedef enum{
335 ASCXX_INST_STATUS_UNKNOWN=0, ASCXX_VAR_FIXED, ASCXX_VAR_UNSOLVED, ASCXX_VAR_ACTIVE, ASCXX_VAR_SOLVED
336 , ASCXX_REL_INACTIVE
337 } InstanceStatus;
338
339 /*
340 we really want to get rid of this and just %include...
341 */
342 class Instanc{
343 private:
344 Instanc();
345 public:
346 Instanc(Instance *);
347 Instanc(Instance *, SymChar &name);
348 ~Instanc();
349 std::vector<Instanc> getChildren();
350 const std::string getKindStr() const;
351 const SymChar &getName();
352 const Type getType() const;
353 const bool isAtom() const;
354 const bool isFixed() const;
355 const bool isIncluded() const;
356 const bool isFund() const;
357 const bool isConst() const;
358 const bool isAssigned() const;
359 const bool isCompound() const;
360 const bool isRelation() const;
361 const bool isLogicalRelation() const;
362 const bool isWhen() const;
363 const bool isSet() const; // a set (group) of things
364 const bool isSetInt() const;
365 const bool isSetString() const;
366 const bool isSetEmpty() const;
367 const bool isArray() const;
368 const bool isDefined() const;
369 const bool isBool() const;
370 const bool isInt() const;
371 const bool isSymbol() const;
372 const bool isReal() const;
373 const bool isModel() const;
374
375 const double getRealValue() const;
376 const bool isDimensionless() const;
377 const Dimensions getDimensions() const;
378 const bool getBoolValue() const;
379 const long getIntValue() const;
380 const SymChar getSymbolValue() const;
381 const std::string getValueAsString() const; ///< Use carefully: rounding will occur for doubles!
382
383 const std::string getRelationAsString(const Instanc &relative_to) const;
384 const double getResidual() const;
385 const bool getLogicalResidual() const;
386
387 Plot getPlot() const;
388
389 const bool isPlottable() const;
390 const ASCXX_Set<long> getSetValue<long>() const;
391 const ASCXX_Set<SymChar> getSetValue<SymChar>() const;
392 const bool isChildless() const;
393 void setFixed(const bool &val=true);
394 void setIncluded(const bool &val=true);
395 void setRealValue(const double &val);
396 void setRealValueWithUnits(const double &, const char *);
397 void setBoolValue(const bool &val);
398 void setIntValue(const long &val);
399 void setSymbolValue(const SymChar &sym);
400 void write(FILE *fp);
401
402 const InstanceStatus getStatus() const;
403
404 void setLowerBound(const double &);
405 void setUpperBound(const double &);
406 void setNominal(const double &);
407 const double getLowerBound() const;
408 const double getUpperBound() const;
409 const double getNominal() const;
410
411 const std::vector<Instanc> getClique() const;
412 const std::vector<std::string> getAliases() const;
413 };
414
415 %extend Instanc{
416 const char *__repr__(){
417 return self->getName().toString();
418 }
419 Instanc __getattr__(const char *name){
420 return self->getChild(SymChar(name));
421 }
422 Instanc __getitem__(const long &index){
423 return self->getChild(index);
424 }
425 double __float__(){
426 if(self->isReal()){
427 return self->getRealValue();
428 }else{
429 throw std::runtime_error("Can't cast this instance to float");
430 }
431 }
432
433 %pythoncode {
434 def getSetValue(self):
435 """Return the value of a set, as a integer or string Python sequence."""
436 if self.isSetInt():
437 return self.getSetIntValue()
438 elif self.isSetString():
439 return self.getSetStringValue()
440 elif self.isSetEmpty():
441 return set()
442 else:
443 raise RuntimeError("getSetValue: unknown set type");
444
445 def getValue(self):
446 """Returns an instance value, including units if applicable."""
447 #print "GETTING VALUE OF %s" % self.getName()
448 if self.isCompound():
449 return ""
450 elif self.isRelation():
451 return self.getResidual()
452 elif self.isWhen():
453 return "WHEN"
454 elif self.isSet():
455 _s = set(self.getSetValue());
456 #for _v in self.getSetValue():
457 # _s.add( _v )
458 return _s
459
460 elif ( self.isAtom() or self.isFund() ) and not self.isDefined():
461 return "undefined"
462 elif self.isReal():
463 return self.getRealValueAndUnits()
464 elif self.isBool():
465 return self.getBoolValue()
466 elif self.isInt():
467 return self.getIntValue()
468 elif self.isSymbol():
469 return self.getSymbolValue()
470 elif self.isLogicalRelation():
471 return self.getLogicalResidual()
472 else:
473 return "UNKNOWN TYPE"
474 #raise RuntimeError("Unknown value model type="+self.getType().getName().toString()+", instance kind=".getKindStr())
475
476 def getRealValueAndUnits(self):
477 """Return real-valued instance value as a string, converted to, and including, its preferred units."""
478 if not self.isReal():
479 raise TypeError
480 if self.isFund():
481 return self.getRealValue();
482 _u = self.getType().getPreferredUnits();
483 if _u is None:
484 _u = self.getDimensions().getDefaultUnits()
485 return _u.getConvertedValue(self.getRealValue())
486
487 def to(self,units):
488 """Returns an instance value converted to specified units."""
489 if not self.isReal():
490 raise TypeError
491 if units.__class__==str:
492 units = Units(units);
493 if units.__class__!=Units:
494 raise TypeError
495 return self.getRealValue() / units.getConversion()
496
497 def setFixedValue(self,val):
498 """Set a value to 'fixed', and specify its value, at the same time."""
499 if not self.isFixed():
500 self.setFixed();
501 # getReporter().reportError("Setting value of %s to %s" % (self.getName().toString(),val))
502 self.setRealValue(val);
503
504 def __coerce__(self,other):
505 if self.isInt():
506 if other.__class__==int:
507 return self.getIntValue(),int(other)
508 elif other.__class__==float:
509 return float(self.getIntValue()),other
510 elif self.isReal():
511 if other.__class__== int:
512 return self.getRealValue(),float(other)
513 elif other.__class__==float:
514 return self.getRealValue(),other
515 return str(self),str(other)
516
517 def __sub__(self,other):
518 a,b = self.__coerce__(other)
519 return a - b
520
521 def __rsub__(self,other):
522 a,b = self.__coerce__(other)
523 return b - a
524
525 def __add__(self,other):
526 a,b = self.__coerce__(other)
527 return a + b
528
529 def __radd__(self,other):
530 a,b = self.__coerce__(other)
531 return b + a
532 }
533 }
534
535 /*
536 This 'registry' thing is a bit of a hack that allows interface pointers to
537 be registered with libascend so that they can be accessed from external
538 script methods
539 */
540 %include "registry.h"
541 %extend Registry{
542 void set(const char *key, PyObject *obj){
543 /* CONSOLE_DEBUG("Registry::set(PyObject *obj=%p)",obj); */
544 self->setPyObject(key,obj);
545 }
546 }
547
548 void shutdown();
549
550 %{
551 void shutdown(){
552 ascshutdown("Shutdown ASCEND...");
553 }
554 %}
555
556 %include "solver.i"
557
558 %include "extmethod.h"
559
560 %include "annotation.h"
561
562 %include "plot.i"
563
564 %ignore Curve::Curve();
565
566 %include "curve.h"

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