Actual source code: umfpack.c

  1: /*$Id: umfpack.c,v 1.10 2001/08/15 15:56:50 bsmith Exp $*/

  3: /* 
  4:         Provides an interface to the UMFPACK sparse solver
  5: */

 7:  #include src/mat/impls/aij/seq/aij.h

  9: EXTERN_C_BEGIN
 10: #include "umfpack.h"
 11: EXTERN_C_END

 13: typedef struct {
 14:   void         *Symbolic, *Numeric;
 15:   double       Info[UMFPACK_INFO], Control[UMFPACK_CONTROL],*W;
 16:   int          *Wi,*ai,*aj,*perm_c;
 17:   PetscScalar  *av;
 18:   MatStructure flg;
 19:   PetscTruth   PetscMatOdering;

 21:   /* A few function pointers for inheritance */
 22:   int (*MatDuplicate)(Mat,MatDuplicateOption,Mat*);
 23:   int (*MatView)(Mat,PetscViewer);
 24:   int (*MatAssemblyEnd)(Mat,MatAssemblyType);
 25:   int (*MatLUFactorSymbolic)(Mat,IS,IS,MatFactorInfo*,Mat*);
 26:   int (*MatDestroy)(Mat);
 27: 
 28:   /* Flag to clean up UMFPACK objects during Destroy */
 29:   PetscTruth CleanUpUMFPACK;
 30: } Mat_UMFPACK;

 32: EXTERN int MatDuplicate_UMFPACK(Mat,MatDuplicateOption,Mat*);

 34: EXTERN_C_BEGIN
 37: int MatConvert_UMFPACK_SeqAIJ(Mat A,const MatType type,Mat *newmat) {
 38:   /* This routine is only called to convert an unfactored PETSc-UMFPACK matrix */
 39:   /* to its base PETSc type, so we will ignore 'MatType type'. */
 40:   int         ierr;
 41:   Mat         B=*newmat;
 42:   Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;

 45:   if (B != A) {
 46:     /* This routine was inherited from SeqAIJ. */
 47:     MatDuplicate(A,MAT_COPY_VALUES,&B);
 48:   }
 49:   /* Reset the original function pointers */
 50:   A->ops->duplicate        = lu->MatDuplicate;
 51:   A->ops->view             = lu->MatView;
 52:   A->ops->assemblyend      = lu->MatAssemblyEnd;
 53:   A->ops->lufactorsymbolic = lu->MatLUFactorSymbolic;
 54:   A->ops->destroy          = lu->MatDestroy;
 55: 
 56:   PetscFree(lu);
 57:   PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
 58:   *newmat = B;
 59:   return(0);
 60: }
 61: EXTERN_C_END

 65: int MatDestroy_UMFPACK(Mat A) {
 66:   int         ierr;
 67:   Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;

 70:   if (lu->CleanUpUMFPACK) {
 71:     umfpack_di_free_symbolic(&lu->Symbolic) ;
 72:     umfpack_di_free_numeric(&lu->Numeric) ;
 73:     PetscFree(lu->Wi);
 74:     PetscFree(lu->W);

 76:     if (lu->PetscMatOdering) {
 77:       PetscFree(lu->perm_c);
 78:     }
 79:   }
 80:   MatConvert_UMFPACK_SeqAIJ(A,MATSEQAIJ,&A);
 81:   (*A->ops->destroy)(A);
 82:   return(0);
 83: }

 87: int MatSolve_UMFPACK(Mat A,Vec b,Vec x) {
 88:   Mat_UMFPACK *lu = (Mat_UMFPACK*)A->spptr;
 89:   PetscScalar *av=lu->av,*ba,*xa;
 90:   int         ierr,*ai=lu->ai,*aj=lu->aj,status;
 91: 
 93:   /* solve Ax = b by umfpack_di_wsolve */
 94:   /* ----------------------------------*/
 95:   VecGetArray(b,&ba);
 96:   VecGetArray(x,&xa);

 98:   status = umfpack_di_wsolve(UMFPACK_At,ai,aj,av,xa,ba,lu->Numeric,lu->Control,lu->Info,lu->Wi,lu->W);
 99:   umfpack_di_report_info(lu->Control, lu->Info);
100:   if (status < 0){
101:     umfpack_di_report_status(lu->Control, status) ;
102:     SETERRQ(1,"umfpack_di_wsolve failed") ;
103:   }
104: 
105:   VecRestoreArray(b,&ba);
106:   VecRestoreArray(x,&xa);
107:   return(0);
108: }

