xref: /petsc/src/ksp/pc/impls/tfs/tfs.c (revision bebe2cf65d55febe21a5af8db2bd2e168caaa2e7)
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(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_SIZ,"matrix must be square");
111   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
112   if (!ismpiaij) SETERRQ(PetscObjectComm((PetscObject)pc),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 = PetscMalloc1(ncol,&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,NULL,&tfs->b);CHKERRQ(ierr);
122   ierr    = VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->A->cmap->n,NULL,&tfs->xd);CHKERRQ(ierr);
123   ierr    = VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->B->cmap->n,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(PetscOptions *PetscOptionsObject,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 #undef __FUNCT__
160 #define __FUNCT__ "PCCreate_TFS"
161 /*MC
162      PCTFS - A parallel direct solver intended for problems with very few unknowns (like the
163          coarse grid in multigrid).
164 
165    Implemented by  Henry M. Tufo III and Paul Fischer
166 
167    Level: beginner
168 
169    Notes: Only implemented for the MPIAIJ matrices
170 
171           Only works on a solver object that lives on all of PETSC_COMM_WORLD!
172 
173 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC
174 M*/
175 PETSC_EXTERN PetscErrorCode PCCreate_TFS(PC pc)
176 {
177   PetscErrorCode ierr;
178   PC_TFS         *tfs;
179   PetscMPIInt    cmp;
180 
181   PetscFunctionBegin;
182   ierr = MPI_Comm_compare(PETSC_COMM_WORLD,PetscObjectComm((PetscObject)pc),&cmp);CHKERRQ(ierr);
183   if (cmp != MPI_IDENT && cmp != MPI_CONGRUENT) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"TFS only works with PETSC_COMM_WORLD objects");
184   ierr = PetscNewLog(pc,&tfs);CHKERRQ(ierr);
185 
186   tfs->xxt = 0;
187   tfs->xyt = 0;
188   tfs->b   = 0;
189   tfs->xd  = 0;
190   tfs->xo  = 0;
191   tfs->nd  = 0;
192 
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   PetscFunctionReturn(0);
204 }
205 
206