Actual source code: umfpack.c

  2: /* 
  3:         Provides an interface to the UMFPACKv4.3 sparse solver
  4: */

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

  9: #include "umfpack.h"

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

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

 31: EXTERN PetscErrorCode MatDuplicate_UMFPACK(Mat,MatDuplicateOption,Mat*);

 36: PetscErrorCode MatConvert_UMFPACK_SeqAIJ(Mat A,const MatType type,Mat *newmat)
 37: {
 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'. */
 41:   Mat         B=*newmat;
 42:   Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;

 45:   if (B != A) {
 46:     MatDuplicate(A,MAT_COPY_VALUES,&B);
 47:   }
 48:   /* Reset the original function pointers */
 49:   B->ops->duplicate        = lu->MatDuplicate;
 50:   B->ops->view             = lu->MatView;
 51:   B->ops->assemblyend      = lu->MatAssemblyEnd;
 52:   B->ops->lufactorsymbolic = lu->MatLUFactorSymbolic;
 53:   B->ops->destroy          = lu->MatDestroy;
 54: 
 55:   PetscFree(lu);

 57:   PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_umfpack_C","",PETSC_NULL);
 58:   PetscObjectComposeFunction((PetscObject)B,"MatConvert_umfpack_seqaij_C","",PETSC_NULL);

 60:   PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
 61:   *newmat = B;
 62:   return(0);
 63: }

 68: PetscErrorCode MatDestroy_UMFPACK(Mat A)
 69: {
 71:   Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;

 74:   if (lu->CleanUpUMFPACK) {
 75:     umfpack_di_free_symbolic(&lu->Symbolic);
 76:     umfpack_di_free_numeric(&lu->Numeric);
 77:     PetscFree(lu->Wi);
 78:     PetscFree(lu->W);
 79:     if (lu->PetscMatOdering) {
 80:       PetscFree(lu->perm_c);
 81:     }
 82:   }
 83:   MatConvert_UMFPACK_SeqAIJ(A,MATSEQAIJ,&A);
 84:   (*A->ops->destroy)(A);
 85:   return(0);
 86: }

 90: PetscErrorCode MatSolve_UMFPACK(Mat A,Vec b,Vec x)
 91: {
 92:   Mat_UMFPACK *lu = (Mat_UMFPACK*)A->spptr;
 93:   PetscScalar *av=lu->av,*ba,*xa;
 95:   int          *ai=lu->ai,*aj=lu->aj,status;
 96: 
 98:   /* solve Ax = b by umfpack_di_wsolve */
 99:   /* ----------------------------------*/
100:   VecGetArray(b,&ba);
101:   VecGetArray(x,&xa);

103:   status = umfpack_di_wsolve(UMFPACK_At,ai,aj,av,xa,ba,lu->Numeric,lu->Control,lu->Info,lu->Wi,lu->W);
104:   umfpack_di_report_info(lu->Control, lu->Info);
105:   if (status < 0){
106:     umfpack_di_report_status(lu->Control, status);
107:     SETERRQ(PETSC_ERR_LIB,"umfpack_di_wsolve failed");
108:   }
109: 
110:   VecRestoreArray(b,&ba);
111:   VecRestoreArray(x,&xa);

113:   return(0);
114: }

118: PetscErrorCode MatLUFactorNumeric_UMFPACK(Mat A,Mat *F)
119: {
120:   Mat_UMFPACK *lu=(Mat_UMFPACK*)(*F)->spptr;
122:   int         *ai=lu->ai,*aj=lu->aj,m=A->m,status;
123:   PetscScalar *av=lu->av;

126:   /* numeric factorization of A' */
127:   /* ----------------------------*/
128:   if (lu->flg == SAME_NONZERO_PATTERN && lu->Numeric){
129:       umfpack_di_free_numeric(&lu->Numeric);
130:   }
131:   status = umfpack_di_numeric (ai,aj,av,lu->Symbolic,&lu->Numeric,lu->Control,lu->Info);
132:   if (status < 0) SETERRQ(PETSC_ERR_LIB,"umfpack_di_numeric failed");
133:   /* report numeric factorization of A' when Control[PRL] > 3 */
134:   (void) umfpack_di_report_numeric (lu->Numeric, lu->Control);

136:   if (lu->flg == DIFFERENT_NONZERO_PATTERN){  /* first numeric factorization */
137:     /* allocate working space to be used by Solve */
138:     PetscMalloc(m * sizeof(int), &lu->Wi);
139:     PetscMalloc(5*m * sizeof(double), &lu->W);
140:   }
141:   lu->flg = SAME_NONZERO_PATTERN;
142:   lu->CleanUpUMFPACK = PETSC_TRUE;
143:   return(0);
144: }

