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