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: }