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