我正在尝试为复杂版本的MUMPS解算器(zmumps)编写一个cython接口。我遇到了一些问题,因为我以前没有C或cython的经验。按照pymumps package的例子,我能够获得真正的代码版本(dmumps)。
我相信我的问题是指向ZMUMPS_COMPLEX结构的指针。对于
到目前为止,我有以下内容(从pymumps大量提升):
zmumps_c.pxd:
from libc.string cimport strncpy
cdef extern from "mumps_c_types.h":
ctypedef struct ZMUMPS_COMPLEX "ZMUMPS_COMPLEX":
double r
double i
cdef extern from "zmumps_c.h":
ctypedef int MUMPS_INT
ctypedef struct c_ZMUMPS_STRUC_C "ZMUMPS_STRUC_C":
MUMPS_INT sym, par, job
MUMPS_INT comm_fortran # Fortran communicator
MUMPS_INT n
# Assembled entry
MUMPS_INT nz
MUMPS_INT *irn
MUMPS_INT *jcn
ZMUMPS_COMPLEX *a
# RHS and statistics
ZMUMPS_COMPLEX *rhs
MUMPS_INT infog[40]
void c_zmumps_c "zmumps_c" (c_ZMUMPS_STRUC_C *)
zmumps_c.pyx
cdef class ZMUMPS_STRUC_C:
cdef c_ZMUMPS_STRUC_C ob
property sym:
def __get__(self): return self.ob.sym
def __set__(self, value): self.ob.sym = value
property par:
def __get__(self): return self.ob.par
def __set__(self, value): self.ob.par = value
property job:
def __get__(self): return self.ob.job
def __set__(self, value): self.ob.job = value
property comm_fortran:
def __get__(self): return self.ob.comm_fortran
def __set__(self, value): self.ob.comm_fortran = value
property n:
def __get__(self): return self.ob.n
def __set__(self, value): self.ob.n = value
property nz:
def __get__(self): return self.ob.nz
def __set__(self, value): self.ob.nz = value
property irn:
def __get__(self): return <long> self.ob.irn
def __set__(self, long value): self.ob.irn = <MUMPS_INT*> value
property jcn:
def __get__(self): return <long> self.ob.jcn
def __set__(self, long value): self.ob.jcn = <MUMPS_INT*> value
property a:
def __get__(self): return <long> self.ob.a
def __set__(self, long value): self.ob.a = <ZMUMPS_COMPLEX*> value
property rhs:
def __get__(self): return <long> self.ob.rhs
def __set__(self, long value): self.ob.rhs = <ZMUMPS_COMPLEX*> value
property infog:
def __get__(self):
cdef MUMPS_INT[:] view = self.ob.infog
return view
def zmumps_c(ZMUMPS_STRUC_C s not None):
c_zmumps_c(&s.ob)
在我的python代码中,我可以使用
设置irn和jcnimport zmumps_c
import numpy as np
MUMPS_STRUC_C = staticmethod(zmumps_c.ZMUMPS_STRUC_C)
id = MUMPS_STRUC_C()
x = np.r_[1:10]
id.irn = x.__array_interface__['data'][0]
但是,我不知道如何设置a或rhs的值。任何帮助将不胜感激。
答案 0 :(得分:1)
这可能会有所帮助:
以下示例可让您了解Python内置“复杂”对象的C级成员:
cdef extern from "complexobject.h":
struct Py_complex:
double real
double imag
ctypedef class __builtin__.complex [object PyComplexObject]:
cdef Py_complex cval
# A function which uses the above type
def spam(complex c):
print "Real:", c.cval.real
print "Imag:", c.cval.imag
从here抓住。
由于ZMUMPS_COMPLEX
和内置Py_complex
结构具有完全相同的结构,您应该能够通过在这两种类型之间创建桥梁来实现这一目的(使用typedef和/或强制转换或函数)将Py_complex变成ZMUMPS_COMPLEX)...
我很乐意帮忙,但我目前没有安装过腮腺炎...
答案 1 :(得分:1)
实现这一目标的方法不止一种 - 这是一种方法。
下面的代码定义了ZMUMPS_COMPLEX
的包装器。然后,它为ZMUMPS_STRUC_C
定义了一个包装器,__get__
属性的__set__
和rhs
方法允许它接受ZMUMPS_COMPLEX
包装器。
<强> zmumps_c.pyx 强>
cdef class ZMUMPS_COMPLEX:
'''A wrapper for the ZMUMPS_COMPLEX struct'''
cdef c_ZMUMPS_COMPLEX c_zm
def __init__(self, double real, double imag=0):
self.c_zm.r = real
self.c_zm.i = imag
property r:
def __get__(self):
return self.c_zm.r
def __set__(self, value):
self.c_zm.r = value
property i:
def __get__(self):
return self.c_zm.i
def __set__(self, value):
self.c_zm.i = value
def __repr__(self):
return '({real}{imag:+}j)'.format(real=self.c_zm.r, imag=self.c_zm.i)
cdef class ZMUMPS_STRUC_C:
'''A wrapper for the ZMUMPS_STRUC_C struct'''
cdef c_ZMUMPS_STRUC_C ob
cdef object _rhs
property rhs:
def __get__(self):
return self._rhs
def __set__(self, ZMUMPS_COMPLEX c):
self._rhs = c
self.ob.rhs = &c.c_zm
def test(self):
return (self.ob.rhs[0].r, self.ob.rhs[0].i,)
def main():
z = ZMUMPS_STRUC_C()
c = ZMUMPS_COMPLEX(-3.5, 2.0)
z.rhs = c
print z.rhs
print z.test()
c.r = 42.0
print z.rhs
z.rhs.i = -5.0
print z.rhs
main()
函数演示了两个对象的行为。输出应如下所示:
(-3.5+2.0j)
(-3.5, 2.0)
(42.0+2.0j)
(42.0-5.0j)
我没有安装库,所以我使用下面的虚拟定义测试了这个:
<强> zmumps_c.pxd 强>
cdef struct c_ZMUMPS_COMPLEX "ZMUMPS_COMPLEX":
double r
double i
cdef struct c_ZMUMPS_STRUC_C "ZMUMPS_STRUC_C":
c_ZMUMPS_COMPLEX *rhs
<强> setup.py 强>
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("example.pyx")
)