112: int MatLUFactorNumeric_UMFPACK(Mat A,Mat *F) {
113:   Mat_UMFPACK *lu=(Mat_UMFPACK*)(*F)->spptr;
114:   int         *ai=lu->ai,*aj=lu->aj,m=A->m,status,ierr;
115:   PetscScalar *av=lu->av;

118:   /* numeric factorization of A' */
119:   /* ----------------------------*/
120:   status = umfpack_di_numeric (ai,aj,av,lu->Symbolic,&lu->Numeric,lu->Control,lu->Info) ;
121:   if (status < 0) SETERRQ(1,"umfpack_di_numeric failed");
122:   /* report numeric factorization of A' when Control[PRL] > 3 */
123:   (void) umfpack_di_report_numeric (lu->Numeric, lu->Control) ;

125:   if (lu->flg == DIFFERENT_NONZERO_PATTERN){  /* first numeric factorization */
126:     /* allocate working space to be used by Solve */
127:     PetscMalloc(m * sizeof(int), &lu->Wi);
128:     PetscMalloc(5*m * sizeof(double), &lu->W);

130:     lu->flg = SAME_NONZERO_PATTERN;
131:   }

133:   return(0);
134: }

136: /*
137:    Note the r permutation is ignored
138: */
141: int MatLUFactorSymbolic_UMFPACK(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F) {
142:   Mat         B;
143:   Mat_SeqAIJ  *mat=(Mat_SeqAIJ*)A->data;
144:   Mat_UMFPACK *lu;
145:   int         ierr,m=A->m,n=A->n,*ai=mat->i,*aj=mat->j,status,*ca;
146:   PetscScalar *av=mat->a;
147: 
149:   /* Create the factorization matrix F */
150:   MatCreate(A->comm,PETSC_DECIDE,PETSC_DECIDE,m,n,&B);
151:   MatSetType(B,A->type_name);
152:   MatSeqAIJSetPreallocation(B,0,PETSC_NULL);
153: 
154:   B->ops->lufactornumeric = MatLUFactorNumeric_UMFPACK;
155:   B->ops->solve           = MatSolve_UMFPACK;
156:   B->factor               = FACTOR_LU;
157:   B->assembled            = PETSC_TRUE;  /* required by -ksp_view */

159:   lu = (Mat_UMFPACK*)(B->spptr);
160: 
161:   /* initializations */
162:   /* ------------------------------------------------*/
163:   /* get the default control parameters */
164:   umfpack_di_defaults (lu->Control) ;
165:   lu->perm_c = PETSC_NULL;  /* use defaul UMFPACK col permutation */

167:   PetscOptionsBegin(A->comm,A->prefix,"UMFPACK Options","Mat");
168:   /* Control parameters used by reporting routiones */
169:   PetscOptionsReal("-mat_umfpack_prl","Control[UMFPACK_PRL]","None",lu->Control[UMFPACK_PRL],&lu->Control[UMFPACK_PRL],PETSC_NULL);

171:   /* Control parameters for symbolic factorization */
172:   PetscOptionsReal("-mat_umfpack_dense_col","Control[UMFPACK_DENSE_COL]","None",lu->Control[UMFPACK_DENSE_COL],&lu->Control[UMFPACK_DENSE_COL],PETSC_NULL);
173:   PetscOptionsReal("-mat_umfpack_dense_row","Control[UMFPACK_DENSE_ROW]","None",lu->Control[UMFPACK_DENSE_ROW],&lu->Control[UMFPACK_DENSE_ROW],PETSC_NULL);
174:   PetscOptionsReal("-mat_umfpack_block_size","Control[UMFPACK_BLOCK_SIZE]","None",lu->Control[UMFPACK_BLOCK_SIZE],&lu->Control[UMFPACK_BLOCK_SIZE],PETSC_NULL);

176:   /* Control parameters used by numeric factorization */
177:   PetscOptionsReal("-mat_umfpack_pivot_tolerance","Control[UMFPACK_PIVOT_TOLERANCE]","None",lu->Control[UMFPACK_PIVOT_TOLERANCE],&lu->Control[UMFPACK_PIVOT_TOLERANCE],PETSC_NULL);
178: #if !defined(PETSC_HAVE_UMFPACK_41_OR_NEWER)
179:   PetscOptionsReal("-mat_umfpack_relaxed_amalgamation","Control[UMFPACK_RELAXED_AMALGAMATION]","None",lu->Control[UMFPACK_RELAXED_AMALGAMATION],&lu->Control[UMFPACK_RELAXED_AMALGAMATION],PETSC_NULL);
180:   PetscOptionsReal("-mat_umfpack_relaxed2_amalgamation","Control[UMFPACK_RELAXED2_AMALGAMATION]","None",lu->Control[UMFPACK_RELAXED2_AMALGAMATION],&lu->Control[UMFPACK_RELAXED2_AMALGAMATION],PETSC_NULL);
181:   PetscOptionsReal("-mat_umfpack_relaxed3_amalgamation","Control[UMFPACK_RELAXED3_AMALGAMATION]","None",lu->Control[UMFPACK_RELAXED3_AMALGAMATION],&lu->Control[UMFPACK_RELAXED3_AMALGAMATION],PETSC_NULL);
182: #endif
183:   PetscOptionsReal("-mat_umfpack_alloc_init","Control[UMFPACK_ALLOC_INIT]","None",lu->Control[UMFPACK_ALLOC_INIT],&lu->Control[UMFPACK_ALLOC_INIT],PETSC_NULL);

185:   /* Control parameters used by solve */
186:   PetscOptionsReal("-mat_umfpack_irstep","Control[UMFPACK_IRSTEP]","None",lu->Control[UMFPACK_IRSTEP],&lu->Control[UMFPACK_IRSTEP],PETSC_NULL);
187: 
188:   /* use Petsc mat ordering (notice size is for the transpose) */
189:   PetscOptionsHasName(PETSC_NULL,"-pc_lu_mat_ordering_type",&lu->PetscMatOdering);
190:   if (lu->PetscMatOdering) {
191:     ISGetIndices(c,&ca);
192:     PetscMalloc(A->m*sizeof(int),&lu->perm_c);
193:     PetscMemcpy(lu->perm_c,ca,A->m*sizeof(int));
194:     ISRestoreIndices(c,&ca);
195:   }
196:   PetscOptionsEnd();

198:   /* print the control parameters */
199:   if( lu->Control[UMFPACK_PRL] > 1 ) umfpack_di_report_control (lu->Control);

201:   /* symbolic factorization of A' */
202:   /* ---------------------------------------------------------------------- */
203: #if defined(PETSC_HAVE_UMFPACK_41_OR_NEWER)
204:   status = umfpack_di_qsymbolic(n,m,ai,aj,PETSC_NULL,lu->perm_c,&lu->Symbolic,lu->Control,lu->Info) ;
205: #else
206:   status = umfpack_di_qsymbolic(n,m,ai,aj,lu->perm_c,&lu->Symbolic,lu->Control,lu->Info) ;
207: #endif
208:   if (status < 0){
209:     umfpack_di_report_info(lu->Control, lu->Info) ;
210:     umfpack_di_report_status(lu->Control, status) ;
211:     SETERRQ(1,"umfpack_di_symbolic failed");
212:   }
213:   /* report sumbolic factorization of A' when Control[PRL] > 3 */
214:   (void) umfpack_di_report_symbolic(lu->Symbolic, lu->Control) ;

216:   lu->flg = DIFFERENT_NONZERO_PATTERN;
217:   lu->ai  = ai;
218:   lu->aj  = aj;
219:   lu->av  = av;
220:   lu->CleanUpUMFPACK = PETSC_TRUE;
221:   *F = B;
222:   return(0);
223: }

