xref: /petsc/src/mat/impls/normal/normm.c (revision 1baa6e3354bfe224b33a0c158f482508792a8a6e)
1c8a8475eSBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/matimpl.h>          /*I "petscmat.h" I*/
3c8a8475eSBarry Smith 
4c8a8475eSBarry Smith typedef struct {
57cfd0b8cSBarry Smith   Mat         A;
6a48507d3SJose E. Roman   Mat         D; /* local submatrix for diagonal part */
77cfd0b8cSBarry Smith   Vec         w,left,right,leftwork,rightwork;
8b20f02adSBarry Smith   PetscScalar scale;
9c8a8475eSBarry Smith } Mat_Normal;
10c8a8475eSBarry Smith 
1169ef1043SBarry Smith PetscErrorCode MatScale_Normal(Mat inA,PetscScalar scale)
1269ef1043SBarry Smith {
1369ef1043SBarry Smith   Mat_Normal *a = (Mat_Normal*)inA->data;
1469ef1043SBarry Smith 
1569ef1043SBarry Smith   PetscFunctionBegin;
1669ef1043SBarry Smith   a->scale *= scale;
1769ef1043SBarry Smith   PetscFunctionReturn(0);
1869ef1043SBarry Smith }
1969ef1043SBarry Smith 
207cfd0b8cSBarry Smith PetscErrorCode MatDiagonalScale_Normal(Mat inA,Vec left,Vec right)
217cfd0b8cSBarry Smith {
227cfd0b8cSBarry Smith   Mat_Normal     *a = (Mat_Normal*)inA->data;
237cfd0b8cSBarry Smith 
247cfd0b8cSBarry Smith   PetscFunctionBegin;
257cfd0b8cSBarry Smith   if (left) {
267cfd0b8cSBarry Smith     if (!a->left) {
279566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(left,&a->left));
289566063dSJacob Faibussowitsch       PetscCall(VecCopy(left,a->left));
297cfd0b8cSBarry Smith     } else {
309566063dSJacob Faibussowitsch       PetscCall(VecPointwiseMult(a->left,left,a->left));
317cfd0b8cSBarry Smith     }
327cfd0b8cSBarry Smith   }
337cfd0b8cSBarry Smith   if (right) {
347cfd0b8cSBarry Smith     if (!a->right) {
359566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(right,&a->right));
369566063dSJacob Faibussowitsch       PetscCall(VecCopy(right,a->right));
377cfd0b8cSBarry Smith     } else {
389566063dSJacob Faibussowitsch       PetscCall(VecPointwiseMult(a->right,right,a->right));
397cfd0b8cSBarry Smith     }
407cfd0b8cSBarry Smith   }
417cfd0b8cSBarry Smith   PetscFunctionReturn(0);
427cfd0b8cSBarry Smith }
437cfd0b8cSBarry Smith 
44fa80d070SPierre Jolivet PetscErrorCode MatIncreaseOverlap_Normal(Mat A,PetscInt is_max,IS is[],PetscInt ov)
45fa80d070SPierre Jolivet {
46fa80d070SPierre Jolivet   Mat_Normal     *a = (Mat_Normal*)A->data;
47fa80d070SPierre Jolivet   Mat            pattern;
48fa80d070SPierre Jolivet 
49fa80d070SPierre Jolivet   PetscFunctionBegin;
5008401ef6SPierre Jolivet   PetscCheck(ov >= 0,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Negative overlap specified");
519566063dSJacob Faibussowitsch   PetscCall(MatProductCreate(a->A,a->A,NULL,&pattern));
529566063dSJacob Faibussowitsch   PetscCall(MatProductSetType(pattern,MATPRODUCT_AtB));
539566063dSJacob Faibussowitsch   PetscCall(MatProductSetFromOptions(pattern));
549566063dSJacob Faibussowitsch   PetscCall(MatProductSymbolic(pattern));
559566063dSJacob Faibussowitsch   PetscCall(MatIncreaseOverlap(pattern,is_max,is,ov));
569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pattern));
57fa80d070SPierre Jolivet   PetscFunctionReturn(0);
58fa80d070SPierre Jolivet }
59fa80d070SPierre Jolivet 
60fa80d070SPierre Jolivet PetscErrorCode MatCreateSubMatrices_Normal(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
61fa80d070SPierre Jolivet {
62fa80d070SPierre Jolivet   Mat_Normal     *a = (Mat_Normal*)mat->data;
63fa80d070SPierre Jolivet   Mat            B = a->A, *suba;
64fa80d070SPierre Jolivet   IS             *row;
65fa80d070SPierre Jolivet   PetscInt       M;
66fa80d070SPierre Jolivet 
67fa80d070SPierre Jolivet   PetscFunctionBegin;
68aed4548fSBarry Smith   PetscCheck(!a->left && !a->right && irow == icol,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not implemented");
69fa80d070SPierre Jolivet   if (scall != MAT_REUSE_MATRIX) {
709566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(n,submat));
71fa80d070SPierre Jolivet   }
729566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B,&M,NULL));
739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n,&row));
749566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF,M,0,1,&row[0]));
759566063dSJacob Faibussowitsch   PetscCall(ISSetIdentity(row[0]));
76fa80d070SPierre Jolivet   for (M = 1; M < n; ++M) row[M] = row[0];
779566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrices(B,n,row,icol,MAT_INITIAL_MATRIX,&suba));
78fa80d070SPierre Jolivet   for (M = 0; M < n; ++M) {
799566063dSJacob Faibussowitsch     PetscCall(MatCreateNormal(suba[M],*submat+M));
80fa80d070SPierre Jolivet     ((Mat_Normal*)(*submat)[M]->data)->scale = a->scale;
81fa80d070SPierre Jolivet   }
829566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&row[0]));
839566063dSJacob Faibussowitsch   PetscCall(PetscFree(row));
849566063dSJacob Faibussowitsch   PetscCall(MatDestroySubMatrices(n,&suba));
85fa80d070SPierre Jolivet   PetscFunctionReturn(0);
86fa80d070SPierre Jolivet }
87fa80d070SPierre Jolivet 
88fa80d070SPierre Jolivet PetscErrorCode MatPermute_Normal(Mat A,IS rowp,IS colp,Mat *B)
89fa80d070SPierre Jolivet {
90fa80d070SPierre Jolivet   Mat_Normal     *a = (Mat_Normal*)A->data;
91fa80d070SPierre Jolivet   Mat            C,Aa = a->A;
92fa80d070SPierre Jolivet   IS             row;
93fa80d070SPierre Jolivet 
94fa80d070SPierre Jolivet   PetscFunctionBegin;
9508401ef6SPierre Jolivet   PetscCheck(rowp == colp,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Row permutation and column permutation must be the same");
969566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PetscObjectComm((PetscObject)Aa),Aa->rmap->n,Aa->rmap->rstart,1,&row));
979566063dSJacob Faibussowitsch   PetscCall(ISSetIdentity(row));
989566063dSJacob Faibussowitsch   PetscCall(MatPermute(Aa,row,colp,&C));
999566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&row));
1009566063dSJacob Faibussowitsch   PetscCall(MatCreateNormal(C,B));
1019566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
102fa80d070SPierre Jolivet   PetscFunctionReturn(0);
103fa80d070SPierre Jolivet }
104fa80d070SPierre Jolivet 
105fa80d070SPierre Jolivet PetscErrorCode MatDuplicate_Normal(Mat A, MatDuplicateOption op, Mat *B)
106fa80d070SPierre Jolivet {
107fa80d070SPierre Jolivet   Mat_Normal     *a = (Mat_Normal*)A->data;
108fa80d070SPierre Jolivet   Mat            C;
109fa80d070SPierre Jolivet 
110fa80d070SPierre Jolivet   PetscFunctionBegin;
11108401ef6SPierre Jolivet   PetscCheck(!a->left && !a->right,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Not implemented");
1129566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(a->A,op,&C));
1139566063dSJacob Faibussowitsch   PetscCall(MatCreateNormal(C,B));
1149566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&C));
115fa80d070SPierre Jolivet   if (op == MAT_COPY_VALUES) ((Mat_Normal*)(*B)->data)->scale = a->scale;
116fa80d070SPierre Jolivet   PetscFunctionReturn(0);
117fa80d070SPierre Jolivet }
118fa80d070SPierre Jolivet 
119fa80d070SPierre Jolivet PetscErrorCode MatCopy_Normal(Mat A,Mat B,MatStructure str)
120fa80d070SPierre Jolivet {
121fa80d070SPierre Jolivet   Mat_Normal     *a = (Mat_Normal*)A->data,*b = (Mat_Normal*)B->data;
122fa80d070SPierre Jolivet 
123fa80d070SPierre Jolivet   PetscFunctionBegin;
12408401ef6SPierre Jolivet   PetscCheck(!a->left && !a->right,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Not implemented");
1259566063dSJacob Faibussowitsch   PetscCall(MatCopy(a->A,b->A,str));
126fa80d070SPierre Jolivet   b->scale = a->scale;
1279566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->left));
1289566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->right));
1299566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->leftwork));
1309566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->rightwork));
131fa80d070SPierre Jolivet   PetscFunctionReturn(0);
132fa80d070SPierre Jolivet }
133fa80d070SPierre Jolivet 
134dfbe8321SBarry Smith PetscErrorCode MatMult_Normal(Mat N,Vec x,Vec y)
135c8a8475eSBarry Smith {
136c8a8475eSBarry Smith   Mat_Normal     *Na = (Mat_Normal*)N->data;
1377cfd0b8cSBarry Smith   Vec            in;
138c8a8475eSBarry Smith 
139c8a8475eSBarry Smith   PetscFunctionBegin;
1407cfd0b8cSBarry Smith   in = x;
1417cfd0b8cSBarry Smith   if (Na->right) {
1427cfd0b8cSBarry Smith     if (!Na->rightwork) {
1439566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(Na->right,&Na->rightwork));
1447cfd0b8cSBarry Smith     }
1459566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Na->rightwork,Na->right,in));
1467cfd0b8cSBarry Smith     in   = Na->rightwork;
1477cfd0b8cSBarry Smith   }
1489566063dSJacob Faibussowitsch   PetscCall(MatMult(Na->A,in,Na->w));
1499566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(Na->A,Na->w,y));
150*1baa6e33SBarry Smith   if (Na->left) PetscCall(VecPointwiseMult(y,Na->left,y));
1519566063dSJacob Faibussowitsch   PetscCall(VecScale(y,Na->scale));
152c8a8475eSBarry Smith   PetscFunctionReturn(0);
153c8a8475eSBarry Smith }
154c8a8475eSBarry Smith 
155db090513SMatthew Knepley PetscErrorCode MatMultAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3)
156db090513SMatthew Knepley {
157db090513SMatthew Knepley   Mat_Normal     *Na = (Mat_Normal*)N->data;
1587cfd0b8cSBarry Smith   Vec            in;
159db090513SMatthew Knepley 
160db090513SMatthew Knepley   PetscFunctionBegin;
1617cfd0b8cSBarry Smith   in = v1;
1627cfd0b8cSBarry Smith   if (Na->right) {
1637cfd0b8cSBarry Smith     if (!Na->rightwork) {
1649566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(Na->right,&Na->rightwork));
1657cfd0b8cSBarry Smith     }
1669566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Na->rightwork,Na->right,in));
1677cfd0b8cSBarry Smith     in   = Na->rightwork;
1687cfd0b8cSBarry Smith   }
1699566063dSJacob Faibussowitsch   PetscCall(MatMult(Na->A,in,Na->w));
1709566063dSJacob Faibussowitsch   PetscCall(VecScale(Na->w,Na->scale));
1717cfd0b8cSBarry Smith   if (Na->left) {
1729566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(Na->A,Na->w,v3));
1739566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(v3,Na->left,v3));
1749566063dSJacob Faibussowitsch     PetscCall(VecAXPY(v3,1.0,v2));
1757cfd0b8cSBarry Smith   } else {
1769566063dSJacob Faibussowitsch     PetscCall(MatMultTransposeAdd(Na->A,Na->w,v2,v3));
1777cfd0b8cSBarry Smith   }
178b20f02adSBarry Smith   PetscFunctionReturn(0);
179b20f02adSBarry Smith }
180b20f02adSBarry Smith 
181b20f02adSBarry Smith PetscErrorCode MatMultTranspose_Normal(Mat N,Vec x,Vec y)
182b20f02adSBarry Smith {
183b20f02adSBarry Smith   Mat_Normal     *Na = (Mat_Normal*)N->data;
1847cfd0b8cSBarry Smith   Vec            in;
185b20f02adSBarry Smith 
186b20f02adSBarry Smith   PetscFunctionBegin;
1877cfd0b8cSBarry Smith   in = x;
1887cfd0b8cSBarry Smith   if (Na->left) {
1897cfd0b8cSBarry Smith     if (!Na->leftwork) {
1909566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(Na->left,&Na->leftwork));
1917cfd0b8cSBarry Smith     }
1929566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Na->leftwork,Na->left,in));
1937cfd0b8cSBarry Smith     in   = Na->leftwork;
1947cfd0b8cSBarry Smith   }
1959566063dSJacob Faibussowitsch   PetscCall(MatMult(Na->A,in,Na->w));
1969566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(Na->A,Na->w,y));
197*1baa6e33SBarry Smith   if (Na->right) PetscCall(VecPointwiseMult(y,Na->right,y));
1989566063dSJacob Faibussowitsch   PetscCall(VecScale(y,Na->scale));
199b20f02adSBarry Smith   PetscFunctionReturn(0);
200b20f02adSBarry Smith }
201b20f02adSBarry Smith 
202b20f02adSBarry Smith PetscErrorCode MatMultTransposeAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3)
203b20f02adSBarry Smith {
204b20f02adSBarry Smith   Mat_Normal     *Na = (Mat_Normal*)N->data;
2057cfd0b8cSBarry Smith   Vec            in;
206b20f02adSBarry Smith 
207b20f02adSBarry Smith   PetscFunctionBegin;
2087cfd0b8cSBarry Smith   in = v1;
2097cfd0b8cSBarry Smith   if (Na->left) {
2107cfd0b8cSBarry Smith     if (!Na->leftwork) {
2119566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(Na->left,&Na->leftwork));
2127cfd0b8cSBarry Smith     }
2139566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Na->leftwork,Na->left,in));
2147cfd0b8cSBarry Smith     in   = Na->leftwork;
2157cfd0b8cSBarry Smith   }
2169566063dSJacob Faibussowitsch   PetscCall(MatMult(Na->A,in,Na->w));
2179566063dSJacob Faibussowitsch   PetscCall(VecScale(Na->w,Na->scale));
2187cfd0b8cSBarry Smith   if (Na->right) {
2199566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(Na->A,Na->w,v3));
2209566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(v3,Na->right,v3));
2219566063dSJacob Faibussowitsch     PetscCall(VecAXPY(v3,1.0,v2));
2227cfd0b8cSBarry Smith   } else {
2239566063dSJacob Faibussowitsch     PetscCall(MatMultTransposeAdd(Na->A,Na->w,v2,v3));
2247cfd0b8cSBarry Smith   }
225db090513SMatthew Knepley   PetscFunctionReturn(0);
226db090513SMatthew Knepley }
227db090513SMatthew Knepley 
228dfbe8321SBarry Smith PetscErrorCode MatDestroy_Normal(Mat N)
229c8a8475eSBarry Smith {
230c8a8475eSBarry Smith   Mat_Normal     *Na = (Mat_Normal*)N->data;
231c8a8475eSBarry Smith 
232c8a8475eSBarry Smith   PetscFunctionBegin;
2339566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Na->A));
234a48507d3SJose E. Roman   PetscCall(MatDestroy(&Na->D));
2359566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Na->w));
2369566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Na->left));
2379566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Na->right));
2389566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Na->leftwork));
2399566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Na->rightwork));
2409566063dSJacob Faibussowitsch   PetscCall(PetscFree(N->data));
2419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)N,"MatNormalGetMat_C",NULL));
2429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)N,"MatConvert_normal_seqaij_C",NULL));
2439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)N,"MatConvert_normal_mpiaij_C",NULL));
2449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)N,"MatProductSetFromOptions_normal_seqdense_C",NULL));
2459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)N,"MatProductSetFromOptions_normal_mpidense_C",NULL));
2469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)N,"MatProductSetFromOptions_normal_dense_C",NULL));
247c8a8475eSBarry Smith   PetscFunctionReturn(0);
248c8a8475eSBarry Smith }
249c8a8475eSBarry Smith 
25017a6fd94SBarry Smith /*
25117a6fd94SBarry Smith       Slow, nonscalable version
25217a6fd94SBarry Smith */
253dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_Normal(Mat N,Vec v)
25417a6fd94SBarry Smith {
25517a6fd94SBarry Smith   Mat_Normal        *Na = (Mat_Normal*)N->data;
25617a6fd94SBarry Smith   Mat               A   = Na->A;
257b24ad042SBarry Smith   PetscInt          i,j,rstart,rend,nnz;
258b24ad042SBarry Smith   const PetscInt    *cols;
25917a6fd94SBarry Smith   PetscScalar       *diag,*work,*values;
260b3cc6726SBarry Smith   const PetscScalar *mvalues;
26117a6fd94SBarry Smith 
26217a6fd94SBarry Smith   PetscFunctionBegin;
2639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(A->cmap->N,&diag,A->cmap->N,&work));
2649566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(work,A->cmap->N));
2659566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A,&rstart,&rend));
26617a6fd94SBarry Smith   for (i=rstart; i<rend; i++) {
2679566063dSJacob Faibussowitsch     PetscCall(MatGetRow(A,i,&nnz,&cols,&mvalues));
26817a6fd94SBarry Smith     for (j=0; j<nnz; j++) {
269b3cc6726SBarry Smith       work[cols[j]] += mvalues[j]*mvalues[j];
27017a6fd94SBarry Smith     }
2719566063dSJacob Faibussowitsch     PetscCall(MatRestoreRow(A,i,&nnz,&cols,&mvalues));
27217a6fd94SBarry Smith   }
2731c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(work,diag,A->cmap->N,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)N)));
274d0f46423SBarry Smith   rstart = N->cmap->rstart;
275d0f46423SBarry Smith   rend   = N->cmap->rend;
2769566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v,&values));
2779566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(values,diag+rstart,rend-rstart));
2789566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v,&values));
2799566063dSJacob Faibussowitsch   PetscCall(PetscFree2(diag,work));
2809566063dSJacob Faibussowitsch   PetscCall(VecScale(v,Na->scale));
28117a6fd94SBarry Smith   PetscFunctionReturn(0);
28217a6fd94SBarry Smith }
283c8a8475eSBarry Smith 
284a48507d3SJose E. Roman PetscErrorCode MatGetDiagonalBlock_Normal(Mat N,Mat *D)
285a48507d3SJose E. Roman {
286a48507d3SJose E. Roman   Mat_Normal *Na = (Mat_Normal*)N->data;
287a48507d3SJose E. Roman   Mat        M,A = Na->A;
288a48507d3SJose E. Roman 
289a48507d3SJose E. Roman   PetscFunctionBegin;
290a48507d3SJose E. Roman   PetscCall(MatGetDiagonalBlock(A,&M));
291a48507d3SJose E. Roman   PetscCall(MatCreateNormal(M,&Na->D));
292a48507d3SJose E. Roman   *D = Na->D;
293a48507d3SJose E. Roman   PetscFunctionReturn(0);
294a48507d3SJose E. Roman }
295a48507d3SJose E. Roman 
296fa80d070SPierre Jolivet PetscErrorCode MatNormalGetMat_Normal(Mat A,Mat *M)
297fa80d070SPierre Jolivet {
298fa80d070SPierre Jolivet   Mat_Normal *Aa = (Mat_Normal*)A->data;
299fa80d070SPierre Jolivet 
300fa80d070SPierre Jolivet   PetscFunctionBegin;
301fa80d070SPierre Jolivet   *M = Aa->A;
302fa80d070SPierre Jolivet   PetscFunctionReturn(0);
303fa80d070SPierre Jolivet }
304fa80d070SPierre Jolivet 
305fa80d070SPierre Jolivet /*@
306fa80d070SPierre Jolivet       MatNormalGetMat - Gets the Mat object stored inside a MATNORMAL
307fa80d070SPierre Jolivet 
308fa80d070SPierre Jolivet    Logically collective on Mat
309fa80d070SPierre Jolivet 
310fa80d070SPierre Jolivet    Input Parameter:
311fa80d070SPierre Jolivet .   A  - the MATNORMAL matrix
312fa80d070SPierre Jolivet 
313fa80d070SPierre Jolivet    Output Parameter:
314fa80d070SPierre Jolivet .   M - the matrix object stored inside A
315fa80d070SPierre Jolivet 
316fa80d070SPierre Jolivet    Level: intermediate
317fa80d070SPierre Jolivet 
318db781477SPatrick Sanan .seealso: `MatCreateNormal()`
319fa80d070SPierre Jolivet 
320fa80d070SPierre Jolivet @*/
321fa80d070SPierre Jolivet PetscErrorCode MatNormalGetMat(Mat A,Mat *M)
322fa80d070SPierre Jolivet {
323fa80d070SPierre Jolivet   PetscFunctionBegin;
324fa80d070SPierre Jolivet   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
325fa80d070SPierre Jolivet   PetscValidType(A,1);
326fa80d070SPierre Jolivet   PetscValidPointer(M,2);
327cac4c232SBarry Smith   PetscUseMethod(A,"MatNormalGetMat_C",(Mat,Mat*),(A,M));
328fa80d070SPierre Jolivet   PetscFunctionReturn(0);
329fa80d070SPierre Jolivet }
330fa80d070SPierre Jolivet 
331fa80d070SPierre Jolivet PetscErrorCode MatConvert_Normal_AIJ(Mat A,MatType newtype,MatReuse reuse,Mat *newmat)
332fa80d070SPierre Jolivet {
333fa80d070SPierre Jolivet   Mat_Normal     *Aa = (Mat_Normal*)A->data;
334fa80d070SPierre Jolivet   Mat            B;
335fa80d070SPierre Jolivet   PetscInt       m,n,M,N;
336fa80d070SPierre Jolivet 
337fa80d070SPierre Jolivet   PetscFunctionBegin;
3389566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&M,&N));
3399566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A,&m,&n));
340fa80d070SPierre Jolivet   if (reuse == MAT_REUSE_MATRIX) {
341fa80d070SPierre Jolivet     B = *newmat;
3429566063dSJacob Faibussowitsch     PetscCall(MatProductReplaceMats(Aa->A,Aa->A,NULL,B));
343fa80d070SPierre Jolivet   } else {
3449566063dSJacob Faibussowitsch     PetscCall(MatProductCreate(Aa->A,Aa->A,NULL,&B));
3459566063dSJacob Faibussowitsch     PetscCall(MatProductSetType(B,MATPRODUCT_AtB));
3469566063dSJacob Faibussowitsch     PetscCall(MatProductSetFromOptions(B));
3479566063dSJacob Faibussowitsch     PetscCall(MatProductSymbolic(B));
3489566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B,MAT_SYMMETRIC,PETSC_TRUE));
349fa80d070SPierre Jolivet   }
3509566063dSJacob Faibussowitsch   PetscCall(MatProductNumeric(B));
351fa80d070SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) {
3529566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A,&B));
353fa80d070SPierre Jolivet   } else if (reuse == MAT_INITIAL_MATRIX) *newmat = B;
3549566063dSJacob Faibussowitsch   PetscCall(MatConvert(*newmat,MATAIJ,MAT_INPLACE_MATRIX,newmat));
355fa80d070SPierre Jolivet   PetscFunctionReturn(0);
356fa80d070SPierre Jolivet }
357fa80d070SPierre Jolivet 
358fa80d070SPierre Jolivet typedef struct {
359fa80d070SPierre Jolivet   Mat work[2];
360fa80d070SPierre Jolivet } Normal_Dense;
361fa80d070SPierre Jolivet 
362fa80d070SPierre Jolivet PetscErrorCode MatProductNumeric_Normal_Dense(Mat C)
363fa80d070SPierre Jolivet {
364fa80d070SPierre Jolivet   Mat            A,B;
365fa80d070SPierre Jolivet   Normal_Dense   *contents;
366fa80d070SPierre Jolivet   Mat_Normal     *a;
367fa80d070SPierre Jolivet   PetscScalar    *array;
368fa80d070SPierre Jolivet 
369fa80d070SPierre Jolivet   PetscFunctionBegin;
370fa80d070SPierre Jolivet   MatCheckProduct(C,3);
371fa80d070SPierre Jolivet   A = C->product->A;
372fa80d070SPierre Jolivet   a = (Mat_Normal*)A->data;
373fa80d070SPierre Jolivet   B = C->product->B;
374fa80d070SPierre Jolivet   contents = (Normal_Dense*)C->product->data;
37528b400f6SJacob Faibussowitsch   PetscCheck(contents,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Product data empty");
376fa80d070SPierre Jolivet   if (a->right) {
3779566063dSJacob Faibussowitsch     PetscCall(MatCopy(B,C,SAME_NONZERO_PATTERN));
3789566063dSJacob Faibussowitsch     PetscCall(MatDiagonalScale(C,a->right,NULL));
379fa80d070SPierre Jolivet   }
3809566063dSJacob Faibussowitsch   PetscCall(MatProductNumeric(contents->work[0]));
3819566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C,&array));
3829566063dSJacob Faibussowitsch   PetscCall(MatDensePlaceArray(contents->work[1],array));
3839566063dSJacob Faibussowitsch   PetscCall(MatProductNumeric(contents->work[1]));
3849566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C,&array));
3859566063dSJacob Faibussowitsch   PetscCall(MatDenseResetArray(contents->work[1]));
3869566063dSJacob Faibussowitsch   PetscCall(MatSetOption(C,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE));
3879566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
3889566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
3899566063dSJacob Faibussowitsch   PetscCall(MatScale(C,a->scale));
390fa80d070SPierre Jolivet   PetscFunctionReturn(0);
391fa80d070SPierre Jolivet }
392fa80d070SPierre Jolivet 
393fa80d070SPierre Jolivet PetscErrorCode MatNormal_DenseDestroy(void *ctx)
394fa80d070SPierre Jolivet {
395fa80d070SPierre Jolivet   Normal_Dense   *contents = (Normal_Dense*)ctx;
396fa80d070SPierre Jolivet 
397fa80d070SPierre Jolivet   PetscFunctionBegin;
3989566063dSJacob Faibussowitsch   PetscCall(MatDestroy(contents->work));
3999566063dSJacob Faibussowitsch   PetscCall(MatDestroy(contents->work+1));
4009566063dSJacob Faibussowitsch   PetscCall(PetscFree(contents));
401fa80d070SPierre Jolivet   PetscFunctionReturn(0);
402fa80d070SPierre Jolivet }
403fa80d070SPierre Jolivet 
404fa80d070SPierre Jolivet PetscErrorCode MatProductSymbolic_Normal_Dense(Mat C)
405fa80d070SPierre Jolivet {
406fa80d070SPierre Jolivet   Mat            A,B;
407fa80d070SPierre Jolivet   Normal_Dense   *contents = NULL;
408fa80d070SPierre Jolivet   Mat_Normal     *a;
409fa80d070SPierre Jolivet   PetscScalar    *array;
410fa80d070SPierre Jolivet   PetscInt       n,N,m,M;
411fa80d070SPierre Jolivet 
412fa80d070SPierre Jolivet   PetscFunctionBegin;
413fa80d070SPierre Jolivet   MatCheckProduct(C,4);
41428b400f6SJacob Faibussowitsch   PetscCheck(!C->product->data,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Product data not empty");
415fa80d070SPierre Jolivet   A = C->product->A;
416fa80d070SPierre Jolivet   a = (Mat_Normal*)A->data;
41728b400f6SJacob Faibussowitsch   PetscCheck(!a->left,PetscObjectComm((PetscObject)C),PETSC_ERR_SUP,"Not implemented");
418fa80d070SPierre Jolivet   B = C->product->B;
4199566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(C,&m,&n));
4209566063dSJacob Faibussowitsch   PetscCall(MatGetSize(C,&M,&N));
421fa80d070SPierre Jolivet   if (m == PETSC_DECIDE || n == PETSC_DECIDE || M == PETSC_DECIDE || N == PETSC_DECIDE) {
4229566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(B,NULL,&n));
4239566063dSJacob Faibussowitsch     PetscCall(MatGetSize(B,NULL,&N));
4249566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A,&m,NULL));
4259566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A,&M,NULL));
4269566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(C,m,n,M,N));
427fa80d070SPierre Jolivet   }
4289566063dSJacob Faibussowitsch   PetscCall(MatSetType(C,((PetscObject)B)->type_name));
4299566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
4309566063dSJacob Faibussowitsch   PetscCall(PetscNew(&contents));
431fa80d070SPierre Jolivet   C->product->data = contents;
432fa80d070SPierre Jolivet   C->product->destroy = MatNormal_DenseDestroy;
433fa80d070SPierre Jolivet   if (a->right) {
4349566063dSJacob Faibussowitsch     PetscCall(MatProductCreate(a->A,C,NULL,contents->work));
435fa80d070SPierre Jolivet   } else {
4369566063dSJacob Faibussowitsch     PetscCall(MatProductCreate(a->A,B,NULL,contents->work));
437fa80d070SPierre Jolivet   }
4389566063dSJacob Faibussowitsch   PetscCall(MatProductSetType(contents->work[0],MATPRODUCT_AB));
4399566063dSJacob Faibussowitsch   PetscCall(MatProductSetFromOptions(contents->work[0]));
4409566063dSJacob Faibussowitsch   PetscCall(MatProductSymbolic(contents->work[0]));
4419566063dSJacob Faibussowitsch   PetscCall(MatProductCreate(a->A,contents->work[0],NULL,contents->work+1));
4429566063dSJacob Faibussowitsch   PetscCall(MatProductSetType(contents->work[1],MATPRODUCT_AtB));
4439566063dSJacob Faibussowitsch   PetscCall(MatProductSetFromOptions(contents->work[1]));
4449566063dSJacob Faibussowitsch   PetscCall(MatProductSymbolic(contents->work[1]));
4459566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C,&array));
4469566063dSJacob Faibussowitsch   PetscCall(MatSeqDenseSetPreallocation(contents->work[1],array));
4479566063dSJacob Faibussowitsch   PetscCall(MatMPIDenseSetPreallocation(contents->work[1],array));
4489566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C,&array));
449fa80d070SPierre Jolivet   C->ops->productnumeric = MatProductNumeric_Normal_Dense;
450fa80d070SPierre Jolivet   PetscFunctionReturn(0);
451fa80d070SPierre Jolivet }
452fa80d070SPierre Jolivet 
453fa80d070SPierre Jolivet PetscErrorCode MatProductSetFromOptions_Normal_Dense_AB(Mat C)
454fa80d070SPierre Jolivet {
455fa80d070SPierre Jolivet   PetscFunctionBegin;
456fa80d070SPierre Jolivet   C->ops->productsymbolic = MatProductSymbolic_Normal_Dense;
457fa80d070SPierre Jolivet   PetscFunctionReturn(0);
458fa80d070SPierre Jolivet }
459fa80d070SPierre Jolivet 
460fa80d070SPierre Jolivet PetscErrorCode MatProductSetFromOptions_Normal_Dense(Mat C)
461fa80d070SPierre Jolivet {
462fa80d070SPierre Jolivet   Mat_Product    *product = C->product;
463fa80d070SPierre Jolivet 
464fa80d070SPierre Jolivet   PetscFunctionBegin;
465fa80d070SPierre Jolivet   if (product->type == MATPRODUCT_AB) {
4669566063dSJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_Normal_Dense_AB(C));
467fa80d070SPierre Jolivet   }
468fa80d070SPierre Jolivet   PetscFunctionReturn(0);
469fa80d070SPierre Jolivet }
470fa80d070SPierre Jolivet 
471c8a8475eSBarry Smith /*@
472c8a8475eSBarry Smith       MatCreateNormal - Creates a new matrix object that behaves like A'*A.
473c8a8475eSBarry Smith 
474c8a8475eSBarry Smith    Collective on Mat
475c8a8475eSBarry Smith 
476c8a8475eSBarry Smith    Input Parameter:
477c8a8475eSBarry Smith .   A  - the (possibly rectangular) matrix
478c8a8475eSBarry Smith 
479c8a8475eSBarry Smith    Output Parameter:
480c8a8475eSBarry Smith .   N - the matrix that represents A'*A
481c8a8475eSBarry Smith 
482c30e7cdbSSatish Balay    Level: intermediate
483c30e7cdbSSatish Balay 
48495452b02SPatrick Sanan    Notes:
48595452b02SPatrick Sanan     The product A'*A is NOT actually formed! Rather the new matrix
486c8a8475eSBarry Smith           object performs the matrix-vector product by first multiplying by
487c8a8475eSBarry Smith           A and then A'
488c8a8475eSBarry Smith @*/
4897087cfbeSBarry Smith PetscErrorCode  MatCreateNormal(Mat A,Mat *N)
490c8a8475eSBarry Smith {
4919ca0e1b6SStefano Zampini   PetscInt       n,nn;
492c8a8475eSBarry Smith   Mat_Normal     *Na;
4939ca0e1b6SStefano Zampini   VecType        vtype;
494c8a8475eSBarry Smith 
495c8a8475eSBarry Smith   PetscFunctionBegin;
4969566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,NULL,&nn));
4979566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A,NULL,&n));
4989566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A),N));
4999566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*N,n,n,nn,nn));
5009566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*N,MATNORMAL));
5019566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap,&(*N)->rmap));
5029566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap,&(*N)->cmap));
503c8a8475eSBarry Smith 
5049566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(*N,&Na));
50538f2d2fdSLisandro Dalcin   (*N)->data = (void*) Na;
5069566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)A));
507c3122656SLisandro Dalcin   Na->A      = A;
508b20f02adSBarry Smith   Na->scale  = 1.0;
509c8a8475eSBarry Smith 
5109566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(A,NULL,&Na->w));
5112205254eSKarl Rupp 
512c8a8475eSBarry Smith   (*N)->ops->destroy           = MatDestroy_Normal;
513c8a8475eSBarry Smith   (*N)->ops->mult              = MatMult_Normal;
514b20f02adSBarry Smith   (*N)->ops->multtranspose     = MatMultTranspose_Normal;
515b20f02adSBarry Smith   (*N)->ops->multtransposeadd  = MatMultTransposeAdd_Normal;
516db090513SMatthew Knepley   (*N)->ops->multadd           = MatMultAdd_Normal;
51717a6fd94SBarry Smith   (*N)->ops->getdiagonal       = MatGetDiagonal_Normal;
518a48507d3SJose E. Roman   (*N)->ops->getdiagonalblock  = MatGetDiagonalBlock_Normal;
51969ef1043SBarry Smith   (*N)->ops->scale             = MatScale_Normal;
52069ef1043SBarry Smith   (*N)->ops->diagonalscale     = MatDiagonalScale_Normal;
521fa80d070SPierre Jolivet   (*N)->ops->increaseoverlap   = MatIncreaseOverlap_Normal;
522fa80d070SPierre Jolivet   (*N)->ops->createsubmatrices = MatCreateSubMatrices_Normal;
523fa80d070SPierre Jolivet   (*N)->ops->permute           = MatPermute_Normal;
524fa80d070SPierre Jolivet   (*N)->ops->duplicate         = MatDuplicate_Normal;
525fa80d070SPierre Jolivet   (*N)->ops->copy              = MatCopy_Normal;
526c8a8475eSBarry Smith   (*N)->assembled              = PETSC_TRUE;
52748331cefSBarry Smith   (*N)->preallocated           = PETSC_TRUE;
5289ca0e1b6SStefano Zampini 
5299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatNormalGetMat_C",MatNormalGetMat_Normal));
5309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatConvert_normal_seqaij_C",MatConvert_Normal_AIJ));
5319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatConvert_normal_mpiaij_C",MatConvert_Normal_AIJ));
5329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatProductSetFromOptions_normal_seqdense_C",MatProductSetFromOptions_Normal_Dense));
5339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatProductSetFromOptions_normal_mpidense_C",MatProductSetFromOptions_Normal_Dense));
5349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatProductSetFromOptions_normal_dense_C",MatProductSetFromOptions_Normal_Dense));
5359566063dSJacob Faibussowitsch   PetscCall(MatSetOption(*N,MAT_SYMMETRIC,PETSC_TRUE));
5369566063dSJacob Faibussowitsch   PetscCall(MatGetVecType(A,&vtype));
5379566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(*N,vtype));
5389ca0e1b6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
5399566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU(*N,A->boundtocpu));
5409ca0e1b6SStefano Zampini #endif
541c8a8475eSBarry Smith   PetscFunctionReturn(0);
542c8a8475eSBarry Smith }
543