Actual source code: normmh.c
petsc-3.7.7 2017-09-25
2: #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
4: typedef struct {
5: Mat A;
6: Vec w,left,right,leftwork,rightwork;
7: PetscScalar scale;
8: } Mat_Normal;
12: PetscErrorCode MatScaleHermitian_Normal(Mat inA,PetscScalar scale)
13: {
14: Mat_Normal *a = (Mat_Normal*)inA->data;
17: a->scale *= scale;
18: return(0);
19: }
23: PetscErrorCode MatDiagonalScaleHermitian_Normal(Mat inA,Vec left,Vec right)
24: {
25: Mat_Normal *a = (Mat_Normal*)inA->data;
29: if (left) {
30: if (!a->left) {
31: VecDuplicate(left,&a->left);
32: VecCopy(left,a->left);
33: } else {
34: VecPointwiseMult(a->left,left,a->left);
35: }
36: }
37: if (right) {
38: if (!a->right) {
39: VecDuplicate(right,&a->right);
40: VecCopy(right,a->right);
41: } else {
42: VecPointwiseMult(a->right,right,a->right);
43: }
44: }
45: return(0);
46: }
50: PetscErrorCode MatMultHermitian_Normal(Mat N,Vec x,Vec y)
51: {
52: Mat_Normal *Na = (Mat_Normal*)N->data;
54: Vec in;
57: in = x;
58: if (Na->right) {
59: if (!Na->rightwork) {
60: VecDuplicate(Na->right,&Na->rightwork);
61: }
62: VecPointwiseMult(Na->rightwork,Na->right,in);
63: in = Na->rightwork;
64: }
65: MatMult(Na->A,in,Na->w);
66: MatMultHermitianTranspose(Na->A,Na->w,y);
67: if (Na->left) {
68: VecPointwiseMult(y,Na->left,y);
69: }
70: VecScale(y,Na->scale);
71: return(0);
72: }
76: PetscErrorCode MatMultHermitianAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3)
77: {
78: Mat_Normal *Na = (Mat_Normal*)N->data;
80: Vec in;
83: in = v1;
84: if (Na->right) {
85: if (!Na->rightwork) {
86: VecDuplicate(Na->right,&Na->rightwork);
87: }
88: VecPointwiseMult(Na->rightwork,Na->right,in);
89: in = Na->rightwork;
90: }
91: MatMult(Na->A,in,Na->w);
92: VecScale(Na->w,Na->scale);
93: if (Na->left) {
94: MatMultHermitianTranspose(Na->A,Na->w,v3);
95: VecPointwiseMult(v3,Na->left,v3);
96: VecAXPY(v3,1.0,v2);
97: } else {
98: MatMultHermitianTransposeAdd(Na->A,Na->w,v2,v3);
99: }
100: return(0);
101: }
105: PetscErrorCode MatMultHermitianTranspose_Normal(Mat N,Vec x,Vec y)
106: {
107: Mat_Normal *Na = (Mat_Normal*)N->data;
109: Vec in;
112: in = x;
113: if (Na->left) {
114: if (!Na->leftwork) {
115: VecDuplicate(Na->left,&Na->leftwork);
116: }
117: VecPointwiseMult(Na->leftwork,Na->left,in);
118: in = Na->leftwork;
119: }
120: MatMult(Na->A,in,Na->w);
121: MatMultHermitianTranspose(Na->A,Na->w,y);
122: if (Na->right) {
123: VecPointwiseMult(y,Na->right,y);
124: }
125: VecScale(y,Na->scale);
126: return(0);
127: }
131: PetscErrorCode MatMultHermitianTransposeAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3)
132: {
133: Mat_Normal *Na = (Mat_Normal*)N->data;
135: Vec in;
138: in = v1;
139: if (Na->left) {
140: if (!Na->leftwork) {
141: VecDuplicate(Na->left,&Na->leftwork);
142: }
143: VecPointwiseMult(Na->leftwork,Na->left,in);
144: in = Na->leftwork;
145: }
146: MatMult(Na->A,in,Na->w);
147: VecScale(Na->w,Na->scale);
148: if (Na->right) {
149: MatMultHermitianTranspose(Na->A,Na->w,v3);
150: VecPointwiseMult(v3,Na->right,v3);
151: VecAXPY(v3,1.0,v2);
152: } else {
153: MatMultHermitianTransposeAdd(Na->A,Na->w,v2,v3);
154: }
155: return(0);
156: }
160: PetscErrorCode MatDestroyHermitian_Normal(Mat N)
161: {
162: Mat_Normal *Na = (Mat_Normal*)N->data;
166: MatDestroy(&Na->A);
167: VecDestroy(&Na->w);
168: VecDestroy(&Na->left);
169: VecDestroy(&Na->right);
170: VecDestroy(&Na->leftwork);
171: VecDestroy(&Na->rightwork);
172: PetscFree(N->data);
173: return(0);
174: }
176: /*
177: Slow, nonscalable version
178: */
181: PetscErrorCode MatGetDiagonalHermitian_Normal(Mat N,Vec v)
182: {
183: Mat_Normal *Na = (Mat_Normal*)N->data;
184: Mat A = Na->A;
185: PetscErrorCode ierr;
186: PetscInt i,j,rstart,rend,nnz;
187: const PetscInt *cols;
188: PetscScalar *diag,*work,*values;
189: const PetscScalar *mvalues;
192: PetscMalloc2(A->cmap->N,&diag,A->cmap->N,&work);
193: PetscMemzero(work,A->cmap->N*sizeof(PetscScalar));
194: MatGetOwnershipRange(A,&rstart,&rend);
195: for (i=rstart; i<rend; i++) {
196: MatGetRow(A,i,&nnz,&cols,&mvalues);
197: for (j=0; j<nnz; j++) {
198: work[cols[j]] += mvalues[j]*PetscConj(mvalues[j]);
199: }
200: MatRestoreRow(A,i,&nnz,&cols,&mvalues);
201: }
202: MPIU_Allreduce(work,diag,A->cmap->N,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)N));
203: rstart = N->cmap->rstart;
204: rend = N->cmap->rend;
205: VecGetArray(v,&values);
206: PetscMemcpy(values,diag+rstart,(rend-rstart)*sizeof(PetscScalar));
207: VecRestoreArray(v,&values);
208: PetscFree2(diag,work);
209: VecScale(v,Na->scale);
210: return(0);
211: }
215: /*@
216: MatCreateNormalHermitian - Creates a new matrix object that behaves like (A*)'*A.
218: Collective on Mat
220: Input Parameter:
221: . A - the (possibly rectangular complex) matrix
223: Output Parameter:
224: . N - the matrix that represents (A*)'*A
226: Level: intermediate
228: Notes: The product (A*)'*A is NOT actually formed! Rather the new matrix
229: object performs the matrix-vector product by first multiplying by
230: A and then (A*)'
231: @*/
232: PetscErrorCode MatCreateNormalHermitian(Mat A,Mat *N)
233: {
235: PetscInt m,n;
236: Mat_Normal *Na;
239: MatGetLocalSize(A,&m,&n);
240: MatCreate(PetscObjectComm((PetscObject)A),N);
241: MatSetSizes(*N,n,n,PETSC_DECIDE,PETSC_DECIDE);
242: PetscObjectChangeTypeName((PetscObject)*N,MATNORMALHERMITIAN);
244: PetscNewLog(*N,&Na);
245: (*N)->data = (void*) Na;
246: PetscObjectReference((PetscObject)A);
247: Na->A = A;
248: Na->scale = 1.0;
250: VecCreateMPI(PetscObjectComm((PetscObject)A),m,PETSC_DECIDE,&Na->w);
252: (*N)->ops->destroy = MatDestroyHermitian_Normal;
253: (*N)->ops->mult = MatMultHermitian_Normal;
254: (*N)->ops->multtranspose = MatMultHermitianTranspose_Normal;
255: (*N)->ops->multtransposeadd = MatMultHermitianTransposeAdd_Normal;
256: (*N)->ops->multadd = MatMultHermitianAdd_Normal;
257: (*N)->ops->getdiagonal = MatGetDiagonalHermitian_Normal;
258: (*N)->ops->scale = MatScaleHermitian_Normal;
259: (*N)->ops->diagonalscale = MatDiagonalScaleHermitian_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: }