1 2 /* 3 Code for manipulating distributed regular arrays in parallel. 4 */ 5 6 #include <petsc/private/dmdaimpl.h> /*I "petscdmda.h" I*/ 7 8 /* 9 DMLocalToLocalCreate_DA - Creates the local to local scatter 10 11 Collective on da 12 13 Input Parameter: 14 . da - the distributed array 15 16 */ 17 PetscErrorCode DMLocalToLocalCreate_DA(DM da) 18 { 19 PetscInt *idx, left, j, count, up, down, i, bottom, top, k, dim = da->dim; 20 DM_DA *dd = (DM_DA *)da->data; 21 22 PetscFunctionBegin; 23 PetscValidHeaderSpecific(da, DM_CLASSID, 1); 24 25 if (dd->ltol) PetscFunctionReturn(0); 26 /* 27 We simply remap the values in the from part of 28 global to local to read from an array with the ghost values 29 rather then from the plain array. 30 */ 31 PetscCall(VecScatterCopy(dd->gtol, &dd->ltol)); 32 if (dim == 1) { 33 left = dd->xs - dd->Xs; 34 PetscCall(PetscMalloc1(dd->xe - dd->xs, &idx)); 35 for (j = 0; j < dd->xe - dd->xs; j++) idx[j] = left + j; 36 } else if (dim == 2) { 37 left = dd->xs - dd->Xs; 38 down = dd->ys - dd->Ys; 39 up = down + dd->ye - dd->ys; 40 PetscCall(PetscMalloc1((dd->xe - dd->xs) * (up - down), &idx)); 41 count = 0; 42 for (i = down; i < up; i++) { 43 for (j = 0; j < dd->xe - dd->xs; j++) idx[count++] = left + i * (dd->Xe - dd->Xs) + j; 44 } 45 } else if (dim == 3) { 46 left = dd->xs - dd->Xs; 47 bottom = dd->ys - dd->Ys; 48 top = bottom + dd->ye - dd->ys; 49 down = dd->zs - dd->Zs; 50 up = down + dd->ze - dd->zs; 51 count = (dd->xe - dd->xs) * (top - bottom) * (up - down); 52 PetscCall(PetscMalloc1(count, &idx)); 53 count = 0; 54 for (i = down; i < up; i++) { 55 for (j = bottom; j < top; j++) { 56 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; 57 } 58 } 59 } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_CORRUPT, "DMDA has invalid dimension %" PetscInt_FMT, dim); 60 61 PetscCall(VecScatterRemap(dd->ltol, idx, NULL)); 62 PetscCall(PetscFree(idx)); 63 PetscFunctionReturn(0); 64 } 65 66 /* 67 DMLocalToLocalBegin_DA - Maps from a local vector (including ghost points 68 that contain irrelevant values) to another local vector where the ghost 69 points in the second are set correctly. Must be followed by DMLocalToLocalEnd_DA(). 70 71 Neighbor-wise Collective on da 72 73 Input Parameters: 74 + da - the distributed array context 75 . g - the original local vector 76 - mode - one of INSERT_VALUES or ADD_VALUES 77 78 Output Parameter: 79 . l - the local vector with correct ghost values 80 81 Notes: 82 The local vectors used here need not be the same as those 83 obtained from DMCreateLocalVector(), BUT they 84 must have the same parallel data layout; they could, for example, be 85 obtained with VecDuplicate() from the DMDA originating vectors. 86 87 */ 88 PetscErrorCode DMLocalToLocalBegin_DA(DM da, Vec g, InsertMode mode, Vec l) 89 { 90 DM_DA *dd = (DM_DA *)da->data; 91 92 PetscFunctionBegin; 93 PetscValidHeaderSpecific(da, DM_CLASSID, 1); 94 if (!dd->ltol) PetscCall(DMLocalToLocalCreate_DA(da)); 95 PetscCall(VecScatterBegin(dd->ltol, g, l, mode, SCATTER_FORWARD)); 96 PetscFunctionReturn(0); 97 } 98 99 /* 100 DMLocalToLocalEnd_DA - Maps from a local vector (including ghost points 101 that contain irrelevant values) to another local vector where the ghost 102 points in the second are set correctly. Must be preceded by 103 DMLocalToLocalBegin_DA(). 104 105 Neighbor-wise Collective on da 106 107 Input Parameters: 108 + da - the distributed array context 109 . g - the original local vector 110 - mode - one of INSERT_VALUES or ADD_VALUES 111 112 Output Parameter: 113 . l - the local vector with correct ghost values 114 115 Note: 116 The local vectors used here need not be the same as those 117 obtained from DMCreateLocalVector(), BUT they 118 must have the same parallel data layout; they could, for example, be 119 obtained with VecDuplicate() from the DMDA originating vectors. 120 121 */ 122 PetscErrorCode DMLocalToLocalEnd_DA(DM da, Vec g, InsertMode mode, Vec l) 123 { 124 DM_DA *dd = (DM_DA *)da->data; 125 126 PetscFunctionBegin; 127 PetscValidHeaderSpecific(da, DM_CLASSID, 1); 128 PetscValidHeaderSpecific(g, VEC_CLASSID, 2); 129 PetscCall(VecScatterEnd(dd->ltol, g, l, mode, SCATTER_FORWARD)); 130 PetscFunctionReturn(0); 131 } 132