superlu_complex.c
Go to the documentation of this file.
1
2/* Wrapper for SuperLU solver. Based on fortran wrapper supplied
3 * with SuperLU version 3.0. Given that, it seems appropriate
4 * to retain this copyright notice:
5 *
6 * -- SuperLU routine (version 3.0) --
7 * Univ. of California Berkeley, Xerox Palo Alto Research Center,
8 * and Lawrence Berkeley National Lab.
9 * October 15, 2003
10 *
11 */
12
13#include "slu_zdefs.h"
14#include "math.h"
15
16
17/* ================================================= */
18/* Pointer to the LU factors*/
19/* ================================================= */
20typedef void* fptr;
21
22
23/* ================================================= */
24/* Struct for the lu factors */
25/* ================================================= */
26typedef struct
27{
28 SuperMatrix* L;
29 SuperMatrix* U;
30 int* perm_c;
31 int* perm_r;
32} factors_t;
33
34
35/* =========================================================================
36 * Wrapper to superlu solver:
37 *
38 * op_flag = int specifies the operation:
39 * 1, performs LU decomposition for the first time
40 * 2, performs triangular solve
41 * 3, free all the storage in the end
42 * n = dimension of matrix
43 * nnz = # of nonzero entries
44 * nrhs = # of RHSs
45 * values = double array containing the nonzero entries
46 * rowind = int array containing the row indices of the entries
47 * colptr = int array containing the column start
48 * b = double array containing the rhs vector (gets overwritten
49 * with solution)
50 * ldb = leading dimension of b
51 * transpose = 0/1 if matrix is transposed/not transposed
52 * doc = 0/1 for full doc/no full doc
53 * info = info flag from superlu
54 * f_factors = pointer to LU factors. (If op_flag == 1, it is an output
55 * and contains the pointer pointing to the structure of
56 * the factored matrices. Otherwise, it it an input.
57 * Returns the SIGN of the determinant of the matrix
58 * =========================================================================
59 */
60int superlu_complex(int* op_flag,
61 int* n,
62 int* nnz,
63 int* nrhs,
64 doublecomplex* values,
65 int* rowind,
66 int* colptr,
67 doublecomplex* b,
68 int* ldb,
69 int* transpose,
70 int* doc,
71 fptr* f_factors,
72 int* info)
73
74{
75 SuperMatrix A, AC, B;
76 SuperMatrix *L, *U;
77 int* perm_r; /* row permutations from partial pivoting */
78 int* perm_c; /* column permutation vector */
79 int* etree; /* column elimination tree */
80 SCformat* Lstore;
81 NCformat* Ustore;
82 int i, j, panel_size, permc_spec, relax;
83 trans_t trans;
84 // double drop_tol = 0.0; //No longer needed SuperLU 4.3
85 mem_usage_t mem_usage;
86 superlu_options_t options;
87 SuperLUStat_t stat;
88 factors_t* LUfactors;
89 GlobalLU_t Glu;
90
91 doublecomplex* Lval;
92 doublecomplex *diagU, *dblock;
93 int_t fsupc, nsupr, nsupc, luptr;
94 int_t i2, k2, nsupers;
95 int signature = 1;
96 int sign = 0;
97
98 /* Do we need to transpose? */
99 if (*transpose == 0)
100 {
101 trans = NOTRANS;
102 }
103 else
104 {
105 trans = TRANS;
106 }
107
108 if (*op_flag == 1)
109 { /* LU decomposition */
110
111 /* Set the default input options. */
112 set_default_options(&options);
113
114 /* Initialize the statistics variables. */
115 StatInit(&stat);
116
117 zCreate_CompCol_Matrix(
118 &A, *n, *n, *nnz, values, rowind, colptr, SLU_NC, SLU_Z, SLU_GE);
119 L = (SuperMatrix*)SUPERLU_MALLOC(sizeof(SuperMatrix));
120 U = (SuperMatrix*)SUPERLU_MALLOC(sizeof(SuperMatrix));
121 if (!(perm_r = intMalloc(*n))) ABORT("Malloc fails for perm_r[].");
122 if (!(perm_c = intMalloc(*n))) ABORT("Malloc fails for perm_c[].");
123 if (!(etree = intMalloc(*n))) ABORT("Malloc fails for etree[].");
124
125 /*
126 * Get column permutation vector perm_c[], according to permc_spec:
127 * permc_spec = 0: natural ordering
128 * permc_spec = 1: minimum degree on structure of A'*A
129 * permc_spec = 2: minimum degree on structure of A'+A
130 * permc_spec = 3: approximate minimum degree for unsymmetric matrices
131 */
132 permc_spec = options.ColPerm;
133 get_perm_c(permc_spec, &A, perm_c);
134
135 sp_preorder(&options, &A, perm_c, etree, &AC);
136
137 panel_size = sp_ienv(1);
138 relax = sp_ienv(2);
139
140 zgstrf(&options,
141 &AC,
142 /*drop_tol,*/ relax,
143 panel_size,
144 etree,
145 NULL,
146 0,
147 perm_c,
148 perm_r,
149 L,
150 U,
151 &Glu, /* new with SuperLU 5.0 */
152 &stat,
153 info);
154
155 if (*info == 0)
156 {
157 Lstore = (SCformat*)L->Store;
158 Ustore = (NCformat*)U->Store;
159 if (*doc != 0)
160 {
161 printf(" No of nonzeros in factor L = %d\n", Lstore->nnz);
162 printf(" No of nonzeros in factor U = %d\n", Ustore->nnz);
163 printf(" No of nonzeros in L+U = %d\n", Lstore->nnz + Ustore->nnz);
164 zQuerySpace(L, U, &mem_usage);
165 printf(" L\\U MB %.3f\ttotal MB needed %.3f\n",
166 //\texpansions %d\n",
167 mem_usage.for_lu / 1e6,
168 mem_usage.total_needed / 1e6);
169 // mem_usage.expansions);
170 }
171 }
172 else
173 {
174 printf("dgstrf() error returns INFO= %d\n", *info);
175 if (*info <= *n)
176 { /* factorization completes */
177 zQuerySpace(L, U, &mem_usage);
178 printf(" L\\U MB %.3f\ttotal MB needed %.3f\n",
179 //\texpansions %d\n\n",
180 mem_usage.for_lu / 1e6,
181 mem_usage.total_needed / 1e6);
182 // mem_usage.expansions);
183 }
184 }
185
186 /* Save the LU factors in the factors handle */
187 LUfactors = (factors_t*)SUPERLU_MALLOC(sizeof(factors_t));
188 LUfactors->L = L;
189 LUfactors->U = U;
190 LUfactors->perm_c = perm_c;
191 LUfactors->perm_r = perm_r;
192 *f_factors = (fptr)LUfactors;
193
194 // Work out and print the sign of the determinant
195 // This code is hacked from supraLU by Alex Pletzer
196 // and Doug McCune (NTCC) (http://w3.pppl.gov/ntcc/SupraLu/)
197 Lstore = L->Store;
198 Lval = Lstore->nzval;
199 nsupers = Lstore->nsuper + 1;
200
201 // Get the diagonal entries of the U matrix
202 // Allocate store for the entries
203 if (!(diagU = SUPERLU_MALLOC(*n * sizeof(SuperMatrix))))
204 ABORT("Malloc fails for diagU[].");
205 // Loop over the number of super diagonal terms(?)
206 for (k2 = 0; k2 < nsupers; k2++)
207 {
208 fsupc = L_FST_SUPC(k2);
209 nsupc = L_FST_SUPC(k2 + 1) - fsupc;
210 nsupr = L_SUB_START(fsupc + 1) - L_SUB_START(fsupc);
211 luptr = L_NZ_START(fsupc);
212
213 dblock = &diagU[fsupc];
214 for (i2 = 0; i2 < nsupc; i2++)
215 {
216 dblock[i2] = Lval[luptr];
217 luptr += nsupr + 1;
218 }
219 }
220
221 // Now multiply all the diagonal terms together to get the determinant
222 // Note that we need to use the mantissa, exponent formulation to
223 // avoid underflow errors
224 double determinant_mantissa = 1.0;
225 int determinant_exponent = 0, iexp;
226 for (i = 0; i < *n; i++)
227 {
228 determinant_mantissa *= frexp(diagU[i].r, &iexp);
229 determinant_exponent += iexp;
230 /* normalise*/
231 determinant_mantissa = frexp(determinant_mantissa, &iexp);
232 determinant_exponent += iexp;
233
234 /*Now worry about the permutations
235 (this is done in a stupid, but not too inefficient way)*/
236 for (j = i; j < *n; j++)
237 {
238 if (perm_r[j] < perm_r[i])
239 {
240 signature *= -1;
241 }
242 if (perm_c[j] < perm_c[i])
243 {
244 signature *= -1;
245 }
246 }
247 }
248
249 // Find the sign of the determinant
250 if (determinant_mantissa > 0.0)
251 {
252 sign = 1;
253 }
254 if (determinant_mantissa < 0.0)
255 {
256 sign = -1;
257 }
258
259 // Multiply the sign by the signature
260 sign *= signature;
261
262 /* Free un-wanted storage */
263 SUPERLU_FREE(diagU);
264 SUPERLU_FREE(etree);
265 Destroy_SuperMatrix_Store(&A);
266 Destroy_CompCol_Permuted(&AC);
267 StatFree(&stat);
268
269 // Return the sign of the determinant
270 return sign;
271 }
272 else if (*op_flag == 2)
273 { /* Triangular solve */
274 /* Initialize the statistics variables. */
275 StatInit(&stat);
276
277 /* Extract the LU factors in the factors handle */
278 LUfactors = (factors_t*)*f_factors;
279 L = LUfactors->L;
280 U = LUfactors->U;
281 perm_c = LUfactors->perm_c;
282 perm_r = LUfactors->perm_r;
283
284 zCreate_Dense_Matrix(&B, *n, *nrhs, b, *ldb, SLU_DN, SLU_Z, SLU_GE);
285
286 /* Solve the system A*X=B, overwriting B with X. */
287 zgstrs(trans, L, U, perm_c, perm_r, &B, &stat, info);
288
289 Destroy_SuperMatrix_Store(&B);
290 StatFree(&stat);
291
292 // Return zero
293 return 0;
294 }
295 else if (*op_flag == 3)
296 { /* Free storage */
297 /* Free the LU factors in the factors handle */
298 LUfactors = (factors_t*)*f_factors;
299 SUPERLU_FREE(LUfactors->perm_r);
300 SUPERLU_FREE(LUfactors->perm_c);
301 Destroy_SuperNode_Matrix(LUfactors->L);
302 Destroy_CompCol_Matrix(LUfactors->U);
303 SUPERLU_FREE(LUfactors->L);
304 SUPERLU_FREE(LUfactors->U);
305 SUPERLU_FREE(LUfactors);
306 return 0;
307 }
308 else
309 {
310 fprintf(stderr, "Invalid op_flag=%d passed to c_cpp_dgssv()\n", *op_flag);
311 exit(-1);
312 }
313}
cstr elem_len * i
Definition cfortran.h:603
SuperMatrix * L
Definition superlu.c:26
SuperMatrix * U
Definition superlu.c:27
int * perm_r
Definition superlu.c:29
int * perm_c
Definition superlu.c:28
void * fptr
Definition superlu.c:19
int superlu_complex(int *op_flag, int *n, int *nnz, int *nrhs, doublecomplex *values, int *rowind, int *colptr, doublecomplex *b, int *ldb, int *transpose, int *doc, fptr *f_factors, int *info)
void * fptr