XdmfCore.i 42 KB
Newer Older
1
2
3
4
5
/*
XdmfCorePython.cpp:
swig -v -c++ -python -o XdmfCorePython.cpp XdmfCore.i
*/

6
7
8

#ifdef XDMF_BUILD_DSM

9
10
%module XdmfCore
%{
11
12
13

    #include <mpi.h>

14
15
16
17
18
    #include <XdmfArray.hpp>
    #include <XdmfArrayType.hpp>
    #include <XdmfCore.hpp>
    #include <XdmfCoreItemFactory.hpp>
    #include <XdmfCoreReader.hpp>
19
    #include <XdmfError.hpp>
20
21
22
23
24
25
26
27
28
    #include <XdmfHeavyDataController.hpp>
    #include <XdmfHeavyDataWriter.hpp>
    #include <XdmfHDF5Controller.hpp>
    #include <XdmfHDF5Writer.hpp>
    #include <XdmfHDF5ControllerDSM.hpp>
    #include <XdmfHDF5WriterDSM.hpp>
    #include <XdmfInformation.hpp>
    #include <XdmfItem.hpp>
    #include <XdmfItemProperty.hpp>
29
    #include <XdmfSharedPtr.hpp>
30
    #include <XdmfSparseMatrix.hpp>
31
32
33
34
    #include <XdmfSystemUtils.hpp>
    #include <XdmfVersion.hpp>
    #include <XdmfVisitor.hpp>
    #include <XdmfWriter.hpp>
35
36

    #include <ProjectVersion.hpp>
37
38
%}

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#else

%module XdmfCore
%{
    #include <XdmfArray.hpp>
    #include <XdmfArrayType.hpp>
    #include <XdmfCore.hpp>
    #include <XdmfCoreItemFactory.hpp>
    #include <XdmfCoreReader.hpp>
    #include <XdmfError.hpp>
    #include <XdmfHeavyDataController.hpp>
    #include <XdmfHeavyDataWriter.hpp>
    #include <XdmfHDF5Controller.hpp>
    #include <XdmfHDF5Writer.hpp>
    #include <XdmfInformation.hpp>
    #include <XdmfItem.hpp>
    #include <XdmfItemProperty.hpp>
    #include <XdmfSharedPtr.hpp>
58
    #include <XdmfSparseMatrix.hpp>
59
60
61
62
63
64
65
66
67
68
    #include <XdmfSystemUtils.hpp>
    #include <XdmfVersion.hpp>
    #include <XdmfVisitor.hpp>
    #include <XdmfWriter.hpp>

    #include <ProjectVersion.hpp>
%}

#endif

69
#ifdef SWIGJAVA
70

71
// Ignore const overloaded methods
72
%ignore XdmfArray::getHeavyDataController() const;
73
74
75
%ignore XdmfArray::getValuesInternal() const;
%ignore XdmfItem::getInformation(const unsigned int) const;
%ignore XdmfItem::getInformation(const std::string &) const;
76
%ignore XdmfWriter::getHeavyDataWriter() const;
77
78
%ignore XdmfInformation::getArray(unsigned int const) const;
%ignore XdmfInformation::getArray(std::string const &) const;
79

80
81
82
// Ignore ItemTags
%ignore XdmfArray::ItemTag;
%ignore XdmfInformation::ItemTag;
83

84
// Define equality operators
85
%extend XdmfItem {
86

87
88
89
90
91
92
93
94
95
96
97
98
99
    bool equals(boost::shared_ptr<XdmfItem> item) {
        if (item == NULL) {
            return false;
        }
        return self == item.get();
    }

    bool IsEqual(boost::shared_ptr<XdmfItem> item) {
        if (item == NULL) {
            return false;
        }
        return self == item.get();
    }
100
};
101

102
%extend XdmfItemProperty {
103

104
105
106
107
108
109
110
111
112
113
114
115
116
    bool equals(boost::shared_ptr<XdmfItemProperty> itemProperty) {
        if (itemProperty == NULL) {
            return false;
        }
        return self == itemProperty.get();
    }

    bool IsEqual(boost::shared_ptr<XdmfItemProperty> itemProperty) {
        if (itemProperty == NULL) {
            return false;
        }
        return self == itemProperty.get();
    }
117
118
119

};

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
%typemap(javacode) XdmfArray %{
    public void insertValuesAsInt8(int index, char[] values) {
        for(int i = 0; i < values.length; i++)
            this.insertValueAsInt8(index+i, values[i]);
    }

    public void insertValuesAsInt16(int index, short[] values) {
        for(int i = 0; i < values.length; i++)
            this.insertValueAsInt16(index+i, values[i]);
    }

    public void insertValuesAsInt32(int index, int[] values) {
        for(int i = 0; i < values.length; i++)
            this.insertValueAsInt32(index+i, values[i]);
    }

    public void insertValuesAsFloat32(int index, float[] values) {
        for(int i = 0; i < values.length; i++)
            this.insertValueAsFloat32(index+i, values[i]);
    }

    public void insertValuesAsFloat64(int index, double[] values) {
        for(int i = 0; i < values.length; i++)
            this.insertValueAsFloat64(index+i, values[i]);
    }
%}

147
%pragma(java) jniclasscode=%{
148
149
150
151
152
    static {
        try {
            System.loadLibrary("XdmfCoreJava");
        }
        catch (UnsatisfiedLinkError e) {
153
154
            System.err.println("Native code library failed to load for" +
                               "XdmfCoreJava\n" + e);
155
156
157
            System.exit(1);
        }
    }
158
159
160
%}

#endif /* SWIGJAVA */
161

162
163
#ifdef SWIGPYTHON

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
%exception
{
        try
        {
                $action
        }
        catch (XdmfError e)
        {
                PyErr_SetString(PyExc_RuntimeError, e.what());
                return NULL;
        }
}

#ifdef XDMF_BUILD_DSM

179
180
181
182
%include mpi4py/mpi4py.i

%mpi4py_typemap(Comm, MPI_Comm);

183
184
#endif

