1 /* 2 Code for manipulating distributed regular arrays in parallel. 3 */ 4 5 #include <petsc/private/dmdaimpl.h> /*I "petscdmda.h" I*/ 6 7 static PetscErrorCode VecDuplicate_MPI_DA(Vec g, Vec *gg) 8 { 9 DM da; 10 PetscLayout map; 11 12 PetscFunctionBegin; 13 PetscCall(VecGetDM(g, &da)); 14 PetscCall(DMCreateGlobalVector(da, gg)); 15 PetscCall(VecGetLayout(g, &map)); 16 PetscCall(VecSetLayout(*gg, map)); 17 PetscFunctionReturn(PETSC_SUCCESS); 18 } 19 20 PetscErrorCode DMCreateGlobalVector_DA(DM da, Vec *g) 21 { 22 DM_DA *dd = (DM_DA *)da->data; 23 24 PetscFunctionBegin; 25 PetscValidHeaderSpecific(da, DM_CLASSID, 1); 26 PetscAssertPointer(g, 2); 27 PetscCall(VecCreate(PetscObjectComm((PetscObject)da), g)); 28 PetscCall(VecSetSizes(*g, dd->Nlocal, PETSC_DETERMINE)); 29 PetscCall(VecSetBlockSize(*g, dd->w)); 30 PetscCall(VecSetType(*g, da->vectype)); 31 if (dd->Nlocal < da->bind_below) { 32 PetscCall(VecSetBindingPropagates(*g, PETSC_TRUE)); 33 PetscCall(VecBindToCPU(*g, PETSC_TRUE)); 34 } 35 PetscCall(VecSetDM(*g, da)); 36 PetscCall(VecSetLocalToGlobalMapping(*g, da->ltogmap)); 37 PetscCall(VecSetOperation(*g, VECOP_VIEW, (void (*)(void))VecView_MPI_DA)); 38 PetscCall(VecSetOperation(*g, VECOP_LOAD, (void (*)(void))VecLoad_Default_DA)); 39 PetscCall(VecSetOperation(*g, VECOP_DUPLICATE, (void (*)(void))VecDuplicate_MPI_DA)); 40 PetscFunctionReturn(PETSC_SUCCESS); 41 } 42 43 /*@ 44 DMDACreateNaturalVector - Creates a parallel PETSc vector that 45 will hold vector values in the natural numbering, rather than in 46 the PETSc parallel numbering associated with the `DMDA`. 47 48 Collective 49 50 Input Parameter: 51 . da - the distributed array 52 53 Output Parameter: 54 . g - the distributed global vector 55 56 Level: advanced 57 58 Notes: 59 The natural numbering is a number of grid nodes that starts with, in three dimensions, with (0,0,0), (1,0,0), (2,0,0), ..., (m-1,0,0) followed by 60 (0,1,0), (1,1,0), (2,1,0), ..., (m,1,0) etc up to (0,n-1,p-1), (1,n-1,p-1), (2,n-1,p-1), ..., (m-1,n-1,p-1). 61 62 The output parameter, `g`, is a regular `Vec` that should be destroyed 63 with a call to `VecDestroy()` when usage is finished. 64 65 The number of local entries in the vector on each process is the same 66 as in a vector created with `DMCreateGlobalVector()`. 67 68 .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGlobalToNaturalBegin()`, `DMDAGlobalToNaturalEnd()`, `DMDANaturalToGlobalBegin()`, `DMDANaturalToGlobalEnd()`, 69 `DMCreateLocalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`, 70 `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()` 71 @*/ 72 PetscErrorCode DMDACreateNaturalVector(DM da, Vec *g) 73 { 74 PetscInt cnt; 75 DM_DA *dd = (DM_DA *)da->data; 76 77 PetscFunctionBegin; 78 PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA); 79 PetscAssertPointer(g, 2); 80 if (dd->natural) { 81 PetscCall(PetscObjectGetReference((PetscObject)dd->natural, &cnt)); 82 if (cnt == 1) { /* object is not currently used by anyone */ 83 PetscCall(PetscObjectReference((PetscObject)dd->natural)); 84 *g = dd->natural; 85 } else PetscCall(VecDuplicate(dd->natural, g)); 86 } else { /* create the first version of this guy */ 87 PetscCall(VecCreate(PetscObjectComm((PetscObject)da), g)); 88 PetscCall(VecSetSizes(*g, dd->Nlocal, PETSC_DETERMINE)); 89 PetscCall(VecSetBlockSize(*g, dd->w)); 90 PetscCall(VecSetType(*g, da->vectype)); 91 PetscCall(PetscObjectReference((PetscObject)*g)); 92 dd->natural = *g; 93 } 94 PetscFunctionReturn(PETSC_SUCCESS); 95 } 96