Actual source code: normm.c

  1: #define PETSCMAT_DLL

 3:  #include include/private/matimpl.h

  5: typedef struct {
  6:   Mat A;
  7:   Vec w;
  8: } Mat_Normal;

 12: PetscErrorCode MatMult_Normal(Mat N,Vec x,Vec y)
 13: {
 14:   Mat_Normal     *Na = (Mat_Normal*)N->data;

 18:   MatMult(Na->A,x,Na->w);
 19:   MatMultTranspose(Na->A,Na->w,y);
 20:   return(0);
 21: }
 22: 
 25: PetscErrorCode MatMultAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3)
 26: {
 27:   Mat_Normal     *Na = (Mat_Normal*)N->data;
 29: 
 31:   MatMult(Na->A,v1,Na->w);
 32:   MatMultTransposeAdd(Na->A,Na->w,v2,v3);
 33:   return(0);
 34: }

 38: PetscErrorCode MatDestroy_Normal(Mat N)
 39: {
 40:   Mat_Normal     *Na = (Mat_Normal*)N->data;

 44:   PetscObjectDereference((PetscObject)Na->A);
 45:   VecDestroy(Na->w);
 46:   PetscFree(Na);
 47:   return(0);
 48: }
 49: 
 50: /*
 51:       Slow, nonscalable version
 52: */
 55: PetscErrorCode MatGetDiagonal_Normal(Mat N,Vec v)
 56: {
 57:   Mat_Normal        *Na = (Mat_Normal*)N->data;
 58:   Mat               A = Na->A;
 59:   PetscErrorCode    ierr;
 60:   PetscInt          i,j,rstart,rend,nnz;
 61:   const PetscInt    *cols;
 62:   PetscScalar       *diag,*work,*values;
 63:   const PetscScalar *mvalues;

 66:   PetscMalloc(2*A->cmap.N*sizeof(PetscScalar),&diag);
 67:   work = diag + A->cmap.N;
 68:   PetscMemzero(work,A->cmap.N*sizeof(PetscScalar));
 69:   MatGetOwnershipRange(A,&rstart,&rend);
 70:   for (i=rstart; i<rend; i++) {
 71:     MatGetRow(A,i,&nnz,&cols,&mvalues);
 72:     for (j=0; j<nnz; j++) {
 73:       work[cols[j]] += mvalues[j]*mvalues[j];
 74:     }
 75:     MatRestoreRow(A,i,&nnz,&cols,&mvalues);
 76:   }
 77:   MPI_Allreduce(work,diag,A->cmap.N,MPIU_SCALAR,MPI_SUM,N->comm);
 78:   rstart = N->cmap.rstart;
 79:   rend   = N->cmap.rend;
 80:   VecGetArray(v,&values);
 81:   PetscMemcpy(values,diag+rstart,(rend-rstart)*sizeof(PetscScalar));
 82:   VecRestoreArray(v,&values);
 83:   PetscFree(diag);
 84:   return(0);
 85: }

 89: /*@
 90:       MatCreateNormal - Creates a new matrix object that behaves like A'*A.

 92:    Collective on Mat

 94:    Input Parameter:
 95: .   A  - the (possibly rectangular) matrix

 97:    Output Parameter:
 98: .   N - the matrix that represents A'*A

100:    Level: intermediate

102:    Notes: The product A'*A is NOT actually formed! Rather the new matrix
103:           object performs the matrix-vector product by first multiplying by
104:           A and then A'
105: @*/
106: PetscErrorCode  MatCreateNormal(Mat A,Mat *N)
107: {
109:   PetscInt       m,n;
110:   Mat_Normal     *Na;

113:   MatGetLocalSize(A,&m,&n);
114:   MatCreate(A->comm,N);
115:   MatSetSizes(*N,n,n,PETSC_DECIDE,PETSC_DECIDE);
116:   PetscObjectChangeTypeName((PetscObject)*N,MATNORMAL);
117: 
118:   PetscNew(Mat_Normal,&Na);
119:   Na->A     = A;
120:   PetscObjectReference((PetscObject)A);
121:   (*N)->data = (void*) Na;

123:   VecCreateMPI(A->comm,m,PETSC_DECIDE,&Na->w);
124:   (*N)->ops->destroy     = MatDestroy_Normal;
125:   (*N)->ops->mult        = MatMult_Normal;
126:   (*N)->ops->multadd     = MatMultAdd_Normal;
127:   (*N)->ops->getdiagonal = MatGetDiagonal_Normal;
128:   (*N)->assembled        = PETSC_TRUE;
129:   (*N)->cmap.N           = A->cmap.N;
130:   (*N)->rmap.N           = A->cmap.N;
131:   (*N)->cmap.n           = A->cmap.n;
132:   (*N)->rmap.n           = A->cmap.n;
133:   return(0);
134: }