185
186
187
188
/*This causes it to avoid throwing a warning for redefining fuctions that are defined for XdmfArray.
  I this case doing so was intentional.*/
#pragma SWIG nowarn=302

189
// Provide accessors from python lists to XdmfArrays
190
%extend XdmfArray {
191

192
%{
193
  #include <stack>
194
195
196
197
198
  static std::map<std::string, PyObject *> pythonFunctions;
  static std::map<char, PyObject *> pythonOperations;
  static int pythonOperationPriority [4];
  static std::string pythonSupportedOperations = "";
%}
199
/*These can't be accessed from python so don't worry about security issues.*/
200

201
202
203
204
205
206
207
208
209
210
    PyObject * getBuffer() {
        void *vp = $self->getValuesInternal();
        Py_ssize_t sz =
            $self->getSize() * $self->getArrayType()->getElementSize();
        PyObject * c = PyBuffer_FromMemory(vp, sz);
        return(c);
    }

    %pythoncode {
        def getNumpyArray(self):
211
            h5ctl = self.getHeavyDataController()
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
            if h5ctl == None :
                try :
                    from numpy import frombuffer as ___frombuffer
                except :
                    return None
                buf = self.getBuffer()
                aType = self.getArrayType()
                if aType == XdmfArrayType.Int8() :
                    return(___frombuffer(buf, 'int8'))
                if aType == XdmfArrayType.Int16() :
                    return(___frombuffer(buf, 'int16'))
                if aType == XdmfArrayType.Int32() :
                    return(___frombuffer(buf, 'int32'))
                if aType == XdmfArrayType.Int64() :
                    return(___frombuffer(buf, 'int64'))
                if aType == XdmfArrayType.Float32() :
                    return(___frombuffer(buf, 'float32'))
                if aType == XdmfArrayType.Float64() :
                    return(___frombuffer(buf, 'float64'))
                if aType == XdmfArrayType.UInt8() :
                    return(___frombuffer(buf, 'uint8'))
                if aType == XdmfArrayType.UInt16() :
                    return(___frombuffer(buf, 'uint16'))
                if aType == XdmfArrayType.UInt32() :
                    return(___frombuffer(buf, 'uint32'))
                return None
            else :
                h5FileName = h5ctl.getFilePath()
                h5DataSetName = h5ctl.getDataSetPath()
                if (h5FileName == None) | (h5DataSetName == None) :
                    return None
                try :
                    from h5py import File as ___File
                    from numpy import array as ___array
                    f = ___File(h5FileName, 'r')
                    if h5DataSetName in f.keys() :
                        return(___array(f[h5DataSetName]))
                except :
                    pass
                return None
    };

254
255
256
257
258
    void insertAsInt8(int startIndex, PyObject * list) {
        Py_ssize_t size = PyList_Size(list);
        for(Py_ssize_t i = 0; i < size; ++i) {
            $self->insert(i+startIndex, (char)(PyLong_AsLong(PyList_GetItem(list, i))));
        }
259
260
    }

261
262
263
264
265
    void insertAsInt16(int startIndex, PyObject * list) {
        Py_ssize_t size = PyList_Size(list);
        for(Py_ssize_t i = 0; i < size; ++i) {
            $self->insert(i+startIndex, (short)(PyLong_AsLong(PyList_GetItem(list, i))));
        }
266
267
    }

268
269
270
271
272
    void insertAsInt32(int startIndex, PyObject * list) {
        Py_ssize_t size = PyList_Size(list);
        for(Py_ssize_t i = 0; i < size; ++i) {
            $self->insert(i+startIndex, (int)(PyLong_AsLong(PyList_GetItem(list, i))));
        }
273
274
    }

275
276
277
278
279
    void insertAsInt64(int startIndex, PyObject * list) {
        Py_ssize_t size = PyList_Size(list);
        for(Py_ssize_t i = 0; i < size; ++i) {
            $self->insert(i+startIndex, PyLong_AsLong(PyList_GetItem(list, i)));
        }
280
281
    }

282
283
284
285
286
    void insertAsFloat32(int startIndex, PyObject * list) {
        Py_ssize_t size = PyList_Size(list);
        for(Py_ssize_t i = 0; i < size; ++i) {
            $self->insert(i+startIndex, (float)PyFloat_AsDouble(PyList_GetItem(list, i)));
        }
287
288
    }

289
290
291
292
293
    void insertAsFloat64(int startIndex, PyObject * list) {
        Py_ssize_t size = PyList_Size(list);
        for(Py_ssize_t i = 0; i < size; ++i) {
            $self->insert(i+startIndex, PyFloat_AsDouble(PyList_GetItem(list, i)));
        }
294
295
    }

296
297
298
299
300
    void insertAsUInt8(int startIndex, PyObject * list) {
        Py_ssize_t size = PyList_Size(list);
        for(Py_ssize_t i = 0; i < size; ++i) {
            $self->insert(i+startIndex, (unsigned char)(PyLong_AsUnsignedLong(PyList_GetItem(list, i))));
        }
301
302
    }

303
304
305
306
307
    void insertAsUInt16(int startIndex, PyObject * list) {
        Py_ssize_t size = PyList_Size(list);
        for(Py_ssize_t i = 0; i < size; ++i) {
            $self->insert(i+startIndex, (unsigned short)(PyLong_AsUnsignedLong(PyList_GetItem(list, i))));
        }
308
309
    }

310
311
312
313
314
    void insertAsUInt32(int startIndex, PyObject * list) {
        Py_ssize_t size = PyList_Size(list);
        for(Py_ssize_t i = 0; i < size; ++i) {
            $self->insert(i+startIndex, (unsigned int)(PyLong_AsUnsignedLong(PyList_GetItem(list, i))));
        }
315
    }
316

Kenneth Leiter's avatar
Kenneth Leiter committed
317
318
319
320
321
322
323
    void insertAsString(int startIndex, PyObject * list) {
        Py_ssize_t size = PyList_Size(list);
        for(Py_ssize_t i = 0; i < size; ++i) {
            $self->insert<std::string>(i+startIndex, PyString_AsString(PyList_GetItem(list, i)));
        }
    }

324
325
326
327
328
329
330
331
332
333

/*Note, the things in this block are defined twice for a reason.
  If they are not defined here they can not be referenced by other functions in swig.*/
%{
    /*trying to transfer python funcitons*/
    /*note, accessing private members is impossible from swig.*/

    /*to generate new static functions mark them as static here.*/
    static shared_ptr<XdmfArray> evaluateFunction(std::vector<shared_ptr<XdmfArray> > functValues, std::string functName)
    {
334
      if (pythonFunctions.find(functName)!= pythonFunctions.end()) {
335
336
337
338
339
340
341
342
343
344
345
346
        swig_type_info * paramType = SWIG_TypeQuery("_p_std__vectorT_boost__shared_ptrT_XdmfArray_t_std__allocatorT_boost__shared_ptrT_XdmfArray_t_t_t");
        PyObject * pyVector = SWIG_NewPointerObj(static_cast<void*>(& functValues), paramType, SWIG_POINTER_NEW);
        PyObject * args = PyTuple_New(1);
        PyTuple_SetItem(args, 0, pyVector);/*In this case you could also cast a pointer to the vector into the PyObject * type, but that doesn't work for all types*/
        PyObject * resultObject = PyObject_CallObject(pythonFunctions[functName], args);
        void * resultPointer = 0;
        swig_type_info * returnType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t");
        SWIG_ConvertPtr(resultObject, &resultPointer, returnType, 0);
        shared_ptr<XdmfArray> * returnArrayPointer = reinterpret_cast<shared_ptr<XdmfArray> *>(resultPointer);
        shared_ptr<XdmfArray> returnArray = returnArrayPointer[0];
        return returnArray;
      }
347
      else {
348
349
350
351
352
353
354
         /*this does not actually cause an infinte recursive loop, it sends the values to the version of the function defined in XdmfArray.cpp*/
         return XdmfArray::evaluateFunction(functValues, functName);
      }
    }

    static shared_ptr<XdmfArray> evaluateOperation(shared_ptr<XdmfArray> val1, shared_ptr<XdmfArray> val2, char functName)
    {
355
      if (pythonOperations.find(functName)!= pythonOperations.end()) {
356
357
358
359
360
361
362
363
364
365
366
367
368
369
        swig_type_info * paramType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t");
        PyObject * pyVal1 = SWIG_NewPointerObj(static_cast<void*>(& val1), paramType, SWIG_POINTER_NEW);
        PyObject * pyVal2 = SWIG_NewPointerObj(static_cast<void*>(& val2), paramType, SWIG_POINTER_NEW);
        PyObject * args = PyTuple_New(2);
        PyTuple_SetItem(args, 0, pyVal1);
        PyTuple_SetItem(args, 1, pyVal2);
        PyObject * resultObject = PyObject_CallObject(pythonOperations[functName], args);
        void * resultPointer = 0;
        swig_type_info * returnType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t");
        SWIG_ConvertPtr(resultObject, &resultPointer, returnType, 0);
        shared_ptr<XdmfArray> * returnArrayPointer = reinterpret_cast<shared_ptr<XdmfArray> *>(resultPointer);
        shared_ptr<XdmfArray> returnArray = returnArrayPointer[0];
        return returnArray;
      }
370
      else {
371
372
373
374
375
376
377
378
379
380
381
382
         /*this does not actually cause an infinte recursive loop, it sends the values to the version of the function defined in XdmfArray.cpp*/
         return XdmfArray::evaluateOperation(val1, val2, functName);
      }
    }

    static shared_ptr<XdmfArray> evaluateExpression(std::string expression, std::map<std::string, shared_ptr<XdmfArray> > variables)
    {
      std::stack<shared_ptr<XdmfArray> > valueStack;
      std::stack<char> operationStack;

      /*string is parsed left to right
        elements of the same priority are evaluated right to left*/
383
      for (unsigned int i = 0; i < expression.size(); i++) {
384
        if (XdmfArray::getValidDigitChars().find(expression[i]) != std::string::npos) {/*found to be a digit*/
385
386
          /*progress until a non-digit is found*/
          int valueStart = i;
387
          while (XdmfArray::getValidDigitChars().find(expression[i + 1]) != std::string::npos) {
388
389
390
391
392
393
394
            i++;
          }
          /*push back to the value stack*/
          shared_ptr<XdmfArray> valueArray = XdmfArray::New();
          valueArray->insert(0, atof(expression.substr(valueStart, i + 1 - valueStart).c_str()));/*use this to convert to double*/
          valueStack.push(valueArray);
        }
395
        else if (XdmfArray::getValidVariableChars().find(expression[i]) != std::string::npos) {/*found to be a variable*/
396
397
          int valueStart = i;
          /*progress until a nonvariable value is found*/
398
          while (XdmfArray::getValidVariableChars().find(expression[i + 1]) != std::string::npos) {
399
400
401
            i++;
          }
          /*convert to equivalent*/
402
          if (variables.find(expression.substr(valueStart, i + 1 - valueStart)) == variables.end()) {
403
404
            std::vector<std::string> functionList = XdmfArray::getSupportedFunctions();
            bool functionExists = false;
405
            for (unsigned int j = 0; j < functionList.size() && !functionExists; j++) {
406
              if (functionList[j] == expression.substr(valueStart, i + 1 - valueStart)) {
407
408
409
                functionExists = true;
              }
            }
410
            if (functionExists) {
411
412
413
              XdmfError::message(XdmfError::FATAL,
                                 "Error: Invalid Variable in evaluateExpression " + expression.substr(valueStart, i + 1 - valueStart));
            }
414
            else {
415
416
              std::string currentFunction = expression.substr(valueStart, i + 1 - valueStart);
              /*check if next character is an open parenthesis*/
417
              if (expression[i+1] != '(') {
418
419
420
421
422
423
424
                XdmfError::message(XdmfError::FATAL,
                                   "Error: No values supplied to function " + expression.substr(valueStart, i + 1 - valueStart));
              }
              /*if it is grab the string between paranthesis*/
              i = i + 2;
              valueStart = i;
              int numOpenParenthesis = 0;
425
426
              while ((expression[i] != ')' || numOpenParenthesis) && i < expression.size()) {
                if (expression[i] == '(') {
427
428
                  numOpenParenthesis++;
                }
429
                else if (expression[i] == ')') {
430
431
432
433
434
435
436
437
                  numOpenParenthesis--;
                }
                i++;
              }
              std::string functionParameters = expression.substr(valueStart, i - valueStart);
              std::vector<shared_ptr<XdmfArray> > parameterVector;
              /*split that string at commas*/
              size_t parameterSplit = 0;
438
              while (parameterSplit != std::string::npos) {
439
440
441
                parameterSplit = 0;
                parameterSplit = functionParameters.find_first_of(",", parameterSplit);
                /*feed the substrings to the parse function*/
442
                if (parameterSplit == std::string::npos) {
443
444
                  parameterVector.push_back(evaluateExpression(functionParameters, variables));
                }
445
                else {
446
447
448
449
450
451
452
                  parameterVector.push_back(evaluateExpression(functionParameters.substr(0, parameterSplit), variables));
                  functionParameters = functionParameters.substr(parameterSplit+1);
                }
              }
              valueStack.push(evaluateFunction(parameterVector, currentFunction));
            }
          }
453
          else {
454
455
456
457
            /*push equivalent to value stack*/
            valueStack.push(variables.find(expression.substr(valueStart, i + 1 - valueStart))->second);
          }
        }
458
        else if (XdmfArray::getSupportedOperations().find(expression[i]) != std::string::npos) {/*found to be an operation*/
459
          /*pop operations off the stack until one of a lower or equal importance is found*/
460
461
          if (operationStack.size() > 0) {
            if (expression[i] == ')') {
462
              /*to close a parenthesis pop off all operations until another parentheis is found*/
463
464
              while (operationStack.size() > 0 && operationStack.top() != '(') {
                if (valueStack.size() < 2) {/*must be at least two values for this loop to work properly*/
465
466
467
                  XdmfError::message(XdmfError::FATAL,
                                     "Error: Not Enough Values in evaluateExpression");
                }
468
                else {
469
470
471
472
473
474
475
476
477
478
                  shared_ptr<XdmfArray> val2 = valueStack.top();
                  valueStack.pop();
                  shared_ptr<XdmfArray> val1 = valueStack.top();
                  valueStack.pop();
                  valueStack.push(evaluateOperation(val1, val2, operationStack.top()));
                  operationStack.pop();
                }
              }
              operationStack.pop();
            }
479
            else if (expression[i] == '(') {
480
481
482
483
              /*just add it if it's a start parenthesis
                nothing happens here in that case
                addition happens after the if statement block*/
            }
484
            else {
485
486
487
              int operationLocation = XdmfArray::getOperationPriority(expression[i]);
              int topOperationLocation = XdmfArray::getOperationPriority(operationStack.top());
              /*see order of operations to determine importance*/
488
489
              while (operationStack.size() > 0 && operationLocation < topOperationLocation) {
                if (valueStack.size() < 2) {/*must be at least two values for this loop to work properly*/
490
491
492
                  XdmfError::message(XdmfError::FATAL,
                                     "Error: Not Enough Values in evaluateExpression");
                }
493
                else {
494
495
496
497
498
499
                  shared_ptr<XdmfArray> val2 = valueStack.top();
                  valueStack.pop();
                  shared_ptr<XdmfArray> val1 = valueStack.top();
                  valueStack.pop();
                  valueStack.push(evaluateOperation(val1, val2, operationStack.top()));
                  operationStack.pop();
500
                  if (operationStack.size() == 0) {
501
502
503
504
505
506
507
                    break;
                  }
                  topOperationLocation = XdmfArray::getOperationPriority(operationStack.top());
                }
              }
            }
          }
508
          if (expression[i] != ')') {
509
510
511
512
513
514
515
516
517
            /*add the operation to the operation stack*/
            operationStack.push(expression[i]);
          }
        }
        /*if not a value or operation the character is ignored*/
      }


      /*empty what's left in the stacks before finishing*/
518
519
      while (valueStack.size() > 1 && operationStack.size() > 0) {
        if (valueStack.size() < 2) {/*must be at least two values for this loop to work properly*/
520
521
522
          XdmfError::message(XdmfError::FATAL,
                             "Error: Not Enough Values in evaluateExpression");
        }
523
524
        else {
          if(operationStack.top() == '(') {
525
526
527
            XdmfError::message(XdmfError::WARNING,
                               "Warning: Unpaired Parenthesis");
          }
528
          else {
529
530
531
532
            shared_ptr<XdmfArray> val2 = valueStack.top();
            valueStack.pop();
            shared_ptr<XdmfArray> val1 = valueStack.top();
            valueStack.pop();
533
            if (operationStack.size() == 0) {
534
535
536
              XdmfError::message(XdmfError::FATAL,
                                 "Error: Not Enough Operators in evaluateExpression");
            }
537
            else {
538
539
540
541
542
543
544
545
              valueStack.push(evaluateOperation(val1, val2, operationStack.top()));
              operationStack.pop();
            }
          }
        }
      }

      /*throw error if there's extra operations*/
546
      if (operationStack.size() > 0) {
547
548
549
550
        XdmfError::message(XdmfError::WARNING,
                           "Warning: Left Over Operators in evaluateExpression");
      }

551
      if (valueStack.size() > 1) {
552
553
554
555
556
557
558
559
560
561
562
563
564
565
        XdmfError::message(XdmfError::WARNING,
                           "Warning: Left Over Values in evaluateExpression");
      }

      return valueStack.top();
    }

%}

    /*trying to transfer python funcitons*/
    /*note, accessing private members is impossible from swig.*/
    static int addFunction(std::string newName, PyObject * functionref)
    {
      /*check if the object is callable*/
566
      if (PyCallable_Check(functionref) == 1) {
567
568
569
        pythonFunctions[newName] = functionref;
        return pythonFunctions.size();
      }
570
      else {
571
572
573
574
575
576
577
578
579
580
        XdmfError::message(XdmfError::FATAL,
          "Error: Function is not callable");
        return -1;
      }
    }

    /*to generate new static functions mark them as static here.*/
    static std::vector<std::string> getSupportedFunctions()
    {
      std::vector<std::string> returnVector = XdmfArray::getSupportedFunctions();
581
      for (std::map<std::string, PyObject *>::iterator functionWalker = pythonFunctions.begin(); functionWalker != pythonFunctions.end(); functionWalker++) {
582
583
584
585
586
587
588
        returnVector.push_back(functionWalker->first);
      }
      return returnVector;
    }

    static shared_ptr<XdmfArray> evaluateFunction(std::vector<shared_ptr<XdmfArray> > functValues, std::string functName)
    {
589
      if (pythonFunctions.find(functName)!= pythonFunctions.end()) {
590
591
592
593
594
595
596
597
598
599
600
601
        swig_type_info * paramType = SWIG_TypeQuery("_p_std__vectorT_boost__shared_ptrT_XdmfArray_t_std__allocatorT_boost__shared_ptrT_XdmfArray_t_t_t");
        PyObject * pyVector = SWIG_NewPointerObj(static_cast<void*>(& functValues), paramType, SWIG_POINTER_NEW);
        PyObject * args = PyTuple_New(1);
        PyTuple_SetItem(args, 0, pyVector);/*In this case you could also cast a pointer to the vector into the PyObject * type, but that doesn't work for all types*/
        PyObject * resultObject = PyObject_CallObject(pythonFunctions[functName], args);
        void * resultPointer = 0;
        swig_type_info * returnType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t");
        SWIG_ConvertPtr(resultObject, &resultPointer, returnType, 0);
        shared_ptr<XdmfArray> * returnArrayPointer = reinterpret_cast<shared_ptr<XdmfArray> *>(resultPointer);
        shared_ptr<XdmfArray> returnArray = returnArrayPointer[0];
        return returnArray;
      }
602
      else {
603
604
605
606
607
608
609
         /*this does not actually cause an infinte recursive loop, it sends the values to the version of the function defined in XdmfArray.cpp*/
         return XdmfArray::evaluateFunction(functValues, functName);
      }
    }

    static int addOperation(char newName, PyObject * calcref, int priority)
    {
610
      if (newName == '(' || newName == ')') {
611
612
613
614
        XdmfError::message(XdmfError::FATAL,
                           "Error: Parenthesis can not be redefined");
      }
      /*check if the object is callable*/
615
616
      if (PyCallable_Check(calcref) == 1) {
        if (pythonOperations.find(newName) != pythonOperations.end() || XdmfArray::getSupportedOperations().find(newName) != std::string::npos) {
617
          XdmfError::message(XdmfError::WARNING,
618
                             "Warning: Operation Redefined");/*It's a good idea to warn users when they're doing this*/
619
620
          size_t operationLocation = pythonSupportedOperations.find(newName);
          /*if not an already defined python function*/
621
          if (pythonOperations.find(newName) == pythonOperations.end()) {
622
            pythonSupportedOperations.push_back(newName);
623
            unsigned int priorityArraySize = sizeof(pythonOperationPriority)/sizeof(int);
624
            if (pythonSupportedOperations.size()-1 > priorityArraySize) {
625
626
627
628
629
630
631
632
              int newArray [priorityArraySize*2];
              std::copy(pythonOperationPriority, pythonOperationPriority+(priorityArraySize-1), newArray);
              *pythonOperationPriority = *newArray;
            }
          }
          pythonOperationPriority[operationLocation] = priority;
          /*if defined on the c++ side same as adding a new one*/
        }
633
        else {
634
          pythonSupportedOperations += newName;
635
          if (XdmfArray::getValidVariableChars().find(newName) != std::string::npos || XdmfArray::getValidDigitChars().find(newName) != std::string::npos) {
636
637
638
            XdmfError::message(XdmfError::FATAL,
              "Error: Operation Overlaps with Variables");
          }
639
          else {
640
            pythonSupportedOperations.push_back(newName);
641
            unsigned int priorityArraySize = sizeof(pythonOperationPriority)/sizeof(int);
642
643
644
645
646
647
648
649
650
651
652
            if (pythonSupportedOperations.size()-1 > priorityArraySize)
            {
              int newArray [priorityArraySize*2];
              std::copy(pythonOperationPriority, pythonOperationPriority+(priorityArraySize-1), newArray);
              *pythonOperationPriority = *newArray;
            }
          }
        }
        pythonOperations[newName] = calcref;
        return pythonOperations.size();
      }
653
      else {
654
655
656
657
658
659
660
661
662
        XdmfError::message(XdmfError::FATAL,
          "Error: Operation is not callable");
        return -1;
      }
    }

    static std::string getSupportedOperations()
    {
      std::string returnVector = XdmfArray::getSupportedOperations();
663
      for (std::map<char, PyObject *>::iterator functionWalker = pythonOperations.begin(); functionWalker != pythonOperations.end(); functionWalker++) {
664
665
666
667
668
669
670
        returnVector += functionWalker->first;
      }
      return returnVector;
    }

    static shared_ptr<XdmfArray> evaluateOperation(shared_ptr<XdmfArray> val1, shared_ptr<XdmfArray> val2, char functName)
    {
671
      if (pythonOperations.find(functName)!= pythonOperations.end()) {
672
673
674
675
676
677
678
679
680
681
682
683
684
685
        swig_type_info * paramType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t");
        PyObject * pyVal1 = SWIG_NewPointerObj(static_cast<void*>(& val1), paramType, SWIG_POINTER_NEW);
        PyObject * pyVal2 = SWIG_NewPointerObj(static_cast<void*>(& val2), paramType, SWIG_POINTER_NEW);
        PyObject * args = PyTuple_New(2);
        PyTuple_SetItem(args, 0, pyVal1);
        PyTuple_SetItem(args, 1, pyVal2);
        PyObject * resultObject = PyObject_CallObject(pythonOperations[functName], args);
        void * resultPointer = 0;
        swig_type_info * returnType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t");
        SWIG_ConvertPtr(resultObject, &resultPointer, returnType, 0);
        shared_ptr<XdmfArray> * returnArrayPointer = reinterpret_cast<shared_ptr<XdmfArray> *>(resultPointer);
        shared_ptr<XdmfArray> returnArray = returnArrayPointer[0];
        return returnArray;
      }
686
      else {
687
688
689
690
691
692
693
694
695
696
697
698
         /*this does not actually cause an infinte recursive loop, it sends the values to the version of the function defined in XdmfArray.cpp*/
         return XdmfArray::evaluateOperation(val1, val2, functName);
      }
    }

    static shared_ptr<XdmfArray> evaluateExpression(std::string expression, std::map<std::string, shared_ptr<XdmfArray> > variables)
    {
      std::stack<shared_ptr<XdmfArray> > valueStack;
      std::stack<char> operationStack;

      /*string is parsed left to right
        elements of the same priority are evaluated right to left*/
699
      for (unsigned int i = 0; i < expression.size(); i++) {
700
        if (XdmfArray::getValidDigitChars().find(expression[i]) != std::string::npos) { /*found to be a digit*/
701
702
          /*progress until a non-digit is found*/
          int valueStart = i;
703
          while (XdmfArray::getValidDigitChars().find(expression[i + 1]) != std::string::npos) {
704
705
706
707
708
709
710
            i++;
          }
          /*push back to the value stack*/
          shared_ptr<XdmfArray> valueArray = XdmfArray::New();
          valueArray->insert(0, atof(expression.substr(valueStart, i + 1 - valueStart).c_str()));/*use this to convert to double*/
          valueStack.push(valueArray);
        }
711
        else if (XdmfArray::getValidVariableChars().find(expression[i]) != std::string::npos) {/*found to be a variable*/
712
713
          int valueStart = i;
          /*progress until a nonvariable value is found*/
714
          while (XdmfArray::getValidVariableChars().find(expression[i + 1]) != std::string::npos) {
715
716
717
            i++;
          }
          /*convert to equivalent*/
718
          if (variables.find(expression.substr(valueStart, i + 1 - valueStart)) == variables.end()) {
719
720
            std::vector<std::string> functionList = XdmfArray::getSupportedFunctions();
            bool functionExists = false;
721
            for (unsigned int j = 0; j < functionList.size() && !functionExists; j++) {
722
              if (functionList[j] == expression.substr(valueStart, i + 1 - valueStart)) {
723
724
725
                functionExists = true;
              }
            }
726
            if (functionExists) {
727
728
729
              XdmfError::message(XdmfError::FATAL,
                                 "Error: Invalid Variable in evaluateExpression " + expression.substr(valueStart, i + 1 - valueStart));
            }
730
            else {
731
732
              std::string currentFunction = expression.substr(valueStart, i + 1 - valueStart);
              /*check if next character is an open parenthesis*/
733
              if (expression[i+1] != '(') {
734
735
736
737
738
739
740
                XdmfError::message(XdmfError::FATAL,
                                   "Error: No values supplied to function " + expression.substr(valueStart, i + 1 - valueStart));
              }
              /*if it is grab the string between paranthesis*/
              i = i + 2;
              valueStart = i;
              int numOpenParenthesis = 0;
741
742
              while ((expression[i] != ')' || numOpenParenthesis) && i < expression.size()) {
                if (expression[i] == '(') {
743
744
                  numOpenParenthesis++;
                }
745
                else if (expression[i] == ')') {
746
747
748
749
750
751
752
753
                  numOpenParenthesis--;
                }
                i++;
              }
              std::string functionParameters = expression.substr(valueStart, i - valueStart);
              std::vector<shared_ptr<XdmfArray> > parameterVector;
              /*split that string at commas*/
              size_t parameterSplit = 0;
754
              while (parameterSplit != std::string::npos) {
755
756
757
                parameterSplit = 0;
                parameterSplit = functionParameters.find_first_of(",", parameterSplit);
                /*feed the substrings to the parse function*/
758
                if (parameterSplit == std::string::npos) {
759
760
                  parameterVector.push_back(evaluateExpression(functionParameters, variables));
                }
761
                else {
762
763
764
765
766
767
768
                  parameterVector.push_back(evaluateExpression(functionParameters.substr(0, parameterSplit), variables));
                  functionParameters = functionParameters.substr(parameterSplit+1);
                }
              }
              valueStack.push(evaluateFunction(parameterVector, currentFunction));
            }
          }
769
          else {
770
771
772
773
            /*push equivalent to value stack*/
            valueStack.push(variables.find(expression.substr(valueStart, i + 1 - valueStart))->second);
          }
        }
774
        else if (XdmfArray::getSupportedOperations().find(expression[i]) != std::string::npos) {/*found to be an operation*/
775
          /*pop operations off the stack until one of a lower or equal importance is found*/
776
777
          if (operationStack.size() > 0) {
            if (expression[i] == ')') {
778
              /*to close a parenthesis pop off all operations until another parentheis is found*/
779
780
              while (operationStack.size() > 0 && operationStack.top() != '(') {
                if (valueStack.size() < 2) {/*must be at least two values for this loop to work properly*/
781
782
783
                  XdmfError::message(XdmfError::FATAL,
                                     "Error: Not Enough Values in evaluateExpression");
                }
784
                else {
785
786
787
788
789
790
791
792
793
794
                  shared_ptr<XdmfArray> val2 = valueStack.top();
                  valueStack.pop();
                  shared_ptr<XdmfArray> val1 = valueStack.top();
                  valueStack.pop();
                  valueStack.push(evaluateOperation(val1, val2, operationStack.top()));
                  operationStack.pop();
                }
              }
              operationStack.pop();
            }
795
            else if (expression[i] == '(') {
796
797
798
799
              /*just add it if it's a start parenthesis
                nothing happens here in that case
                addition happens after the if statement*/
            }
800
            else {
801
802
803
              int operationLocation = XdmfArray::getOperationPriority(expression[i]);
              int topOperationLocation = XdmfArray::getOperationPriority(operationStack.top());
              /*see order of operations to determine importance*/
804
805
              while (operationStack.size() > 0 && operationLocation < topOperationLocation) {
                if (valueStack.size() < 2) {/*must be at least two values for this loop to work properly*/
806
807
808
                  XdmfError::message(XdmfError::FATAL,
                                     "Error: Not Enough Values in evaluateExpression");
                }
809
                else {
810
811
812
813
814
815
                  shared_ptr<XdmfArray> val2 = valueStack.top();
                  valueStack.pop();
                  shared_ptr<XdmfArray> val1 = valueStack.top();
                  valueStack.pop();
                  valueStack.push(evaluateOperation(val1, val2, operationStack.top()));
                  operationStack.pop();
816
                  if (operationStack.size() == 0) {
817
818
819
820
821
822
823
                    break;
                  }
                  topOperationLocation = XdmfArray::getOperationPriority(operationStack.top());
                }
              }
            }
          }
824
          if (expression[i] != ')') {
825
826
827
828
829
830
831
832
833
            /*add the operation to the operation stack*/
            operationStack.push(expression[i]);
          }
        }
        /*if not a value or operation the character is ignored*/
      }


      /*empty what's left in the stacks before finishing*/
834
835
      while (valueStack.size() > 1 && operationStack.size() > 0) {
        if (valueStack.size() < 2) {/*must be at least two values for this loop to work properly*/
836
837
838
          XdmfError::message(XdmfError::FATAL,
                             "Error: Not Enough Values in evaluateExpression");
        }
839
840
        else {
          if(operationStack.top() == '(') {
841
842
843
            XdmfError::message(XdmfError::WARNING,
                               "Warning: Unpaired Parenthesis");
          }
844
          else {
845
846
847
848
            shared_ptr<XdmfArray> val2 = valueStack.top();
            valueStack.pop();
            shared_ptr<XdmfArray> val1 = valueStack.top();
            valueStack.pop();
849
            if (operationStack.size() == 0) {
850
851
852
              XdmfError::message(XdmfError::FATAL,
                                 "Error: Not Enough Operators in evaluateExpression");
            }
853
            else {
854
855
856
857
858
859
860
861
              valueStack.push(evaluateOperation(val1, val2, operationStack.top()));
              operationStack.pop();
            }
          }
        }
      }

      /*throw error if there's extra operations*/
862
      if (operationStack.size() > 0) {
863
864
865
866
        XdmfError::message(XdmfError::WARNING,
                           "Warning: Left Over Operators in evaluateExpression");
      }

867
      if (valueStack.size() > 1) {
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
        XdmfError::message(XdmfError::WARNING,
                           "Warning: Left Over Values in evaluateExpression");
      }

      return valueStack.top();
    }



    static shared_ptr<XdmfArray> XdmfArrayPtr(PyObject * obj)
    {
      void * resultPointer = 0;
      swig_type_info * returnType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t");
      SWIG_ConvertPtr(obj, &resultPointer, returnType, 0);
      shared_ptr<XdmfArray> * returnArrayPointer = reinterpret_cast<shared_ptr<XdmfArray> *>(resultPointer);
      shared_ptr<XdmfArray> returnArray = returnArrayPointer[0];
      return returnArray;
    }



889
890
};

