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 Gets the natural number for each global number on the process.
9
10 Used by DMDAGetAO() and DMDAGlobalToNatural_Create()
11 */
DMDAGetNatural_Private(DM da,PetscInt * outNlocal,IS * isnatural)12 PetscErrorCode DMDAGetNatural_Private(DM da, PetscInt *outNlocal, IS *isnatural)
13 {
14 PetscInt Nlocal, i, j, k, *lidx, lict = 0, dim = da->dim;
15 DM_DA *dd = (DM_DA *)da->data;
16
17 PetscFunctionBegin;
18 Nlocal = (dd->xe - dd->xs);
19 if (dim > 1) Nlocal *= (dd->ye - dd->ys);
20 if (dim > 2) Nlocal *= (dd->ze - dd->zs);
21
22 PetscCall(PetscMalloc1(Nlocal, &lidx));
23
24 if (dim == 1) {
25 for (i = dd->xs; i < dd->xe; i++) {
26 /* global number in natural ordering */
27 lidx[lict++] = i;
28 }
29 } else if (dim == 2) {
30 for (j = dd->ys; j < dd->ye; j++) {
31 for (i = dd->xs; i < dd->xe; i++) {
32 /* global number in natural ordering */
33 lidx[lict++] = i + j * dd->M * dd->w;
34 }
35 }
36 } else if (dim == 3) {
37 for (k = dd->zs; k < dd->ze; k++) {
38 for (j = dd->ys; j < dd->ye; j++) {
39 for (i = dd->xs; i < dd->xe; i++) lidx[lict++] = i + j * dd->M * dd->w + k * dd->M * dd->N * dd->w;
40 }
41 }
42 }
43 *outNlocal = Nlocal;
44 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)da), Nlocal, lidx, PETSC_OWN_POINTER, isnatural));
45 PetscFunctionReturn(PETSC_SUCCESS);
46 }
47
48 /*@
49 DMDASetAOType - Sets the type of application ordering to create with `DMDAGetAO()`, for a distributed array.
50
51 Collective
52
53 Input Parameters:
54 + da - the `DMDA`
55 - aotype - type of `AO`. `AOType` which can be `AOBASIC`, `AOADVANCED`, `AOMAPPING`, or `AOMEMORYSCALABLE`
56
57 Level: intermediate
58
59 Note:
60 It will generate an error if an `AO` has already been obtained with a call to `DMDAGetAO()` and the user sets a different `AOType`
61
62 .seealso: [](sec_struct), `DM`, `DMDA`, `DMDACreate2d()`, `DMDAGetAO()`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `DMLocalToGlobal()`
63 `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMLocalToLocalBegin()`, `DMLocalToLocalEnd()`, `DMDAGetGlobalIndices()`, `DMDAGetOwnershipRanges()`,
64 `AO`, `AOPetscToApplication()`, `AOApplicationToPetsc()`, `AOType`, `AOBASIC`, `AOADVANCED`, `AOMAPPING`, `AOMEMORYSCALABLE`
65 @*/
DMDASetAOType(DM da,AOType aotype)66 PetscErrorCode DMDASetAOType(DM da, AOType aotype)
67 {
68 DM_DA *dd;
69 PetscBool isdmda;
70
71 PetscFunctionBegin;
72 PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA);
73 PetscCall(PetscObjectTypeCompare((PetscObject)da, DMDA, &isdmda));
74 PetscCheck(isdmda, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Requires a DMDA as input");
75 /* now we can safely dereference */
76 dd = (DM_DA *)da->data;
77 if (dd->ao) { /* check if the already computed AO has the same type as requested */
78 PetscBool match;
79 PetscCall(PetscObjectTypeCompare((PetscObject)dd->ao, aotype, &match));
80 PetscCheck(match, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Cannot change AO type");
81 PetscFunctionReturn(PETSC_SUCCESS);
82 }
83 PetscCall(PetscFree(dd->aotype));
84 PetscCall(PetscStrallocpy(aotype, (char **)&dd->aotype));
85 PetscFunctionReturn(PETSC_SUCCESS);
86 }
87
88 /*@
89 DMDAGetAO - Gets the application ordering context for a distributed array.
90
91 Collective
92
93 Input Parameter:
94 . da - the `DMDA`
95
96 Output Parameter:
97 . ao - the application ordering context for `DMDA`
98
99 Level: intermediate
100
101 Notes:
102 In this case, the `AO` maps to the natural grid ordering that would be used
103 for the `DMDA` if only 1 processor were employed (ordering most rapidly in the
104 x-direction, then y, then z). Multiple degrees of freedom are numbered
105 for each node (rather than 1 component for the whole grid, then the next
106 component, etc.)
107
108 Do NOT call `AODestroy()` on the `ao` returned by this function.
109
110 .seealso: [](sec_struct), `DM`, `DMDA`, `DMDACreate2d()`, `DMDASetAOType()`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `DMLocalToGlobal()`
111 `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMLocalToLocalBegin()`, `DMLocalToLocalEnd()`, `DMDAGetOwnershipRanges()`,
112 `AO`, `AOPetscToApplication()`, `AOApplicationToPetsc()`
113 @*/
DMDAGetAO(DM da,AO * ao)114 PetscErrorCode DMDAGetAO(DM da, AO *ao)
115 {
116 DM_DA *dd;
117 PetscBool isdmda;
118
119 PetscFunctionBegin;
120 PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA);
121 PetscAssertPointer(ao, 2);
122 PetscCall(PetscObjectTypeCompare((PetscObject)da, DMDA, &isdmda));
123 PetscCheck(isdmda, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Requires a DMDA as input");
124 /* now we can safely dereference */
125 dd = (DM_DA *)da->data;
126
127 /*
128 Build the natural ordering to PETSc ordering mappings.
129 */
130 if (!dd->ao) {
131 IS ispetsc, isnatural;
132 PetscInt Nlocal;
133
134 PetscCall(DMDAGetNatural_Private(da, &Nlocal, &isnatural));
135 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)da), Nlocal, dd->base, 1, &ispetsc));
136 PetscCall(AOCreate(PetscObjectComm((PetscObject)da), &dd->ao));
137 PetscCall(AOSetIS(dd->ao, isnatural, ispetsc));
138 PetscCall(AOSetType(dd->ao, dd->aotype));
139 PetscCall(ISDestroy(&ispetsc));
140 PetscCall(ISDestroy(&isnatural));
141 }
142 *ao = dd->ao;
143 PetscFunctionReturn(PETSC_SUCCESS);
144 }
145