3
#include "SuperLU/SRC/zsp_defs.h"
4
#define NO_IMPORT_ARRAY
5
#include "_superluobject.h"
7
extern jmp_buf _superlu_py_jmpbuf;
9
/***********************************************************************
10
* SciPyLUObject methods
13
static char solve_doc[] = "x = self.solve(b, trans)\n\
15
solves linear system of equations with one or sereral right hand sides.\n\
20
b array, right hand side(s) of equation\n\
21
x array, solution vector(s)\n\
22
trans 'N': solve A * x == b\n\
23
'T': solve A^T * x == b\n\
24
'H': solve A^H * x == b (not yet implemented)\n\
25
(optional, default value 'N')\n\
29
SciPyLU_solve(SciPyLUObject *self, PyObject *args, PyObject *kwds) {
30
PyArrayObject *b, *x=NULL;
37
static char *kwlist[] = {"rhs","trans",NULL};
39
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|c", kwlist,
44
/* solve transposed system: matrix was passed row-wise instead of column-wise */
45
if (itrans == 'n' || itrans == 'N')
47
else if (itrans == 't' || itrans == 'T')
49
else if (itrans == 'h' || itrans == 'H')
52
PyErr_SetString(PyExc_ValueError, "trans must be N, T, or H");
56
if ((x = (PyArrayObject *) \
57
PyArray_CopyFromObject((PyObject *)b,self->type,1,2))==NULL) return NULL;
59
if (b->dimensions[0] != self->n) goto fail;
62
if (setjmp(_superlu_py_jmpbuf)) goto fail;
64
if (DenseSuper_from_Numeric(&B, (PyObject *)x)) goto fail;
68
/* Solve the system, overwriting vector x. */
71
sgstrs(trans, &self->L, &self->U, self->perm_c, self->perm_r, &B, &stat, &info);
74
dgstrs(trans, &self->L, &self->U, self->perm_c, self->perm_r, &B, &stat, &info);
77
cgstrs(trans, &self->L, &self->U, self->perm_c, self->perm_r, &B, &stat, &info);
80
zgstrs(trans, &self->L, &self->U, self->perm_c, self->perm_r, &B, &stat, &info);
83
PyErr_SetString(PyExc_TypeError, "Invalid type for array.");
88
PyErr_SetString(PyExc_SystemError, "gstrs was called with invalid arguments");
93
Destroy_SuperMatrix_Store(&B);
98
Destroy_SuperMatrix_Store(&B);
104
/** table of object methods
106
PyMethodDef SciPyLU_methods[] = {
107
{"solve", (PyCFunction)SciPyLU_solve, METH_VARARGS|METH_KEYWORDS, solve_doc},
108
{NULL, NULL} /* sentinel */
112
/***********************************************************************
113
* SciPySuperLUType methods
117
SciPyLU_dealloc(SciPyLUObject *self)
119
SUPERLU_FREE(self->perm_r);
120
SUPERLU_FREE(self->perm_c);
121
Destroy_SuperNode_Matrix(&self->L);
122
Destroy_CompCol_Matrix(&self->U);
127
SciPyLU_getattr(SciPyLUObject *self, char *name)
129
if (strcmp(name, "shape") == 0)
130
return Py_BuildValue("(i,i)", self->m, self->n);
131
if (strcmp(name, "nnz") == 0)
132
return Py_BuildValue("i", ((SCformat *)self->L.Store)->nnz + ((SCformat *)self->U.Store)->nnz);
133
if (strcmp(name, "__members__") == 0) {
134
char *members[] = {"shape", "nnz"};
137
PyObject *list = PyList_New(sizeof(members)/sizeof(char *));
139
for (i = 0; i < sizeof(members)/sizeof(char *); i ++)
140
PyList_SetItem(list, i, PyString_FromString(members[i]));
141
if (PyErr_Occurred()) {
148
return Py_FindMethod(SciPyLU_methods, (PyObject *)self, name);
152
/***********************************************************************
153
* SciPySuperLUType structure
156
PyTypeObject SciPySuperLUType = {
157
PyObject_HEAD_INIT(NULL)
160
sizeof(SciPyLUObject),
162
(destructor)SciPyLU_dealloc, /* tp_dealloc */
164
(getattrfunc)SciPyLU_getattr, /* tp_getattr */
169
0, /* tp_as_sequence*/
170
0, /* tp_as_mapping*/
175
int DenseSuper_from_Numeric(SuperMatrix *X, PyObject *PyX)
180
if (!PyArray_Check(PyX)) {
181
PyErr_SetString(PyExc_TypeError, "dgssv: Second argument is not an array.");
185
aX = (PyArrayObject *)PyX;
189
m = aX->dimensions[0];
194
m = aX->dimensions[1];
195
n = aX->dimensions[0];
199
if (setjmp(_superlu_py_jmpbuf)) return -1;
201
switch (aX->descr->type_num) {
203
sCreate_Dense_Matrix(X, m, n, (float *)aX->data, ldx, SLU_DN, SLU_S, SLU_GE);
206
dCreate_Dense_Matrix(X, m, n, (double *)aX->data, ldx, SLU_DN, SLU_D, SLU_GE);
209
cCreate_Dense_Matrix(X, m, n, (complex *)aX->data, ldx, SLU_DN, SLU_C, SLU_GE);
211
case PyArray_CDOUBLE:
212
zCreate_Dense_Matrix(X, m, n, (doublecomplex *)aX->data, ldx, SLU_DN, SLU_Z, SLU_GE);
215
PyErr_SetString(PyExc_TypeError, "Invalid type for Numeric array.");
222
/* Natively handles Compressed Sparse Row and CSC */
224
int NRFormat_from_spMatrix(SuperMatrix *A, int m, int n, int nnz, PyArrayObject *nzvals, PyArrayObject *colind, PyArrayObject *rowptr, int typenum)
228
err = (nzvals->descr->type_num != typenum);
229
err += (nzvals->nd != 1);
230
err += (nnz > nzvals->dimensions[0]);
232
PyErr_SetString(PyExc_TypeError, "Fourth argument must be a 1-D array at least as big as third argument.");
236
if (setjmp(_superlu_py_jmpbuf)) return -1;
238
switch (nzvals->descr->type_num) {
240
sCreate_CompRow_Matrix(A, m, n, nnz, (float *)nzvals->data, (int *)colind->data, \
241
(int *)rowptr->data, SLU_NR, SLU_S, SLU_GE);
244
dCreate_CompRow_Matrix(A, m, n, nnz, (double *)nzvals->data, (int *)colind->data, \
245
(int *)rowptr->data, SLU_NR, SLU_D, SLU_GE);
248
cCreate_CompRow_Matrix(A, m, n, nnz, (complex *)nzvals->data, (int *)colind->data, \
249
(int *)rowptr->data, SLU_NR, SLU_C, SLU_GE);
251
case PyArray_CDOUBLE:
252
zCreate_CompRow_Matrix(A, m, n, nnz, (doublecomplex *)nzvals->data, (int *)colind->data, \
253
(int *)rowptr->data, SLU_NR, SLU_Z, SLU_GE);
256
PyErr_SetString(PyExc_TypeError, "Invalid type for array.");
263
int NCFormat_from_spMatrix(SuperMatrix *A, int m, int n, int nnz, PyArrayObject *nzvals, PyArrayObject *rowind, PyArrayObject *colptr, int typenum)
267
err = (nzvals->descr->type_num != typenum);
268
err += (nzvals->nd != 1);
269
err += (nnz > nzvals->dimensions[0]);
271
PyErr_SetString(PyExc_TypeError, "Fifth argument must be a 1-D array at least as big as fourth argument.");
276
if (setjmp(_superlu_py_jmpbuf)) return -1;
278
switch (nzvals->descr->type_num) {
280
sCreate_CompCol_Matrix(A, m, n, nnz, (float *)nzvals->data, (int *)rowind->data, \
281
(int *)colptr->data, SLU_NC, SLU_S, SLU_GE);
284
dCreate_CompCol_Matrix(A, m, n, nnz, (double *)nzvals->data, (int *)rowind->data, \
285
(int *)colptr->data, SLU_NC, SLU_D, SLU_GE);
288
cCreate_CompCol_Matrix(A, m, n, nnz, (complex *)nzvals->data, (int *)rowind->data, \
289
(int *)colptr->data, SLU_NC, SLU_C, SLU_GE);
291
case PyArray_CDOUBLE:
292
zCreate_CompCol_Matrix(A, m, n, nnz, (doublecomplex *)nzvals->data, (int *)rowind->data, \
293
(int *)colptr->data, SLU_NC, SLU_Z, SLU_GE);
296
PyErr_SetString(PyExc_TypeError, "Invalid type for array.");
303
colperm_t superlu_module_getpermc(int permc_spec)
311
return MMD_AT_PLUS_A;
315
ABORT("Invalid input for permc_spec.");
316
return NATURAL; /* compiler complains... */
320
newSciPyLUObject(SuperMatrix *A, double diag_pivot_thresh,
321
double drop_tol, int relax, int panel_size, int permc_spec,
325
/* A must be in SLU_NC format used by the factorization routine. */
327
SuperMatrix AC; /* Matrix postmultiplied by Pc */
332
superlu_options_t options;
337
/* Create SciPyLUObject */
338
self = PyObject_New(SciPyLUObject, &SciPySuperLUType);
340
return PyErr_NoMemory();
347
if (setjmp(_superlu_py_jmpbuf)) goto fail;
349
/* Calculate and apply minimum degree ordering*/
350
etree = intMalloc(n);
351
self->perm_r = intMalloc(n);
352
self->perm_c = intMalloc(n);
354
set_default_options(&options);
355
options.ColPerm=superlu_module_getpermc(permc_spec);
356
options.DiagPivotThresh = diag_pivot_thresh;
359
get_perm_c(permc_spec, A, self->perm_c); /* calc column permutation */
360
sp_preorder(&options, A, self->perm_c, etree, &AC); /* apply column permutation */
363
/* Perform factorization */
366
sgstrf(&options, &AC, (float) drop_tol, relax, panel_size,
367
etree, NULL, lwork, self->perm_c, self->perm_r,
368
&self->L, &self->U, &stat, &info);
371
dgstrf(&options, &AC, drop_tol, relax, panel_size,
372
etree, NULL, lwork, self->perm_c, self->perm_r,
373
&self->L, &self->U, &stat, &info);
376
cgstrf(&options, &AC, (float) drop_tol, relax, panel_size,
377
etree, NULL, lwork, self->perm_c, self->perm_r,
378
&self->L, &self->U, &stat, &info);
381
zgstrf(&options, &AC, drop_tol, relax, panel_size,
382
etree, NULL, lwork, self->perm_c, self->perm_r,
383
&self->L, &self->U, &stat, &info);
386
PyErr_SetString(PyExc_ValueError, "Invalid type in SuperMatrix.");
392
PyErr_SetString(PyExc_SystemError, "dgstrf was called with invalid arguments");
395
PyErr_SetString(PyExc_RuntimeError, "Factor is exactly singular");
404
Destroy_CompCol_Permuted(&AC);
407
return (PyObject *)self;
411
Destroy_CompCol_Permuted(&AC);
413
SciPyLU_dealloc(self);