Nektar++
VarCoeffEntry.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: VarCoeffEntry.cpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Scientific Computing and Imaging Institute,
10 // University of Utah (USA) and Department of Aeronautics, Imperial
11 // College London (UK).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: Python wrapper for VarCoeffEntry.
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
38 
39 #include <type_traits>
40 
41 using namespace Nektar;
42 using namespace Nektar::LibUtilities;
43 using namespace Nektar::StdRegions;
44 
45 #if PY_MAJOR_VERSION == 2
46 void CapsuleDestructor(void *ptr)
47 {
48  VarCoeffEntry *tmp = (VarCoeffEntry *)ptr;
49  delete tmp;
50 }
51 #else
52 void CapsuleDestructor(PyObject *ptr)
53 {
54  VarCoeffEntry *tmp = (VarCoeffEntry *)PyCapsule_GetPointer(ptr, 0);
55  delete tmp;
56 }
57 #endif
58 
60 {
61  static PyObject *convert(VarCoeffEntry const &entry)
62  {
63  // Create a Python capsule to hold a pointer that contains a lightweight
64  // copy of arr. That way we guarantee Python will still have access to
65  // the memory allocated inside arr even if arr is deallocated in C++.
66 #if PY_MAJOR_VERSION == 2
67  py::object capsule(py::handle<>(PyCObject_FromVoidPtr(
68  new VarCoeffEntry(entry), CapsuleDestructor)));
69 #else
70  py::object capsule(py::handle<>(
71  PyCapsule_New(new VarCoeffEntry(entry), 0,
72  (PyCapsule_Destructor)&CapsuleDestructor)));
73 #endif
74  PyObject *tmp =
75  py::incref(np::from_data(entry.GetValue().data(),
76  np::dtype::get_builtin<NekDouble>(),
77  py::make_tuple(entry.GetValue().size()),
78  py::make_tuple(sizeof(NekDouble)), capsule)
79  .ptr());
80 
81  return tmp;
82  }
83 };
84 
86 {
88  {
89  py::converter::registry::push_back(&convertible, &construct,
90  py::type_id<VarCoeffEntry>());
91  }
92  static void *convertible(PyObject *objPtr)
93  {
94  try
95  {
96  py::object obj((py::handle<>(py::borrowed(objPtr))));
97  np::ndarray array = py::extract<np::ndarray>(obj);
98 
99  // Check data types match
100  np::dtype dtype = np::dtype::get_builtin<
101  typename boost::remove_const<NekDouble>::type>();
102  if (dtype != array.get_dtype())
103  {
104  return 0;
105  }
106 
107  // Check shape is 1D
108  if (array.get_nd() != 1)
109  {
110  return 0;
111  }
112  }
113  catch (boost::python::error_already_set &)
114  {
115  py::handle_exception();
116  PyErr_Clear();
117  return 0;
118  }
119 
120  return objPtr;
121  }
122 
123  static void decrement(void *objPtr)
124  {
125  if (!Py_IsInitialized())
126  {
127  // In deinitialisation phase, reference counters are not terribly
128  // robust; decremementing counters here can lead to segfaults during
129  // program exit in some cases.
130  return;
131  }
132 
133  // Otherwise decrement reference counter.
134  py::decref((PyObject *)objPtr);
135  }
136 
137  static void construct(PyObject *objPtr,
138  py::converter::rvalue_from_python_stage1_data *data)
139  {
140  // This has to be a _borrowed_ reference, otherwise at the end of this
141  // scope it seems memory gets deallocated
142  py::object obj((py::handle<>(py::borrowed(objPtr))));
143  Array<OneD, NekDouble> array = py::extract<Array<OneD, NekDouble>>(obj);
144 
145  void *storage =
146  ((py::converter::rvalue_from_python_storage<VarCoeffEntry> *)data)
147  ->storage.bytes;
148  data->convertible = storage;
149 
150  new (storage) VarCoeffEntry(array);
151 
152  py::incref(objPtr);
153  }
154 };
155 
157 {
158  py::to_python_converter<VarCoeffEntry, VarCoeffEntryToPython>();
160 }
void CapsuleDestructor(PyObject *ptr)
void export_VarCoeffEntry()
The namespace associated with the the StdRegions library (StdRegions introduction)
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble
Representation of a variable coefficient.
Definition: StdRegions.hpp:262
const Array< OneD, const NekDouble > & GetValue() const
Returns a const reference to the coefficients.
Definition: StdRegions.hpp:308
PythonToVarCoeffEntry()
static void construct(PyObject *objPtr, py::converter::rvalue_from_python_stage1_data *data)
static void * convertible(PyObject *objPtr)
static void decrement(void *objPtr)
static PyObject * convert(VarCoeffEntry const &entry)