xref: /petsc/src/ksp/pc/impls/tfs/tfs.c (revision 117ef88edefbfc12e7c19efe87a19a2e1b0acd4f)
1 /*
2         Provides an interface to the Tufo-Fischer parallel direct solver
3 */
4 
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>
8 
9 typedef struct {
10   xxt_ADT  xxt;
11   xyt_ADT  xyt;
12   Vec      b,xd,xo;
13   PetscInt nd;
14 } PC_TFS;
15 
16 PetscErrorCode PCDestroy_TFS(PC pc)
17 {
18   PC_TFS         *tfs = (PC_TFS*)pc->data;
19   PetscErrorCode ierr;
20 
21   PetscFunctionBegin;
22   /* free the XXT datastructures */
23   if (tfs->xxt) {
24     ierr = XXT_free(tfs->xxt);CHKERRQ(ierr);
25   }
26   if (tfs->xyt) {
27     ierr = XYT_free(tfs->xyt);CHKERRQ(ierr);
28   }
29   ierr = VecDestroy(&tfs->b);CHKERRQ(ierr);
30   ierr = VecDestroy(&tfs->xd);CHKERRQ(ierr);
31   ierr = VecDestroy(&tfs->xo);CHKERRQ(ierr);
32   ierr = PetscFree(pc->data);CHKERRQ(ierr);
33   PetscFunctionReturn(0);
34 }
35 
36 static PetscErrorCode PCApply_TFS_XXT(PC pc,Vec x,Vec y)
37 {
38   PC_TFS            *tfs = (PC_TFS*)pc->data;
39   PetscScalar       *yy;
40   const PetscScalar *xx;
41   PetscErrorCode    ierr;
42 
43   PetscFunctionBegin;
44   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
45   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
46   ierr = XXT_solve(tfs->xxt,yy,(PetscScalar*)xx);CHKERRQ(ierr);
47   ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
48   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
49   PetscFunctionReturn(0);
50 }
51 
52 static PetscErrorCode PCApply_TFS_XYT(PC pc,Vec x,Vec y)
53 {
54   PC_TFS            *tfs = (PC_TFS*)pc->data;
55   PetscScalar       *yy;
56   const PetscScalar *xx;
57   PetscErrorCode    ierr;
58 
59   PetscFunctionBegin;
60   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
61   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
62   ierr = XYT_solve(tfs->xyt,yy,(PetscScalar*)xx);CHKERRQ(ierr);
63   ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
64   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
65   PetscFunctionReturn(0);
66 }
67 
68 static PetscErrorCode PCTFSLocalMult_TFS(PC pc,PetscScalar *xin,PetscScalar *xout)
69 {
70   PC_TFS         *tfs = (PC_TFS*)pc->data;
71   Mat            A    = pc->pmat;
72   Mat_MPIAIJ     *a   = (Mat_MPIAIJ*)A->data;
73   PetscErrorCode ierr;
74 
75   PetscFunctionBegin;
76   ierr = VecPlaceArray(tfs->b,xout);CHKERRQ(ierr);
77   ierr = VecPlaceArray(tfs->xd,xin);CHKERRQ(ierr);
78   ierr = VecPlaceArray(tfs->xo,xin+tfs->nd);CHKERRQ(ierr);
79   ierr = MatMult(a->A,tfs->xd,tfs->b);CHKERRQ(ierr);
80   ierr = MatMultAdd(a->B,tfs->xo,tfs->b,tfs->b);CHKERRQ(ierr);
81   ierr = VecResetArray(tfs->b);CHKERRQ(ierr);
82   ierr = VecResetArray(tfs->xd);CHKERRQ(ierr);
83   ierr = VecResetArray(tfs->xo);CHKERRQ(ierr);
84   PetscFunctionReturn(0);
85 }
86 
87 static PetscErrorCode PCSetUp_TFS(PC pc)
88 {
89   PC_TFS         *tfs = (PC_TFS*)pc->data;
90   Mat            A    = pc->pmat;
91   Mat_MPIAIJ     *a   = (Mat_MPIAIJ*)A->data;
92   PetscErrorCode ierr;
93   PetscInt       *localtoglobal,ncol,i;
94   PetscBool      ismpiaij;
95 
96   /*
97   PetscBool      issymmetric;
98   Petsc Real tol = 0.0;
99   */
100 
101   PetscFunctionBegin;
102   if (A->cmap->N != A->rmap->N) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_SIZ,"matrix must be square");
103   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
104   if (!ismpiaij) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Currently only supports MPIAIJ matrices");
105 
106   /* generate the local to global mapping */
107   ncol = a->A->cmap->n + a->B->cmap->n;
108   ierr = PetscMalloc1(ncol,&localtoglobal);CHKERRQ(ierr);
109   for (i=0; i<a->A->cmap->n; i++) localtoglobal[i] = A->cmap->rstart + i + 1;
110   for (i=0; i<a->B->cmap->n; i++) localtoglobal[i+a->A->cmap->n] = a->garray[i] + 1;
111 
112   /* generate the vectors needed for the local solves */
113   ierr    = VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->A->rmap->n,NULL,&tfs->b);CHKERRQ(ierr);
114   ierr    = VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->A->cmap->n,NULL,&tfs->xd);CHKERRQ(ierr);
115   ierr    = VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->B->cmap->n,NULL,&tfs->xo);CHKERRQ(ierr);
116   tfs->nd = a->A->cmap->n;
117 
118 
119   /*  ierr =  MatIsSymmetric(A,tol,&issymmetric); */
120   /*  if (issymmetric) { */
121   ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
122   if (A->symmetric) {
123     tfs->xxt       = XXT_new();
124     ierr           = XXT_factor(tfs->xxt,localtoglobal,A->rmap->n,ncol,(PetscErrorCode (*)(void*,PetscScalar*,PetscScalar*))PCTFSLocalMult_TFS,pc);CHKERRQ(ierr);
125     pc->ops->apply = PCApply_TFS_XXT;
126   } else {
127     tfs->xyt       = XYT_new();
128     ierr           = XYT_factor(tfs->xyt,localtoglobal,A->rmap->n,ncol,(PetscErrorCode (*)(void*,PetscScalar*,PetscScalar*))PCTFSLocalMult_TFS,pc);CHKERRQ(ierr);
129     pc->ops->apply = PCApply_TFS_XYT;
130   }
131 
132   ierr = PetscFree(localtoglobal);CHKERRQ(ierr);
133   PetscFunctionReturn(0);
134 }
135 
136 static PetscErrorCode PCSetFromOptions_TFS(PetscOptionItems *PetscOptionsObject,PC pc)
137 {
138   PetscFunctionBegin;
139   PetscFunctionReturn(0);
140 }
141 static PetscErrorCode PCView_TFS(PC pc,PetscViewer viewer)
142 {
143   PetscFunctionBegin;
144   PetscFunctionReturn(0);
145 }
146 
147 /*MC
148      PCTFS - A parallel direct solver intended for problems with very few unknowns (like the
149          coarse grid in multigrid). Performs a Cholesky or LU factorization of a matrix defined by
150          its local matrix vector product.
151 
152    Implemented by  Henry M. Tufo III and Paul Fischer originally for Nek5000 and called XXT or XYT
153 
154    Level: beginner
155 
156    Notes:
157     Only implemented for the MPIAIJ matrices
158 
159     Only works on a solver object that lives on all of PETSC_COMM_WORLD!
160 
161     Only works for real numbers (is not built if PetscScalar is complex)
162 
163 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC
164 M*/
165 PETSC_EXTERN PetscErrorCode PCCreate_TFS(PC pc)
166 {
167   PetscErrorCode ierr;
168   PC_TFS         *tfs;
169   PetscMPIInt    cmp;
170 
171   PetscFunctionBegin;
172   ierr = MPI_Comm_compare(PETSC_COMM_WORLD,PetscObjectComm((PetscObject)pc),&cmp);CHKERRQ(ierr);
173   if (cmp != MPI_IDENT && cmp != MPI_CONGRUENT) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"TFS only works with PETSC_COMM_WORLD objects");
174   ierr = PetscNewLog(pc,&tfs);CHKERRQ(ierr);
175 
176   tfs->xxt = NULL;
177   tfs->xyt = NULL;
178   tfs->b   = NULL;
179   tfs->xd  = NULL;
180   tfs->xo  = NULL;
181   tfs->nd  = 0;
182 
183   pc->ops->apply               = NULL;
184   pc->ops->applytranspose      = NULL;
185   pc->ops->setup               = PCSetUp_TFS;
186   pc->ops->destroy             = PCDestroy_TFS;
187   pc->ops->setfromoptions      = PCSetFromOptions_TFS;
188   pc->ops->view                = PCView_TFS;
189   pc->ops->applyrichardson     = NULL;
190   pc->ops->applysymmetricleft  = NULL;
191   pc->ops->applysymmetricright = NULL;
192   pc->data                     = (void*)tfs;
193   PetscFunctionReturn(0);
194 }
195 
196