Actual source code: ex4.c
petsc-3.3-p7 2013-05-11
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: petscsys.h - base PETSc routines petscvec.h - vectors
9: petscmat.h - matrices
10: petscis.h - index sets petscviewer.h - viewers
11: */
12: #include <petscmat.h>
13: extern PetscErrorCode LowRankUpdate(Mat,Mat,Vec,Vec,Vec,Vec,PetscInt);
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: PetscBool 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,&flg);
36: if (!flg) SETERRQ(PETSC_COMM_WORLD,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: MatCreate(PETSC_COMM_WORLD,&U);
50: MatSetType(U,MATMPIDENSE);
51: MatLoad(U,fd);
52: MatCreate(PETSC_COMM_WORLD,&V);
53: MatSetType(V,MATMPIDENSE);
54: MatLoad(V,fd);
55: PetscViewerDestroy(&fd);
57: MatGetLocalSize(U,&N,&n);
58: MatGetLocalSize(V,&M,&m);
59: if (N != M) SETERRQ2(PETSC_COMM_SELF,1,"U and V matrices must have same number of local rows %D %D",N,M);
60: if (n != m) SETERRQ2(PETSC_COMM_SELF,1,"U and V matrices must have same number of local columns %D %D",n,m);
62: VecCreateMPI(PETSC_COMM_WORLD,N,PETSC_DETERMINE,&x);
63: VecDuplicate(x,&y);
65: MatGetSize(U,0,&n);
66: VecCreateSeq(PETSC_COMM_SELF,n,&work1);
67: VecDuplicate(work1,&work2);
69: /* put some initial values into x for testing */
70: VecGetArray(x,&xx);
71: for (i=0; i<N; i++) xx[i] = i;
72: VecRestoreArray(x,&xx);
73: LowRankUpdate(U,V,x,y,work1,work2,n);
74: VecView(x,PETSC_VIEWER_STDOUT_WORLD);
75: VecView(y,PETSC_VIEWER_STDOUT_WORLD);
77: /*
78: Free work space. All PETSc objects should be destroyed when they
79: are no longer needed.
80: */
81: MatDestroy(&U);
82: MatDestroy(&V);
83: VecDestroy(&x);
84: VecDestroy(&y);
85: VecDestroy(&work1);
86: VecDestroy(&work2);
88: PetscFinalize();
89: return 0;
90: }
92: #include <../src/mat/impls/dense/mpi/mpidense.h>
96: /*
97: Computes y = V*U'*x where U and V are N by n (N >> n).
99: U and V are stored as PETSc MPIDENSE (parallel) dense matrices with their rows partitioned the
100: same way as x and y are partitioned
102: Note: this routine directly access the Vec and Mat data-structures
103: */
104: PetscErrorCode LowRankUpdate(Mat U,Mat V,Vec x,Vec y,Vec work1,Vec work2,PetscInt nwork)
105: {
106: Mat Ulocal = ((Mat_MPIDense*)U->data)->A;
107: Mat Vlocal = ((Mat_MPIDense*)V->data)->A;
108: PetscInt Nsave = x->map->N;
110: PetscScalar *w1,*w2;
113: /* First multiply the local part of U with the local part of x */
114: x->map->N = x->map->n; /* this tricks the silly error checking in MatMultTranspose();*/
115: MatMultTranspose(Ulocal,x,work1);/* note in this call x is treated as a sequential vector */
116: x->map->N = Nsave;
118: /* Form the sum of all the local multiplies : this is work2 = U'*x = sum_{all processors} work1 */
119: VecGetArray(work1,&w1);
120: VecGetArray(work2,&w2);
121: MPI_Allreduce(w1,w2,nwork,MPI_DOUBLE,MPI_SUM,PETSC_COMM_WORLD);
122: VecRestoreArray(work1,&w1);
123: VecRestoreArray(work2,&w2);
125: /* multiply y = V*work2 */
126: y->map->N = y->map->n; /* this tricks the silly error checking in MatMult() */
127: MatMult(Vlocal,work2,y);/* note in this call y is treated as a sequential vector */
128: y->map->N = Nsave;
130: return(0);
131: }