Actual source code: centering.c


  2: #include <petsc/private/matimpl.h>

  4: PetscErrorCode MatMult_Centering(Mat A,Vec xx,Vec yy)
  5: {
  6:   PetscScalar       *y;
  7:   const PetscScalar *x;
  8:   PetscScalar       sum,mean;
  9:   PetscInt          i,m=A->rmap->n,size;

 11:   VecSum(xx,&sum);
 12:   VecGetSize(xx,&size);
 13:   mean = sum / (PetscScalar)size;
 14:   VecGetArrayRead(xx,&x);
 15:   VecGetArray(yy,&y);
 16:   for (i=0; i<m; i++) {
 17:     y[i] = x[i] - mean;
 18:   }
 19:   VecRestoreArrayRead(xx,&x);
 20:   VecRestoreArray(yy,&y);
 21:   return 0;
 22: }

 24: /*@
 25:    MatCreateCentering - Creates a new matrix object that implements the (symmetric and idempotent) centering matrix, I - (1/N) * ones*ones'

 27:    Collective on Mat

 29:    Input Parameters:
 30: +  comm - MPI communicator
 31: .  n - number of local rows (or PETSC_DECIDE to have calculated if N is given)
 32:            This value should be the same as the local size used in creating the
 33:            y vector for the matrix-vector product y = Ax.
 34: -  N - number of global rows (or PETSC_DETERMINE to have calculated if n is given)

 36:    Output Parameter:
 37: .  C - the matrix

 39:    Notes:
 40:    The entries of the matrix C are not explicitly stored. Instead, the new matrix
 41:    object is a shell that simply performs the action of the centering matrix, i.e.,
 42:    multiplying C*x subtracts the mean of the vector x from each of its elements.
 43:    This is useful for preserving sparsity when mean-centering the columns of a
 44:    matrix is required. For instance, to perform principal components analysis with
 45:    a matrix A, the composite matrix C*A can be passed to a partial SVD solver.

 47:    Level: intermediate

 49: .seealso: MatCreateLRC(), MatCreateComposite()
 50: @*/
 51: PetscErrorCode MatCreateCentering(MPI_Comm comm,PetscInt n,PetscInt N,Mat *C)
 52: {
 53:   PetscMPIInt    size;

 55:   MatCreate(comm,C);
 56:   MatSetSizes(*C,n,n,N,N);
 57:   MPI_Comm_size(comm,&size);
 58:   PetscObjectChangeTypeName((PetscObject)*C,MATCENTERING);

 60:   (*C)->ops->mult         = MatMult_Centering;
 61:   (*C)->assembled         = PETSC_TRUE;
 62:   (*C)->preallocated      = PETSC_TRUE;
 63:   (*C)->symmetric         = PETSC_TRUE;
 64:   (*C)->symmetric_eternal = PETSC_TRUE;
 65:   MatSetUp(*C);
 66:   return 0;
 67: }