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