891
892
893
%extend XdmfArrayType {
    bool __eq__(const XdmfArrayType * arrayType) {
   	return $self == arrayType;
894
    }
895
896
897
898
};

#endif /* SWIGPYTHON */

899
%include boost_shared_ptr.i
900
901
902
903
904
905
906

%inline
%{
    #include <boost/shared_ptr.hpp>
    using namespace boost;
%}

907
908
%include std_string.i
%include std_vector.i
909
%include std_map.i
910

911
%shared_ptr(Loki::BaseVisitor)
912
913
914
915
%shared_ptr(Loki::BaseVisitable<void>)
%shared_ptr(Loki::Visitor<XdmfItem>)
%shared_ptr(Loki::Visitor<XdmfArray>)

916
%include loki/Visitor.h
917

918
919
920
921
922
923
924
// Shared Pointer Templates
%shared_ptr(XdmfArray)
%shared_ptr(XdmfArrayType)
%shared_ptr(XdmfCoreItemFactory)
%shared_ptr(XdmfCoreReader)
%shared_ptr(XdmfHDF5Controller)
%shared_ptr(XdmfHDF5Writer)
925
#ifdef XDMF_BUILD_DSM
926
927
    %shared_ptr(XdmfHDF5ControllerDSM)
    %shared_ptr(XdmfHDF5WriterDSM)
