xref: /petsc/src/dm/impls/patch/patch.c (revision 5abee1b0b3222114477266f27b16603976fd612a)
1 #include <petsc-private/patchimpl.h>   /*I      "petscdmpatch.h"   I*/
2 #include <petscdmda.h>
3 
4 /*
5 Solver loop to update \tau:
6 
7   DMZoom(dmc, &dmz)
8   DMRefine(dmz, &dmf),
9   Scatter Xcoarse -> Xzoom,
10   Interpolate Xzoom -> Xfine (note that this may be on subcomms),
11   Smooth Xfine using two-step smoother
12     normal smoother plus Kaczmarz---moves back and forth from dmzoom to dmfine
13   Compute residual Rfine
14   Restrict Rfine to Rzoom_restricted
15   Scatter Rzoom_restricted -> Rcoarse_restricted
16   Compute global residual Rcoarse
17   TauCoarse = Rcoarse - Rcoarse_restricted
18 */
19 
20 #undef __FUNCT__
21 #define __FUNCT__ "DMPatchZoom"
22 /*
23   DMPatchZoom - Create a version of the coarse patch (identified by rank) with halo on communicator commz
24 
25   Collective on DM
26 
27   Input Parameters:
28   + dm - the DM
29   . rank - the rank which holds the given patch
30   - commz - the new communicator for the patch
31 
32   Output Parameters:
33   + dmz  - the patch DM
34   . sfz  - the PetscSF mapping the patch+halo to the zoomed version
35   . sfzr - the PetscSF mapping the patch to the restricted zoomed version
36 
37   Level: intermediate
38 
39   Note: All processes in commz should have the same rank (could autosplit comm)
40 
41 .seealso: DMPatchSolve()
42 */
43 PetscErrorCode DMPatchZoom(DM dm, MatStencil lower, MatStencil upper, MPI_Comm commz, DM *dmz, PetscSF *sfz, PetscSF *sfzr)
44 {
45   DMDAStencilType st;
46   MatStencil      blower, bupper;
47   PetscInt       *localPoints;
48   PetscSFNode    *remotePoints;
49   PetscInt        dim, dof;
50   PetscInt        M, N, P, rM, rN, rP, halo = 1, sx, sy, sz, sxb, syb, szb, sxr, syr, szr, mxb, myb, mzb, mxr, myr, mzr, i, j, k, q;
51   PetscErrorCode  ierr;
52 
53   PetscFunctionBegin;
54   if (commz == MPI_COMM_NULL) {
55     /* Split communicator */
56     SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Not implemented");
57   }
58   /* Create patch DM */
59   ierr = DMDAGetInfo(dm, &dim, &M, &N, &P, 0,0,0, &dof, 0,0,0,0, &st);CHKERRQ(ierr);
60 
61   /* Get piece for rank r, expanded by halo */
62   bupper.i = PetscMin(M, upper.i + halo); blower.i = PetscMax(lower.i - halo, 0);
63   bupper.j = PetscMin(N, upper.j + halo); blower.j = PetscMax(lower.j - halo, 0);
64   bupper.k = PetscMin(P, upper.k + halo); blower.k = PetscMax(lower.k - halo, 0);
65   rM = bupper.i - blower.i;
66   rN = bupper.j - blower.j;
67   rP = bupper.k - blower.k;
68 
69   ierr = DMDACreate(commz, dmz);CHKERRQ(ierr);
70   ierr = DMDASetDim(*dmz, dim);CHKERRQ(ierr);
71   ierr = DMDASetSizes(*dmz, rM, rN, rP);CHKERRQ(ierr);
72   ierr = DMDASetNumProcs(*dmz, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE);CHKERRQ(ierr);
73   ierr = DMDASetBoundaryType(*dmz, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE);CHKERRQ(ierr);
74   ierr = DMDASetDof(*dmz, dof);CHKERRQ(ierr);
75   ierr = DMDASetStencilType(*dmz, st);CHKERRQ(ierr);
76   ierr = DMDASetStencilWidth(*dmz, 0);CHKERRQ(ierr);
77   ierr = DMDASetOwnershipRanges(*dmz, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr);
78   ierr = DMSetFromOptions(*dmz);CHKERRQ(ierr);
79   ierr = DMSetUp(*dmz);CHKERRQ(ierr);
80   ierr = DMDAGetCorners(*dmz, &sx, &sy, &sz, &mxb, &myb, &mzb);CHKERRQ(ierr);
81 
82   ierr = PetscMalloc2(rM*rN*rP,PetscInt,&localPoints,rM*rN*rP,PetscSFNode,&remotePoints);CHKERRQ(ierr);
83 
84   /* Create SF for restricted map */
85   q = 0;
86   szr = lower.k + sz; syr = lower.j + sy; sxr = lower.i + sx;
87   /* This is not quite right. Only works for serial patches */
88   mzr = mzb - (bupper.k-upper.k) - (lower.k-blower.k);
89   myr = myb - (bupper.j-upper.j) - (lower.j-blower.j);
90   mxr = mxb - (bupper.i-upper.i) - (lower.i-blower.i);
91   for(k = szr; k < szr+mzr; ++k) {
92     for(j = syr; j < syr+myr; ++j) {
93       for(i = sxr; i < sxr+mxr; ++i, ++q) {
94         const PetscInt lp = ((k-szr)*rN + (j-syr))*rM + i-sxr;
95         const PetscInt gp = (k*N + j)*M + i;
96 
97         localPoints[q]        = lp;
98         /* Replace with a function that can figure this out */
99         remotePoints[q].rank  = 0;
100         remotePoints[q].index = gp;
101       }
102     }
103   }
104   ierr = PetscSFCreate(commz, sfzr);CHKERRQ(ierr);
105   ierr = PetscSFSetGraph(*sfzr, M*N*P, q, localPoints, PETSC_COPY_VALUES, remotePoints, PETSC_COPY_VALUES);CHKERRQ(ierr);
106 
107   /* Create SF for buffered map */
108   q = 0;
109   szb = blower.k + sz; syb = blower.j + sy; sxb = blower.i + sx;
110   for(k = szb; k < szb+mzb; ++k) {
111     for(j = syb; j < syb+myb; ++j) {
112       for(i = sxb; i < sxb+mxb; ++i, ++q) {
113         const PetscInt lp = ((k-szb)*rN + (j-syb))*rM + i-sxb;
114         const PetscInt gp = (k*N + j)*M + i;
115 
116         localPoints[q]        = lp;
117         /* Replace with a function that can figure this out */
118         remotePoints[q].rank  = 0;
119         remotePoints[q].index = gp;
120       }
121     }
122   }
123   ierr = PetscSFCreate(commz, sfz);CHKERRQ(ierr);
124   ierr = PetscSFSetGraph(*sfz, M*N*P, q, localPoints, PETSC_COPY_VALUES, remotePoints, PETSC_COPY_VALUES);CHKERRQ(ierr);
125 
126   ierr = PetscFree2(localPoints, remotePoints);CHKERRQ(ierr);
127   PetscFunctionReturn(0);
128 }
129 
130 #undef __FUNCT__
131 #define __FUNCT__ "DMPatchSolve"
132 PetscErrorCode DMPatchSolve(DM dm)
133 {
134   MPI_Comm       comm = ((PetscObject) dm)->comm;
135   DM_Patch      *mesh = (DM_Patch *) dm->data;
136   DM             cdm  = mesh->dmCoarse;
137   DM             dmz;
138   PetscSF        sfz, sfzr;
139   MatStencil     patchSize, lower, upper;
140   PetscInt       M, N, P, i, j, k, p = 0;
141   PetscErrorCode ierr;
142 
143   PetscFunctionBegin;
144   ierr = DMPatchGetPatchSize(dm, &patchSize);CHKERRQ(ierr);
145   ierr = DMDAGetInfo(cdm, 0, &M, &N, &P, 0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
146   M    = PetscMax(M, 1);
147   N    = PetscMax(N, 1);
148   P    = PetscMax(P, 1);
149   for(k = 0; k < P; k += PetscMax(patchSize.k, 1)) {
150     for(j = 0; j < N; j += PetscMax(patchSize.j, 1)) {
151       for(i = 0; i < M; i += PetscMax(patchSize.i, 1), ++p) {
152         lower.i = i; lower.j = j; lower.k = k;
153         upper.i = i + patchSize.i; upper.j = j + patchSize.j; upper.k = k + patchSize.k;
154         ierr = DMPatchZoom(cdm, lower, upper, comm, &dmz, &sfz, &sfzr);CHKERRQ(ierr);
155 
156         ierr = PetscPrintf(comm, "Patch %d: (%d, %d, %d)--(%d, %d, %d)\n", p, lower.i, lower.j, lower.k, upper.i, upper.j, upper.k);CHKERRQ(ierr);
157         ierr = DMView(dmz, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
158         ierr = PetscSFView(sfz,  PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
159         ierr = PetscSFView(sfzr, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
160 #if 0
161     DM  dmf;
162     Mat interpz;
163     /* Scatter Xcoarse -> Xzoom */
164     ierr = PetscSFBcastBegin(sfz, MPIU_SCALAR, xcarray, xzarray);CHKERRQ(ierr);
165     ierr = PetscSFBcastEnd(sfz, MPIU_SCALAR, xcarray, xzarray);CHKERRQ(ierr);
166     /* Interpolate Xzoom -> Xfine, note that this may be on subcomms */
167     ierr = DMRefine(dmz, MPI_COMM_NULL, &dmf);CHKERRQ(ierr);
168     ierr = DMCreateInterpolation(dmz, dmf, &interpz, PETSC_NULL);CHKERRQ(ierr);
169     ierr = DMInterpolate(dmz, interpz, dmf);CHKERRQ(ierr);
170     /* Smooth Xfine using two-step smoother, normal smoother plus Kaczmarz---moves back and forth from dmzoom to dmfine */
171     /* Compute residual Rfine */
172     /* Restrict Rfine to Rzoom_restricted */
173     /* Scatter Rzoom_restricted -> Rcoarse_restricted */
174     ierr = PetscSFBcastBegin(sfzr, MPIU_SCALAR, xzarray, xcarray, MPI_SUM);CHKERRQ(ierr);
175     ierr = PetscSFBcastEnd(sfzr, MPIU_SCALAR, xzarray, xcarray, MPI_SUM);CHKERRQ(ierr);
176     /* Compute global residual Rcoarse */
177     /* TauCoarse = Rcoarse - Rcoarse_restricted */
178 #endif
179         ierr = PetscSFDestroy(&sfz);CHKERRQ(ierr);
180         ierr = PetscSFDestroy(&sfzr);CHKERRQ(ierr);
181         ierr = DMDestroy(&dmz);CHKERRQ(ierr);
182       }
183     }
184   }
185   PetscFunctionReturn(0);
186 }
187 
188 #undef __FUNCT__
189 #define __FUNCT__ "DMPatchView_Ascii"
190 PetscErrorCode DMPatchView_Ascii(DM dm, PetscViewer viewer)
191 {
192   DM_Patch         *mesh = (DM_Patch *) dm->data;
193   PetscViewerFormat format;
194   const char       *name;
195   PetscErrorCode    ierr;
196 
197   PetscFunctionBegin;
198   ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
199   /* if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) */
200   ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
201   ierr = PetscViewerASCIIPrintf(viewer, "Patch DM %s\n", name);CHKERRQ(ierr);
202   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
203   ierr = PetscViewerASCIIPrintf(viewer, "Coarse DM\n");CHKERRQ(ierr);
204   ierr = DMView(mesh->dmCoarse, viewer);CHKERRQ(ierr);
205   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
206   PetscFunctionReturn(0);
207 }
208 
209 #undef __FUNCT__
210 #define __FUNCT__ "DMView_Patch"
211 PetscErrorCode DMView_Patch(DM dm, PetscViewer viewer)
212 {
213   PetscBool      iascii, isbinary;
214   PetscErrorCode ierr;
215 
216   PetscFunctionBegin;
217   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
218   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
219   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
220   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr);
221   if (iascii) {
222     ierr = DMPatchView_Ascii(dm, viewer);CHKERRQ(ierr);
223 #if 0
224   } else if (isbinary) {
225     ierr = DMPatchView_Binary(dm, viewer);CHKERRQ(ierr);
226 #endif
227   } else SETERRQ1(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Viewer type %s not supported by this mesh object", ((PetscObject)viewer)->type_name);
228   PetscFunctionReturn(0);
229 }
230 
231 #undef __FUNCT__
232 #define __FUNCT__ "DMDestroy_Patch"
233 PetscErrorCode DMDestroy_Patch(DM dm)
234 {
235   DM_Patch      *mesh = (DM_Patch *) dm->data;
236   PetscErrorCode ierr;
237 
238   PetscFunctionBegin;
239   if (--mesh->refct > 0) {PetscFunctionReturn(0);}
240   ierr = DMDestroy(&mesh->dmCoarse);CHKERRQ(ierr);
241   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
242   ierr = PetscFree(mesh);CHKERRQ(ierr);
243   PetscFunctionReturn(0);
244 }
245 
246 #undef __FUNCT__
247 #define __FUNCT__ "DMSetUp_Patch"
248 PetscErrorCode DMSetUp_Patch(DM dm)
249 {
250   DM_Patch      *mesh = (DM_Patch *) dm->data;
251   PetscErrorCode ierr;
252 
253   PetscFunctionBegin;
254   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
255   ierr = DMSetUp(mesh->dmCoarse);CHKERRQ(ierr);
256   PetscFunctionReturn(0);
257 }
258 
259 #undef __FUNCT__
260 #define __FUNCT__ "DMCreateGlobalVector_Patch"
261 PetscErrorCode DMCreateGlobalVector_Patch(DM dm, Vec *g)
262 {
263   DM_Patch      *mesh = (DM_Patch *) dm->data;
264   PetscErrorCode ierr;
265 
266   PetscFunctionBegin;
267   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
268   ierr = DMCreateGlobalVector(mesh->dmCoarse, g);CHKERRQ(ierr);
269   PetscFunctionReturn(0);
270 }
271 
272 #undef __FUNCT__
273 #define __FUNCT__ "DMCreateLocalVector_Patch"
274 PetscErrorCode DMCreateLocalVector_Patch(DM dm, Vec *l)
275 {
276   DM_Patch      *mesh = (DM_Patch *) dm->data;
277   PetscErrorCode ierr;
278 
279   PetscFunctionBegin;
280   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
281   ierr = DMCreateLocalVector(mesh->dmCoarse, l);CHKERRQ(ierr);
282   PetscFunctionReturn(0);
283 }
284 
285 #undef __FUNCT__
286 #define __FUNCT__ "DMCreateSubDM_Patch"
287 PetscErrorCode DMCreateSubDM_Patch(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
288 {
289   PetscFunctionBegin;
290   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
291   SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tell me to code this");
292   PetscFunctionReturn(0);
293 }
294 
295 #undef __FUNCT__
296 #define __FUNCT__ "DMPatchGetCoarse"
297 PetscErrorCode DMPatchGetCoarse(DM dm, DM *dmCoarse)
298 {
299   DM_Patch *mesh = (DM_Patch *) dm->data;
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
303   *dmCoarse = mesh->dmCoarse;
304   PetscFunctionReturn(0);
305 }
306 
307 #undef __FUNCT__
308 #define __FUNCT__ "DMPatchGetPatchSize"
309 PetscErrorCode DMPatchGetPatchSize(DM dm, MatStencil *patchSize)
310 {
311   DM_Patch *mesh = (DM_Patch *) dm->data;
312 
313   PetscFunctionBegin;
314   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
315   PetscValidPointer(patchSize, 2);
316   *patchSize = mesh->patchSize;
317   PetscFunctionReturn(0);
318 }
319 
320 #undef __FUNCT__
321 #define __FUNCT__ "DMPatchSetPatchSize"
322 PetscErrorCode DMPatchSetPatchSize(DM dm, MatStencil patchSize)
323 {
324   DM_Patch *mesh = (DM_Patch *) dm->data;
325 
326   PetscFunctionBegin;
327   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
328   mesh->patchSize = patchSize;
329   PetscFunctionReturn(0);
330 }
331