~jdpipe/ascend/trunk-old

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
/* : set syntax=cpp : */
/*
	SWIG interface routines to read a file into the library
*/

%module(directors=1) ascpy

%include <python/std_string.i>
%include <python/std_except.i>
%include <python/std_vector.i>
%include <python/std_map.i>
%include <python/std_set.i>

%{
#include "library.h"
#include "compiler.h"
#include "type.h"
#include "instance.h"
#include "variable.h"
#include "relation.h"
#include "name.h"
#include "reporter.h"
#include "simulation.h"
#include "solver.h"
#include "symchar.h"
#include "set.h"
#include "dimensions.h"
#include "units.h"
#include "extmethod.h"
#include "plot.h"
#include "curve.h"
#include "solverparameters.h"
#include "solverstatus.h"
#include "solverreporter.h"
#include "incidencematrix.h"
#include "registry.h"
#include "annotation.h"

extern "C"{
#include <ascend/compiler/importhandler.h>
#include <ascend/general/ascMalloc.h>
}

#ifdef ASC_WITH_DMALLOC
# include <dmalloc.h>
#endif

%}

// All STL runtime_errors caught to Python

%exception {
	try {
		$action
	}
	catch (std::range_error &e) {
		SWIG_exception(SWIG_IndexError,e.what());
	}
	catch (std::runtime_error &e) {
		SWIG_exception(SWIG_RuntimeError,e.what());
	}
}

// Import the preferences module
%pythoncode {
	import preferences;
}

// Set-valued instance variable
%pythoncode {
	class SetIter:
		def __init__(self,set):
			self.set=set
			self.index=0
		def next(self):
			if self.index==self.set.length():
				raise StopIteration
			self.index = self.index + 1
			return self.set[self.index]
}

template<class T>
class ASCXX_Set{
private:
	ASCXX_Set();
public:
	const T at(const unsigned long&) const;
	const unsigned long	length() const;
};
%extend ASCXX_Set<long>{
	%pythoncode {
		def __getitem__(self, index):
			return self.at(index)
		def __iter__(self):
			return SetIter(self)
	}
}
%extend ASCXX_Set<SymChar>{
	%pythoncode {
		def __getitem__(self, index):
			return self.at(index)
		def __iter__(self):
			return SetIter(self)
	}
}


%template(ModuleVector) std::vector<Module>;
%template(TypeVector) std::vector<Type>;
%template(MethodVector) std::vector<Method>;
%template(InstancVector) std::vector<Instanc>;
%template(ExtMethodVector) std::vector<ExtMethod>;
%template(SetInt) ASCXX_Set<long>;
%template(SetString) ASCXX_Set<SymChar>;
%template(DoubleVector) std::vector<double>;
%template(IntVector) std::vector<int>;

%ignore std::vector<Curve>::vector(size_type);
%ignore std::vector<Curve>::resize;
%template(CurveVector) std::vector<Curve>;
%template(StringVector) std::vector<std::string>;
%template(IntStringMap) std::map<int,std::string>;
%template(AnnotationVector) std::vector<Annotation>;
%template(UnitsVector) std::vector<UnitsM>;
%template(TypeSet) std::set<Type>;

%rename(Instance) Instanc;
%rename(Name) Nam;
%rename(getSetIntValue) Instanc::getSetValue<long>;
%rename(getSetStringValue) Instanc::getSetValue<SymChar>;
%rename(Units) UnitsM;

// Grab a Python function object as a Python object.
%typemap(in) PyObject *pyfunc {
  if (!PyCallable_Check($input)) {
      PyErr_SetString(PyExc_TypeError, "Need a callable object!");
      return NULL;
  }
  $1 = $input;
}

//----------------------------
// REPORTER: callbacks to python
class Reporter{
private:
	~Reporter();
	Reporter();
public:
	// use 'getReporter' instead of 'Reporter::Instance()' in python
	void setErrorCallback(error_reporter_callback_t callback, void *client_data);
	void setPythonErrorCallback(PyObject *pyfunc);
	void clearPythonErrorCallback();
};

%extend Reporter {
	void reportError(const char *msg){
		ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"%s", msg);
	}
	void reportNote(const char *msg){
		ERROR_REPORTER_NOLINE(ASC_USER_NOTE,"%s",msg);
	}
	void reportWarning(const char *msg){
		ERROR_REPORTER_NOLINE(ASC_USER_WARNING,"%s",msg);
	}
	void reportSuccess(const char *msg){
		ERROR_REPORTER_NOLINE(ASC_USER_SUCCESS,"%s",msg);
	}
}

// There are problems with Instance(), so use this instead:
Reporter *getReporter();

//----------------------------------------
// UNITS AND DIMENSIONS


class UnitsM;

%include "dimensions.h"
%include "units.h"

%extend UnitsM{
	%pythoncode{
		def getConvertedValue(self,si_value):
			"""Return an SI value converted to self's units of measurement."""
			_v = si_value / self.getConversion()
			_s = str(_v)
			_n = self.getName().toString()
			if _n=="1":
				return _s
			elif _n=="?":
				return _s
			else:
				return _s + " " + _n;
	}
}