227: int MatAssemblyEnd_UMFPACK(Mat A,MatAssemblyType mode) {
228:   int         ierr;
229:   Mat_UMFPACK *lu=(Mat_UMFPACK*)(A->spptr);

232:   (*lu->MatAssemblyEnd)(A,mode);
233:   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
234:   A->ops->lufactorsymbolic = MatLUFactorSymbolic_UMFPACK;
235:   return(0);
236: }

238: /* used by -ksp_view */
241: int MatFactorInfo_UMFPACK(Mat A,PetscViewer viewer) {
242:   Mat_UMFPACK *lu= (Mat_UMFPACK*)A->spptr;
243:   int         ierr;

246:   /* check if matrix is UMFPACK type */
247:   if (A->ops->solve != MatSolve_UMFPACK) return(0);

249:   PetscViewerASCIIPrintf(viewer,"UMFPACK run parameters:\n");
250:   /* Control parameters used by reporting routiones */
251:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_PRL]: %g\n",lu->Control[UMFPACK_PRL]);

253:   /* Control parameters used by symbolic factorization */
254:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DENSE_COL]: %g\n",lu->Control[UMFPACK_DENSE_COL]);
255:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DENSE_ROW]: %g\n",lu->Control[UMFPACK_DENSE_ROW]);
256:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_BLOCK_SIZE]: %g\n",lu->Control[UMFPACK_BLOCK_SIZE]);

