Actual source code: ex26.c

  1: /*$Id: ex26.c,v 1.13 2001/09/11 16:32:10 bsmith Exp $*/
  2: /*

  4: Test program follows. Writing it I realised that 
  5: 1/ I built the pipeline object around an MPI-to-MPI vector scatter.
  6: 2/ That necessitates the 'little trick' below.
  7: 3/ This trick will always be necessary, since the code inside the
  8:   pipe is a critical section.
  9: 4/ Hence I really should have used an MPI-to-Seq scatter.
 10: 5/ This shouldn't be too hard to fix in the implementation you
 11:   guys are making,right?  :-)  <-- smiley just in case.

 13: If this is not clear, I'll try to elaborate.

 15: */
 16: /* Example of pipeline code: 
 17:    accumulation of the sum $s_p=sum_{qleq p} (q+1)^2$.
 18:    E.g., processor 3 computes 1^2+2^2+3^+4^2 = 30.
 19:    Every processor computes its term, then passes it on to the next.
 20: */
 21:  #include petscvec.h

 23: int main(int Argc,char **Args)
 24: {
 25:   Vec         src_v,tar_v,loc_v;
 26:   IS          src_idx,tar_idx;
 27:   VecPipeline pipe;
 28:   MPI_Comm    comm;
 29:   int         size,rank,src_loc,tar_loc,ierr,zero_loc=0;
 30:   PetscScalar zero=0,my_value,*vec_values,*loc_ar;

 32:   PetscInitialize(&Argc,&Args,PETSC_NULL,PETSC_NULL);

 34:   comm = MPI_COMM_WORLD;
 35:   MPI_Comm_size(comm,&size);
 36:   MPI_Comm_rank(comm,&rank);
 37: 
 38:   /* Create the necessary vectors; one element per processor */
 39:   VecCreate(comm,&tar_v);
 40:   VecSetSizes(tar_v,1,PETSC_DECIDE);
 41:   VecSetFromOptions(tar_v);
 42:   VecSet(&zero,tar_v);
 43:   VecCreate(comm,&src_v);
 44:   VecSetSizes(src_v,1,PETSC_DECIDE);
 45:   VecSetFromOptions(src_v);
 46:   VecCreateSeq(MPI_COMM_SELF,1,&loc_v);
 47:   /* -- little trick: we need a distributed and a local vector
 48:      that share each other's data; see below for application */
 49:   VecGetArray(loc_v,&loc_ar);
 50:   VecPlaceArray(src_v,loc_ar);

 52:   /* Create the pipeline data: we write into our own location,
 53:      and read one location from the left */
 54:   tar_loc = rank;
 55:   if (tar_loc>0) src_loc = tar_loc-1; else src_loc = tar_loc;
 56:   ISCreateGeneral(MPI_COMM_SELF,1,&tar_loc,&tar_idx);
 57:   ISCreateGeneral(MPI_COMM_SELF,1,&src_loc,&src_idx);
 58:   VecPipelineCreate(comm,src_v,src_idx,tar_v,tar_idx,&pipe);
 59:   VecPipelineSetType(pipe,PIPELINE_SEQUENTIAL,PETSC_NULL);
 60:   VecPipelineSetup(pipe);

 62:   /* The actual pipe:
 63:      receive accumulated value from previous processor,
 64:      add the square of your own value, and send on. */
 65:   VecPipelineBegin(src_v,tar_v,INSERT_VALUES,SCATTER_FORWARD,PIPELINE_UP,pipe);
 66:   VecGetArray(tar_v,&vec_values);
 67:   my_value = vec_values[0] + (PetscReal)((rank+1)*(rank+1));

 69:   VecRestoreArray(tar_v,&vec_values);CHKERRQ(ierr)
 70:   /* -- little trick: we have to be able to call VecAssembly, 
 71:      but since this code executed sequentially (critical section!),
 72:      we have a local vector with data aliased to the distributed one */
 73:   VecSetValues(loc_v,1,&zero_loc,&my_value,INSERT_VALUES);
 74:   VecAssemblyBegin(loc_v);
 75:   VecAssemblyEnd(loc_v);
 76:   VecPipelineEnd(src_v,tar_v,INSERT_VALUES,SCATTER_FORWARD,PIPELINE_UP,pipe);

 78:   PetscSynchronizedPrintf(PETSC_COMM_WORLD,"[%d] value=%dn",rank,(int)PetscRealPart(my_value));
 79:   PetscSynchronizedFlush(PETSC_COMM_WORLD);

 81:   /* Clean up */
 82:   VecPipelineDestroy(pipe);
 83:   VecDestroy(src_v);
 84:   VecDestroy(tar_v);
 85:   VecDestroy(loc_v);
 86:   ISDestroy(src_idx);
 87:   ISDestroy(tar_idx);

 89:   PetscFinalize();

 91:   return 0;
 92: }