xref: /petsc/src/mat/impls/aij/seq/superlu/superlu.c (revision 1a2e2f443b0dd18e9f46e022a6b50ee3d44d0c82)
1be1d678aSKris Buschelman #define PETSCMAT_DLL
214b396bbSKris Buschelman 
35a46d3faSBarry Smith /*  --------------------------------------------------------------------
45a46d3faSBarry Smith 
55a46d3faSBarry Smith      This file implements a subclass of the SeqAIJ matrix class that uses
65d8b2efaSHong Zhang      the SuperLU sparse solver. You can use this as a starting point for
75a46d3faSBarry Smith      implementing your own subclass of a PETSc matrix class.
85a46d3faSBarry Smith 
95a46d3faSBarry Smith      This demonstrates a way to make an implementation inheritence of a PETSc
105a46d3faSBarry Smith      matrix type. This means constructing a new matrix type (SuperLU) by changing some
115a46d3faSBarry Smith      of the methods of the previous type (SeqAIJ), adding additional data, and possibly
125a46d3faSBarry Smith      additional method. (See any book on object oriented programming).
1314b396bbSKris Buschelman */
1414b396bbSKris Buschelman 
155a46d3faSBarry Smith /*
165a46d3faSBarry Smith      Defines the data structure for the base matrix type (SeqAIJ)
175a46d3faSBarry Smith */
187c4f633dSBarry Smith #include "../src/mat/impls/aij/seq/aij.h"
1914b396bbSKris Buschelman 
205a46d3faSBarry Smith /*
215a46d3faSBarry Smith      SuperLU include files
225a46d3faSBarry Smith */
2314b396bbSKris Buschelman EXTERN_C_BEGIN
2414b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
2566f57492SHong Zhang #include "slu_zdefs.h"
2614b396bbSKris Buschelman #else
2766f57492SHong Zhang #include "slu_ddefs.h"
2814b396bbSKris Buschelman #endif
2966f57492SHong Zhang #include "slu_util.h"
3014b396bbSKris Buschelman EXTERN_C_END
3114b396bbSKris Buschelman 
325a46d3faSBarry Smith /*
335a46d3faSBarry Smith      This is the data we are "ADDING" to the SeqAIJ matrix type to get the SuperLU matrix type
345a46d3faSBarry Smith */
3514b396bbSKris Buschelman typedef struct {
3675af56d4SHong Zhang   SuperMatrix       A,L,U,B,X;
3775af56d4SHong Zhang   superlu_options_t options;
38da7a1d00SHong Zhang   PetscInt          *perm_c; /* column permutation vector */
39da7a1d00SHong Zhang   PetscInt          *perm_r; /* row permutations from partial pivoting */
40da7a1d00SHong Zhang   PetscInt          *etree;
41da7a1d00SHong Zhang   PetscReal         *R, *C;
4275af56d4SHong Zhang   char              equed[1];
43da7a1d00SHong Zhang   PetscInt          lwork;
4475af56d4SHong Zhang   void              *work;
45da7a1d00SHong Zhang   PetscReal         rpg, rcond;
4675af56d4SHong Zhang   mem_usage_t       mem_usage;
4775af56d4SHong Zhang   MatStructure      flg;
485d8b2efaSHong Zhang   SuperLUStat_t     stat;
4914b396bbSKris Buschelman 
5014b396bbSKris Buschelman   /* Flag to clean up (non-global) SuperLU objects during Destroy */
5114b396bbSKris Buschelman   PetscTruth CleanUpSuperLU;
52f0c56d0fSKris Buschelman } Mat_SuperLU;
5314b396bbSKris Buschelman 
54e0e586b9SHong Zhang extern PetscErrorCode MatFactorInfo_SuperLU(Mat,PetscViewer);
550481f469SBarry Smith extern PetscErrorCode MatLUFactorNumeric_SuperLU(Mat,Mat,const MatFactorInfo *);
56e0e586b9SHong Zhang extern PetscErrorCode MatDestroy_SuperLU(Mat);
57e0e586b9SHong Zhang extern PetscErrorCode MatView_SuperLU(Mat,PetscViewer);
58e0e586b9SHong Zhang extern PetscErrorCode MatAssemblyEnd_SuperLU(Mat,MatAssemblyType);
59e0e586b9SHong Zhang extern PetscErrorCode MatSolve_SuperLU(Mat,Vec,Vec);
60e0e586b9SHong Zhang extern PetscErrorCode MatSolveTranspose_SuperLU(Mat,Vec,Vec);
610481f469SBarry Smith extern PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat,Mat,IS,IS,const MatFactorInfo*);
62e0e586b9SHong Zhang extern PetscErrorCode MatDuplicate_SuperLU(Mat, MatDuplicateOption, Mat *);
63e0e586b9SHong Zhang 
645a46d3faSBarry Smith /*
655a46d3faSBarry Smith     Utility function
665a46d3faSBarry Smith */
675a46d3faSBarry Smith #undef __FUNCT__
685a46d3faSBarry Smith #define __FUNCT__ "MatFactorInfo_SuperLU"
695a46d3faSBarry Smith PetscErrorCode MatFactorInfo_SuperLU(Mat A,PetscViewer viewer)
705a46d3faSBarry Smith {
715a46d3faSBarry Smith   Mat_SuperLU       *lu= (Mat_SuperLU*)A->spptr;
725a46d3faSBarry Smith   PetscErrorCode    ierr;
735a46d3faSBarry Smith   superlu_options_t options;
745a46d3faSBarry Smith 
755a46d3faSBarry Smith   PetscFunctionBegin;
765a46d3faSBarry Smith   /* check if matrix is superlu_dist type */
775a46d3faSBarry Smith   if (A->ops->solve != MatSolve_SuperLU) PetscFunctionReturn(0);
785a46d3faSBarry Smith 
795a46d3faSBarry Smith   options = lu->options;
805a46d3faSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"SuperLU run parameters:\n");CHKERRQ(ierr);
815a46d3faSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  Equil: %s\n",(options.Equil != NO) ? "YES": "NO");CHKERRQ(ierr);
825a46d3faSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  ColPerm: %D\n",options.ColPerm);CHKERRQ(ierr);
835a46d3faSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  IterRefine: %D\n",options.IterRefine);CHKERRQ(ierr);
845a46d3faSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  SymmetricMode: %s\n",(options.SymmetricMode != NO) ? "YES": "NO");CHKERRQ(ierr);
855a46d3faSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  DiagPivotThresh: %g\n",options.DiagPivotThresh);CHKERRQ(ierr);
865a46d3faSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  PivotGrowth: %s\n",(options.PivotGrowth != NO) ? "YES": "NO");CHKERRQ(ierr);
875a46d3faSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  ConditionNumber: %s\n",(options.ConditionNumber != NO) ? "YES": "NO");CHKERRQ(ierr);
885a46d3faSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  RowPerm: %D\n",options.RowPerm);CHKERRQ(ierr);
895a46d3faSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  ReplaceTinyPivot: %s\n",(options.ReplaceTinyPivot != NO) ? "YES": "NO");CHKERRQ(ierr);
905a46d3faSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  PrintStat: %s\n",(options.PrintStat != NO) ? "YES": "NO");CHKERRQ(ierr);
915a46d3faSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  lwork: %D\n",lu->lwork);CHKERRQ(ierr);
92cffbb591SHong Zhang   if (A->factor == MAT_FACTOR_ILU){
93cffbb591SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  ILU_DropTol: %g\n",options.ILU_DropTol);CHKERRQ(ierr);
94cffbb591SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  ILU_FillTol: %g\n",options.ILU_FillTol);CHKERRQ(ierr);
95cffbb591SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  ILU_FillFactor: %g\n",options.ILU_FillFactor);CHKERRQ(ierr);
96cffbb591SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  ILU_DropRule: %D\n",options.ILU_DropRule);CHKERRQ(ierr);
97cffbb591SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  ILU_Norm: %D\n",options.ILU_Norm);CHKERRQ(ierr);
98cffbb591SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  ILU_MILU: %D\n",options.ILU_MILU);CHKERRQ(ierr);
99cffbb591SHong Zhang   }
1005a46d3faSBarry Smith   PetscFunctionReturn(0);
1015a46d3faSBarry Smith }
1025a46d3faSBarry Smith 
1035a46d3faSBarry Smith /*
1045a46d3faSBarry Smith     These are the methods provided to REPLACE the corresponding methods of the
1055a46d3faSBarry Smith    SeqAIJ matrix class. Other methods of SeqAIJ are not replaced
1065a46d3faSBarry Smith */
1075a46d3faSBarry Smith #undef __FUNCT__
1085a46d3faSBarry Smith #define __FUNCT__ "MatLUFactorNumeric_SuperLU"
1090481f469SBarry Smith PetscErrorCode MatLUFactorNumeric_SuperLU(Mat F,Mat A,const MatFactorInfo *info)
1105a46d3faSBarry Smith {
1115a46d3faSBarry Smith   Mat_SeqAIJ     *aa = (Mat_SeqAIJ*)(A)->data;
112719d5645SBarry Smith   Mat_SuperLU    *lu = (Mat_SuperLU*)(F)->spptr;
1135a46d3faSBarry Smith   PetscErrorCode ierr;
1145a46d3faSBarry Smith   PetscInt       sinfo;
1155a46d3faSBarry Smith   PetscReal      ferr, berr;
1165a46d3faSBarry Smith   NCformat       *Ustore;
1175a46d3faSBarry Smith   SCformat       *Lstore;
1185a46d3faSBarry Smith 
1195a46d3faSBarry Smith   PetscFunctionBegin;
1205a46d3faSBarry Smith   if (lu->flg == SAME_NONZERO_PATTERN){ /* successing numerical factorization */
1215a46d3faSBarry Smith     lu->options.Fact = SamePattern;
1225a46d3faSBarry Smith     /* Ref: ~SuperLU_3.0/EXAMPLE/dlinsolx2.c */
1235a46d3faSBarry Smith     Destroy_SuperMatrix_Store(&lu->A);
1245a46d3faSBarry Smith     if ( lu->lwork >= 0 ) {
1255a46d3faSBarry Smith       Destroy_SuperNode_Matrix(&lu->L);
1265a46d3faSBarry Smith       Destroy_CompCol_Matrix(&lu->U);
1275a46d3faSBarry Smith       lu->options.Fact = SamePattern;
1285a46d3faSBarry Smith     }
1295a46d3faSBarry Smith   }
1305a46d3faSBarry Smith 
1315a46d3faSBarry Smith   /* Create the SuperMatrix for lu->A=A^T:
1325a46d3faSBarry Smith        Since SuperLU likes column-oriented matrices,we pass it the transpose,
1335a46d3faSBarry Smith        and then solve A^T X = B in MatSolve(). */
1345a46d3faSBarry Smith #if defined(PETSC_USE_COMPLEX)
135d0f46423SBarry Smith   zCreate_CompCol_Matrix(&lu->A,A->cmap->n,A->rmap->n,aa->nz,(doublecomplex*)aa->a,aa->j,aa->i,
1365a46d3faSBarry Smith                            SLU_NC,SLU_Z,SLU_GE);
1375a46d3faSBarry Smith #else
138d0f46423SBarry Smith   dCreate_CompCol_Matrix(&lu->A,A->cmap->n,A->rmap->n,aa->nz,aa->a,aa->j,aa->i,
1395a46d3faSBarry Smith                            SLU_NC,SLU_D,SLU_GE);
1405a46d3faSBarry Smith #endif
1415a46d3faSBarry Smith 
1425a46d3faSBarry Smith   /* Numerical factorization */
1435a46d3faSBarry Smith   lu->B.ncol = 0;  /* Indicate not to solve the system */
144cffbb591SHong Zhang   if (F->factor == MAT_FACTOR_LU){
1455a46d3faSBarry Smith #if defined(PETSC_USE_COMPLEX)
1465a46d3faSBarry Smith     zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
1475a46d3faSBarry Smith            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
1485d8b2efaSHong Zhang            &lu->mem_usage, &lu->stat, &sinfo);
1495a46d3faSBarry Smith #else
1505a46d3faSBarry Smith     dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
1515a46d3faSBarry Smith            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
1525d8b2efaSHong Zhang            &lu->mem_usage, &lu->stat, &sinfo);
1535a46d3faSBarry Smith #endif
154cffbb591SHong Zhang   } else if (F->factor == MAT_FACTOR_ILU){
155cffbb591SHong Zhang     /* Compute the incomplete factorization, condition number and pivot growth */
156cffbb591SHong Zhang #if defined(PETSC_USE_COMPLEX)
157cffbb591SHong Zhang     zgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r,lu->etree, lu->equed, lu->R, lu->C,
158cffbb591SHong Zhang            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond,
1595d8b2efaSHong Zhang            &lu->mem_usage, &lu->stat, &sinfo);
160cffbb591SHong Zhang #else
161cffbb591SHong Zhang     dgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
162cffbb591SHong Zhang           &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond,
1635d8b2efaSHong Zhang           &lu->mem_usage, &lu->stat, &sinfo);
164cffbb591SHong Zhang #endif
165cffbb591SHong Zhang   } else {
166cffbb591SHong Zhang     SETERRQ(PETSC_ERR_SUP,"Factor type not supported");
167cffbb591SHong Zhang   }
1685a46d3faSBarry Smith   if ( !sinfo || sinfo == lu->A.ncol+1 ) {
1695a46d3faSBarry Smith     if ( lu->options.PivotGrowth )
1705a46d3faSBarry Smith       ierr = PetscPrintf(PETSC_COMM_SELF,"  Recip. pivot growth = %e\n", lu->rpg);
1715a46d3faSBarry Smith     if ( lu->options.ConditionNumber )
1725a46d3faSBarry Smith       ierr = PetscPrintf(PETSC_COMM_SELF,"  Recip. condition number = %e\n", lu->rcond);
1735a46d3faSBarry Smith   } else if ( sinfo > 0 ){
1745a46d3faSBarry Smith     if ( lu->lwork == -1 ) {
1755a46d3faSBarry Smith       ierr = PetscPrintf(PETSC_COMM_SELF,"  ** Estimated memory: %D bytes\n", sinfo - lu->A.ncol);
1765a46d3faSBarry Smith     } else {
1775a46d3faSBarry Smith       ierr = PetscPrintf(PETSC_COMM_SELF,"  Warning: gssvx() returns info %D\n",sinfo);
1785a46d3faSBarry Smith     }
1795a46d3faSBarry Smith   } else { /* sinfo < 0 */
1805a46d3faSBarry Smith     SETERRQ2(PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", sinfo,-sinfo);
1815a46d3faSBarry Smith   }
1825a46d3faSBarry Smith 
1835a46d3faSBarry Smith   if ( lu->options.PrintStat ) {
1845a46d3faSBarry Smith     ierr = PetscPrintf(PETSC_COMM_SELF,"MatLUFactorNumeric_SuperLU():\n");
1855d8b2efaSHong Zhang     StatPrint(&lu->stat);
1865a46d3faSBarry Smith     Lstore = (SCformat *) lu->L.Store;
1875a46d3faSBarry Smith     Ustore = (NCformat *) lu->U.Store;
1885a46d3faSBarry Smith     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in factor L = %D\n", Lstore->nnz);
1895a46d3faSBarry Smith     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in factor U = %D\n", Ustore->nnz);
1905a46d3faSBarry Smith     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in L+U = %D\n", Lstore->nnz + Ustore->nnz - lu->A.ncol);
1916da386baSHong Zhang     ierr = PetscPrintf(PETSC_COMM_SELF,"  L\\U MB %.3f\ttotal MB needed %.3f\n",
1926da386baSHong Zhang 	       lu->mem_usage.for_lu/1e6, lu->mem_usage.total_needed/1e6);
1935a46d3faSBarry Smith   }
1945a46d3faSBarry Smith 
1955a46d3faSBarry Smith   lu->flg = SAME_NONZERO_PATTERN;
196719d5645SBarry Smith   (F)->ops->solve          = MatSolve_SuperLU;
197719d5645SBarry Smith   (F)->ops->solvetranspose = MatSolveTranspose_SuperLU;
1985a46d3faSBarry Smith   PetscFunctionReturn(0);
1995a46d3faSBarry Smith }
2005a46d3faSBarry Smith 
20114b396bbSKris Buschelman #undef __FUNCT__
202f0c56d0fSKris Buschelman #define __FUNCT__ "MatDestroy_SuperLU"
203dfbe8321SBarry Smith PetscErrorCode MatDestroy_SuperLU(Mat A)
20414b396bbSKris Buschelman {
205dfbe8321SBarry Smith   PetscErrorCode ierr;
206f0c56d0fSKris Buschelman   Mat_SuperLU    *lu=(Mat_SuperLU*)A->spptr;
20714b396bbSKris Buschelman 
20814b396bbSKris Buschelman   PetscFunctionBegin;
20975af56d4SHong Zhang   if (lu->CleanUpSuperLU) { /* Free the SuperLU datastructures */
21075af56d4SHong Zhang     Destroy_SuperMatrix_Store(&lu->A);
21175af56d4SHong Zhang     Destroy_SuperMatrix_Store(&lu->B);
21275af56d4SHong Zhang     Destroy_SuperMatrix_Store(&lu->X);
2135d8b2efaSHong Zhang     StatFree(&lu->stat);
2149ce50919SHong Zhang 
2159ce50919SHong Zhang     ierr = PetscFree(lu->etree);CHKERRQ(ierr);
2169ce50919SHong Zhang     ierr = PetscFree(lu->perm_r);CHKERRQ(ierr);
2179ce50919SHong Zhang     ierr = PetscFree(lu->perm_c);CHKERRQ(ierr);
2189ce50919SHong Zhang     ierr = PetscFree(lu->R);CHKERRQ(ierr);
2199ce50919SHong Zhang     ierr = PetscFree(lu->C);CHKERRQ(ierr);
22075af56d4SHong Zhang     if ( lu->lwork >= 0 ) {
221fb3e25aaSKris Buschelman       Destroy_SuperNode_Matrix(&lu->L);
222fb3e25aaSKris Buschelman       Destroy_CompCol_Matrix(&lu->U);
22375af56d4SHong Zhang     }
224fb3e25aaSKris Buschelman   }
225b24902e0SBarry Smith   ierr = MatDestroy_SeqAIJ(A);CHKERRQ(ierr);
22614b396bbSKris Buschelman   PetscFunctionReturn(0);
22714b396bbSKris Buschelman }
22814b396bbSKris Buschelman 
22914b396bbSKris Buschelman #undef __FUNCT__
230f0c56d0fSKris Buschelman #define __FUNCT__ "MatView_SuperLU"
231dfbe8321SBarry Smith PetscErrorCode MatView_SuperLU(Mat A,PetscViewer viewer)
23214b396bbSKris Buschelman {
233dfbe8321SBarry Smith   PetscErrorCode    ierr;
23432077d6dSBarry Smith   PetscTruth        iascii;
23514b396bbSKris Buschelman   PetscViewerFormat format;
23614b396bbSKris Buschelman 
23714b396bbSKris Buschelman   PetscFunctionBegin;
238b24902e0SBarry Smith   ierr = MatView_SeqAIJ(A,viewer);CHKERRQ(ierr);
23914b396bbSKris Buschelman 
24032077d6dSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
24132077d6dSBarry Smith   if (iascii) {
24214b396bbSKris Buschelman     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
2432f59403fSHong Zhang     if (format == PETSC_VIEWER_ASCII_INFO) {
244f0c56d0fSKris Buschelman       ierr = MatFactorInfo_SuperLU(A,viewer);CHKERRQ(ierr);
24514b396bbSKris Buschelman     }
24614b396bbSKris Buschelman   }
24714b396bbSKris Buschelman   PetscFunctionReturn(0);
24814b396bbSKris Buschelman }
24914b396bbSKris Buschelman 
25014b396bbSKris Buschelman 
25114b396bbSKris Buschelman #undef __FUNCT__
252c29e884eSHong Zhang #define __FUNCT__ "MatSolve_SuperLU_Private"
253c29e884eSHong Zhang PetscErrorCode MatSolve_SuperLU_Private(Mat A,Vec b,Vec x)
25414b396bbSKris Buschelman {
255f0c56d0fSKris Buschelman   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
25675af56d4SHong Zhang   PetscScalar    *barray,*xarray;
257dfbe8321SBarry Smith   PetscErrorCode ierr;
258da7a1d00SHong Zhang   PetscInt       info,i;
259da7a1d00SHong Zhang   PetscReal      ferr,berr;
26014b396bbSKris Buschelman 
26114b396bbSKris Buschelman   PetscFunctionBegin;
262937a6b0eSHong Zhang   if ( lu->lwork == -1 ) {
263937a6b0eSHong Zhang     PetscFunctionReturn(0);
264937a6b0eSHong Zhang   }
26575af56d4SHong Zhang   lu->B.ncol = 1;   /* Set the number of right-hand side */
26675af56d4SHong Zhang   ierr = VecGetArray(b,&barray);CHKERRQ(ierr);
26775af56d4SHong Zhang   ierr = VecGetArray(x,&xarray);CHKERRQ(ierr);
2685fe6150dSHong Zhang 
2695fe6150dSHong Zhang #if defined(PETSC_USE_COMPLEX)
2705fe6150dSHong Zhang   ((DNformat*)lu->B.Store)->nzval = (doublecomplex*)barray;
2715fe6150dSHong Zhang   ((DNformat*)lu->X.Store)->nzval = (doublecomplex*)xarray;
2725fe6150dSHong Zhang #else
2735fe6150dSHong Zhang   ((DNformat*)lu->B.Store)->nzval = barray;
27475af56d4SHong Zhang   ((DNformat*)lu->X.Store)->nzval = xarray;
2755fe6150dSHong Zhang #endif
27675af56d4SHong Zhang 
27775af56d4SHong Zhang   lu->options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
278cffbb591SHong Zhang   if (A->factor == MAT_FACTOR_LU){
2798914a3f7SHong Zhang #if defined(PETSC_USE_COMPLEX)
2808914a3f7SHong Zhang     zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
2818914a3f7SHong Zhang            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
2825d8b2efaSHong Zhang            &lu->mem_usage, &lu->stat, &info);
2838914a3f7SHong Zhang #else
28475af56d4SHong Zhang     dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
28575af56d4SHong Zhang            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
2865d8b2efaSHong Zhang            &lu->mem_usage, &lu->stat, &info);
2878914a3f7SHong Zhang #endif
288cffbb591SHong Zhang   } else if (A->factor == MAT_FACTOR_ILU){
289cffbb591SHong Zhang #if defined(PETSC_USE_COMPLEX)
290cffbb591SHong Zhang     zgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
291cffbb591SHong Zhang            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond,
2925d8b2efaSHong Zhang            &lu->mem_usage, &lu->stat, &info);
293cffbb591SHong Zhang #else
294cffbb591SHong Zhang     dgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
295cffbb591SHong Zhang            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond,
2965d8b2efaSHong Zhang            &lu->mem_usage, &lu->stat, &info);
297cffbb591SHong Zhang #endif
298cffbb591SHong Zhang   } else {
299cffbb591SHong Zhang     SETERRQ(PETSC_ERR_SUP,"Factor type not supported");
300cffbb591SHong Zhang   }
30175af56d4SHong Zhang   ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr);
30275af56d4SHong Zhang   ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
30375af56d4SHong Zhang 
304958c9bccSBarry Smith   if ( !info || info == lu->A.ncol+1 ) {
30575af56d4SHong Zhang     if ( lu->options.IterRefine ) {
3068914a3f7SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"Iterative Refinement:\n");
3078914a3f7SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  %8s%8s%16s%16s\n", "rhs", "Steps", "FERR", "BERR");
30875af56d4SHong Zhang       for (i = 0; i < 1; ++i)
3095d8b2efaSHong Zhang         ierr = PetscPrintf(PETSC_COMM_SELF,"  %8d%8d%16e%16e\n", i+1, lu->stat.RefineSteps, ferr, berr);
31075af56d4SHong Zhang     }
3118914a3f7SHong Zhang   } else if ( info > 0 ){
3128914a3f7SHong Zhang     if ( lu->lwork == -1 ) {
31377431f27SBarry Smith       ierr = PetscPrintf(PETSC_COMM_SELF,"  ** Estimated memory: %D bytes\n", info - lu->A.ncol);
3148914a3f7SHong Zhang     } else {
31577431f27SBarry Smith       ierr = PetscPrintf(PETSC_COMM_SELF,"  Warning: gssvx() returns info %D\n",info);
3168914a3f7SHong Zhang     }
3178914a3f7SHong Zhang   } else if (info < 0){
31877431f27SBarry Smith     SETERRQ2(PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", info,-info);
31914b396bbSKris Buschelman   }
32014b396bbSKris Buschelman 
3218914a3f7SHong Zhang   if ( lu->options.PrintStat ) {
3228914a3f7SHong Zhang     ierr = PetscPrintf(PETSC_COMM_SELF,"MatSolve__SuperLU():\n");
3235d8b2efaSHong Zhang     StatPrint(&lu->stat);
3248914a3f7SHong Zhang   }
32575af56d4SHong Zhang   PetscFunctionReturn(0);
32675af56d4SHong Zhang }
32714b396bbSKris Buschelman 
32814b396bbSKris Buschelman #undef __FUNCT__
329c29e884eSHong Zhang #define __FUNCT__ "MatSolve_SuperLU"
330c29e884eSHong Zhang PetscErrorCode MatSolve_SuperLU(Mat A,Vec b,Vec x)
331c29e884eSHong Zhang {
332c29e884eSHong Zhang   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
333c29e884eSHong Zhang   PetscErrorCode ierr;
334c29e884eSHong Zhang 
335c29e884eSHong Zhang   PetscFunctionBegin;
336c29e884eSHong Zhang   lu->options.Trans = TRANS;
337c29e884eSHong Zhang   ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr);
338c29e884eSHong Zhang   PetscFunctionReturn(0);
339c29e884eSHong Zhang }
340c29e884eSHong Zhang 
341c29e884eSHong Zhang #undef __FUNCT__
342c7c1fe80SHong Zhang #define __FUNCT__ "MatSolveTranspose_SuperLU"
343c7c1fe80SHong Zhang PetscErrorCode MatSolveTranspose_SuperLU(Mat A,Vec b,Vec x)
344c7c1fe80SHong Zhang {
345c7c1fe80SHong Zhang   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
346c7c1fe80SHong Zhang   PetscErrorCode ierr;
347c7c1fe80SHong Zhang 
348c7c1fe80SHong Zhang   PetscFunctionBegin;
349c7c1fe80SHong Zhang   lu->options.Trans = NOTRANS;
350c29e884eSHong Zhang   ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr);
351c7c1fe80SHong Zhang   PetscFunctionReturn(0);
352c7c1fe80SHong Zhang }
353c7c1fe80SHong Zhang 
35414b396bbSKris Buschelman /*
35514b396bbSKris Buschelman    Note the r permutation is ignored
35614b396bbSKris Buschelman */
35714b396bbSKris Buschelman #undef __FUNCT__
358f0c56d0fSKris Buschelman #define __FUNCT__ "MatLUFactorSymbolic_SuperLU"
3590481f469SBarry Smith PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
36014b396bbSKris Buschelman {
361719d5645SBarry Smith   Mat_SuperLU    *lu = (Mat_SuperLU*)((F)->spptr);
362b24902e0SBarry Smith 
363b24902e0SBarry Smith   PetscFunctionBegin;
364b24902e0SBarry Smith   lu->flg                   = DIFFERENT_NONZERO_PATTERN;
365b24902e0SBarry Smith   lu->CleanUpSuperLU        = PETSC_TRUE;
366719d5645SBarry Smith   (F)->ops->lufactornumeric = MatLUFactorNumeric_SuperLU;
367b24902e0SBarry Smith   PetscFunctionReturn(0);
368b24902e0SBarry Smith }
369b24902e0SBarry Smith 
37035bd34faSBarry Smith EXTERN_C_BEGIN
37135bd34faSBarry Smith #undef __FUNCT__
37235bd34faSBarry Smith #define __FUNCT__ "MatFactorGetSolverPackage_seqaij_superlu"
37335bd34faSBarry Smith PetscErrorCode MatFactorGetSolverPackage_seqaij_superlu(Mat A,const MatSolverPackage *type)
37435bd34faSBarry Smith {
37535bd34faSBarry Smith   PetscFunctionBegin;
37635bd34faSBarry Smith   *type = MAT_SOLVER_SUPERLU;
37735bd34faSBarry Smith   PetscFunctionReturn(0);
37835bd34faSBarry Smith }
37935bd34faSBarry Smith EXTERN_C_END
38035bd34faSBarry Smith 
381b24902e0SBarry Smith 
382b24902e0SBarry Smith /*MC
383b5e56a35SBarry Smith   MAT_SOLVER_SUPERLU = "superlu" - A solver package roviding direct solvers (LU) for sequential matrices
384b24902e0SBarry Smith   via the external package SuperLU.
385b24902e0SBarry Smith 
3865c9eb25fSBarry Smith   Use config/configure.py --download-superlu to have PETSc installed with SuperLU
387b24902e0SBarry Smith 
388b24902e0SBarry Smith   Options Database Keys:
3895c9eb25fSBarry Smith + -mat_superlu_ordering <0,1,2,3> - 0: natural ordering,
390b24902e0SBarry Smith                                     1: MMD applied to A'*A,
391b24902e0SBarry Smith                                     2: MMD applied to A'+A,
392b24902e0SBarry Smith                                     3: COLAMD, approximate minimum degree column ordering
393b24902e0SBarry Smith . -mat_superlu_iterrefine - have SuperLU do iterative refinement after the triangular solve
394b24902e0SBarry Smith                           choices: NOREFINE, SINGLE, DOUBLE, EXTRA; default is NOREFINE
395b24902e0SBarry Smith - -mat_superlu_printstat - print SuperLU statistics about the factorization
396b24902e0SBarry Smith 
3975c9eb25fSBarry Smith    Notes: Do not confuse this with MAT_SOLVER_SUPERLU_DIST which is for parallel sparse solves
3985c9eb25fSBarry Smith 
399b24902e0SBarry Smith    Level: beginner
400b24902e0SBarry Smith 
40141c8de11SBarry Smith .seealso: PCLU, MAT_SOLVER_SUPERLU_DIST, MAT_SOLVER_MUMPS, MAT_SOLVER_SPOOLES, PCFactorSetMatSolverPackage(), MatSolverPackage
402b24902e0SBarry Smith M*/
403b24902e0SBarry Smith 
4045c9eb25fSBarry Smith EXTERN_C_BEGIN
405b24902e0SBarry Smith #undef __FUNCT__
406b24902e0SBarry Smith #define __FUNCT__ "MatGetFactor_seqaij_superlu"
4075c9eb25fSBarry Smith PetscErrorCode MatGetFactor_seqaij_superlu(Mat A,MatFactorType ftype,Mat *F)
408b24902e0SBarry Smith {
40914b396bbSKris Buschelman   Mat            B;
410f0c56d0fSKris Buschelman   Mat_SuperLU    *lu;
4116849ba73SBarry Smith   PetscErrorCode ierr;
4125d8b2efaSHong Zhang   PetscInt       indx,m=A->rmap->n,n=A->cmap->n;
4139ce50919SHong Zhang   PetscTruth     flg;
4145ca28756SHong Zhang   const char     *colperm[]={"NATURAL","MMD_ATA","MMD_AT_PLUS_A","COLAMD"}; /* MY_PERMC - not supported by the petsc interface yet */
4155ca28756SHong Zhang   const char     *iterrefine[]={"NOREFINE", "SINGLE", "DOUBLE", "EXTRA"};
4165ca28756SHong Zhang   const char     *rowperm[]={"NOROWPERM", "LargeDiag"}; /* MY_PERMC - not supported by the petsc interface yet */
41714b396bbSKris Buschelman 
41814b396bbSKris Buschelman   PetscFunctionBegin;
4197adad957SLisandro Dalcin   ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr);
420d0f46423SBarry Smith   ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
4217adad957SLisandro Dalcin   ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr);
422899d7b4fSKris Buschelman   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
423f0c56d0fSKris Buschelman 
424cffbb591SHong Zhang   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU){
425b24902e0SBarry Smith     B->ops->lufactorsymbolic  = MatLUFactorSymbolic_SuperLU;
426cffbb591SHong Zhang     B->ops->ilufactorsymbolic = MatLUFactorSymbolic_SuperLU;
427cffbb591SHong Zhang   } else {
428cffbb591SHong Zhang     SETERRQ(PETSC_ERR_SUP,"Factor type not supported");
429cffbb591SHong Zhang   }
430cffbb591SHong Zhang 
431b24902e0SBarry Smith   B->ops->destroy          = MatDestroy_SuperLU;
4323519fcdcSHong Zhang   B->ops->view             = MatView_SuperLU;
433cffbb591SHong Zhang   B->factor                = ftype;
43494b7f48cSBarry Smith   B->assembled             = PETSC_TRUE;  /* required by -ksp_view */
4355c9eb25fSBarry Smith   B->preallocated          = PETSC_TRUE;
43614b396bbSKris Buschelman 
437b24902e0SBarry Smith   ierr = PetscNewLog(B,Mat_SuperLU,&lu);CHKERRQ(ierr);
438cffbb591SHong Zhang   if (ftype == MAT_FACTOR_LU){
4399ce50919SHong Zhang     set_default_options(&lu->options);
440cffbb591SHong Zhang   } else if (ftype == MAT_FACTOR_ILU){
441cffbb591SHong Zhang     /* Set the default input options of ilu:
442cffbb591SHong Zhang 	options.Fact = DOFACT;
443cffbb591SHong Zhang 	options.Equil = YES;
444cffbb591SHong Zhang 	options.ColPerm = COLAMD;
445cffbb591SHong Zhang 	options.DiagPivotThresh = 0.1; //different from complete LU
446cffbb591SHong Zhang 	options.Trans = NOTRANS;
447cffbb591SHong Zhang 	options.IterRefine = NOREFINE;
448cffbb591SHong Zhang 	options.SymmetricMode = NO;
449cffbb591SHong Zhang 	options.PivotGrowth = NO;
450cffbb591SHong Zhang 	options.ConditionNumber = NO;
451cffbb591SHong Zhang 	options.PrintStat = YES;
452cffbb591SHong Zhang 	options.RowPerm = LargeDiag;
453cffbb591SHong Zhang 	options.ILU_DropTol = 1e-4;
454cffbb591SHong Zhang 	options.ILU_FillTol = 1e-2;
455cffbb591SHong Zhang 	options.ILU_FillFactor = 10.0;
456cffbb591SHong Zhang 	options.ILU_DropRule = DROP_BASIC | DROP_AREA;
457cffbb591SHong Zhang 	options.ILU_Norm = INF_NORM;
458cffbb591SHong Zhang 	options.ILU_MILU = SMILU_2;
459cffbb591SHong Zhang     */
460*1a2e2f44SHong Zhang 
461cffbb591SHong Zhang     ilu_set_default_options(&lu->options);
462cffbb591SHong Zhang   }
463*1a2e2f44SHong Zhang   /* equilibration causes error in solve()(ref. [petsc-maint #42782] SuperLU troubles)
464*1a2e2f44SHong Zhang      thus not supported here. See dgssvx.c for possible reason. */
465*1a2e2f44SHong Zhang   lu->options.Equil     = NO;
4669ce50919SHong Zhang   lu->options.PrintStat = NO;
467*1a2e2f44SHong Zhang 
4685d8b2efaSHong Zhang   /* Initialize the statistics variables. */
4695d8b2efaSHong Zhang   StatInit(&lu->stat);
4708914a3f7SHong Zhang   lu->lwork = 0;   /* allocate space internally by system malloc */
4719ce50919SHong Zhang 
4727adad957SLisandro Dalcin   ierr = PetscOptionsBegin(((PetscObject)A)->comm,((PetscObject)A)->prefix,"SuperLU Options","Mat");CHKERRQ(ierr);
473cffbb591SHong Zhang     ierr = PetscOptionsTruth("-mat_superlu_equil","Equil","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
474cffbb591SHong Zhang     if (flg) lu->options.Equil = YES;
4758914a3f7SHong Zhang     ierr = PetscOptionsEList("-mat_superlu_colperm","ColPerm","None",colperm,4,colperm[3],&indx,&flg);CHKERRQ(ierr);
4769ce50919SHong Zhang     if (flg) {lu->options.ColPerm = (colperm_t)indx;}
4778914a3f7SHong Zhang     ierr = PetscOptionsEList("-mat_superlu_iterrefine","IterRefine","None",iterrefine,4,iterrefine[0],&indx,&flg);CHKERRQ(ierr);
4789ce50919SHong Zhang     if (flg) { lu->options.IterRefine = (IterRefine_t)indx;}
4794dc4c822SBarry Smith     ierr = PetscOptionsTruth("-mat_superlu_symmetricmode","SymmetricMode","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
4809ce50919SHong Zhang     if (flg) lu->options.SymmetricMode = YES;
4818914a3f7SHong Zhang     ierr = PetscOptionsReal("-mat_superlu_diagpivotthresh","DiagPivotThresh","None",lu->options.DiagPivotThresh,&lu->options.DiagPivotThresh,PETSC_NULL);CHKERRQ(ierr);
4824dc4c822SBarry Smith     ierr = PetscOptionsTruth("-mat_superlu_pivotgrowth","PivotGrowth","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
4839ce50919SHong Zhang     if (flg) lu->options.PivotGrowth = YES;
4844dc4c822SBarry Smith     ierr = PetscOptionsTruth("-mat_superlu_conditionnumber","ConditionNumber","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
4859ce50919SHong Zhang     if (flg) lu->options.ConditionNumber = YES;
4868914a3f7SHong Zhang     ierr = PetscOptionsEList("-mat_superlu_rowperm","rowperm","None",rowperm,2,rowperm[0],&indx,&flg);CHKERRQ(ierr);
4879ce50919SHong Zhang     if (flg) {lu->options.RowPerm = (rowperm_t)indx;}
4884dc4c822SBarry Smith     ierr = PetscOptionsTruth("-mat_superlu_replacetinypivot","ReplaceTinyPivot","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
4899ce50919SHong Zhang     if (flg) lu->options.ReplaceTinyPivot = YES;
4904dc4c822SBarry Smith     ierr = PetscOptionsTruth("-mat_superlu_printstat","PrintStat","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
4919ce50919SHong Zhang     if (flg) lu->options.PrintStat = YES;
4928914a3f7SHong Zhang     ierr = PetscOptionsInt("-mat_superlu_lwork","size of work array in bytes used by factorization","None",lu->lwork,&lu->lwork,PETSC_NULL);CHKERRQ(ierr);
4935fe6150dSHong Zhang     if (lu->lwork > 0 ){
4945fe6150dSHong Zhang       ierr = PetscMalloc(lu->lwork,&lu->work);CHKERRQ(ierr);
4955fe6150dSHong Zhang     } else if (lu->lwork != 0 && lu->lwork != -1){
49677431f27SBarry Smith       ierr = PetscPrintf(PETSC_COMM_SELF,"   Warning: lwork %D is not supported by SUPERLU. The default lwork=0 is used.\n",lu->lwork);
4978914a3f7SHong Zhang       lu->lwork = 0;
4988914a3f7SHong Zhang     }
499cffbb591SHong Zhang     /* ilu options */
500cffbb591SHong Zhang     ierr = PetscOptionsReal("-mat_superlu_ilu_droptol","ILU_DropTol","None",lu->options.ILU_DropTol,&lu->options.ILU_DropTol,PETSC_NULL);CHKERRQ(ierr);
501cffbb591SHong Zhang     ierr = PetscOptionsReal("-mat_superlu_ilu_filltol","ILU_FillTol","None",lu->options.ILU_FillTol,&lu->options.ILU_FillTol,PETSC_NULL);CHKERRQ(ierr);
502cffbb591SHong Zhang     ierr = PetscOptionsReal("-mat_superlu_ilu_fillfactor","ILU_FillFactor","None",lu->options.ILU_FillFactor,&lu->options.ILU_FillFactor,PETSC_NULL);CHKERRQ(ierr);
503cffbb591SHong Zhang     ierr = PetscOptionsInt("-mat_superlu_ilu_droprull","ILU_DropRule","None",lu->options.ILU_DropRule,&lu->options.ILU_DropRule,PETSC_NULL);CHKERRQ(ierr);
504cffbb591SHong Zhang     ierr = PetscOptionsInt("-mat_superlu_ilu_norm","ILU_Norm","None",lu->options.ILU_Norm,&indx,&flg);CHKERRQ(ierr);
505cffbb591SHong Zhang     if (flg){
506cffbb591SHong Zhang       lu->options.ILU_Norm = (norm_t)indx;
507cffbb591SHong Zhang     }
508cffbb591SHong Zhang     ierr = PetscOptionsInt("-mat_superlu_ilu_milu","ILU_MILU","None",lu->options.ILU_MILU,&indx,&flg);CHKERRQ(ierr);
509cffbb591SHong Zhang     if (flg){
510cffbb591SHong Zhang       lu->options.ILU_MILU = (milu_t)indx;
511cffbb591SHong Zhang     }
5129ce50919SHong Zhang   PetscOptionsEnd();
5139ce50919SHong Zhang 
5145d8b2efaSHong Zhang   /* Allocate spaces (notice sizes are for the transpose) */
5155d8b2efaSHong Zhang   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->etree);CHKERRQ(ierr);
5165d8b2efaSHong Zhang   ierr = PetscMalloc(n*sizeof(PetscInt),&lu->perm_r);CHKERRQ(ierr);
5175d8b2efaSHong Zhang   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->perm_c);CHKERRQ(ierr);
5185d8b2efaSHong Zhang   ierr = PetscMalloc(n*sizeof(PetscScalar),&lu->R);CHKERRQ(ierr);
5195d8b2efaSHong Zhang   ierr = PetscMalloc(m*sizeof(PetscScalar),&lu->C);CHKERRQ(ierr);
5205d8b2efaSHong Zhang 
5215d8b2efaSHong Zhang   /* create rhs and solution x without allocate space for .Store */
5225d8b2efaSHong Zhang #if defined(PETSC_USE_COMPLEX)
5235d8b2efaSHong Zhang   zCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
5245d8b2efaSHong Zhang   zCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
5255d8b2efaSHong Zhang #else
5265d8b2efaSHong Zhang   dCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
5275d8b2efaSHong Zhang   dCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
5285d8b2efaSHong Zhang #endif
5295d8b2efaSHong Zhang 
53075af56d4SHong Zhang #ifdef SUPERLU2
5315c9eb25fSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatCreateNull","MatCreateNull_SuperLU",(void(*)(void))MatCreateNull_SuperLU);CHKERRQ(ierr);
53275af56d4SHong Zhang #endif
53335bd34faSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatFactorGetSolverPackage_C","MatFactorGetSolverPackage_seqaij_superlu",MatFactorGetSolverPackage_seqaij_superlu);CHKERRQ(ierr);
5345c9eb25fSBarry Smith   B->spptr = lu;
535899d7b4fSKris Buschelman   *F = B;
53614b396bbSKris Buschelman   PetscFunctionReturn(0);
53714b396bbSKris Buschelman }
5385c9eb25fSBarry Smith EXTERN_C_END
539