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: