MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
mfield.cpp
Go to the documentation of this file.
1 // mfield.cpp ---
2 //
3 // Filename: mfield.cpp
4 // Description:
5 // Author:
6 // Maintainer:
7 // Created: Mon Jul 22 17:03:03 2013 (+0530)
8 // Version:
9 // Last-Updated: Fri Jan 22 11:50:17 2016 (-0500)
10 // By: Subhasis Ray
11 // Update #: 16
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 <structmember.h> // This defines the type id macros like T_STRING
50 // #include "numpy/arrayobject.h"
51 
52 #include <iostream>
53 #include <typeinfo>
54 #include <cstring>
55 #include <map>
56 #include <ctime>
57 
58 #include "../basecode/header.h"
59 #include "../basecode/Id.h"
60 #include "../basecode/ObjId.h"
61 #include "../utility/utility.h"
62 #include "../shell/Shell.h"
63 
64 #include "moosemodule.h"
65 
66 using namespace std;
67 
68 
69 extern PyTypeObject ObjIdType;
70 extern PyTypeObject IdType;
71 
72 // Does not get called at all by PyObject_New. See:
73 // http://www.velocityreviews.com/forums/t344033-pyobject_new-not-running-tp_new-for-iterators.html
74 // static PyObject * moose_Field_new(PyTypeObject *type,
75 // PyObject *args, PyObject *kwds)
76 // {
77 // _Field *self = NULL;
78 // self = (_Field*)type->tp_alloc(type, 0);
79 // if (self != NULL){
80 // self->name = NULL;
81 // self->owner = ObjId::bad;
82 // }
83 // return (PyObject*)self;
84 // }
85 
89 int moose_Field_init(_Field * self, PyObject * args, PyObject * kwargs)
90 {
91  PyObject * owner;
92  char * fieldName;
93  if (!PyArg_ParseTuple(args, "Os:moose_Field_init", &owner, &fieldName))
94  {
95  return -1;
96  }
97  if (fieldName == NULL)
98  {
99  PyErr_SetString(PyExc_ValueError, "fieldName cannot be NULL");
100  return -1;
101  }
102  if (owner == NULL)
103  {
104  PyErr_SetString(PyExc_ValueError, "owner cannot be NULL");
105  return -1;
106  }
107  if (!PyObject_IsInstance(owner, (PyObject*)&ObjIdType))
108  {
109  PyErr_SetString(PyExc_TypeError, "Owner must be subtype of ObjId");
110  return -1;
111  }
112  if (!Id::isValid(((_ObjId*)owner)->oid_.id))
113  {
114  Py_DECREF(self);
115  RAISE_INVALID_ID(-1, "moose_Field_init");
116  }
117  self->owner = ((_ObjId*)owner);
118  Py_INCREF(self->owner);
119  self->name = strdup(fieldName);
120  if (!self->name) {
121  PyErr_NoMemory();
122  return -1;
123  }
124 
125  // In earlier version I tried to deallocate the existing
126  // self->name if it is not NULL. But it turns out that it
127  // causes a SIGABRT. In any case it should not be an issue as
128  // we can safely assume __init__ will be called only once in
129  // this case. The Fields are created only internally at
130  // initialization of the MOOSE module.
131  return 0;
132 }
133 
135 {
136  Py_DECREF(self->owner);
137  Py_TYPE(self)->tp_free((PyObject*)self);
138 }
139 
140 
143 {
144  if (!Id::isValid(self->owner->oid_.id))
145  {
146  RAISE_INVALID_ID(-1, "moose_Field_hash");
147  }
148  string fieldPath = self->owner->oid_.path() + "." + self->name;
149  PyObject * path = PyString_FromString(fieldPath.c_str());
150  long hash = PyObject_Hash(path);
151  Py_XDECREF(path);
152  return hash;
153 }
154 
156 PyObject * moose_Field_repr(_Field * self)
157 {
158  if (!Id::isValid(self->owner->oid_.id))
159  {
160  RAISE_INVALID_ID(NULL, "moose_Field_repr");
161  }
162  ostringstream fieldPath;
163  fieldPath << self->owner->oid_.path() << "." << self->name;
164  return PyString_FromString(fieldPath.str().c_str());
165 }
166 
167 PyDoc_STRVAR(moose_Field_documentation,
168  "Base class for MOOSE fields.\n"
169  "\n"
170  "Instances contain the field name and a pointer to the owner\n"
171  "object. Note on hash: the Field class is hashable but the hash is\n"
172  "constructed from the path of the container element and the field\n"
173  "name. Hence changing the name of the container element will cause the\n"
174  "hash to change. This is rather unusual in a moose script, but if you\n"
175  "are putting fields as dictionary keys, you should do that after names\n"
176  "of all elements have been finalized.\n"
177  "\n");
178 static PyTypeObject moose_Field =
179 {
180  PyVarObject_HEAD_INIT(NULL, 0)
181  "moose.Field", /* tp_name */
182  sizeof(_Field), /* tp_basicsize */
183  0, /* tp_itemsize */
184  (destructor)moose_Field_dealloc, /* tp_dealloc */
185  0, /* tp_print */
186  0, /* tp_getattr */
187  0, /* tp_setattr */
188  0, /* tp_compare */
189  (reprfunc)moose_Field_repr, /* tp_repr */
190  0, /* tp_as_number */
191  0, /* tp_as_sequence */
192  0, /* tp_as_mapping */
193  (hashfunc)moose_Field_hash, /* tp_hash */
194  0, /* tp_call */
195  (reprfunc)moose_Field_repr, /* tp_str */
196  0, /* tp_getattro */
197  PyObject_GenericSetAttr, /* tp_setattro */
198  0, /* tp_as_buffer */
199  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
200  moose_Field_documentation,
201  0, /* tp_traverse */
202  0, /* tp_clear */
203  0, /* tp_richcompare */
204  0, /* tp_weaklistoffset */
205  0, /* tp_iter */
206  0, /* tp_iternext */
207  0, /* tp_methods */
208  0, /* tp_members */
209  0, /* tp_getset */
210  0, /* tp_base */
211  0, /* tp_dict */
212  0, /* tp_descr_get */
213  0, /* tp_descr_set */
214  0, /* tp_dictoffset */
215  (initproc)moose_Field_init, /* tp_init */
216  0, /* tp_alloc */
217  0, /* tp_new */
218  0, /* tp_free */
219 };
220 
221 PyObject * moose_LookupField_getItem(_Field * self, PyObject * key)
222 {
223  return getLookupField(self->owner->oid_, self->name, key);
224 }
225 
226 int moose_LookupField_setItem(_Field * self, PyObject * key,
227  PyObject * value)
228 {
229  return setLookupField(self->owner->oid_,
230  self->name, key, value);
231 }
232 
236 static PyMappingMethods LookupFieldMappingMethods =
237 {
238  0,
239  (binaryfunc)moose_LookupField_getItem,
240  (objobjargproc)moose_LookupField_setItem,
241 };
242 
243 PyDoc_STRVAR(moose_LookupField_documentation,
244  "LookupField is dictionary-like fields that map keys to values.\n"
245  "The keys need not be fixed, as in case of interpolation tables,\n"
246  "keys can be any number and the corresponding value is dynamically\n"
247  "computed by the method of interpolation.\n"
248  "Use moose.doc('classname.fieldname') to display builtin\n"
249  "documentation for `field` in class `classname`.\n"
250  "\n"
251  );
252 PyTypeObject moose_LookupField =
253 {
254  PyVarObject_HEAD_INIT(NULL, 0)
255  "moose.LookupField", /* tp_name */
256  sizeof(_Field), /* tp_basicsize */
257  0, /* tp_itemsize */
258  0, /* tp_dealloc */
259  0, /* tp_print */
260  0, /* tp_getattr */
261  0, /* tp_setattr */
262  0, /* tp_compare */
263  (reprfunc)moose_Field_repr, /* tp_repr */
264  0, /* tp_as_number */
265  0, /* tp_as_sequence */
266  &LookupFieldMappingMethods, /* tp_as_mapping */
267  (hashfunc)moose_Field_hash, /* tp_hash */
268  0, /* tp_call */
269  (reprfunc)moose_Field_repr, /* tp_str */
270  0, /* tp_getattro */
271  PyObject_GenericSetAttr, /* tp_setattro */
272  0, /* tp_as_buffer */
273  Py_TPFLAGS_DEFAULT,
274  moose_LookupField_documentation,
275  0, /* tp_traverse */
276  0, /* tp_clear */
277  0, /* tp_richcompare */
278  0, /* tp_weaklistoffset */
279  0, /* tp_iter */
280  0, /* tp_iternext */
281  0, /* tp_methods */
282  0, /* tp_members */
283  0, /* tp_getset */
284  &moose_Field, /* tp_base */
285  0, /* tp_dict */
286  0, /* tp_descr_get */
287  0, /* tp_descr_set */
288  0, /* tp_dictoffset */
289  (initproc)moose_Field_init, /* tp_init */
290  0, /* tp_alloc */
291  0, /* tp_new */
292  0, /* tp_free */
293 };
294 
295 
296 PyObject * moose_DestField_call(PyObject * self, PyObject * args,
297  PyObject * kw)
298 {
299  // copy the name as the first argument into a new argument tuple.
300  PyObject * newargs = PyTuple_New(PyTuple_Size(args)+1); // one extra for the field name
301  PyObject * name = PyString_FromString(((_Field*)self)->name);
302  if (name == NULL)
303  {
304  Py_DECREF(newargs);
305  return NULL;
306  }
307  if (PyTuple_SetItem(newargs, 0, name) != 0)
308  {
309  Py_DECREF(newargs);
310  // Py_DECREF(name);
311  return NULL;
312  }
313  // copy the arguments in `args` into the new argument tuple
314  Py_ssize_t argc = PyTuple_Size(args);
315  for (Py_ssize_t ii = 0; ii < argc; ++ii)
316  {
317  PyObject * arg = PyTuple_GetItem(args, ii);
318  Py_INCREF(arg);
319  PyTuple_SetItem(newargs, ii+1, arg);
320  //Py_DECREF(arg);
321  }
322  // Call ObjId._setDestField with the new arguments
323  PyObject * ret = moose_ObjId_setDestField(((_Field*)self)->owner, newargs);
324  return ret;
325 }
326 
327 PyDoc_STRVAR(moose_DestField_documentation,
328  "DestField is a method field, i.e. it can be called like a function.\n"
329  "Use moose.doc('classname.fieldname') to display builtin\n"
330  "documentation for `field` in class `classname`.\n");
331 
332 
333 PyTypeObject moose_DestField =
334 {
335  PyVarObject_HEAD_INIT(NULL, 0)
336  "moose.DestField", /* tp_name */
337  sizeof(_Field), /* tp_basicsize */
338  0, /* tp_itemsize */
339  0, /* tp_dealloc */
340  0, /* tp_print */
341  0, /* tp_getattr */
342  0, /* tp_setattr */
343  0, /* tp_compare */
344  (reprfunc)moose_Field_repr, /* tp_repr */
345  0, /* tp_as_number */
346  0, /* tp_as_sequence */
347  0, /* tp_as_mapping */
348  (hashfunc)moose_Field_hash, /* tp_hash */
349  moose_DestField_call, /* tp_call */
350  (reprfunc)moose_Field_repr, /* tp_str */
351  0, /* tp_getattro */
352  PyObject_GenericSetAttr, /* tp_setattro */
353  0, /* tp_as_buffer */
354  Py_TPFLAGS_DEFAULT,
355  moose_DestField_documentation,
356  0, /* tp_traverse */
357  0, /* tp_clear */
358  0, /* tp_richcompare */
359  0, /* tp_weaklistoffset */
360  0, /* tp_iter */
361  0, /* tp_iternext */
362  0, /* tp_methods */
363  0, /* tp_members */
364  0, /* tp_getset */
365  &moose_Field, /* tp_base */
366  0, /* tp_dict */
367  0, /* tp_descr_get */
368  0, /* tp_descr_set */
369  0, /* tp_dictoffset */
370  (initproc)moose_Field_init, /* tp_init */
371  0, /* tp_alloc */
372  0, /* tp_new */
373  0, /* tp_free */
374 };
375 
376 PyDoc_STRVAR(moose_ElementField_documentation,
377  "ElementField represents fields that are themselves elements. For\n"
378  "example, synapse in an IntFire neuron. Element fields can be traversed\n"
379  "like a sequence. Additionally, you can set the number of entries by\n"
380  "setting the `num` attribute to a desired value.\n");
381 
382 PyDoc_STRVAR(moose_ElementField_num_documentation,
383  "Number of entries in the field.");
384 
385 PyDoc_STRVAR(moose_ElementField_path_documentation,
386  "Path of the field element.");
387 
388 PyDoc_STRVAR(moose_ElementField_name_documentation,
389  "Name of the field element.");
390 
391 PyDoc_STRVAR(moose_ElementField_owner_documentation,
392  "Reference to owner element of the field element.");
393 
394 PyDoc_STRVAR(moose_ElementField_id_documentation,
395  "Id of the field element.");
396 
397 PyDoc_STRVAR(moose_ElementField_dataId_documentation,
398  "dataIndex of the field element");
399 
400 /* These static defs are required for compiler complaining about string literals. */
401 static char name[] = "name";
402 static char numfield[] = "num";
403 static char path[] = "path";
404 static char id[] = "vec";
405 static char owner[] = "owner";
406 static char dataIndex[] = "dataIndex";
407 char emptyString[] = "";
408 static PyGetSetDef ElementFieldGetSetters[] =
409 {
410  {
411  numfield,
414  moose_ElementField_num_documentation,
415  NULL
416  },
417  {
418  path,
420  NULL,
421  moose_ElementField_path_documentation,
422  NULL
423  },
424  {
425  id,
426  (getter)moose_ElementField_getId,
427  NULL,
428  moose_ElementField_id_documentation,
429  NULL
430  },
431  {
432  name,
434  NULL,
435  moose_ElementField_name_documentation,
436  NULL
437  },
438  {
439  owner,
441  NULL,
442  moose_ElementField_owner_documentation,
443  NULL
444  },
445  {
446  dataIndex,
448  NULL,
449  moose_ElementField_dataId_documentation,
450  NULL
451  },
452  {NULL}, /* sentinel */
453 };
454 
455 static PySequenceMethods ElementFieldSequenceMethods =
456 {
457  (lenfunc)moose_ElementField_getLen, // sq_length
458  0, //sq_concat
459  0, //sq_repeat
460  (ssizeargfunc)moose_ElementField_getItem, //sq_item
461 #ifndef PY3K
462  (ssizessizeargfunc)moose_ElementField_getSlice, // getslice
463 #endif
464  0, //sq_ass_item
465 #ifndef PY3K
466  0, // setslice
467 #endif
468  0, // sq_contains
469  0, // sq_inplace_concat
470  0 // sq_inplace_repeat
471 };
472 
473 PyTypeObject moose_ElementField =
474 {
475  PyVarObject_HEAD_INIT(NULL, 0)
476  "moose.ElementField", /* tp_name */
477  sizeof(_Field), /* tp_basicsize */
478  0, /* tp_itemsize */
479  0, /* tp_dealloc */
480  0, /* tp_print */
481  0, /* tp_getattr */
482  0, /* tp_setattr */
483  0, /* tp_compare */
484  (reprfunc)moose_Field_repr, /* tp_repr */
485  0, /* tp_as_number */
486  &ElementFieldSequenceMethods, /* tp_as_sequence */
487  0, /* tp_as_mapping */
488  (hashfunc)moose_Field_hash, /* tp_hash */
489  0, /* tp_call */
490  (reprfunc)moose_Field_repr, /* tp_str */
491  (getattrofunc)moose_ElementField_getattro, /* tp_getattro */
492  (setattrofunc)moose_ElementField_setattro, /* tp_setattro */
493  0, /* tp_as_buffer */
494  Py_TPFLAGS_DEFAULT,
495  moose_ElementField_documentation,
496  0, /* tp_traverse */
497  0, /* tp_clear */
498  0, // (richcmpfunc)moose_ElementField_richcmp, /* tp_richcompare */
499  0, /* tp_weaklistoffset */
500  0, /* tp_iter */
501  0, /* tp_iternext */
502  0, /* tp_methods */
503  0, /* tp_members */
504  ElementFieldGetSetters, /* tp_getset */
505  &moose_Field, /* tp_base */
506  0, /* tp_dict */
507  0, /* tp_descr_get */
508  0, /* tp_descr_set */
509  0, /* tp_dictoffset */
510  (initproc)moose_ElementField_init, /* tp_init */
511  0, /* tp_alloc */
512  0, /* tp_new */
513  0, /* tp_free */
514 };
515 
519 int moose_ElementField_init(_Field * self, PyObject * args, PyObject * kwargs)
520 {
521  moose_Field_init(self, args, kwargs);
522  string path = self->owner->oid_.path()+"/";
523  path += string(self->name);
524  self->myoid = ObjId(path);
525  return 0;
526 }
527 
528 PyObject * moose_ElementField_getNum(_Field * self, void * closure)
529 {
530  if (self->owner->oid_.bad())
531  {
532  RAISE_INVALID_ID(NULL, "moose_ElementField_getNum");
533  }
534  string name = self->name;
535  name[0] = std::toupper( name[0] );
536  unsigned int num = Field<unsigned int>::get(self->myoid, "numField");
537  return Py_BuildValue("I", num);
538 }
539 
540 int moose_ElementField_setNum(_Field * self, PyObject * args, void * closure)
541 {
542  if (self->owner->oid_.bad())
543  {
544  RAISE_INVALID_ID(-1, "moose_ElementField_setNum");
545  }
546  unsigned int num;
547  if (!PyInt_Check(args))
548  {
549  PyErr_SetString(PyExc_TypeError, "moose.ElementField.setNum - needes an integer.");
550  return -1;
551  }
552  num = PyInt_AsUnsignedLongMask(args);
553  if (!Field<unsigned int>::set(self->myoid, "numField", num))
554  {
555  PyErr_SetString(PyExc_RuntimeError, "moose.ElementField.setNum : Field::set returned False.");
556  return -1;
557  }
558  return 0;
559 }
560 
561 Py_ssize_t moose_ElementField_getLen(_Field * self, void * closure)
562 {
563  if (self->owner->oid_.bad())
564  {
565  RAISE_INVALID_ID(-1, "moose_ElementField_getLen");
566  }
567  unsigned int num = Field<unsigned int>::get(self->myoid, "numField");
568  return Py_ssize_t(num);
569 }
570 
571 PyObject * moose_ElementField_getPath(_Field * self, void * closure)
572 {
573  if (!Id::isValid(self->owner->oid_.id))
574  {
575  RAISE_INVALID_ID(NULL, "moose_ElementField_setNum");
576  }
577  string path = Id(self->owner->oid_.path() + "/" + string(self->name)).path();
578  return Py_BuildValue("s", path.c_str());
579 }
580 
581 PyObject * moose_ElementField_getId(_Field * self, void * closure)
582 {
583  if (self->owner->oid_.bad())
584  {
585  RAISE_INVALID_ID(NULL, "moose_ElementField_setNum");
586  }
587  Id myId(self->owner->oid_.path() + "/" + string(self->name));
588  _Id * new_id = PyObject_New(_Id, &IdType);
589  new_id->id_ = myId;
590  return (PyObject*)new_id;
591 }
592 
593 PyObject * moose_ElementField_getName(_Field * self, void * closure)
594 {
595  return Py_BuildValue("s", self->name);
596 }
597 PyObject * moose_ElementField_getOwner(_Field * self, void * closure)
598 {
599  Py_INCREF(self->owner);
600  return (PyObject*)self->owner;
601 }
602 PyObject * moose_ElementField_getDataId(_Field * self, void * closure)
603 {
604  if (self->owner->oid_.bad())
605  {
606  RAISE_INVALID_ID(NULL, "moose_ElementField_getItem");
607  }
608  return Py_BuildValue("I", self->owner->oid_.dataIndex);
609 }
610 
611 PyObject * moose_ElementField_getItem(_Field * self, Py_ssize_t index)
612 {
613  if (self->owner->oid_.bad())
614  {
615  RAISE_INVALID_ID(NULL, "moose_ElementField_getItem");
616  }
617  int len = Field<unsigned int>::get(self->myoid, "numField");
618  assert(len >= 0);
619  if (index >= len)
620  {
621  PyErr_SetString(PyExc_IndexError, "moose.ElementField.getItem: index out of bounds.");
622  return NULL;
623  }
624  if (index < 0)
625  {
626  index += len;
627  }
628  if (index < 0)
629  {
630  PyErr_SetString(PyExc_IndexError, "moose.ElementField.getItem: invalid index.");
631  return NULL;
632  }
633  // _ObjId * oid = PyObject_New(_ObjId, &ObjIdType);
634  // cout << "Element field: " << self->name << ", owner: " << self->owner->oid_.path() << endl;
635  // stringstream path;
636  // path << self->owner->oid_.path() << "/" << self->name << "[" << index << "]";
637  // cout << "moose_ElementField_getItem:: path=" << path.str();
638  // oid->oid_ = ObjId(self->myoid.id, self->myoid.dataIndex, index);
639  // return (PyObject*)oid;
640  ObjId oid(self->myoid.id, self->myoid.dataIndex, index);
641  return oid_to_element(oid);
642 }
643 
644 PyObject * moose_ElementField_getSlice(_Field * self, Py_ssize_t start, Py_ssize_t end)
645 {
646  assert(start >= 0);
647  assert(end >= 0);
648 
649  if (self->owner->oid_.bad())
650  {
651  RAISE_INVALID_ID(NULL, "moose_ElementField_getSlice");
652  }
653  Py_ssize_t len = Field<unsigned int>::get(self->myoid, "numField");
654  while (start < 0)
655  {
656  start += len;
657  }
658  while (end < 0)
659  {
660  end += len;
661  }
662  if (start > end)
663  {
664  // PyErr_SetString(PyExc_IndexError, "Start index must be less than end.");
665  // return NULL;
666  // Python itself returns empty tuple in such cases, follow that
667  return PyTuple_New(0);
668  }
669  PyObject * ret = PyTuple_New((Py_ssize_t)(end - start));
670  for ( int ii = start; ii < end; ++ii)
671  {
672  ObjId oid(self->myoid.id, self->myoid.dataIndex, ii);
673  PyObject * value = oid_to_element(oid);
674  if (PyTuple_SetItem(ret, (Py_ssize_t)(ii-start), value))
675  {
676  Py_XDECREF(ret);
677  // Py_XDECREF(value);
678  PyErr_SetString(PyExc_RuntimeError, "Could not assign tuple entry.");
679  return NULL;
680  }
681  }
682  return ret;
683 }
684 
685 PyObject * moose_ElementField_getattro(_Field * self, PyObject * attr)
686 {
687  int new_attr = 0;
688  PyObject * ret = NULL;
689  if (self->owner->oid_.bad())
690  {
691  RAISE_INVALID_ID(NULL, "moose_ElementField_getSlice");
692  }
693  char * field = PyString_AsString(attr);
694  string className = Field<string>::get(self->myoid, "className");
695  string type = getFieldType(className, field);
696  if (type.empty())
697  {
698  // Check if this field name is aliased and update fieldname and type if so.
699  map<string, string>::const_iterator it = get_field_alias().find(string(field));
700  if (it != get_field_alias().end())
701  {
702  field = const_cast<char*>((it->second).c_str());
703  type = getFieldType(Field<string>::get(self->myoid, "className"), it->second);
704  // Update attr for next level (PyObject_GenericGetAttr) in case.
705  new_attr = 1;
706  attr = PyString_FromString(field);
707  }
708  }
709  if (type.empty())
710  {
711  ret = PyObject_GenericGetAttr((PyObject*)self, attr);
712  if (new_attr)
713  {
714  Py_DECREF(attr);
715  return ret;
716  }
717  }
718  char ftype = shortType(type);
719  switch (ftype)
720  {
721  case 'd':
722  {
723  vector < double > val;
724  Field< double >::getVec(self->myoid, string(field), val);
725  ret = to_pytuple(&val, ftype);
726  break;
727  }
728  case 's':
729  {
730  vector < string > val;
731  Field< string >::getVec(self->myoid, string(field), val);
732  ret = to_pytuple(&val, ftype);
733  break;
734  }
735  case 'l':
736  {
737  vector < long > val;
738  Field< long >::getVec(self->myoid, string(field), val);
739  ret = to_pytuple(&val, ftype);
740  break;
741  }
742  case 'x':
743  {
744  vector < Id > val;
745  Field< Id >::getVec(self->myoid, string(field), val);
746  ret = to_pytuple(&val, ftype);
747  break;
748  }
749  case 'y':
750  {
751  vector < ObjId > val;
752  Field< ObjId >::getVec(self->myoid, string(field), val);
753  ret = to_pytuple(&val, ftype);
754  break;
755  }
756  case 'i':
757  {
758  vector < int > val;
759  Field< int >::getVec(self->myoid, string(field), val);
760  ret = to_pytuple(&val, ftype);
761  break;
762  }
763  case 'I':
764  {
765  vector < unsigned int > val;
766  Field< unsigned int >::getVec(self->myoid, string(field), val);
767  ret = to_pytuple(&val, ftype);
768  break;
769  }
770  case 'k':
771  {
772  vector < unsigned long > val;
773  Field< unsigned long >::getVec(self->myoid, string(field), val);
774  ret = to_pytuple(&val, ftype);
775  break;
776  }
777  case 'f':
778  {
779  vector < float > val;
780  Field< float >::getVec(self->myoid, string(field), val);
781  ret = to_pytuple(&val, ftype);
782  break;
783  }
784  case 'b':
785  {
786  vector<bool> val;
787  Field< bool >::getVec(self->myoid, string(field), val);
788  ret = to_pytuple(&val, ftype);
789  break;
790  }
791  case 'c':
792  {
793  vector < char > val;
794  Field< char >::getVec(self->myoid, string(field), val);
795  ret = to_pytuple(&val, ftype);
796  break;
797  }
798  case 'h':
799  {
800  vector < short > val;
801  Field< short >::getVec(self->myoid, string(field), val);
802  ret = to_pytuple(&val, ftype);
803  break;
804  }
805  case 'z':
806  {
807  PyErr_SetString(PyExc_NotImplementedError, "DataId handling not implemented yet.");
808  break;
809  }
810  case 0:
811  {
812  ret = PyObject_GenericGetAttr((PyObject*)self, attr);
813  break;
814  }
815  default:
816  PyErr_SetString(PyExc_ValueError, "unhandled field type.");
817  break;
818  }
819  if (new_attr)
820  {
821  Py_DECREF(attr);
822  }
823  return ret;
824 }
825 
826 int moose_ElementField_setattro(_Field * self, PyObject * attr, PyObject * value)
827 {
828  if (!Id::isValid(self->myoid))
829  {
830  RAISE_INVALID_ID(-1, "moose_ElementField_setattro");
831  }
832  int ret = -1;
833  string field;
834  if (PyString_Check(attr))
835  {
836  field = string(PyString_AsString(attr));
837  }
838  else
839  {
840  PyErr_SetString(PyExc_TypeError, "Attribute name must be a string");
841  return -1;
842  }
843  string moose_class = Field<string>::get(self->myoid, "className");
844  string fieldtype = getFieldType(moose_class, field);
845  if (fieldtype.length() == 0)
846  {
847  if (field == "num")
848  {
849  return PyObject_GenericSetAttr((PyObject*)self, attr, value);
850  }
851  PyErr_SetString(PyExc_AttributeError, "cannot add new field to ElementField objects");
852  return -1;
853  }
854  char ftype = shortType(fieldtype);
855  Py_ssize_t length = moose_ElementField_getLen(self, NULL);
856  bool is_seq = true;
857  if (!PySequence_Check(value))
858  {
859  is_seq = false;
860  }
861  else if (length != PySequence_Length(value))
862  {
863  PyErr_SetString(PyExc_IndexError, "Length of the sequence on the right hand side does not match Id size.");
864  return -1;
865  }
866 
867  assert(length >= 0);
868  switch(ftype)
869  {
870  case 'd': //SET_VECFIELD(double, d)
871  {
872  vector<double> _value;
873  if (is_seq)
874  {
875  for ( int ii = 0; ii < length; ++ii)
876  {
877  double v = PyFloat_AsDouble(PySequence_GetItem(value, ii));
878  _value.push_back(v);
879  }
880  }
881  else
882  {
883  double v = PyFloat_AsDouble(value);
884  _value.assign(length, v);
885  }
886  ret = Field<double>::setVec(self->myoid, field, _value);
887  break;
888  }
889  case 's':
890  {
891  vector<string> _value;
892  if (is_seq)
893  {
894  for ( int ii = 0; ii < length; ++ii)
895  {
896  char * v = PyString_AsString(PySequence_GetItem(value, ii));
897  _value.push_back(string(v));
898  }
899  }
900  else
901  {
902  char * v = PyString_AsString(value);
903  _value.assign(length, string(v));
904  }
905  ret = Field<string>::setVec(self->myoid, field, _value);
906  break;
907  }
908  case 'i':
909  {
910  vector<int> _value;
911  if (is_seq)
912  {
913  for ( int ii = 0; ii < length; ++ii)
914  {
915  int v = PyInt_AsLong(PySequence_GetItem(value, ii));
916  _value.push_back(v);
917  }
918  }
919  else
920  {
921  int v = PyInt_AsLong(value);
922  _value.assign(length, v);
923  }
924  ret = Field< int >::setVec(self->myoid, field, _value);
925  break;
926  }
927  case 'I': //SET_VECFIELD(unsigned int, I)
928  {
929  vector<unsigned int> _value;
930  if (is_seq)
931  {
932  for ( int ii = 0; ii < length; ++ii)
933  {
934  unsigned int v = PyInt_AsUnsignedLongMask(PySequence_GetItem(value, ii));
935  _value.push_back(v);
936  }
937  }
938  else
939  {
940  unsigned int v = PyInt_AsUnsignedLongMask(value);
941  _value.assign(length, v);
942  }
943  ret = Field< unsigned int >::setVec(self->myoid, field, _value);
944  break;
945  }
946  case 'l': //SET_VECFIELD(long, l)
947  {
948  vector<long> _value;
949  if (is_seq)
950  {
951  for ( int ii = 0; ii < length; ++ii)
952  {
953  long v = PyInt_AsLong(PySequence_GetItem(value, ii));
954  _value.push_back(v);
955  }
956  }
957  else
958  {
959  long v = PyInt_AsLong(value);
960  _value.assign(length, v);
961  }
962  ret = Field<long>::setVec(self->myoid, field, _value);
963  break;
964  }
965  case 'k': //SET_VECFIELD(unsigned long, k)
966  {
967  vector<unsigned long> _value;
968  if (is_seq)
969  {
970  for ( int ii = 0; ii < length; ++ii)
971  {
972  unsigned long v = PyInt_AsUnsignedLongMask(PySequence_GetItem(value, ii));
973  _value.push_back(v);
974  }
975  }
976  else
977  {
978  unsigned long v = PyInt_AsUnsignedLongMask(value);
979  _value.assign(length, v);
980  }
981  ret = Field< unsigned long >::setVec(self->myoid, field, _value);
982  break;
983  }
984  case 'b':
985  {
986  vector<bool> _value;
987  if (is_seq)
988  {
989  for ( int ii = 0; ii < length; ++ii)
990  {
991  PyObject * _v = PySequence_GetItem(value, ii);
992  bool v = (Py_True ==_v) || (PyInt_AsLong(_v) != 0);
993  _value.push_back(v);
994  }
995  }
996  else
997  {
998  bool v = (Py_True ==value) || (PyInt_AsLong(value) != 0);
999  _value.assign(length, v);
1000  }
1001  ret = Field< bool >::setVec(self->myoid, field, _value);
1002  break;
1003  }
1004  case 'c':
1005  {
1006  vector<char> _value;
1007  if (is_seq)
1008  {
1009  for ( int ii = 0; ii < length; ++ii)
1010  {
1011  PyObject * _v = PySequence_GetItem(value, ii);
1012  char * v = PyString_AsString(_v);
1013  if (v && v[0])
1014  {
1015  _value.push_back(v[0]);
1016  }
1017  else
1018  {
1019  ostringstream err;
1020  err << ii << "-th element is NUL";
1021  PyErr_SetString(PyExc_ValueError, err.str().c_str());
1022  return -1;
1023  }
1024  }
1025  }
1026  else
1027  {
1028  char * v = PyString_AsString(value);
1029  if (v && v[0])
1030  {
1031  _value.assign(length, v[0]);
1032  }
1033  else
1034  {
1035  PyErr_SetString(PyExc_ValueError, "value is an empty string");
1036  return -1;
1037  }
1038  }
1039  ret = Field< char >::setVec(self->myoid, field, _value);
1040  break;
1041  }
1042  case 'h':
1043  {
1044  vector<short> _value;
1045  if (is_seq)
1046  {
1047  for ( int ii = 0; ii < length; ++ii)
1048  {
1049  short v = PyInt_AsLong(PySequence_GetItem(value, ii));
1050  _value.push_back(v);
1051  }
1052  }
1053  else
1054  {
1055  short v = PyInt_AsLong(value);
1056  _value.assign(length, v);
1057  }
1058  ret = Field< short >::setVec(self->myoid, field, _value);
1059  break;
1060  }
1061  case 'f': //SET_VECFIELD(float, f)
1062  {
1063  vector<float> _value;
1064  if (is_seq)
1065  {
1066  for ( int ii = 0; ii < length; ++ii)
1067  {
1068  float v = PyFloat_AsDouble(PySequence_GetItem(value, ii));
1069  _value.push_back(v);
1070  }
1071  }
1072  else
1073  {
1074  float v = PyFloat_AsDouble(value);
1075  _value.assign(length, v);
1076  }
1077  ret = Field<float>::setVec(self->myoid, field, _value);
1078  break;
1079  }
1080  default:
1081  break;
1082  }
1083  // MOOSE Field::set returns 1 for success 0 for
1084  // failure. Python treats return value 0 from setters as
1085  // success, anything else failure.
1086  if (ret && (PyErr_Occurred() == NULL))
1087  {
1088  return 0;
1089  }
1090  else
1091  {
1092  return -1;
1093  }
1094 
1095 }
1096 
1097 // PyObject * moose_ElementField_richcmp(_Field * self, void * closure);
1098 
1099 
1100 //
1101 // mfield.cpp ends here
static PyTypeObject moose_Field
Definition: mfield.cpp:178
char shortType(string)
uint32_t value
Definition: moosemodule.h:42
static PyGetSetDef ElementFieldGetSetters[]
Definition: mfield.cpp:408
static PySequenceMethods ElementFieldSequenceMethods
Definition: mfield.cpp:455
int moose_Field_init(_Field *self, PyObject *args, PyObject *kwargs)
Definition: mfield.cpp:89
PyObject * getLookupField(ObjId target, char *fieldName, PyObject *key)
Definition: melement.cpp:1295
PyObject * moose_DestField_call(PyObject *self, PyObject *args, PyObject *kw)
Definition: mfield.cpp:296
PyObject * moose_ObjId_setDestField(_ObjId *self, PyObject *args)
Definition: melement.cpp:1634
Definition: SetGet.h:236
char emptyString[]
Definition: mfield.cpp:407
PyTypeObject moose_LookupField
Definition: mfield.cpp:252
PyTypeObject moose_DestField
Definition: mfield.cpp:333
Py_ssize_t moose_ElementField_getLen(_Field *self, void *closure)
Definition: mfield.cpp:561
PyTypeObject IdType
Definition: vec.cpp:262
Definition: ObjId.h:20
const map< string, string > & get_field_alias()
static char owner[]
Definition: mfield.cpp:405
PyTypeObject ObjIdType
int moose_ElementField_setattro(_Field *self, PyObject *attr, PyObject *value)
Definition: mfield.cpp:826
#define RAISE_INVALID_ID(ret, msg)
Definition: moosemodule.h:71
PyObject * moose_LookupField_getItem(_Field *self, PyObject *key)
Definition: mfield.cpp:221
long moose_Field_hash(_Field *self)
Return the hash of the string {objectpath}.{fieldName}
Definition: mfield.cpp:142
PyObject * moose_ElementField_getPath(_Field *self, void *closure)
Definition: mfield.cpp:571
void moose_Field_dealloc(_Field *self)
Definition: mfield.cpp:134
PyObject * moose_ElementField_getSlice(_Field *self, Py_ssize_t start, Py_ssize_t end)
Definition: mfield.cpp:644
static char dataIndex[]
Definition: mfield.cpp:406
PyObject * moose_ElementField_getDataId(_Field *self, void *closure)
Definition: mfield.cpp:602
PyDoc_STRVAR(moose_Field_documentation,"Base class for MOOSE fields.\n""\n""Instances contain the field name and a pointer to the owner\n""object. Note on hash: the Field class is hashable but the hash is\n""constructed from the path of the container element and the field\n""name. Hence changing the name of the container element will cause the\n""hash to change. This is rather unusual in a moose script, but if you\n""are putting fields as dictionary keys, you should do that after names\n""of all elements have been finalized.\n""\n")
int moose_ElementField_init(_Field *self, PyObject *args, PyObject *kwargs)
Definition: mfield.cpp:519
PyTypeObject moose_ElementField
Definition: mfield.cpp:473
PyObject * to_pytuple(void *obj, char typecode)
int setLookupField(ObjId target, char *fieldName, PyObject *key, PyObject *value)
Definition: melement.cpp:1480
PyObject * moose_ElementField_getNum(_Field *self, void *closure)
Definition: mfield.cpp:528
string getFieldType(string className, string fieldName)
static bool setVec(ObjId destId, const string &field, const vector< A > &arg)
Definition: SetGet.h:252
static bool isValid(Id id)
Definition: Id.h:145
PyObject * moose_ElementField_getOwner(_Field *self, void *closure)
Definition: mfield.cpp:597
PyObject * moose_ElementField_getattro(_Field *self, PyObject *attr)
Definition: mfield.cpp:685
static char numfield[]
Definition: mfield.cpp:402
static char name[]
Definition: mfield.cpp:401
int moose_LookupField_setItem(_Field *self, PyObject *key, PyObject *value)
Definition: mfield.cpp:226
PyObject * moose_ElementField_getName(_Field *self, void *closure)
Definition: mfield.cpp:593
Definition: Id.h:17
int moose_ElementField_setNum(_Field *self, PyObject *args, void *closure)
Definition: mfield.cpp:540
static A get(const ObjId &dest, const string &field)
Definition: SetGet.h:284
PyObject * moose_Field_repr(_Field *self)
String representation of fields is {objectpath}.{fieldName}
Definition: mfield.cpp:156
PyObject * moose_ElementField_getId(_Field *self, void *closure)
Definition: mfield.cpp:581
PyObject * moose_ElementField_getItem(_Field *self, Py_ssize_t index)
Definition: mfield.cpp:611
static void getVec(ObjId dest, const string &field, vector< A > &vec)
Definition: SetGet.h:317
PyObject * oid_to_element(ObjId oid)
static char id[]
Definition: mfield.cpp:404
static char path[]
Definition: mfield.cpp:403
static PyMappingMethods LookupFieldMappingMethods
Definition: mfield.cpp:236