MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
PyRun.cpp
Go to the documentation of this file.
1 // PyRun.cpp ---
2 //
3 // Filename: PyRun.cpp
4 // Description:
5 // Author: subha
6 // Maintainer:
7 // Created: Sat Oct 11 14:47:22 2014 (+0530)
8 // Version:
9 // Last-Updated: Fri Jun 19 18:56:06 2015 (-0400)
10 // By: Subhasis Ray
11 // Update #: 15
12 // URL:
13 // Keywords:
14 // Compatibility:
15 //
16 //
17 
18 // Commentary:
19 //
20 //
21 //
22 //
23 
24 // Change log:
25 //
26 //
27 //
28 //
29 // This program is free software; you can redistribute it and/or
30 // modify it under the terms of the GNU General Public License as
31 // published by the Free Software Foundation; either version 3, or
32 // (at your option) any later version.
33 //
34 // This program is distributed in the hope that it will be useful,
35 // but WITHOUT ANY WARRANTY; without even the implied warranty of
36 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
37 // General Public License for more details.
38 //
39 // You should have received a copy of the GNU General Public License
40 // along with this program; see the file COPYING. If not, write to
41 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth
42 // Floor, Boston, MA 02110-1301, USA.
43 //
44 //
45 
46 // Code:
47 
48 #include "Python.h"
49 #include "../basecode/header.h"
50 #include "PyRun.h"
51 
52 const int PyRun::RUNPROC = 1;
53 const int PyRun::RUNTRIG = 2;
54 const int PyRun::RUNBOTH = 0;
55 
57 {
58  static SrcFinfo1< double > outputOut( "output",
59  "Sends out the value of local variable called `output`. Thus, you can"
60  " have Python statements which compute some value and assign it to the"
61  " variable called `output` (which is defined at `reinit` call). This"
62  " will be sent out to any target connected to the `output` field.");
63  return &outputOut;
64 }
65 
66 
68 {
69  static ValueFinfo< PyRun, string > runstring(
70  "runString",
71  "String to be executed at each time step.",
74 
75  static ValueFinfo< PyRun, string > initstring(
76  "initString",
77  "String to be executed at initialization (reinit).",
80 
81  static ValueFinfo< PyRun, string > inputvar(
82  "inputVar",
83  "Name of local variable in which input balue is to be stored. Default"
84  " is `input_` (to avoid conflict with Python's builtin function"
85  " `input`).",
88 
89  static ValueFinfo< PyRun, string > outputvar(
90  "outputVar",
91  "Name of local variable for storing output. Default is `output`.",
94 
95  static ValueFinfo< PyRun, int > mode(
96  "mode",
97  "Flag to indicate whether runString should be executed for both trigger and process, or one of them.",
100 
101  // static ValueFinfo< PyRun, PyObject* > globals(
102  // "globals",
103  // "Global environment dict",
104  // &PyRun::setGlobals,
105  // &PyRun::getGlobals);
106 
107  // static ValueFinfo< PyRun, PyObject* > locals(
108  // "locals",
109  // "Local environment dict",
110  // &PyRun::setLocals,
111  // &PyRun::getLocals);
112 
113  static DestFinfo trigger(
114  "trigger",
115  "Executes the current runString whenever a message arrives. It stores"
116  " the incoming value in local variable named"
117  " `input_`, which can be used in the"
118  " `runString` (the underscore is added to avoid conflict with Python's"
119  " builtin function `input`). If debug is True, it prints the input"
120  " value.",
122 
123  static DestFinfo run(
124  "run",
125  "Runs a specified string. Does not modify existing run or init strings.",
127 
128  static DestFinfo process(
129  "process",
130  "Handles process call. Runs the current runString.",
132 
133  static DestFinfo reinit(
134  "reinit",
135  "Handles reinit call. Runs the current initString.",
137 
138  static Finfo * processShared[] = { &process, &reinit };
139  static SharedFinfo proc(
140  "proc",
141  "This is a shared message to receive Process messages "
142  "from the scheduler objects."
143  "The first entry in the shared msg is a MsgDest "
144  "for the Process operation. It has a single argument, "
145  "ProcInfo, which holds lots of information about current "
146  "time, thread, dt and so on. The second entry is a MsgDest "
147  "for the Reinit operation. It also uses ProcInfo. ",
148  processShared, sizeof( processShared ) / sizeof( Finfo* ));
149 
150  static Finfo * pyRunFinfos[] = {
151  &runstring,
152  &initstring,
153  &mode,
154  &inputvar,
155  &outputvar,
156  &trigger,
157  outputOut(),
158  // &locals,
159  // &globals,
160  &run,
161  &proc,
162  };
163 
164  static string doc[] = {
165  "Name", "PyRun",
166  "Author", "Subhasis Ray",
167  "Description", "Runs Python statements from inside MOOSE."};
168  static Dinfo< PyRun > dinfo;
169  static Cinfo pyRunCinfo(
170  "PyRun",
172  pyRunFinfos,
173  sizeof(pyRunFinfos) / sizeof(Finfo*),
174  &dinfo,
175  doc,
176  sizeof(doc) / sizeof(string));
177  return &pyRunCinfo;
178 }
179 
180 static const Cinfo * pyRunCinfo = PyRun::initCinfo();
181 
182 PyRun::PyRun():mode_(0), initstr_(""), runstr_(""),
183  globals_(0), locals_(0),
184  runcompiled_(0), initcompiled_(0),
185  inputvar_("input_"), outputvar_("output")
186 {
187  locals_ = PyDict_New();
188  if (!locals_){
189  cerr << "Could not initialize locals dict" << endl;
190  return;
191  }
192  PyObject * value = PyFloat_FromDouble(0.0);
193  if (!value && PyErr_Occurred()){
194  PyErr_Print();
195  return;
196  }
197  if (PyDict_SetItemString(locals_, inputvar_.c_str(), value)){
198  PyErr_Print();
199  }
200 }
201 
203 {
204  Py_XDECREF(globals_);
205  Py_XDECREF(locals_);
206 }
207 
208 void PyRun::setRunString(string statement)
209 {
210  runstr_ = statement;
211 }
212 
213 string PyRun::getRunString() const
214 {
215  return runstr_;
216 }
217 
218 void PyRun::setInitString(string statement)
219 {
220  initstr_ = statement;
221 }
222 
223 string PyRun::getInitString() const
224 {
225  return initstr_;
226 }
227 
229 {
230  PyDict_DelItemString(locals_, inputvar_.c_str());
231  inputvar_ = name;
232 }
233 
234 string PyRun::getInputVar() const
235 {
236  return inputvar_;
237 }
238 
240 {
241  PyDict_DelItemString(locals_, outputvar_.c_str());
242  outputvar_ = name;
243 }
244 
245 string PyRun::getOutputVar() const
246 {
247  return outputvar_;
248 }
249 
250 void PyRun::setMode(int flag)
251 {
252  mode_ = flag;
253 }
254 
255 int PyRun::getMode() const
256 {
257  return mode_;
258 }
259 
260 void PyRun::trigger(const Eref& e, double input)
261 {
262  if (!runcompiled_){
263  return;
264  }
265  if (mode_ == 1){
266  return;
267  }
268 
269  PyObject * value = PyDict_GetItemString(locals_, inputvar_.c_str());
270  if (value){
271  Py_DECREF(value);
272  }
273  value = PyFloat_FromDouble(input);
274  if (!value && PyErr_Occurred()){
275  PyErr_Print();
276  }
277  if (PyDict_SetItemString(locals_, inputvar_.c_str(), value)){
278  PyErr_Print();
279  }
280  PyEval_EvalCode(runcompiled_, globals_, locals_);
281  if (PyErr_Occurred()){
282  PyErr_Print ();
283  }
284  value = PyDict_GetItemString(locals_, outputvar_.c_str());
285  if (value){
286  double output = PyFloat_AsDouble(value);
287  if (PyErr_Occurred()){
288  PyErr_Print ();
289  } else {
290  outputOut()->send(e, output);
291  }
292  }
293 }
294 
295 void PyRun::run(const Eref&e, string statement)
296 {
297  PyRun_SimpleString(statement.c_str());
298  PyObject * value = PyDict_GetItemString(locals_, outputvar_.c_str());
299  if (value){
300  double output = PyFloat_AsDouble(value);
301  if (PyErr_Occurred()){
302  PyErr_Print ();
303  } else {
304  outputOut()->send(e, output);
305  }
306  }
307 }
308 
309 void PyRun::process(const Eref & e, ProcPtr p)
310 {
311  // PyRun_String(runstr_.c_str(), 0, globals_, locals_);
312  // PyRun_SimpleString(runstr_.c_str());
313  if (!runcompiled_ || mode_ == 2){
314  return;
315  }
316  PyEval_EvalCode(runcompiled_, globals_, locals_);
317  if (PyErr_Occurred()){
318  PyErr_Print ();
319  }
320  PyObject * value = PyDict_GetItemString(locals_, outputvar_.c_str());
321  if (value){
322  double output = PyFloat_AsDouble(value);
323  if (PyErr_Occurred()){
324  PyErr_Print ();
325  } else {
326  outputOut()->send(e, output);
327  }
328  }
329 }
330 
335 void handleError(bool syntax)
336 {
337  PyObject *exc, *val, *trb;
338  char * msg;
339 
340  if (syntax && PyErr_ExceptionMatches (PyExc_SyntaxError)){
341  PyErr_Fetch (&exc, &val, &trb); /* clears exception! */
342 
343  if (PyArg_ParseTuple (val, "sO", &msg, &trb) &&
344  !strcmp (msg, "unexpected EOF while parsing")){ /* E_EOF */
345  Py_XDECREF (exc);
346  Py_XDECREF (val);
347  Py_XDECREF (trb);
348  } else { /* some other syntax error */
349  PyErr_Restore (exc, val, trb);
350  PyErr_Print ();
351  }
352  } else { /* some non-syntax error */
353  PyErr_Print ();
354  }
355 }
356 
357 void PyRun::reinit(const Eref& e, ProcPtr p)
358 {
359  PyObject * main_module;
360  if (globals_ == NULL){
361  main_module = PyImport_AddModule("__main__");
362  globals_ = PyModule_GetDict(main_module);
363  Py_XINCREF(globals_);
364  }
365  if (locals_ == NULL){
366  locals_ = PyDict_New();
367  if (!locals_){
368  cerr << "Could not initialize locals dict" << endl;
369  }
370  }
371  initcompiled_ = (PYCODEOBJECT*)Py_CompileString(
372  initstr_.c_str(),
373  get_program_name().c_str(),
374  Py_file_input);
375  if (!initcompiled_){
376  cerr << "Error compiling initString" << endl;
377  handleError(true);
378  } else {
379  PyEval_EvalCode(initcompiled_, globals_, locals_);
380  if (PyErr_Occurred()){
381  PyErr_Print ();
382  }
383  }
384  runcompiled_ = (PYCODEOBJECT*)Py_CompileString(
385  runstr_.c_str(),
386  get_program_name().c_str(),
387  Py_file_input);
388  if (!runcompiled_){
389  cerr << "Error compiling runString" << endl;
390  handleError(true);
391  } else {
392  PyEval_EvalCode(runcompiled_, globals_, locals_);
393  if (PyErr_Occurred()){
394  PyErr_Print ();
395  }
396  }
397 }
398 
399 
400 //
401 // PyRun.cpp ends here
uint32_t value
Definition: moosemodule.h:42
string initstr_
Definition: PyRun.h:119
string getOutputVar() const
Definition: PyRun.cpp:245
PYCODEOBJECT * runcompiled_
Definition: PyRun.h:123
void run(const Eref &e, string statement)
Definition: PyRun.cpp:295
PyObject * globals_
Definition: PyRun.h:121
Definition: Dinfo.h:60
Definition: EpFunc.h:64
void process(const Eref &e, ProcPtr p)
Definition: PyRun.cpp:309
void setInitString(string str)
Definition: PyRun.cpp:218
static const Cinfo * pyRunCinfo
Definition: PyRun.cpp:180
static SrcFinfo1< double > * output()
Definition: Arith.cpp:14
static const int RUNPROC
Definition: PyRun.h:80
string runstr_
Definition: PyRun.h:120
void setMode(int flag)
Definition: PyRun.cpp:250
static SrcFinfo1< double > * outputOut()
Definition: PyRun.cpp:56
PyRun()
Definition: PyRun.cpp:182
string get_program_name()
Definition: PyRun.h:67
PYCODEOBJECT * initcompiled_
Definition: PyRun.h:124
int getMode() const
Definition: PyRun.cpp:255
Definition: Eref.h:26
void setOutputVar(string name)
Definition: PyRun.cpp:239
~PyRun()
Definition: PyRun.cpp:202
void reinit(const Eref &e, ProcPtr p)
Definition: PyRun.cpp:357
PyObject * locals_
Definition: PyRun.h:122
string getRunString() const
Definition: PyRun.cpp:213
static const Cinfo * initCinfo()
Definition: PyRun.cpp:67
static char name[]
Definition: mfield.cpp:401
string getInputVar() const
Definition: PyRun.cpp:234
void setRunString(string str)
Definition: PyRun.cpp:208
void handleError(bool syntax)
Definition: PyRun.cpp:335
static const int RUNTRIG
Definition: PyRun.h:81
void trigger(const Eref &e, double input)
Definition: PyRun.cpp:260
string inputvar_
Definition: PyRun.h:125
static const Cinfo * initCinfo()
Definition: Neutral.cpp:16
#define PYCODEOBJECT
Definition: PyRun.h:65
void setInputVar(string name)
Definition: PyRun.cpp:228
int mode_
Definition: PyRun.h:118
string getInitString() const
Definition: PyRun.cpp:223
Definition: Cinfo.h:18
string outputvar_
Definition: PyRun.h:126
Definition: Finfo.h:12
static const int RUNBOTH
Definition: PyRun.h:82