Actual source code: getcolv.c

  1: #define PETSCMAT_DLL

 3:  #include private/matimpl.h

  7: /*@
  8:    MatGetColumnVector - Gets the values from a given column of a matrix.

 10:    Not Collective

 12:    Input Parameters:
 13: +  A - the matrix
 14: .  yy - the vector
 15: -  c - the column requested (in global numbering)

 17:    Level: advanced

 19:    Notes:
 20:    Each processor for which this is called gets the values for its rows.

 22:    Since PETSc matrices are usually stored in compressed row format, this routine
 23:    will generally be slow.

 25:    The vector must have the same parallel row layout as the matrix.

 27:    Contributed by: Denis Vanderstraeten

 29: .keywords: matrix, column, get 

 31: .seealso: MatGetRow(), MatGetDiagonal()

 33: @*/
 34: PetscErrorCode  MatGetColumnVector(Mat A,Vec yy,PetscInt col)
 35: {
 36:   PetscScalar        *y;
 37:   const PetscScalar  *v;
 38:   PetscErrorCode     ierr;
 39:   PetscInt           i,j,nz,N,Rs,Re,rs,re;
 40:   const PetscInt     *idx;
 41: 
 45:   if (col < 0)  SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Requested negative column: %D",col);
 46:   MatGetSize(A,PETSC_NULL,&N);
 47:   if (col >= N)  SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Requested column %D larger than number columns in matrix %D",col,N);
 48:   MatGetOwnershipRange(A,&Rs,&Re);
 49:   VecGetOwnershipRange(yy,&rs,&re);
 50:   if (Rs != rs || Re != re) SETERRQ4(PETSC_ERR_ARG_INCOMP,"Matrix %D %D does not have same ownership range (size) as vector %D %D",Rs,Re,rs,re);

 52:   if (A->ops->getcolumnvector) {
 53:     (*A->ops->getcolumnvector)(A,yy,col);
 54:   } else {
 55:     VecSet(yy,0.0);
 56:     VecGetArray(yy,&y);
 57: 
 58:     for (i=Rs; i<Re; i++) {
 59:       MatGetRow(A,i,&nz,&idx,&v);
 60:       if (nz && idx[0] <= col) {
 61:         /*
 62:           Should use faster search here 
 63:         */
 64:         for (j=0; j<nz; j++) {
 65:           if (idx[j] >= col) {
 66:             if (idx[j] == col) y[i-rs] = v[j];
 67:             break;
 68:           }
 69:         }
 70:       }
 71:       MatRestoreRow(A,i,&nz,&idx,&v);
 72:     }
 73:     VecRestoreArray(yy,&y);
 74:   }
 75:   return(0);
 76: }

 78:  #include ../src/mat/impls/aij/seq/aij.h

 82: PetscErrorCode MatGetColumnNorms_SeqAIJ(Mat A,NormType type,PetscReal *norms)
 83: {
 85:   PetscInt       i,m,n;
 86:   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;

 89:   MatGetSize(A,&m,&n);
 90:   PetscMemzero(norms,n*sizeof(PetscReal));
 91:   if (type == NORM_2) {
 92:     for (i=0; i<aij->i[m]; i++) {
 93:       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
 94:     }
 95:   } else if (type == NORM_1) {
 96:     for (i=0; i<aij->i[m]; i++) {
 97:       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]);
 98:     }
 99:   } else if (type == NORM_INFINITY) {
100:     for (i=0; i<aij->i[m]; i++) {
101:       norms[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),norms[aij->j[i]]);
102:     }
103:   } else SETERRQ(PETSC_ERR_ARG_WRONG,"Unknown NormType");

105:   if (type == NORM_2) {
106:     for (i=0; i<n; i++) norms[i] = sqrt(norms[i]);
107:   }
108:   return(0);
109: }

111:  #include ../src/mat/impls/aij/mpi/mpiaij.h

115: PetscErrorCode MatGetColumnNorms_MPIAIJ(Mat A,NormType type,PetscReal *norms)
116: {
118:   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)A->data;
119:   PetscInt       i,n,*garray = aij->garray;
120:   Mat_SeqAIJ     *a_aij = (Mat_SeqAIJ*) aij->A->data;
121:   Mat_SeqAIJ     *b_aij = (Mat_SeqAIJ*) aij->B->data;
122:   PetscReal      *work;

125:   MatGetSize(A,PETSC_NULL,&n);
126:   PetscMalloc(n*sizeof(PetscReal),&work);
127:   PetscMemzero(work,n*sizeof(PetscReal));
128:   if (type == NORM_2) {
129:     for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) {
130:       work[A->rmap->rstart + a_aij->j[i]] += PetscAbsScalar(a_aij->a[i]*a_aij->a[i]);
131:     }
132:     for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) {
133:       work[garray[b_aij->j[i]]] += PetscAbsScalar(b_aij->a[i]*b_aij->a[i]);
134:     }
135:   } else if (type == NORM_1) {
136:     for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) {
137:       work[A->rmap->rstart + a_aij->j[i]] += PetscAbsScalar(a_aij->a[i]);
138:     }
139:     for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) {
140:       work[garray[b_aij->j[i]]] += PetscAbsScalar(b_aij->a[i]);
141:     }
142:   } else if (type == NORM_INFINITY) {
143:     for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) {
144:       work[A->rmap->rstart + a_aij->j[i]] = PetscMax(PetscAbsScalar(a_aij->a[i]), work[A->rmap->rstart + a_aij->j[i]]);
145:     }
146:     for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) {
147:       work[garray[b_aij->j[i]]] = PetscMax(PetscAbsScalar(b_aij->a[i]),work[garray[b_aij->j[i]]]);
148:     }

