xref: /petsc/src/dm/impls/patch/patch.c (revision bb87e0066235d5bef9b7618da753537bc26601af)
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(((PetscObject) dm)->comm, 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(((PetscObject) dm)->comm, 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         DM  dmf;
153         Mat interpz;
154         PetscScalar *xcarray, *xzarray;
155 
156         /* Zoom to coarse patch */
157         lower.i = i; lower.j = j; lower.k = k;
158         upper.i = i + patchSize.i; upper.j = j + patchSize.j; upper.k = k + patchSize.k;
159         ierr = DMPatchZoom(cdm, lower, upper, comm, &dmz, &sfz, &sfzr);CHKERRQ(ierr);
160         /* Debug */
161         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);
162         ierr = DMView(dmz, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
163         ierr = PetscSFView(sfz,  PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
164         ierr = PetscSFView(sfzr, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
165         /* Scatter Xcoarse -> Xzoom */
166         ierr = PetscSFBcastBegin(sfz, MPIU_SCALAR, (void *) xcarray, (void *) xzarray);CHKERRQ(ierr);
167         ierr = PetscSFBcastEnd(sfz, MPIU_SCALAR, (void *) xcarray, (void *) xzarray);CHKERRQ(ierr);
168         /* Interpolate Xzoom -> Xfine, note that this may be on subcomms */
169         ierr = DMRefine(dmz, MPI_COMM_NULL, &dmf);CHKERRQ(ierr);
170         ierr = DMCreateInterpolation(dmz, dmf, &interpz, PETSC_NULL);CHKERRQ(ierr);
171         ierr = DMInterpolate(dmz, interpz, dmf);CHKERRQ(ierr);
172         /* Smooth Xfine using two-step smoother, normal smoother plus Kaczmarz---moves back and forth from dmzoom to dmfine */
173         /* Compute residual Rfine */
174         /* Restrict Rfine to Rzoom_restricted */
175         /* Scatter Rzoom_restricted -> Rcoarse_restricted */
176         ierr = PetscSFReduceBegin(sfzr, MPIU_SCALAR, (void *) xzarray, (void *) xcarray, MPI_SUM);CHKERRQ(ierr);
177         ierr = PetscSFReduceEnd(sfzr, MPIU_SCALAR, (void *) xzarray, (void *) xcarray, MPI_SUM);CHKERRQ(ierr);
178         /* Compute global residual Rcoarse */
179         /* TauCoarse = Rcoarse - Rcoarse_restricted */
180 
181         ierr = PetscSFDestroy(&sfz);CHKERRQ(ierr);
182         ierr = PetscSFDestroy(&sfzr);CHKERRQ(ierr);
183         ierr = DMDestroy(&dmz);CHKERRQ(ierr);
184       }
185     }
186   }
187   PetscFunctionReturn(0);
188 }
189 
190 #undef __FUNCT__
191 #define __FUNCT__ "DMPatchView_Ascii"
192 PetscErrorCode DMPatchView_Ascii(DM dm, PetscViewer viewer)
193 {
194   DM_Patch         *mesh = (DM_Patch *) dm->data;
195   PetscViewerFormat format;
196   const char       *name;
197   PetscErrorCode    ierr;
198 
199   PetscFunctionBegin;
200   ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
201   /* if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) */
202   ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
203   ierr = PetscViewerASCIIPrintf(viewer, "Patch DM %s\n", name);CHKERRQ(ierr);
204   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
205   ierr = PetscViewerASCIIPrintf(viewer, "Coarse DM\n");CHKERRQ(ierr);
206   ierr = DMView(mesh->dmCoarse, viewer);CHKERRQ(ierr);
207   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
208   PetscFunctionReturn(0);
209 }
210 
211 #undef __FUNCT__
212 #define __FUNCT__ "DMView_Patch"
213 PetscErrorCode DMView_Patch(DM dm, PetscViewer viewer)
214 {
215   PetscBool      iascii, isbinary;
216   PetscErrorCode ierr;
217 
218   PetscFunctionBegin;
219   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
220   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
221   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
222   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr);
223   if (iascii) {
224     ierr = DMPatchView_Ascii(dm, viewer);CHKERRQ(ierr);
225 #if 0
226   } else if (isbinary) {
227     ierr = DMPatchView_Binary(dm, viewer);CHKERRQ(ierr);
228 #endif
229   } else SETERRQ1(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Viewer type %s not supported by this mesh object", ((PetscObject)viewer)->type_name);
230   PetscFunctionReturn(0);
231 }
232 
233 #undef __FUNCT__
234 #define __FUNCT__ "DMDestroy_Patch"
235 PetscErrorCode DMDestroy_Patch(DM dm)
236 {
237   DM_Patch      *mesh = (DM_Patch *) dm->data;
238   PetscErrorCode ierr;
239 
240   PetscFunctionBegin;
241   if (--mesh->refct > 0) {PetscFunctionReturn(0);}
242   ierr = DMDestroy(&mesh->dmCoarse);CHKERRQ(ierr);
243   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
244   ierr = PetscFree(mesh);CHKERRQ(ierr);
245   PetscFunctionReturn(0);
246 }
247 
248 #undef __FUNCT__
249 #define __FUNCT__ "DMSetUp_Patch"
250 PetscErrorCode DMSetUp_Patch(DM dm)
251 {
252   DM_Patch      *mesh = (DM_Patch *) dm->data;
253   PetscErrorCode ierr;
254 
255   PetscFunctionBegin;
256   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
257   ierr = DMSetUp(mesh->dmCoarse);CHKERRQ(ierr);
258   PetscFunctionReturn(0);
259 }
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "DMCreateGlobalVector_Patch"
263 PetscErrorCode DMCreateGlobalVector_Patch(DM dm, Vec *g)
264 {
265   DM_Patch      *mesh = (DM_Patch *) dm->data;
266   PetscErrorCode ierr;
267 
268   PetscFunctionBegin;
269   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
270   ierr = DMCreateGlobalVector(mesh->dmCoarse, g);CHKERRQ(ierr);
271   PetscFunctionReturn(0);
272 }
273 
274 #undef __FUNCT__
275 #define __FUNCT__ "DMCreateLocalVector_Patch"
276 PetscErrorCode DMCreateLocalVector_Patch(DM dm, Vec *l)
277 {
278   DM_Patch      *mesh = (DM_Patch *) dm->data;
279   PetscErrorCode ierr;
280 
281   PetscFunctionBegin;
282   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
283   ierr = DMCreateLocalVector(mesh->dmCoarse, l);CHKERRQ(ierr);
284   PetscFunctionReturn(0);
285 }
286 
287 #undef __FUNCT__
288 #define __FUNCT__ "DMCreateSubDM_Patch"
289 PetscErrorCode DMCreateSubDM_Patch(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
290 {
291   PetscFunctionBegin;
292   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
293   SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tell me to code this");
294   PetscFunctionReturn(0);
295 }
296 
297 #undef __FUNCT__
298 #define __FUNCT__ "DMPatchGetCoarse"
299 PetscErrorCode DMPatchGetCoarse(DM dm, DM *dmCoarse)
300 {
301   DM_Patch *mesh = (DM_Patch *) dm->data;
302 
303   PetscFunctionBegin;
304   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
305   *dmCoarse = mesh->dmCoarse;
306   PetscFunctionReturn(0);
307 }
308 
309 #undef __FUNCT__
310 #define __FUNCT__ "DMPatchGetPatchSize"
311 PetscErrorCode DMPatchGetPatchSize(DM dm, MatStencil *patchSize)
312 {
313   DM_Patch *mesh = (DM_Patch *) dm->data;
314 
315   PetscFunctionBegin;
316   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
317   PetscValidPointer(patchSize, 2);
318   *patchSize = mesh->patchSize;
319   PetscFunctionReturn(0);
320 }
321 
322 #undef __FUNCT__
323 #define __FUNCT__ "DMPatchSetPatchSize"
324 PetscErrorCode DMPatchSetPatchSize(DM dm, MatStencil patchSize)
325 {
326   DM_Patch *mesh = (DM_Patch *) dm->data;
327 
328   PetscFunctionBegin;
329   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
330   mesh->patchSize = patchSize;
331   PetscFunctionReturn(0);
332 }
333