MoDeNa  1.0
Software framework facilitating sequential multi-scale modelling
function.c
1 /*
2 
3  ooo ooooo oooooooooo. ooooo ooo
4  `88. .888' `888' `Y8b `888b. `8'
5  888b d'888 .ooooo. 888 888 .ooooo. 8 `88b. 8 .oooo.
6  8 Y88. .P 888 d88' `88b 888 888 d88' `88b 8 `88b. 8 `P )88b
7  8 `888' 888 888 888 888 888 888ooo888 8 `88b.8 .oP"888
8  8 Y 888 888 888 888 d88' 888 .o 8 `888 d8( 888
9  o8o o888o `Y8bod8P' o888bood8P' `Y8bod8P' o8o `8 `Y888""8o
10 
11 Copyright
12  2014-2016 MoDeNa Consortium, All rights reserved.
13 
14 License
15  This file is part of Modena.
16 
17  The Modena interface library is free software; you can redistribute it
18  and/or modify it under the terms of the GNU Lesser General Public License
19  as published by the Free Software Foundation, either version 3 of the
20  License, or (at your option) any later version.
21 
22  Modena is distributed in the hope that it will be useful, but WITHOUT ANY
23  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
24  FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
25  details.
26 
27  You should have received a copy of the GNU General Public License along
28  with Modena. If not, see <http://www.gnu.org/licenses/>.
29 */
30 
31 #include "function.h"
32 #include "structmember.h"
33 #include "global.h"
34 #include "model.h"
35 
36 PyObject *modena_SurrogateFunction = NULL;
37 
38 void modena_function_load_library(modena_function_t* self)
39 {
40  PyObject *pFunctionName =
41  PyObject_GetAttrString(self->pFunction, "functionName");
42  if(!pFunctionName){ Modena_PyErr_Print(); }
43 
44  PyObject *pLibraryName =
45  PyObject_GetAttrString(self->pFunction, "libraryName");
46  if(!pLibraryName){ Modena_PyErr_Print(); }
47 
48  self->handle = lt_dlopen(PyString_AsString(pLibraryName));
49 
50  if(!self->handle)
51  {
52  Modena_Error_Print
53  (
54  "lt_dlopen: Could not open library %s\nlt_dlopen: %s",
55  PyString_AsString(pLibraryName),
56  lt_dlerror()
57  );
58  exit(1);
59  }
60 
61  self->function = lt_dlsym(self->handle, PyString_AsString(pFunctionName));
62  if(!self->function)
63  {
64  Modena_Error_Print
65  (
66  "lt_dlsym: Could not find function %s in library %s"
67  "lt_dlsym: %s",
68  PyString_AsString(pFunctionName),
69  PyString_AsString(pLibraryName),
70  lt_dlerror()
71  );
72  lt_dlclose(self->handle);
73  exit(1);
74  }
75 
76  Py_DECREF(pFunctionName);
77  Py_DECREF(pLibraryName);
78 
79  PyObject *pInputs =
80  PyObject_GetAttrString(self->pFunction, "inputs");
81  if(!pInputs){ Modena_PyErr_Print(); }
82  self->inputs_size = PyObject_Size(pInputs);
83  Py_DECREF(pInputs);
84 
85  PyObject *pOutputs =
86  PyObject_GetAttrString(self->pFunction, "outputs");
87  if(!pOutputs){ Modena_PyErr_Print(); }
88  self->outputs_size = PyObject_Size(pOutputs);
89  Py_DECREF(pOutputs);
90 
91  PyObject *pParameters =
92  PyObject_GetAttrString(self->pFunction, "parameters");
93  if(!pParameters){ Modena_PyErr_Print(); }
94  self->parameters_size = PyObject_Size(pParameters);
95  Py_DECREF(pParameters);
96 }
97 
98 
99 modena_function_t *modena_function_new
100 (
101  const char *functionId
102 )
103 {
104  //Modena_Info_Print("In %s", __func__);
105 
106  // Initialize the Python Interpreter
107  if(!Py_IsInitialized())
108  {
109  Py_Initialize();
110  }
111 
112  // Initialize this module
113  initlibmodena();
114 
115  PyObject *args = PyTuple_New(0);
116  PyObject *kw = Py_BuildValue("{s:s}", "functionId", functionId);
117 
118  PyObject *pNewObj = PyObject_Call
119  (
120  (PyObject *) &modena_function_tType,
121  args,
122  kw
123  );
124 
125  Py_DECREF(args);
126  Py_DECREF(kw);
127  if(!pNewObj)
128  {
129  if(PyErr_ExceptionMatches(modena_DoesNotExist))
130  {
131  PyErr_Clear();
132 
133  PyObject *pRet = PyObject_CallMethod
134  (
135  modena_SurrogateFunction,
136  "exceptionLoad",
137  "(z)",
138  functionId
139  );
140  if(!pRet){ Modena_PyErr_Print(); }
141  int ret = PyInt_AsLong(pRet);
142  Py_DECREF(pRet);
143 
144  modena_error_code = ret;
145  return NULL;
146  }
147  else
148  {
149  Modena_PyErr_Print();
150  }
151  }
152 
153 
154  modena_function_t *self = (modena_function_t *) pNewObj;
155 
156  if(lt_dlinit())
157  {
158  Modena_Error_Print("lt_dlinit: %s", lt_dlerror());
159  exit(1);
160  }
161 
162  modena_function_load_library(self);
163 
164  return self;
165 }
166 
167 modena_function_t *modena_function_new_from_model
168 (
169  const modena_model_t *m
170 )
171 {
172  //Modena_Info_Print("In %s", __func__);
173 
174  modena_function_t *self = malloc(sizeof(modena_function_t));
175 
176  if(lt_dlinit())
177  {
178  Modena_Error_Print("lt_dlinit: %s", lt_dlerror());
179  exit(1);
180  }
181 
182  self->pFunction =
183  PyObject_GetAttrString(m->pModel, "surrogateFunction");
184  if(!self->pFunction){ Modena_PyErr_Print(); }
185 
186  modena_function_load_library(self);
187 
188  return self;
189 }
190 
191 modena_index_set_t *modena_function_get_index_set
192 (
193  const modena_function_t* self,
194  const char* name
195 )
196 {
197  PyObject *pRet = PyObject_CallMethod
198  (
199  self->pFunction,
200  "indexSet",
201  "(z)",
202  name
203  );
204  if(!pRet){ Modena_PyErr_Print(); }
205 
206  PyObject *args = PyTuple_New(0);
207  PyObject *kw = Py_BuildValue("{s:O}", "indexSet", pRet);
208 
209  PyObject *pNewObj = PyObject_Call
210  (
211  (PyObject *) &modena_index_set_tType,
212  args,
213  kw
214  );
215 
216  Py_DECREF(args);
217  Py_DECREF(kw);
218  if(!pNewObj)
219  {
220  Modena_PyErr_Print();
221  }
222 
223  return (modena_index_set_t *) pNewObj;
224 }
225 
226 /* Destructor, deallocates the memory block occupied by a surrogate function
227  */
228 void modena_function_destroy(modena_function_t *self)
229 {
230  lt_dlclose(self->handle);
231  lt_dlexit();
232  Py_XDECREF(self->pFunction);
233  free(self);
234 }
235 
236 /* C-Python: Destructor, exposed as the __del__ method in Python.
237  */
238 static void modena_function_t_dealloc(modena_function_t* self)
239 {
240  modena_function_destroy(self);
241 }
242 
243 /* C-Python: Member-Table
244  *
245  * Structure which describes an attribute of a type which corresponds to a C
246  * struct member. Its fields are:
247  *
248  * Field C Type Meaning
249  * ------ ---------- --------------------------------------------------------
250  * name char * name of the member
251  * type int the type of the member in the C struct
252  * offset Py_ssize_t the offset in bytes that the member is located on the
253  * type's object struct
254  * flags int flag bits indicating if the field should be read-only or
255  * writable
256  * doc char * points to the contents of the docstring
257  */
258 static PyMemberDef modena_function_t_members[] = {
259  {NULL} /* Sentinel */
260 };
261 
262 /* C-Python: Method-Table
263  *
264  * Structure used to describe a method of an extension type. This structure has
265  * four fields:
266  *
267  * Field C Type Meaning
268  * ------- ----------- ----------------------------------------------------
269  * ml_name char * name of the method
270  * ml_meth PyCFunction pointer to the C implementation
271  * ml_flags int flag bits indicating how the call should be
272  * constructed
273  * ml_doc char * points to the contents of the docstring
274  */
275 static PyMethodDef modena_function_t_methods[] = {
276  {NULL} /* Sentinel */
277 };
278 
279 /* C-Python: Initialiser, exposed in Python as the method: __init__
280  */
281 static int modena_function_t_init
282 (
283  modena_function_t *self,
284  PyObject *args,
285  PyObject *kwds
286 )
287 {
288  PyObject *pFunction=NULL;
289  char *functionId=NULL;
290 
291  static char *kwlist[] = {"function", "functionId", NULL};
292 
293  if
294  (
295  !PyArg_ParseTupleAndKeywords
296  (
297  args,
298  kwds,
299  "|Os",
300  kwlist,
301  &pFunction,
302  &functionId
303  )
304  )
305  {
306  Modena_PyErr_Print();
307  }
308 
309  if(!pFunction)
310  {
311  self->pFunction = PyObject_CallMethod
312  (
313  modena_SurrogateFunction,
314  "load",
315  "(z)",
316  functionId
317  );
318 
319  if(!self->pFunction)
320  {
321  PyErr_SetString(modena_DoesNotExist, "Function does not exist");
322 
323  Modena_PyErr_Print();
324  }
325  }
326  else
327  {
328  Py_INCREF(pFunction);
329  self->pFunction = pFunction;
330  }
331 
332  // Shouldn't I load the function from the library here?
333 
334  PyObject *pParameters =
335  PyObject_GetAttrString(self->pFunction, "parameters");
336  if(!pParameters){ Modena_PyErr_Print(); }
337  self->parameters_size = PyObject_Size(pParameters);
338  Py_DECREF(pParameters);
339 
340  return 0;
341 }
342 
343 /* C-Python: Constructor, exposed in Python as the method: __new__
344  */
345 static PyObject *modena_function_t_new
346 (
347  PyTypeObject *type,
348  PyObject *args,
349  PyObject *kwds
350 )
351 {
352  modena_function_t *self;
353 
354  self = (modena_function_t *)type->tp_alloc(type, 0);
355  if(self)
356  {
357  self->pFunction = NULL;
358  self->parameters_size = 0;
359  }
360 
361  return (PyObject *)self;
362 }
363 
364 /* C-Python: The C structure used to describe the modena_model type.
365  */
366 PyTypeObject modena_function_tType = {
367  PyObject_HEAD_INIT(NULL)
368  0, /*ob_size*/
369  "modena.modena_function_t", /*tp_name*/
370  sizeof(modena_function_t), /*tp_basicsize*/
371  0, /*tp_itemsize*/
372  (destructor)modena_function_t_dealloc, /*tp_dealloc*/
373  0, /*tp_print*/
374  0, /*tp_getattr*/
375  0, /*tp_setattr*/
376  0, /*tp_compare*/
377  0, /*tp_repr*/
378  0, /*tp_as_number*/
379  0, /*tp_as_sequence*/
380  0, /*tp_as_mapping*/
381  0, /*tp_hash */
382  0, /*tp_call*/
383  0, /*tp_str*/
384  0, /*tp_getattro*/
385  0, /*tp_setattro*/
386  0, /*tp_as_buffer*/
387  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
388  "modena_function_t objects", /* tp_doc */
389  0, /* tp_traverse */
390  0, /* tp_clear */
391  0, /* tp_richcompare */
392  0, /* tp_weaklistoffset */
393  0, /* tp_iter */
394  0, /* tp_iternext */
395  modena_function_t_methods, /* tp_methods */
396  modena_function_t_members, /* tp_members */
397  0, /* tp_getset */
398  0, /* tp_base */
399  0, /* tp_dict */
400  0, /* tp_descr_get */
401  0, /* tp_descr_set */
402  0, /* tp_dictoffset */
403  (initproc)modena_function_t_init, /* tp_init */
404  0, /* tp_alloc */
405  modena_function_t_new, /* tp_new */
406 };
PyObject_HEAD PyObject * pModel
Definition: model.h:98
struct modena_function_t modena_function_t
stores a surrogate model
Definition: model.h:94
m
Bubble Growth Application Recipe.
Definition: bubbleGrowth.py:59