1 2 static char help[] = "Demonstrates use of VecCreateGhost().\n\n"; 3 4 /*T 5 Concepts: vectors^assembling vectors; 6 Concepts: vectors^ghost padding; 7 Processors: n 8 9 Description: Ghost padding is one way to handle local calculations that 10 involve values from other processors. VecCreateGhost() provides 11 a way to create vectors with extra room at the end of the vector 12 array to contain the needed ghost values from other processors, 13 vector computations are otherwise unaffected. 14 T*/ 15 16 /* 17 Include "petscvec.h" so that we can use vectors. Note that this file 18 automatically includes: 19 petscsys.h - base PETSc routines petscis.h - index sets 20 petscviewer.h - viewers 21 */ 22 #include <petscvec.h> 23 24 int main(int argc,char **argv) 25 { 26 PetscMPIInt rank,size; 27 PetscInt nlocal = 6,nghost = 2,ifrom[2],i,rstart,rend; 28 PetscBool flg,flg2,flg3; 29 PetscScalar value,*array,*tarray=0; 30 Vec lx,gx,gxs; 31 32 PetscCall(PetscInitialize(&argc,&argv,(char*)0,help)); 33 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank)); 34 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size)); 35 PetscCheck(size == 2,PETSC_COMM_WORLD,PETSC_ERR_WRONG_MPI_SIZE,"Must run example with two processors"); 36 37 /* 38 Construct a two dimensional graph connecting nlocal degrees of 39 freedom per processor. From this we will generate the global 40 indices of needed ghost values 41 42 For simplicity we generate the entire graph on each processor: 43 in real application the graph would stored in parallel, but this 44 example is only to demonstrate the management of ghost padding 45 with VecCreateGhost(). 46 47 In this example we consider the vector as representing 48 degrees of freedom in a one dimensional grid with periodic 49 boundary conditions. 50 51 ----Processor 1--------- ----Processor 2 -------- 52 0 1 2 3 4 5 6 7 8 9 10 11 53 |----| 54 |-------------------------------------------------| 55 56 */ 57 58 if (rank == 0) { 59 ifrom[0] = 11; ifrom[1] = 6; 60 } else { 61 ifrom[0] = 0; ifrom[1] = 5; 62 } 63 64 /* 65 Create the vector with two slots for ghost points. Note that both 66 the local vector (lx) and the global vector (gx) share the same 67 array for storing vector values. 68 */ 69 PetscCall(PetscOptionsHasName(NULL,NULL,"-allocate",&flg)); 70 PetscCall(PetscOptionsHasName(NULL,NULL,"-vecmpisetghost",&flg2)); 71 PetscCall(PetscOptionsHasName(NULL,NULL,"-minvalues",&flg3)); 72 if (flg) { 73 PetscCall(PetscMalloc1(nlocal+nghost,&tarray)); 74 PetscCall(VecCreateGhostWithArray(PETSC_COMM_WORLD,nlocal,PETSC_DECIDE,nghost,ifrom,tarray,&gxs)); 75 } else if (flg2) { 76 PetscCall(VecCreate(PETSC_COMM_WORLD,&gxs)); 77 PetscCall(VecSetType(gxs,VECMPI)); 78 PetscCall(VecSetSizes(gxs,nlocal,PETSC_DECIDE)); 79 PetscCall(VecMPISetGhost(gxs,nghost,ifrom)); 80 } else { 81 PetscCall(VecCreateGhost(PETSC_COMM_WORLD,nlocal,PETSC_DECIDE,nghost,ifrom,&gxs)); 82 } 83 84 /* 85 Test VecDuplicate() 86 */ 87 PetscCall(VecDuplicate(gxs,&gx)); 88 PetscCall(VecDestroy(&gxs)); 89 90 /* 91 Access the local representation 92 */ 93 PetscCall(VecGhostGetLocalForm(gx,&lx)); 94 95 /* 96 Set the values from 0 to 12 into the "global" vector 97 */ 98 PetscCall(VecGetOwnershipRange(gx,&rstart,&rend)); 99 for (i=rstart; i<rend; i++) { 100 value = (PetscScalar) i; 101 PetscCall(VecSetValues(gx,1,&i,&value,INSERT_VALUES)); 102 } 103 PetscCall(VecAssemblyBegin(gx)); 104 PetscCall(VecAssemblyEnd(gx)); 105 106 PetscCall(VecGhostUpdateBegin(gx,INSERT_VALUES,SCATTER_FORWARD)); 107 PetscCall(VecGhostUpdateEnd(gx,INSERT_VALUES,SCATTER_FORWARD)); 108 109 /* 110 Print out each vector, including the ghost padding region. 111 */ 112 PetscCall(VecGetArray(lx,&array)); 113 for (i=0; i<nlocal+nghost; i++) { 114 PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD,"%" PetscInt_FMT " %g\n",i,(double)PetscRealPart(array[i]))); 115 } 116 PetscCall(VecRestoreArray(lx,&array)); 117 PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT)); 118 PetscCall(VecGhostRestoreLocalForm(gx,&lx)); 119 120 /* Another test that sets ghost values and then accumulates onto the owning processors using MIN_VALUES */ 121 if (flg3) { 122 if (rank == 0)PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD,"\nTesting VecGhostUpdate with MIN_VALUES\n")); 123 PetscCall(VecGhostGetLocalForm(gx,&lx)); 124 PetscCall(VecGetArray(lx,&array)); 125 for (i=0; i<nghost; i++) array[nlocal+i] = rank ? (PetscScalar)4 : (PetscScalar)8; 126 PetscCall(VecRestoreArray(lx,&array)); 127 PetscCall(VecGhostRestoreLocalForm(gx,&lx)); 128 129 PetscCall(VecGhostUpdateBegin(gx,MIN_VALUES,SCATTER_REVERSE)); 130 PetscCall(VecGhostUpdateEnd(gx,MIN_VALUES,SCATTER_REVERSE)); 131 132 PetscCall(VecGhostGetLocalForm(gx,&lx)); 133 PetscCall(VecGetArray(lx,&array)); 134 135 for (i=0; i<nlocal+nghost; i++) { 136 PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD,"%" PetscInt_FMT " %g\n",i,(double)PetscRealPart(array[i]))); 137 } 138 PetscCall(VecRestoreArray(lx,&array)); 139 PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT)); 140 PetscCall(VecGhostRestoreLocalForm(gx,&lx)); 141 } 142 143 PetscCall(VecDestroy(&gx)); 144 145 if (flg) PetscCall(PetscFree(tarray)); 146 PetscCall(PetscFinalize()); 147 return 0; 148 } 149 150 /*TEST 151 152 test: 153 nsize: 2 154 155 test: 156 suffix: 2 157 nsize: 2 158 args: -allocate 159 output_file: output/ex9_1.out 160 161 test: 162 suffix: 3 163 nsize: 2 164 args: -vecmpisetghost 165 output_file: output/ex9_1.out 166 167 test: 168 suffix: 4 169 nsize: 2 170 args: -minvalues 171 output_file: output/ex9_2.out 172 requires: !complex 173 174 TEST*/ 175