xref: /petsc/src/ksp/pc/impls/tfs/tfs.c (revision 2205254efee3a00a594e5e2a3a70f74dcb40bc03)
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 #undef __FUNCT__
17 #define __FUNCT__ "PCDestroy_TFS"
18 PetscErrorCode PCDestroy_TFS(PC pc)
19 {
20   PC_TFS         *tfs = (PC_TFS*)pc->data;
21   PetscErrorCode ierr;
22 
23   PetscFunctionBegin;
24   /* free the XXT datastructures */
25   if (tfs->xxt) {
26     ierr = XXT_free(tfs->xxt);CHKERRQ(ierr);
27   }
28   if (tfs->xyt) {
29     ierr = XYT_free(tfs->xyt);CHKERRQ(ierr);
30   }
31   ierr = VecDestroy(&tfs->b);CHKERRQ(ierr);
32   ierr = VecDestroy(&tfs->xd);CHKERRQ(ierr);
33   ierr = VecDestroy(&tfs->xo);CHKERRQ(ierr);
34   ierr = PetscFree(pc->data);CHKERRQ(ierr);
35   PetscFunctionReturn(0);
36 }
37 
38 #undef __FUNCT__
39 #define __FUNCT__ "PCApply_TFS_XXT"
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;
44   PetscErrorCode ierr;
45 
46   PetscFunctionBegin;
47   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
48   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
49   ierr = XXT_solve(tfs->xxt,yy,xx);CHKERRQ(ierr);
50   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
51   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
52   PetscFunctionReturn(0);
53 }
54 
55 #undef __FUNCT__
56 #define __FUNCT__ "PCApply_TFS_XYT"
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;
61   PetscErrorCode ierr;
62 
63   PetscFunctionBegin;
64   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
65   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
66   ierr = XYT_solve(tfs->xyt,yy,xx);CHKERRQ(ierr);
67   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
68   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
69   PetscFunctionReturn(0);
70 }
71 
72 #undef __FUNCT__
73 #define __FUNCT__ "PCTFSLocalMult_TFS"
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;
79   PetscErrorCode ierr;
80 
81   PetscFunctionBegin;
82   ierr = VecPlaceArray(tfs->b,xout);CHKERRQ(ierr);
83   ierr = VecPlaceArray(tfs->xd,xin);CHKERRQ(ierr);
84   ierr = VecPlaceArray(tfs->xo,xin+tfs->nd);CHKERRQ(ierr);
85   ierr = MatMult(a->A,tfs->xd,tfs->b);CHKERRQ(ierr);
86   ierr = MatMultAdd(a->B,tfs->xo,tfs->b,tfs->b);CHKERRQ(ierr);
87   ierr = VecResetArray(tfs->b);CHKERRQ(ierr);
88   ierr = VecResetArray(tfs->xd);CHKERRQ(ierr);
89   ierr = VecResetArray(tfs->xo);CHKERRQ(ierr);
90   PetscFunctionReturn(0);
91 }
92 
93 #undef __FUNCT__
94 #define __FUNCT__ "PCSetUp_TFS"
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;
100   PetscErrorCode ierr;
101   PetscInt       *localtoglobal,ncol,i;
102   PetscBool      ismpiaij;
103 
104   /*
105   PetscBool      issymmetric;
106   Petsc Real tol = 0.0;
107   */
108 
109   PetscFunctionBegin;
110   if (A->cmap->N != A->rmap->N) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_SIZ,"matrix must be square");
111   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
112   if (!ismpiaij) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Currently only supports MPIAIJ matrices");
113 
114   /* generate the local to global mapping */
115   ncol = a->A->cmap->n + a->B->cmap->n;
116   ierr = PetscMalloc((ncol)*sizeof(PetscInt),&localtoglobal);CHKERRQ(ierr);
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;
119 
120   /* generate the vectors needed for the local solves */
121   ierr    = VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->A->rmap->n,PETSC_NULL,&tfs->b);CHKERRQ(ierr);
122   ierr    = VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->A->cmap->n,PETSC_NULL,&tfs->xd);CHKERRQ(ierr);
123   ierr    = VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->B->cmap->n,PETSC_NULL,&tfs->xo);CHKERRQ(ierr);
124   tfs->nd = a->A->cmap->n;
125 
126 
127   /*  ierr =  MatIsSymmetric(A,tol,&issymmetric); */
128   /*  if (issymmetric) { */
129   ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
130   if (A->symmetric) {
131     tfs->xxt       = XXT_new();
132     ierr           = XXT_factor(tfs->xxt,localtoglobal,A->rmap->n,ncol,(PetscErrorCode (*)(void*,PetscScalar*,PetscScalar*))PCTFSLocalMult_TFS,pc);CHKERRQ(ierr);
133     pc->ops->apply = PCApply_TFS_XXT;
134   } else {
135     tfs->xyt       = XYT_new();
136     ierr           = XYT_factor(tfs->xyt,localtoglobal,A->rmap->n,ncol,(PetscErrorCode (*)(void*,PetscScalar*,PetscScalar*))PCTFSLocalMult_TFS,pc);CHKERRQ(ierr);
137     pc->ops->apply = PCApply_TFS_XYT;
138   }
139 
140   ierr = PetscFree(localtoglobal);CHKERRQ(ierr);
141   PetscFunctionReturn(0);
142 }
143 
144 #undef __FUNCT__
145 #define __FUNCT__ "PCSetFromOptions_TFS"
146 static PetscErrorCode PCSetFromOptions_TFS(PC pc)
147 {
148   PetscFunctionBegin;
149   PetscFunctionReturn(0);
150 }
151 #undef __FUNCT__
152 #define __FUNCT__ "PCView_TFS"
153 static PetscErrorCode PCView_TFS(PC pc,PetscViewer viewer)
154 {
155   PetscFunctionBegin;
156   PetscFunctionReturn(0);
157 }
158 
159 EXTERN_C_BEGIN
160 #undef __FUNCT__
161 #define __FUNCT__ "PCCreate_TFS"
162 /*MC
163      PCTFS - A parallel direct solver intended for problems with very few unknowns (like the
164          coarse grid in multigrid).
165 
166    Implemented by  Henry M. Tufo III and Paul Fischer
167 
168    Level: beginner
169 
170    Notes: Only implemented for the MPIAIJ matrices
171 
172           Only works on a solver object that lives on all of PETSC_COMM_WORLD!
173 
174 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC
175 M*/
176 PetscErrorCode  PCCreate_TFS(PC pc)
177 {
178   PetscErrorCode ierr;
179   PC_TFS         *tfs;
180   PetscMPIInt    cmp;
181 
182   PetscFunctionBegin;
183   ierr = MPI_Comm_compare(PETSC_COMM_WORLD,((PetscObject)pc)->comm,&cmp);CHKERRQ(ierr);
184   if (cmp != MPI_IDENT && cmp != MPI_CONGRUENT) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_SUP,"TFS only works with PETSC_COMM_WORLD objects");
185   ierr = PetscNewLog(pc,PC_TFS,&tfs);CHKERRQ(ierr);
186 
187   tfs->xxt = 0;
188   tfs->xyt = 0;
189   tfs->b   = 0;
190   tfs->xd  = 0;
191   tfs->xo  = 0;
192   tfs->nd  = 0;
193 
194   pc->ops->apply               = 0;
195   pc->ops->applytranspose      = 0;
196   pc->ops->setup               = PCSetUp_TFS;
197   pc->ops->destroy             = PCDestroy_TFS;
198   pc->ops->setfromoptions      = PCSetFromOptions_TFS;
199   pc->ops->view                = PCView_TFS;
200   pc->ops->applyrichardson     = 0;
201   pc->ops->applysymmetricleft  = 0;
202   pc->ops->applysymmetricright = 0;
203   pc->data                     = (void*)tfs;
204   PetscFunctionReturn(0);
205 }
206 EXTERN_C_END
207 
208