150:   } else SETERRQ(PETSC_ERR_ARG_WRONG,"Unknown NormType");
151:   if (type == NORM_INFINITY) {
152:     MPI_Allreduce(work,norms,n,MPIU_REAL,MPI_MAX,A->hdr.comm);
153:   } else {
154:     MPI_Allreduce(work,norms,n,MPIU_REAL,MPI_SUM,A->hdr.comm);
155:   }
156:   PetscFree(work);
157:   if (type == NORM_2) {
158:     for (i=0; i<n; i++) norms[i] = sqrt(norms[i]);
159:   }
160:   return(0);
161: }

165: PetscErrorCode MatGetColumnNorms_SeqDense(Mat A,NormType type,PetscReal *norms)
166: {
168:   PetscInt       i,j,m,n;
169:   PetscScalar    *a;

172:   MatGetSize(A,&m,&n);
173:   PetscMemzero(norms,n*sizeof(PetscReal));
174:   MatGetArray(A,&a);
175:   if (type == NORM_2) {
176:     for (i=0; i<n; i++ ){
177:       for (j=0; j<m; j++) {
178:         norms[i] += PetscAbsScalar(a[j]*a[j]);
179:       }
180:       a += m;
181:     }
182:   } else if (type == NORM_1) {
183:     for (i=0; i<n; i++ ){
184:       for (j=0; j<m; j++) {
185:         norms[i] += PetscAbsScalar(a[j]);
186:       }
187:       a += m;
188:     }
189:   } else if (type == NORM_INFINITY) {
190:     for (i=0; i<n; i++ ){
191:       for (j=0; j<m; j++) {
192:         norms[i] = PetscMax(PetscAbsScalar(a[j]),norms[i]);
193:       }
194:       a += m;
195:     }
196:   } else SETERRQ(PETSC_ERR_ARG_WRONG,"Unknown NormType");
197:   if (type == NORM_2) {
198:     for (i=0; i<n; i++) norms[i] = sqrt(norms[i]);
199:   }
200:   return(0);
201: }

203:  #include ../src/mat/impls/dense/mpi/mpidense.h
206: PetscErrorCode MatGetColumnNorms_MPIDense(Mat A,NormType type,PetscReal *norms)
207: {
209:   PetscInt       i,n;
210:   Mat_MPIDense   *a = (Mat_MPIDense*) A->data;
211:   PetscReal      *work;

214:   MatGetSize(A,PETSC_NULL,&n);
215:   PetscMalloc(n*sizeof(PetscReal),&work);
216:   MatGetColumnNorms_SeqDense(a->A,type,work);
217:   if (type == NORM_2) {
218:     for (i=0; i<n; i++) work[i] *= work[i];
219:   }
220:   if (type == NORM_INFINITY) {
221:     MPI_Allreduce(work,norms,n,MPIU_REAL,MPI_MAX,A->hdr.comm);
222:   } else {
223:     MPI_Allreduce(work,norms,n,MPIU_REAL,MPI_SUM,A->hdr.comm);
224:   }
225:   PetscFree(work);
226:   if (type == NORM_2) {
227:     for (i=0; i<n; i++) norms[i] = sqrt(norms[i]);
228:   }
229:   return(0);
230: }

234: /*@
235:     MatGetColumnNorms - Gets the 2 norms of each column of a sparse or dense matrix.

237:   Input Parameter:
238: +  A - the matrix
239: -  type - NORM_2, NORM_1 or NORM_INFINITY

241:   Output Parameter:
242: .  norms - an array as large as the TOTAL number of columns in the matrix

244:    Level: intermediate

246:    Notes: Each process has ALL the column norms after the call. Because of the way this is computed each process gets all the values,
247:     if each process wants only some of the values it should extract the ones it wants from the array.

249: .seealso: MatGetColumns()

251: @*/
252: PetscErrorCode MatGetColumnNorms(Mat A,NormType type,PetscReal *norms)
253: {
255:   PetscTruth     flg;

258:   PetscTypeCompare((PetscObject)A,MATSEQAIJ,&flg);
259:   if (flg) {
260:     MatGetColumnNorms_SeqAIJ(A,type,norms);
261:   } else {
262:     PetscTypeCompare((PetscObject)A,MATSEQDENSE,&flg);
263:     if (flg) {
264:       MatGetColumnNorms_SeqDense(A,type,norms);
265:     } else {
266:       PetscTypeCompare((PetscObject)A,MATMPIDENSE,&flg);
267:       if (flg) {
268:         MatGetColumnNorms_MPIDense(A,type,norms);
269:       } else {
270:         PetscTypeCompare((PetscObject)A,MATMPIAIJ,&flg);
271:         if (flg) {
272:           MatGetColumnNorms_MPIAIJ(A,type,norms);
273:         } else SETERRQ(PETSC_ERR_SUP,"Not coded for this matrix type");
274:       }
275:     }
276:   }
277:   return(0);
278: }
279: