Actual source code: ex4.c
2: static char help[] = "Reads U and V matrices from a file and performs y = V*U'*x.\n\
3: -f <input_file> : file to load \n\n";
5: /*
6: Include "petscmat.h" so that we can use matrices.
7: automatically includes:
8: petsc.h - base PETSc routines petscvec.h - vectors
9: petscsys.h - system routines petscmat.h - matrices
10: petscis.h - index sets petscviewer.h - viewers
11: */
12: #include petscmat.h
18: int main(int argc,char **args)
19: {
20: Mat U,V; /* matrix */
21: PetscViewer fd; /* viewer */
22: char file[PETSC_MAX_PATH_LEN]; /* input file name */
23: PetscErrorCode ierr;
24: PetscTruth flg;
25: Vec x,y,work1,work2;
26: PetscInt i,N,n,M,m;
27: PetscScalar *xx;
29: PetscInitialize(&argc,&args,(char *)0,help);
31: /*
32: Determine file from which we read the matrix
34: */
35: PetscOptionsGetString(PETSC_NULL,"-f",file,PETSC_MAX_PATH_LEN-1,&flg);
36: if (!flg) SETERRQ(1,"Must indicate binary file with the -f option");
39: /*
40: Open binary file. Note that we use FILE_MODE_READ to indicate
41: reading from this file.
42: */
43: PetscViewerBinaryOpen(PETSC_COMM_WORLD,file,FILE_MODE_READ,&fd);
45: /*
46: Load the matrix; then destroy the viewer.
47: Note both U and V are stored as tall skinny matrices
48: */
49: MatLoad(fd,MATMPIDENSE,&U);
50: MatLoad(fd,MATMPIDENSE,&V);
51: PetscViewerDestroy(fd);
53: MatGetLocalSize(U,&N,&n);
54: MatGetLocalSize(V,&M,&m);
55: if (N != M) SETERRQ2(1,"U and V matrices must have same number of local rows %D %D",N,M);
56: if (n != m) SETERRQ2(1,"U and V matrices must have same number of local columns %D %D",n,m);
58: VecCreateMPI(PETSC_COMM_WORLD,N,PETSC_DETERMINE,&x);
59: VecDuplicate(x,&y);
61: MatGetSize(U,0,&n);
62: VecCreateSeq(PETSC_COMM_SELF,n,&work1);
63: VecDuplicate(work1,&work2);
65: /* put some initial values into x for testing */
66: VecGetArray(x,&xx);
67: for (i=0; i<N; i++) xx[i] = i;
68: VecRestoreArray(x,&xx);
69: LowRankUpdate(U,V,x,y,work1,work2,n);
70: VecView(x,PETSC_VIEWER_STDOUT_WORLD);
71: VecView(y,PETSC_VIEWER_STDOUT_WORLD);
73: /*
74: Free work space. All PETSc objects should be destroyed when they
75: are no longer needed.
76: */
77: MatDestroy(U);
78: MatDestroy(V);
79: VecDestroy(x);
80: VecDestroy(y);
81: VecDestroy(work1);
82: VecDestroy(work2);
84: PetscFinalize();
85: return 0;
86: }
88: #include ../src/mat/impls/dense/mpi/mpidense.h
92: /*
93: Computes y = V*U'*x where U and V are N by n (N >> n).
95: U and V are stored as PETSc MPIDENSE (parallel) dense matrices with their rows partitioned the
96: same way as x and y are partitioned
98: Note: this routine directly access the Vec and Mat data-structures
99: */
100: PetscErrorCode LowRankUpdate(Mat U,Mat V,Vec x,Vec y,Vec work1,Vec work2,PetscInt nwork)
101: {
102: Mat Ulocal = ((Mat_MPIDense*)U->data)->A;
103: Mat Vlocal = ((Mat_MPIDense*)V->data)->A;
104: PetscInt Nsave = x->map->N;
106: PetscScalar *w1,*w2;
109: /* First multiply the local part of U with the local part of x */
110: x->map->N = x->map->n; /* this tricks the silly error checking in MatMultTranspose();*/
111: MatMultTranspose(Ulocal,x,work1);/* note in this call x is treated as a sequential vector */
112: x->map->N = Nsave;
114: /* Form the sum of all the local multiplies : this is work2 = U'*x = sum_{all processors} work1 */
115: VecGetArray(work1,&w1);
116: VecGetArray(work2,&w2);
117: MPI_Allreduce(w1,w2,nwork,MPI_DOUBLE,MPI_SUM,PETSC_COMM_WORLD);
118: VecRestoreArray(work1,&w1);
119: VecRestoreArray(work2,&w2);
121: /* multiply y = V*work2 */
122: y->map->N = y->map->n; /* this tricks the silly error checking in MatMult() */
123: MatMult(Vlocal,work2,y);/* note in this call y is treated as a sequential vector */
124: y->map->N = Nsave;
126: return(0);
127: }