xref: /petsc/src/mat/impls/aij/seq/lusol/lusol.c (revision 72ce74bd30d5d09d1371a3eb387704f4af395d1a)
1 /*
2         Provides an interface to the LUSOL package of ....
3 
4 */
5 #include "src/mat/impls/aij/seq/aij.h"
6 
7 #if defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
8 #define LU1FAC   lu1fac_
9 #define LU6SOL   lu6sol_
10 #define M1PAGE   m1page_
11 #define M5SETX   m5setx_
12 #define M6RDEL   m6rdel_
13 #elif !defined(PETSC_HAVE_FORTRAN_CAPS)
14 #define LU1FAC   lu1fac
15 #define LU6SOL   lu6sol
16 #define M1PAGE   m1page
17 #define M5SETX   m5setx
18 #define M6RDEL   m6rdel
19 #endif
20 
21 EXTERN_C_BEGIN
22 /*
23     Dummy symbols that the MINOS files mi25bfac.f and mi15blas.f may require
24 */
25 void PETSC_STDCALL M1PAGE() {
26   ;
27 }
28 void PETSC_STDCALL M5SETX() {
29   ;
30 }
31 
32 void PETSC_STDCALL M6RDEL() {
33   ;
34 }
35 
36 extern void PETSC_STDCALL LU1FAC (int *m, int *n, int *nnz, int *size, int *luparm,
37                         double *parmlu, double *data, int *indc, int *indr,
38                         int *rowperm, int *colperm, int *collen, int *rowlen,
39                         int *colstart, int *rowstart, int *rploc, int *cploc,
40                         int *rpinv, int *cpinv, double *w, int *inform);
41 
42 extern void PETSC_STDCALL LU6SOL (int *mode, int *m, int *n, double *rhs, double *x,
43                         int *size, int *luparm, double *parmlu, double *data,
44                         int *indc, int *indr, int *rowperm, int *colperm,
45                         int *collen, int *rowlen, int *colstart, int *rowstart,
46                         int *inform);
47 EXTERN_C_END
48 
49 EXTERN PetscErrorCode MatDuplicate_LUSOL(Mat,MatDuplicateOption,Mat*);
50 
51 typedef struct  {
52   double *data;
53   int *indc;
54   int *indr;
55 
56   int *ip;
57   int *iq;
58   int *lenc;
59   int *lenr;
60   int *locc;
61   int *locr;
62   int *iploc;
63   int *iqloc;
64   int *ipinv;
65   int *iqinv;
66   double *mnsw;
67   double *mnsv;
68 
69   double elbowroom;
70   double luroom;		/* Extra space allocated when factor fails   */
71   double parmlu[30];		/* Input/output to LUSOL                     */
72 
73   int n;			/* Number of rows/columns in matrix          */
74   int nz;			/* Number of nonzeros                        */
75   int nnz;			/* Number of nonzeros allocated for factors  */
76   int luparm[30];		/* Input/output to LUSOL                     */
77 
78   int (*MatDuplicate)(Mat,MatDuplicateOption,Mat*);
79   int (*MatLUFactorSymbolic)(Mat,IS,IS,MatFactorInfo*,Mat*);
80   int (*MatDestroy)(Mat);
81   PetscTruth CleanUpLUSOL;
82 
83 } Mat_LUSOL;
84 
85 /*  LUSOL input/Output Parameters (Description uses C-style indexes
86  *
87  *  Input parameters                                        Typical value
88  *
89  *  luparm(0) = nout     File number for printed messages.         6
90  *  luparm(1) = lprint   Print level.                              0
91  *                    < 0 suppresses output.
92  *                    = 0 gives error messages.
93  *                    = 1 gives debug output from some of the
94  *                        other routines in LUSOL.
95  *                   >= 2 gives the pivot row and column and the
96  *                        no. of rows and columns involved at
97  *                        each elimination step in lu1fac.
98  *  luparm(2) = maxcol   lu1fac: maximum number of columns         5
99  *                        searched allowed in a Markowitz-type
100  *                        search for the next pivot element.
101  *                        For some of the factorization, the
102  *                        number of rows searched is
103  *                        maxrow = maxcol - 1.
104  *
105  *
106  *  Output parameters
107  *
108  *  luparm(9) = inform   Return code from last call to any LU routine.
109  *  luparm(10) = nsing    No. of singularities marked in the
110  *                        output array w(*).
111  *  luparm(11) = jsing    Column index of last singularity.
112  *  luparm(12) = minlen   Minimum recommended value for  lena.
113  *  luparm(13) = maxlen   ?
114  *  luparm(14) = nupdat   No. of updates performed by the lu8 routines.
115  *  luparm(15) = nrank    No. of nonempty rows of U.
116  *  luparm(16) = ndens1   No. of columns remaining when the density of
117  *                        the matrix being factorized reached dens1.
118  *  luparm(17) = ndens2   No. of columns remaining when the density of
119  *                        the matrix being factorized reached dens2.
120  *  luparm(18) = jumin    The column index associated with dumin.
121  *  luparm(19) = numl0    No. of columns in initial  L.
122  *  luparm(20) = lenl0    Size of initial  L  (no. of nonzeros).
123  *  luparm(21) = lenu0    Size of initial  U.
124  *  luparm(22) = lenl     Size of current  L.
125  *  luparm(23) = lenu     Size of current  U.
126  *  luparm(24) = lrow     Length of row file.
127  *  luparm(25) = ncp      No. of compressions of LU data structures.
128  *  luparm(26) = mersum   lu1fac: sum of Markowitz merit counts.
129  *  luparm(27) = nutri    lu1fac: triangular rows in U.
130  *  luparm(28) = nltri    lu1fac: triangular rows in L.
131  *  luparm(29) =
132  *
133  *
134  *  Input parameters                                        Typical value
135  *
136  *  parmlu(0) = elmax1   Max multiplier allowed in  L           10.0
137  *                        during factor.
138  *  parmlu(1) = elmax2   Max multiplier allowed in  L           10.0
139  *                        during updates.
140  *  parmlu(2) = small    Absolute tolerance for             eps**0.8
141  *                        treating reals as zero.     IBM double: 3.0d-13
142  *  parmlu(3) = utol1    Absolute tol for flagging          eps**0.66667
143  *                        small diagonals of U.       IBM double: 3.7d-11
144  *  parmlu(4) = utol2    Relative tol for flagging          eps**0.66667
145  *                        small diagonals of U.       IBM double: 3.7d-11
146  *  parmlu(5) = uspace   Factor limiting waste space in  U.      3.0
147  *                        In lu1fac, the row or column lists
148  *                        are compressed if their length
149  *                        exceeds uspace times the length of
150  *                        either file after the last compression.
151  *  parmlu(6) = dens1    The density at which the Markowitz      0.3
152  *                        strategy should search maxcol columns
153  *                        and no rows.
154  *  parmlu(7) = dens2    the density at which the Markowitz      0.6
155  *                        strategy should search only 1 column
156  *                        or (preferably) use a dense LU for
157  *                        all the remaining rows and columns.
158  *
159  *
160  *  Output parameters
161  *
162  *  parmlu(9) = amax     Maximum element in  A.
163  *  parmlu(10) = elmax    Maximum multiplier in current  L.
164  *  parmlu(11) = umax     Maximum element in current  U.
165  *  parmlu(12) = dumax    Maximum diagonal in  U.
166  *  parmlu(13) = dumin    Minimum diagonal in  U.
167  *  parmlu(14) =
168  *  parmlu(15) =
169  *  parmlu(16) =
170  *  parmlu(17) =
171  *  parmlu(18) =
172  *  parmlu(19) = resid    lu6sol: residual after solve with U or U'.
173  *  ...
174  *  parmlu(29) =
175  */
176 
177 #define Factorization_Tolerance       1e-1
178 #define Factorization_Pivot_Tolerance pow(2.2204460492503131E-16, 2.0 / 3.0)
179 #define Factorization_Small_Tolerance 1e-15 /* pow(DBL_EPSILON, 0.8) */
180 
181 EXTERN_C_BEGIN
182 #undef __FUNCT__
183 #define __FUNCT__ "MatConvert_LUSOL_SeqAIJ"
184 PetscErrorCode MatConvert_LUSOL_SeqAIJ(Mat A,const MatType type,Mat *newmat) {
185   /* This routine is only called to convert an unfactored PETSc-LUSOL matrix */
186   /* to its base PETSc type, so we will ignore 'MatType type'. */
187   PetscErrorCode ierr;
188   Mat       B=*newmat;
189   Mat_LUSOL *lusol=(Mat_LUSOL *)A->spptr;
190 
191   PetscFunctionBegin;
192   if (B != A) {
193     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
194   }
195   B->ops->duplicate        = lusol->MatDuplicate;
196   B->ops->lufactorsymbolic = lusol->MatLUFactorSymbolic;
197   B->ops->destroy          = lusol->MatDestroy;
198 
199   ierr = PetscFree(lusol);CHKERRQ(ierr);
200   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
201   *newmat = B;
202   PetscFunctionReturn(0);
203 }
204 EXTERN_C_END
205 
206 #undef __FUNCT__
207 #define __FUNCT__ "MatDestroy_LUSOL"
208 PetscErrorCode MatDestroy_LUSOL(Mat A)
209 {
210   PetscErrorCode ierr;
211   Mat_LUSOL *lusol=(Mat_LUSOL *)A->spptr;
212 
213   PetscFunctionBegin;
214   if (lusol->CleanUpLUSOL) {
215     ierr = PetscFree(lusol->ip);CHKERRQ(ierr);
216     ierr = PetscFree(lusol->iq);CHKERRQ(ierr);
217     ierr = PetscFree(lusol->lenc);CHKERRQ(ierr);
218     ierr = PetscFree(lusol->lenr);CHKERRQ(ierr);
219     ierr = PetscFree(lusol->locc);CHKERRQ(ierr);
220     ierr = PetscFree(lusol->locr);CHKERRQ(ierr);
221     ierr = PetscFree(lusol->iploc);CHKERRQ(ierr);
222     ierr = PetscFree(lusol->iqloc);CHKERRQ(ierr);
223     ierr = PetscFree(lusol->ipinv);CHKERRQ(ierr);
224     ierr = PetscFree(lusol->iqinv);CHKERRQ(ierr);
225     ierr = PetscFree(lusol->mnsw);CHKERRQ(ierr);
226     ierr = PetscFree(lusol->mnsv);CHKERRQ(ierr);
227 
228     ierr = PetscFree(lusol->indc);CHKERRQ(ierr);
229   }
230 
231   ierr = MatConvert_LUSOL_SeqAIJ(A,MATSEQAIJ,&A);
232   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
233   PetscFunctionReturn(0);
234 }
235 
236 #undef __FUNCT__
237 #define __FUNCT__  "MatSolve_LUSOL"
238 PetscErrorCode MatSolve_LUSOL(Mat A,Vec b,Vec x) {
239   Mat_LUSOL *lusol=(Mat_LUSOL*)A->spptr;
240   double    *bb,*xx;
241   int       mode=5;
242   int       i,m,n,nnz,status,ierr;
243 
244   PetscFunctionBegin;
245   ierr = VecGetArray(x, &xx);CHKERRQ(ierr);
246   ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
247 
248   m = n = lusol->n;
249   nnz = lusol->nnz;
250 
251   for (i = 0; i < m; i++)
252     {
253       lusol->mnsv[i] = bb[i];
254     }
255 
256   LU6SOL(&mode, &m, &n, lusol->mnsv, xx, &nnz,
257          lusol->luparm, lusol->parmlu, lusol->data,
258          lusol->indc, lusol->indr, lusol->ip, lusol->iq,
259          lusol->lenc, lusol->lenr, lusol->locc, lusol->locr, &status);
260 
261   if (status != 0)
262     {
263       SETERRQ(PETSC_ERR_ARG_SIZ,"solve failed");
264     }
265 
266   ierr = VecRestoreArray(x, &xx);CHKERRQ(ierr);
267   ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
268   PetscFunctionReturn(0);
269 }
270 
271 #undef __FUNCT__
272 #define __FUNCT__ "MatLUFactorNumeric_LUSOL"
273 PetscErrorCode MatLUFactorNumeric_LUSOL(Mat A, Mat *F) {
274   Mat_SeqAIJ *a;
275   Mat_LUSOL  *lusol = (Mat_LUSOL*)(*F)->spptr;
276   int        m, n, nz, nnz, status;
277   int        i, rs, re,ierr;
278   int        factorizations;
279 
280   PetscFunctionBegin;
281   ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);CHKERRQ(ierr);
282   a = (Mat_SeqAIJ *)A->data;
283 
284   if (m != lusol->n) {
285     SETERRQ(PETSC_ERR_ARG_SIZ,"factorization struct inconsistent");
286   }
287 
288   factorizations = 0;
289   do
290     {
291       /*******************************************************************/
292       /* Check the workspace allocation.                                 */
293       /*******************************************************************/
294 
295       nz = a->nz;
296       nnz = PetscMax(lusol->nnz, (int)(lusol->elbowroom*nz));
297       nnz = PetscMax(nnz, 5*n);
298 
299       if (nnz < lusol->luparm[12]){
300         nnz = (int)(lusol->luroom * lusol->luparm[12]);
301       } else if ((factorizations > 0) && (lusol->luroom < 6)){
302         lusol->luroom += 0.1;
303       }
304 
305       nnz = PetscMax(nnz, (int)(lusol->luroom*(lusol->luparm[22] + lusol->luparm[23])));
306 
307       if (nnz > lusol->nnz){
308         ierr = PetscFree(lusol->indc);CHKERRQ(ierr);
309         ierr        = PetscMalloc((sizeof(double)+2*sizeof(int))*nnz,&lusol->indc);CHKERRQ(ierr);
310         lusol->indr = lusol->indc + nnz;
311         lusol->data = (double *)(lusol->indr + nnz);
312         lusol->nnz  = nnz;
313       }
314 
315       /*******************************************************************/
316       /* Fill in the data for the problem.      (1-based Fortran style)  */
317       /*******************************************************************/
318 
319       nz = 0;
320       for (i = 0; i < n; i++)
321         {
322           rs = a->i[i];
323           re = a->i[i+1];
324 
325           while (rs < re)
326             {
327               if (a->a[rs] != 0.0)
328                 {
329                   lusol->indc[nz] = i + 1;
330                   lusol->indr[nz] = a->j[rs] + 1;
331                   lusol->data[nz] = a->a[rs];
332                   nz++;
333                 }
334               rs++;
335             }
336         }
337 
338       /*******************************************************************/
339       /* Do the factorization.                                           */
340       /*******************************************************************/
341 
342       LU1FAC(&m, &n, &nz, &nnz,
343              lusol->luparm, lusol->parmlu, lusol->data,
344              lusol->indc, lusol->indr, lusol->ip, lusol->iq,
345              lusol->lenc, lusol->lenr, lusol->locc, lusol->locr,
346              lusol->iploc, lusol->iqloc, lusol->ipinv,
347              lusol->iqinv, lusol->mnsw, &status);
348 
349       switch(status)
350         {
351         case 0:		/* factored */
352           break;
353 
354         case 7:		/* insufficient memory */
355           break;
356 
357         case 1:
358         case -1:		/* singular */
359           SETERRQ(1,"Singular matrix");
360 
361         case 3:
362         case 4:		/* error conditions */
363           SETERRQ(1,"matrix error");
364 
365         default:		/* unknown condition */
366           SETERRQ(1,"matrix unknown return code");
367         }
368 
369       factorizations++;
370     } while (status == 7);
371   (*F)->assembled = PETSC_TRUE;
372   PetscFunctionReturn(0);
373 }
374 
375 #undef __FUNCT__
376 #define __FUNCT__ "MatLUFactorSymbolic_LUSOL"
377 PetscErrorCode MatLUFactorSymbolic_LUSOL(Mat A, IS r, IS c,MatFactorInfo *info, Mat *F) {
378   /************************************************************************/
379   /* Input                                                                */
380   /*     A  - matrix to factor                                            */
381   /*     r  - row permutation (ignored)                                   */
382   /*     c  - column permutation (ignored)                                */
383   /*                                                                      */
384   /* Output                                                               */
385   /*     F  - matrix storing the factorization;                           */
386   /************************************************************************/
387   Mat       B;
388   Mat_LUSOL *lusol;
389   PetscErrorCode ierr;
390   int        i, m, n, nz, nnz;
391 
392   PetscFunctionBegin;
393 
394   /************************************************************************/
395   /* Check the arguments.                                                 */
396   /************************************************************************/
397 
398   ierr = MatGetSize(A, &m, &n);CHKERRQ(ierr);
399   nz = ((Mat_SeqAIJ *)A->data)->nz;
400 
401   /************************************************************************/
402   /* Create the factorization.                                            */
403   /************************************************************************/
404 
405   ierr = MatCreate(A->comm,PETSC_DECIDE,PETSC_DECIDE,m,n,&B);CHKERRQ(ierr);
406   ierr = MatSetType(B,A->type_name);CHKERRQ(ierr);
407   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
408 
409   B->ops->lufactornumeric = MatLUFactorNumeric_LUSOL;
410   B->ops->solve           = MatSolve_LUSOL;
411   B->factor               = FACTOR_LU;
412   lusol                   = (Mat_LUSOL*)(B->spptr);
413 
414   /************************************************************************/
415   /* Initialize parameters                                                */
416   /************************************************************************/
417 
418   for (i = 0; i < 30; i++)
419     {
420       lusol->luparm[i] = 0;
421       lusol->parmlu[i] = 0;
422     }
423 
424   lusol->luparm[1] = -1;
425   lusol->luparm[2] = 5;
426   lusol->luparm[7] = 1;
427 
428   lusol->parmlu[0] = 1 / Factorization_Tolerance;
429   lusol->parmlu[1] = 1 / Factorization_Tolerance;
430   lusol->parmlu[2] = Factorization_Small_Tolerance;
431   lusol->parmlu[3] = Factorization_Pivot_Tolerance;
432   lusol->parmlu[4] = Factorization_Pivot_Tolerance;
433   lusol->parmlu[5] = 3.0;
434   lusol->parmlu[6] = 0.3;
435   lusol->parmlu[7] = 0.6;
436 
437   /************************************************************************/
438   /* Allocate the workspace needed by LUSOL.                              */
439   /************************************************************************/
440 
441   lusol->elbowroom = PetscMax(lusol->elbowroom, info->fill);
442   nnz = PetscMax((int)(lusol->elbowroom*nz), 5*n);
443 
444   lusol->n = n;
445   lusol->nz = nz;
446   lusol->nnz = nnz;
447   lusol->luroom = 1.75;
448 
449   ierr = PetscMalloc(sizeof(int)*n,&lusol->ip);
450   ierr = PetscMalloc(sizeof(int)*n,&lusol->iq);
451   ierr = PetscMalloc(sizeof(int)*n,&lusol->lenc);
452   ierr = PetscMalloc(sizeof(int)*n,&lusol->lenr);
453   ierr = PetscMalloc(sizeof(int)*n,&lusol->locc);
454   ierr = PetscMalloc(sizeof(int)*n,&lusol->locr);
455   ierr = PetscMalloc(sizeof(int)*n,&lusol->iploc);
456   ierr = PetscMalloc(sizeof(int)*n,&lusol->iqloc);
457   ierr = PetscMalloc(sizeof(int)*n,&lusol->ipinv);
458   ierr = PetscMalloc(sizeof(int)*n,&lusol->iqinv);
459   ierr = PetscMalloc(sizeof(double)*n,&lusol->mnsw);
460   ierr = PetscMalloc(sizeof(double)*n,&lusol->mnsv);
461 
462   ierr        = PetscMalloc((sizeof(double)+2*sizeof(int))*nnz,&lusol->indc);
463   lusol->indr = lusol->indc + nnz;
464   lusol->data = (double *)(lusol->indr + nnz);
465   lusol->CleanUpLUSOL = PETSC_TRUE;
466   *F = B;
467   PetscFunctionReturn(0);
468 }
469 
470 EXTERN_C_BEGIN
471 #undef __FUNCT__
472 #define __FUNCT__ "MatConvert_SeqAIJ_LUSOL"
473 PetscErrorCode MatConvert_SeqAIJ_LUSOL(Mat A,const MatType type,Mat *newmat) {
474   PetscErrorCode ierr;
475   int        m, n;
476   Mat_LUSOL *lusol;
477   Mat       B=*newmat;
478 
479   PetscFunctionBegin;
480   ierr = MatGetSize(A, &m, &n);CHKERRQ(ierr);
481   if (m != n) {
482     SETERRQ(PETSC_ERR_ARG_SIZ,"matrix must be square");
483   }
484   if (B != A) {
485     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
486   }
487 
488   ierr                       = PetscNew(Mat_LUSOL,&lusol);CHKERRQ(ierr);
489   lusol->MatDuplicate        = A->ops->duplicate;
490   lusol->MatLUFactorSymbolic = A->ops->lufactorsymbolic;
491   lusol->MatDestroy          = A->ops->destroy;
492   lusol->CleanUpLUSOL        = PETSC_FALSE;
493 
494   B->spptr                   = (void*)lusol;
495   B->ops->duplicate          = MatDuplicate_LUSOL;
496   B->ops->lufactorsymbolic   = MatLUFactorSymbolic_LUSOL;
497   B->ops->destroy            = MatDestroy_LUSOL;
498 
499   PetscLogInfo(0,"Using LUSOL for LU factorization and solves.");
500   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_lusol_C",
501                                            "MatConvert_SeqAIJ_LUSOL",MatConvert_SeqAIJ_LUSOL);CHKERRQ(ierr);
502   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_lusol_seqaij_C",
503                                            "MatConvert_LUSOL_SeqAIJ",MatConvert_LUSOL_SeqAIJ);CHKERRQ(ierr);
504   ierr = PetscObjectChangeTypeName((PetscObject)B,type);CHKERRQ(ierr);
505   *newmat = B;
506   PetscFunctionReturn(0);
507 }
508 EXTERN_C_END
509 
510 #undef __FUNCT__
511 #define __FUNCT__ "MatDuplicate_LUSOL"
512 PetscErrorCode MatDuplicate_LUSOL(Mat A, MatDuplicateOption op, Mat *M) {
513   PetscErrorCode ierr;
514   Mat_LUSOL *lu=(Mat_LUSOL *)A->spptr;
515   PetscFunctionBegin;
516   ierr = (*lu->MatDuplicate)(A,op,M);CHKERRQ(ierr);
517   ierr = PetscMemcpy((*M)->spptr,lu,sizeof(Mat_LUSOL));CHKERRQ(ierr);
518   PetscFunctionReturn(0);
519 }
520 
521 /*MC
522   MATLUSOL - MATLUSOL = "lusol" - A matrix type providing direct solvers (LU) for sequential matrices
523   via the external package LUSOL.
524 
525   If LUSOL is installed (see the manual for
526   instructions on how to declare the existence of external packages),
527   a matrix type can be constructed which invokes LUSOL solvers.
528   After calling MatCreate(...,A), simply call MatSetType(A,MATLUSOL).
529   This matrix type is only supported for double precision real.
530 
531   This matrix inherits from MATSEQAIJ.  As a result, MatSeqAIJSetPreallocation is
532   supported for this matrix type.  MatConvert can be called for a fast inplace conversion
533   to and from the MATSEQAIJ matrix type.
534 
535   Options Database Keys:
536 . -mat_type lusol - sets the matrix type to "lusol" during a call to MatSetFromOptions()
537 
538    Level: beginner
539 
540 .seealso: PCLU
541 M*/
542 
543 EXTERN_C_BEGIN
544 #undef __FUNCT__
545 #define __FUNCT__ "MatCreate_LUSOL"
546 PetscErrorCode MatCreate_LUSOL(Mat A)
547 {
548   PetscErrorCode ierr;
549 
550   PetscFunctionBegin;
551   /* Change type name before calling MatSetType to force proper construction of SeqAIJ and LUSOL types */
552   ierr = PetscObjectChangeTypeName((PetscObject)A,MATLUSOL);CHKERRQ(ierr);
553   ierr = MatSetType(A,MATSEQAIJ);CHKERRQ(ierr);
554   ierr = MatConvert_SeqAIJ_LUSOL(A,MATLUSOL,&A);CHKERRQ(ierr);
555   PetscFunctionReturn(0);
556 }
557 EXTERN_C_END
558