/*
	This function creates default (SI) units for any dimension given. Most
	of the time you will want to use custom units in place of these, eg
	'N' instead of 'kg*m/s^2'.
*/

%rename(__str__) Dimensions::toString;

%extend Dimensions{
	%pythoncode %{
		
		def __str__(self):
			return self.toString()

		def getDefaultUnits(self):
			"""Return the default (SI) units for a specific set of dimensions."""
			if self.isWild():
				return Units("?");

			# create a string representation of the current dimensions
			numparts=[]
			denparts=[]
			for i in range(0, self.MAX_DIMS):
				baseunit = self.getBaseUnit(i);
				num = self.getFractionNumerator(i)
				den = self.getFractionDenominator(i)
				if num > 0:
					if den == 1:
						if num == 1:
							numparts.append(baseunit)
						else:
							numparts.append("%s^%d" % (baseunit, num) )
					else:
						numparts.append("%s^(%d/%d)" % (baseunit, num, den) )
				elif num < 0:
					if den == 1:
						if num == -1:
							denparts.append(baseunit)
						else:
							denparts.append("%s^%d" % (baseunit, -num) )
					else:
						denparts.append("%s^(%d/%d)" % (baseunit, -num, den) )

			if len(numparts):
				str = "*".join(numparts)
			else:
				str = "1"

			if len(denparts):
				str = str + "/" + "/".join(denparts)

			return Units(str)

	%}
}

/*
some python code for nice unicode unit strings, need to extend the units.c code as well though.

elif num == 2:
	numparts.append(baseunit + ur'\u00b2')
elif num == 3:
	numparts.append(baseunit + ur'\u00b3')

str = ur'\u00b7'.join(numparts)
*/
//----------------------------

%typemap(in) const SymChar& {
	$1 = new SymChar(PyString_AsString($input));
}

%include "library.h"

class SymChar{
public:
	SymChar(const std::string &);
	const char *toString() const;
};
%extend SymChar{
	const char *__repr__(){
		return self->toString();
	}
}

class Module{
public:
	const char *getName() const;
	const char *getFilename() const;
	const struct tm *getMtime() const;
};

%include "method.h"

%ignore Method::getInternalType;
%ignore Method::getSym;

// Renamed in python as 'Name'
class Nam{
public:
	Nam(const SymChar &);
	const std::string getName() const;
};

%include "compiler.h"
/* we can always disown Compiler * as it's a singleton */
%apply SWIGTYPE *DISOWN { Compiler * };
%apply SWIGTYPE *DISOWN { Simulation * };

%include "type.h"

%extend Type{
	const char *__repr__(){
		return self->getName().toString();
	}

	%pythoncode %{
		def getPreferredUnits(self):
			"""Return preferred units for an instance, which is done by lookup per atom type."""
			if not self.isRefinedReal():
				return None

			_pref = preferences.Preferences()
			#print "Checking for preferred units for %s" % self.getName()
			_u = _pref.getPreferredUnits(self.getName().toString())
			if _u is None:
				# no preferred units set
				return None
			_units = Units(_u);

			if _units.getDimensions() != self.getDimensions():
				getReporter().reportWarning("Preferred units '%s' for type '%s' are not dimensionally correct: ignoring." % (_u, self.getName()) );
				return None

			return _units;
	%}
}

typedef enum{
	ASCXX_INST_STATUS_UNKNOWN=0, ASCXX_VAR_FIXED, ASCXX_VAR_UNSOLVED, ASCXX_VAR_ACTIVE, ASCXX_VAR_SOLVED
	, ASCXX_REL_INACTIVE
} InstanceStatus;

/*
	we really want to get rid of this and just %include... 
*/
class Instanc{
private:
	Instanc();
public:
	Instanc(Instance *);
	Instanc(Instance *, SymChar &name);
	~Instanc();
	std::vector<Instanc> getChildren();
	const std::string getKindStr() const;
	const SymChar &getName();
	const Type getType() const;
	const bool isAtom() const;
	const bool isFixed() const;
	const bool isIncluded() const;
	const bool isFund() const;
	const bool isConst() const;
	const bool isAssigned() const;
	const bool isCompound() const;
	const bool isRelation() const;
	const bool isLogicalRelation() const;
	const bool isWhen() const;
	const bool isSet() const; // a set (group) of things
	const bool isSetInt() const;
	const bool isSetString() const;
	const bool isSetEmpty() const;
	const bool isArray() const;
	const bool isDefined() const;
	const bool isBool() const;
	const bool isInt() const;
	const bool isSymbol() const;
	const bool isReal() const;
	const bool isModel() const;

	const double getRealValue() const;
	const bool isDimensionless() const;
	const Dimensions getDimensions() const;
	const bool getBoolValue() const;
	const long getIntValue() const;
	const SymChar getSymbolValue() const;
	const std::string getValueAsString() const; ///< Use carefully: rounding will occur for doubles!

