MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
melement.cpp
Go to the documentation of this file.
1 // melement.cpp ---
2 //
3 // Filename: melement.cpp
4 // Description:
5 // Author:
6 // Maintainer:
7 // Created: Mon Jul 22 16:50:41 2013 (+0530)
8 // Version:
9 // Last-Updated: Fri Sep 25 23:02:53 2015 (-0400)
10 // By: subha
11 // Update #: 76
12 // URL:
13 // Keywords:
14 // Compatibility:
15 //
16 //
17 
18 // Commentary:
19 //
20 // Mon Jul 22 16:50:47 IST 2013 - Taking out ObjId stuff from
21 // moosemodule.cpp
22 //
23 //
24 
25 // Change log:
26 //
27 //
28 //
29 //
30 // This program is free software; you can redistribute it and/or
31 // modify it under the terms of the GNU General Public License as
32 // published by the Free Software Foundation; either version 3, or
33 // (at your option) any later version.
34 //
35 // This program is distributed in the hope that it will be useful,
36 // but WITHOUT ANY WARRANTY; without even the implied warranty of
37 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38 // General Public License for more details.
39 //
40 // You should have received a copy of the GNU General Public License
41 // along with this program; see the file COPYING. If not, write to
42 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth
43 // Floor, Boston, MA 02110-1301, USA.
44 //
45 //
46 
47 // Code:
48 
49 #include <Python.h>
50 #include <structmember.h>
51 
52 #ifdef USE_BOOST_ODE
53 #include <boost/format.hpp>
54 #endif
55 
56 #include <iostream>
57 #include <typeinfo>
58 #include <cstring>
59 #include <map>
60 #include <ctime>
61 
62 #ifdef USE_MPI
63 #include <mpi.h>
64 #endif
65 
66 #include "../basecode/header.h"
67 #include "../basecode/Id.h"
68 #include "../basecode/ObjId.h"
69 #include "../utility/utility.h"
70 #include "../utility/print_function.hpp"
71 #include "../shell/Shell.h"
72 
73 #include "moosemodule.h"
74 
75 using namespace std;
76 
77 
78 extern PyTypeObject ObjIdType;
79 extern PyTypeObject IdType;
80 extern int PyType_IsSubtype(PyTypeObject *, PyTypeObject *);
81 
82 
83 PyObject * get_ObjId_attr(_ObjId * oid, string attribute)
84 {
85  if (attribute == "vec")
86  {
87  return moose_ObjId_getId(oid);
88  }
89  else if (attribute == "dindex")
90  {
91  return moose_ObjId_getDataIndex(oid);
92  }
93  else if (attribute == "findex")
94  {
95  return moose_ObjId_getFieldIndex(oid);
96  }
97  return NULL;
98 }
99 
100 int moose_ObjId_init_from_id(_ObjId * self, PyObject * args, PyObject * kwargs)
101 {
102  extern PyTypeObject ObjIdType;
103  static const char* const kwlist[] = {"id", "dataIndex", "fieldIndex", NULL};
104  unsigned int id = 0, data = 0, field = 0;
105  PyObject * obj = NULL;
106  if (PyArg_ParseTupleAndKeywords(args, kwargs,
107  "I|II:moose_ObjId_init_from_id",
108  (char**)kwlist,
109  &id, &data, &field))
110  {
111  PyErr_Clear();
112  if (!Id::isValid(id))
113  {
114  RAISE_INVALID_ID(-1, "moose_ObjId_init_from_id");
115  }
116  self->oid_ = ObjId(Id(id), data, field );
117  if (self->oid_.bad())
118  {
119  PyErr_SetString(PyExc_ValueError, "Invalid ObjId");
120  return -1;
121  }
122  return 0;
123  }
124  PyErr_Clear();
125  if (PyArg_ParseTupleAndKeywords(args, kwargs,
126  "O|II:moose_ObjId_init_from_id",
127  (char**)kwlist,
128  &obj, &data, &field))
129  {
130  PyErr_Clear();
131  // If first argument is an Id object, construct an ObjId out of it
132  if (Id_Check(obj))
133  {
134  if (!Id::isValid(((_Id*)obj)->id_))
135  {
136  RAISE_INVALID_ID(-1, "moose_ObjId_init_from_id");
137  }
138  self->oid_ = ObjId(((_Id*)obj)->id_, data, field );
139  if (self->oid_.bad())
140  {
141  PyErr_SetString(PyExc_ValueError, "Invalid dataIndex/fieldIndex.");
142  return -1;
143  }
144  return 0;
145  }
146  else if (PyObject_IsInstance(obj, (PyObject*)&ObjIdType))
147  {
148  if (!Id::isValid(((_ObjId*)obj)->oid_.id))
149  {
150  RAISE_INVALID_ID(-1, "moose_ObjId_init_from_id");
151  }
152  self->oid_ = ((_ObjId*)obj)->oid_;
153  if (self->oid_.bad())
154  {
155  PyErr_SetString(PyExc_ValueError, "Invalid ObjId");
156  return -1;
157  }
158  return 0;
159  }
160  }
161  return -1;
162 }
163 
164 int moose_ObjId_init_from_path(_ObjId * self, PyObject * args,
165  PyObject * kwargs)
166 {
167  static const char* const kwlist[] = {"path", "n", "g", "dtype", NULL};
168  const char* parsedPath;
169  unsigned int numData = 1;
170  unsigned int isGlobal = 0;
171  char* type = NULL;
172 
173  self->oid_ = ObjId( 0, BADINDEX );
174  PyTypeObject * mytype = Py_TYPE(self);
175  string mytypename(mytype->tp_name);
176 
177  // First try to parse the arguments as (parsedPath, n, g, dtype)
178  bool parse_success = false;
179  if (PyArg_ParseTupleAndKeywords(args, kwargs,
180  "s|IIs:moose_ObjId_init_from_path",
181  (char**)kwlist,
182  &parsedPath, &numData, &isGlobal, &type))
183  {
184  parse_success = true;
185  }
186  // we need to clear the parse error so that the callee can try
187  // other alternative: moose_ObjId_init_from_id
188  PyErr_Clear();
189  if (!parse_success)
190  {
191  return -2;
192  }
193 
194  string path(parsedPath);
195 
196  // Remove one or more instances of '/' by a single '/' e.g. //a -> /a,
197  // /a//b -> /a/b etc.
198  path = moose::fix(path);
199 
200  ostringstream err, warn;
201 
202  // First see if there is an existing object with at path
203  self->oid_ = ObjId(path);
204  PyTypeObject* basetype = getBaseClass((PyObject*)self);
205  string basetype_str;
206  if (type == NULL)
207  {
208  if (basetype == NULL)
209  {
210  PyErr_SetString(PyExc_TypeError
211  , "Unknown class. Need a valid MOOSE class or subclass thereof."
212  );
213  return -1;
214  }
215  basetype_str = string(basetype->tp_name).substr(6); // remove `moose.` prefix from type name
216  }
217  else
218  {
219  basetype_str = string(type);
220  }
221 
222 
223  // If oid_ is bad, it can be either a nonexistent path or the root.
224  if (self->oid_.bad())
225  {
226  // is this the root element?
227  if ((path == "/") || (path == "/root"))
228  {
229  if ((basetype == NULL) || PyType_IsSubtype(mytype, basetype))
230  {
231  return 0;
232  }
233  err << "cannot convert moose." << Field<string>::get(self->oid_, "className")
234  << " to " << mytypename
235  << "To get the existing object use `moose.element(obj)` instead.";
236  PyErr_SetString(PyExc_TypeError, err.str().c_str());
237  return -1;
238  }
239  // no - so we need to create a new element
240  }
241  else // this is a non-root existing element
242  {
243  // If the current class is a subclass of some predefined
244  // moose class, do nothing.
245  string className = self->oid_.element()->cinfo()->name();
246  map <string, PyTypeObject * >::iterator ii =
247  get_moose_classes().find( className );
248 
249  PyTypeObject * basetype = 0;
250  if ( ii != get_moose_classes().end() )
251  {
252  basetype = ii->second;
253  // remove `moose.` prefix from type name
254  basetype_str = string(basetype->tp_name).substr(6);
255  }
256  else
257  {
258  err << "Unknown class: " << className << endl;
259  basetype = getBaseClass((PyObject*)self);
260  }
261 
262  // NOTE: Existing paths are handled in Shell::doCreate function.
263  if ((basetype != NULL) && PyType_IsSubtype(mytype, basetype))
264  {
265  // Fine. This path already exits.
266  err << "Accessing existing paths using object constrcutors has been deprecated. Use "
267  << " moose.element to access existing object. In future "
268  << " this will be an error." << endl;
269  PyErr_WarnEx(PyExc_DeprecationWarning, err.str().c_str(), 1);
270  return 0;
271  }
272 
273  // element exists at this path, but it does not inherit from any moose class.
274  // throw an error
275  err << "cannot convert moose." << className
276  << " to " << mytypename
277  << ". To get the existing object use `moose.element(obj)` instead.";
278  PyErr_SetString(PyExc_TypeError, err.str().c_str());
279  return -1;
280  }
281 
282  // try to create new vec
283  Id new_id = create_Id_from_path(path, numData, isGlobal, basetype_str);
284 
285  // vec failed. throw error
286  if (new_id == Id() && PyErr_Occurred())
287  {
288  // Py_XDECREF(self);
289  return -1;
290  }
291 
292  self->oid_ = ObjId(new_id);
293  return 0;
294 }
295 
296 int moose_ObjId_init(_ObjId * self, PyObject * args,
297  PyObject * kwargs)
298 {
299  if (self && !PyObject_IsInstance((PyObject*)self, (PyObject*)Py_TYPE((PyObject*)self)))
300  {
301  ostringstream error;
302  error << "Expected an melement or subclass. Found "
303  << Py_TYPE(self)->tp_name;
304  PyErr_SetString(PyExc_TypeError, error.str().c_str());
305  return -1;
306  }
307  int ret = moose_ObjId_init_from_path(self, args, kwargs);
308  if (ret >= -1)
309  {
310  return ret;
311  }
312  // parsing arguments as (path, dims, classname) failed. See if it is existing Id or ObjId.
313  if (moose_ObjId_init_from_id(self, args, kwargs) == 0)
314  {
315  return 0;
316  }
317  PyErr_SetString(PyExc_ValueError,
318  "Could not parse arguments. "
319  " Call __init__(path, n, g, dtype) or"
320  " __init__(id, dataIndex, fieldIndex)");
321  return -1;
322 }
323 
334 {
335  if (!Id::isValid(self->oid_.id))
336  {
337  RAISE_INVALID_ID(-1, "moose_ObjId_hash");
338  }
339  long long id = (long long)(self->oid_.id.value());
340  long dataIndex = self->oid_.dataIndex;
341  long fieldIndex = self->oid_.fieldIndex;
342  /* attempt to make it with 32 bit system - assuming id will
343  * have its value within least significant 16 bits and
344  * dataIndex and fieldIndex will be limited to first 8 bits */
345  if (sizeof(size_t) == 8)
346  {
347  return id << 48 | dataIndex << 16 | fieldIndex;
348  }
349  else
350  {
351  return id << 16 | dataIndex << 8 | fieldIndex;
352  }
353 }
354 
355 PyObject * moose_ObjId_repr(_ObjId * self)
356 {
357  if (!Id::isValid(self->oid_.id))
358  {
359  RAISE_INVALID_ID(NULL, "moose_ObjId_repr");
360  }
361  ostringstream repr;
362  repr << "<moose." << Field<string>::get(self->oid_, "className") << ": "
363  << "id=" << self->oid_.id.value() << ", "
364  << "dataIndex=" << self->oid_.dataIndex << ", "
365  << "path=" << self->oid_.path() << ">";
366  return PyString_FromString(repr.str().c_str());
367 } // ! moose_ObjId_repr
368 
369 PyObject * moose_ObjId_str(_ObjId * self)
370 {
371  if (!Id::isValid(self->oid_.id))
372  {
373  RAISE_INVALID_ID(NULL, "moose_ObjId_str");
374  }
375  ostringstream repr;
376  repr << "<moose." << Field<string>::get(self->oid_, "className") << ": "
377  << "id=" << self->oid_.id.value() << ", "
378  << "dataIndex=" << self->oid_.dataIndex << ", "
379  << "path=" << self->oid_.path() << ">";
380  return PyString_FromString(repr.str().c_str());
381 } // ! moose_ObjId_str
382 
383 PyDoc_STRVAR(moose_ObjId_getId_documentation,
384  "getId() -> vec\n"
385  "\n"
386  "Returns the information of the object's classtype, Id, and path \n"
387  "in form of a vector.\n"
388  "\nExample\n"
389  "-------\n"
390  " >>> com = moose.Compartment('/com')\n"
391  " >>> com.getId()\n"
392  " moose.vec: class=Compartment, id=481, path=/com>"
393  "\n");
394 PyObject* moose_ObjId_getId(_ObjId * self)
395 {
396  if (!Id::isValid(self->oid_.id))
397  {
398  RAISE_INVALID_ID(NULL, "moose_ObjId_getId");
399  }
400  extern PyTypeObject IdType;
401  _Id * ret = PyObject_New(_Id, &IdType);
402  ret->id_ = self->oid_.id;
403  return (PyObject*)ret;
404 }
405 
406 PyDoc_STRVAR(moose_ObjId_getFieldType_documentation,
407  "getFieldType(fieldname)\n"
408  "\n"
409  "Returns the type of the field `fieldname` (as a string).\n"
410  "\n"
411  "Parameters\n"
412  "----------\n"
413  "fieldname : string\n"
414  " Name of the field to be queried.\n"
415  "\n"
416  " >>> comp.getFieldType('neighbors')\n"
417  " >>> 'string,vector<Id>' \n"
418  "\n");
419 
420 PyObject * moose_ObjId_getFieldType(_ObjId * self, PyObject * args)
421 {
422  if (!Id::isValid(self->oid_.id))
423  {
424  RAISE_INVALID_ID(NULL, "moose_ObjId_getFieldType");
425  }
426  char * fieldName = NULL;
427  if (!PyArg_ParseTuple(args, "s:moose_ObjId_getFieldType", &fieldName))
428  {
429  return NULL;
430  }
431  string typeStr = getFieldType(Field<string>::get(self->oid_, "className"),
432  string(fieldName));
433  if (typeStr.length() <= 0)
434  {
435  PyErr_SetString(PyExc_ValueError,
436  "Empty string for field type. "
437  "Field name may be incorrect.");
438  return NULL;
439  }
440  PyObject * type = PyString_FromString(typeStr.c_str());
441  return type;
442 } // ! moose_Id_getFieldType
443 
448 PyDoc_STRVAR(moose_ObjId_getField_documentation,
449  "getField(fieldname)\n"
450  "\n"
451  "Returns the value of the field `fieldname`.\n"
452  "\n"
453  "Parameters\n"
454  "----------\n"
455  "fieldname : string\n"
456  " Name of the field.\n"
457  "\n"
458  " >>> comp.getField('x0')\n"
459  " >>> 0.0 \n");
460 PyObject * moose_ObjId_getField(_ObjId * self, PyObject * args)
461 {
462  if (!Id::isValid(self->oid_.id))
463  {
464  RAISE_INVALID_ID(NULL, "moose_ObjId_getField");
465  }
466  PyObject * attr;
467  if (!PyArg_ParseTuple(args, "O:moose_ObjId_getField", &attr))
468  {
469  return NULL;
470  }
471  return moose_ObjId_getattro(self, attr);
472 }
473 
484 PyObject * moose_ObjId_getattro(_ObjId * self, PyObject * attr)
485 {
486  int new_attr = 0;
487  if (self->oid_.bad())
488  {
489  RAISE_INVALID_ID(NULL, "moose_ObjId_getattro");
490  }
491  // extern PyTypeObject IdType;
492  // extern PyTypeObject ObjIdType;
493  const char * field;
494  char ftype;
495  if (PyString_Check(attr))
496  {
497  field = PyString_AsString(attr);
498  }
499  else
500  {
501  return PyObject_GenericGetAttr((PyObject*)self, attr);
502  }
503  PyObject * _ret = get_ObjId_attr(self, field);
504  if (_ret != NULL)
505  {
506  return _ret;
507  }
508  string fieldName(field);
509  string className = Field<string>::get(self->oid_, "className");
510  vector<string> valueFinfos = getFieldNames(className, "valueFinfo");
511  bool isValueField = false;
512  for (unsigned int ii = 0; ii < valueFinfos.size(); ++ii)
513  {
514  if (fieldName == valueFinfos[ii])
515  {
516  isValueField = true;
517  break;
518  }
519  }
520 
521  string type = getFieldType(className, fieldName);
522  if (type.empty() || !isValueField )
523  {
524  // Check if this field name is aliased and update fieldName and type if so.
525  map<string, string>::const_iterator it = get_field_alias().find(fieldName);
526  if (it != get_field_alias().end())
527  {
528  fieldName = it->second;
529  field = fieldName.c_str();
530  isValueField = false;
531  for (unsigned int ii = 0; ii < valueFinfos.size(); ++ii)
532  {
533  if (fieldName == valueFinfos[ii])
534  {
535  isValueField = true;
536  break;
537  }
538  }
539  type = getFieldType(Field<string>::get(self->oid_, "className"), fieldName);
540  // Update attr for next level (PyObject_GenericGetAttr) in case.
541  // Py_XDECREF(attr);
542  attr = PyString_FromString(field);
543  new_attr = 1;
544  }
545  }
546  if (type.empty() || !isValueField)
547  {
548  _ret = PyObject_GenericGetAttr((PyObject*)self, attr);
549  if (new_attr)
550  {
551  Py_DECREF(attr);
552  }
553  return _ret;
554  }
555  ftype = shortType(type);
556  if (!ftype)
557  {
558  _ret = PyObject_GenericGetAttr((PyObject*)self, attr);
559  if (new_attr)
560  {
561  Py_DECREF(attr);
562  }
563  return _ret;
564  }
565  fieldName= string(field);
566  switch(ftype)
567  {
568  case 's':
569  {
570  string _s = Field<string>::get(self->oid_, fieldName);
571  _ret = Py_BuildValue("s", _s.c_str());
572  break;
573  }
574  case 'd':
575  {
576  double value = Field< double >::get(self->oid_, fieldName);
577  _ret = to_py(&value, ftype);
578  break;
579  }
580  case 'i':
581  {
582  int value = Field<int>::get(self->oid_, fieldName);
583  _ret = to_py(&value, ftype);
584  break;
585  }
586  case 'I':
587  {
588  unsigned int value = Field<unsigned int>::get(self->oid_, fieldName);
589  _ret = to_py(&value, ftype);
590  break;
591  }
592  case 'l':
593  {
594  long value = Field<long>::get(self->oid_, fieldName);
595  _ret = to_py(&value, ftype);
596  break;
597  }
598  case 'L':
599  {
600  long long value = Field<long long>::get(self->oid_, fieldName);
601  _ret = to_py(&value, ftype);
602  break;
603  }
604  case 'k':
605  {
606  unsigned long value = Field<unsigned long>::get(self->oid_, fieldName);
607  _ret = to_py(&value, ftype);
608  break;
609  }
610  case 'K':
611  {
612  unsigned long long value = Field<unsigned long long>::get(self->oid_, fieldName);
613  _ret = to_py(&value, ftype);
614  break;
615  }
616  case 'f':
617  {
618  float value = Field<float>::get(self->oid_, fieldName);
619  _ret = to_py(&value, ftype);
620  break;
621  }
622  case 'x':
623  {
624  Id value = Field<Id>::get(self->oid_, fieldName);
625  _ret = to_py(&value, ftype);
626  break;
627  }
628  case 'y':
629  {
630  ObjId value = Field<ObjId>::get(self->oid_, fieldName);
631  _ret = to_py(&value, ftype);
632  break;
633  }
634  case 'z':
635  {
636  PyErr_SetString(PyExc_NotImplementedError, "DataId handling not implemented yet.");
637  _ret = NULL;
638  break;
639  }
640  case 'D':
641  {
642  vector< double > value = Field< vector < double > >::get(self->oid_, fieldName);
643  _ret = to_py(&value, ftype);
644  break;
645  }
646  case 'X': // vector<Id>
647  {
648  vector < Id > value = Field<vector <Id> >::get(self->oid_, fieldName);
649  _ret = to_py(&value, ftype);
650  break;
651  }
652  case 'Y': // vector<ObjId>
653  {
654  vector < ObjId > value = Field<vector <ObjId> >::get(self->oid_, fieldName);
655  _ret = to_py(&value, ftype);
656  break;
657  }
658  case 'M':
659  {
660  vector< long > value = Field< vector <long> >::get(self->oid_, fieldName);
661  _ret = to_py(&value, ftype);
662  break;
663  }
664  case 'P':
665  {
666  vector < unsigned long > value = Field< vector < unsigned long > >::get(self->oid_, fieldName);
667  _ret = to_py(&value, ftype);
668  break;
669  }
670  case 'S':
671  {
672  vector < string > value = Field<vector <string> >::get(self->oid_, fieldName);
673  _ret = to_py(&value, ftype);
674  break;
675  }
676  case 'v':
677  {
678  vector < int > value = Field<vector <int> >::get(self->oid_, fieldName);
679  _ret = to_py(&value, ftype);
680  break;
681  }
682  case 'N':
683  {
684  vector <unsigned int > value = Field< vector < unsigned int> >::get(self->oid_, fieldName);
685  _ret = to_py(&value, ftype);
686  break;
687  }
688  case 'T': // vector<vector < unsigned int >>
689  {
690  vector < vector < unsigned int > > value = Field<vector <vector < unsigned int > > >::get(self->oid_, fieldName);
691  _ret = to_py(&value, ftype);
692  break;
693  }
694  case 'Q': // vector< vector < int > >
695  {
696  vector < vector < int > > value = Field<vector < vector < int > > >::get(self->oid_, fieldName);
697  _ret = to_py(&value, ftype);
698  break;
699  }
700  case 'R': // vector< vector < double > >
701  {
702  vector < vector < double > > value = Field<vector < vector < double > > >::get(self->oid_, fieldName);
703  _ret = to_py(&value, ftype);
704  break;
705  }
706  case 'F':
707  {
708  vector <float> value = Field< vector < float > >::get(self->oid_, fieldName);
709  _ret = to_py(&value, ftype);
710  break;
711  }
712  case 'c':
713  {
714  char value = Field<char>::get(self->oid_, fieldName);
715  _ret = to_py(&value, ftype);
716  break;
717  }
718  case 'h':
719  {
720  short value = Field<short>::get(self->oid_, fieldName);
721  _ret = to_py(&value, ftype);
722  break;
723  }
724  case 'H':
725  {
726  unsigned short value = Field<unsigned short>::get(self->oid_, fieldName);
727  _ret = to_py(&value, ftype);
728  break;
729  }
730  case 'w':
731  {
732  vector < short > value = Field<vector <short> >::get(self->oid_, fieldName);
733  _ret = to_py(&value, ftype);
734  break;
735  }
736  case 'C':
737  {
738  vector < char > value = Field<vector <char> >::get(self->oid_, fieldName);
739  _ret = to_py(&value, ftype);
740  break;
741  }
742 
743  case 'b':
744  {
745  bool value = Field<bool>::get(self->oid_, fieldName);
746  if (value)
747  {
748  _ret = Py_True;
749  Py_INCREF(Py_True);
750  }
751  else
752  {
753  _ret = Py_False;
754  Py_INCREF(Py_False);
755  }
756  break;
757  }
758 
759  default:
760  _ret = PyObject_GenericGetAttr((PyObject*)self, attr);
761 
762  }
763  if (new_attr)
764  {
765  Py_DECREF(attr);
766  }
767  return _ret;
768 }
769 
773 PyDoc_STRVAR(moose_ObjId_setField_documentation,
774  "setField(fieldname, value)\n"
775  "\n"
776  "Set the value of specified field.\n"
777  "\n"
778  "Parameters\n"
779  "----------\n"
780  "fieldname : string\n"
781  " Field to be assigned value to.\n"
782  "\n"
783  "value : python datatype compatible with the type of the field\n"
784  " The value to be assigned to the field."
785  "\n"
786  "\n"
787  " >>> comp.setField('x0', 45.25) \n"
788  " >>> print comp.x0\n"
789  " 45.25\n");
790 
791 PyObject * moose_ObjId_setField(_ObjId * self, PyObject * args)
792 {
793  PyObject * field;
794  PyObject * value;
795  if (!PyArg_ParseTuple(args, "OO:moose_ObjId_setField", &field, &value))
796  {
797  return NULL;
798  }
799  if (moose_ObjId_setattro(self, field, value) == -1)
800  {
801  return NULL;
802  }
803  Py_RETURN_NONE;
804 }
805 
809 int moose_ObjId_setattro(_ObjId * self, PyObject * attr, PyObject * value)
810 {
811  if (!Id::isValid(self->oid_.id))
812  {
813  RAISE_INVALID_ID(-1, "moose_ObjId_setattro");
814  }
815  const char * field;
816  if (PyString_Check(attr))
817  {
818  field = PyString_AsString(attr);
819  }
820  else
821  {
822  PyErr_SetString(PyExc_TypeError, "Attribute name must be a string");
823  return -1;
824  }
825  string fieldtype = getFieldType(Field<string>::get(self->oid_, "className"), string(field));
826  if (fieldtype.length() == 0)
827  {
828  // If it is instance of a MOOSE built-in class then throw
829  // error (to avoid silently creating new attributes due to
830  // typos). Otherwise, it must have been subclassed in
831  // Python. Then we allow normal Pythonic behaviour and
832  // consider such mistakes user's responsibility.
833  string className = ((PyTypeObject*)PyObject_Type((PyObject*)self))->tp_name;
834  if (get_moose_classes().find(className) == get_moose_classes().end())
835  {
836  return PyObject_GenericSetAttr((PyObject*)self, PyString_FromString(field), value);
837  }
838  ostringstream msg;
839  msg << "'" << className << "' class has no field '" << field << "'" << endl;
840  PyErr_SetString(PyExc_AttributeError, msg.str().c_str());
841  return -1;
842  }
843  char ftype = shortType(fieldtype);
844  int ret = 0;
845  switch(ftype)
846  {
847  case 'd':
848  {
849  double _value = PyFloat_AsDouble(value);
850  ret = Field<double>::set(self->oid_, string(field), _value);
851  break;
852  }
853  case 'l':
854  {
855  long _value = PyInt_AsLong(value);
856  if ((_value != -1) || (!PyErr_Occurred()))
857  {
858  ret = Field<long>::set(self->oid_, string(field), _value);
859  }
860  break;
861  }
862  case 'I':
863  {
864  unsigned long _value = PyInt_AsUnsignedLongMask(value);
865  ret = Field<unsigned int>::set(self->oid_, string(field), (unsigned int)_value);
866  break;
867  }
868  case 'k':
869  {
870  unsigned long _value = PyInt_AsUnsignedLongMask(value);
871  ret = Field<unsigned long>::set(self->oid_, string(field), _value);
872  break;
873  }
874  case 'f':
875  {
876  float _value = PyFloat_AsDouble(value);
877  ret = Field<float>::set(self->oid_, string(field), _value);
878  break;
879  }
880  case 's':
881  {
882  char * _value = PyString_AsString(value);
883  if (_value)
884  {
885  ret = Field<string>::set(self->oid_, string(field), string(_value));
886  }
887  break;
888  }
889  case 'x': // Id
890  {
891  if (value)
892  {
893  ret = Field<Id>::set(self->oid_, string(field), ((_Id*)value)->id_);
894  }
895  else
896  {
897  PyErr_SetString(PyExc_ValueError, "Null pointer passed as vec Id value.");
898  return -1;
899  }
900  break;
901  }
902  case 'y': // ObjId
903  {
904  if (value)
905  {
906  ret = Field<ObjId>::set(self->oid_, string(field), ((_ObjId*)value)->oid_);
907  }
908  else
909  {
910  PyErr_SetString(PyExc_ValueError, "Null pointer passed as vec Id value.");
911  return -1;
912  }
913  break;
914  }
915  case 'D': //SET_VECFIELD(double, d)
916  {
917  if (!PySequence_Check(value))
918  {
919  PyErr_SetString(PyExc_TypeError, "For setting vector<double> field, specified value must be a sequence." );
920  }
921  else
922  {
923  Py_ssize_t length = PySequence_Length(value);
924  vector<double> _value;
925  for ( int ii = 0; ii < length; ++ii)
926  {
927  PyObject * vo = PySequence_GetItem(value, ii);
928  double v = PyFloat_AsDouble(vo);
929  Py_XDECREF(vo);
930  _value.push_back(v);
931  }
932  ret = Field< vector < double > >::set(self->oid_, string(field), _value);
933  }
934  break;
935  }
936  case 'b':
937  {
938  bool _value = (Py_True == value) || (PyInt_AsLong(value) != 0);
939  ret = Field<bool>::set(self->oid_, string(field), _value);
940  break;
941  }
942  case 'c':
943  {
944  char * _value = PyString_AsString(value);
945  if (_value && _value[0])
946  {
947  ret = Field<char>::set(self->oid_, string(field), _value[0]);
948  }
949  break;
950  }
951  case 'i':
952  {
953  int _value = PyInt_AsLong(value);
954  if ((_value != -1) || (!PyErr_Occurred()))
955  {
956  ret = Field<int>::set(self->oid_, string(field), _value);
957  }
958  break;
959  }
960  case 'h':
961  {
962  short _value = (short)PyInt_AsLong(value);
963  if ((_value != -1) || (!PyErr_Occurred()))
964  {
965  ret = Field<short>::set(self->oid_, string(field), _value);
966  }
967  break;
968  }
969  case 'z': // DataId
970  {
971  PyErr_SetString(PyExc_NotImplementedError, "DataId handling not implemented yet.");
972  return -1;
973  }
974  case 'v':
975  {
976  if (!PySequence_Check(value))
977  {
978  PyErr_SetString(PyExc_TypeError, "For setting vector<int> field, specified value must be a sequence." );
979  }
980  Py_ssize_t length = PySequence_Length(value);
981  vector<int> _value;
982  for ( int ii = 0; ii < length; ++ii)
983  {
984  PyObject * vo = PySequence_GetItem(value, ii);
985  int v = PyInt_AsLong(vo);
986  Py_XDECREF(vo);
987  _value.push_back(v);
988  }
989  ret = Field< vector < int > >::set(self->oid_, string(field), _value);
990  break;
991  }
992  case 'w':
993  {
994  if (!PySequence_Check(value))
995  {
996  PyErr_SetString(PyExc_TypeError, "For setting vector<short> field, specified value must be a sequence." );
997  }
998  else
999  {
1000  Py_ssize_t length = PySequence_Length(value);
1001  vector<short> _value;
1002  for ( int ii = 0; ii < length; ++ii)
1003  {
1004  PyObject * vo = PySequence_GetItem(value, ii);
1005  short v = PyInt_AsLong(vo);
1006  Py_XDECREF(vo);
1007  _value.push_back(v);
1008  }
1009  ret = Field< vector < short > >::set(self->oid_, string(field), _value);
1010  }
1011  break;
1012  }
1013  case 'L': //SET_VECFIELD(long, l)
1014  {
1015  if (!PySequence_Check(value))
1016  {
1017  PyErr_SetString(PyExc_TypeError,
1018  "For setting vector<long> field, specified value must be a sequence." );
1019  }
1020  else
1021  {
1022  Py_ssize_t length = PySequence_Length(value);
1023  vector<long> _value;
1024  for ( int ii = 0; ii < length; ++ii)
1025  {
1026  PyObject * vo = PySequence_GetItem(value, ii);
1027  long v = PyInt_AsLong(vo);
1028  Py_XDECREF(vo);
1029  _value.push_back(v);
1030  }
1031  ret = Field< vector < long > >::set(self->oid_, string(field), _value);
1032  }
1033  break;
1034  }
1035  case 'N': //SET_VECFIELD(unsigned int, I)
1036  {
1037  if (!PySequence_Check(value))
1038  {
1039  PyErr_SetString(PyExc_TypeError, "For setting vector<unsigned int> field, specified value must be a sequence." );
1040  }
1041  else
1042  {
1043  Py_ssize_t length = PySequence_Length(value);
1044  vector<unsigned int> _value;
1045  for ( int ii = 0; ii < length; ++ii)
1046  {
1047  PyObject * vo = PySequence_GetItem(value, ii);
1048  unsigned int v = PyInt_AsUnsignedLongMask(vo);
1049  Py_XDECREF(vo);
1050  _value.push_back(v);
1051  }
1052  ret = Field< vector < unsigned int > >::set(self->oid_, string(field), _value);
1053  }
1054  break;
1055  }
1056  case 'K': //SET_VECFIELD(unsigned long, k)
1057  {
1058  if (!PySequence_Check(value))
1059  {
1060  PyErr_SetString(PyExc_TypeError, "For setting vector<unsigned long> field, specified value must be a sequence." );
1061  }
1062  else
1063  {
1064  Py_ssize_t length = PySequence_Length(value);
1065  vector<unsigned long> _value;
1066  for ( int ii = 0; ii < length; ++ii)
1067  {
1068  PyObject * vo = PySequence_GetItem(value, ii);
1069  unsigned long v = PyInt_AsUnsignedLongMask(vo);
1070  Py_XDECREF(vo);
1071  _value.push_back(v);
1072  }
1073  ret = Field< vector < unsigned long > >::set(self->oid_, string(field), _value);
1074  }
1075  break;
1076  }
1077  case 'F': //SET_VECFIELD(float, f)
1078  {
1079  if (!PySequence_Check(value))
1080  {
1081  PyErr_SetString(PyExc_TypeError, "For setting vector<float> field, specified value must be a sequence." );
1082  }
1083  else
1084  {
1085  Py_ssize_t length = PySequence_Length(value);
1086  vector<float> _value;
1087  for ( int ii = 0; ii < length; ++ii)
1088  {
1089  PyObject * vo = PySequence_GetItem(value, ii);
1090  float v = PyFloat_AsDouble(vo);
1091  Py_XDECREF(vo);
1092  _value.push_back(v);
1093  }
1094  ret = Field< vector < float > >::set(self->oid_, string(field), _value);
1095  }
1096  break;
1097  }
1098  case 'S':
1099  {
1100  if (!PySequence_Check(value))
1101  {
1102  PyErr_SetString(PyExc_TypeError, "For setting vector<string> field, specified value must be a sequence." );
1103  }
1104  else
1105  {
1106  Py_ssize_t length = PySequence_Length(value);
1107  vector<string> _value;
1108  for ( int ii = 0; ii < length; ++ii)
1109  {
1110  PyObject * vo = PySequence_GetItem(value, ii);
1111  char * v = PyString_AsString(vo);
1112  Py_XDECREF(vo);
1113  _value.push_back(string(v));
1114  }
1115  ret = Field< vector < string > >::set(self->oid_, string(field), _value);
1116  }
1117  break;
1118  }
1119  case 'T': // vector< vector<unsigned int> >
1120  {
1121  vector < vector <unsigned> > * _value = (vector < vector <unsigned> > *)to_cpp(value, ftype);
1122  if (!PyErr_Occurred())
1123  {
1124  ret = Field < vector < vector <unsigned> > >::set(self->oid_, string(field), *_value);
1125  }
1126  delete _value;
1127  break;
1128  }
1129  case 'Q': // vector< vector<int> >
1130  {
1131  vector < vector <int> > * _value = (vector < vector <int> > *)to_cpp(value, ftype);
1132  if (!PyErr_Occurred())
1133  {
1134  ret = Field < vector < vector <int> > >::set(self->oid_, string(field), *_value);
1135  }
1136  delete _value;
1137  break;
1138  }
1139  case 'R': // vector< vector<double> >
1140  {
1141  vector < vector <double> > * _value = (vector < vector <double> > *)to_cpp(value, ftype);
1142  if (!PyErr_Occurred())
1143  {
1144  ret = Field < vector < vector <double> > >::set(self->oid_, string(field), *_value);
1145  }
1146  delete _value;
1147  break;
1148  }
1149  case 'X': //SET_VECFIELD(Id, f)
1150  {
1151  if (!PySequence_Check(value))
1152  {
1153  PyErr_SetString(PyExc_TypeError, "For setting vector<Id> field, specified value must be a sequence." );
1154  }
1155  else
1156  {
1157  Py_ssize_t length = PySequence_Length(value);
1158  vector<Id> _value;
1159  for ( int ii = 0; ii < length; ++ii)
1160  {
1161  PyObject * vo = PySequence_GetItem(value, ii);
1162  Id v = ((_Id*)vo)->id_;
1163  Py_XDECREF(vo);
1164  _value.push_back(v);
1165  }
1166  ret = Field< vector < Id > >::set(self->oid_, string(field), _value);
1167  }
1168  break;
1169  }
1170  case 'Y': //SET_VECFIELD(ObjId, f)
1171  {
1172  if (!PySequence_Check(value))
1173  {
1174  PyErr_SetString(PyExc_TypeError, "For setting vector<ObjId> field, specified value must be a sequence." );
1175  }
1176  else
1177  {
1178  Py_ssize_t length = PySequence_Length(value);
1179  vector<ObjId> _value;
1180  for ( int ii = 0; ii < length; ++ii)
1181  {
1182  PyObject * vo = PySequence_GetItem(value, ii);
1183  ObjId v = ((_ObjId*)vo)->oid_;
1184  Py_XDECREF(vo);
1185  _value.push_back(v);
1186  }
1187  ret = Field< vector < ObjId > >::set(self->oid_, string(field), _value);
1188  }
1189  break;
1190  }
1191  default:
1192  break;
1193  }
1194  // MOOSE Field::set returns 1 for success 0 for
1195  // failure. Python treats return value 0 from stters as
1196  // success, anything else failure.
1197  if (ret)
1198  {
1199  return 0;
1200  }
1201  else
1202  {
1203  ostringstream msg;
1204  msg << "Failed to set field '" << field << "'";
1205  PyErr_SetString(PyExc_AttributeError,msg.str().c_str());
1206  return -1;
1207  }
1208 } // moose_ObjId_setattro
1209 
1210 PyObject * moose_ObjId_getItem(_ObjId * self, Py_ssize_t index)
1211 {
1212  if (index < 0)
1213  {
1214  index += moose_ObjId_getLength(self);
1215  }
1216  if ((index < 0) || (index >= moose_ObjId_getLength(self)))
1217  {
1218  PyErr_SetString(PyExc_IndexError, "Index out of bounds.");
1219  return NULL;
1220  }
1221  // Here I am assuming the user can start with any ObjId and
1222  // ask for an index - which will be field index.
1223  // Thus if syn[0...9] correspond to chan[0...9], then syn[0] is still a valid ObjId.
1224  // For example, syn has Id X, dataIndex 0...9, and under dataIndex=0, we have 5 field elements f[0...5]
1225  // Then syn = Id(X)
1226  // syn[0] = ObjId(X, 0, 0) = syn[0][0]
1227  // assign s0 <- syn[0]
1228  // what is s0[1]? ObjId(X
1229  // syn[0][1]->ObjId(X, 0, 1) =syn[0][0][0] - which is an ObjId.
1230  // Now, what is syn[0][1][2] ?
1231 
1232  // In PyMOOSE, user is allowed to directly put in the numbers
1233  // for Id, dataIndex and fieldIndex directly and construct an
1234  // ObjId.
1235  _ObjId * ret = PyObject_New(_ObjId, &ObjIdType);
1236  ret->oid_ = ObjId(self->oid_.id, self->oid_.dataIndex, index);
1237  return (PyObject*)ret;
1238 }
1239 
1240 PyObject * moose_ObjId_getSlice(_ObjId * self, Py_ssize_t start, Py_ssize_t end)
1241 {
1242  Py_ssize_t len = moose_ObjId_getLength(self);
1243  while (start < 0)
1244  {
1245  start += len;
1246  }
1247  while (end < 0)
1248  {
1249  end += len;
1250  }
1251  if (start > end)
1252  {
1253  // PyErr_SetString(PyExc_IndexError, "Start index must be less than end.");
1254  // python itself returns empty tuple - follow that
1255  return PyTuple_New(0);
1256  }
1257  PyObject * ret = PyTuple_New((Py_ssize_t)(end - start));
1258 
1259  // Py_XINCREF(ret);
1260  for ( int ii = start; ii < end; ++ii)
1261  {
1262  _ObjId * value = PyObject_New(_ObjId, &ObjIdType);
1263  value->oid_ = ObjId(self->oid_.id, self->oid_.dataIndex, ii);
1264  if (PyTuple_SetItem(ret, (Py_ssize_t)(ii-start), (PyObject*)value)) // danger - must we DECREF all prior values?
1265  {
1266  Py_XDECREF(ret);
1267  // Py_XDECREF(value);
1268  PyErr_SetString(PyExc_RuntimeError, "Failed to assign tuple entry.");
1269  return NULL;
1270  }
1271  }
1272  return ret;
1273 }
1274 
1275 
1276 Py_ssize_t moose_ObjId_getLength(_ObjId * self)
1277 {
1278  Element * el = self->oid_.element();
1279  if (!el->hasFields())
1280  {
1281  return 0;
1282  }
1283  FieldElement * fe = reinterpret_cast< FieldElement* >(el);
1284  if (fe == NULL)
1285  {
1286  return 0;
1287  }
1288  return (Py_ssize_t)(fe->numData());
1289 }
1290 
1295 PyObject * getLookupField(ObjId target, char * fieldName, PyObject * key)
1296 {
1297  vector<string> type_vec;
1298  if (parseFinfoType(Field<string>::get(target, "className"), "lookupFinfo", string(fieldName), type_vec) < 0)
1299  {
1300  ostringstream error;
1301  error << "Cannot handle key type for LookupField `" << Field<string>::get(target, "className") << "." << fieldName << "`.";
1302  PyErr_SetString(PyExc_TypeError, error.str().c_str());
1303  return NULL;
1304  }
1305  if (type_vec.size() != 2)
1306  {
1307  ostringstream error;
1308  error << "LookupField type signature should be <keytype>, <valuetype>. But for `"
1309  << Field<string>::get(target, "className") << "." << fieldName << "` got " << type_vec.size() << " components." ;
1310  PyErr_SetString(PyExc_AssertionError, error.str().c_str());
1311  return NULL;
1312  }
1313  PyObject * ret = NULL;
1314  char key_type_code = shortType(type_vec[0]);
1315  char value_type_code = shortType(type_vec[1]);
1316  switch(key_type_code)
1317  {
1318  case 'b':
1319  {
1320  ret = lookup_value <bool> (target, string(fieldName), value_type_code, key_type_code, key);
1321  break;
1322  }
1323  case 'c':
1324  {
1325  ret = lookup_value <char> (target, string(fieldName), value_type_code, key_type_code, key);
1326  break;
1327  }
1328  case 'h':
1329  {
1330  ret = lookup_value <short> (target, string(fieldName), value_type_code, key_type_code, key);
1331  break;
1332  }
1333  case 'H':
1334  {
1335  ret = lookup_value <unsigned short> (target, string(fieldName), value_type_code, key_type_code, key);
1336  break;
1337  }
1338  case 'i':
1339  {
1340  ret = lookup_value <int> (target, string(fieldName), value_type_code, key_type_code, key);
1341  break;
1342  }
1343  case 'I':
1344  {
1345  ret = lookup_value <unsigned int> (target, string(fieldName), value_type_code, key_type_code, key);
1346  break;
1347  }
1348  case 'l':
1349  {
1350  ret = lookup_value <long> (target, string(fieldName), value_type_code, key_type_code, key);
1351  break;
1352  }
1353  case 'k':
1354  {
1355  ret = lookup_value <unsigned long> (target, string(fieldName), value_type_code, key_type_code, key);
1356  break;
1357  }
1358  case 'L':
1359  {
1360  ret = lookup_value <long long> (target, string(fieldName), value_type_code, key_type_code, key);
1361  break;
1362  }
1363  case 'K':
1364  {
1365  ret = lookup_value <unsigned long long> (target, string(fieldName), value_type_code, key_type_code, key);
1366  break;
1367  }
1368  case 'd':
1369  {
1370  ret = lookup_value <double> (target, string(fieldName), value_type_code, key_type_code, key);
1371  break;
1372  }
1373  case 'f':
1374  {
1375  ret = lookup_value <float> (target, string(fieldName), value_type_code, key_type_code, key);
1376  break;
1377  }
1378  case 's':
1379  {
1380  ret = lookup_value <string> (target, string(fieldName), value_type_code, key_type_code, key);
1381  break;
1382  }
1383  case 'x':
1384  {
1385  ret = lookup_value <Id> (target, string(fieldName), value_type_code, key_type_code, key);
1386  break;
1387  }
1388  case 'y':
1389  {
1390  ret = lookup_value <ObjId> (target, string(fieldName), value_type_code, key_type_code, key);
1391  break;
1392  }
1393  case 'D':
1394  {
1395  ret = lookup_value < vector <double> >(target, string(fieldName), value_type_code, key_type_code, key);
1396  break;
1397  }
1398  case 'S':
1399  {
1400  ret = lookup_value < vector <string> >(target, string(fieldName), value_type_code, key_type_code, key);
1401  break;
1402  }
1403  case 'X':
1404  {
1405  ret = lookup_value < vector <Id> >(target, string(fieldName), value_type_code, key_type_code, key);
1406  break;
1407  }
1408  case 'Y':
1409  {
1410  ret = lookup_value < vector <ObjId> >(target, string(fieldName), value_type_code, key_type_code, key);
1411  break;
1412  }
1413  case 'v':
1414  {
1415  ret = lookup_value < vector <int> >(target, string(fieldName), value_type_code, key_type_code, key);
1416  break;
1417  }
1418  case 'N':
1419  {
1420  ret = lookup_value < vector <unsigned int> >(target, string(fieldName), value_type_code, key_type_code, key);
1421  break;
1422  }
1423  case 'P':
1424  {
1425  ret = lookup_value < vector <unsigned long> >(target, string(fieldName), value_type_code, key_type_code, key);
1426  break;
1427  }
1428  case 'F':
1429  {
1430  ret = lookup_value < vector <float> >(target, string(fieldName), value_type_code, key_type_code, key);
1431  break;
1432  }
1433  case 'w':
1434  {
1435  ret = lookup_value < vector <short> >(target, string(fieldName), value_type_code, key_type_code, key);
1436  break;
1437  }
1438  case 'C':
1439  {
1440  ret = lookup_value < vector <char> >(target, string(fieldName), value_type_code, key_type_code, key);
1441  break;
1442  }
1443  default:
1444  ostringstream error;
1445  error << "Unhandled key type `" << type_vec[0] << "` for " << Field<string>::get(target, "className") << "." << fieldName;
1446  PyErr_SetString(PyExc_TypeError, error.str().c_str());
1447  }
1448  return ret;
1449 }
1450 
1451 PyDoc_STRVAR(moose_ObjId_getLookupField_documentation,
1452  "getLookupField(fieldname, key) -> value type\n"
1453  "\n"
1454  "Lookup entry for `key` in `fieldName`\n"
1455  "\n"
1456  "Parameters\n"
1457  "----------\n"
1458  "fieldname : string\n"
1459  " Name of the lookupfield.\n"
1460  "\n"
1461  "key : appropriate type for key of the lookupfield (as in the dict "
1462  " getFieldDict).\n"
1463  " Key for the look-up.");
1464 
1465 PyObject * moose_ObjId_getLookupField(_ObjId * self, PyObject * args)
1466 {
1467  if (!Id::isValid(self->oid_.id))
1468  {
1469  RAISE_INVALID_ID(NULL, "moose_ObjId_getLookupField");
1470  }
1471  char * fieldName = NULL;
1472  PyObject * key = NULL;
1473  if (!PyArg_ParseTuple(args, "sO:moose_ObjId_getLookupField", &fieldName, &key))
1474  {
1475  return NULL;
1476  }
1477  return getLookupField(self->oid_, fieldName, key);
1478 } // moose_ObjId_getLookupField
1479 
1480 int setLookupField(ObjId target, char * fieldName, PyObject * key, PyObject * value)
1481 {
1482  vector<string> type_vec;
1483  if (parseFinfoType(Field<string>::get(target, "className"), "lookupFinfo", string(fieldName), type_vec) < 0)
1484  {
1485  ostringstream error;
1486  error << "Cannot handle key type for LookupField `" << Field<string>::get(target, "className") << "." << fieldName << "`.";
1487  PyErr_SetString(PyExc_TypeError, error.str().c_str());
1488  return -1;
1489  }
1490  if (type_vec.size() != 2)
1491  {
1492  ostringstream error;
1493  error << "LookupField type signature should be <keytype>, <valuetype>. But for `"
1494  << Field<string>::get(target, "className") << "." << fieldName << "` got " << type_vec.size() << " components." ;
1495  PyErr_SetString(PyExc_AssertionError, error.str().c_str());
1496  return -1;
1497  }
1498  char key_type_code = shortType(type_vec[0]);
1499  char value_type_code = shortType(type_vec[1]);
1500  int ret = -1;
1501  switch(key_type_code)
1502  {
1503  case 'I':
1504  {
1505  ret = set_lookup_value <unsigned int> (target, string(fieldName), value_type_code, key_type_code, key, value);
1506  break;
1507  }
1508  case 'k':
1509  {
1510  ret = set_lookup_value <unsigned long> (target, string(fieldName), value_type_code, key_type_code, key, value);
1511  break;
1512  }
1513  case 's':
1514  {
1515  ret = set_lookup_value <string> (target, string(fieldName), value_type_code, key_type_code, key, value);
1516  break;
1517  }
1518  case 'i':
1519  {
1520  ret = set_lookup_value <int> (target, string(fieldName), value_type_code, key_type_code, key, value);
1521  break;
1522  }
1523  case 'l':
1524  {
1525  ret = set_lookup_value <long> (target, string(fieldName), value_type_code, key_type_code, key, value);
1526  break;
1527  }
1528  case 'L':
1529  {
1530  ret = set_lookup_value <long long> (target, string(fieldName), value_type_code, key_type_code, key, value);
1531  break;
1532  }
1533  case 'K':
1534  {
1535  ret = set_lookup_value <unsigned long long> (target, string(fieldName), value_type_code, key_type_code, key, value);
1536  break;
1537  }
1538  case 'b':
1539  {
1540  ret = set_lookup_value <bool> (target, string(fieldName), value_type_code, key_type_code, key, value);
1541  break;
1542  }
1543  case 'c':
1544  {
1545  ret = set_lookup_value <char> (target, string(fieldName), value_type_code, key_type_code, key, value);
1546  break;
1547  }
1548  case 'h':
1549  {
1550  ret = set_lookup_value <short> (target, string(fieldName), value_type_code, key_type_code, key, value);
1551  break;
1552  }
1553  case 'H':
1554  {
1555  ret = set_lookup_value <unsigned short> (target, string(fieldName), value_type_code, key_type_code, key, value);
1556  break;
1557  }
1558  case 'd':
1559  {
1560  ret = set_lookup_value <double> (target, string(fieldName), value_type_code, key_type_code, key, value);
1561  break;
1562  }
1563  case 'f':
1564  {
1565  ret = set_lookup_value <float> (target, string(fieldName), value_type_code, key_type_code, key, value);
1566  break;
1567  }
1568  case 'x':
1569  {
1570  ret = set_lookup_value <Id> (target, string(fieldName), value_type_code, key_type_code, key, value);
1571  break;
1572  }
1573  case 'y':
1574  {
1575  ret = set_lookup_value <ObjId> (target, string(fieldName), value_type_code, key_type_code, key, value);
1576  break;
1577  }
1578  default:
1579  ostringstream error;
1580  error << "setLookupField: invalid key type " << type_vec[0];
1581  PyErr_SetString(PyExc_TypeError, error.str().c_str());
1582  }
1583  return ret;
1584 }// setLookupField
1585 
1586 PyDoc_STRVAR(moose_ObjId_setLookupField_documentation,
1587  "setLookupField(fieldname, key, value)\n"
1588  "\n"
1589  "Set a lookup field entry.\n"
1590  "\n"
1591  "Parameters\n"
1592  "----------\n"
1593  "fieldname : str\n"
1594  " name of the field to be set\n"
1595  "key : key type\n"
1596  " key in the lookup field for which the value is to be set.\n"
1597  "value : value type\n"
1598  " value to be set for `key` in the lookup field.\n");
1599 
1600 PyObject * moose_ObjId_setLookupField(_ObjId * self, PyObject * args)
1601 {
1602  if (!Id::isValid(self->oid_.id))
1603  {
1604  return NULL;
1605  }
1606  PyObject * key;
1607  PyObject * value;
1608  char * field;
1609  if (!PyArg_ParseTuple(args, "sOO:moose_ObjId_setLookupField", &field, &key, &value))
1610  {
1611  return NULL;
1612  }
1613  if ( setLookupField(self->oid_, field, key, value) == 0)
1614  {
1615  Py_RETURN_NONE;
1616  }
1617  return NULL;
1618 }// moose_ObjId_setLookupField
1619 
1620 PyDoc_STRVAR(moose_ObjId_setDestField_documentation,
1621  "setDestField(arg0, arg1, ...)\n"
1622  "\n"
1623  "Set a destination field. This is for advanced uses. destFields can\n"
1624  "(and should) be directly called like functions as\n"
1625  "`element.fieldname(arg0, ...)`\n"
1626  "\n"
1627  "Parameters\n"
1628  "----------\n"
1629  "The number and type of paramateres depend on the destFinfo to be\n"
1630  "set. Use moose.doc('{classname}.{fieldname}') to get builtin\n"
1631  "documentation on the destFinfo `fieldname`\n"
1632  );
1633 
1634 PyObject * moose_ObjId_setDestField(_ObjId * self, PyObject * args)
1635 {
1636  if (!Id::isValid(self->oid_.id))
1637  {
1638  RAISE_INVALID_ID(NULL, "moose_ObjId_setDestField");
1639  }
1640  PyObject * arglist[10] = {NULL, NULL, NULL, NULL, NULL,
1641  NULL, NULL, NULL, NULL, NULL
1642  };
1643  ostringstream error;
1644  ObjId oid = ((_ObjId*)self)->oid_;
1645 
1646  error << "moose.setDestField: ";
1647  // Unpack the arguments
1648  if (!PyArg_UnpackTuple(args, "setDestField", minArgs, maxArgs,
1649  &arglist[0], &arglist[1], &arglist[2],
1650  &arglist[3], &arglist[4], &arglist[5],
1651  &arglist[6], &arglist[7], &arglist[8],
1652  &arglist[9]))
1653  {
1654  error << "At most " << maxArgs - 1 << " arguments can be handled.";
1655  PyErr_SetString(PyExc_ValueError, error.str().c_str());
1656  return NULL;
1657  }
1658 
1659  // Get the destFinfo name
1660  char * fieldName = PyString_AsString(arglist[0]);
1661  if (!fieldName) // not a string, raises TypeError
1662  {
1663  error << "first argument must be a string specifying field name.";
1664  PyErr_SetString(PyExc_TypeError, error.str().c_str());
1665  return NULL;
1666  }
1667 
1668  // Try to parse the arguments.
1669  vector< string > argType;
1670  if (parseFinfoType(Field<string>::get(oid, "className"),
1671  "destFinfo", string(fieldName), argType) < 0)
1672  {
1673  error << "Arguments not handled: " << fieldName << "(";
1674  for (unsigned int ii = 0; ii < argType.size(); ++ii)
1675  {
1676  error << argType[ii] << ",";
1677  }
1678  error << ")";
1679  PyErr_SetString(PyExc_TypeError, error.str().c_str());
1680  return NULL;
1681  }
1682  if (argType.size() == 1)
1683  {
1684  if ( arglist[1] == NULL && argType[0] == "void")
1685  {
1686  bool ret = SetGet0::set(oid, string(fieldName));
1687  if (ret)
1688  {
1689  Py_RETURN_TRUE;
1690  }
1691  else
1692  {
1693  Py_RETURN_FALSE;
1694  }
1695  }
1696  return setDestFinfo(oid, string(fieldName), arglist[1], argType[0]);
1697  }
1698  else if (argType.size() == 2)
1699  {
1700  return setDestFinfo2(oid, string(fieldName), arglist[1], shortType(argType[0]), arglist[2], shortType(argType[1]));
1701  }
1702  else
1703  {
1704  error << "Can handle only up to 2 arguments" << endl;
1705  return NULL;
1706  }
1707 } // moose_ObjId_setDestField
1708 
1709 PyObject * setDestFinfo(ObjId obj, string fieldName, PyObject *arg, string argType)
1710 {
1711  char typecode = shortType(argType);
1712  bool ret;
1713  ostringstream error;
1714  error << "moose.setDestFinfo: ";
1715 
1716  switch (typecode)
1717  {
1718  case 'f':
1719  case 'd':
1720  {
1721  double param = PyFloat_AsDouble(arg);
1722  if (typecode == 'f')
1723  {
1724  ret = SetGet1<float>::set(obj, fieldName, (float)param);
1725  }
1726  else
1727  {
1728  ret = SetGet1<double>::set(obj, fieldName, param);
1729  }
1730  }
1731  break;
1732  case 's':
1733  {
1734  char * param = PyString_AsString(arg);
1735  ret = SetGet1<string>::set(obj, fieldName, string(param));
1736  }
1737  break;
1738  case 'i':
1739  case 'l':
1740  {
1741  long param = PyInt_AsLong(arg);
1742  if (param == -1 && PyErr_Occurred())
1743  {
1744  return NULL;
1745  }
1746  if (typecode == 'i')
1747  {
1748  ret = SetGet1<int>::set(obj, fieldName, (int)param);
1749  }
1750  else
1751  {
1752  ret = SetGet1<long>::set(obj, fieldName, param);
1753  }
1754  }
1755  break;
1756  case 'I':
1757  case 'k':
1758  {
1759  unsigned long param =PyLong_AsUnsignedLong(arg);
1760  if (PyErr_Occurred())
1761  {
1762  return NULL;
1763  }
1764  if (typecode == 'I')
1765  {
1766  ret = SetGet1< unsigned int>::set(obj, fieldName, (unsigned int)param);
1767  }
1768  else
1769  {
1770  ret = SetGet1<unsigned long>::set(obj, fieldName, param);
1771  }
1772  }
1773  break;
1774  case 'x':
1775  {
1776  Id param;
1777  _Id * id = (_Id*)(arg);
1778  if (id == NULL)
1779  {
1780  error << "argument should be an vec or an melement";
1781  PyErr_SetString(PyExc_TypeError, error.str().c_str());
1782  return NULL;
1783  }
1784  param = id->id_;
1785  ret = SetGet1<Id>::set(obj, fieldName, param);
1786  }
1787  break;
1788  case 'y':
1789  {
1790  ObjId param;
1791  _ObjId * oid = (_ObjId*)(arg);
1792  if (oid == NULL)
1793  {
1794  error << "argument should be vec or an melement";
1795  PyErr_SetString(PyExc_TypeError, error.str().c_str());
1796  return NULL;
1797  }
1798  param = oid->oid_;
1799  ret = SetGet1<ObjId>::set(obj, fieldName, param);
1800  }
1801  break;
1802  case 'c':
1803  {
1804  char * param = PyString_AsString(arg);
1805  if (!param)
1806  {
1807  error << "expected argument of type char/string";
1808  PyErr_SetString(PyExc_TypeError, error.str().c_str());
1809  return NULL;
1810  }
1811  else if (strlen(param) == 0)
1812  {
1813  error << "Empty string not allowed.";
1814  PyErr_SetString(PyExc_ValueError, error.str().c_str());
1815  return NULL;
1816  }
1817  ret = SetGet1<char>::set(obj, fieldName, param[0]);
1818  }
1819  break;
1821  // We do NOT handle multiple vectors. Use the argument
1822  // list as a single vector argument.
1824  case 'v':
1825  {
1826  return _set_vector_destFinfo<int>(obj, string(fieldName), arg, typecode);
1827  }
1828  case 'w':
1829  {
1830  return _set_vector_destFinfo<short>(obj, string(fieldName), arg, typecode);
1831  }
1832  case 'L': //SET_VECFIELD(long, l) {
1833  {
1834  return _set_vector_destFinfo<long>(obj, string(fieldName), arg, typecode);
1835  }
1836  case 'N': //SET_VECFIELD(unsigned int, I)
1837  {
1838  return _set_vector_destFinfo<unsigned int>(obj, string(fieldName), arg, typecode);
1839  }
1840  case 'K': //SET_VECFIELD(unsigned long, k)
1841  {
1842  return _set_vector_destFinfo<unsigned long>(obj, string(fieldName), arg, typecode);
1843  }
1844  case 'F': //SET_VECFIELD(float, f)
1845  {
1846  return _set_vector_destFinfo<float>(obj, string(fieldName), arg, typecode);
1847  }
1848  case 'D': //SET_VECFIELD(double, d)
1849  {
1850  return _set_vector_destFinfo<double>(obj, string(fieldName), arg, typecode);
1851  }
1852  case 'S':
1853  {
1854  return _set_vector_destFinfo<string>(obj, string(fieldName), arg, typecode);
1855  }
1856  case 'X':
1857  {
1858  return _set_vector_destFinfo<Id>(obj, string(fieldName), arg, typecode);
1859  }
1860  case 'Y':
1861  {
1862  return _set_vector_destFinfo<ObjId>(obj, string(fieldName), arg, typecode);
1863  }
1864  default:
1865  {
1866  error << "Cannot handle argument type: " << argType;
1867  PyErr_SetString(PyExc_TypeError, error.str().c_str());
1868  return NULL;
1869  }
1870  } // switch (shortType(argType[ii])
1871  if (ret)
1872  {
1873  Py_RETURN_TRUE;
1874  }
1875  else
1876  {
1877  Py_RETURN_FALSE;
1878  }
1879 
1880 }
1881 
1885 // template <class A>
1886 PyObject* setDestFinfo2(ObjId obj, string fieldName, PyObject * arg1, char type1, PyObject * arg2, char type2)
1887 {
1888  ostringstream error;
1889  error << "moose.setDestFinfo2: ";
1890  switch (type2)
1891  {
1892  case 'f':
1893  case 'd':
1894  {
1895  double param = PyFloat_AsDouble(arg2);
1896  if (type2 == 'f')
1897  {
1898  return setDestFinfo1<float>(obj, fieldName, arg1, type1, (float)param);
1899  }
1900  else
1901  {
1902  return setDestFinfo1<double>(obj, fieldName, arg1, type1, param);
1903  }
1904  }
1905  case 's':
1906  {
1907  char * param = PyString_AsString(arg2);
1908  return setDestFinfo1<string>(obj, fieldName, arg1, type1, string(param));
1909  }
1910  case 'i':
1911  case 'l':
1912  {
1913  long param = PyInt_AsLong(arg2);
1914  if (param == -1 && PyErr_Occurred())
1915  {
1916  return NULL;
1917  }
1918  if (type2 == 'i')
1919  {
1920  return setDestFinfo1< int>(obj, fieldName, arg1, type1, (int)param);
1921  }
1922  else
1923  {
1924  return setDestFinfo1< long>(obj, fieldName, arg1, type1, param);
1925  }
1926  }
1927  case 'I':
1928  case 'k':
1929  {
1930  unsigned long param =PyLong_AsUnsignedLong(arg2);
1931  if (PyErr_Occurred())
1932  {
1933  return NULL;
1934  }
1935  if (type2 == 'I')
1936  {
1937  return setDestFinfo1< unsigned int>(obj, fieldName, arg1, type1, (unsigned int)param);
1938  }
1939  else
1940  {
1941  return setDestFinfo1< unsigned long>(obj, fieldName, arg1, type1, param);
1942  }
1943  }
1944  case 'x':
1945  {
1946  Id param;
1947  // if (Id_SubtypeCheck(arg)){
1948  _Id * id = (_Id*)(arg2);
1949  if (id == NULL)
1950  {
1951  error << "argument should be an vec or an melement";
1952  PyErr_SetString(PyExc_TypeError, error.str().c_str());
1953  return NULL;
1954  }
1955  param = id->id_;
1956  // } else if (ObjId_SubtypeCheck(arg)){
1957  // _ObjId * oid = (_ObjId*)(arg);
1958  // if (oid == NULL){
1959  // error << "argument should be an vec or an melement";
1960  // PyErr_SetString(PyExc_TypeError, error.str().c_str());
1961  // return NULL;
1962  // }
1963  // param = oid->oid_.id;
1964  // }
1965  return setDestFinfo1< Id>(obj, fieldName, arg1, type1, param);
1966  }
1967  case 'y':
1968  {
1969  ObjId param;
1970  // if (Id_SubtypeCheck(arg)){
1971  // _Id * id = (_Id*)(arg);
1972  // if (id == NULL){
1973  // error << "argument should be an vec or an melement";
1974  // PyErr_SetString(PyExc_TypeError, error.str().c_str());
1975  // return NULL;
1976  // }
1977  // param = ObjId(id->id_);
1978  // } else if (ObjId_SubtypeCheck(arg)){
1979  _ObjId * oid = (_ObjId*)(arg2);
1980  if (oid == NULL)
1981  {
1982  error << "argument should be an vec or an melement";
1983  PyErr_SetString(PyExc_TypeError, error.str().c_str());
1984  return NULL;
1985  }
1986  param = oid->oid_;
1987  // }
1988  return setDestFinfo1< ObjId>(obj, fieldName, arg1, type1, param);
1989  }
1990  case 'c':
1991  {
1992  char * param = PyString_AsString(arg2);
1993  if (!param)
1994  {
1995  error << "expected argument of type char/string";
1996  PyErr_SetString(PyExc_TypeError, error.str().c_str());
1997  return NULL;
1998  }
1999  else if (strlen(param) == 0)
2000  {
2001  error << "Empty string not allowed.";
2002  PyErr_SetString(PyExc_ValueError, error.str().c_str());
2003  return NULL;
2004  }
2005  return setDestFinfo1< char>(obj, fieldName, arg1, type1, param[0]);
2006  }
2007  default:
2008  {
2009  error << "Unhandled argument 2 type (shortType=" << type2 << ")";
2010  PyErr_SetString(PyExc_TypeError, error.str().c_str());
2011  return NULL;
2012  }
2013  }
2014 }
2015 
2016 
2017 PyDoc_STRVAR(moose_ObjId_getFieldNames_documenation,
2018  "getFieldNames(fieldType='') -> tuple of str\n"
2019  "\n"
2020  "Returns the names of fields of this element of fieldType kind.\n"
2021  "\n"
2022  "Parameters\n"
2023  "----------\n"
2024  "fieldType : str\n"
2025  " Type of the fields you wish to retrieve. Can be\n"
2026  " - `valueFinfo` - attributes of the object\n"
2027  " - `srcFinfo` - fields of the object which can be used as source of information for connect\n"
2028  " - `destFinfo` - fields of the object which can be used as destination of information for connect\n"
2029  " - `lookupFinfo`- fields which can be looked at through this object"
2030  ", etc. If an empty string is specified, names of all avaialable fields are returned.\n"
2031  "\n"
2032  "Returns\n"
2033  "-------\n"
2034  "names : tuple of strings.\n"
2035  " names of the fields of the specified type.\n"
2036  "\n"
2037  "Examples\n"
2038  "--------\n"
2039  "List names of all the source fields in PulseGen class:\n"
2040  "\n"
2041  " >>> comp.getFieldNames('lookupFinfo') \n"
2042  " ('neighbors', 'msgDests', 'msgDestFunctions', 'isA')\n"
2043  " >>> moose.getFieldNames('PulseGen', 'srcFinfo')\n"
2044  " ('childMsg', 'output')\n"
2045  "\n");
2046 // 2011-03-23 15:28:26 (+0530)
2047 PyObject * moose_ObjId_getFieldNames(_ObjId * self, PyObject *args)
2048 {
2049  if (!Id::isValid(self->oid_.id))
2050  {
2051  RAISE_INVALID_ID(NULL, "moose_ObjId_getFieldNames");
2052  }
2053  char * ftype = NULL;
2054  if (!PyArg_ParseTuple(args, "|s:moose_ObjId_getFieldNames", &ftype))
2055  {
2056  return NULL;
2057  }
2058  string ftype_str = (ftype != NULL)? string(ftype): "";
2059  vector<string> ret;
2060  string className = Field<string>::get(self->oid_, "className");
2061  if (ftype_str == "")
2062  {
2063  for (const char **a = getFinfoTypes(); *a; ++a)
2064  {
2065  vector<string> fields = getFieldNames(className, string(*a));
2066  ret.insert(ret.end(), fields.begin(), fields.end());
2067  }
2068  }
2069  else
2070  {
2071  ret = getFieldNames(className, ftype_str);
2072  }
2073 
2074  PyObject * pyret = PyTuple_New((Py_ssize_t)ret.size());
2075 
2076  for (unsigned int ii = 0; ii < ret.size(); ++ ii )
2077  {
2078  PyObject * fname = Py_BuildValue("s", ret[ii].c_str());
2079  if (!fname)
2080  {
2081  Py_XDECREF(pyret);
2082  pyret = NULL;
2083  break;
2084  }
2085  if (PyTuple_SetItem(pyret, (Py_ssize_t)ii, fname))
2086  {
2087  Py_XDECREF(pyret);
2088  // Py_DECREF(fname);
2089  pyret = NULL;
2090  break;
2091  }
2092  }
2093  return pyret;
2094 }
2095 
2096 PyDoc_STRVAR(moose_ObjId_getNeighbors_documentation,
2097  "getNeighbors(fieldName) -> tuple of vecs\n"
2098  "\n"
2099  "Get the objects connected to this element on specified field.\n"
2100  "\n"
2101  "Parameters\n"
2102  "----------\n"
2103  "fieldName : str\n"
2104  " name of the connection field (a destFinfo/srcFinfo/sharedFinfo)\n"
2105  "\n"
2106  "Returns\n"
2107  "-------\n"
2108  "neighbors: tuple of vecs.\n"
2109  " tuple containing the ids of the neighbour vecs.\n"
2110  "\n");
2111 
2112 PyObject * moose_ObjId_getNeighbors(_ObjId * self, PyObject * args)
2113 {
2114  if (!Id::isValid(self->oid_.id))
2115  {
2116  RAISE_INVALID_ID(NULL, "moose_ObjId_getNeighbors");
2117  }
2118  char * field = NULL;
2119  if (!PyArg_ParseTuple(args, "s:moose_ObjId_getNeighbors", &field))
2120  {
2121  return NULL;
2122  }
2123  vector< Id > val = LookupField< string, vector< Id > >::get(self->oid_, "neighbors", string(field));
2124 
2125  PyObject * ret = PyTuple_New((Py_ssize_t)val.size());
2126 
2127  for (unsigned int ii = 0; ii < val.size(); ++ ii )
2128  {
2129  _Id * entry = PyObject_New(_Id, &IdType);
2130  if (!entry || PyTuple_SetItem(ret, (Py_ssize_t)ii, (PyObject*)entry))
2131  {
2132  Py_DECREF(ret);
2133  // Py_DECREF((PyObject*)entry);
2134  ret = NULL;
2135  break;
2136  }
2137  entry->id_ = val[ii];
2138  }
2139  return ret;
2140 }
2141 
2142 // 2011-03-28 10:10:19 (+0530)
2143 // 2011-03-23 15:13:29 (+0530)
2144 // getChildren is not required as it can be accessed as getField("children")
2145 
2146 // 2011-03-28 10:51:52 (+0530)
2147 PyDoc_STRVAR(moose_ObjId_connect_documentation,
2148  "connect(src, srcfield, destobj, destfield[,msgtype]) -> bool\n"
2149  "\n"
2150  "Create a message between `src_field` on `src` object to `dest_field` on `dest` object.\n"
2151  "This function is used mainly, to say, connect two entities, and to denote what kind of give-and-take relationship they share."
2152  "It enables the 'destfield' (of the 'destobj') to acquire the data, from 'srcfield'(of the 'src')."
2153  "\n"
2154  "Parameters\n"
2155  "----------\n"
2156  "src : element/vec/string\n"
2157  " the source object (or its path) \n"
2158  " (the one that provides information)\n"
2159  "srcfield : str\n"
2160  " source field on self.(type of the information)\n"
2161  "destobj : element\n"
2162  " Destination object to connect to.\n"
2163  " (The one that need to get information)\n"
2164  "destfield : str\n"
2165  " field to connect to on `destobj`.\n"
2166  "msgtype : str\n"
2167  " type of the message. Can be \n"
2168  " `Single` - \n"
2169  " `OneToAll` - \n"
2170  " `AllToOne` - \n"
2171  " `OneToOne` - \n"
2172  " `Reduce` - \n"
2173  " `Sparse` - \n"
2174  " Default: `Single`.\n"
2175  "\n"
2176  "Returns\n"
2177  "-------\n"
2178  "msgmanager: melement\n"
2179  " message-manager for the newly created message.\n"
2180  "\n"
2181  "Examples\n"
2182  "--------\n"
2183  "Connect the output of a pulse generator to the input of a spike\n"
2184  "generator::\n"
2185  "\n"
2186  " >>> pulsegen = moose.PulseGen('pulsegen')\n"
2187  " >>> spikegen = moose.SpikeGen('spikegen')\n"
2188  " >>> pulsegen.connect('output', spikegen, 'Vm')\n"
2189  "\n"
2190  "See also\n"
2191  "--------\n"
2192  "moose.connect\n"
2193  "\n"
2194  );
2195 PyObject * moose_ObjId_connect(_ObjId * self, PyObject * args)
2196 {
2197  if (!Id::isValid(self->oid_.id))
2198  {
2199  RAISE_INVALID_ID(NULL, "moose_ObjId_connect");
2200  }
2201  extern PyTypeObject ObjIdType;
2202  PyObject * destPtr = NULL;
2203  char * srcField = NULL, * destField = NULL, * msgType = NULL;
2204  static char default_msg_type[] = "Single";
2205  if(!PyArg_ParseTuple(args,
2206  "sOs|s:moose_ObjId_connect",
2207  &srcField,
2208  &destPtr,
2209  &destField,
2210  &msgType))
2211  {
2212  return NULL;
2213  }
2214  if (msgType == NULL)
2215  {
2216  msgType = default_msg_type;
2217  }
2218  _ObjId * dest = reinterpret_cast<_ObjId*>(destPtr);
2219  ObjId mid = SHELLPTR->doAddMsg(msgType,
2220  self->oid_,
2221  string(srcField),
2222  dest->oid_,
2223  string(destField));
2224  if (mid.bad())
2225  {
2226  PyErr_SetString(PyExc_NameError,
2227  "connect failed: check field names and type compatibility.");
2228  return NULL;
2229  }
2230  _ObjId* msgMgrId = (_ObjId*)PyObject_New(_ObjId, &ObjIdType);
2231  msgMgrId->oid_ = mid;
2232  return (PyObject*)msgMgrId;
2233 }
2234 
2235 PyDoc_STRVAR(moose_ObjId_richcompare_documentation,
2236  "Compare two element instances. This just does a string comparison of\n"
2237  "the paths of the element instances. This function exists only to\n"
2238  "facilitate certain operations requiring sorting/comparison, like\n"
2239  "using elements for dict keys. Conceptually only equality comparison is\n"
2240  "meaningful for elements.\n");
2241 PyObject* moose_ObjId_richcompare(_ObjId * self, PyObject * other, int op)
2242 {
2243  if (!Id::isValid(self->oid_.id))
2244  {
2245  RAISE_INVALID_ID(NULL, "moose_ObjId_richcompare");
2246  }
2247  extern PyTypeObject ObjIdType;
2248  if ((self != NULL && other == NULL) || (self == NULL && other != NULL))
2249  {
2250  if (op == Py_EQ)
2251  {
2252  Py_RETURN_FALSE;
2253  }
2254  else if (op == Py_NE)
2255  {
2256  Py_RETURN_TRUE;
2257  }
2258  else
2259  {
2260  PyErr_SetString(PyExc_TypeError, "Cannot compare NULL with non-NULL");
2261  return NULL;
2262  }
2263  }
2264  if (!PyObject_IsInstance(other, (PyObject*)&ObjIdType))
2265  {
2266  ostringstream error;
2267  error << "Cannot compare ObjId with "
2268  << Py_TYPE(other)->tp_name;
2269  PyErr_SetString(PyExc_TypeError, error.str().c_str());
2270  return NULL;
2271  }
2272  if (!Id::isValid(((_ObjId*)other)->oid_.id))
2273  {
2274  RAISE_INVALID_ID(NULL, "moose_ObjId_richcompare");
2275  }
2276 
2277  string l_path = self->oid_.path();
2278  string r_path = ((_ObjId*)other)->oid_.path();
2279  int result = l_path.compare(r_path);
2280  if (result == 0)
2281  {
2282  if (op == Py_EQ || op == Py_LE || op == Py_GE)
2283  {
2284  Py_RETURN_TRUE;
2285  }
2286  Py_RETURN_FALSE;
2287  }
2288  else if (result < 0)
2289  {
2290  if (op == Py_LT || op == Py_LE || op == Py_NE)
2291  {
2292  Py_RETURN_TRUE;
2293  }
2294  Py_RETURN_FALSE;
2295  }
2296  else
2297  {
2298  if (op == Py_GT || op == Py_GE || op == Py_NE)
2299  {
2300  Py_RETURN_TRUE;
2301  }
2302  Py_RETURN_FALSE;
2303  }
2304 }
2305 
2306 PyDoc_STRVAR(moose_ObjId_getDataIndex_documentation,
2307  "getDataIndex() -> int\n"
2308  "\n"
2309  "Returns the dataIndex (position of the object in vector) "
2310  "of this object, if it belongs to a vector, otherwise returns 0.\n"
2311  "\n"
2312  " >>> comp = moose.Compartment('/comp')\n"
2313  " >>> comp.getDataIndex()\n"
2314  " >>> 0\n"
2315  ""
2316  );
2318 {
2319  if (!Id::isValid(self->oid_.id))
2320  {
2321  RAISE_INVALID_ID(NULL, "moose_ObjId_getDataIndex");
2322  }
2323  PyObject * ret = Py_BuildValue("I", self->oid_.dataIndex);
2324  return ret;
2325 }
2326 
2327 // WARNING: fieldIndex has been deprecated in dh_branch. This
2328 // needs to be updated accordingly. The current code is just
2329 // place-holer to avoid compilation errors.
2331 {
2332  if (!Id::isValid(self->oid_.id))
2333  {
2334  RAISE_INVALID_ID(NULL, "moose_ObjId_getFieldIndex");
2335  }
2336  PyObject * ret = Py_BuildValue("I", self->oid_.dataIndex);
2337  return ret;
2338 }
2339 
2341 // Python method lists for PyObject of ObjId
2343 
2344 static PyMethodDef ObjIdMethods[] =
2345 {
2346  {
2347  "getFieldType", (PyCFunction)moose_ObjId_getFieldType, METH_VARARGS,
2348  moose_ObjId_getFieldType_documentation
2349  },
2350  {
2351  "getField", (PyCFunction)moose_ObjId_getField, METH_VARARGS,
2352  moose_ObjId_getField_documentation
2353  },
2354  {
2355  "setField", (PyCFunction)moose_ObjId_setField, METH_VARARGS,
2356  moose_ObjId_setField_documentation
2357  },
2358  {
2359  "getLookupField", (PyCFunction)moose_ObjId_getLookupField, METH_VARARGS,
2360  moose_ObjId_getLookupField_documentation
2361  },
2362  {
2363  "setLookupField", (PyCFunction)moose_ObjId_setLookupField, METH_VARARGS,
2364  moose_ObjId_setLookupField_documentation
2365  },
2366  {
2367  "getId", (PyCFunction)moose_ObjId_getId, METH_NOARGS,
2368  moose_ObjId_getId_documentation
2369  },
2370  {
2371  "vec", (PyCFunction)moose_ObjId_getId, METH_NOARGS,
2372  "Return the vec this element belongs to. This is overridden by the"
2373  " attribute of the same name for quick access."
2374  },
2375  {
2376  "getFieldNames", (PyCFunction)moose_ObjId_getFieldNames, METH_VARARGS,
2377  moose_ObjId_getFieldNames_documenation
2378  },
2379  {
2380  "getNeighbors", (PyCFunction)moose_ObjId_getNeighbors, METH_VARARGS,
2381  moose_ObjId_getNeighbors_documentation
2382  },
2383  {
2384  "connect", (PyCFunction)moose_ObjId_connect, METH_VARARGS,
2385  moose_ObjId_connect_documentation
2386  },
2387  {
2388  "getDataIndex", (PyCFunction)moose_ObjId_getDataIndex, METH_NOARGS,
2389  moose_ObjId_getDataIndex_documentation
2390  },
2391  {
2392  "getFieldIndex", (PyCFunction)moose_ObjId_getFieldIndex, METH_NOARGS,
2393  "Get the index of this object as a field."
2394  },
2395  {
2396  "setDestField", (PyCFunction)moose_ObjId_setDestField, METH_VARARGS,
2397  moose_ObjId_setDestField_documentation
2398  },
2399  {NULL, NULL, 0, NULL}, /* Sentinel */
2400 };
2401 
2402 
2404 // Type defs for PyObject of ObjId
2406 PyDoc_STRVAR(moose_ObjId_documentation,
2407  "Individual moose element contained in an array-type object"
2408  " (vec).\n"
2409  "\n"
2410  "Each element has a unique path, possibly with its index in"
2411  " the vec. These are identified by three components: vec, dndex and"
2412  " findex. vec is the containing vec, which is identified by a unique"
2413  " number (field `value`). `dindex` is the index of the current"
2414  " item in the containing vec. `dindex` is 0 for single elements."
2415  " findex is field index, specifying the index of elements which exist"
2416  " as fields of another moose element.\n"
2417  "\n"
2418  "Notes\n"
2419  "-----\n"
2420  "Users need not create melement directly. Instead use the named moose"
2421  " class for creating new elements. To get a reference to an existing"
2422  " element, use the :ref:`moose.element` function.\n"
2423  "\n"
2424  "Parameters\n"
2425  "----------\n"
2426  "path : str\n"
2427  " path of the element to be created.\n"
2428  "\n"
2429  "n : positive int, optional\n"
2430  " defaults to 1. If greater, then a vec of that size is created and\n"
2431  " this element is a reference to the first entry of the vec.\n"
2432  "\n"
2433  "g : int, optional\n"
2434  " if 1, this is a global element, else if 0 (default), the element\n"
2435  " is local to the current node.\n"
2436  "\n"
2437  "dtype : str\n"
2438  " name of the class of the element. If creating any concrete\n"
2439  " subclass, this is automatically taken from the class name and\n"
2440  " should not be specified explicitly.\n"
2441  "\n"
2442  "Attributes\n"
2443  "----------\n"
2444  "vec : moose.vec\n"
2445  " The vec containing this element. `vec` wraps the Id of the object in MOOSE C++ API.\n"
2446  "\n"
2447  "dindex : int\n"
2448  " index of this element in the container vec\n"
2449  "\n"
2450  "findex: int\n"
2451  " if this is a tertiary object, i.e. acts as a field in another\n"
2452  " element (like synapse[0] in IntFire[1]), then the index of\n"
2453  " this field in the containing element.\n"
2454  "\n"
2455  "Examples\n"
2456  "--------\n"
2457  "\n"
2458  ">>> a = Neutral('alpha') # Creates element named `alpha` under current working element\n"
2459  ">>> b = Neutral('alpha/beta') # Creates the element named `beta` under `alpha`\n"
2460  ">>> c = moose.melement(b)"
2461  );
2462 
2463 PyTypeObject ObjIdType =
2464 {
2465  PyVarObject_HEAD_INIT(NULL, 0) /* tp_head */
2466  "moose.melement", /* tp_name */
2467  sizeof(_ObjId), /* tp_basicsize */
2468  0, /* tp_itemsize */
2469  0, /* tp_dealloc */
2470  0, /* tp_print */
2471  0, /* tp_getattr */
2472  0, /* tp_setattr */
2473  0, /* tp_compare */
2474  (reprfunc)moose_ObjId_repr, /* tp_repr */
2475  0, /* tp_as_number */
2476  0, /* tp_as_sequence */
2477  0, /* tp_as_mapping */
2478  (hashfunc)moose_ObjId_hash, /* tp_hash */
2479  0, /* tp_call */
2480  (reprfunc)moose_ObjId_str, /* tp_str */
2481  (getattrofunc)moose_ObjId_getattro, /* tp_getattro */
2482  (setattrofunc)moose_ObjId_setattro, /* tp_setattro */
2483  0, /* tp_as_buffer */
2484  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
2485  moose_ObjId_documentation,
2486  0, /* tp_traverse */
2487  0, /* tp_clear */
2488  (richcmpfunc)moose_ObjId_richcompare, /* tp_richcompare */
2489  0, /* tp_weaklistoffset */
2490  0, /* tp_iter */
2491  0, /* tp_iternext */
2492  ObjIdMethods, /* tp_methods */
2493  0, /* tp_members */
2494  0, /* tp_getset */
2495  0, /* tp_base */
2496  0, /* tp_dict */
2497  0, /* tp_descr_get */
2498  0, /* tp_descr_set */
2499  0, /* tp_dictoffset */
2500  (initproc) moose_ObjId_init, /* tp_init */
2501  0, /* tp_alloc */
2502  0, /* tp_new */
2503  0, /* tp_free */
2504 };
2505 
2506 
2507 
2508 //
2509 // melement.cpp ends here
PyObject * moose_ObjId_getNeighbors(_ObjId *self, PyObject *args)
Definition: melement.cpp:2112
PyObject_HEAD Id id_
Definition: moosemodule.h:114
PyObject * moose_ObjId_richcompare(_ObjId *self, PyObject *other, int op)
Definition: melement.cpp:2241
char shortType(string)
uint32_t value
Definition: moosemodule.h:42
#define SHELLPTR
Definition: moosemodule.h:105
const char ** getFinfoTypes()
finalize()
PyObject * moose_ObjId_setLookupField(_ObjId *self, PyObject *args)
Definition: melement.cpp:1600
PyObject * getLookupField(ObjId target, char *fieldName, PyObject *key)
Definition: melement.cpp:1295
PyObject * moose_ObjId_getSlice(_ObjId *self, Py_ssize_t start, Py_ssize_t end)
Definition: melement.cpp:1240
static double op(double x)
#define minArgs
Definition: moosemodule.h:84
bool bad() const
Definition: ObjId.cpp:18
PyObject * moose_ObjId_setDestField(_ObjId *self, PyObject *args)
Definition: melement.cpp:1634
Definition: SetGet.h:236
#define Id_Check(v)
Definition: moosemodule.h:95
PyObject * moose_ObjId_getFieldType(_ObjId *self, PyObject *args)
Definition: melement.cpp:420
map< string, PyTypeObject * > & get_moose_classes()
PyObject * moose_ObjId_setField(_ObjId *self, PyObject *args)
Definition: melement.cpp:791
int moose_ObjId_init_from_id(_ObjId *self, PyObject *args, PyObject *kwargs)
Definition: melement.cpp:100
int moose_ObjId_init_from_path(_ObjId *self, PyObject *args, PyObject *kwargs)
Definition: melement.cpp:164
Definition: ObjId.h:20
const map< string, string > & get_field_alias()
static bool set(const ObjId &dest, const string &field, A arg)
Definition: SetGet.h:245
Py_ssize_t moose_ObjId_getLength(_ObjId *self)
Definition: melement.cpp:1276
#define RAISE_INVALID_ID(ret, msg)
Definition: moosemodule.h:71
PyObject_HEAD ObjId oid_
Definition: moosemodule.h:133
PyObject * moose_ObjId_getFieldIndex(_ObjId *self)
Definition: melement.cpp:2330
void * to_cpp(PyObject *object, char typecode)
PyObject * get_ObjId_attr(_ObjId *oid, string attribute)
Definition: melement.cpp:83
PyObject * moose_ObjId_repr(_ObjId *self)
Definition: melement.cpp:355
static char dataIndex[]
Definition: mfield.cpp:406
PyTypeObject IdType
Definition: vec.cpp:262
PyObject * moose_ObjId_getDataIndex(_ObjId *self)
Definition: melement.cpp:2317
static PyMethodDef ObjIdMethods[]
Definition: melement.cpp:2344
Id create_Id_from_path(string path, unsigned int numData, unsigned int isGlobal, string type)
PyObject * moose_ObjId_getattro(_ObjId *self, PyObject *attr)
Definition: melement.cpp:484
long moose_ObjId_hash(_ObjId *self)
Definition: melement.cpp:333
virtual bool hasFields() const =0
PyObject * moose_ObjId_str(_ObjId *self)
Definition: melement.cpp:369
int setLookupField(ObjId target, char *fieldName, PyObject *key, PyObject *value)
Definition: melement.cpp:1480
int moose_ObjId_init(_ObjId *self, PyObject *args, PyObject *kwargs)
Definition: melement.cpp:296
PyObject * moose_ObjId_getId(_ObjId *self)
Definition: melement.cpp:394
string getFieldType(string className, string fieldName)
PyObject * setDestFinfo2(ObjId obj, string fieldName, PyObject *arg1, char type1, PyObject *arg2, char type2)
Definition: melement.cpp:1886
static bool isValid(Id id)
Definition: Id.h:145
int parseFinfoType(string className, string finfoType, string fieldName, vector< string > &typeVec)
static bool set(const ObjId &dest, const string &field)
Definition: SetGet.h:103
PyDoc_STRVAR(moose_ObjId_getId_documentation,"getId() -> vec\n""\n""Returns the information of the object's classtype, Id, and path \n""in form of a vector.\n""\nExample\n""-------\n"" >>> com = moose.Compartment('/com')\n"" >>> com.getId()\n"" moose.vec: class=Compartment, id=481, path=/com>""\n")
std::string fix(const std::string userPath, const string &delimiters)
Definition: strutil.cpp:71
int PyType_IsSubtype(PyTypeObject *, PyTypeObject *)
unsigned int numData() const
Virtual: Returns number of data entries.
static bool set(const ObjId &dest, const string &field, A arg)
Definition: SetGet.h:153
PyObject * moose_ObjId_getFieldNames(_ObjId *self, PyObject *args)
Definition: melement.cpp:2047
#define maxArgs
Definition: moosemodule.h:88
Definition: Id.h:17
PyObject * to_py(void *obj, char typecode)
PyTypeObject * getBaseClass(PyObject *self)
static A get(const ObjId &dest, const string &field)
Definition: SetGet.h:284
PyObject * moose_ObjId_connect(_ObjId *self, PyObject *args)
Definition: melement.cpp:2195
PyObject * moose_ObjId_getItem(_ObjId *self, Py_ssize_t index)
Definition: melement.cpp:1210
unsigned int id_
Definition: Id.h:172
int moose_ObjId_setattro(_ObjId *self, PyObject *attr, PyObject *value)
Definition: melement.cpp:809
vector< string > getFieldNames(string className, string finfoType)
const unsigned int BADINDEX
Used by ObjId and Eref.
Definition: consts.cpp:25
PyObject * moose_ObjId_getLookupField(_ObjId *self, PyObject *args)
Definition: melement.cpp:1465
PyTypeObject ObjIdType
Definition: melement.cpp:2463
static char path[]
Definition: mfield.cpp:403
PyObject * setDestFinfo(ObjId obj, string fieldName, PyObject *arg, string argType)
Definition: melement.cpp:1709
PyObject * moose_ObjId_getField(_ObjId *self, PyObject *args)
Definition: melement.cpp:460