146: /*
147:    Note the r permutation is ignored
148: */
151: PetscErrorCode MatLUFactorSymbolic_UMFPACK(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F)
152: {
153:   Mat         B;
154:   Mat_SeqAIJ  *mat=(Mat_SeqAIJ*)A->data;
155:   Mat_UMFPACK *lu;
157:   int          m=A->m,n=A->n,*ai=mat->i,*aj=mat->j,status,*ra,idx;
158:   PetscScalar *av=mat->a;
159:   const char  *strategy[]={"AUTO","UNSYMMETRIC","SYMMETRIC","2BY2"},
160:               *scale[]={"NONE","SUM","MAX"};
161:   PetscTruth  flg;
162: 
164:   /* Create the factorization matrix F */
165:   MatCreate(A->comm,PETSC_DECIDE,PETSC_DECIDE,m,n,&B);
166:   MatSetType(B,A->type_name);
167:   MatSeqAIJSetPreallocation(B,0,PETSC_NULL);
168: 
169:   B->ops->lufactornumeric = MatLUFactorNumeric_UMFPACK;
170:   B->ops->solve           = MatSolve_UMFPACK;
171:   B->factor               = FACTOR_LU;
172:   B->assembled            = PETSC_TRUE;  /* required by -ksp_view */

174:   lu = (Mat_UMFPACK*)(B->spptr);
175: 
176:   /* initializations */
177:   /* ------------------------------------------------*/
178:   /* get the default control parameters */
179:   umfpack_di_defaults (lu->Control);
180:   lu->perm_c = PETSC_NULL;  /* use defaul UMFPACK col permutation */
181:   lu->Control[UMFPACK_IRSTEP] = 0; /* max num of iterative refinement steps to attempt */

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

187:   /* Control parameters for symbolic factorization */
188:   PetscOptionsEList("-mat_umfpack_strategy","ordering and pivoting strategy","None",strategy,4,strategy[0],&idx,&flg);
189:   if (flg) {
190:     switch (idx){
191:     case 0: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_AUTO; break;
192:     case 1: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC; break;
193:     case 2: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_SYMMETRIC; break;
194:     case 3: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_2BY2; break;
195:     }
196:   }
197:   PetscOptionsReal("-mat_umfpack_dense_col","Control[UMFPACK_DENSE_COL]","None",lu->Control[UMFPACK_DENSE_COL],&lu->Control[UMFPACK_DENSE_COL],PETSC_NULL);
198:   PetscOptionsReal("-mat_umfpack_dense_row","Control[UMFPACK_DENSE_ROW]","None",lu->Control[UMFPACK_DENSE_ROW],&lu->Control[UMFPACK_DENSE_ROW],PETSC_NULL);
199:   PetscOptionsReal("-mat_umfpack_amd_dense","Control[UMFPACK_AMD_DENSE]","None",lu->Control[UMFPACK_AMD_DENSE],&lu->Control[UMFPACK_AMD_DENSE],PETSC_NULL);
200:   PetscOptionsReal("-mat_umfpack_block_size","Control[UMFPACK_BLOCK_SIZE]","None",lu->Control[UMFPACK_BLOCK_SIZE],&lu->Control[UMFPACK_BLOCK_SIZE],PETSC_NULL);
201:   PetscOptionsReal("-mat_umfpack_2by2_tolerance","Control[UMFPACK_2BY2_TOLERANCE]","None",lu->Control[UMFPACK_2BY2_TOLERANCE],&lu->Control[UMFPACK_2BY2_TOLERANCE],PETSC_NULL);
202:   PetscOptionsReal("-mat_umfpack_fixq","Control[UMFPACK_FIXQ]","None",lu->Control[UMFPACK_FIXQ],&lu->Control[UMFPACK_FIXQ],PETSC_NULL);
203:   PetscOptionsReal("-mat_umfpack_aggressive","Control[UMFPACK_AGGRESSIVE]","None",lu->Control[UMFPACK_AGGRESSIVE],&lu->Control[UMFPACK_AGGRESSIVE],PETSC_NULL);

205:   /* Control parameters used by numeric factorization */
206:   PetscOptionsReal("-mat_umfpack_pivot_tolerance","Control[UMFPACK_PIVOT_TOLERANCE]","None",lu->Control[UMFPACK_PIVOT_TOLERANCE],&lu->Control[UMFPACK_PIVOT_TOLERANCE],PETSC_NULL);
207:   PetscOptionsReal("-mat_umfpack_sym_pivot_tolerance","Control[UMFPACK_SYM_PIVOT_TOLERANCE]","None",lu->Control[UMFPACK_SYM_PIVOT_TOLERANCE],&lu->Control[UMFPACK_SYM_PIVOT_TOLERANCE],PETSC_NULL);
208:   PetscOptionsEList("-mat_umfpack_scale","Control[UMFPACK_SCALE]","None",scale,3,scale[0],&idx,&flg);
209:   if (flg) {
210:     switch (idx){
211:     case 0: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_NONE; break;
212:     case 1: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_SUM; break;
213:     case 2: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_MAX; break;
214:     }
215:   }
216:   PetscOptionsReal("-mat_umfpack_alloc_init","Control[UMFPACK_ALLOC_INIT]","None",lu->Control[UMFPACK_ALLOC_INIT],&lu->Control[UMFPACK_ALLOC_INIT],PETSC_NULL);
217:   PetscOptionsReal("-mat_umfpack_front_alloc_init","Control[UMFPACK_FRONT_ALLOC_INIT]","None",lu->Control[UMFPACK_FRONT_ALLOC_INIT],&lu->Control[UMFPACK_ALLOC_INIT],PETSC_NULL);
218:   PetscOptionsReal("-mat_umfpack_droptol","Control[UMFPACK_DROPTOL]","None",lu->Control[UMFPACK_DROPTOL],&lu->Control[UMFPACK_DROPTOL],PETSC_NULL);

220:   /* Control parameters used by solve */
221:   PetscOptionsReal("-mat_umfpack_irstep","Control[UMFPACK_IRSTEP]","None",lu->Control[UMFPACK_IRSTEP],&lu->Control[UMFPACK_IRSTEP],PETSC_NULL);
222: 
223:   /* use Petsc mat ordering (note: size is for the transpose, and PETSc r = Umfpack perm_c) */
224:   PetscOptionsHasName(PETSC_NULL,"-pc_lu_mat_ordering_type",&lu->PetscMatOdering);
225:   if (lu->PetscMatOdering) {
226:     ISGetIndices(r,&ra);
227:     PetscMalloc(A->m*sizeof(int),&lu->perm_c);
228:     PetscMemcpy(lu->perm_c,ra,A->m*sizeof(int));
229:     ISRestoreIndices(r,&ra);
230:   }
231:   PetscOptionsEnd();

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

236:   /* symbolic factorization of A' */
237:   /* ---------------------------------------------------------------------- */
238:   if (lu->PetscMatOdering) { /* use Petsc row ordering */
239:     status = umfpack_di_qsymbolic(n,m,ai,aj,av,lu->perm_c,&lu->Symbolic,lu->Control,lu->Info);
240:   } else { /* use Umfpack col ordering */
241:     status = umfpack_di_symbolic(n,m,ai,aj,av,&lu->Symbolic,lu->Control,lu->Info);
242:   }
243:   if (status < 0){
244:     umfpack_di_report_info(lu->Control, lu->Info);
245:     umfpack_di_report_status(lu->Control, status);
246:     SETERRQ(PETSC_ERR_LIB,"umfpack_di_symbolic failed");
247:   }
248:   /* report sumbolic factorization of A' when Control[PRL] > 3 */
249:   (void) umfpack_di_report_symbolic(lu->Symbolic, lu->Control);

251:   lu->flg = DIFFERENT_NONZERO_PATTERN;
252:   lu->ai  = ai;
253:   lu->aj  = aj;
254:   lu->av  = av;
255:   lu->CleanUpUMFPACK = PETSC_TRUE;
256:   *F = B;
257:   return(0);
258: }