	const std::string getRelationAsString(const Instanc &relative_to) const;
	const double getResidual() const;
	const bool getLogicalResidual() const;

	Plot getPlot() const;

	const bool isPlottable() const;
	const ASCXX_Set<long> getSetValue<long>() const;
	const ASCXX_Set<SymChar> getSetValue<SymChar>() const;
	const bool isChildless() const;
	void setFixed(const bool &val=true);
	void setIncluded(const bool &val=true);
	void setRealValue(const double &val);
	void setRealValueWithUnits(const double &, const char *);
	void setBoolValue(const bool &val);
	void setIntValue(const long &val);
	void setSymbolValue(const SymChar &sym);
	void write(const char *fname);

	const InstanceStatus getStatus() const;

	void setLowerBound(const double &);
	void setUpperBound(const double &);
	void setNominal(const double &);
	const double getLowerBound() const;
	const double  getUpperBound() const;
	const double  getNominal() const;

	const std::vector<Instanc> getClique() const;
	const std::vector<std::string> getAliases() const;
};

%extend Instanc{
	const char *__repr__(){
		return self->getName().toString();
	}
	Instanc __getattr__(const char *name){
		return self->getChild(SymChar(name));
	}
	Instanc __getitem__(const long &index){
		return self->getChild(index);
	} 
	double __float__(){
		if(self->isReal()){
			return self->getRealValue();
		}else{
			throw std::runtime_error("Can't cast this instance to float");
		}
	}
		
	%pythoncode %{
		def getSetValue(self):
			"""Return the value of a set, as a integer or string Python sequence."""
			if self.isSetInt():
				return self.getSetIntValue()
			elif self.isSetString():
				return self.getSetStringValue()
			elif self.isSetEmpty():
				return set()
			else:
				raise RuntimeError("getSetValue: unknown set type");

		def getValue(self):
			"""Returns an instance value, including units if applicable."""
			#print "GETTING VALUE OF %s" % self.getName()
			if self.isCompound():
				return ""
			elif self.isRelation():
				return self.getResidual()
			elif self.isWhen():
				return "WHEN"
			elif self.isSet():
				_s = set(self.getSetValue());
				#for _v in self.getSetValue():
				#	_s.add( _v )
				return _s

			elif ( self.isAtom() or self.isFund() ) and not self.isDefined():
				return "undefined"
			elif self.isReal():
				return self.getRealValueAndUnits()
			elif self.isBool():
				return self.getBoolValue()
			elif self.isInt():
				return self.getIntValue()
			elif self.isSymbol():
				return self.getSymbolValue()
			elif self.isLogicalRelation():
				return self.getLogicalResidual()
			else:
				return "UNKNOWN TYPE" 
				#raise RuntimeError("Unknown value model type="+self.getType().getName().toString()+", instance kind=".getKindStr())

		def getRealValueAndUnits(self):
			"""Return real-valued instance value as a string, converted to, and including, its preferred units."""
			if not self.isReal():
				raise TypeError
			if self.isFund():
				return self.getRealValue();
			_u = self.getType().getPreferredUnits();
			if _u is None:
				_u = self.getDimensions().getDefaultUnits()
			return _u.getConvertedValue(self.getRealValue())

		def to(self,units):
			"""Returns an instance value converted to specified units."""
			if not self.isReal():
				raise TypeError
			if units.__class__==str:
				units = Units(units);
			if units.__class__!=Units:
				raise TypeError
			return self.getRealValue() / units.getConversion()

		def setFixedValue(self,val):
			"""Set a value to 'fixed', and specify its value, at the same time."""
			if not self.isFixed():
				self.setFixed();
			# getReporter().reportError("Setting value of %s to %s" % (self.getName().toString(),val))
			self.setRealValue(val);

		def __coerce__(self,other):
			if self.isInt():
				if other.__class__==int:
					return self.getIntValue(),int(other)
				elif other.__class__==float:
					return float(self.getIntValue()),other
			elif self.isReal():
				if other.__class__== int:
					return self.getRealValue(),float(other)
				elif other.__class__==float:
					return self.getRealValue(),other
			return str(self),str(other)

		def __sub__(self,other):
			a,b = self.__coerce__(other)
			return a - b

		def __rsub__(self,other):
			a,b = self.__coerce__(other)
			return b - a

		def __add__(self,other):
			a,b = self.__coerce__(other)
			return a + b

		def __radd__(self,other):
			a,b = self.__coerce__(other)
			return b + a
	%}
}

/*
	This 'registry' thing is a bit of a hack that allows interface pointers to 
	be registered with libascend so that they can be accessed from external
	script methods
*/
%include "registry.h"
%extend Registry{
	void set(const char *key, PyObject *obj){
		/* CONSOLE_DEBUG("Registry::set(PyObject *obj=%p)",obj); */
		self->setPyObject(key,obj);
	}
}

void shutdown();

%{
void shutdown(){
	ascshutdown("Shutdown ASCEND...");
}
%}

%include "solver.i"

%include "extmethod.h"

%include "annotation.h"

%include "plot.i"

%ignore Curve::Curve();

%include "curve.h"