Actual source code: tfs.c

petsc-3.3-p7 2013-05-11
  1: /* 
  2:         Provides an interface to the Tufo-Fischer parallel direct solver
  3: */

  5: #include <petsc-private/pcimpl.h>   /*I "petscpc.h" I*/
  6: #include <../src/mat/impls/aij/mpi/mpiaij.h>
  7: #include <../src/ksp/pc/impls/tfs/tfs.h>

  9: typedef struct {
 10:   xxt_ADT  xxt;
 11:   xyt_ADT  xyt;
 12:   Vec      b,xd,xo;
 13:   PetscInt nd;
 14: } PC_TFS;

 18: PetscErrorCode PCDestroy_TFS(PC pc)
 19: {
 20:   PC_TFS *tfs = (PC_TFS*)pc->data;

 24:   /* free the XXT datastructures */
 25:   if (tfs->xxt) {
 26:     XXT_free(tfs->xxt);
 27:   }
 28:   if (tfs->xyt) {
 29:     XYT_free(tfs->xyt);
 30:   }
 31:   VecDestroy(&tfs->b);
 32:   VecDestroy(&tfs->xd);
 33:   VecDestroy(&tfs->xo);
 34:   PetscFree(pc->data);
 35:   return(0);
 36: }

 40: static PetscErrorCode PCApply_TFS_XXT(PC pc,Vec x,Vec y)
 41: {
 42:   PC_TFS *tfs = (PC_TFS*)pc->data;
 43:   PetscScalar    *xx,*yy;

 47:   VecGetArray(x,&xx);
 48:   VecGetArray(y,&yy);
 49:   XXT_solve(tfs->xxt,yy,xx);
 50:   VecRestoreArray(x,&xx);
 51:   VecRestoreArray(y,&yy);
 52:   return(0);
 53: }

 57: static PetscErrorCode PCApply_TFS_XYT(PC pc,Vec x,Vec y)
 58: {
 59:   PC_TFS *tfs = (PC_TFS*)pc->data;
 60:   PetscScalar    *xx,*yy;

 64:   VecGetArray(x,&xx);
 65:   VecGetArray(y,&yy);
 66:   XYT_solve(tfs->xyt,yy,xx);
 67:   VecRestoreArray(x,&xx);
 68:   VecRestoreArray(y,&yy);
 69:   return(0);
 70: }

 74: static PetscErrorCode PCTFSLocalMult_TFS(PC pc,PetscScalar *xin,PetscScalar *xout)
 75: {
 76:   PC_TFS        *tfs = (PC_TFS*)pc->data;
 77:   Mat           A = pc->pmat;
 78:   Mat_MPIAIJ    *a = (Mat_MPIAIJ*)A->data;
 80: 
 82:   VecPlaceArray(tfs->b,xout);
 83:   VecPlaceArray(tfs->xd,xin);
 84:   VecPlaceArray(tfs->xo,xin+tfs->nd);
 85:   MatMult(a->A,tfs->xd,tfs->b);
 86:   MatMultAdd(a->B,tfs->xo,tfs->b,tfs->b);
 87:   VecResetArray(tfs->b);
 88:   VecResetArray(tfs->xd);
 89:   VecResetArray(tfs->xo);
 90:   return(0);
 91: }

 95: static PetscErrorCode PCSetUp_TFS(PC pc)
 96: {
 97:   PC_TFS        *tfs = (PC_TFS*)pc->data;
 98:   Mat            A = pc->pmat;
 99:   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
101:   PetscInt      *localtoglobal,ncol,i;
102:   PetscBool      ismpiaij;

104:   /*
105:   PetscBool      issymmetric;
106:   Petsc Real tol = 0.0;
107:   */

110:   if (A->cmap->N != A->rmap->N) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_SIZ,"matrix must be square");
111:   PetscObjectTypeCompare((PetscObject)pc->pmat,MATMPIAIJ,&ismpiaij);
112:   if (!ismpiaij) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Currently only supports MPIAIJ matrices");