262: PetscErrorCode MatAssemblyEnd_UMFPACK(Mat A,MatAssemblyType mode)
263: {
265:   Mat_UMFPACK *lu=(Mat_UMFPACK*)(A->spptr);

268:   (*lu->MatAssemblyEnd)(A,mode);
269:   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
270:   A->ops->lufactorsymbolic = MatLUFactorSymbolic_UMFPACK;
271:   return(0);
272: }

274: /* used by -ksp_view */
277: PetscErrorCode MatFactorInfo_UMFPACK(Mat A,PetscViewer viewer)
278: {
279:   Mat_UMFPACK *lu= (Mat_UMFPACK*)A->spptr;

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

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

290:   /* Control parameters used by symbolic factorization */
291:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_STRATEGY]: %g\n",lu->Control[UMFPACK_STRATEGY]);
292:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DENSE_COL]: %g\n",lu->Control[UMFPACK_DENSE_COL]);
293:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DENSE_ROW]: %g\n",lu->Control[UMFPACK_DENSE_ROW]);
294:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_AMD_DENSE]: %g\n",lu->Control[UMFPACK_AMD_DENSE]);
295:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_BLOCK_SIZE]: %g\n",lu->Control[UMFPACK_BLOCK_SIZE]);
296:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_2BY2_TOLERANCE]: %g\n",lu->Control[UMFPACK_2BY2_TOLERANCE]);
297:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_FIXQ]: %g\n",lu->Control[UMFPACK_FIXQ]);
298:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_AGGRESSIVE]: %g\n",lu->Control[UMFPACK_AGGRESSIVE]);

