|
1 | 1 | from sparse_lib.sparse.ll_mat cimport LLSparseMatrix |
2 | 2 |
|
3 | | -cdef extern from "suitesparse/umfpack.h": |
| 3 | +import sys |
4 | 4 |
|
5 | | - char * UMFPACK_DATE |
6 | | - |
7 | | - # OPAQUE UMFPACK OBJECTS |
8 | | - cdef struct Symbolic: |
9 | | - pass |
10 | | - ctypedef Symbolic * symbolic_t |
| 5 | +cdef extern from "umfpack.h": |
11 | 6 |
|
12 | | - cdef struct Numeric: |
13 | | - pass |
14 | | - ctypedef Numeric * numeric_t |
| 7 | + char * UMFPACK_DATE |
15 | 8 |
|
16 | 9 | cdef enum: |
17 | 10 | UMFPACK_CONTROL, UMFPACK_INFO |
@@ -88,26 +81,31 @@ cdef extern from "suitesparse/umfpack.h": |
88 | 81 |
|
89 | 82 | int umfpack_di_symbolic(int n_row, int n_col, |
90 | 83 | int * Ap, int * Ai, double * Ax, |
91 | | - symbolic_t * symbolic, |
| 84 | + void ** symbolic, |
92 | 85 | double * control, double * info) |
93 | 86 |
|
94 | 87 | int umfpack_di_numeric(int * Ap, int * Ai, double * Ax, |
95 | | - symbolic_t symbolic, |
96 | | - numeric_t * numeric, |
| 88 | + void * symbolic, |
| 89 | + void ** numeric, |
97 | 90 | double * control, double * info) |
98 | 91 |
|
99 | | - void umfpack_di_free_symbolic(symbolic_t * symbolic) |
100 | | - void umfpack_di_free_numeric(numeric_t * numeric) |
| 92 | + void umfpack_di_free_symbolic(void ** symbolic) |
| 93 | + void umfpack_di_free_numeric(void ** numeric) |
101 | 94 | void umfpack_di_defaults(double * control) |
102 | 95 |
|
103 | 96 | int umfpack_di_get_lunz(int * lnz, int * unz, int * n_row, int * n_col, |
104 | | - int * nz_udiag, numeric_t numeric) |
| 97 | + int * nz_udiag, void * numeric) |
105 | 98 |
|
106 | 99 | int umfpack_di_get_numeric(int * Lp, int * Lj, double * Lx, double * Lz, |
107 | 100 | int * Up, int * Ui, double * Ux, double * Uz, |
108 | 101 | int * P, int * Q, double * Dx, double * Dz, |
109 | 102 | int * do_recip, double * Rs, |
110 | | - numeric_t numeric) |
| 103 | + void * numeric) |
| 104 | + |
| 105 | + void umfpack_di_report_control(double *) |
| 106 | + void umfpack_di_report_info(double *, double *) |
| 107 | + void umfpack_di_report_symbolic(void *, double *) |
| 108 | + void umfpack_di_report_numeric(void *, double *) |
111 | 109 |
|
112 | 110 |
|
113 | 111 | def umfpack_version(): |
@@ -181,16 +179,26 @@ def test_umfpack_result(status, msg, raise_error=True, print_on_screen=True): |
181 | 179 |
|
182 | 180 |
|
183 | 181 | cdef class UmfpackSolver: |
| 182 | + """ |
| 183 | + Umfpack Solver from SuiteSparse. |
| 184 | +
|
| 185 | + This version **only** deals with ``LLSparseMatrix`` objects. |
| 186 | +
|
| 187 | + We follow the common use of Umfpack. In particular, we use the same names for the methods of this |
| 188 | + class as their corresponding counter-parts in Umfpack. |
| 189 | + """ |
184 | 190 | UMFPACK_VERSION = "%s.%s.%s (%s)" % (UMFPACK_MAIN_VERSION, |
185 | 191 | UMFPACK_SUB_VERSION, |
186 | 192 | UMFPACK_SUBSUB_VERSION, |
187 | 193 | UMFPACK_DATE) |
| 194 | + |
188 | 195 | def __cinit__(self, LLSparseMatrix A): |
189 | 196 | self.A = A |
190 | 197 | self.nrow = A.nrow |
191 | 198 | self.ncol = A.ncol |
192 | 199 |
|
193 | | - self.csc = self.A.to_csc() |
| 200 | + # TODO: type csc in pxd file |
| 201 | + self.csc_mat = self.A.to_csc() |
194 | 202 |
|
195 | 203 | #cdef double * val = self.val |
196 | 204 | #cdef int * col = <int *> self.col |
@@ -224,42 +232,111 @@ cdef class UmfpackSolver: |
224 | 232 | #################################################################################################################### |
225 | 233 | # PRIMARY ROUTINES |
226 | 234 | #################################################################################################################### |
227 | | - cdef create_symbolic(self, recompute=False): |
| 235 | + cdef int _create_symbolic(self): |
228 | 236 |
|
229 | 237 | if self.symbolic_computed: |
230 | | - if not recompute: |
231 | | - pass |
232 | | - else: |
233 | | - self.free_symbolic() |
234 | | - |
235 | | - #cdef double* info = <double>self.info.data |
236 | | - #cdef double * control = self.control.data |
237 | | - #cdef symbolic_t symbolic = self.symbolic |
238 | | - |
239 | | - |
240 | | - |
241 | | - #status= umfpack_di_symbolic(self.nrow, self.ncol, ind, col, val, &self.symbolic, &self.control, &self.info) |
242 | | - |
243 | | - #if status != UMFPACK_OK: |
244 | | - # self.free_symbolic() |
245 | | - # test_umfpack_result(status, "create_symbolic()") |
246 | | - #else: |
247 | | - # self.symbolic_computed = True |
248 | | - |
249 | | - # def create_numeric(self, recompute=False): |
250 | | - # |
251 | | - # if self.numeric is not None: |
252 | | - # if not recompute: |
253 | | - # pass |
254 | | - # else: |
255 | | - # self.free_numeric() |
256 | | - # |
257 | | - # self.create_symbolic() |
258 | | - # |
259 | | - # status, self.numeric = self.UMFPACK_ROUTINES['numeric'](self.ind, self.col, self.val, self.symbolic, self.control, self.info) |
260 | | - # |
261 | | - # if status != UMFPACK_OK: |
262 | | - # self.numeric = None |
263 | | - # test_umfpack_result(status, "create_numeric()") |
| 238 | + self.free_symbolic() |
| 239 | + |
| 240 | + cdef int * ind = <int *> self.csc_mat.ind |
| 241 | + cdef int * row = <int *> self.csc_mat.row |
| 242 | + cdef double * val = <double *> self.csc_mat.val |
| 243 | + |
| 244 | + |
| 245 | + cdef int status= umfpack_di_symbolic(self.nrow, self.ncol, ind, row, val, &self.symbolic, self.control, self.info) |
| 246 | + |
| 247 | + self.symbolic_computed = True |
| 248 | + |
| 249 | + return status |
| 250 | + |
| 251 | + |
| 252 | + def create_symbolic(self, recompute=False): |
| 253 | + if not recompute and self.symbolic_computed: |
| 254 | + return |
264 | 255 |
|
| 256 | + cdef int status = self._create_symbolic() |
| 257 | + |
| 258 | + if status != UMFPACK_OK: |
| 259 | + self.free_symbolic() |
| 260 | + test_umfpack_result(status, "create_symbolic") |
| 261 | + |
| 262 | + cdef int _create_numeric(self): |
| 263 | + |
| 264 | + if self.numeric_computed: |
| 265 | + self.free_numeric() |
| 266 | + |
| 267 | + cdef int * ind = <int *> self.csc_mat.ind |
| 268 | + cdef int * row = <int *> self.csc_mat.row |
| 269 | + cdef double * val = <double *> self.csc_mat.val |
| 270 | + |
| 271 | + cdef int status = umfpack_di_numeric(ind, row, val, |
| 272 | + self.symbolic, |
| 273 | + &self.numeric, |
| 274 | + self.control, self.info) |
| 275 | + |
| 276 | + self.numeric_computed = True |
| 277 | + |
| 278 | + return status |
| 279 | + |
| 280 | + def create_numeric(self, recompute=False): |
| 281 | + |
| 282 | + if not recompute and self.numeric_computed: |
| 283 | + return |
| 284 | + |
| 285 | + cdef int status = self._create_numeric() |
| 286 | + |
| 287 | + if status != UMFPACK_OK: |
| 288 | + self.free_numeric() |
| 289 | + test_umfpack_result(status, "create_numeric") |
| 290 | + |
| 291 | + |
| 292 | + #################################################################################################################### |
| 293 | + # REPORTING ROUTINES |
| 294 | + #################################################################################################################### |
| 295 | + def set_verbosity(self, level): |
| 296 | + """ |
| 297 | + Set UMFPACK verbosity level. |
| 298 | +
|
| 299 | + Args: |
| 300 | + level (int): Verbosity level (default: 1). |
| 301 | + """ |
| 302 | + self.control[UMFPACK_PRL] = level |
| 303 | + |
| 304 | + def get_verbosity(self): |
| 305 | + """ |
| 306 | + Return UMFPACK verbosity level. |
| 307 | +
|
| 308 | + Returns: |
| 309 | + verbosity_level (int): The verbosity level set. |
| 310 | + """ |
| 311 | + return self.control[UMFPACK_PRL] |
| 312 | + |
| 313 | + def report_control(self): |
| 314 | + """ |
| 315 | + Print control values. |
| 316 | + """ |
| 317 | + umfpack_di_report_control(self.control) |
| 318 | + |
| 319 | + def report_info(self): |
| 320 | + """ |
| 321 | + Print all status information. |
| 322 | +
|
| 323 | + Use **after** calling :meth:`create_symbolic()`, :meth:`create_numeric()`, :meth:`factorize()` or :meth:`solve()`. |
| 324 | + """ |
| 325 | + umfpack_di_report_info(self.control, self.info) |
| 326 | + |
| 327 | + def report_symbolic(self): |
| 328 | + """ |
| 329 | + Print information about the opaque ``symbolic`` object. |
| 330 | + """ |
| 331 | + if not self.symbolic_computed: |
| 332 | + print "No opaque symbolic object has been computed" |
| 333 | + return |
| 334 | + |
| 335 | + umfpack_di_report_symbolic(self.symbolic, self.control) |
| 336 | + |
| 337 | + def report_numeric(self): |
| 338 | + """ |
| 339 | + Print information about the opaque ``numeric`` object. |
| 340 | + """ |
| 341 | + umfpack_di_report_numeric(self.numeric, self.control) |
265 | 342 |
|
0 commit comments