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