114:   /* generate the local to global mapping */
115:   ncol = a->A->cmap->n + a->B->cmap->n;
116:   PetscMalloc((ncol)*sizeof(PetscInt),&localtoglobal);
117:   for (i=0; i<a->A->cmap->n; i++) {
118:     localtoglobal[i] = A->cmap->rstart + i + 1;
119:   }
120:   for (i=0; i<a->B->cmap->n; i++) {
121:     localtoglobal[i+a->A->cmap->n] = a->garray[i] + 1;
122:   }
123:   /* generate the vectors needed for the local solves */
124:   VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->A->rmap->n,PETSC_NULL,&tfs->b);
125:   VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->A->cmap->n,PETSC_NULL,&tfs->xd);
126:   VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->B->cmap->n,PETSC_NULL,&tfs->xo);
127:   tfs->nd = a->A->cmap->n;


130:   /*   MatIsSymmetric(A,tol,&issymmetric); */
131:   /*  if (issymmetric) { */
132:   PetscBarrier((PetscObject)pc);
133:   if (A->symmetric) {
134:     tfs->xxt       = XXT_new();
135:     XXT_factor(tfs->xxt,localtoglobal,A->rmap->n,ncol,(void*)PCTFSLocalMult_TFS,pc);
136:     pc->ops->apply = PCApply_TFS_XXT;
137:   } else {
138:     tfs->xyt       = XYT_new();
139:     XYT_factor(tfs->xyt,localtoglobal,A->rmap->n,ncol,(void*)PCTFSLocalMult_TFS,pc);
140:     pc->ops->apply = PCApply_TFS_XYT;
141:   }

143:   PetscFree(localtoglobal);
144:   return(0);
145: }

149: static PetscErrorCode PCSetFromOptions_TFS(PC pc)
150: {
152:   return(0);
153: }
156: static PetscErrorCode PCView_TFS(PC pc,PetscViewer viewer)
157: {
159:   return(0);
160: }

162: EXTERN_C_BEGIN
165: /*MC
166:      PCTFS - A parallel direct solver intended for problems with very few unknowns (like the 
167:          coarse grid in multigrid).

169:    Implemented by  Henry M. Tufo III and Paul Fischer

171:    Level: beginner

173:    Notes: Only implemented for the MPIAIJ matrices

175:           Only works on a solver object that lives on all of PETSC_COMM_WORLD!

177: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC
178: M*/
179: PetscErrorCode  PCCreate_TFS(PC pc)
180: {
182:   PC_TFS         *tfs;
183:   PetscMPIInt    cmp;

186:   MPI_Comm_compare(PETSC_COMM_WORLD,((PetscObject)pc)->comm,&cmp);
187:   if (cmp != MPI_IDENT && cmp != MPI_CONGRUENT) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_SUP,"TFS only works with PETSC_COMM_WORLD objects");
188:   PetscNewLog(pc,PC_TFS,&tfs);

190:   tfs->xxt = 0;
191:   tfs->xyt = 0;
192:   tfs->b   = 0;
193:   tfs->xd  = 0;
194:   tfs->xo  = 0;
195:   tfs->nd  = 0;

197:   pc->ops->apply               = 0;
198:   pc->ops->applytranspose      = 0;
199:   pc->ops->setup               = PCSetUp_TFS;
200:   pc->ops->destroy             = PCDestroy_TFS;
201:   pc->ops->setfromoptions      = PCSetFromOptions_TFS;
202:   pc->ops->view                = PCView_TFS;
203:   pc->ops->applyrichardson     = 0;
204:   pc->ops->applysymmetricleft  = 0;
205:   pc->ops->applysymmetricright = 0;
206:   pc->data                     = (void*)tfs;
207:   return(0);
208: }
209: EXTERN_C_END