928
#endif
929
930
%shared_ptr(XdmfHeavyDataController)
%shared_ptr(XdmfHeavyDataWriter)
931
932
933
%shared_ptr(XdmfInformation)
%shared_ptr(XdmfItem)
%shared_ptr(XdmfItemProperty)
934
%shared_ptr(XdmfSparseMatrix)
935
936
%shared_ptr(XdmfVisitor)
%shared_ptr(XdmfWriter)
937

938
939
%shared_ptr(std::vector<int>)

940
// Abstract Base Classes
941
%template(BaseVisitable) Loki::BaseVisitable<void>;
942
943
%template() Loki::Visitor<XdmfArray>;
%template() Loki::Visitor<XdmfItem>;
944

945
%include XdmfCore.hpp
946
%include XdmfError.hpp
947
948
%include XdmfItem.hpp
%include XdmfItemProperty.hpp
949
%include XdmfSparseMatrix.hpp
950
%include XdmfVisitor.hpp
951
952
953
%include XdmfHeavyDataController.hpp
%include XdmfHeavyDataWriter.hpp

954
955
956
957
958
959
960
%include XdmfCoreItemFactory.hpp
%include XdmfCoreReader.hpp
%include XdmfInformation.hpp
%include XdmfHDF5Controller.hpp
%include XdmfHDF5Writer.hpp
%include XdmfWriter.hpp

