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