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 {
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 /* ========================================================================= */
85 void 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 */
118 int 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