961
962
963
%include CMake/VersionSuite/ProjectVersion.hpp
%include XdmfVersion.hpp

964
#ifdef XDMF_BUILD_DSM
965
966
    %include XdmfHDF5ControllerDSM.hpp
    %include XdmfHDF5WriterDSM.hpp
967
968
#endif

969
970
971
%include XdmfArray.hpp
%include XdmfArrayType.hpp

972
973
974
975
976
977
978
979
#ifdef SWIGPYTHON

%pythoncode {
    XdmfVersion = _XdmfCore.cvar.XdmfVersion
};

#endif /* SWIGPYTHON */

980
981
982
983
984
985
986
987
988
%template(getValueAsInt8) XdmfArray::getValue<char>;
%template(getValueAsInt16) XdmfArray::getValue<short>;
%template(getValueAsInt32) XdmfArray::getValue<int>;
%template(getValueAsInt64) XdmfArray::getValue<long>;
%template(getValueAsFloat32) XdmfArray::getValue<float>;
%template(getValueAsFloat64) XdmfArray::getValue<double>;
%template(getValueAsUInt8) XdmfArray::getValue<unsigned char>;
%template(getValueAsUInt16) XdmfArray::getValue<unsigned short>;
%template(getValueAsUInt32) XdmfArray::getValue<unsigned int>;
Kenneth Leiter's avatar
Kenneth Leiter committed
989
%template(getValueAsString) XdmfArray::getValue<std::string>;
990
991
992
993
994
995
996
997
998
999

