Actual source code: normm.c
1: #define PETSCMAT_DLL
3: #include private/matimpl.h
5: typedef struct {
6: Mat A;
7: Vec w,left,right,leftwork,rightwork;
8: PetscScalar scale;
9: } Mat_Normal;
13: PetscErrorCode MatScale_Normal(Mat inA,PetscScalar scale)
14: {
15: Mat_Normal *a = (Mat_Normal*)inA->data;
18: a->scale *= scale;
19: return(0);
20: }
24: PetscErrorCode MatDiagonalScale_Normal(Mat inA,Vec left,Vec right)
25: {
26: Mat_Normal *a = (Mat_Normal*)inA->data;
30: if (left) {
31: if (!a->left) {
32: VecDuplicate(left,&a->left);
33: VecCopy(left,a->left);
34: } else {
35: VecPointwiseMult(a->left,left,a->left);
36: }
37: }
38: if (right) {
39: if (!a->right) {
40: VecDuplicate(right,&a->right);
41: VecCopy(right,a->right);
42: } else {
43: VecPointwiseMult(a->right,right,a->right);
44: }
45: }
46: return(0);
47: }
51: PetscErrorCode MatMult_Normal(Mat N,Vec x,Vec y)
52: {
53: Mat_Normal *Na = (Mat_Normal*)N->data;
55: Vec in;
58: in = x;
59: if (Na->right) {
60: if (!Na->rightwork) {
61: VecDuplicate(Na->right,&Na->rightwork);
62: }
63: VecPointwiseMult(Na->rightwork,Na->right,in);
64: in = Na->rightwork;
65: }
66: MatMult(Na->A,in,Na->w);
67: MatMultTranspose(Na->A,Na->w,y);
68: if (Na->left) {
69: VecPointwiseMult(y,Na->left,y);
70: }
71: VecScale(y,Na->scale);
72: return(0);
73: }
74:
77: PetscErrorCode MatMultAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3)
78: {
79: Mat_Normal *Na = (Mat_Normal*)N->data;
81: Vec in;
84: in = v1;
85: if (Na->right) {
86: if (!Na->rightwork) {
87: VecDuplicate(Na->right,&Na->rightwork);
88: }
89: VecPointwiseMult(Na->rightwork,Na->right,in);
90: in = Na->rightwork;
91: }
92: MatMult(Na->A,in,Na->w);
93: VecScale(Na->w,Na->scale);
94: if (Na->left) {
95: MatMultTranspose(Na->A,Na->w,v3);
96: VecPointwiseMult(v3,Na->left,v3);
97: VecAXPY(v3,1.0,v2);
98: } else {
99: MatMultTransposeAdd(Na->A,Na->w,v2,v3);
100: }
101: return(0);
102: }
106: PetscErrorCode MatMultTranspose_Normal(Mat N,Vec x,Vec y)
107: {
108: Mat_Normal *Na = (Mat_Normal*)N->data;
110: Vec in;
113: in = x;
114: if (Na->left) {
115: if (!Na->leftwork) {
116: VecDuplicate(Na->left,&Na->leftwork);
117: }
118: VecPointwiseMult(Na->leftwork,Na->left,in);
119: in = Na->leftwork;
120: }
121: MatMult(Na->A,in,Na->w);
122: MatMultTranspose(Na->A,Na->w,y);
123: if (Na->right) {
124: VecPointwiseMult(y,Na->right,y);
125: }
126: VecScale(y,Na->scale);
127: return(0);
128: }
132: PetscErrorCode MatMultTransposeAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3)
133: {
134: Mat_Normal *Na = (Mat_Normal*)N->data;
136: Vec in;
139: in = v1;
140: if (Na->left) {
141: if (!Na->leftwork) {
142: VecDuplicate(Na->left,&Na->leftwork);
143: }
144: VecPointwiseMult(Na->leftwork,Na->left,in);
145: in = Na->leftwork;
146: }
147: MatMult(Na->A,in,Na->w);
148: VecScale(Na->w,Na->scale);
149: if (Na->right) {
150: MatMultTranspose(Na->A,Na->w,v3);
151: VecPointwiseMult(v3,Na->right,v3);
152: VecAXPY(v3,1.0,v2);
153: } else {
154: MatMultTransposeAdd(Na->A,Na->w,v2,v3);
155: }
156: return(0);
157: }
161: PetscErrorCode MatDestroy_Normal(Mat N)
162: {
163: Mat_Normal *Na = (Mat_Normal*)N->data;
167: if (Na->A) { MatDestroy(Na->A); }
168: if (Na->w) { VecDestroy(Na->w); }
169: if (Na->left) { VecDestroy(Na->left); }
170: if (Na->right) { VecDestroy(Na->right); }
171: if (Na->leftwork) { VecDestroy(Na->leftwork); }
172: if (Na->rightwork) { VecDestroy(Na->rightwork); }
173: PetscFree(Na);
174: return(0);
175: }
176:
177: /*
178: Slow, nonscalable version
179: */
182: PetscErrorCode MatGetDiagonal_Normal(Mat N,Vec v)
183: {
184: Mat_Normal *Na = (Mat_Normal*)N->data;
185: Mat A = Na->A;
186: PetscErrorCode ierr;
187: PetscInt i,j,rstart,rend,nnz;
188: const PetscInt *cols;
189: PetscScalar *diag,*work,*values;
190: const PetscScalar *mvalues;
193: PetscMalloc2(A->cmap->N,PetscScalar,&diag,A->cmap->N,PetscScalar,&work);
194: PetscMemzero(work,A->cmap->N*sizeof(PetscScalar));
195: MatGetOwnershipRange(A,&rstart,&rend);
196: for (i=rstart; i<rend; i++) {
197: MatGetRow(A,i,&nnz,&cols,&mvalues);
198: for (j=0; j<nnz; j++) {
199: work[cols[j]] += mvalues[j]*mvalues[j];
200: }
201: MatRestoreRow(A,i,&nnz,&cols,&mvalues);
202: }
203: MPI_Allreduce(work,diag,A->cmap->N,MPIU_SCALAR,MPI_SUM,((PetscObject)N)->comm);
204: rstart = N->cmap->rstart;
205: rend = N->cmap->rend;
206: VecGetArray(v,&values);
207: PetscMemcpy(values,diag+rstart,(rend-rstart)*sizeof(PetscScalar));
208: VecRestoreArray(v,&values);
209: PetscFree2(diag,work);
210: VecScale(v,Na->scale);
211: return(0);
212: }
216: /*@
217: MatCreateNormal - Creates a new matrix object that behaves like A'*A.
219: Collective on Mat
221: Input Parameter:
222: . A - the (possibly rectangular) matrix
224: Output Parameter:
225: . N - the matrix that represents A'*A
227: Level: intermediate
229: Notes: The product A'*A is NOT actually formed! Rather the new matrix
230: object performs the matrix-vector product by first multiplying by
231: A and then A'
232: @*/
233: PetscErrorCode MatCreateNormal(Mat A,Mat *N)
234: {
236: PetscInt m,n;
237: Mat_Normal *Na;
240: MatGetLocalSize(A,&m,&n);
241: MatCreate(((PetscObject)A)->comm,N);
242: MatSetSizes(*N,n,n,PETSC_DECIDE,PETSC_DECIDE);
243: PetscObjectChangeTypeName((PetscObject)*N,MATNORMAL);
244:
245: PetscNewLog(*N,Mat_Normal,&Na);
246: (*N)->data = (void*) Na;
247: PetscObjectReference((PetscObject)A);
248: Na->A = A;
249: Na->scale = 1.0;
251: VecCreateMPI(((PetscObject)A)->comm,m,PETSC_DECIDE,&Na->w);
252: (*N)->ops->destroy = MatDestroy_Normal;
253: (*N)->ops->mult = MatMult_Normal;
254: (*N)->ops->multtranspose = MatMultTranspose_Normal;
255: (*N)->ops->multtransposeadd = MatMultTransposeAdd_Normal;
256: (*N)->ops->multadd = MatMultAdd_Normal;
257: (*N)->ops->getdiagonal = MatGetDiagonal_Normal;
258: (*N)->ops->scale = MatScale_Normal;
259: (*N)->ops->diagonalscale = MatDiagonalScale_Normal;
260: (*N)->assembled = PETSC_TRUE;
261: (*N)->cmap->N = A->cmap->N;
262: (*N)->rmap->N = A->cmap->N;
263: (*N)->cmap->n = A->cmap->n;
264: (*N)->rmap->n = A->cmap->n;
265: return(0);
266: }