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 "../../external_src/oomph_superlu_4.3/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 SuperMatrix *L;
28 SuperMatrix *U;
29 int *perm_c;
30 int *perm_r;
31} factors_t;
32
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, int *n, int *nnz, int *nrhs,
61 doublecomplex *values, int *rowind, int *colptr,
62 doublecomplex *b, int *ldb, int *transpose, int *doc,
63 fptr *f_factors, int *info)
64
65{
66
67 SuperMatrix A, AC, B;
68 SuperMatrix *L, *U;
69 int *perm_r; /* row permutations from partial pivoting */
70 int *perm_c; /* column permutation vector */
71 int *etree; /* column elimination tree */
72 SCformat *Lstore;
73 NCformat *Ustore;
74 int i, j, panel_size, permc_spec, relax;
75 trans_t trans;
76 //double drop_tol = 0.0; //No longer needed SuperLU 4.3
77 mem_usage_t mem_usage;
78 superlu_options_t options;
79 SuperLUStat_t stat;
80 factors_t *LUfactors;
81
82 doublecomplex *Lval;
83 doublecomplex *diagU, *dblock;
84 int_t fsupc, nsupr, nsupc, luptr;
85 int_t i2, k2, nsupers;
86 int signature=1;
87 int sign = 0;
88
89/* Do we need to transpose? */
90 if (*transpose==0)
91 {
92 trans = NOTRANS;
93 }
94 else
95 {
96 trans = TRANS;
97 }
98
99 if ( *op_flag == 1 ) { /* LU decomposition */
100
101 /* Set the default input options. */
102 set_default_options(&options);
103
104 /* Initialize the statistics variables. */
105 StatInit(&stat);
106
107 zCreate_CompCol_Matrix(&A, *n, *n, *nnz, values, rowind, colptr,
108 SLU_NC, SLU_Z, SLU_GE);
109 L = (SuperMatrix *) SUPERLU_MALLOC( sizeof(SuperMatrix) );
110 U = (SuperMatrix *) SUPERLU_MALLOC( sizeof(SuperMatrix) );
111 if ( !(perm_r = intMalloc(*n)) ) ABORT("Malloc fails for perm_r[].");
112 if ( !(perm_c = intMalloc(*n)) ) ABORT("Malloc fails for perm_c[].");
113 if ( !(etree = intMalloc(*n)) ) ABORT("Malloc fails for etree[].");
114
115 /*
116 * Get column permutation vector perm_c[], according to permc_spec:
117 * permc_spec = 0: natural ordering
118 * permc_spec = 1: minimum degree on structure of A'*A
119 * permc_spec = 2: minimum degree on structure of A'+A
120 * permc_spec = 3: approximate minimum degree for unsymmetric matrices
121 */
122 permc_spec = options.ColPerm;
123 get_perm_c(permc_spec, &A, perm_c);
124
125 sp_preorder(&options, &A, perm_c, etree, &AC);
126
127 panel_size = sp_ienv(1);
128 relax = sp_ienv(2);
129
130 zgstrf(&options, &AC, /*drop_tol,*/ relax, panel_size,
131 etree, NULL, 0, perm_c, perm_r, L, U, &stat, info);
132
133 if ( *info == 0 ) {
134 Lstore = (SCformat *) L->Store;
135 Ustore = (NCformat *) U->Store;
136 if (*doc!=0)
137 {
138 printf(" No of nonzeros in factor L = %d\n", Lstore->nnz);
139 printf(" No of nonzeros in factor U = %d\n", Ustore->nnz);
140 printf(" No of nonzeros in L+U = %d\n", Lstore->nnz + Ustore->nnz);
141 zQuerySpace(L, U, &mem_usage);
142 printf(" L\\U MB %.3f\ttotal MB needed %.3f\n",
143 //\texpansions %d\n",
144 mem_usage.for_lu/1e6, mem_usage.total_needed/1e6);
145 //mem_usage.expansions);
146 }
147 } else {
148 printf("dgstrf() error returns INFO= %d\n", *info);
149 if ( *info <= *n ) { /* factorization completes */
150 zQuerySpace(L, U, &mem_usage);
151 printf(" L\\U MB %.3f\ttotal MB needed %.3f\n",
152 //\texpansions %d\n\n",
153 mem_usage.for_lu/1e6, mem_usage.total_needed/1e6);
154 //mem_usage.expansions);
155 }
156 }
157
158 /* Save the LU factors in the factors handle */
159 LUfactors = (factors_t*) SUPERLU_MALLOC(sizeof(factors_t));
160 LUfactors->L = L;
161 LUfactors->U = U;
162 LUfactors->perm_c = perm_c;
163 LUfactors->perm_r = perm_r;
164 *f_factors = (fptr) LUfactors;
165
166 //Work out and print the sign of the determinant
167 //This code is hacked from supraLU by Alex Pletzer
168 //and Doug McCune (NTCC) (http://w3.pppl.gov/ntcc/SupraLu/)
169 Lstore = L->Store;
170 Lval = Lstore->nzval;
171 nsupers = Lstore->nsuper + 1;
172
173 //Get the diagonal entries of the U matrix
174 //Allocate store for the entries
175 if ( !(diagU = SUPERLU_MALLOC( *n * sizeof(SuperMatrix) )) )
176 ABORT("Malloc fails for diagU[].");
177 //Loop over the number of super diagonal terms(?)
178 for(k2=0; k2< nsupers; k2++)
179 {
180 fsupc = L_FST_SUPC(k2);
181 nsupc = L_FST_SUPC(k2+1) - fsupc;
182 nsupr = L_SUB_START(fsupc+1) - L_SUB_START(fsupc);
183 luptr = L_NZ_START(fsupc);
184
185 dblock = &diagU[fsupc];
186 for(i2 = 0; i2 < nsupc; i2++)
187 {
188 dblock[i2] = Lval[luptr];
189 luptr += nsupr + 1;
190 }
191 }
192
193 //Now multiply all the diagonal terms together to get the determinant
194 //Note that we need to use the mantissa, exponent formulation to
195 //avoid underflow errors
196 double determinant_mantissa=1.0;
197 int determinant_exponent = 0, iexp;
198 for(i=0; i<*n; i++)
199 {
200 determinant_mantissa *= frexp(diagU[i].r, &iexp);
201 determinant_exponent += iexp;
202 /* normalise*/
203 determinant_mantissa = frexp(determinant_mantissa,&iexp);
204 determinant_exponent += iexp;
205
206 /*Now worry about the permutations
207 (this is done in a stupid, but not too inefficient way)*/
208 for(j=i;j<*n;j++)
209 {
210 if(perm_r[j] < perm_r[i]) {signature *= -1;}
211 if(perm_c[j] < perm_c[i]) {signature *= -1;}
212 }
213 }
214
215 //Find the sign of the determinant
216 if(determinant_mantissa > 0.0) {sign = 1;}
217 if(determinant_mantissa < 0.0) {sign = -1;}
218
219 //Multiply the sign by the signature
220 sign *= signature;
221
222 /* Free un-wanted storage */
223 SUPERLU_FREE(diagU);
224 SUPERLU_FREE(etree);
225 Destroy_SuperMatrix_Store(&A);
226 Destroy_CompCol_Permuted(&AC);
227 StatFree(&stat);
228
229 //Return the sign of the determinant
230 return sign;
231
232 } else if ( *op_flag == 2 ) { /* Triangular solve */
233 /* Initialize the statistics variables. */
234 StatInit(&stat);
235
236 /* Extract the LU factors in the factors handle */
237 LUfactors = (factors_t*) *f_factors;
238 L = LUfactors->L;
239 U = LUfactors->U;
240 perm_c = LUfactors->perm_c;
241 perm_r = LUfactors->perm_r;
242
243 zCreate_Dense_Matrix(&B, *n, *nrhs, b, *ldb, SLU_DN, SLU_Z, SLU_GE);
244
245 /* Solve the system A*X=B, overwriting B with X. */
246 zgstrs (trans, L, U, perm_c, perm_r, &B, &stat, info);
247
248 Destroy_SuperMatrix_Store(&B);
249 StatFree(&stat);
250
251 //Return zero
252 return 0;
253
254 } else if ( *op_flag == 3 ) { /* Free storage */
255 /* Free the LU factors in the factors handle */
256 LUfactors = (factors_t*) *f_factors;
257 SUPERLU_FREE (LUfactors->perm_r);
258 SUPERLU_FREE (LUfactors->perm_c);
259 Destroy_SuperNode_Matrix(LUfactors->L);
260 Destroy_CompCol_Matrix(LUfactors->U);
261 SUPERLU_FREE (LUfactors->L);
262 SUPERLU_FREE (LUfactors->U);
263 SUPERLU_FREE (LUfactors);
264 return 0;
265 } else {
266 fprintf(stderr,"Invalid op_flag=%d passed to c_cpp_dgssv()\n",*op_flag);
267 exit(-1);
268 }
269}
270
271
cstr elem_len * i
Definition cfortran.h:603
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
void * fptr
Definition superlu.c:23
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