xref: /petsc/src/mat/impls/aij/seq/superlu/superlu.c (revision fb10cecf1927e102c85c17a39b04f58da85ca3ce)
1 /*$Id: superlu.c,v 1.10 2001/08/15 15:56:50 bsmith Exp $*/
2 
3 /*
4         Provides an interface to the SuperLU sparse solver
5           Modified for SuperLU 2.0 by Matthew Knepley
6 */
7 
8 #include "src/mat/impls/aij/seq/aij.h"
9 
10 EXTERN_C_BEGIN
11 #if defined(PETSC_USE_COMPLEX)
12 #include "zsp_defs.h"
13 #else
14 #include "dsp_defs.h"
15 #endif
16 #include "util.h"
17 EXTERN_C_END
18 
19 typedef struct {
20   SuperMatrix  A,B,AC,L,U;
21   int          *perm_r,*perm_c,ispec,relax,panel_size;
22   double       pivot_threshold;
23   NCformat     *store;
24   MatStructure flg;
25   PetscTruth   SuperluMatOdering;
26 
27   /* A few function pointers for inheritance */
28   int (*MatDuplicate)(Mat,MatDuplicateOption,Mat*);
29   int (*MatView)(Mat,PetscViewer);
30   int (*MatAssemblyEnd)(Mat,MatAssemblyType);
31   int (*MatLUFactorSymbolic)(Mat,IS,IS,MatFactorInfo*,Mat*);
32   int (*MatDestroy)(Mat);
33 
34   /* Flag to clean up (non-global) SuperLU objects during Destroy */
35   PetscTruth CleanUpSuperLU;
36 } Mat_SuperLU;
37 
38 
39 EXTERN int MatFactorInfo_SuperLU(Mat,PetscViewer);
40 EXTERN int MatLUFactorSymbolic_SuperLU(Mat,IS,IS,MatFactorInfo*,Mat*);
41 
42 EXTERN_C_BEGIN
43 EXTERN int MatConvert_SuperLU_SeqAIJ(Mat,MatType,Mat*);
44 EXTERN int MatConvert_SeqAIJ_SuperLU(Mat,MatType,Mat*);
45 EXTERN_C_END
46 
47 #undef __FUNCT__
48 #define __FUNCT__ "MatDestroy_SuperLU"
49 int MatDestroy_SuperLU(Mat A)
50 {
51   int         ierr;
52   Mat_SuperLU *lu = (Mat_SuperLU*)A->spptr;
53 
54   PetscFunctionBegin;
55   if (lu->CleanUpSuperLU) {
56     /* We have to free the global data or SuperLU crashes (sucky design)*/
57     /* Since we don't know if more solves on other matrices may be done
58        we cannot free the yucky SuperLU global data
59        StatFree();
60     */
61 
62     /* Free the SuperLU datastructures */
63     Destroy_CompCol_Permuted(&lu->AC);
64     Destroy_SuperNode_Matrix(&lu->L);
65     Destroy_CompCol_Matrix(&lu->U);
66     ierr = PetscFree(lu->B.Store);CHKERRQ(ierr);
67     ierr = PetscFree(lu->A.Store);CHKERRQ(ierr);
68     ierr = PetscFree(lu->perm_r);CHKERRQ(ierr);
69     ierr = PetscFree(lu->perm_c);CHKERRQ(ierr);
70   }
71   ierr = MatConvert_SuperLU_SeqAIJ(A,MATSEQAIJ,&A);CHKERRQ(ierr);
72   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
73   PetscFunctionReturn(0);
74 }
75 
76 #undef __FUNCT__
77 #define __FUNCT__ "MatView_SuperLU"
78 int MatView_SuperLU(Mat A,PetscViewer viewer)
79 {
80   int               ierr;
81   PetscTruth        isascii;
82   PetscViewerFormat format;
83   Mat_SuperLU       *lu=(Mat_SuperLU*)(A->spptr);
84 
85   PetscFunctionBegin;
86   ierr = (*lu->MatView)(A,viewer);CHKERRQ(ierr);
87 
88   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
89   if (isascii) {
90     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
91     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
92       ierr = MatFactorInfo_SuperLU(A,viewer);CHKERRQ(ierr);
93     }
94   }
95   PetscFunctionReturn(0);
96 }
97 
98 #undef __FUNCT__
99 #define __FUNCT__ "MatAssemblyEnd_SuperLU"
100 int MatAssemblyEnd_SuperLU(Mat A,MatAssemblyType mode) {
101   int         ierr;
102   Mat_SuperLU *lu=(Mat_SuperLU*)(A->spptr);
103 
104   PetscFunctionBegin;
105   ierr = (*lu->MatAssemblyEnd)(A,mode);CHKERRQ(ierr);
106 
107   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
108   A->ops->lufactorsymbolic = MatLUFactorSymbolic_SuperLU;
109   PetscFunctionReturn(0);
110 }
111 
112 #include "src/mat/impls/dense/seq/dense.h"
113 #undef __FUNCT__
114 #define __FUNCT__ "MatCreateNull_SuperLU"
115 int MatCreateNull_SuperLU(Mat A,Mat *nullMat)
116 {
117   Mat_SuperLU   *lu = (Mat_SuperLU*)A->spptr;
118   int           numRows = A->m,numCols = A->n;
119   SCformat      *Lstore;
120   int           numNullCols,size;
121 #if defined(PETSC_USE_COMPLEX)
122   doublecomplex *nullVals,*workVals;
123 #else
124   PetscScalar   *nullVals,*workVals;
125 #endif
126   int           row,newRow,col,newCol,block,b,ierr;
127 
128   PetscFunctionBegin;
129   PetscValidHeaderSpecific(A,MAT_COOKIE);
130   PetscValidPointer(nullMat);
131   if (!A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
132   numNullCols = numCols - numRows;
133   if (numNullCols < 0) SETERRQ(PETSC_ERR_ARG_WRONG,"Function only applies to underdetermined problems");
134   /* Create the null matrix */
135   ierr = MatCreateSeqDense(A->comm,numRows,numNullCols,PETSC_NULL,nullMat);CHKERRQ(ierr);
136   if (numNullCols == 0) {
137     ierr = MatAssemblyBegin(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
138     ierr = MatAssemblyEnd(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
139     PetscFunctionReturn(0);
140   }
141 #if defined(PETSC_USE_COMPLEX)
142   nullVals = (doublecomplex*)((Mat_SeqDense*)(*nullMat)->data)->v;
143 #else
144   nullVals = ((Mat_SeqDense*)(*nullMat)->data)->v;
145 #endif
146   /* Copy in the columns */
147   Lstore = (SCformat*)lu->L.Store;
148   for(block = 0; block <= Lstore->nsuper; block++) {
149     newRow = Lstore->sup_to_col[block];
150     size   = Lstore->sup_to_col[block+1] - Lstore->sup_to_col[block];
151     for(col = Lstore->rowind_colptr[newRow]; col < Lstore->rowind_colptr[newRow+1]; col++) {
152       newCol = Lstore->rowind[col];
153       if (newCol >= numRows) {
154         for(b = 0; b < size; b++)
155 #if defined(PETSC_USE_COMPLEX)
156           nullVals[(newCol-numRows)*numRows+newRow+b] = ((doublecomplex*)Lstore->nzval)[Lstore->nzval_colptr[newRow+b]+col];
157 #else
158           nullVals[(newCol-numRows)*numRows+newRow+b] = ((double*)Lstore->nzval)[Lstore->nzval_colptr[newRow+b]+col];
159 #endif
160       }
161     }
162   }
163   /* Permute rhs to form P^T_c B */
164   ierr = PetscMalloc(numRows*sizeof(double),&workVals);CHKERRQ(ierr);
165   for(b = 0; b < numNullCols; b++) {
166     for(row = 0; row < numRows; row++) workVals[lu->perm_c[row]] = nullVals[b*numRows+row];
167     for(row = 0; row < numRows; row++) nullVals[b*numRows+row]   = workVals[row];
168   }
169   /* Backward solve the upper triangle A x = b */
170   for(b = 0; b < numNullCols; b++) {
171 #if defined(PETSC_USE_COMPLEX)
172     sp_ztrsv("L","T","U",&lu->L,&lu->U,&nullVals[b*numRows],&ierr);
173 #else
174     sp_dtrsv("L","T","U",&lu->L,&lu->U,&nullVals[b*numRows],&ierr);
175 #endif
176     if (ierr < 0)
177       SETERRQ1(PETSC_ERR_ARG_WRONG,"The argument %d was invalid",-ierr);
178   }
179   ierr = PetscFree(workVals);CHKERRQ(ierr);
180 
181   ierr = MatAssemblyBegin(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
182   ierr = MatAssemblyEnd(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
183   PetscFunctionReturn(0);
184 }
185 
186 #undef __FUNCT__
187 #define __FUNCT__ "MatSolve_SuperLU"
188 int MatSolve_SuperLU(Mat A,Vec b,Vec x)
189 {
190   Mat_SuperLU *lu = (Mat_SuperLU*)A->spptr;
191   PetscScalar *array;
192   int         m,ierr;
193 
194   PetscFunctionBegin;
195   ierr = VecGetLocalSize(b,&m);CHKERRQ(ierr);
196   ierr = VecCopy(b,x);CHKERRQ(ierr);
197   ierr = VecGetArray(x,&array);CHKERRQ(ierr);
198   /* Create the Rhs */
199   lu->B.Stype        = SLU_DN;
200   lu->B.Mtype        = SLU_GE;
201   lu->B.nrow         = m;
202   lu->B.ncol         = 1;
203   ((DNformat*)lu->B.Store)->lda   = m;
204   ((DNformat*)lu->B.Store)->nzval = array;
205 #if defined(PETSC_USE_COMPLEX)
206   lu->B.Dtype        = SLU_Z;
207   zgstrs("T",&lu->L,&lu->U,lu->perm_r,lu->perm_c,&lu->B,&ierr);
208 #else
209   lu->B.Dtype        = SLU_D;
210   dgstrs("T",&lu->L,&lu->U,lu->perm_r,lu->perm_c,&lu->B,&ierr);
211 #endif
212   if (ierr < 0) SETERRQ1(PETSC_ERR_ARG_WRONG,"The diagonal element of row %d was invalid",-ierr);
213   ierr = VecRestoreArray(x,&array);CHKERRQ(ierr);
214   PetscFunctionReturn(0);
215 }
216 
217 static int StatInitCalled = 0;
218 
219 #undef __FUNCT__
220 #define __FUNCT__ "MatLUFactorNumeric_SuperLU"
221 int MatLUFactorNumeric_SuperLU(Mat A,Mat *F)
222 {
223   Mat_SeqAIJ  *aa = (Mat_SeqAIJ*)(A)->data;
224   Mat_SuperLU *lu = (Mat_SuperLU*)(*F)->spptr;
225   int         *etree,ierr;
226   PetscTruth  flag;
227 
228   PetscFunctionBegin;
229   /* Create the SuperMatrix for A^T:
230        Since SuperLU only likes column-oriented matrices,we pass it the transpose,
231        and then solve A^T X = B in MatSolve().
232   */
233 
234   if ( lu->flg == DIFFERENT_NONZERO_PATTERN){ /* first numerical factorization */
235     lu->A.Stype   = SLU_NC;
236 #if defined(PETSC_USE_COMPLEX)
237     lu->A.Dtype   = SLU_Z;
238 #else
239     lu->A.Dtype   = SLU_D;
240 #endif
241     lu->A.Mtype   = SLU_GE;
242     lu->A.nrow    = A->n;
243     lu->A.ncol    = A->m;
244 
245     ierr = PetscMalloc(sizeof(NCformat),&lu->store);CHKERRQ(ierr);
246     ierr = PetscMalloc(sizeof(DNformat),&lu->B.Store);CHKERRQ(ierr);
247   }
248   lu->store->nnz    = aa->nz;
249   lu->store->colptr = aa->i;
250   lu->store->rowind = aa->j;
251   lu->store->nzval  = aa->a;
252   lu->A.Store       = lu->store;
253 
254   /* Set SuperLU options */
255   lu->relax      = sp_ienv(2);
256   lu->panel_size = sp_ienv(1);
257   /* We have to initialize global data or SuperLU crashes (sucky design) */
258   if (!StatInitCalled) {
259     StatInit(lu->panel_size,lu->relax);
260   }
261   StatInitCalled++;
262 
263   ierr = PetscOptionsBegin(A->comm,A->prefix,"SuperLU Options","Mat");CHKERRQ(ierr);
264   /* use SuperLU mat ordeing */
265   ierr = PetscOptionsInt("-mat_superlu_ordering","SuperLU ordering type (one of 0, 1, 2, 3)\n   0: natural ordering;\n   1: MMD applied to A'*A;\n   2: MMD applied to A'+A;\n   3: COLAMD, approximate minimum degree column ordering","None",lu->ispec,&lu->ispec,&flag);CHKERRQ(ierr);
266   if (flag) {
267     get_perm_c(lu->ispec, &lu->A, lu->perm_c);
268     lu->SuperluMatOdering = PETSC_TRUE;
269   }
270   PetscOptionsEnd();
271 
272   /* Create the elimination tree */
273   ierr = PetscMalloc(A->n*sizeof(int),&etree);CHKERRQ(ierr);
274   sp_preorder("N",&lu->A,lu->perm_c,etree,&lu->AC);
275   /* Factor the matrix */
276 #if defined(PETSC_USE_COMPLEX)
277   zgstrf("N",&lu->AC,lu->pivot_threshold,0.0,lu->relax,lu->panel_size,etree,PETSC_NULL,0,lu->perm_r,lu->perm_c,&lu->L,&lu->U,&ierr);
278 #else
279   dgstrf("N",&lu->AC,lu->pivot_threshold,0.0,lu->relax,lu->panel_size,etree,PETSC_NULL,0,lu->perm_r,lu->perm_c,&lu->L,&lu->U,&ierr);
280 #endif
281   if (ierr < 0) {
282     SETERRQ1(PETSC_ERR_ARG_WRONG,"The diagonal element of row %d was invalid",-ierr);
283   } else if (ierr > 0) {
284     if (ierr <= A->m) {
285       SETERRQ1(PETSC_ERR_ARG_WRONG,"The diagonal element %d of U is exactly zero",ierr);
286     } else {
287       SETERRQ1(PETSC_ERR_ARG_WRONG,"Memory allocation failure after %d bytes were allocated",ierr-A->m);
288     }
289   }
290 
291   /* Cleanup */
292   ierr = PetscFree(etree);CHKERRQ(ierr);
293 
294   lu->flg = SAME_NONZERO_PATTERN;
295   PetscFunctionReturn(0);
296 }
297 
298 /*
299    Note the r permutation is ignored
300 */
301 #undef __FUNCT__
302 #define __FUNCT__ "MatLUFactorSymbolic_SuperLU"
303 int MatLUFactorSymbolic_SuperLU(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F)
304 {
305   Mat                 B;
306   Mat_SuperLU  *lu;
307   int                 ierr,*ca;
308 
309   PetscFunctionBegin;
310 
311   ierr = MatCreate(A->comm,A->m,A->n,PETSC_DETERMINE,PETSC_DETERMINE,&B);CHKERRQ(ierr);
312   ierr = MatSetType(B,MATSUPERLU);CHKERRQ(ierr);
313   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
314 
315   B->ops->lufactornumeric = MatLUFactorNumeric_SuperLU;
316   B->ops->solve           = MatSolve_SuperLU;
317   B->factor               = FACTOR_LU;
318   B->assembled            = PETSC_TRUE;  /* required by -sles_view */
319 
320   lu = (Mat_SuperLU*)(B->spptr);
321   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatCreateNull","MatCreateNull_SuperLU",
322                                     (void(*)(void))MatCreateNull_SuperLU);CHKERRQ(ierr);
323 
324   /* Allocate the work arrays required by SuperLU (notice sizes are for the transpose) */
325   ierr = PetscMalloc(A->n*sizeof(int),&lu->perm_r);CHKERRQ(ierr);
326   ierr = PetscMalloc(A->m*sizeof(int),&lu->perm_c);CHKERRQ(ierr);
327 
328   /* use PETSc mat ordering */
329   ierr = ISGetIndices(c,&ca);CHKERRQ(ierr);
330   ierr = PetscMemcpy(lu->perm_c,ca,A->m*sizeof(int));CHKERRQ(ierr);
331   ierr = ISRestoreIndices(c,&ca);CHKERRQ(ierr);
332   lu->SuperluMatOdering = PETSC_FALSE;
333 
334   lu->pivot_threshold = info->dtcol;
335   PetscLogObjectMemory(B,(A->m+A->n)*sizeof(int)+sizeof(Mat_SuperLU));
336 
337   lu->flg            = DIFFERENT_NONZERO_PATTERN;
338   lu->CleanUpSuperLU = PETSC_TRUE;
339 
340   *F = B;
341   PetscFunctionReturn(0);
342 }
343 
344 /* used by -sles_view */
345 #undef __FUNCT__
346 #define __FUNCT__ "MatFactorInfo_SuperLU"
347 int MatFactorInfo_SuperLU(Mat A,PetscViewer viewer)
348 {
349   Mat_SuperLU *lu= (Mat_SuperLU*)A->spptr;
350   int         ierr;
351 
352   PetscFunctionBegin;
353   ierr = PetscViewerASCIIPrintf(viewer,"SuperLU run parameters:\n");CHKERRQ(ierr);
354   if(lu->SuperluMatOdering) {
355     ierr = PetscViewerASCIIPrintf(viewer,"  SuperLU mat ordering: %d\n",lu->ispec);CHKERRQ(ierr);
356   }
357   PetscFunctionReturn(0);
358 }
359 
360 #undef __FUNCT__
361 #define __FUNCT__ "MatDuplicate_SuperLU"
362 int MatDuplicate_SuperLU(Mat A, MatDuplicateOption op, Mat *M) {
363   int         ierr;
364   Mat_SuperLU *lu=(Mat_SuperLU *)A->spptr;
365 
366   PetscFunctionBegin;
367   ierr = (*lu->MatDuplicate)(A,op,M);CHKERRQ(ierr);
368   ierr = MatConvert_SeqAIJ_SuperLU(*M,MATSUPERLU,M);CHKERRQ(ierr);
369   ierr = PetscMemcpy((*M)->spptr,lu,sizeof(Mat_SuperLU));CHKERRQ(ierr);
370   PetscFunctionReturn(0);
371 }
372 
373 EXTERN_C_BEGIN
374 #undef __FUNCT__
375 #define __FUNCT__ "MatConvert_SuperLU_SeqAIJ"
376 int MatConvert_SuperLU_SeqAIJ(Mat A,MatType type,Mat *newmat) {
377   /* This routine is only called to convert an unfactored PETSc-SuperLU matrix */
378   /* to its base PETSc type, so we will ignore 'MatType type'. */
379   int                  ierr;
380   Mat                  B=*newmat;
381   Mat_SuperLU   *lu=(Mat_SuperLU *)A->spptr;
382 
383   PetscFunctionBegin;
384   if (B != A) {
385     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
386   }
387   /* Reset the original function pointers */
388   B->ops->duplicate        = lu->MatDuplicate;
389   B->ops->view             = lu->MatView;
390   B->ops->assemblyend      = lu->MatAssemblyEnd;
391   B->ops->lufactorsymbolic = lu->MatLUFactorSymbolic;
392   B->ops->destroy          = lu->MatDestroy;
393   /* lu is only a function pointer stash unless we've factored the matrix, which we haven't! */
394   ierr = PetscFree(lu);CHKERRQ(ierr);
395   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
396   *newmat = B;
397   PetscFunctionReturn(0);
398 }
399 EXTERN_C_END
400 
401 EXTERN_C_BEGIN
402 #undef __FUNCT__
403 #define __FUNCT__ "MatConvert_SeqAIJ_SuperLU"
404 int MatConvert_SeqAIJ_SuperLU(Mat A,MatType type,Mat *newmat) {
405   /* This routine is only called to convert to MATSUPERLU */
406   /* from MATSEQAIJ, so we will ignore 'MatType type'. */
407   int         ierr;
408   Mat         B=*newmat;
409   Mat_SuperLU *lu;
410 
411   PetscFunctionBegin;
412   if (B != A) {
413     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
414   }
415 
416   ierr = PetscNew(Mat_SuperLU,&lu);CHKERRQ(ierr);
417   lu->MatDuplicate         = A->ops->duplicate;
418   lu->MatView              = A->ops->view;
419   lu->MatAssemblyEnd       = A->ops->assemblyend;
420   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
421   lu->MatDestroy           = A->ops->destroy;
422   lu->CleanUpSuperLU       = PETSC_FALSE;
423 
424   B->spptr                 = (void*)lu;
425   B->ops->duplicate        = MatDuplicate_SuperLU;
426   B->ops->view             = MatView_SuperLU;
427   B->ops->assemblyend      = MatAssemblyEnd_SuperLU;
428   B->ops->lufactorsymbolic = MatLUFactorSymbolic_SuperLU;
429   B->ops->destroy          = MatDestroy_SuperLU;
430 
431   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_superlu_C",
432                                            "MatConvert_SeqAIJ_SuperLU",MatConvert_SeqAIJ_SuperLU);CHKERRQ(ierr);
433   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_superlu_seqaij_C",
434                                            "MatConvert_SuperLU_SeqAIJ",MatConvert_SuperLU_SeqAIJ);CHKERRQ(ierr);
435   PetscLogInfo(0,"Using SuperLU for SeqAIJ LU factorization and solves.");
436   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSUPERLU);CHKERRQ(ierr);
437   *newmat = B;
438   PetscFunctionReturn(0);
439 }
440 EXTERN_C_END
441 
442 /*MC
443   MATSUPERLU - MATSUPERLU = "superlu" - A matrix type providing direct solvers (LU) for sequential matrices
444   via the external package SuperLU.
445 
446   If SuperLU is installed (see the manual for
447   instructions on how to declare the existence of external packages),
448   a matrix type can be constructed which invokes SuperLU solvers.
449   After calling MatCreate(...,A), simply call MatSetType(A,MATSUPERLU).
450   This matrix type is only supported for double precision real.
451 
452   This matrix inherits from MATSEQAIJ.  As a result, MatSeqAIJSetPreallocation is
453   supported for this matrix type.  One can also call MatConvert for an inplace conversion to or from
454   the MATSEQAIJ type without data copy.
455 
456   Options Database Keys:
457 + -mat_type superlu - sets the matrix type to "superlu" during a call to MatSetFromOptions()
458 - -mat_superlu_ordering <0,1,2,3> - 0: natural ordering,
459                                     1: MMD applied to A'*A,
460                                     2: MMD applied to A'+A,
461                                     3: COLAMD, approximate minimum degree column ordering
462 
463    Level: beginner
464 
465 .seealso: PCLU
466 M*/
467 
468 EXTERN_C_BEGIN
469 #undef __FUNCT__
470 #define __FUNCT__ "MatCreate_SuperLU"
471 int MatCreate_SuperLU(Mat A) {
472   int ierr;
473 
474   PetscFunctionBegin;
475   /* Change type name before calling MatSetType to force proper construction of SeqAIJ and SUPERLU types */
476   ierr = PetscObjectChangeTypeName((PetscObject)A,MATSUPERLU);CHKERRQ(ierr);
477   ierr = MatSetType(A,MATSEQAIJ);CHKERRQ(ierr);
478   ierr = MatConvert_SeqAIJ_SuperLU(A,MATSUPERLU,&A);CHKERRQ(ierr);
479   PetscFunctionReturn(0);
480 }
481 EXTERN_C_END
482