258:   /* Control parameters used by numeric factorization */
259:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_PIVOT_TOLERANCE]: %g\n",lu->Control[UMFPACK_PIVOT_TOLERANCE]);
260: #if !defined(PETSC_HAVE_UMFPACK_41_OR_NEWER)
261:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_RELAXED_AMALGAMATION]: %g\n",lu->Control[UMFPACK_RELAXED_AMALGAMATION]);
262:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_RELAXED2_AMALGAMATION]: %g\n",lu->Control[UMFPACK_RELAXED2_AMALGAMATION]);
263:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_RELAXED3_AMALGAMATION]: %g\n",lu->Control[UMFPACK_RELAXED3_AMALGAMATION]);
264: #endif
265:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_ALLOC_INIT]: %g\n",lu->Control[UMFPACK_ALLOC_INIT]);

267:   /* Control parameters used by solve */
268:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_IRSTEP]: %g\n",lu->Control[UMFPACK_IRSTEP]);

270:   /* mat ordering */
271:   if(!lu->PetscMatOdering) PetscViewerASCIIPrintf(viewer,"  UMFPACK default matrix ordering is used (not the PETSc matrix ordering) \n");

273:   return(0);
274: }

278: int MatView_UMFPACK(Mat A,PetscViewer viewer) {
279:   int               ierr;
280:   PetscTruth        isascii;
281:   PetscViewerFormat format;
282:   Mat_UMFPACK       *lu=(Mat_UMFPACK*)(A->spptr);

285:   (*lu->MatView)(A,viewer);

287:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
288:   if (isascii) {
289:     PetscViewerGetFormat(viewer,&format);
290:     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
291:       MatFactorInfo_UMFPACK(A,viewer);
292:     }
293:   }
294:   return(0);
295: }