%template(initializeAsInt8) XdmfArray::initialize<char>;
%template(initializeAsInt16) XdmfArray::initialize<short>;
%template(initializeAsInt32) XdmfArray::initialize<int>;
%template(initializeAsInt64) XdmfArray::initialize<long>;
%template(initializeAsFloat32) XdmfArray::initialize<float>;
%template(initializeAsFloat64) XdmfArray::initialize<double>;
%template(initializeAsUInt8) XdmfArray::initialize<unsigned char>;
%template(initializeAsUInt16) XdmfArray::initialize<unsigned short>;
%template(initializeAsUInt32) XdmfArray::initialize<unsigned int>;
Kenneth Leiter's avatar
Kenneth Leiter committed
1000
%template(initializeAsString) XdmfArray::initialize<std::string>;
1001

1002
1003
1004
1005
1006
1007
1008
1009
1010
%template(insertValueAsInt8) XdmfArray::insert<char>;
%template(insertValueAsInt16) XdmfArray::insert<short>;
%template(insertValueAsInt32) XdmfArray::insert<int>;
%template(insertValueAsInt64) XdmfArray::insert<long>;
%template(insertValueAsFloat32) XdmfArray::insert<float>;
%template(insertValueAsFloat64) XdmfArray::insert<double>;
%template(insertValueAsUInt8) XdmfArray::insert<unsigned char>;
%template(insertValueAsUInt16) XdmfArray::insert<unsigned short>;
%template(insertValueAsUInt32) XdmfArray::insert<unsigned int>;
Kenneth Leiter's avatar
Kenneth Leiter committed
1011
%template(insertValueAsString) XdmfArray::insert<std::string>;
1012

