1c8a8475eSBarry Smith 2af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 3c8a8475eSBarry Smith 4c8a8475eSBarry Smith typedef struct { 57cfd0b8cSBarry Smith Mat A; 67cfd0b8cSBarry Smith Vec w,left,right,leftwork,rightwork; 7b20f02adSBarry Smith PetscScalar scale; 8c8a8475eSBarry Smith } Mat_Normal; 9c8a8475eSBarry Smith 1069ef1043SBarry Smith PetscErrorCode MatScale_Normal(Mat inA,PetscScalar scale) 1169ef1043SBarry Smith { 1269ef1043SBarry Smith Mat_Normal *a = (Mat_Normal*)inA->data; 1369ef1043SBarry Smith 1469ef1043SBarry Smith PetscFunctionBegin; 1569ef1043SBarry Smith a->scale *= scale; 1669ef1043SBarry Smith PetscFunctionReturn(0); 1769ef1043SBarry Smith } 1869ef1043SBarry Smith 197cfd0b8cSBarry Smith PetscErrorCode MatDiagonalScale_Normal(Mat inA,Vec left,Vec right) 207cfd0b8cSBarry Smith { 217cfd0b8cSBarry Smith Mat_Normal *a = (Mat_Normal*)inA->data; 227cfd0b8cSBarry Smith 237cfd0b8cSBarry Smith PetscFunctionBegin; 247cfd0b8cSBarry Smith if (left) { 257cfd0b8cSBarry Smith if (!a->left) { 269566063dSJacob Faibussowitsch PetscCall(VecDuplicate(left,&a->left)); 279566063dSJacob Faibussowitsch PetscCall(VecCopy(left,a->left)); 287cfd0b8cSBarry Smith } else { 299566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(a->left,left,a->left)); 307cfd0b8cSBarry Smith } 317cfd0b8cSBarry Smith } 327cfd0b8cSBarry Smith if (right) { 337cfd0b8cSBarry Smith if (!a->right) { 349566063dSJacob Faibussowitsch PetscCall(VecDuplicate(right,&a->right)); 359566063dSJacob Faibussowitsch PetscCall(VecCopy(right,a->right)); 367cfd0b8cSBarry Smith } else { 379566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(a->right,right,a->right)); 387cfd0b8cSBarry Smith } 397cfd0b8cSBarry Smith } 407cfd0b8cSBarry Smith PetscFunctionReturn(0); 417cfd0b8cSBarry Smith } 427cfd0b8cSBarry Smith 43fa80d070SPierre Jolivet PetscErrorCode MatIncreaseOverlap_Normal(Mat A,PetscInt is_max,IS is[],PetscInt ov) 44fa80d070SPierre Jolivet { 45fa80d070SPierre Jolivet Mat_Normal *a = (Mat_Normal*)A->data; 46fa80d070SPierre Jolivet Mat pattern; 47fa80d070SPierre Jolivet 48fa80d070SPierre Jolivet PetscFunctionBegin; 492c71b3e2SJacob Faibussowitsch PetscCheckFalse(ov < 0,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Negative overlap specified"); 509566063dSJacob Faibussowitsch PetscCall(MatProductCreate(a->A,a->A,NULL,&pattern)); 519566063dSJacob Faibussowitsch PetscCall(MatProductSetType(pattern,MATPRODUCT_AtB)); 529566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(pattern)); 539566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(pattern)); 549566063dSJacob Faibussowitsch PetscCall(MatIncreaseOverlap(pattern,is_max,is,ov)); 559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pattern)); 56fa80d070SPierre Jolivet PetscFunctionReturn(0); 57fa80d070SPierre Jolivet } 58fa80d070SPierre Jolivet 59fa80d070SPierre Jolivet PetscErrorCode MatCreateSubMatrices_Normal(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[]) 60fa80d070SPierre Jolivet { 61fa80d070SPierre Jolivet Mat_Normal *a = (Mat_Normal*)mat->data; 62fa80d070SPierre Jolivet Mat B = a->A, *suba; 63fa80d070SPierre Jolivet IS *row; 64fa80d070SPierre Jolivet PetscInt M; 65fa80d070SPierre Jolivet 66fa80d070SPierre Jolivet PetscFunctionBegin; 672c71b3e2SJacob Faibussowitsch PetscCheckFalse(a->left || a->right || irow != icol,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not implemented"); 68fa80d070SPierre Jolivet if (scall != MAT_REUSE_MATRIX) { 699566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n,submat)); 70fa80d070SPierre Jolivet } 719566063dSJacob Faibussowitsch PetscCall(MatGetSize(B,&M,NULL)); 729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n,&row)); 739566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,M,0,1,&row[0])); 749566063dSJacob Faibussowitsch PetscCall(ISSetIdentity(row[0])); 75fa80d070SPierre Jolivet for (M = 1; M < n; ++M) row[M] = row[0]; 769566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(B,n,row,icol,MAT_INITIAL_MATRIX,&suba)); 77fa80d070SPierre Jolivet for (M = 0; M < n; ++M) { 789566063dSJacob Faibussowitsch PetscCall(MatCreateNormal(suba[M],*submat+M)); 79fa80d070SPierre Jolivet ((Mat_Normal*)(*submat)[M]->data)->scale = a->scale; 80fa80d070SPierre Jolivet } 819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&row[0])); 829566063dSJacob Faibussowitsch PetscCall(PetscFree(row)); 839566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices(n,&suba)); 84fa80d070SPierre Jolivet PetscFunctionReturn(0); 85fa80d070SPierre Jolivet } 86fa80d070SPierre Jolivet 87fa80d070SPierre Jolivet PetscErrorCode MatPermute_Normal(Mat A,IS rowp,IS colp,Mat *B) 88fa80d070SPierre Jolivet { 89fa80d070SPierre Jolivet Mat_Normal *a = (Mat_Normal*)A->data; 90fa80d070SPierre Jolivet Mat C,Aa = a->A; 91fa80d070SPierre Jolivet IS row; 92fa80d070SPierre Jolivet 93fa80d070SPierre Jolivet PetscFunctionBegin; 942c71b3e2SJacob Faibussowitsch PetscCheckFalse(rowp != colp,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Row permutation and column permutation must be the same"); 959566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)Aa),Aa->rmap->n,Aa->rmap->rstart,1,&row)); 969566063dSJacob Faibussowitsch PetscCall(ISSetIdentity(row)); 979566063dSJacob Faibussowitsch PetscCall(MatPermute(Aa,row,colp,&C)); 989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&row)); 999566063dSJacob Faibussowitsch PetscCall(MatCreateNormal(C,B)); 1009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 101fa80d070SPierre Jolivet PetscFunctionReturn(0); 102fa80d070SPierre Jolivet } 103fa80d070SPierre Jolivet 104fa80d070SPierre Jolivet PetscErrorCode MatDuplicate_Normal(Mat A, MatDuplicateOption op, Mat *B) 105fa80d070SPierre Jolivet { 106fa80d070SPierre Jolivet Mat_Normal *a = (Mat_Normal*)A->data; 107fa80d070SPierre Jolivet Mat C; 108fa80d070SPierre Jolivet 109fa80d070SPierre Jolivet PetscFunctionBegin; 1102c71b3e2SJacob Faibussowitsch PetscCheckFalse(a->left || a->right,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Not implemented"); 1119566063dSJacob Faibussowitsch PetscCall(MatDuplicate(a->A,op,&C)); 1129566063dSJacob Faibussowitsch PetscCall(MatCreateNormal(C,B)); 1139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 114fa80d070SPierre Jolivet if (op == MAT_COPY_VALUES) ((Mat_Normal*)(*B)->data)->scale = a->scale; 115fa80d070SPierre Jolivet PetscFunctionReturn(0); 116fa80d070SPierre Jolivet } 117fa80d070SPierre Jolivet 118fa80d070SPierre Jolivet PetscErrorCode MatCopy_Normal(Mat A,Mat B,MatStructure str) 119fa80d070SPierre Jolivet { 120fa80d070SPierre Jolivet Mat_Normal *a = (Mat_Normal*)A->data,*b = (Mat_Normal*)B->data; 121fa80d070SPierre Jolivet 122fa80d070SPierre Jolivet PetscFunctionBegin; 1232c71b3e2SJacob Faibussowitsch PetscCheckFalse(a->left || a->right,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Not implemented"); 1249566063dSJacob Faibussowitsch PetscCall(MatCopy(a->A,b->A,str)); 125fa80d070SPierre Jolivet b->scale = a->scale; 1269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->left)); 1279566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->right)); 1289566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->leftwork)); 1299566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->rightwork)); 130fa80d070SPierre Jolivet PetscFunctionReturn(0); 131fa80d070SPierre Jolivet } 132fa80d070SPierre Jolivet 133dfbe8321SBarry Smith PetscErrorCode MatMult_Normal(Mat N,Vec x,Vec y) 134c8a8475eSBarry Smith { 135c8a8475eSBarry Smith Mat_Normal *Na = (Mat_Normal*)N->data; 1367cfd0b8cSBarry Smith Vec in; 137c8a8475eSBarry Smith 138c8a8475eSBarry Smith PetscFunctionBegin; 1397cfd0b8cSBarry Smith in = x; 1407cfd0b8cSBarry Smith if (Na->right) { 1417cfd0b8cSBarry Smith if (!Na->rightwork) { 1429566063dSJacob Faibussowitsch PetscCall(VecDuplicate(Na->right,&Na->rightwork)); 1437cfd0b8cSBarry Smith } 1449566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Na->rightwork,Na->right,in)); 1457cfd0b8cSBarry Smith in = Na->rightwork; 1467cfd0b8cSBarry Smith } 1479566063dSJacob Faibussowitsch PetscCall(MatMult(Na->A,in,Na->w)); 1489566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(Na->A,Na->w,y)); 1497cfd0b8cSBarry Smith if (Na->left) { 1509566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(y,Na->left,y)); 1517cfd0b8cSBarry Smith } 1529566063dSJacob Faibussowitsch PetscCall(VecScale(y,Na->scale)); 153c8a8475eSBarry Smith PetscFunctionReturn(0); 154c8a8475eSBarry Smith } 155c8a8475eSBarry Smith 156db090513SMatthew Knepley PetscErrorCode MatMultAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3) 157db090513SMatthew Knepley { 158db090513SMatthew Knepley Mat_Normal *Na = (Mat_Normal*)N->data; 1597cfd0b8cSBarry Smith Vec in; 160db090513SMatthew Knepley 161db090513SMatthew Knepley PetscFunctionBegin; 1627cfd0b8cSBarry Smith in = v1; 1637cfd0b8cSBarry Smith if (Na->right) { 1647cfd0b8cSBarry Smith if (!Na->rightwork) { 1659566063dSJacob Faibussowitsch PetscCall(VecDuplicate(Na->right,&Na->rightwork)); 1667cfd0b8cSBarry Smith } 1679566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Na->rightwork,Na->right,in)); 1687cfd0b8cSBarry Smith in = Na->rightwork; 1697cfd0b8cSBarry Smith } 1709566063dSJacob Faibussowitsch PetscCall(MatMult(Na->A,in,Na->w)); 1719566063dSJacob Faibussowitsch PetscCall(VecScale(Na->w,Na->scale)); 1727cfd0b8cSBarry Smith if (Na->left) { 1739566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(Na->A,Na->w,v3)); 1749566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(v3,Na->left,v3)); 1759566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3,1.0,v2)); 1767cfd0b8cSBarry Smith } else { 1779566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(Na->A,Na->w,v2,v3)); 1787cfd0b8cSBarry Smith } 179b20f02adSBarry Smith PetscFunctionReturn(0); 180b20f02adSBarry Smith } 181b20f02adSBarry Smith 182b20f02adSBarry Smith PetscErrorCode MatMultTranspose_Normal(Mat N,Vec x,Vec y) 183b20f02adSBarry Smith { 184b20f02adSBarry Smith Mat_Normal *Na = (Mat_Normal*)N->data; 1857cfd0b8cSBarry Smith Vec in; 186b20f02adSBarry Smith 187b20f02adSBarry Smith PetscFunctionBegin; 1887cfd0b8cSBarry Smith in = x; 1897cfd0b8cSBarry Smith if (Na->left) { 1907cfd0b8cSBarry Smith if (!Na->leftwork) { 1919566063dSJacob Faibussowitsch PetscCall(VecDuplicate(Na->left,&Na->leftwork)); 1927cfd0b8cSBarry Smith } 1939566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Na->leftwork,Na->left,in)); 1947cfd0b8cSBarry Smith in = Na->leftwork; 1957cfd0b8cSBarry Smith } 1969566063dSJacob Faibussowitsch PetscCall(MatMult(Na->A,in,Na->w)); 1979566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(Na->A,Na->w,y)); 1987cfd0b8cSBarry Smith if (Na->right) { 1999566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(y,Na->right,y)); 2007cfd0b8cSBarry Smith } 2019566063dSJacob Faibussowitsch PetscCall(VecScale(y,Na->scale)); 202b20f02adSBarry Smith PetscFunctionReturn(0); 203b20f02adSBarry Smith } 204b20f02adSBarry Smith 205b20f02adSBarry Smith PetscErrorCode MatMultTransposeAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3) 206b20f02adSBarry Smith { 207b20f02adSBarry Smith Mat_Normal *Na = (Mat_Normal*)N->data; 2087cfd0b8cSBarry Smith Vec in; 209b20f02adSBarry Smith 210b20f02adSBarry Smith PetscFunctionBegin; 2117cfd0b8cSBarry Smith in = v1; 2127cfd0b8cSBarry Smith if (Na->left) { 2137cfd0b8cSBarry Smith if (!Na->leftwork) { 2149566063dSJacob Faibussowitsch PetscCall(VecDuplicate(Na->left,&Na->leftwork)); 2157cfd0b8cSBarry Smith } 2169566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Na->leftwork,Na->left,in)); 2177cfd0b8cSBarry Smith in = Na->leftwork; 2187cfd0b8cSBarry Smith } 2199566063dSJacob Faibussowitsch PetscCall(MatMult(Na->A,in,Na->w)); 2209566063dSJacob Faibussowitsch PetscCall(VecScale(Na->w,Na->scale)); 2217cfd0b8cSBarry Smith if (Na->right) { 2229566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(Na->A,Na->w,v3)); 2239566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(v3,Na->right,v3)); 2249566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3,1.0,v2)); 2257cfd0b8cSBarry Smith } else { 2269566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(Na->A,Na->w,v2,v3)); 2277cfd0b8cSBarry Smith } 228db090513SMatthew Knepley PetscFunctionReturn(0); 229db090513SMatthew Knepley } 230db090513SMatthew Knepley 231dfbe8321SBarry Smith PetscErrorCode MatDestroy_Normal(Mat N) 232c8a8475eSBarry Smith { 233c8a8475eSBarry Smith Mat_Normal *Na = (Mat_Normal*)N->data; 234c8a8475eSBarry Smith 235c8a8475eSBarry Smith PetscFunctionBegin; 2369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Na->A)); 2379566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->w)); 2389566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->left)); 2399566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->right)); 2409566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->leftwork)); 2419566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->rightwork)); 2429566063dSJacob Faibussowitsch PetscCall(PetscFree(N->data)); 2439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)N,"MatNormalGetMat_C",NULL)); 2449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)N,"MatConvert_normal_seqaij_C",NULL)); 2459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)N,"MatConvert_normal_mpiaij_C",NULL)); 2469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)N,"MatProductSetFromOptions_normal_seqdense_C",NULL)); 2479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)N,"MatProductSetFromOptions_normal_mpidense_C",NULL)); 2489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)N,"MatProductSetFromOptions_normal_dense_C",NULL)); 249c8a8475eSBarry Smith PetscFunctionReturn(0); 250c8a8475eSBarry Smith } 251c8a8475eSBarry Smith 25217a6fd94SBarry Smith /* 25317a6fd94SBarry Smith Slow, nonscalable version 25417a6fd94SBarry Smith */ 255dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_Normal(Mat N,Vec v) 25617a6fd94SBarry Smith { 25717a6fd94SBarry Smith Mat_Normal *Na = (Mat_Normal*)N->data; 25817a6fd94SBarry Smith Mat A = Na->A; 259b24ad042SBarry Smith PetscInt i,j,rstart,rend,nnz; 260b24ad042SBarry Smith const PetscInt *cols; 26117a6fd94SBarry Smith PetscScalar *diag,*work,*values; 262b3cc6726SBarry Smith const PetscScalar *mvalues; 26317a6fd94SBarry Smith 26417a6fd94SBarry Smith PetscFunctionBegin; 2659566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(A->cmap->N,&diag,A->cmap->N,&work)); 2669566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(work,A->cmap->N)); 2679566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A,&rstart,&rend)); 26817a6fd94SBarry Smith for (i=rstart; i<rend; i++) { 2699566063dSJacob Faibussowitsch PetscCall(MatGetRow(A,i,&nnz,&cols,&mvalues)); 27017a6fd94SBarry Smith for (j=0; j<nnz; j++) { 271b3cc6726SBarry Smith work[cols[j]] += mvalues[j]*mvalues[j]; 27217a6fd94SBarry Smith } 2739566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A,i,&nnz,&cols,&mvalues)); 27417a6fd94SBarry Smith } 2759566063dSJacob Faibussowitsch PetscCallMPI(MPIU_Allreduce(work,diag,A->cmap->N,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)N))); 276d0f46423SBarry Smith rstart = N->cmap->rstart; 277d0f46423SBarry Smith rend = N->cmap->rend; 2789566063dSJacob Faibussowitsch PetscCall(VecGetArray(v,&values)); 2799566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(values,diag+rstart,rend-rstart)); 2809566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v,&values)); 2819566063dSJacob Faibussowitsch PetscCall(PetscFree2(diag,work)); 2829566063dSJacob Faibussowitsch PetscCall(VecScale(v,Na->scale)); 28317a6fd94SBarry Smith PetscFunctionReturn(0); 28417a6fd94SBarry Smith } 285c8a8475eSBarry Smith 286fa80d070SPierre Jolivet PetscErrorCode MatNormalGetMat_Normal(Mat A,Mat *M) 287fa80d070SPierre Jolivet { 288fa80d070SPierre Jolivet Mat_Normal *Aa = (Mat_Normal*)A->data; 289fa80d070SPierre Jolivet 290fa80d070SPierre Jolivet PetscFunctionBegin; 291fa80d070SPierre Jolivet *M = Aa->A; 292fa80d070SPierre Jolivet PetscFunctionReturn(0); 293fa80d070SPierre Jolivet } 294fa80d070SPierre Jolivet 295fa80d070SPierre Jolivet /*@ 296fa80d070SPierre Jolivet MatNormalGetMat - Gets the Mat object stored inside a MATNORMAL 297fa80d070SPierre Jolivet 298fa80d070SPierre Jolivet Logically collective on Mat 299fa80d070SPierre Jolivet 300fa80d070SPierre Jolivet Input Parameter: 301fa80d070SPierre Jolivet . A - the MATNORMAL matrix 302fa80d070SPierre Jolivet 303fa80d070SPierre Jolivet Output Parameter: 304fa80d070SPierre Jolivet . M - the matrix object stored inside A 305fa80d070SPierre Jolivet 306fa80d070SPierre Jolivet Level: intermediate 307fa80d070SPierre Jolivet 308fa80d070SPierre Jolivet .seealso: MatCreateNormal() 309fa80d070SPierre Jolivet 310fa80d070SPierre Jolivet @*/ 311fa80d070SPierre Jolivet PetscErrorCode MatNormalGetMat(Mat A,Mat *M) 312fa80d070SPierre Jolivet { 313fa80d070SPierre Jolivet PetscFunctionBegin; 314fa80d070SPierre Jolivet PetscValidHeaderSpecific(A,MAT_CLASSID,1); 315fa80d070SPierre Jolivet PetscValidType(A,1); 316fa80d070SPierre Jolivet PetscValidPointer(M,2); 317*cac4c232SBarry Smith PetscUseMethod(A,"MatNormalGetMat_C",(Mat,Mat*),(A,M)); 318fa80d070SPierre Jolivet PetscFunctionReturn(0); 319fa80d070SPierre Jolivet } 320fa80d070SPierre Jolivet 321fa80d070SPierre Jolivet PetscErrorCode MatConvert_Normal_AIJ(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 322fa80d070SPierre Jolivet { 323fa80d070SPierre Jolivet Mat_Normal *Aa = (Mat_Normal*)A->data; 324fa80d070SPierre Jolivet Mat B; 325fa80d070SPierre Jolivet PetscInt m,n,M,N; 326fa80d070SPierre Jolivet 327fa80d070SPierre Jolivet PetscFunctionBegin; 3289566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&M,&N)); 3299566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,&m,&n)); 330fa80d070SPierre Jolivet if (reuse == MAT_REUSE_MATRIX) { 331fa80d070SPierre Jolivet B = *newmat; 3329566063dSJacob Faibussowitsch PetscCall(MatProductReplaceMats(Aa->A,Aa->A,NULL,B)); 333fa80d070SPierre Jolivet } else { 3349566063dSJacob Faibussowitsch PetscCall(MatProductCreate(Aa->A,Aa->A,NULL,&B)); 3359566063dSJacob Faibussowitsch PetscCall(MatProductSetType(B,MATPRODUCT_AtB)); 3369566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(B)); 3379566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(B)); 3389566063dSJacob Faibussowitsch PetscCall(MatSetOption(B,MAT_SYMMETRIC,PETSC_TRUE)); 339fa80d070SPierre Jolivet } 3409566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(B)); 341fa80d070SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) { 3429566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&B)); 343fa80d070SPierre Jolivet } else if (reuse == MAT_INITIAL_MATRIX) *newmat = B; 3449566063dSJacob Faibussowitsch PetscCall(MatConvert(*newmat,MATAIJ,MAT_INPLACE_MATRIX,newmat)); 345fa80d070SPierre Jolivet PetscFunctionReturn(0); 346fa80d070SPierre Jolivet } 347fa80d070SPierre Jolivet 348fa80d070SPierre Jolivet typedef struct { 349fa80d070SPierre Jolivet Mat work[2]; 350fa80d070SPierre Jolivet } Normal_Dense; 351fa80d070SPierre Jolivet 352fa80d070SPierre Jolivet PetscErrorCode MatProductNumeric_Normal_Dense(Mat C) 353fa80d070SPierre Jolivet { 354fa80d070SPierre Jolivet Mat A,B; 355fa80d070SPierre Jolivet Normal_Dense *contents; 356fa80d070SPierre Jolivet Mat_Normal *a; 357fa80d070SPierre Jolivet PetscScalar *array; 358fa80d070SPierre Jolivet 359fa80d070SPierre Jolivet PetscFunctionBegin; 360fa80d070SPierre Jolivet MatCheckProduct(C,3); 361fa80d070SPierre Jolivet A = C->product->A; 362fa80d070SPierre Jolivet a = (Mat_Normal*)A->data; 363fa80d070SPierre Jolivet B = C->product->B; 364fa80d070SPierre Jolivet contents = (Normal_Dense*)C->product->data; 36528b400f6SJacob Faibussowitsch PetscCheck(contents,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Product data empty"); 366fa80d070SPierre Jolivet if (a->right) { 3679566063dSJacob Faibussowitsch PetscCall(MatCopy(B,C,SAME_NONZERO_PATTERN)); 3689566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(C,a->right,NULL)); 369fa80d070SPierre Jolivet } 3709566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(contents->work[0])); 3719566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayWrite(C,&array)); 3729566063dSJacob Faibussowitsch PetscCall(MatDensePlaceArray(contents->work[1],array)); 3739566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(contents->work[1])); 3749566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayWrite(C,&array)); 3759566063dSJacob Faibussowitsch PetscCall(MatDenseResetArray(contents->work[1])); 3769566063dSJacob Faibussowitsch PetscCall(MatSetOption(C,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE)); 3779566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY)); 3789566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY)); 3799566063dSJacob Faibussowitsch PetscCall(MatScale(C,a->scale)); 380fa80d070SPierre Jolivet PetscFunctionReturn(0); 381fa80d070SPierre Jolivet } 382fa80d070SPierre Jolivet 383fa80d070SPierre Jolivet PetscErrorCode MatNormal_DenseDestroy(void *ctx) 384fa80d070SPierre Jolivet { 385fa80d070SPierre Jolivet Normal_Dense *contents = (Normal_Dense*)ctx; 386fa80d070SPierre Jolivet 387fa80d070SPierre Jolivet PetscFunctionBegin; 3889566063dSJacob Faibussowitsch PetscCall(MatDestroy(contents->work)); 3899566063dSJacob Faibussowitsch PetscCall(MatDestroy(contents->work+1)); 3909566063dSJacob Faibussowitsch PetscCall(PetscFree(contents)); 391fa80d070SPierre Jolivet PetscFunctionReturn(0); 392fa80d070SPierre Jolivet } 393fa80d070SPierre Jolivet 394fa80d070SPierre Jolivet PetscErrorCode MatProductSymbolic_Normal_Dense(Mat C) 395fa80d070SPierre Jolivet { 396fa80d070SPierre Jolivet Mat A,B; 397fa80d070SPierre Jolivet Normal_Dense *contents = NULL; 398fa80d070SPierre Jolivet Mat_Normal *a; 399fa80d070SPierre Jolivet PetscScalar *array; 400fa80d070SPierre Jolivet PetscInt n,N,m,M; 401fa80d070SPierre Jolivet 402fa80d070SPierre Jolivet PetscFunctionBegin; 403fa80d070SPierre Jolivet MatCheckProduct(C,4); 40428b400f6SJacob Faibussowitsch PetscCheck(!C->product->data,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Product data not empty"); 405fa80d070SPierre Jolivet A = C->product->A; 406fa80d070SPierre Jolivet a = (Mat_Normal*)A->data; 40728b400f6SJacob Faibussowitsch PetscCheck(!a->left,PetscObjectComm((PetscObject)C),PETSC_ERR_SUP,"Not implemented"); 408fa80d070SPierre Jolivet B = C->product->B; 4099566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(C,&m,&n)); 4109566063dSJacob Faibussowitsch PetscCall(MatGetSize(C,&M,&N)); 411fa80d070SPierre Jolivet if (m == PETSC_DECIDE || n == PETSC_DECIDE || M == PETSC_DECIDE || N == PETSC_DECIDE) { 4129566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(B,NULL,&n)); 4139566063dSJacob Faibussowitsch PetscCall(MatGetSize(B,NULL,&N)); 4149566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,&m,NULL)); 4159566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&M,NULL)); 4169566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,m,n,M,N)); 417fa80d070SPierre Jolivet } 4189566063dSJacob Faibussowitsch PetscCall(MatSetType(C,((PetscObject)B)->type_name)); 4199566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 4209566063dSJacob Faibussowitsch PetscCall(PetscNew(&contents)); 421fa80d070SPierre Jolivet C->product->data = contents; 422fa80d070SPierre Jolivet C->product->destroy = MatNormal_DenseDestroy; 423fa80d070SPierre Jolivet if (a->right) { 4249566063dSJacob Faibussowitsch PetscCall(MatProductCreate(a->A,C,NULL,contents->work)); 425fa80d070SPierre Jolivet } else { 4269566063dSJacob Faibussowitsch PetscCall(MatProductCreate(a->A,B,NULL,contents->work)); 427fa80d070SPierre Jolivet } 4289566063dSJacob Faibussowitsch PetscCall(MatProductSetType(contents->work[0],MATPRODUCT_AB)); 4299566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(contents->work[0])); 4309566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(contents->work[0])); 4319566063dSJacob Faibussowitsch PetscCall(MatProductCreate(a->A,contents->work[0],NULL,contents->work+1)); 4329566063dSJacob Faibussowitsch PetscCall(MatProductSetType(contents->work[1],MATPRODUCT_AtB)); 4339566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(contents->work[1])); 4349566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(contents->work[1])); 4359566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayWrite(C,&array)); 4369566063dSJacob Faibussowitsch PetscCall(MatSeqDenseSetPreallocation(contents->work[1],array)); 4379566063dSJacob Faibussowitsch PetscCall(MatMPIDenseSetPreallocation(contents->work[1],array)); 4389566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayWrite(C,&array)); 439fa80d070SPierre Jolivet C->ops->productnumeric = MatProductNumeric_Normal_Dense; 440fa80d070SPierre Jolivet PetscFunctionReturn(0); 441fa80d070SPierre Jolivet } 442fa80d070SPierre Jolivet 443fa80d070SPierre Jolivet PetscErrorCode MatProductSetFromOptions_Normal_Dense_AB(Mat C) 444fa80d070SPierre Jolivet { 445fa80d070SPierre Jolivet PetscFunctionBegin; 446fa80d070SPierre Jolivet C->ops->productsymbolic = MatProductSymbolic_Normal_Dense; 447fa80d070SPierre Jolivet PetscFunctionReturn(0); 448fa80d070SPierre Jolivet } 449fa80d070SPierre Jolivet 450fa80d070SPierre Jolivet PetscErrorCode MatProductSetFromOptions_Normal_Dense(Mat C) 451fa80d070SPierre Jolivet { 452fa80d070SPierre Jolivet Mat_Product *product = C->product; 453fa80d070SPierre Jolivet 454fa80d070SPierre Jolivet PetscFunctionBegin; 455fa80d070SPierre Jolivet if (product->type == MATPRODUCT_AB) { 4569566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions_Normal_Dense_AB(C)); 457fa80d070SPierre Jolivet } 458fa80d070SPierre Jolivet PetscFunctionReturn(0); 459fa80d070SPierre Jolivet } 460fa80d070SPierre Jolivet 461c8a8475eSBarry Smith /*@ 462c8a8475eSBarry Smith MatCreateNormal - Creates a new matrix object that behaves like A'*A. 463c8a8475eSBarry Smith 464c8a8475eSBarry Smith Collective on Mat 465c8a8475eSBarry Smith 466c8a8475eSBarry Smith Input Parameter: 467c8a8475eSBarry Smith . A - the (possibly rectangular) matrix 468c8a8475eSBarry Smith 469c8a8475eSBarry Smith Output Parameter: 470c8a8475eSBarry Smith . N - the matrix that represents A'*A 471c8a8475eSBarry Smith 472c30e7cdbSSatish Balay Level: intermediate 473c30e7cdbSSatish Balay 47495452b02SPatrick Sanan Notes: 47595452b02SPatrick Sanan The product A'*A is NOT actually formed! Rather the new matrix 476c8a8475eSBarry Smith object performs the matrix-vector product by first multiplying by 477c8a8475eSBarry Smith A and then A' 478c8a8475eSBarry Smith @*/ 4797087cfbeSBarry Smith PetscErrorCode MatCreateNormal(Mat A,Mat *N) 480c8a8475eSBarry Smith { 4819ca0e1b6SStefano Zampini PetscInt n,nn; 482c8a8475eSBarry Smith Mat_Normal *Na; 4839ca0e1b6SStefano Zampini VecType vtype; 484c8a8475eSBarry Smith 485c8a8475eSBarry Smith PetscFunctionBegin; 4869566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,NULL,&nn)); 4879566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,NULL,&n)); 4889566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),N)); 4899566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*N,n,n,nn,nn)); 4909566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*N,MATNORMAL)); 4919566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap,&(*N)->rmap)); 4929566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap,&(*N)->cmap)); 493c8a8475eSBarry Smith 4949566063dSJacob Faibussowitsch PetscCall(PetscNewLog(*N,&Na)); 49538f2d2fdSLisandro Dalcin (*N)->data = (void*) Na; 4969566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 497c3122656SLisandro Dalcin Na->A = A; 498b20f02adSBarry Smith Na->scale = 1.0; 499c8a8475eSBarry Smith 5009566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A,NULL,&Na->w)); 5012205254eSKarl Rupp 502c8a8475eSBarry Smith (*N)->ops->destroy = MatDestroy_Normal; 503c8a8475eSBarry Smith (*N)->ops->mult = MatMult_Normal; 504b20f02adSBarry Smith (*N)->ops->multtranspose = MatMultTranspose_Normal; 505b20f02adSBarry Smith (*N)->ops->multtransposeadd = MatMultTransposeAdd_Normal; 506db090513SMatthew Knepley (*N)->ops->multadd = MatMultAdd_Normal; 50717a6fd94SBarry Smith (*N)->ops->getdiagonal = MatGetDiagonal_Normal; 50869ef1043SBarry Smith (*N)->ops->scale = MatScale_Normal; 50969ef1043SBarry Smith (*N)->ops->diagonalscale = MatDiagonalScale_Normal; 510fa80d070SPierre Jolivet (*N)->ops->increaseoverlap = MatIncreaseOverlap_Normal; 511fa80d070SPierre Jolivet (*N)->ops->createsubmatrices = MatCreateSubMatrices_Normal; 512fa80d070SPierre Jolivet (*N)->ops->permute = MatPermute_Normal; 513fa80d070SPierre Jolivet (*N)->ops->duplicate = MatDuplicate_Normal; 514fa80d070SPierre Jolivet (*N)->ops->copy = MatCopy_Normal; 515c8a8475eSBarry Smith (*N)->assembled = PETSC_TRUE; 51648331cefSBarry Smith (*N)->preallocated = PETSC_TRUE; 5179ca0e1b6SStefano Zampini 5189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatNormalGetMat_C",MatNormalGetMat_Normal)); 5199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatConvert_normal_seqaij_C",MatConvert_Normal_AIJ)); 5209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatConvert_normal_mpiaij_C",MatConvert_Normal_AIJ)); 5219566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatProductSetFromOptions_normal_seqdense_C",MatProductSetFromOptions_Normal_Dense)); 5229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatProductSetFromOptions_normal_mpidense_C",MatProductSetFromOptions_Normal_Dense)); 5239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)(*N),"MatProductSetFromOptions_normal_dense_C",MatProductSetFromOptions_Normal_Dense)); 5249566063dSJacob Faibussowitsch PetscCall(MatSetOption(*N,MAT_SYMMETRIC,PETSC_TRUE)); 5259566063dSJacob Faibussowitsch PetscCall(MatGetVecType(A,&vtype)); 5269566063dSJacob Faibussowitsch PetscCall(MatSetVecType(*N,vtype)); 5279ca0e1b6SStefano Zampini #if defined(PETSC_HAVE_DEVICE) 5289566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(*N,A->boundtocpu)); 5299ca0e1b6SStefano Zampini #endif 530c8a8475eSBarry Smith PetscFunctionReturn(0); 531c8a8475eSBarry Smith } 532