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