xref: /petsc/src/dm/impls/da/daltol.c (revision 705a7f0eb0ef90644623ad86b4e8bfdbdabd856c)
1 /*
2   Code for manipulating distributed regular arrays in parallel.
3 */
4 
5 #include <petsc/private/dmdaimpl.h> /*I   "petscdmda.h"   I*/
6 
7 /*
8    DMLocalToLocalCreate_DA - Creates the local to local scatter
9 
10    Collective
11 
12    Input Parameter:
13 .  da - the `DMDA`
14 
15 */
DMLocalToLocalCreate_DA(DM da)16 PetscErrorCode DMLocalToLocalCreate_DA(DM da)
17 {
18   PetscInt *idx, left, j, count, up, down, i, bottom, top, k, dim = da->dim;
19   DM_DA    *dd = (DM_DA *)da->data;
20 
21   PetscFunctionBegin;
22   PetscValidHeaderSpecific(da, DM_CLASSID, 1);
23 
24   if (dd->ltol) PetscFunctionReturn(PETSC_SUCCESS);
25   /*
26      We simply remap the values in the from part of
27      global to local to read from an array with the ghost values
28      rather than from the plain array.
29   */
30   PetscCall(VecScatterCopy(dd->gtol, &dd->ltol));
31   if (dim == 1) {
32     left = dd->xs - dd->Xs;
33     PetscCall(PetscMalloc1(dd->xe - dd->xs, &idx));
34     for (j = 0; j < dd->xe - dd->xs; j++) idx[j] = left + j;
35   } else if (dim == 2) {
36     left = dd->xs - dd->Xs;
37     down = dd->ys - dd->Ys;
38     up   = down + dd->ye - dd->ys;
39     PetscCall(PetscMalloc1((dd->xe - dd->xs) * (up - down), &idx));
40     count = 0;
41     for (i = down; i < up; i++) {
42       for (j = 0; j < dd->xe - dd->xs; j++) idx[count++] = left + i * (dd->Xe - dd->Xs) + j;
43     }
44   } else if (dim == 3) {
45     left   = dd->xs - dd->Xs;
46     bottom = dd->ys - dd->Ys;
47     top    = bottom + dd->ye - dd->ys;
48     down   = dd->zs - dd->Zs;
49     up     = down + dd->ze - dd->zs;
50     count  = (dd->xe - dd->xs) * (top - bottom) * (up - down);
51     PetscCall(PetscMalloc1(count, &idx));
52     count = 0;
53     for (i = down; i < up; i++) {
54       for (j = bottom; j < top; j++) {
55         for (k = 0; k < dd->xe - dd->xs; k++) idx[count++] = (left + j * (dd->Xe - dd->Xs)) + i * (dd->Xe - dd->Xs) * (dd->Ye - dd->Ys) + k;
56       }
57     }
58   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_CORRUPT, "DMDA has invalid dimension %" PetscInt_FMT, dim);
59 
60   PetscCall(VecScatterRemap(dd->ltol, idx, NULL));
61   PetscCall(PetscFree(idx));
62   PetscFunctionReturn(PETSC_SUCCESS);
63 }
64 
DMLocalToLocalBegin_DA(DM da,Vec g,InsertMode mode,Vec l)65 PetscErrorCode DMLocalToLocalBegin_DA(DM da, Vec g, InsertMode mode, Vec l)
66 {
67   DM_DA *dd = (DM_DA *)da->data;
68 
69   PetscFunctionBegin;
70   PetscValidHeaderSpecific(da, DM_CLASSID, 1);
71   if (!dd->ltol) PetscCall(DMLocalToLocalCreate_DA(da));
72   PetscCall(VecScatterBegin(dd->ltol, g, l, mode, SCATTER_FORWARD));
73   PetscFunctionReturn(PETSC_SUCCESS);
74 }
75 
DMLocalToLocalEnd_DA(DM da,Vec g,InsertMode mode,Vec l)76 PetscErrorCode DMLocalToLocalEnd_DA(DM da, Vec g, InsertMode mode, Vec l)
77 {
78   DM_DA *dd = (DM_DA *)da->data;
79 
80   PetscFunctionBegin;
81   PetscValidHeaderSpecific(da, DM_CLASSID, 1);
82   PetscValidHeaderSpecific(g, VEC_CLASSID, 2);
83   PetscCall(VecScatterEnd(dd->ltol, g, l, mode, SCATTER_FORWARD));
84   PetscFunctionReturn(PETSC_SUCCESS);
85 }
86