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

Contents of /trunk/ascxx/ascpy.i

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3106 - (show annotations) (download)
Wed Jun 1 03:27:36 2016 UTC (17 months, 3 weeks ago) by jpye
File size: 13835 byte(s)
fixes bug 591 (thanks Georgy for the patch).

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

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