3
3
cimport numpy as np
4
4
import numpy as np
5
5
6
+ # C++ modules
7
+ from libcpp cimport bool
8
+
6
9
# -----------------------------------------------------------------------------
7
10
8
11
cdef extern from " c_clib.h" :
@@ -198,17 +201,15 @@ def init_vector(m0, mesh, dim=3, norm=False, *args):
198
201
199
202
def init_vector_func_fast (m0 , mesh , double[:] field , norm = False , *args ):
200
203
"""
201
- An unsafe method of setting the field. Depends on
202
- the setter code being memory safe.
203
-
204
- m0 must be a Python function that takes the mesh
205
- and field as arguments. Within that, the user
206
- must handle evaluating the function at different
207
- coordinate points. It needs to be able to handle
208
- the spatial dependence itself, and write the
209
- field valuse into the field array. This can
210
- be written with Cython which will give much
211
- better performance. For example:
204
+
205
+ An unsafe method of setting the field. Depends on the setter code being
206
+ memory safe.
207
+
208
+ m0 must be a Python function that takes the mesh and field as arguments.
209
+ Within that, the user must handle evaluating the function at different
210
+ coordinate points. It needs to be able to handle the spatial dependence
211
+ itself, and write the field valuse into the field array. This can be
212
+ written with Cython which will give much better performance. For example:
212
213
213
214
from libc.math cimport sin
214
215
@@ -224,3 +225,83 @@ def init_vector_func_fast(m0, mesh, double[:] field, norm=False, *args):
224
225
if norm:
225
226
normalise(field)
226
227
return field
228
+
229
+ # -----------------------------------------------------------------------------
230
+ # -----------------------------------------------------------------------------
231
+ # CLASSES
232
+
233
+ # -----------------------------------------------------------------------------
234
+ # C++ definitions
235
+
236
+ # See:
237
+ # https://cython.readthedocs.io/en/latest/src/userguide/wrapping_CPlusPlus.html
238
+ #
239
+ # - Methods that are redefined in inherited classes are only specified in the
240
+ # base class
241
+ # - These can be declared in a .pxd file:
242
+
243
+ cdef extern from " c_energy.h" :
244
+
245
+ cdef cppclass Energy:
246
+ # except +: Without this declaration, C++ exceptions originating from
247
+ # the constructor will not be handled by Cython.
248
+ Energy() except +
249
+
250
+ void compute_field(double t)
251
+ double compute_energy()
252
+ void setup(int nx, int ny, int nz, double dx, double dy, double dz,
253
+ double unit_length, double * spin,
254
+ double * Ms, double * Ms_inv)
255
+
256
+ bool set_up
257
+ int nx, ny, nz, n
258
+ double dx, dy, dz
259
+ double unit_length
260
+ double * spin
261
+ double * Ms
262
+ double * Ms_inv
263
+ double * field
264
+ double * energy
265
+ double * coordinates
266
+ int * ngbs
267
+
268
+ cdef cppclass ExchangeEnergy(Energy):
269
+ ExchangeEnergy() except +
270
+
271
+ void init(double * A)
272
+
273
+ double * A
274
+
275
+ # -----------------------------------------------------------------------------
276
+ # Python definitions
277
+
278
+ # Cython initializes C++ class attributes of a cdef class using the nullary
279
+ # constructor. If the class you’re wrapping does not have a nullary
280
+ # constructor, you must store a pointer to the wrapped class and manually
281
+ # allocate and deallocate it. A convenient and safe place to do so is in the
282
+ # __cinit__ and __dealloc__ methods which are guaranteed to be called exactly
283
+ # once upon creation and deletion of the Python instance.
284
+
285
+ cdef class PyExchangeEnergy:
286
+ cdef ExchangeEnergy thisptr
287
+ # Try cinit:
288
+ def __init__ (self , double [:] A ):
289
+ self .thisptr.init(& A[0 ])
290
+ # cdef ExchangeEnergy *thisptr
291
+ # We could use another constructor if we use this method:
292
+ # def __cinit__(self):
293
+ # if type(self) is PyEnergy:
294
+ # self.thisptr = new Energy()
295
+ # def __dealloc__(self):
296
+ # if type(self) is PyEnergy:
297
+ # del self.thisptr
298
+ # Necessary?
299
+ def compute_field (self , t ):
300
+ self .thisptr.compute_field(t)
301
+ def compute_energy (self , time ):
302
+ return self .thisptr.compute_energy()
303
+ def setup (self , nx , ny , nz , dx , dy , dz , unit_length ,
304
+ double [:] spin , double [:] Ms , double [:] Ms_inv ):
305
+ return self .thisptr.setup(nx, ny, nz, dx, dy, dz, unit_length,
306
+ & spin[0 ], & Ms[0 ], & Ms_inv[0 ])
307
+
0 commit comments