xref: /petsc/src/mat/impls/normal/normmh.c (revision b2566f29c2b6470df769aa9f7deb9e2726b0959e)
1ebda224cSfranklin5 
2ebda224cSfranklin5 #include <petsc/private/matimpl.h>          /*I "petscmat.h" I*/
3ebda224cSfranklin5 
4ebda224cSfranklin5 typedef struct {
5ebda224cSfranklin5   Mat         A;
6ebda224cSfranklin5   Vec         w,left,right,leftwork,rightwork;
7ebda224cSfranklin5   PetscScalar scale;
8ebda224cSfranklin5 } Mat_Normal;
9ebda224cSfranklin5 
10ebda224cSfranklin5 #undef __FUNCT__
11ebda224cSfranklin5 #define __FUNCT__ "MatScaleHermitian_Normal"
12ebda224cSfranklin5 PetscErrorCode MatScaleHermitian_Normal(Mat inA,PetscScalar scale)
13ebda224cSfranklin5 {
14ebda224cSfranklin5   Mat_Normal *a = (Mat_Normal*)inA->data;
15ebda224cSfranklin5 
16ebda224cSfranklin5   PetscFunctionBegin;
17ebda224cSfranklin5   a->scale *= scale;
18ebda224cSfranklin5   PetscFunctionReturn(0);
19ebda224cSfranklin5 }
20ebda224cSfranklin5 
21ebda224cSfranklin5 #undef __FUNCT__
22ebda224cSfranklin5 #define __FUNCT__ "MatDiagonalScaleHermitian_Normal"
23ebda224cSfranklin5 PetscErrorCode MatDiagonalScaleHermitian_Normal(Mat inA,Vec left,Vec right)
24ebda224cSfranklin5 {
25ebda224cSfranklin5   Mat_Normal     *a = (Mat_Normal*)inA->data;
26ebda224cSfranklin5   PetscErrorCode ierr;
27ebda224cSfranklin5 
28ebda224cSfranklin5   PetscFunctionBegin;
29ebda224cSfranklin5   if (left) {
30ebda224cSfranklin5     if (!a->left) {
31ebda224cSfranklin5       ierr = VecDuplicate(left,&a->left);CHKERRQ(ierr);
32ebda224cSfranklin5       ierr = VecCopy(left,a->left);CHKERRQ(ierr);
33ebda224cSfranklin5     } else {
34ebda224cSfranklin5       ierr = VecPointwiseMult(a->left,left,a->left);CHKERRQ(ierr);
35ebda224cSfranklin5     }
36ebda224cSfranklin5   }
37ebda224cSfranklin5   if (right) {
38ebda224cSfranklin5     if (!a->right) {
39ebda224cSfranklin5       ierr = VecDuplicate(right,&a->right);CHKERRQ(ierr);
40ebda224cSfranklin5       ierr = VecCopy(right,a->right);CHKERRQ(ierr);
41ebda224cSfranklin5     } else {
42ebda224cSfranklin5       ierr = VecPointwiseMult(a->right,right,a->right);CHKERRQ(ierr);
43ebda224cSfranklin5     }
44ebda224cSfranklin5   }
45ebda224cSfranklin5   PetscFunctionReturn(0);
46ebda224cSfranklin5 }
47ebda224cSfranklin5 
48ebda224cSfranklin5 #undef __FUNCT__
49ebda224cSfranklin5 #define __FUNCT__ "MatMultHermitian_Normal"
50ebda224cSfranklin5 PetscErrorCode MatMultHermitian_Normal(Mat N,Vec x,Vec y)
51ebda224cSfranklin5 {
52ebda224cSfranklin5   Mat_Normal     *Na = (Mat_Normal*)N->data;
53ebda224cSfranklin5   PetscErrorCode ierr;
54ebda224cSfranklin5   Vec            in;
55ebda224cSfranklin5 
56ebda224cSfranklin5   PetscFunctionBegin;
57ebda224cSfranklin5   in = x;
58ebda224cSfranklin5   if (Na->right) {
59ebda224cSfranklin5     if (!Na->rightwork) {
60ebda224cSfranklin5       ierr = VecDuplicate(Na->right,&Na->rightwork);CHKERRQ(ierr);
61ebda224cSfranklin5     }
62ebda224cSfranklin5     ierr = VecPointwiseMult(Na->rightwork,Na->right,in);CHKERRQ(ierr);
63ebda224cSfranklin5     in   = Na->rightwork;
64ebda224cSfranklin5   }
65ebda224cSfranklin5   ierr = MatMult(Na->A,in,Na->w);CHKERRQ(ierr);
66ebda224cSfranklin5   ierr = MatMultHermitianTranspose(Na->A,Na->w,y);CHKERRQ(ierr);
67ebda224cSfranklin5   if (Na->left) {
68ebda224cSfranklin5     ierr = VecPointwiseMult(y,Na->left,y);CHKERRQ(ierr);
69ebda224cSfranklin5   }
70ebda224cSfranklin5   ierr = VecScale(y,Na->scale);CHKERRQ(ierr);
71ebda224cSfranklin5   PetscFunctionReturn(0);
72ebda224cSfranklin5 }
73ebda224cSfranklin5 
74ebda224cSfranklin5 #undef __FUNCT__
75ebda224cSfranklin5 #define __FUNCT__ "MatMultHermitianAdd_Normal"
76ebda224cSfranklin5 PetscErrorCode MatMultHermitianAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3)
77ebda224cSfranklin5 {
78ebda224cSfranklin5   Mat_Normal     *Na = (Mat_Normal*)N->data;
79ebda224cSfranklin5   PetscErrorCode ierr;
80ebda224cSfranklin5   Vec            in;
81ebda224cSfranklin5 
82ebda224cSfranklin5   PetscFunctionBegin;
83ebda224cSfranklin5   in = v1;
84ebda224cSfranklin5   if (Na->right) {
85ebda224cSfranklin5     if (!Na->rightwork) {
86ebda224cSfranklin5       ierr = VecDuplicate(Na->right,&Na->rightwork);CHKERRQ(ierr);
87ebda224cSfranklin5     }
88ebda224cSfranklin5     ierr = VecPointwiseMult(Na->rightwork,Na->right,in);CHKERRQ(ierr);
89ebda224cSfranklin5     in   = Na->rightwork;
90ebda224cSfranklin5   }
91ebda224cSfranklin5   ierr = MatMult(Na->A,in,Na->w);CHKERRQ(ierr);
92ebda224cSfranklin5   ierr = VecScale(Na->w,Na->scale);CHKERRQ(ierr);
93ebda224cSfranklin5   if (Na->left) {
94ebda224cSfranklin5     ierr = MatMultHermitianTranspose(Na->A,Na->w,v3);CHKERRQ(ierr);
95ebda224cSfranklin5     ierr = VecPointwiseMult(v3,Na->left,v3);CHKERRQ(ierr);
96ebda224cSfranklin5     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
97ebda224cSfranklin5   } else {
98ebda224cSfranklin5     ierr = MatMultHermitianTransposeAdd(Na->A,Na->w,v2,v3);CHKERRQ(ierr);
99ebda224cSfranklin5   }
100ebda224cSfranklin5   PetscFunctionReturn(0);
101ebda224cSfranklin5 }
102ebda224cSfranklin5 
103ebda224cSfranklin5 #undef __FUNCT__
104ebda224cSfranklin5 #define __FUNCT__ "MatMultHermitianTranspose_Normal"
105ebda224cSfranklin5 PetscErrorCode MatMultHermitianTranspose_Normal(Mat N,Vec x,Vec y)
106ebda224cSfranklin5 {
107ebda224cSfranklin5   Mat_Normal     *Na = (Mat_Normal*)N->data;
108ebda224cSfranklin5   PetscErrorCode ierr;
109ebda224cSfranklin5   Vec            in;
110ebda224cSfranklin5 
111ebda224cSfranklin5   PetscFunctionBegin;
112ebda224cSfranklin5   in = x;
113ebda224cSfranklin5   if (Na->left) {
114ebda224cSfranklin5     if (!Na->leftwork) {
115ebda224cSfranklin5       ierr = VecDuplicate(Na->left,&Na->leftwork);CHKERRQ(ierr);
116ebda224cSfranklin5     }
117ebda224cSfranklin5     ierr = VecPointwiseMult(Na->leftwork,Na->left,in);CHKERRQ(ierr);
118ebda224cSfranklin5     in   = Na->leftwork;
119ebda224cSfranklin5   }
120ebda224cSfranklin5   ierr = MatMult(Na->A,in,Na->w);CHKERRQ(ierr);
121ebda224cSfranklin5   ierr = MatMultHermitianTranspose(Na->A,Na->w,y);CHKERRQ(ierr);
122ebda224cSfranklin5   if (Na->right) {
123ebda224cSfranklin5     ierr = VecPointwiseMult(y,Na->right,y);CHKERRQ(ierr);
124ebda224cSfranklin5   }
125ebda224cSfranklin5   ierr = VecScale(y,Na->scale);CHKERRQ(ierr);
126ebda224cSfranklin5   PetscFunctionReturn(0);
127ebda224cSfranklin5 }
128ebda224cSfranklin5 
129ebda224cSfranklin5 #undef __FUNCT__
130ebda224cSfranklin5 #define __FUNCT__ "MatMultHermitianTransposeAdd_Normal"
131ebda224cSfranklin5 PetscErrorCode MatMultHermitianTransposeAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3)
132ebda224cSfranklin5 {
133ebda224cSfranklin5   Mat_Normal     *Na = (Mat_Normal*)N->data;
134ebda224cSfranklin5   PetscErrorCode ierr;
135ebda224cSfranklin5   Vec            in;
136ebda224cSfranklin5 
137ebda224cSfranklin5   PetscFunctionBegin;
138ebda224cSfranklin5   in = v1;
139ebda224cSfranklin5   if (Na->left) {
140ebda224cSfranklin5     if (!Na->leftwork) {
141ebda224cSfranklin5       ierr = VecDuplicate(Na->left,&Na->leftwork);CHKERRQ(ierr);
142ebda224cSfranklin5     }
143ebda224cSfranklin5     ierr = VecPointwiseMult(Na->leftwork,Na->left,in);CHKERRQ(ierr);
144ebda224cSfranklin5     in   = Na->leftwork;
145ebda224cSfranklin5   }
146ebda224cSfranklin5   ierr = MatMult(Na->A,in,Na->w);CHKERRQ(ierr);
147ebda224cSfranklin5   ierr = VecScale(Na->w,Na->scale);CHKERRQ(ierr);
148ebda224cSfranklin5   if (Na->right) {
149ebda224cSfranklin5     ierr = MatMultHermitianTranspose(Na->A,Na->w,v3);CHKERRQ(ierr);
150ebda224cSfranklin5     ierr = VecPointwiseMult(v3,Na->right,v3);CHKERRQ(ierr);
151ebda224cSfranklin5     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
152ebda224cSfranklin5   } else {
153ebda224cSfranklin5     ierr = MatMultHermitianTransposeAdd(Na->A,Na->w,v2,v3);CHKERRQ(ierr);
154ebda224cSfranklin5   }
155ebda224cSfranklin5   PetscFunctionReturn(0);
156ebda224cSfranklin5 }
157ebda224cSfranklin5 
158ebda224cSfranklin5 #undef __FUNCT__
159ebda224cSfranklin5 #define __FUNCT__ "MatDestroyHermitian_Normal"
160ebda224cSfranklin5 PetscErrorCode MatDestroyHermitian_Normal(Mat N)
161ebda224cSfranklin5 {
162ebda224cSfranklin5   Mat_Normal     *Na = (Mat_Normal*)N->data;
163ebda224cSfranklin5   PetscErrorCode ierr;
164ebda224cSfranklin5 
165ebda224cSfranklin5   PetscFunctionBegin;
166ebda224cSfranklin5   ierr = MatDestroy(&Na->A);CHKERRQ(ierr);
167ebda224cSfranklin5   ierr = VecDestroy(&Na->w);CHKERRQ(ierr);
168ebda224cSfranklin5   ierr = VecDestroy(&Na->left);CHKERRQ(ierr);
169ebda224cSfranklin5   ierr = VecDestroy(&Na->right);CHKERRQ(ierr);
170ebda224cSfranklin5   ierr = VecDestroy(&Na->leftwork);CHKERRQ(ierr);
171ebda224cSfranklin5   ierr = VecDestroy(&Na->rightwork);CHKERRQ(ierr);
172ebda224cSfranklin5   ierr = PetscFree(N->data);CHKERRQ(ierr);
173ebda224cSfranklin5   PetscFunctionReturn(0);
174ebda224cSfranklin5 }
175ebda224cSfranklin5 
176ebda224cSfranklin5 /*
177ebda224cSfranklin5       Slow, nonscalable version
178ebda224cSfranklin5 */
179ebda224cSfranklin5 #undef __FUNCT__
180ebda224cSfranklin5 #define __FUNCT__ "MatGetDiagonalHermitian_Normal"
181ebda224cSfranklin5 PetscErrorCode MatGetDiagonalHermitian_Normal(Mat N,Vec v)
182ebda224cSfranklin5 {
183ebda224cSfranklin5   Mat_Normal        *Na = (Mat_Normal*)N->data;
184ebda224cSfranklin5   Mat               A   = Na->A;
185ebda224cSfranklin5   PetscErrorCode    ierr;
186ebda224cSfranklin5   PetscInt          i,j,rstart,rend,nnz;
187ebda224cSfranklin5   const PetscInt    *cols;
188ebda224cSfranklin5   PetscScalar       *diag,*work,*values;
189ebda224cSfranklin5   const PetscScalar *mvalues;
190ebda224cSfranklin5 
191ebda224cSfranklin5   PetscFunctionBegin;
192ebda224cSfranklin5   ierr = PetscMalloc2(A->cmap->N,&diag,A->cmap->N,&work);CHKERRQ(ierr);
193ebda224cSfranklin5   ierr = PetscMemzero(work,A->cmap->N*sizeof(PetscScalar));CHKERRQ(ierr);
194ebda224cSfranklin5   ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr);
195ebda224cSfranklin5   for (i=rstart; i<rend; i++) {
196ebda224cSfranklin5     ierr = MatGetRow(A,i,&nnz,&cols,&mvalues);CHKERRQ(ierr);
197ebda224cSfranklin5     for (j=0; j<nnz; j++) {
198a8f6171dSBarry Smith       work[cols[j]] += mvalues[j]*PetscConj(mvalues[j]);
199ebda224cSfranklin5     }
200ebda224cSfranklin5     ierr = MatRestoreRow(A,i,&nnz,&cols,&mvalues);CHKERRQ(ierr);
201ebda224cSfranklin5   }
202*b2566f29SBarry Smith   ierr   = MPIU_Allreduce(work,diag,A->cmap->N,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)N));CHKERRQ(ierr);
203ebda224cSfranklin5   rstart = N->cmap->rstart;
204ebda224cSfranklin5   rend   = N->cmap->rend;
205ebda224cSfranklin5   ierr   = VecGetArray(v,&values);CHKERRQ(ierr);
206ebda224cSfranklin5   ierr   = PetscMemcpy(values,diag+rstart,(rend-rstart)*sizeof(PetscScalar));CHKERRQ(ierr);
207ebda224cSfranklin5   ierr   = VecRestoreArray(v,&values);CHKERRQ(ierr);
208ebda224cSfranklin5   ierr   = PetscFree2(diag,work);CHKERRQ(ierr);
209ebda224cSfranklin5   ierr   = VecScale(v,Na->scale);CHKERRQ(ierr);
210ebda224cSfranklin5   PetscFunctionReturn(0);
211ebda224cSfranklin5 }
212ebda224cSfranklin5 
213ebda224cSfranklin5 #undef __FUNCT__
214ebda224cSfranklin5 #define __FUNCT__ "MatCreateNormalHermitian"
215ebda224cSfranklin5 /*@
216ebda224cSfranklin5       MatCreateNormalHermitian - Creates a new matrix object that behaves like (A*)'*A.
217ebda224cSfranklin5 
218ebda224cSfranklin5    Collective on Mat
219ebda224cSfranklin5 
220ebda224cSfranklin5    Input Parameter:
221ebda224cSfranklin5 .   A  - the (possibly rectangular complex) matrix
222ebda224cSfranklin5 
223ebda224cSfranklin5    Output Parameter:
224ebda224cSfranklin5 .   N - the matrix that represents (A*)'*A
225ebda224cSfranklin5 
226ebda224cSfranklin5    Level: intermediate
227ebda224cSfranklin5 
228ebda224cSfranklin5    Notes: The product (A*)'*A is NOT actually formed! Rather the new matrix
229ebda224cSfranklin5           object performs the matrix-vector product by first multiplying by
230ebda224cSfranklin5           A and then (A*)'
231ebda224cSfranklin5 @*/
232ebda224cSfranklin5 PetscErrorCode  MatCreateNormalHermitian(Mat A,Mat *N)
233ebda224cSfranklin5 {
234ebda224cSfranklin5   PetscErrorCode ierr;
235ebda224cSfranklin5   PetscInt       m,n;
236ebda224cSfranklin5   Mat_Normal     *Na;
237ebda224cSfranklin5 
238ebda224cSfranklin5   PetscFunctionBegin;
239ebda224cSfranklin5   ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr);
240ebda224cSfranklin5   ierr = MatCreate(PetscObjectComm((PetscObject)A),N);CHKERRQ(ierr);
241ebda224cSfranklin5   ierr = MatSetSizes(*N,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
242ebda224cSfranklin5   ierr = PetscObjectChangeTypeName((PetscObject)*N,MATNORMALHERMITIAN);CHKERRQ(ierr);
243ebda224cSfranklin5 
244ebda224cSfranklin5   ierr       = PetscNewLog(*N,&Na);CHKERRQ(ierr);
245ebda224cSfranklin5   (*N)->data = (void*) Na;
246ebda224cSfranklin5   ierr       = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
247ebda224cSfranklin5   Na->A      = A;
248ebda224cSfranklin5   Na->scale  = 1.0;
249ebda224cSfranklin5 
250ebda224cSfranklin5   ierr = VecCreateMPI(PetscObjectComm((PetscObject)A),m,PETSC_DECIDE,&Na->w);CHKERRQ(ierr);
251ebda224cSfranklin5 
252ebda224cSfranklin5   (*N)->ops->destroy          = MatDestroyHermitian_Normal;
253ebda224cSfranklin5   (*N)->ops->mult             = MatMultHermitian_Normal;
254ebda224cSfranklin5   (*N)->ops->multtranspose    = MatMultHermitianTranspose_Normal;
255ebda224cSfranklin5   (*N)->ops->multtransposeadd = MatMultHermitianTransposeAdd_Normal;
256ebda224cSfranklin5   (*N)->ops->multadd          = MatMultHermitianAdd_Normal;
257ebda224cSfranklin5   (*N)->ops->getdiagonal      = MatGetDiagonalHermitian_Normal;
258ebda224cSfranklin5   (*N)->ops->scale            = MatScaleHermitian_Normal;
259ebda224cSfranklin5   (*N)->ops->diagonalscale    = MatDiagonalScaleHermitian_Normal;
260ebda224cSfranklin5   (*N)->assembled             = PETSC_TRUE;
261ebda224cSfranklin5   (*N)->cmap->N               = A->cmap->N;
262ebda224cSfranklin5   (*N)->rmap->N               = A->cmap->N;
263ebda224cSfranklin5   (*N)->cmap->n               = A->cmap->n;
264ebda224cSfranklin5   (*N)->rmap->n               = A->cmap->n;
265ebda224cSfranklin5   PetscFunctionReturn(0);
266ebda224cSfranklin5 }
267ebda224cSfranklin5 
268