1 /* 2 Code for manipulating distributed regular arrays in parallel. 3 */ 4 5 #include <petsc/private/dmdaimpl.h> /*I "petscdmda.h" I*/ 6 7 PetscErrorCode DMGlobalToLocalBegin_DA(DM da, Vec g, InsertMode mode, Vec l) { 8 DM_DA *dd = (DM_DA *)da->data; 9 10 PetscFunctionBegin; 11 PetscValidHeaderSpecific(da, DM_CLASSID, 1); 12 PetscValidHeaderSpecific(g, VEC_CLASSID, 2); 13 PetscValidHeaderSpecific(l, VEC_CLASSID, 4); 14 PetscCall(VecScatterBegin(dd->gtol, g, l, mode, SCATTER_FORWARD)); 15 PetscFunctionReturn(0); 16 } 17 18 PetscErrorCode DMGlobalToLocalEnd_DA(DM da, Vec g, InsertMode mode, Vec l) { 19 DM_DA *dd = (DM_DA *)da->data; 20 21 PetscFunctionBegin; 22 PetscValidHeaderSpecific(da, DM_CLASSID, 1); 23 PetscValidHeaderSpecific(g, VEC_CLASSID, 2); 24 PetscValidHeaderSpecific(l, VEC_CLASSID, 4); 25 PetscCall(VecScatterEnd(dd->gtol, g, l, mode, SCATTER_FORWARD)); 26 PetscFunctionReturn(0); 27 } 28 29 PetscErrorCode DMLocalToGlobalBegin_DA(DM da, Vec l, InsertMode mode, Vec g) { 30 DM_DA *dd = (DM_DA *)da->data; 31 32 PetscFunctionBegin; 33 PetscValidHeaderSpecific(da, DM_CLASSID, 1); 34 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 35 PetscValidHeaderSpecific(g, VEC_CLASSID, 4); 36 if (mode == ADD_VALUES) { 37 PetscCall(VecScatterBegin(dd->gtol, l, g, ADD_VALUES, SCATTER_REVERSE)); 38 } else if (mode == INSERT_VALUES) { 39 PetscCheck(dd->bx == DM_BOUNDARY_GHOSTED || dd->bx == DM_BOUNDARY_NONE || dd->s <= 0 || dd->m != 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Available only for boundary none or with parallelism in x direction"); 40 PetscCheck(dd->bx == DM_BOUNDARY_GHOSTED || dd->by == DM_BOUNDARY_NONE || dd->s <= 0 || dd->n != 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Available only for boundary none or with parallelism in y direction"); 41 PetscCheck(dd->bx == DM_BOUNDARY_GHOSTED || dd->bz == DM_BOUNDARY_NONE || dd->s <= 0 || dd->p != 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Available only for boundary none or with parallelism in z direction"); 42 PetscCall(VecScatterBegin(dd->gtol, l, g, INSERT_VALUES, SCATTER_REVERSE_LOCAL)); 43 } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Not yet implemented"); 44 PetscFunctionReturn(0); 45 } 46 47 PetscErrorCode DMLocalToGlobalEnd_DA(DM da, Vec l, InsertMode mode, Vec g) { 48 DM_DA *dd = (DM_DA *)da->data; 49 50 PetscFunctionBegin; 51 PetscValidHeaderSpecific(da, DM_CLASSID, 1); 52 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 53 PetscValidHeaderSpecific(g, VEC_CLASSID, 4); 54 if (mode == ADD_VALUES) { 55 PetscCall(VecScatterEnd(dd->gtol, l, g, ADD_VALUES, SCATTER_REVERSE)); 56 } else if (mode == INSERT_VALUES) { 57 PetscCall(VecScatterEnd(dd->gtol, l, g, INSERT_VALUES, SCATTER_REVERSE_LOCAL)); 58 } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Not yet implemented"); 59 PetscFunctionReturn(0); 60 } 61 62 extern PetscErrorCode DMDAGetNatural_Private(DM, PetscInt *, IS *); 63 /* 64 DMDAGlobalToNatural_Create - Create the global to natural scatter object 65 66 Collective on da 67 68 Input Parameter: 69 . da - the distributed array context 70 71 Level: developer 72 73 Notes: 74 This is an internal routine called by DMDAGlobalToNatural() to 75 create the scatter context. 76 77 .seealso: `DMDAGlobalToNaturalBegin()`, `DMDAGlobalToNaturalEnd()`, `DMLocalToGlobalBegin()`, `DMDACreate2d()`, 78 `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMDACreateNaturalVector()` 79 */ 80 PetscErrorCode DMDAGlobalToNatural_Create(DM da) { 81 PetscInt m, start, Nlocal; 82 IS from, to; 83 Vec global; 84 DM_DA *dd = (DM_DA *)da->data; 85 86 PetscFunctionBegin; 87 PetscValidHeaderSpecific(da, DM_CLASSID, 1); 88 PetscCheck(dd->natural, PetscObjectComm((PetscObject)da), PETSC_ERR_ORDER, "Natural layout vector not yet created; cannot scatter into it"); 89 90 /* create the scatter context */ 91 PetscCall(VecGetLocalSize(dd->natural, &m)); 92 PetscCall(VecGetOwnershipRange(dd->natural, &start, NULL)); 93 94 PetscCall(DMDAGetNatural_Private(da, &Nlocal, &to)); 95 PetscCheck(Nlocal == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error: Nlocal %" PetscInt_FMT " local vector size %" PetscInt_FMT, Nlocal, m); 96 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)da), m, start, 1, &from)); 97 PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)da), dd->w, dd->Nlocal, PETSC_DETERMINE, NULL, &global)); 98 PetscCall(VecScatterCreate(global, from, dd->natural, to, &dd->gton)); 99 PetscCall(VecDestroy(&global)); 100 PetscCall(ISDestroy(&from)); 101 PetscCall(ISDestroy(&to)); 102 PetscFunctionReturn(0); 103 } 104 105 /*@ 106 DMDAGlobalToNaturalBegin - Maps values from the global vector to a global vector 107 in the "natural" grid ordering. Must be followed by 108 DMDAGlobalToNaturalEnd() to complete the exchange. 109 110 Neighbor-wise Collective on da 111 112 Input Parameters: 113 + da - the distributed array context 114 . g - the global vector 115 - mode - one of INSERT_VALUES or ADD_VALUES 116 117 Output Parameter: 118 . l - the natural ordering values 119 120 Level: advanced 121 122 Notes: 123 The global and natrual vectors used here need not be the same as those 124 obtained from DMCreateGlobalVector() and DMDACreateNaturalVector(), BUT they 125 must have the same parallel data layout; they could, for example, be 126 obtained with VecDuplicate() from the DMDA originating vectors. 127 128 You must call DMDACreateNaturalVector() before using this routine 129 130 .seealso: `DMDAGlobalToNaturalEnd()`, `DMLocalToGlobalBegin()`, `DMDACreate2d()`, 131 `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMDACreateNaturalVector()` 132 133 @*/ 134 PetscErrorCode DMDAGlobalToNaturalBegin(DM da, Vec g, InsertMode mode, Vec n) { 135 DM_DA *dd = (DM_DA *)da->data; 136 137 PetscFunctionBegin; 138 PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA); 139 PetscValidHeaderSpecific(g, VEC_CLASSID, 2); 140 PetscValidHeaderSpecific(n, VEC_CLASSID, 4); 141 if (!dd->gton) { 142 /* create the scatter context */ 143 PetscCall(DMDAGlobalToNatural_Create(da)); 144 } 145 PetscCall(VecScatterBegin(dd->gton, g, n, mode, SCATTER_FORWARD)); 146 PetscFunctionReturn(0); 147 } 148 149 /*@ 150 DMDAGlobalToNaturalEnd - Maps values from the global vector to a global vector 151 in the natural ordering. Must be preceded by DMDAGlobalToNaturalBegin(). 152 153 Neighbor-wise Collective on da 154 155 Input Parameters: 156 + da - the distributed array context 157 . g - the global vector 158 - mode - one of INSERT_VALUES or ADD_VALUES 159 160 Output Parameter: 161 . l - the global values in the natural ordering 162 163 Level: advanced 164 165 Notes: 166 The global and local vectors used here need not be the same as those 167 obtained from DMCreateGlobalVector() and DMDACreateNaturalVector(), BUT they 168 must have the same parallel data layout; they could, for example, be 169 obtained with VecDuplicate() from the DMDA originating vectors. 170 171 .seealso: `DMDAGlobalToNaturalBegin()`, `DMLocalToGlobalBegin()`, `DMDACreate2d()`, 172 `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMDACreateNaturalVector()` 173 174 @*/ 175 PetscErrorCode DMDAGlobalToNaturalEnd(DM da, Vec g, InsertMode mode, Vec n) { 176 DM_DA *dd = (DM_DA *)da->data; 177 178 PetscFunctionBegin; 179 PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA); 180 PetscValidHeaderSpecific(g, VEC_CLASSID, 2); 181 PetscValidHeaderSpecific(n, VEC_CLASSID, 4); 182 PetscCall(VecScatterEnd(dd->gton, g, n, mode, SCATTER_FORWARD)); 183 PetscFunctionReturn(0); 184 } 185 186 /*@ 187 DMDANaturalToGlobalBegin - Maps values from a global vector in the "natural" ordering 188 to a global vector in the PETSc DMDA grid ordering. Must be followed by 189 DMDANaturalToGlobalEnd() to complete the exchange. 190 191 Neighbor-wise Collective on da 192 193 Input Parameters: 194 + da - the distributed array context 195 . g - the global vector in a natural ordering 196 - mode - one of INSERT_VALUES or ADD_VALUES 197 198 Output Parameter: 199 . l - the values in the DMDA ordering 200 201 Level: advanced 202 203 Notes: 204 The global and natural vectors used here need not be the same as those 205 obtained from DMCreateGlobalVector() and DMDACreateNaturalVector(), BUT they 206 must have the same parallel data layout; they could, for example, be 207 obtained with VecDuplicate() from the DMDA originating vectors. 208 209 .seealso: `DMDAGlobalToNaturalEnd()`, `DMDAGlobalToNaturalBegin()`, `DMLocalToGlobalBegin()`, `DMDACreate2d()`, 210 `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMDACreateNaturalVector()` 211 212 @*/ 213 PetscErrorCode DMDANaturalToGlobalBegin(DM da, Vec n, InsertMode mode, Vec g) { 214 DM_DA *dd = (DM_DA *)da->data; 215 216 PetscFunctionBegin; 217 PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA); 218 PetscValidHeaderSpecific(n, VEC_CLASSID, 2); 219 PetscValidHeaderSpecific(g, VEC_CLASSID, 4); 220 if (!dd->gton) { 221 /* create the scatter context */ 222 PetscCall(DMDAGlobalToNatural_Create(da)); 223 } 224 PetscCall(VecScatterBegin(dd->gton, n, g, mode, SCATTER_REVERSE)); 225 PetscFunctionReturn(0); 226 } 227 228 /*@ 229 DMDANaturalToGlobalEnd - Maps values from the natural ordering global vector 230 to a global vector in the PETSc DMDA ordering. Must be preceded by DMDANaturalToGlobalBegin(). 231 232 Neighbor-wise Collective on da 233 234 Input Parameters: 235 + da - the distributed array context 236 . g - the global vector in a natural ordering 237 - mode - one of INSERT_VALUES or ADD_VALUES 238 239 Output Parameter: 240 . l - the global values in the PETSc DMDA ordering 241 242 Level: advanced 243 244 Notes: 245 The global and local vectors used here need not be the same as those 246 obtained from DMCreateGlobalVector() and DMDACreateNaturalVector(), BUT they 247 must have the same parallel data layout; they could, for example, be 248 obtained with VecDuplicate() from the DMDA originating vectors. 249 250 .seealso: `DMDAGlobalToNaturalBegin()`, `DMDAGlobalToNaturalEnd()`, `DMLocalToGlobalBegin()`, `DMDACreate2d()`, 251 `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMDACreateNaturalVector()` 252 253 @*/ 254 PetscErrorCode DMDANaturalToGlobalEnd(DM da, Vec n, InsertMode mode, Vec g) { 255 DM_DA *dd = (DM_DA *)da->data; 256 257 PetscFunctionBegin; 258 PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA); 259 PetscValidHeaderSpecific(n, VEC_CLASSID, 2); 260 PetscValidHeaderSpecific(g, VEC_CLASSID, 4); 261 PetscCall(VecScatterEnd(dd->gton, n, g, mode, SCATTER_REVERSE)); 262 PetscFunctionReturn(0); 263 } 264