297: EXTERN_C_BEGIN
300: int MatConvert_SeqAIJ_UMFPACK(Mat A,const MatType type,Mat *newmat) {
301:   /* This routine is only called to convert to MATUMFPACK */
302:   /* from MATSEQAIJ, so we will ignore 'MatType type'. */
303:   int         ierr;
304:   Mat         B=*newmat;
305:   Mat_UMFPACK *lu;

308:   if (B != A) {
309:     MatDuplicate(A,MAT_COPY_VALUES,&B);
310:   }

312:   PetscNew(Mat_UMFPACK,&lu);
313:   lu->MatDuplicate         = A->ops->duplicate;
314:   lu->MatView              = A->ops->view;
315:   lu->MatAssemblyEnd       = A->ops->assemblyend;
316:   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
317:   lu->MatDestroy           = A->ops->destroy;
318:   lu->CleanUpUMFPACK       = PETSC_FALSE;

320:   B->spptr                 = (void*)lu;
321:   B->ops->duplicate        = MatDuplicate_UMFPACK;
322:   B->ops->view             = MatView_UMFPACK;
323:   B->ops->assemblyend      = MatAssemblyEnd_UMFPACK;
324:   B->ops->lufactorsymbolic = MatLUFactorSymbolic_UMFPACK;
325:   B->ops->destroy          = MatDestroy_UMFPACK;

327:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_umfpack_C",
328:                                            "MatConvert_SeqAIJ_UMFPACK",MatConvert_SeqAIJ_UMFPACK);
329:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_umfpack_seqaij_C",
330:                                            "MatConvert_UMFPACK_SeqAIJ",MatConvert_UMFPACK_SeqAIJ);
331:   PetscLogInfo(0,"Using UMFPACK for SeqAIJ LU factorization and solves.");
332:   PetscObjectChangeTypeName((PetscObject)B,MATUMFPACK);
333:   *newmat = B;
334:   return(0);
335: }
336: EXTERN_C_END

340: int MatDuplicate_UMFPACK(Mat A, MatDuplicateOption op, Mat *M) {
341:   int         ierr;
342:   Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;

345:   (*lu->MatDuplicate)(A,op,M);
346:   PetscMemcpy((*M)->spptr,lu,sizeof(Mat_UMFPACK));
347:   return(0);
348: }

350: /*MC
351:   MATUMFPACK - MATUMFPACK = "umfpack" - A matrix type providing direct solvers (LU) for sequential matrices 
352:   via the external package UMFPACK.

354:   If UMFPACK is installed (see the manual for
355:   instructions on how to declare the existence of external packages),
356:   a matrix type can be constructed which invokes UMFPACK solvers.
357:   After calling MatCreate(...,A), simply call MatSetType(A,UMFPACK).
358:   This matrix type is only supported for double precision real.

360:   This matrix inherits from MATSEQAIJ.  As a result, MatSeqAIJSetPreallocation is 
361:   supported for this matrix type.  One can also call MatConvert for an inplace conversion to or from 
362:   the MATSEQAIJ type without data copy.

364:   Consult UMFPACK documentation for more information about the Control parameters
365:   which correspond to the options database keys below.

367:   Options Database Keys:
368: + -mat_type umfpack - sets the matrix type to "umfpack" during a call to MatSetFromOptions()
369: . -mat_umfpack_prl - UMFPACK print level: Control[UMFPACK_PRL]
370: . -mat_umfpack_dense_col <alpha_c> - UMFPACK dense column threshold: Control[UMFPACK_DENSE_COL]
371: . -mat_umfpack_block_size <bs> - UMFPACK block size for BLAS-Level 3 calls: Control[UMFPACK_BLOCK_SIZE]
372: . -mat_umfpack_pivot_tolerance <delta> - UMFPACK partial pivot tolerance: Control[UMFPACK_PIVOT_TOLERANCE]
373: . -mat_umfpack_alloc_init <delta> - UMFPACK factorized matrix allocation modifier: Control[UMFPACK_ALLOC_INIT]
374: - -mat_umfpack_irstep <maxit> - UMFPACK maximum number of iterative refinement steps: Control[UMFPACK_IRSTEP]

376:    Level: beginner

378: .seealso: PCLU
379: M*/

381: EXTERN_C_BEGIN
384: int MatCreate_UMFPACK(Mat A) {
385:   int                ierr;

388:   /* Change type name before calling MatSetType to force proper construction of SeqAIJ and UMFPACK types */
389:   PetscObjectChangeTypeName((PetscObject)A,MATUMFPACK);
390:   MatSetType(A,MATSEQAIJ);
391:   MatConvert_SeqAIJ_UMFPACK(A,MATUMFPACK,&A);
392:   return(0);
393: }
394: EXTERN_C_END