1013
1014
1015
1016
1017
1018
1019
1020
1021
%template(pushBackAsInt8) XdmfArray::pushBack<char>;
%template(pushBackAsInt16) XdmfArray::pushBack<short>;
%template(pushBackAsInt32) XdmfArray::pushBack<int>;
%template(pushBackAsInt64) XdmfArray::pushBack<long>;
%template(pushBackAsFloat32) XdmfArray::pushBack<float>;
%template(pushBackAsFloat64) XdmfArray::pushBack<double>;
%template(pushBackAsUInt8) XdmfArray::pushBack<unsigned char>;
%template(pushBackAsUInt16) XdmfArray::pushBack<unsigned short>;
%template(pushBackAsUInt32) XdmfArray::pushBack<unsigned int>;
Kenneth Leiter's avatar
Kenneth Leiter committed
1022
%template(pushBackAsString) XdmfArray::pushBack<std::string>;
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032

%template(resizeAsInt8) XdmfArray::resize<char>;
%template(resizeAsInt16) XdmfArray::resize<short>;
%template(resizeAsInt32) XdmfArray::resize<int>;
%template(resizeAsInt64) XdmfArray::resize<long>;
%template(resizeAsFloat32) XdmfArray::resize<float>;
%template(resizeAsFloat64) XdmfArray::resize<double>;
%template(resizeAsUInt8) XdmfArray::resize<unsigned char>;
%template(resizeAsUInt16) XdmfArray::resize<unsigned short>;
%template(resizeAsUInt32) XdmfArray::resize<unsigned int>;
Kenneth Leiter's avatar
Kenneth Leiter committed
1033
%template(resizeAsString) XdmfArray::resize<std::string>;
1034

1035
1036
1037
1038
1039
1040
1041
1042
1043
%template(UInt8Vector) std::vector<unsigned char>;
%template(UInt16Vector) std::vector<unsigned short>;
%template(UInt32Vector) std::vector<unsigned int>;
%template(Int8Vector) std::vector<char>;
%template(Int16Vector) std::vector<short>;
%template(Int32Vector) std::vector<int>;
%template(Int64Vector) std::vector<long>;
%template(Float32Vector) std::vector<float>;
%template(Float64Vector) std::vector<double>;
1044
%template(StringVector) std::vector<std::string>;
1045
%template(ItemVector) std::vector<boost::shared_ptr<XdmfItem> >;
1046
%template(ArrayMap) std::map<std::string, boost::shared_ptr<XdmfArray> >;
1047
%template(StringMap) std::map<std::string, std::string>;