300:   /* Control parameters used by numeric factorization */
301:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_PIVOT_TOLERANCE]: %g\n",lu->Control[UMFPACK_PIVOT_TOLERANCE]);
302:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_SYM_PIVOT_TOLERANCE]: %g\n",lu->Control[UMFPACK_SYM_PIVOT_TOLERANCE]);
303:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_SCALE]: %g\n",lu->Control[UMFPACK_SCALE]);
304:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_ALLOC_INIT]: %g\n",lu->Control[UMFPACK_ALLOC_INIT]);
305:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DROPTOL]: %g\n",lu->Control[UMFPACK_DROPTOL]);

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

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

313:   return(0);
314: }

318: PetscErrorCode MatView_UMFPACK(Mat A,PetscViewer viewer)
319: {
321:   PetscTruth        iascii;
322:   PetscViewerFormat format;
323:   Mat_UMFPACK       *lu=(Mat_UMFPACK*)(A->spptr);

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

328:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
329:   if (iascii) {
330:     PetscViewerGetFormat(viewer,&format);
331:     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
332:       MatFactorInfo_UMFPACK(A,viewer);
333:     }
334:   }
335:   return(0);
336: }

341: PetscErrorCode MatConvert_SeqAIJ_UMFPACK(Mat A,const MatType type,Mat *newmat)
342: {
343:   /* This routine is only called to convert to MATUMFPACK */
344:   /* from MATSEQAIJ, so we will ignore 'MatType type'. */
346:   Mat         B=*newmat;
347:   Mat_UMFPACK *lu;

350:   if (B != A) {
351:     MatDuplicate(A,MAT_COPY_VALUES,&B);
352:   }

354:   PetscNew(Mat_UMFPACK,&lu);
355:   lu->MatDuplicate         = A->ops->duplicate;
356:   lu->MatView              = A->ops->view;
357:   lu->MatAssemblyEnd       = A->ops->assemblyend;
358:   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
359:   lu->MatDestroy           = A->ops->destroy;
360:   lu->CleanUpUMFPACK       = PETSC_FALSE;

362:   B->spptr                 = (void*)lu;
363:   B->ops->duplicate        = MatDuplicate_UMFPACK;
364:   B->ops->view             = MatView_UMFPACK;
365:   B->ops->assemblyend      = MatAssemblyEnd_UMFPACK;
366:   B->ops->lufactorsymbolic = MatLUFactorSymbolic_UMFPACK;
367:   B->ops->destroy          = MatDestroy_UMFPACK;

369:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_umfpack_C",
370:                                            "MatConvert_SeqAIJ_UMFPACK",MatConvert_SeqAIJ_UMFPACK);
371:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_umfpack_seqaij_C",
372:                                            "MatConvert_UMFPACK_SeqAIJ",MatConvert_UMFPACK_SeqAIJ);
373:   PetscLogInfo(0,"Using UMFPACK for SeqAIJ LU factorization and solves.");
374:   PetscObjectChangeTypeName((PetscObject)B,MATUMFPACK);
375:   *newmat = B;
376:   return(0);
377: }

382: PetscErrorCode MatDuplicate_UMFPACK(Mat A, MatDuplicateOption op, Mat *M)
383: {
385:   Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;

388:   (*lu->MatDuplicate)(A,op,M);
389:   PetscMemcpy((*M)->spptr,lu,sizeof(Mat_UMFPACK));
390:   return(0);
391: }

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

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

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

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

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

419:    Level: beginner

421: .seealso: PCLU
422: M*/

427: PetscErrorCode MatCreate_UMFPACK(Mat A)
428: {

432:   /* Change type name before calling MatSetType to force proper construction of SeqAIJ and UMFPACK types */
433:   PetscObjectChangeTypeName((PetscObject)A,MATUMFPACK);
434:   MatSetType(A,MATSEQAIJ);
435:   MatConvert_SeqAIJ_UMFPACK(A,MATUMFPACK,&A);
436:   return(0);
437: }