Actual source code: tfs.c
petsc-3.7.7 2017-09-25
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;
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(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_SIZ,"matrix must be square");
111: PetscObjectTypeCompare((PetscObject)pc->pmat,MATMPIAIJ,&ismpiaij);
112: if (!ismpiaij) SETERRQ(PetscObjectComm((PetscObject)pc),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: PetscMalloc1(ncol,&localtoglobal);
117: for (i=0; i<a->A->cmap->n; i++) localtoglobal[i] = A->cmap->rstart + i + 1;
118: for (i=0; i<a->B->cmap->n; i++) localtoglobal[i+a->A->cmap->n] = a->garray[i] + 1;
120: /* generate the vectors needed for the local solves */
121: VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->A->rmap->n,NULL,&tfs->b);
122: VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->A->cmap->n,NULL,&tfs->xd);
123: VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->B->cmap->n,NULL,&tfs->xo);
124: tfs->nd = a->A->cmap->n;
127: /* MatIsSymmetric(A,tol,&issymmetric); */
128: /* if (issymmetric) { */
129: PetscBarrier((PetscObject)pc);
130: if (A->symmetric) {
131: tfs->xxt = XXT_new();
132: XXT_factor(tfs->xxt,localtoglobal,A->rmap->n,ncol,(PetscErrorCode (*)(void*,PetscScalar*,PetscScalar*))PCTFSLocalMult_TFS,pc);
133: pc->ops->apply = PCApply_TFS_XXT;
134: } else {
135: tfs->xyt = XYT_new();
136: XYT_factor(tfs->xyt,localtoglobal,A->rmap->n,ncol,(PetscErrorCode (*)(void*,PetscScalar*,PetscScalar*))PCTFSLocalMult_TFS,pc);
137: pc->ops->apply = PCApply_TFS_XYT;
138: }
140: PetscFree(localtoglobal);
141: return(0);
142: }
146: static PetscErrorCode PCSetFromOptions_TFS(PetscOptionItems *PetscOptionsObject,PC pc)
147: {
149: return(0);
150: }
153: static PetscErrorCode PCView_TFS(PC pc,PetscViewer viewer)
154: {
156: return(0);
157: }
161: /*MC
162: PCTFS - A parallel direct solver intended for problems with very few unknowns (like the
163: coarse grid in multigrid).
165: Implemented by Henry M. Tufo III and Paul Fischer
167: Level: beginner
169: Notes: Only implemented for the MPIAIJ matrices
171: Only works on a solver object that lives on all of PETSC_COMM_WORLD!
173: .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC
174: M*/
175: PETSC_EXTERN PetscErrorCode PCCreate_TFS(PC pc)
176: {
178: PC_TFS *tfs;
179: PetscMPIInt cmp;
182: MPI_Comm_compare(PETSC_COMM_WORLD,PetscObjectComm((PetscObject)pc),&cmp);
183: if (cmp != MPI_IDENT && cmp != MPI_CONGRUENT) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"TFS only works with PETSC_COMM_WORLD objects");
184: PetscNewLog(pc,&tfs);
186: tfs->xxt = 0;
187: tfs->xyt = 0;
188: tfs->b = 0;
189: tfs->xd = 0;
190: tfs->xo = 0;
191: tfs->nd = 0;
193: pc->ops->apply = 0;
194: pc->ops->applytranspose = 0;
195: pc->ops->setup = PCSetUp_TFS;
196: pc->ops->destroy = PCDestroy_TFS;
197: pc->ops->setfromoptions = PCSetFromOptions_TFS;
198: pc->ops->view = PCView_TFS;
199: pc->ops->applyrichardson = 0;
200: pc->ops->applysymmetricleft = 0;
201: pc->ops->applysymmetricright = 0;
202: pc->data = (void*)tfs;
203: return(0);
204: }