1b4319ba4SBarry Smith /* 2b4319ba4SBarry Smith Creates a matrix class for using the Neumann-Neumann type preconditioners. 3b4319ba4SBarry Smith This stores the matrices in globally unassembled form. Each processor 4b4319ba4SBarry Smith assembles only its local Neumann problem and the parallel matrix vector 5b4319ba4SBarry Smith product is handled "implicitly". 6b4319ba4SBarry Smith 7b4319ba4SBarry Smith Currently this allows for only one subdomain per processor. 8b4319ba4SBarry Smith */ 9b4319ba4SBarry Smith 10*d0dbe9f7SStefano Zampini #include <petsc/private/matisimpl.h> /*I "petscmat.h" I*/ 114f2d7cafSStefano Zampini #include <petsc/private/sfimpl.h> 12a72d46e8SStefano Zampini #include <petsc/private/vecimpl.h> 13e432b41dSStefano Zampini #include <petsc/private/hashseti.h> 1428f4e0baSStefano Zampini 15f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048 16b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode); 17b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode); 188546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat); 19f26d0771SStefano Zampini 2075d48cdbSStefano Zampini static PetscErrorCode MatISContainerDestroyPtAP_Private(void *ptr) 2175d48cdbSStefano Zampini { 2275d48cdbSStefano Zampini MatISPtAP ptap = (MatISPtAP)ptr; 2375d48cdbSStefano Zampini 2475d48cdbSStefano Zampini PetscFunctionBegin; 259566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices(ptap->ris1 ? 2 : 1,&ptap->lP)); 269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->cis0)); 279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->cis1)); 289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris0)); 299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris1)); 309566063dSJacob Faibussowitsch PetscCall(PetscFree(ptap)); 3175d48cdbSStefano Zampini PetscFunctionReturn(0); 3275d48cdbSStefano Zampini } 3375d48cdbSStefano Zampini 3475d48cdbSStefano Zampini static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C) 3575d48cdbSStefano Zampini { 3675d48cdbSStefano Zampini MatISPtAP ptap; 3775d48cdbSStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 3875d48cdbSStefano Zampini Mat lA,lC; 3975d48cdbSStefano Zampini MatReuse reuse; 4075d48cdbSStefano Zampini IS ris[2],cis[2]; 4175d48cdbSStefano Zampini PetscContainer c; 4275d48cdbSStefano Zampini PetscInt n; 4375d48cdbSStefano Zampini 4475d48cdbSStefano Zampini PetscFunctionBegin; 459566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)C,"_MatIS_PtAP",(PetscObject*)&c)); 4628b400f6SJacob Faibussowitsch PetscCheck(c,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing PtAP information"); 479566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c,(void**)&ptap)); 4875d48cdbSStefano Zampini ris[0] = ptap->ris0; 4975d48cdbSStefano Zampini ris[1] = ptap->ris1; 5075d48cdbSStefano Zampini cis[0] = ptap->cis0; 5175d48cdbSStefano Zampini cis[1] = ptap->cis1; 5275d48cdbSStefano Zampini n = ptap->ris1 ? 2 : 1; 5375d48cdbSStefano Zampini reuse = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX; 549566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(P,n,ris,cis,reuse,&ptap->lP)); 5575d48cdbSStefano Zampini 569566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A,&lA)); 579566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(C,&lC)); 5875d48cdbSStefano Zampini if (ptap->ris1) { /* unsymmetric A mapping */ 5975d48cdbSStefano Zampini Mat lPt; 6075d48cdbSStefano Zampini 619566063dSJacob Faibussowitsch PetscCall(MatTranspose(ptap->lP[1],MAT_INITIAL_MATRIX,&lPt)); 629566063dSJacob Faibussowitsch PetscCall(MatMatMatMult(lPt,lA,ptap->lP[0],reuse,ptap->fill,&lC)); 6375d48cdbSStefano Zampini if (matis->storel2l) { 649566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",(PetscObject)lPt)); 6575d48cdbSStefano Zampini } 669566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lPt)); 6775d48cdbSStefano Zampini } else { 689566063dSJacob Faibussowitsch PetscCall(MatPtAP(lA,ptap->lP[0],reuse,ptap->fill,&lC)); 6975d48cdbSStefano Zampini if (matis->storel2l) { 709566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)C,"_MatIS_PtAP_l2l",(PetscObject)ptap->lP[0])); 7175d48cdbSStefano Zampini } 7275d48cdbSStefano Zampini } 7375d48cdbSStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 749566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(C,lC)); 759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lC)); 7675d48cdbSStefano Zampini } 779566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY)); 789566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY)); 7975d48cdbSStefano Zampini PetscFunctionReturn(0); 8075d48cdbSStefano Zampini } 8175d48cdbSStefano Zampini 8275d48cdbSStefano Zampini static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT,IS *cis) 8375d48cdbSStefano Zampini { 8475d48cdbSStefano Zampini Mat Po,Pd; 8575d48cdbSStefano Zampini IS zd,zo; 8675d48cdbSStefano Zampini const PetscInt *garray; 8775d48cdbSStefano Zampini PetscInt *aux,i,bs; 8875d48cdbSStefano Zampini PetscInt dc,stc,oc,ctd,cto; 8975d48cdbSStefano Zampini PetscBool ismpiaij,ismpibaij,isseqaij,isseqbaij; 9075d48cdbSStefano Zampini MPI_Comm comm; 9175d48cdbSStefano Zampini 9275d48cdbSStefano Zampini PetscFunctionBegin; 9375d48cdbSStefano Zampini PetscValidHeaderSpecific(PT,MAT_CLASSID,1); 9475d48cdbSStefano Zampini PetscValidPointer(cis,2); 959566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)PT,&comm)); 9675d48cdbSStefano Zampini bs = 1; 979566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT,MATMPIAIJ,&ismpiaij)); 989566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT,MATMPIBAIJ,&ismpibaij)); 999566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT,MATSEQAIJ,&isseqaij)); 1009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)PT,MATSEQBAIJ,&isseqbaij)); 10175d48cdbSStefano Zampini if (isseqaij || isseqbaij) { 10275d48cdbSStefano Zampini Pd = PT; 10375d48cdbSStefano Zampini Po = NULL; 10475d48cdbSStefano Zampini garray = NULL; 10575d48cdbSStefano Zampini } else if (ismpiaij) { 1069566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(PT,&Pd,&Po,&garray)); 10775d48cdbSStefano Zampini } else if (ismpibaij) { 1089566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(PT,&Pd,&Po,&garray)); 1099566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(PT,&bs)); 11098921bdaSJacob Faibussowitsch } else SETERRQ(comm,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(PT))->type_name); 11175d48cdbSStefano Zampini 11275d48cdbSStefano Zampini /* identify any null columns in Pd or Po */ 11322f7620eSStefano Zampini /* We use a tolerance comparison since it may happen that, with geometric multigrid, 11422f7620eSStefano Zampini some of the columns are not really zero, but very close to */ 11575d48cdbSStefano Zampini zo = zd = NULL; 11675d48cdbSStefano Zampini if (Po) { 1179566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(Po,PETSC_TRUE,PETSC_SMALL,&zo)); 11875d48cdbSStefano Zampini } 1199566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(Pd,PETSC_TRUE,PETSC_SMALL,&zd)); 12075d48cdbSStefano Zampini 1219566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(PT,NULL,&dc)); 1229566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(PT,&stc,NULL)); 1239566063dSJacob Faibussowitsch if (Po) PetscCall(MatGetLocalSize(Po,NULL,&oc)); 12475d48cdbSStefano Zampini else oc = 0; 1259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc+oc)/bs,&aux)); 12675d48cdbSStefano Zampini if (zd) { 12775d48cdbSStefano Zampini const PetscInt *idxs; 12875d48cdbSStefano Zampini PetscInt nz; 12975d48cdbSStefano Zampini 13075d48cdbSStefano Zampini /* this will throw an error if bs is not valid */ 1319566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(zd,bs)); 1329566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zd,&nz)); 1339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zd,&idxs)); 13475d48cdbSStefano Zampini ctd = nz/bs; 13575d48cdbSStefano Zampini for (i=0; i<ctd; i++) aux[i] = (idxs[bs*i]+stc)/bs; 1369566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zd,&idxs)); 13775d48cdbSStefano Zampini } else { 13875d48cdbSStefano Zampini ctd = dc/bs; 13975d48cdbSStefano Zampini for (i=0; i<ctd; i++) aux[i] = i+stc/bs; 14075d48cdbSStefano Zampini } 14175d48cdbSStefano Zampini if (zo) { 14275d48cdbSStefano Zampini const PetscInt *idxs; 14375d48cdbSStefano Zampini PetscInt nz; 14475d48cdbSStefano Zampini 14575d48cdbSStefano Zampini /* this will throw an error if bs is not valid */ 1469566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(zo,bs)); 1479566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zo,&nz)); 1489566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zo,&idxs)); 14975d48cdbSStefano Zampini cto = nz/bs; 15075d48cdbSStefano Zampini for (i=0; i<cto; i++) aux[i+ctd] = garray[idxs[bs*i]/bs]; 1519566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zo,&idxs)); 15275d48cdbSStefano Zampini } else { 15375d48cdbSStefano Zampini cto = oc/bs; 15475d48cdbSStefano Zampini for (i=0; i<cto; i++) aux[i+ctd] = garray[i]; 15575d48cdbSStefano Zampini } 1569566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,bs,ctd+cto,aux,PETSC_OWN_POINTER,cis)); 1579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zd)); 1589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zo)); 15975d48cdbSStefano Zampini PetscFunctionReturn(0); 16075d48cdbSStefano Zampini } 16175d48cdbSStefano Zampini 1624222ddf1SHong Zhang static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A,Mat P,PetscReal fill,Mat C) 16375d48cdbSStefano Zampini { 1648546b261SStefano Zampini Mat PT,lA; 16575d48cdbSStefano Zampini MatISPtAP ptap; 16675d48cdbSStefano Zampini ISLocalToGlobalMapping Crl2g,Ccl2g,rl2g,cl2g; 16775d48cdbSStefano Zampini PetscContainer c; 1688546b261SStefano Zampini MatType lmtype; 16975d48cdbSStefano Zampini const PetscInt *garray; 17075d48cdbSStefano Zampini PetscInt ibs,N,dc; 17175d48cdbSStefano Zampini MPI_Comm comm; 17275d48cdbSStefano Zampini 17375d48cdbSStefano Zampini PetscFunctionBegin; 1749566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A,&comm)); 1759566063dSJacob Faibussowitsch PetscCall(MatSetType(C,MATIS)); 1769566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A,&lA)); 1779566063dSJacob Faibussowitsch PetscCall(MatGetType(lA,&lmtype)); 1789566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(C,lmtype)); 1799566063dSJacob Faibussowitsch PetscCall(MatGetSize(P,NULL,&N)); 1809566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(P,NULL,&dc)); 1819566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,dc,dc,N,N)); 18275d48cdbSStefano Zampini /* Not sure about this 1839566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(P,NULL,&ibs)); 1849566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*C,ibs)); 18575d48cdbSStefano Zampini */ 18675d48cdbSStefano Zampini 1879566063dSJacob Faibussowitsch PetscCall(PetscNew(&ptap)); 1889566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF,&c)); 1899566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c,ptap)); 1909566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c,MatISContainerDestroyPtAP_Private)); 1919566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)C,"_MatIS_PtAP",(PetscObject)c)); 1929566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 19375d48cdbSStefano Zampini ptap->fill = fill; 19475d48cdbSStefano Zampini 1959566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A,&rl2g,&cl2g)); 19675d48cdbSStefano Zampini 1979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g,&ibs)); 1989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&N)); 1999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g,&garray)); 2009566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris0)); 2019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&garray)); 20275d48cdbSStefano Zampini 2039566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(P,ptap->ris0,NULL,MAT_INITIAL_MATRIX,&PT)); 2049566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis0)); 2059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis0,&Ccl2g)); 2069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&PT)); 20775d48cdbSStefano Zampini 20875d48cdbSStefano Zampini Crl2g = NULL; 20975d48cdbSStefano Zampini if (rl2g != cl2g) { /* unsymmetric A mapping */ 21075d48cdbSStefano Zampini PetscBool same,lsame = PETSC_FALSE; 21175d48cdbSStefano Zampini PetscInt N1,ibs1; 21275d48cdbSStefano Zampini 2139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&N1)); 2149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g,&ibs1)); 2159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g,&garray)); 2169566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris1)); 2179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&garray)); 21875d48cdbSStefano Zampini if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */ 21975d48cdbSStefano Zampini const PetscInt *i1,*i2; 22075d48cdbSStefano Zampini 2219566063dSJacob Faibussowitsch PetscCall(ISBlockGetIndices(ptap->ris0,&i1)); 2229566063dSJacob Faibussowitsch PetscCall(ISBlockGetIndices(ptap->ris1,&i2)); 2239566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(i1,i2,N,&lsame)); 22475d48cdbSStefano Zampini } 2251c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lsame,&same,1,MPIU_BOOL,MPI_LAND,comm)); 22675d48cdbSStefano Zampini if (same) { 2279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris1)); 22875d48cdbSStefano Zampini } else { 2299566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(P,ptap->ris1,NULL,MAT_INITIAL_MATRIX,&PT)); 2309566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis1)); 2319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis1,&Crl2g)); 2329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&PT)); 23375d48cdbSStefano Zampini } 23475d48cdbSStefano Zampini } 23575d48cdbSStefano Zampini /* Not sure about this 23675d48cdbSStefano Zampini if (!Crl2g) { 2379566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(C,&ibs)); 2389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs)); 23975d48cdbSStefano Zampini } 24075d48cdbSStefano Zampini */ 2419566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(C,Crl2g ? Crl2g : Ccl2g,Ccl2g)); 2429566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&Crl2g)); 2439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&Ccl2g)); 24475d48cdbSStefano Zampini 2454222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ; 24675d48cdbSStefano Zampini PetscFunctionReturn(0); 24775d48cdbSStefano Zampini } 24875d48cdbSStefano Zampini 2494222ddf1SHong Zhang /* ----------------------------------------- */ 2504222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_PtAP_IS_XAIJ(Mat C) 25175d48cdbSStefano Zampini { 2524222ddf1SHong Zhang Mat_Product *product = C->product; 2534222ddf1SHong Zhang Mat A=product->A,P=product->B; 2544222ddf1SHong Zhang PetscReal fill=product->fill; 25575d48cdbSStefano Zampini 25675d48cdbSStefano Zampini PetscFunctionBegin; 2579566063dSJacob Faibussowitsch PetscCall(MatPtAPSymbolic_IS_XAIJ(A,P,fill,C)); 2584222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 25975d48cdbSStefano Zampini PetscFunctionReturn(0); 26075d48cdbSStefano Zampini } 26175d48cdbSStefano Zampini 2624222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_IS_XAIJ_PtAP(Mat C) 2634222ddf1SHong Zhang { 2644222ddf1SHong Zhang PetscFunctionBegin; 2654222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_IS_XAIJ; 2664222ddf1SHong Zhang PetscFunctionReturn(0); 2674222ddf1SHong Zhang } 2684222ddf1SHong Zhang 2694222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat C) 2704222ddf1SHong Zhang { 2714222ddf1SHong Zhang Mat_Product *product = C->product; 2724222ddf1SHong Zhang 2734222ddf1SHong Zhang PetscFunctionBegin; 2744222ddf1SHong Zhang if (product->type == MATPRODUCT_PtAP) { 2759566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions_IS_XAIJ_PtAP(C)); 2766718818eSStefano Zampini } 2774222ddf1SHong Zhang PetscFunctionReturn(0); 2784222ddf1SHong Zhang } 2794222ddf1SHong Zhang 2804222ddf1SHong Zhang /* ----------------------------------------- */ 2815b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr) 2825b003df0Sstefano_zampini { 2835b003df0Sstefano_zampini MatISLocalFields lf = (MatISLocalFields)ptr; 2845b003df0Sstefano_zampini PetscInt i; 2855b003df0Sstefano_zampini 286ab4d48faSStefano Zampini PetscFunctionBegin; 2875b003df0Sstefano_zampini for (i=0;i<lf->nr;i++) { 2889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&lf->rf[i])); 2895b003df0Sstefano_zampini } 2905b003df0Sstefano_zampini for (i=0;i<lf->nc;i++) { 2919566063dSJacob Faibussowitsch PetscCall(ISDestroy(&lf->cf[i])); 2925b003df0Sstefano_zampini } 2939566063dSJacob Faibussowitsch PetscCall(PetscFree2(lf->rf,lf->cf)); 2949566063dSJacob Faibussowitsch PetscCall(PetscFree(lf)); 2955b003df0Sstefano_zampini PetscFunctionReturn(0); 2965b003df0Sstefano_zampini } 297a72627d2SStefano Zampini 298c9225affSStefano Zampini static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat) 2996989cf23SStefano Zampini { 300c9225affSStefano Zampini Mat B,lB; 301c9225affSStefano Zampini 302c9225affSStefano Zampini PetscFunctionBegin; 303c9225affSStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 304c9225affSStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 305c9225affSStefano Zampini PetscInt bs; 306c9225affSStefano Zampini IS is; 307c9225affSStefano Zampini 3089566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A,&bs)); 3099566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->n/bs,0,1,&is)); 310c9225affSStefano Zampini if (bs > 1) { 311c9225affSStefano Zampini IS is2; 312c9225affSStefano Zampini PetscInt i,*aux; 313c9225affSStefano Zampini 3149566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is,&i)); 3159566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is,(const PetscInt**)&aux)); 3169566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2)); 3179566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is,(const PetscInt**)&aux)); 3189566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 319c9225affSStefano Zampini is = is2; 320c9225affSStefano Zampini } 3219566063dSJacob Faibussowitsch PetscCall(ISSetIdentity(is)); 3229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g)); 3239566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3249566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->n/bs,0,1,&is)); 325c9225affSStefano Zampini if (bs > 1) { 326c9225affSStefano Zampini IS is2; 327c9225affSStefano Zampini PetscInt i,*aux; 328c9225affSStefano Zampini 3299566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is,&i)); 3309566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is,(const PetscInt**)&aux)); 3319566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2)); 3329566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is,(const PetscInt**)&aux)); 3339566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 334c9225affSStefano Zampini is = is2; 335c9225affSStefano Zampini } 3369566063dSJacob Faibussowitsch PetscCall(ISSetIdentity(is)); 3379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g)); 3389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3399566063dSJacob Faibussowitsch PetscCall(MatCreateIS(PetscObjectComm((PetscObject)A),bs,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,rl2g,cl2g,&B)); 3409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 3419566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3429566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A,MAT_COPY_VALUES,&lB)); 343c9225affSStefano Zampini if (reuse == MAT_INITIAL_MATRIX) *newmat = B; 344c9225affSStefano Zampini } else { 345c9225affSStefano Zampini B = *newmat; 3469566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 347c9225affSStefano Zampini lB = A; 348c9225affSStefano Zampini } 3499566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B,lB)); 3509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lB)); 3519566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 3529566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 353c9225affSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 3549566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&B)); 355c9225affSStefano Zampini } 356c9225affSStefano Zampini PetscFunctionReturn(0); 357c9225affSStefano Zampini } 358c9225affSStefano Zampini 359c9225affSStefano Zampini static PetscErrorCode MatISScaleDisassembling_Private(Mat A) 360c9225affSStefano Zampini { 361c9225affSStefano Zampini Mat_IS *matis = (Mat_IS*)(A->data); 362c9225affSStefano Zampini PetscScalar *aa; 363c9225affSStefano Zampini const PetscInt *ii,*jj; 364c9225affSStefano Zampini PetscInt i,n,m; 365fabe8965SStefano Zampini PetscInt *ecount,**eneighs; 366c9225affSStefano Zampini PetscBool flg; 367c9225affSStefano Zampini 368c9225affSStefano Zampini PetscFunctionBegin; 3699566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg)); 37008401ef6SPierre Jolivet PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure"); 3719566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(matis->rmapping,&n,&ecount,&eneighs)); 37208401ef6SPierre Jolivet PetscCheck(m == n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %" PetscInt_FMT " != %" PetscInt_FMT,m,n); 3739566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(matis->A,&aa)); 374c9225affSStefano Zampini for (i=0;i<n;i++) { 375fabe8965SStefano Zampini if (ecount[i] > 1) { 376c9225affSStefano Zampini PetscInt j; 377c9225affSStefano Zampini 378c9225affSStefano Zampini for (j=ii[i];j<ii[i+1];j++) { 379c9225affSStefano Zampini PetscInt i2 = jj[j],p,p2; 380fabe8965SStefano Zampini PetscReal scal = 0.0; 381c9225affSStefano Zampini 382c9225affSStefano Zampini for (p=0;p<ecount[i];p++) { 383c9225affSStefano Zampini for (p2=0;p2<ecount[i2];p2++) { 384c9225affSStefano Zampini if (eneighs[i][p] == eneighs[i2][p2]) { scal += 1.0; break; } 385c9225affSStefano Zampini } 386c9225affSStefano Zampini } 387fabe8965SStefano Zampini if (scal) aa[j] /= scal; 388c9225affSStefano Zampini } 389c9225affSStefano Zampini } 390c9225affSStefano Zampini } 3919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(matis->rmapping,&n,&ecount,&eneighs)); 3929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(matis->A,&aa)); 3939566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg)); 39408401ef6SPierre Jolivet PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure"); 395c9225affSStefano Zampini PetscFunctionReturn(0); 396c9225affSStefano Zampini } 397c9225affSStefano Zampini 398fabe8965SStefano Zampini typedef enum {MAT_IS_DISASSEMBLE_L2G_NATURAL,MAT_IS_DISASSEMBLE_L2G_MAT, MAT_IS_DISASSEMBLE_L2G_ND} MatISDisassemblel2gType; 399fabe8965SStefano Zampini 400c9225affSStefano Zampini static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g) 401c9225affSStefano Zampini { 402fabe8965SStefano Zampini Mat Ad,Ao; 403fabe8965SStefano Zampini IS is,ndmap,ndsub; 404c9225affSStefano Zampini MPI_Comm comm; 405fabe8965SStefano Zampini const PetscInt *garray,*ndmapi; 406fabe8965SStefano Zampini PetscInt bs,i,cnt,nl,*ncount,*ndmapc; 407fabe8965SStefano Zampini PetscBool ismpiaij,ismpibaij; 408f4259b30SLisandro Dalcin const char *const MatISDisassemblel2gTypes[] = {"NATURAL","MAT","ND","MatISDisassemblel2gType","MAT_IS_DISASSEMBLE_L2G_",NULL}; 409fabe8965SStefano Zampini MatISDisassemblel2gType mode = MAT_IS_DISASSEMBLE_L2G_NATURAL; 410fabe8965SStefano Zampini MatPartitioning part; 411fabe8965SStefano Zampini PetscSF sf; 41291d376acSStefano Zampini PetscObject dm; 413c9225affSStefano Zampini 414c9225affSStefano Zampini PetscFunctionBegin; 415d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"MatIS l2g disassembling options","Mat"); 4169566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-mat_is_disassemble_l2g_type","Type of local-to-global mapping to be used for disassembling","MatISDisassemblel2gType",MatISDisassemblel2gTypes,(PetscEnum)mode,(PetscEnum*)&mode,NULL)); 417d0609cedSBarry Smith PetscOptionsEnd(); 418fabe8965SStefano Zampini if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) { 4199566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A,l2g,NULL)); 420c9225affSStefano Zampini PetscFunctionReturn(0); 421c9225affSStefano Zampini } 4229566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A,&comm)); 4239566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij)); 4249566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij)); 4259566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A,&bs)); 426fabe8965SStefano Zampini switch (mode) { 427fabe8965SStefano Zampini case MAT_IS_DISASSEMBLE_L2G_ND: 4289566063dSJacob Faibussowitsch PetscCall(MatPartitioningCreate(comm,&part)); 4299566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetAdjacency(part,A)); 4309566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)part,((PetscObject)A)->prefix)); 4319566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetFromOptions(part)); 4329566063dSJacob Faibussowitsch PetscCall(MatPartitioningApplyND(part,&ndmap)); 4339566063dSJacob Faibussowitsch PetscCall(MatPartitioningDestroy(&part)); 4349566063dSJacob Faibussowitsch PetscCall(ISBuildTwoSided(ndmap,NULL,&ndsub)); 4359566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetUseScalableIncreaseOverlap(A,PETSC_TRUE)); 4369566063dSJacob Faibussowitsch PetscCall(MatIncreaseOverlap(A,1,&ndsub,1)); 4379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ndsub,l2g)); 438fabe8965SStefano Zampini 439fabe8965SStefano Zampini /* it may happen that a separator node is not properly shared */ 4409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(*l2g,&nl,&ncount,NULL)); 4419566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,&sf)); 4429566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(*l2g,&garray)); 4439566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(sf,A->rmap,nl,NULL,PETSC_OWN_POINTER,garray)); 4449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(*l2g,&garray)); 4459566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n,&ndmapc)); 4469566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sf,MPIU_INT,ncount,ndmapc,MPI_REPLACE)); 4479566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sf,MPIU_INT,ncount,ndmapc,MPI_REPLACE)); 4489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(*l2g,NULL,&ncount,NULL)); 4499566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ndmap,&ndmapi)); 450fabe8965SStefano Zampini for (i = 0, cnt = 0; i < A->rmap->n; i++) 451fabe8965SStefano Zampini if (ndmapi[i] < 0 && ndmapc[i] < 2) 452fabe8965SStefano Zampini cnt++; 453fabe8965SStefano Zampini 4541c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&cnt,&i,1,MPIU_INT,MPI_MAX,comm)); 455fabe8965SStefano Zampini if (i) { /* we detected isolated separator nodes */ 456fabe8965SStefano Zampini Mat A2,A3; 457fabe8965SStefano Zampini IS *workis,is2; 458fabe8965SStefano Zampini PetscScalar *vals; 459fabe8965SStefano Zampini PetscInt gcnt = i,*dnz,*onz,j,*lndmapi; 460fabe8965SStefano Zampini ISLocalToGlobalMapping ll2g; 461fabe8965SStefano Zampini PetscBool flg; 462fabe8965SStefano Zampini const PetscInt *ii,*jj; 463fabe8965SStefano Zampini 464fabe8965SStefano Zampini /* communicate global id of separators */ 465d0609cedSBarry Smith MatPreallocateBegin(comm,A->rmap->n,A->cmap->n,dnz,onz); 466fabe8965SStefano Zampini for (i = 0, cnt = 0; i < A->rmap->n; i++) 467fabe8965SStefano Zampini dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1; 468fabe8965SStefano Zampini 4699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl,&lndmapi)); 4709566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf,MPIU_INT,dnz,lndmapi,MPI_REPLACE)); 471fabe8965SStefano Zampini 472fabe8965SStefano Zampini /* compute adjacency of isolated separators node */ 4739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gcnt,&workis)); 474fabe8965SStefano Zampini for (i = 0, cnt = 0; i < A->rmap->n; i++) { 475fabe8965SStefano Zampini if (ndmapi[i] < 0 && ndmapc[i] < 2) { 4769566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm,1,i+A->rmap->rstart,1,&workis[cnt++])); 477fabe8965SStefano Zampini } 478fabe8965SStefano Zampini } 479fabe8965SStefano Zampini for (i = cnt; i < gcnt; i++) { 4809566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm,0,0,1,&workis[i])); 481fabe8965SStefano Zampini } 482fabe8965SStefano Zampini for (i = 0; i < gcnt; i++) { 4839566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)workis[i],"ISOLATED")); 4849566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(workis[i],NULL,"-view_isolated_separators")); 485fabe8965SStefano Zampini } 486fabe8965SStefano Zampini 487fabe8965SStefano Zampini /* no communications since all the ISes correspond to locally owned rows */ 4889566063dSJacob Faibussowitsch PetscCall(MatIncreaseOverlap(A,gcnt,workis,1)); 489fabe8965SStefano Zampini 490fabe8965SStefano Zampini /* end communicate global id of separators */ 4919566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf,MPIU_INT,dnz,lndmapi,MPI_REPLACE)); 492fabe8965SStefano Zampini 493fabe8965SStefano Zampini /* communicate new layers : create a matrix and transpose it */ 4949566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(dnz,A->rmap->n)); 4959566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(onz,A->rmap->n)); 496fabe8965SStefano Zampini for (i = 0, j = 0; i < A->rmap->n; i++) { 497fabe8965SStefano Zampini if (ndmapi[i] < 0 && ndmapc[i] < 2) { 498fabe8965SStefano Zampini const PetscInt* idxs; 499fabe8965SStefano Zampini PetscInt s; 500fabe8965SStefano Zampini 5019566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(workis[j],&s)); 5029566063dSJacob Faibussowitsch PetscCall(ISGetIndices(workis[j],&idxs)); 5039566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(i+A->rmap->rstart,s,idxs,dnz,onz)); 504fabe8965SStefano Zampini j++; 505fabe8965SStefano Zampini } 506fabe8965SStefano Zampini } 50708401ef6SPierre Jolivet PetscCheck(j == cnt,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT,j,cnt); 508fabe8965SStefano Zampini 509fabe8965SStefano Zampini for (i = 0; i < gcnt; i++) { 5109566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)workis[i],"EXTENDED")); 5119566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(workis[i],NULL,"-view_isolated_separators")); 512fabe8965SStefano Zampini } 513fabe8965SStefano Zampini 514fabe8965SStefano Zampini for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j,dnz[i]+onz[i]); 5159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(j,&vals)); 516fabe8965SStefano Zampini for (i = 0; i < j; i++) vals[i] = 1.0; 517fabe8965SStefano Zampini 5189566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&A2)); 5199566063dSJacob Faibussowitsch PetscCall(MatSetType(A2,MATMPIAIJ)); 5209566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A2,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N)); 5219566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(A2,0,dnz,0,onz)); 5229566063dSJacob Faibussowitsch PetscCall(MatSetOption(A2,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE)); 523fabe8965SStefano Zampini for (i = 0, j = 0; i < A2->rmap->n; i++) { 524fabe8965SStefano Zampini PetscInt row = i+A2->rmap->rstart,s = dnz[i] + onz[i]; 525fabe8965SStefano Zampini const PetscInt* idxs; 526fabe8965SStefano Zampini 527fabe8965SStefano Zampini if (s) { 5289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(workis[j],&idxs)); 5299566063dSJacob Faibussowitsch PetscCall(MatSetValues(A2,1,&row,s,idxs,vals,INSERT_VALUES)); 5309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(workis[j],&idxs)); 531fabe8965SStefano Zampini j++; 532fabe8965SStefano Zampini } 533fabe8965SStefano Zampini } 53408401ef6SPierre Jolivet PetscCheck(j == cnt,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT,j,cnt); 5359566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 5369566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A2,MAT_FINAL_ASSEMBLY)); 5379566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A2,MAT_FINAL_ASSEMBLY)); 5389566063dSJacob Faibussowitsch PetscCall(MatTranspose(A2,MAT_INPLACE_MATRIX,&A2)); 539fabe8965SStefano Zampini 540fabe8965SStefano Zampini /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */ 541fabe8965SStefano Zampini for (i = 0, j = 0; i < nl; i++) 542fabe8965SStefano Zampini if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i]; 5439566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,j,lndmapi,PETSC_USE_POINTER,&is)); 5449566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetLocalMatCondensed(A2,MAT_INITIAL_MATRIX,&is,NULL,&A3)); 5459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 5469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A2)); 547fabe8965SStefano Zampini 548fabe8965SStefano Zampini /* extend local to global map to include connected isolated separators */ 5499566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A3,"_petsc_GetLocalMatCondensed_iscol",(PetscObject*)&is)); 55028b400f6SJacob Faibussowitsch PetscCheck(is,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing column map"); 5519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&ll2g)); 5529566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg)); 55328b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure"); 5549566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,ii[i],jj,PETSC_COPY_VALUES,&is)); 5559566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg)); 55628b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure"); 5579566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(ll2g,is,&is2)); 5589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 5599566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&ll2g)); 560fabe8965SStefano Zampini 561fabe8965SStefano Zampini /* add new nodes to the local-to-global map */ 5629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(l2g)); 5639566063dSJacob Faibussowitsch PetscCall(ISExpand(ndsub,is2,&is)); 5649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is2)); 5659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,l2g)); 5669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 567fabe8965SStefano Zampini 5689566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A3)); 5699566063dSJacob Faibussowitsch PetscCall(PetscFree(lndmapi)); 570d0609cedSBarry Smith MatPreallocateEnd(dnz,onz); 571fabe8965SStefano Zampini for (i = 0; i < gcnt; i++) { 5729566063dSJacob Faibussowitsch PetscCall(ISDestroy(&workis[i])); 573fabe8965SStefano Zampini } 5749566063dSJacob Faibussowitsch PetscCall(PetscFree(workis)); 575fabe8965SStefano Zampini } 5769566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ndmap,&ndmapi)); 5779566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 5789566063dSJacob Faibussowitsch PetscCall(PetscFree(ndmapc)); 5799566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ndmap)); 5809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ndsub)); 5819566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(*l2g,bs)); 5829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingViewFromOptions(*l2g,NULL,"-matis_nd_l2g_view")); 583fabe8965SStefano Zampini break; 584fabe8965SStefano Zampini case MAT_IS_DISASSEMBLE_L2G_NATURAL: 58591d376acSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)A,"__PETSc_dm",(PetscObject*)&dm)); 58691d376acSStefano Zampini if (dm) { /* if a matrix comes from a DM, most likely we can use the l2gmap if any */ 58791d376acSStefano Zampini PetscCall(MatGetLocalToGlobalMapping(A,l2g,NULL)); 58891d376acSStefano Zampini PetscCall(PetscObjectReference((PetscObject)*l2g)); 58991d376acSStefano Zampini if (*l2g) PetscFunctionReturn(0); 59091d376acSStefano Zampini } 591fabe8965SStefano Zampini if (ismpiaij) { 5929566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray)); 593fabe8965SStefano Zampini } else if (ismpibaij) { 5949566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray)); 59598921bdaSJacob Faibussowitsch } else SETERRQ(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name); 596c9225affSStefano Zampini if (A->rmap->n) { 597fabe8965SStefano Zampini PetscInt dc,oc,stc,*aux; 598c9225affSStefano Zampini 599ebf8cefbSJunchao Zhang PetscCall(MatGetLocalSize(Ad,NULL,&dc)); 6009566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Ao,NULL,&oc)); 601*d0dbe9f7SStefano Zampini PetscCheck(!oc || garray,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"garray not present"); 6029566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A,&stc,NULL)); 6039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc+oc)/bs,&aux)); 604c9225affSStefano Zampini for (i=0; i<dc/bs; i++) aux[i] = i+stc/bs; 605ebf8cefbSJunchao Zhang for (i=0; i<oc/bs; i++) aux[i+dc/bs] = (ismpiaij ? garray[i*bs]/bs : garray[i]); 6069566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is)); 607c9225affSStefano Zampini } else { 6089566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,1,0,NULL,PETSC_OWN_POINTER,&is)); 609c9225affSStefano Zampini } 6109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,l2g)); 6119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 612fabe8965SStefano Zampini break; 613fabe8965SStefano Zampini default: 61498921bdaSJacob Faibussowitsch SETERRQ(comm,PETSC_ERR_ARG_WRONG,"Unsupported l2g disassembling type %d",mode); 615c9225affSStefano Zampini } 616c9225affSStefano Zampini PetscFunctionReturn(0); 617c9225affSStefano Zampini } 618c9225affSStefano Zampini 619c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat) 620c9225affSStefano Zampini { 621c9225affSStefano Zampini Mat lA,Ad,Ao,B = NULL; 6226989cf23SStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 6236989cf23SStefano Zampini IS is; 6246989cf23SStefano Zampini MPI_Comm comm; 6256989cf23SStefano Zampini void *ptrs[2]; 6266989cf23SStefano Zampini const char *names[2] = {"_convert_csr_aux","_convert_csr_data"}; 627c9225affSStefano Zampini const PetscInt *garray; 6286989cf23SStefano Zampini PetscScalar *dd,*od,*aa,*data; 629c9225affSStefano Zampini const PetscInt *di,*dj,*oi,*oj; 630c9225affSStefano Zampini const PetscInt *odi,*odj,*ooi,*ooj; 6316989cf23SStefano Zampini PetscInt *aux,*ii,*jj; 632c9225affSStefano Zampini PetscInt bs,lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum; 633c9225affSStefano Zampini PetscBool flg,ismpiaij,ismpibaij,was_inplace = PETSC_FALSE; 634c9225affSStefano Zampini PetscMPIInt size; 6356989cf23SStefano Zampini 636ab4d48faSStefano Zampini PetscFunctionBegin; 6379566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A,&comm)); 6389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm,&size)); 639c9225affSStefano Zampini if (size == 1) { 6409566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqXAIJ_IS(A,type,reuse,newmat)); 641c9225affSStefano Zampini PetscFunctionReturn(0); 642c9225affSStefano Zampini } 643c9225affSStefano Zampini if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) { 6449566063dSJacob Faibussowitsch PetscCall(MatMPIXAIJComputeLocalToGlobalMapping_Private(A,&rl2g)); 6459566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&B)); 6469566063dSJacob Faibussowitsch PetscCall(MatSetType(B,MATIS)); 6479566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N)); 6489566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B,rl2g,rl2g)); 6499566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A,&bs)); 6509566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B,bs)); 6519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 652c9225affSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE; 653c9225affSStefano Zampini reuse = MAT_REUSE_MATRIX; 654c9225affSStefano Zampini } 655c9225affSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 656c9225affSStefano Zampini Mat *newlA, lA; 657c9225affSStefano Zampini IS rows, cols; 658c9225affSStefano Zampini const PetscInt *ridx, *cidx; 659c9225affSStefano Zampini PetscInt rbs, cbs, nr, nc; 660c9225affSStefano Zampini 661c9225affSStefano Zampini if (!B) B = *newmat; 6629566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(B,&rl2g,&cl2g)); 6639566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g,&ridx)); 6649566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g,&cidx)); 6659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&nr)); 6669566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&nc)); 6679566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g,&rbs)); 6689566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g,&cbs)); 6699566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,rbs,nr/rbs,ridx,PETSC_USE_POINTER,&rows)); 670c9225affSStefano Zampini if (rl2g != cl2g) { 6719566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,cbs,nc/cbs,cidx,PETSC_USE_POINTER,&cols)); 672c9225affSStefano Zampini } else { 6739566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rows)); 674c9225affSStefano Zampini cols = rows; 675c9225affSStefano Zampini } 6769566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(B,&lA)); 6779566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A,1,&rows,&cols,MAT_INITIAL_MATRIX,&newlA)); 6789566063dSJacob Faibussowitsch PetscCall(MatConvert(newlA[0],MATSEQAIJ,MAT_INPLACE_MATRIX,&newlA[0])); 6799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&ridx)); 6809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&cidx)); 6819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 6829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 683c9225affSStefano Zampini if (!lA->preallocated) { /* first time */ 6849566063dSJacob Faibussowitsch PetscCall(MatDuplicate(newlA[0],MAT_COPY_VALUES,&lA)); 6859566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B,lA)); 6869566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)lA)); 687c9225affSStefano Zampini } 6889566063dSJacob Faibussowitsch PetscCall(MatCopy(newlA[0],lA,SAME_NONZERO_PATTERN)); 6899566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices(1,&newlA)); 6909566063dSJacob Faibussowitsch PetscCall(MatISScaleDisassembling_Private(B)); 6919566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 6929566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 6939566063dSJacob Faibussowitsch if (was_inplace) PetscCall(MatHeaderReplace(A,&B)); 694c9225affSStefano Zampini else *newmat = B; 695c9225affSStefano Zampini PetscFunctionReturn(0); 696c9225affSStefano Zampini } 697c9225affSStefano Zampini /* rectangular case, just compress out the column space */ 6989566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij)); 6999566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij)); 700c9225affSStefano Zampini if (ismpiaij) { 701c9225affSStefano Zampini bs = 1; 7029566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray)); 703c9225affSStefano Zampini } else if (ismpibaij) { 7049566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A,&bs)); 7059566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray)); 7069566063dSJacob Faibussowitsch PetscCall(MatConvert(Ad,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ad)); 7079566063dSJacob Faibussowitsch PetscCall(MatConvert(Ao,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ao)); 70898921bdaSJacob Faibussowitsch } else SETERRQ(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name); 7099566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Ad,&dd)); 7109566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Ao,&od)); 71128b400f6SJacob Faibussowitsch PetscCheck(garray,comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present"); 7126989cf23SStefano Zampini 7136989cf23SStefano Zampini /* access relevant information from MPIAIJ */ 7149566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A,&str,NULL)); 7159566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A,&stc,NULL)); 7169566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,&dr,&dc)); 7179566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Ao,NULL,&oc)); 7189566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&di,&dj,&flg)); 71928b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure"); 7209566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&oi,&oj,&flg)); 72128b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure"); 722c9225affSStefano Zampini nnz = di[dr] + oi[dr]; 723c9225affSStefano Zampini /* store original pointers to be restored later */ 724c9225affSStefano Zampini odi = di; odj = dj; ooi = oi; ooj = oj; 7256989cf23SStefano Zampini 7266989cf23SStefano Zampini /* generate l2g maps for rows and cols */ 7279566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm,dr/bs,str/bs,1,&is)); 728c9225affSStefano Zampini if (bs > 1) { 729c9225affSStefano Zampini IS is2; 730c9225affSStefano Zampini 7319566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is,&i)); 7329566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is,(const PetscInt**)&aux)); 7339566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,bs,i,aux,PETSC_COPY_VALUES,&is2)); 7349566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is,(const PetscInt**)&aux)); 7359566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 736c9225affSStefano Zampini is = is2; 737c9225affSStefano Zampini } 7389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g)); 7399566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 740e363d98aSStefano Zampini if (dr) { 7419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc+oc)/bs,&aux)); 742c9225affSStefano Zampini for (i=0; i<dc/bs; i++) aux[i] = i+stc/bs; 743c9225affSStefano Zampini for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i]; 7449566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is)); 745e363d98aSStefano Zampini lc = dc+oc; 746e363d98aSStefano Zampini } else { 7479566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,bs,0,NULL,PETSC_OWN_POINTER,&is)); 748e363d98aSStefano Zampini lc = 0; 749e363d98aSStefano Zampini } 7509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g)); 7519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 7526989cf23SStefano Zampini 7536989cf23SStefano Zampini /* create MATIS object */ 7549566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&B)); 7559566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B,dr,dc,PETSC_DECIDE,PETSC_DECIDE)); 7569566063dSJacob Faibussowitsch PetscCall(MatSetType(B,MATIS)); 7579566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B,bs)); 7589566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B,rl2g,cl2g)); 7599566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 7609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 7616989cf23SStefano Zampini 7626989cf23SStefano Zampini /* merge local matrices */ 7639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz+dr+1,&aux)); 7649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz,&data)); 7656989cf23SStefano Zampini ii = aux; 7666989cf23SStefano Zampini jj = aux+dr+1; 7676989cf23SStefano Zampini aa = data; 7686989cf23SStefano Zampini *ii = *(di++) + *(oi++); 7696989cf23SStefano Zampini for (jd=0,jo=0,cum=0;*ii<nnz;cum++) 7706989cf23SStefano Zampini { 7716989cf23SStefano Zampini for (;jd<*di;jd++) { *jj++ = *dj++; *aa++ = *dd++; } 7726989cf23SStefano Zampini for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; } 7736989cf23SStefano Zampini *(++ii) = *(di++) + *(oi++); 7746989cf23SStefano Zampini } 7756989cf23SStefano Zampini for (;cum<dr;cum++) *(++ii) = nnz; 776c9225affSStefano Zampini 7779566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&odi,&odj,&flg)); 77828b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure"); 7799566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&ooi,&ooj,&flg)); 78028b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure"); 7819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Ad,&dd)); 7829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Ao,&od)); 783c9225affSStefano Zampini 7846989cf23SStefano Zampini ii = aux; 7856989cf23SStefano Zampini jj = aux+dr+1; 7866989cf23SStefano Zampini aa = data; 7879566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA)); 7886989cf23SStefano Zampini 7896989cf23SStefano Zampini /* create containers to destroy the data */ 7906989cf23SStefano Zampini ptrs[0] = aux; 7916989cf23SStefano Zampini ptrs[1] = data; 7926989cf23SStefano Zampini for (i=0; i<2; i++) { 7936989cf23SStefano Zampini PetscContainer c; 7946989cf23SStefano Zampini 7959566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF,&c)); 7969566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c,ptrs[i])); 7979566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault)); 7989566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c)); 7999566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 8006989cf23SStefano Zampini } 801c9225affSStefano Zampini if (ismpibaij) { /* destroy converted local matrices */ 8029566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ad)); 8039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ao)); 804c9225affSStefano Zampini } 8056989cf23SStefano Zampini 8066989cf23SStefano Zampini /* finalize matrix */ 8079566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B,lA)); 8089566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 8099566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 8109566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 811c9225affSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 8129566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&B)); 813c9225affSStefano Zampini } else *newmat = B; 8146989cf23SStefano Zampini PetscFunctionReturn(0); 8156989cf23SStefano Zampini } 8166989cf23SStefano Zampini 8175e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat) 8185e3038f0Sstefano_zampini { 8195e3038f0Sstefano_zampini Mat **nest,*snest,**rnest,lA,B; 8205e3038f0Sstefano_zampini IS *iscol,*isrow,*islrow,*islcol; 8215e3038f0Sstefano_zampini ISLocalToGlobalMapping rl2g,cl2g; 8225e3038f0Sstefano_zampini MPI_Comm comm; 8235b003df0Sstefano_zampini PetscInt *lr,*lc,*l2gidxs; 8245b003df0Sstefano_zampini PetscInt i,j,nr,nc,rbs,cbs; 8259e7b2b25Sstefano_zampini PetscBool convert,lreuse,*istrans; 8265e3038f0Sstefano_zampini 827ab4d48faSStefano Zampini PetscFunctionBegin; 8289566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(A,&nr,&nc,&nest)); 8295e3038f0Sstefano_zampini lreuse = PETSC_FALSE; 8305e3038f0Sstefano_zampini rnest = NULL; 8315e3038f0Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 8325e3038f0Sstefano_zampini PetscBool ismatis,isnest; 8335e3038f0Sstefano_zampini 8349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis)); 83528b400f6SJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type_name); 8369566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat,&lA)); 8379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest)); 8385e3038f0Sstefano_zampini if (isnest) { 8399566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(lA,&i,&j,&rnest)); 8405e3038f0Sstefano_zampini lreuse = (PetscBool)(i == nr && j == nc); 8415e3038f0Sstefano_zampini if (!lreuse) rnest = NULL; 8425e3038f0Sstefano_zampini } 8435e3038f0Sstefano_zampini } 8449566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A,&comm)); 8459566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nr,&lr,nc,&lc)); 8469566063dSJacob Faibussowitsch PetscCall(PetscCalloc6(nr,&isrow,nc,&iscol,nr,&islrow,nc,&islcol,nr*nc,&snest,nr*nc,&istrans)); 8479566063dSJacob Faibussowitsch PetscCall(MatNestGetISs(A,isrow,iscol)); 8485e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 8495e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 8505e3038f0Sstefano_zampini PetscBool ismatis; 8519e7b2b25Sstefano_zampini PetscInt l1,l2,lb1,lb2,ij=i*nc+j; 8525e3038f0Sstefano_zampini 8535e3038f0Sstefano_zampini /* Null matrix pointers are allowed in MATNEST */ 8545e3038f0Sstefano_zampini if (!nest[i][j]) continue; 8555e3038f0Sstefano_zampini 8565e3038f0Sstefano_zampini /* Nested matrices should be of type MATIS */ 8579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij])); 8589e7b2b25Sstefano_zampini if (istrans[ij]) { 8599e7b2b25Sstefano_zampini Mat T,lT; 8609566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[i][j],&T)); 8619566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis)); 86228b400f6SJacob Faibussowitsch PetscCheck(ismatis,comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") (transposed) is not of type MATIS",i,j); 8639566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(T,&lT)); 8649566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(lT,&snest[ij])); 8659e7b2b25Sstefano_zampini } else { 8669566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis)); 86728b400f6SJacob Faibussowitsch PetscCheck(ismatis,comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") is not of type MATIS",i,j); 8689566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(nest[i][j],&snest[ij])); 8699e7b2b25Sstefano_zampini } 8705e3038f0Sstefano_zampini 8715e3038f0Sstefano_zampini /* Check compatibility of local sizes */ 8729566063dSJacob Faibussowitsch PetscCall(MatGetSize(snest[ij],&l1,&l2)); 8739566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(snest[ij],&lb1,&lb2)); 8745e3038f0Sstefano_zampini if (!l1 || !l2) continue; 875aed4548fSBarry Smith PetscCheck(!lr[i] || l1 == lr[i],PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid local size %" PetscInt_FMT " != %" PetscInt_FMT,i,j,lr[i],l1); 876aed4548fSBarry Smith PetscCheck(!lc[j] || l2 == lc[j],PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid local size %" PetscInt_FMT " != %" PetscInt_FMT,i,j,lc[j],l2); 8775e3038f0Sstefano_zampini lr[i] = l1; 8785e3038f0Sstefano_zampini lc[j] = l2; 8795e3038f0Sstefano_zampini 8805e3038f0Sstefano_zampini /* check compatibilty for local matrix reusage */ 8815e3038f0Sstefano_zampini if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE; 8825e3038f0Sstefano_zampini } 8835e3038f0Sstefano_zampini } 8845e3038f0Sstefano_zampini 88576bd3646SJed Brown if (PetscDefined (USE_DEBUG)) { 8865e3038f0Sstefano_zampini /* Check compatibility of l2g maps for rows */ 8875e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 8885e3038f0Sstefano_zampini rl2g = NULL; 8895e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 8905e3038f0Sstefano_zampini PetscInt n1,n2; 8915e3038f0Sstefano_zampini 8925e3038f0Sstefano_zampini if (!nest[i][j]) continue; 8939e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 8949e7b2b25Sstefano_zampini Mat T; 8959e7b2b25Sstefano_zampini 8969566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[i][j],&T)); 8979566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(T,NULL,&cl2g)); 8989e7b2b25Sstefano_zampini } else { 8999566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL)); 9009e7b2b25Sstefano_zampini } 9019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&n1)); 9025e3038f0Sstefano_zampini if (!n1) continue; 9035e3038f0Sstefano_zampini if (!rl2g) { 9045e3038f0Sstefano_zampini rl2g = cl2g; 9055e3038f0Sstefano_zampini } else { 9065e3038f0Sstefano_zampini const PetscInt *idxs1,*idxs2; 9075e3038f0Sstefano_zampini PetscBool same; 9085e3038f0Sstefano_zampini 9099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&n2)); 91008401ef6SPierre Jolivet PetscCheck(n1 == n2,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid row l2gmap size %" PetscInt_FMT " != %" PetscInt_FMT,i,j,n1,n2); 9119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(cl2g,&idxs1)); 9129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(rl2g,&idxs2)); 9139566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1,idxs2,n1,&same)); 9149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1)); 9159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2)); 91628b400f6SJacob Faibussowitsch PetscCheck(same,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid row l2gmap",i,j); 9175e3038f0Sstefano_zampini } 9185e3038f0Sstefano_zampini } 9195e3038f0Sstefano_zampini } 9205e3038f0Sstefano_zampini /* Check compatibility of l2g maps for columns */ 9215e3038f0Sstefano_zampini for (i=0;i<nc;i++) { 9225e3038f0Sstefano_zampini rl2g = NULL; 9235e3038f0Sstefano_zampini for (j=0;j<nr;j++) { 9245e3038f0Sstefano_zampini PetscInt n1,n2; 9255e3038f0Sstefano_zampini 9265e3038f0Sstefano_zampini if (!nest[j][i]) continue; 9279e7b2b25Sstefano_zampini if (istrans[j*nc+i]) { 9289e7b2b25Sstefano_zampini Mat T; 9299e7b2b25Sstefano_zampini 9309566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[j][i],&T)); 9319566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(T,&cl2g,NULL)); 9329e7b2b25Sstefano_zampini } else { 9339566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g)); 9349e7b2b25Sstefano_zampini } 9359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&n1)); 9365e3038f0Sstefano_zampini if (!n1) continue; 9375e3038f0Sstefano_zampini if (!rl2g) { 9385e3038f0Sstefano_zampini rl2g = cl2g; 9395e3038f0Sstefano_zampini } else { 9405e3038f0Sstefano_zampini const PetscInt *idxs1,*idxs2; 9415e3038f0Sstefano_zampini PetscBool same; 9425e3038f0Sstefano_zampini 9439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&n2)); 94408401ef6SPierre Jolivet PetscCheck(n1 == n2,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid column l2gmap size %" PetscInt_FMT " != %" PetscInt_FMT,j,i,n1,n2); 9459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(cl2g,&idxs1)); 9469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(rl2g,&idxs2)); 9479566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1,idxs2,n1,&same)); 9489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1)); 9499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2)); 95028b400f6SJacob Faibussowitsch PetscCheck(same,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid column l2gmap",j,i); 9515e3038f0Sstefano_zampini } 9525e3038f0Sstefano_zampini } 9535e3038f0Sstefano_zampini } 95476bd3646SJed Brown } 9555e3038f0Sstefano_zampini 9565e3038f0Sstefano_zampini B = NULL; 9575e3038f0Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 9585b003df0Sstefano_zampini PetscInt stl; 9595b003df0Sstefano_zampini 9605e3038f0Sstefano_zampini /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */ 9615e3038f0Sstefano_zampini for (i=0,stl=0;i<nr;i++) stl += lr[i]; 9629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stl,&l2gidxs)); 9635b003df0Sstefano_zampini for (i=0,stl=0;i<nr;i++) { 9645e3038f0Sstefano_zampini Mat usedmat; 9655e3038f0Sstefano_zampini Mat_IS *matis; 9665e3038f0Sstefano_zampini const PetscInt *idxs; 9675e3038f0Sstefano_zampini 9685e3038f0Sstefano_zampini /* local IS for local NEST */ 9699566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i])); 9705e3038f0Sstefano_zampini 9715e3038f0Sstefano_zampini /* l2gmap */ 9725e3038f0Sstefano_zampini j = 0; 9735e3038f0Sstefano_zampini usedmat = nest[i][j]; 9749e7b2b25Sstefano_zampini while (!usedmat && j < nc-1) usedmat = nest[i][++j]; 97528b400f6SJacob Faibussowitsch PetscCheck(usedmat,comm,PETSC_ERR_SUP,"Cannot find valid row mat"); 9769e7b2b25Sstefano_zampini 9779e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 9789e7b2b25Sstefano_zampini Mat T; 9799566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(usedmat,&T)); 9809e7b2b25Sstefano_zampini usedmat = T; 9819e7b2b25Sstefano_zampini } 9825e3038f0Sstefano_zampini matis = (Mat_IS*)(usedmat->data); 9839566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow[i],&idxs)); 9849e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 9859566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 9869566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 9879e7b2b25Sstefano_zampini } else { 9889566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 9899566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 9909e7b2b25Sstefano_zampini } 9919566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow[i],&idxs)); 9925e3038f0Sstefano_zampini stl += lr[i]; 9935e3038f0Sstefano_zampini } 9949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g)); 9955e3038f0Sstefano_zampini 9965e3038f0Sstefano_zampini /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */ 9975e3038f0Sstefano_zampini for (i=0,stl=0;i<nc;i++) stl += lc[i]; 9989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stl,&l2gidxs)); 9995b003df0Sstefano_zampini for (i=0,stl=0;i<nc;i++) { 10005e3038f0Sstefano_zampini Mat usedmat; 10015e3038f0Sstefano_zampini Mat_IS *matis; 10025e3038f0Sstefano_zampini const PetscInt *idxs; 10035e3038f0Sstefano_zampini 10045e3038f0Sstefano_zampini /* local IS for local NEST */ 10059566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i])); 10065e3038f0Sstefano_zampini 10075e3038f0Sstefano_zampini /* l2gmap */ 10085e3038f0Sstefano_zampini j = 0; 10095e3038f0Sstefano_zampini usedmat = nest[j][i]; 10109e7b2b25Sstefano_zampini while (!usedmat && j < nr-1) usedmat = nest[++j][i]; 101128b400f6SJacob Faibussowitsch PetscCheck(usedmat,comm,PETSC_ERR_SUP,"Cannot find valid column mat"); 10129e7b2b25Sstefano_zampini if (istrans[j*nc+i]) { 10139e7b2b25Sstefano_zampini Mat T; 10149566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(usedmat,&T)); 10159e7b2b25Sstefano_zampini usedmat = T; 10169e7b2b25Sstefano_zampini } 10175e3038f0Sstefano_zampini matis = (Mat_IS*)(usedmat->data); 10189566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol[i],&idxs)); 10199e7b2b25Sstefano_zampini if (istrans[j*nc+i]) { 10209566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 10219566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 10229e7b2b25Sstefano_zampini } else { 10239566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 10249566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 10259e7b2b25Sstefano_zampini } 10269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol[i],&idxs)); 10275e3038f0Sstefano_zampini stl += lc[i]; 10285e3038f0Sstefano_zampini } 10299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g)); 10305e3038f0Sstefano_zampini 10315e3038f0Sstefano_zampini /* Create MATIS */ 10329566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&B)); 10339566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N)); 10349566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(A,&rbs,&cbs)); 10359566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B,rbs,cbs)); 10369566063dSJacob Faibussowitsch PetscCall(MatSetType(B,MATIS)); 10379566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B,MATNEST)); 10388546b261SStefano Zampini { /* hack : avoid setup of scatters */ 10398546b261SStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 10408546b261SStefano Zampini matis->islocalref = PETSC_TRUE; 10418546b261SStefano Zampini } 10429566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B,rl2g,cl2g)); 10439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 10449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 10459566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA)); 10469566063dSJacob Faibussowitsch PetscCall(MatNestSetVecType(lA,VECNEST)); 10479e7b2b25Sstefano_zampini for (i=0;i<nr*nc;i++) { 10489e7b2b25Sstefano_zampini if (istrans[i]) { 10499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snest[i])); 10509e7b2b25Sstefano_zampini } 10519e7b2b25Sstefano_zampini } 10529566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B,lA)); 10539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 10548546b261SStefano Zampini { /* hack : setup of scatters done here */ 10558546b261SStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 10568546b261SStefano Zampini 10578546b261SStefano Zampini matis->islocalref = PETSC_FALSE; 10589566063dSJacob Faibussowitsch PetscCall(MatISSetUpScatters_Private(B)); 10598546b261SStefano Zampini } 10609566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 10619566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 10625e3038f0Sstefano_zampini if (reuse == MAT_INPLACE_MATRIX) { 10639566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&B)); 10645e3038f0Sstefano_zampini } else { 10655e3038f0Sstefano_zampini *newmat = B; 10665e3038f0Sstefano_zampini } 10675e3038f0Sstefano_zampini } else { 10685e3038f0Sstefano_zampini if (lreuse) { 10699566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat,&lA)); 10705e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 10715e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 10725e3038f0Sstefano_zampini if (snest[i*nc+j]) { 10739566063dSJacob Faibussowitsch PetscCall(MatNestSetSubMat(lA,i,j,snest[i*nc+j])); 10749e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 10759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snest[i*nc+j])); 10769e7b2b25Sstefano_zampini } 10775e3038f0Sstefano_zampini } 10785e3038f0Sstefano_zampini } 10795e3038f0Sstefano_zampini } 10805e3038f0Sstefano_zampini } else { 10815b003df0Sstefano_zampini PetscInt stl; 10825b003df0Sstefano_zampini for (i=0,stl=0;i<nr;i++) { 10839566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i])); 10845b003df0Sstefano_zampini stl += lr[i]; 10855e3038f0Sstefano_zampini } 10865b003df0Sstefano_zampini for (i=0,stl=0;i<nc;i++) { 10879566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i])); 10885b003df0Sstefano_zampini stl += lc[i]; 10895e3038f0Sstefano_zampini } 10909566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA)); 1091ab4d48faSStefano Zampini for (i=0;i<nr*nc;i++) { 10929e7b2b25Sstefano_zampini if (istrans[i]) { 10939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snest[i])); 10949e7b2b25Sstefano_zampini } 1095ab4d48faSStefano Zampini } 10969566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat,lA)); 10979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 10985e3038f0Sstefano_zampini } 10999566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY)); 11009566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY)); 11015e3038f0Sstefano_zampini } 11025e3038f0Sstefano_zampini 11035b003df0Sstefano_zampini /* Create local matrix in MATNEST format */ 11045b003df0Sstefano_zampini convert = PETSC_FALSE; 11059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL)); 11065b003df0Sstefano_zampini if (convert) { 11075b003df0Sstefano_zampini Mat M; 11085b003df0Sstefano_zampini MatISLocalFields lf; 11095b003df0Sstefano_zampini PetscContainer c; 11105b003df0Sstefano_zampini 11119566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat,&lA)); 11129566063dSJacob Faibussowitsch PetscCall(MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M)); 11139566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat,M)); 11149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 11155b003df0Sstefano_zampini 11165b003df0Sstefano_zampini /* attach local fields to the matrix */ 11179566063dSJacob Faibussowitsch PetscCall(PetscNew(&lf)); 11189566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nr,&lf->rf,nc,&lf->cf)); 11195b003df0Sstefano_zampini for (i=0;i<nr;i++) { 11205b003df0Sstefano_zampini PetscInt n,st; 11215b003df0Sstefano_zampini 11229566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islrow[i],&n)); 11239566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(islrow[i],&st,NULL)); 11249566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm,n,st,1,&lf->rf[i])); 11255b003df0Sstefano_zampini } 11265b003df0Sstefano_zampini for (i=0;i<nc;i++) { 11275b003df0Sstefano_zampini PetscInt n,st; 11285b003df0Sstefano_zampini 11299566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islcol[i],&n)); 11309566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(islcol[i],&st,NULL)); 11319566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm,n,st,1,&lf->cf[i])); 11325b003df0Sstefano_zampini } 11335b003df0Sstefano_zampini lf->nr = nr; 11345b003df0Sstefano_zampini lf->nc = nc; 11359566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c)); 11369566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c,lf)); 11379566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private)); 11389566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c)); 11399566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 11405b003df0Sstefano_zampini } 11415b003df0Sstefano_zampini 11425e3038f0Sstefano_zampini /* Free workspace */ 11435e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 11449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&islrow[i])); 11455e3038f0Sstefano_zampini } 11465e3038f0Sstefano_zampini for (i=0;i<nc;i++) { 11479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&islcol[i])); 11485e3038f0Sstefano_zampini } 11499566063dSJacob Faibussowitsch PetscCall(PetscFree6(isrow,iscol,islrow,islcol,snest,istrans)); 11509566063dSJacob Faibussowitsch PetscCall(PetscFree2(lr,lc)); 11515e3038f0Sstefano_zampini PetscFunctionReturn(0); 11525e3038f0Sstefano_zampini } 11535e3038f0Sstefano_zampini 1154ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r) 1155ad219c80Sstefano_zampini { 1156ad219c80Sstefano_zampini Mat_IS *matis = (Mat_IS*)A->data; 1157ad219c80Sstefano_zampini Vec ll,rr; 1158ad219c80Sstefano_zampini const PetscScalar *Y,*X; 1159ad219c80Sstefano_zampini PetscScalar *x,*y; 1160ad219c80Sstefano_zampini 1161ad219c80Sstefano_zampini PetscFunctionBegin; 1162ad219c80Sstefano_zampini if (l) { 1163ad219c80Sstefano_zampini ll = matis->y; 11649566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(l,&Y)); 11659566063dSJacob Faibussowitsch PetscCall(VecGetArray(ll,&y)); 11669566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y,MPI_REPLACE)); 1167ad219c80Sstefano_zampini } else { 1168ad219c80Sstefano_zampini ll = NULL; 1169ad219c80Sstefano_zampini } 1170ad219c80Sstefano_zampini if (r) { 1171ad219c80Sstefano_zampini rr = matis->x; 11729566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(r,&X)); 11739566063dSJacob Faibussowitsch PetscCall(VecGetArray(rr,&x)); 11749566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x,MPI_REPLACE)); 1175ad219c80Sstefano_zampini } else { 1176ad219c80Sstefano_zampini rr = NULL; 1177ad219c80Sstefano_zampini } 1178ad219c80Sstefano_zampini if (ll) { 11799566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y,MPI_REPLACE)); 11809566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(l,&Y)); 11819566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(ll,&y)); 1182ad219c80Sstefano_zampini } 1183ad219c80Sstefano_zampini if (rr) { 11849566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x,MPI_REPLACE)); 11859566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(r,&X)); 11869566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(rr,&x)); 1187ad219c80Sstefano_zampini } 11889566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(matis->A,ll,rr)); 1189ad219c80Sstefano_zampini PetscFunctionReturn(0); 1190ad219c80Sstefano_zampini } 1191ad219c80Sstefano_zampini 11927fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo) 11937fa8f2d3SStefano Zampini { 11947fa8f2d3SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 11957fa8f2d3SStefano Zampini MatInfo info; 11963966268fSBarry Smith PetscLogDouble isend[6],irecv[6]; 11977fa8f2d3SStefano Zampini PetscInt bs; 11987fa8f2d3SStefano Zampini 11997fa8f2d3SStefano Zampini PetscFunctionBegin; 12009566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A,&bs)); 1201a2ccb5f9Sstefano_zampini if (matis->A->ops->getinfo) { 12029566063dSJacob Faibussowitsch PetscCall(MatGetInfo(matis->A,MAT_LOCAL,&info)); 12037fa8f2d3SStefano Zampini isend[0] = info.nz_used; 12047fa8f2d3SStefano Zampini isend[1] = info.nz_allocated; 12057fa8f2d3SStefano Zampini isend[2] = info.nz_unneeded; 12067fa8f2d3SStefano Zampini isend[3] = info.memory; 12077fa8f2d3SStefano Zampini isend[4] = info.mallocs; 1208a2ccb5f9Sstefano_zampini } else { 1209a2ccb5f9Sstefano_zampini isend[0] = 0.; 1210a2ccb5f9Sstefano_zampini isend[1] = 0.; 1211a2ccb5f9Sstefano_zampini isend[2] = 0.; 1212a2ccb5f9Sstefano_zampini isend[3] = 0.; 1213a2ccb5f9Sstefano_zampini isend[4] = 0.; 1214a2ccb5f9Sstefano_zampini } 1215314ce898Sstefano_zampini isend[5] = matis->A->num_ass; 12167fa8f2d3SStefano Zampini if (flag == MAT_LOCAL) { 12177fa8f2d3SStefano Zampini ginfo->nz_used = isend[0]; 12187fa8f2d3SStefano Zampini ginfo->nz_allocated = isend[1]; 12197fa8f2d3SStefano Zampini ginfo->nz_unneeded = isend[2]; 12207fa8f2d3SStefano Zampini ginfo->memory = isend[3]; 12217fa8f2d3SStefano Zampini ginfo->mallocs = isend[4]; 1222314ce898Sstefano_zampini ginfo->assemblies = isend[5]; 12237fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_MAX) { 12241c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(isend,irecv,6,MPIU_PETSCLOGDOUBLE,MPI_MAX,PetscObjectComm((PetscObject)A))); 12257fa8f2d3SStefano Zampini 12267fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 12277fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 12287fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 12297fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 12307fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 1231314ce898Sstefano_zampini ginfo->assemblies = irecv[5]; 12327fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_SUM) { 12331c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(isend,irecv,5,MPIU_PETSCLOGDOUBLE,MPI_SUM,PetscObjectComm((PetscObject)A))); 12347fa8f2d3SStefano Zampini 12357fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 12367fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 12377fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 12387fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 12397fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 12407fa8f2d3SStefano Zampini ginfo->assemblies = A->num_ass; 12417fa8f2d3SStefano Zampini } 12427fa8f2d3SStefano Zampini ginfo->block_size = bs; 12437fa8f2d3SStefano Zampini ginfo->fill_ratio_given = 0; 12447fa8f2d3SStefano Zampini ginfo->fill_ratio_needed = 0; 12457fa8f2d3SStefano Zampini ginfo->factor_mallocs = 0; 12465e3038f0Sstefano_zampini PetscFunctionReturn(0); 12475e3038f0Sstefano_zampini } 12485e3038f0Sstefano_zampini 12498b9382cfSStefano Zampini static PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B) 1250d7f69cd0SStefano Zampini { 1251d7f69cd0SStefano Zampini Mat C,lC,lA; 1252d7f69cd0SStefano Zampini 1253d7f69cd0SStefano Zampini PetscFunctionBegin; 1254cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) { 1255cf37664fSBarry Smith ISLocalToGlobalMapping rl2g,cl2g; 12569566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&C)); 12579566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N)); 12589566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs))); 12599566063dSJacob Faibussowitsch PetscCall(MatSetType(C,MATIS)); 12609566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A,&rl2g,&cl2g)); 12619566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(C,cl2g,rl2g)); 1262e432b41dSStefano Zampini } else C = *B; 1263d7f69cd0SStefano Zampini 1264d7f69cd0SStefano Zampini /* perform local transposition */ 12659566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A,&lA)); 12669566063dSJacob Faibussowitsch PetscCall(MatTranspose(lA,MAT_INITIAL_MATRIX,&lC)); 12679566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(lC,lA->cmap->mapping,lA->rmap->mapping)); 12689566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(C,lC)); 12699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lC)); 1270d7f69cd0SStefano Zampini 1271cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 1272d7f69cd0SStefano Zampini *B = C; 1273d7f69cd0SStefano Zampini } else { 12749566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(A,&C)); 1275d7f69cd0SStefano Zampini } 12769566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY)); 12779566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY)); 1278d7f69cd0SStefano Zampini PetscFunctionReturn(0); 1279d7f69cd0SStefano Zampini } 1280d7f69cd0SStefano Zampini 12818b9382cfSStefano Zampini static PetscErrorCode MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode) 12823fd1c9e7SStefano Zampini { 12833fd1c9e7SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 12843fd1c9e7SStefano Zampini 12853fd1c9e7SStefano Zampini PetscFunctionBegin; 12864b89b9cdSStefano Zampini if (D) { /* MatShift_IS pass D = NULL */ 12879566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD)); 12889566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD)); 12893fd1c9e7SStefano Zampini } 12909566063dSJacob Faibussowitsch PetscCall(VecPointwiseDivide(is->y,is->y,is->counter)); 12919566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(is->A,is->y,insmode)); 12923fd1c9e7SStefano Zampini PetscFunctionReturn(0); 12933fd1c9e7SStefano Zampini } 12943fd1c9e7SStefano Zampini 12958b9382cfSStefano Zampini static PetscErrorCode MatShift_IS(Mat A,PetscScalar a) 12963fd1c9e7SStefano Zampini { 12974b89b9cdSStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 12983fd1c9e7SStefano Zampini 12993fd1c9e7SStefano Zampini PetscFunctionBegin; 13009566063dSJacob Faibussowitsch PetscCall(VecSet(is->y,a)); 13019566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_IS(A,NULL,ADD_VALUES)); 13023fd1c9e7SStefano Zampini PetscFunctionReturn(0); 13033fd1c9e7SStefano Zampini } 13043fd1c9e7SStefano Zampini 1305f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1306f26d0771SStefano Zampini { 1307f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1308f26d0771SStefano Zampini 1309f26d0771SStefano Zampini PetscFunctionBegin; 1310aed4548fSBarry Smith PetscCheck(m <= MATIS_MAX_ENTRIES_INSERTION && n <= MATIS_MAX_ENTRIES_INSERTION,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %d: they are %" PetscInt_FMT " %" PetscInt_FMT,MATIS_MAX_ENTRIES_INSERTION,m,n); 13119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l)); 13129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l)); 13139566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv)); 1314f26d0771SStefano Zampini PetscFunctionReturn(0); 1315f26d0771SStefano Zampini } 1316f26d0771SStefano Zampini 1317f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1318f26d0771SStefano Zampini { 1319f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1320f26d0771SStefano Zampini 1321f26d0771SStefano Zampini PetscFunctionBegin; 1322aed4548fSBarry Smith PetscCheck(m <= MATIS_MAX_ENTRIES_INSERTION && n <= MATIS_MAX_ENTRIES_INSERTION,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %d: they are %" PetscInt_FMT " %" PetscInt_FMT,MATIS_MAX_ENTRIES_INSERTION,m,n); 13239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l)); 13249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l)); 13259566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv)); 1326f26d0771SStefano Zampini PetscFunctionReturn(0); 1327f26d0771SStefano Zampini } 1328f26d0771SStefano Zampini 13297dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat) 1330a8116848SStefano Zampini { 1331a8116848SStefano Zampini Mat locmat,newlocmat; 1332a8116848SStefano Zampini Mat_IS *newmatis; 1333a8116848SStefano Zampini const PetscInt *idxs; 1334a8116848SStefano Zampini PetscInt i,m,n; 1335a8116848SStefano Zampini 1336a8116848SStefano Zampini PetscFunctionBegin; 1337a8116848SStefano Zampini if (scall == MAT_REUSE_MATRIX) { 1338a8116848SStefano Zampini PetscBool ismatis; 1339a8116848SStefano Zampini 13409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis)); 134128b400f6SJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type"); 1342a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 134328b400f6SJacob Faibussowitsch PetscCheck(newmatis->getsub_ris,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS"); 134428b400f6SJacob Faibussowitsch PetscCheck(newmatis->getsub_cis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS"); 1345a8116848SStefano Zampini } 1346a8116848SStefano Zampini /* irow and icol may not have duplicate entries */ 134776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 134876bd3646SJed Brown Vec rtest,ltest; 134976bd3646SJed Brown const PetscScalar *array; 135076bd3646SJed Brown 13519566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(mat,<est,&rtest)); 13529566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(irow,&n)); 13539566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irow,&idxs)); 1354a8116848SStefano Zampini for (i=0;i<n;i++) { 13559566063dSJacob Faibussowitsch PetscCall(VecSetValue(rtest,idxs[i],1.0,ADD_VALUES)); 1356a8116848SStefano Zampini } 13579566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(rtest)); 13589566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(rtest)); 13599566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rtest,&n)); 13609566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(rtest,&m,NULL)); 13619566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(rtest,&array)); 1362aed4548fSBarry Smith for (i=0;i<n;i++) PetscCheck(array[i] == 0. || array[i] == 1.,PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %" PetscInt_FMT " counted %" PetscInt_FMT " times! Irow may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i])); 13639566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(rtest,&array)); 13649566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irow,&idxs)); 13659566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(icol,&n)); 13669566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icol,&idxs)); 1367a8116848SStefano Zampini for (i=0;i<n;i++) { 13689566063dSJacob Faibussowitsch PetscCall(VecSetValue(ltest,idxs[i],1.0,ADD_VALUES)); 1369a8116848SStefano Zampini } 13709566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(ltest)); 13719566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(ltest)); 13729566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ltest,&n)); 13739566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(ltest,&m,NULL)); 13749566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(ltest,&array)); 1375aed4548fSBarry Smith for (i=0;i<n;i++) PetscCheck(array[i] == 0. || array[i] == 1.,PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %" PetscInt_FMT " counted %" PetscInt_FMT " times! Icol may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i])); 13769566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(ltest,&array)); 13779566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icol,&idxs)); 13789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rtest)); 13799566063dSJacob Faibussowitsch PetscCall(VecDestroy(<est)); 138076bd3646SJed Brown } 1381a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 1382a8116848SStefano Zampini Mat_IS *matis = (Mat_IS*)mat->data; 1383a8116848SStefano Zampini ISLocalToGlobalMapping rl2g; 1384a8116848SStefano Zampini IS is; 1385a8116848SStefano Zampini PetscInt *lidxs,*lgidxs,*newgidxs; 1386306cf5c7SStefano Zampini PetscInt ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs; 138794342113SStefano Zampini PetscBool cong; 1388a8116848SStefano Zampini MPI_Comm comm; 1389a8116848SStefano Zampini 13909566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat,&comm)); 13919566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(mat,&arbs,&acbs)); 13929566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(irow,&irbs)); 13939566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(icol,&icbs)); 1394306cf5c7SStefano Zampini rbs = arbs == irbs ? irbs : 1; 1395306cf5c7SStefano Zampini cbs = acbs == icbs ? icbs : 1; 13969566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(irow,&m)); 13979566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(icol,&n)); 13989566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,newmat)); 13999566063dSJacob Faibussowitsch PetscCall(MatSetType(*newmat,MATIS)); 14009566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE)); 14019566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(*newmat,rbs,cbs)); 1402a8116848SStefano Zampini /* communicate irow to their owners in the layout */ 14039566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irow,&idxs)); 14049566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs)); 14059566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irow,&idxs)); 14069566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata,matis->sf->nroots)); 1407a8116848SStefano Zampini for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1; 14089566063dSJacob Faibussowitsch PetscCall(PetscFree(lidxs)); 14099566063dSJacob Faibussowitsch PetscCall(PetscFree(lgidxs)); 14109566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 14119566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 14123d996552SStefano Zampini for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++; 14139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc,&newgidxs)); 14149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc,&lidxs)); 14153d996552SStefano Zampini for (i=0,newloc=0;i<matis->sf->nleaves;i++) 1416a8116848SStefano Zampini if (matis->sf_leafdata[i]) { 1417a8116848SStefano Zampini lidxs[newloc] = i; 1418a8116848SStefano Zampini newgidxs[newloc++] = matis->sf_leafdata[i]-1; 1419a8116848SStefano Zampini } 14209566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is)); 14219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g)); 14229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(rl2g,rbs)); 14239566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1424a8116848SStefano Zampini /* local is to extract local submatrix */ 1425a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 14269566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris)); 14279566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(mat,&cong)); 142894342113SStefano Zampini if (cong && irow == icol && matis->csf == matis->sf) { 14299566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g)); 14309566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)newmatis->getsub_ris)); 1431a8116848SStefano Zampini newmatis->getsub_cis = newmatis->getsub_ris; 1432a8116848SStefano Zampini } else { 1433a8116848SStefano Zampini ISLocalToGlobalMapping cl2g; 1434a8116848SStefano Zampini 1435a8116848SStefano Zampini /* communicate icol to their owners in the layout */ 14369566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icol,&idxs)); 14379566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs)); 14389566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icol,&idxs)); 14399566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->csf_rootdata,matis->csf->nroots)); 1440a8116848SStefano Zampini for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1; 14419566063dSJacob Faibussowitsch PetscCall(PetscFree(lidxs)); 14429566063dSJacob Faibussowitsch PetscCall(PetscFree(lgidxs)); 14439566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata,MPI_REPLACE)); 14449566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata,MPI_REPLACE)); 14453d996552SStefano Zampini for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++; 14469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc,&newgidxs)); 14479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc,&lidxs)); 14483d996552SStefano Zampini for (i=0,newloc=0;i<matis->csf->nleaves;i++) 1449a8116848SStefano Zampini if (matis->csf_leafdata[i]) { 1450a8116848SStefano Zampini lidxs[newloc] = i; 1451a8116848SStefano Zampini newgidxs[newloc++] = matis->csf_leafdata[i]-1; 1452a8116848SStefano Zampini } 14539566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is)); 14549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g)); 14559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(cl2g,cbs)); 14569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1457a8116848SStefano Zampini /* local is to extract local submatrix */ 14589566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis)); 14599566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g)); 14609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 1461a8116848SStefano Zampini } 14629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 1463a8116848SStefano Zampini } else { 14649566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat,&newlocmat)); 1465a8116848SStefano Zampini } 14669566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat,&locmat)); 1467a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 14689566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat)); 1469a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 14709566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat,newlocmat)); 14719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlocmat)); 1472a8116848SStefano Zampini } 14739566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY)); 14749566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY)); 1475a8116848SStefano Zampini PetscFunctionReturn(0); 1476a8116848SStefano Zampini } 1477a8116848SStefano Zampini 1478a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str) 14792b404112SStefano Zampini { 14802b404112SStefano Zampini Mat_IS *a = (Mat_IS*)A->data,*b; 14812b404112SStefano Zampini PetscBool ismatis; 14822b404112SStefano Zampini 14832b404112SStefano Zampini PetscFunctionBegin; 14849566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis)); 148528b400f6SJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented"); 14862b404112SStefano Zampini b = (Mat_IS*)B->data; 14879566063dSJacob Faibussowitsch PetscCall(MatCopy(a->A,b->A,str)); 14889566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 14892b404112SStefano Zampini PetscFunctionReturn(0); 14902b404112SStefano Zampini } 14912b404112SStefano Zampini 1492a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool *missing,PetscInt *d) 14936bd84002SStefano Zampini { 1494527b2640SStefano Zampini Vec v; 1495527b2640SStefano Zampini const PetscScalar *array; 1496527b2640SStefano Zampini PetscInt i,n; 14976bd84002SStefano Zampini 14986bd84002SStefano Zampini PetscFunctionBegin; 1499527b2640SStefano Zampini *missing = PETSC_FALSE; 15009566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A,NULL,&v)); 15019566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(A,v)); 15029566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v,&n)); 15039566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v,&array)); 1504527b2640SStefano Zampini for (i=0;i<n;i++) if (array[i] == 0.) break; 15059566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v,&array)); 15069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 1507527b2640SStefano Zampini if (i != n) *missing = PETSC_TRUE; 1508527b2640SStefano Zampini if (d) { 1509527b2640SStefano Zampini *d = -1; 1510527b2640SStefano Zampini if (*missing) { 1511527b2640SStefano Zampini PetscInt rstart; 15129566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A,&rstart,NULL)); 1513527b2640SStefano Zampini *d = i+rstart; 1514527b2640SStefano Zampini } 1515527b2640SStefano Zampini } 15166bd84002SStefano Zampini PetscFunctionReturn(0); 15176bd84002SStefano Zampini } 15186bd84002SStefano Zampini 1519cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B) 152028f4e0baSStefano Zampini { 152128f4e0baSStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 152228f4e0baSStefano Zampini const PetscInt *gidxs; 15234f2d7cafSStefano Zampini PetscInt nleaves; 152428f4e0baSStefano Zampini 152528f4e0baSStefano Zampini PetscFunctionBegin; 15264f2d7cafSStefano Zampini if (matis->sf) PetscFunctionReturn(0); 15279566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf)); 15289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping,&gidxs)); 15299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping,&nleaves)); 15309566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs)); 15319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping,&gidxs)); 15329566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata)); 1533e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { /* setup SF for columns */ 15349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping,&nleaves)); 15359566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf)); 15369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping,&gidxs)); 15379566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs)); 15389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping,&gidxs)); 15399566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata)); 1540a8116848SStefano Zampini } else { 1541a8116848SStefano Zampini matis->csf = matis->sf; 1542a8116848SStefano Zampini matis->csf_leafdata = matis->sf_leafdata; 1543a8116848SStefano Zampini matis->csf_rootdata = matis->sf_rootdata; 1544a8116848SStefano Zampini } 154528f4e0baSStefano Zampini PetscFunctionReturn(0); 154628f4e0baSStefano Zampini } 15472e1947a5SStefano Zampini 1548eb82efa4SStefano Zampini /*@ 154975d48cdbSStefano Zampini MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP. 155075d48cdbSStefano Zampini 1551d083f849SBarry Smith Collective 155275d48cdbSStefano Zampini 155375d48cdbSStefano Zampini Input Parameters: 155475d48cdbSStefano Zampini + A - the matrix 155575d48cdbSStefano Zampini - store - the boolean flag 155675d48cdbSStefano Zampini 155775d48cdbSStefano Zampini Level: advanced 155875d48cdbSStefano Zampini 155975d48cdbSStefano Zampini Notes: 156075d48cdbSStefano Zampini 1561db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatPtAP()` 156275d48cdbSStefano Zampini @*/ 156375d48cdbSStefano Zampini PetscErrorCode MatISStoreL2L(Mat A, PetscBool store) 156475d48cdbSStefano Zampini { 156575d48cdbSStefano Zampini PetscFunctionBegin; 156675d48cdbSStefano Zampini PetscValidHeaderSpecific(A,MAT_CLASSID,1); 156775d48cdbSStefano Zampini PetscValidType(A,1); 156875d48cdbSStefano Zampini PetscValidLogicalCollectiveBool(A,store,2); 1569cac4c232SBarry Smith PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store)); 157075d48cdbSStefano Zampini PetscFunctionReturn(0); 157175d48cdbSStefano Zampini } 157275d48cdbSStefano Zampini 157375d48cdbSStefano Zampini static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store) 157475d48cdbSStefano Zampini { 157575d48cdbSStefano Zampini Mat_IS *matis = (Mat_IS*)(A->data); 157675d48cdbSStefano Zampini 157775d48cdbSStefano Zampini PetscFunctionBegin; 157875d48cdbSStefano Zampini matis->storel2l = store; 157975d48cdbSStefano Zampini if (!store) { 15809566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL)); 158175d48cdbSStefano Zampini } 158275d48cdbSStefano Zampini PetscFunctionReturn(0); 158375d48cdbSStefano Zampini } 158475d48cdbSStefano Zampini 158575d48cdbSStefano Zampini /*@ 1586f03112d0SStefano Zampini MatISFixLocalEmpty - Compress out zero local rows from the local matrices 1587f03112d0SStefano Zampini 1588d083f849SBarry Smith Collective 1589f03112d0SStefano Zampini 1590f03112d0SStefano Zampini Input Parameters: 1591f03112d0SStefano Zampini + A - the matrix 1592f03112d0SStefano Zampini - fix - the boolean flag 1593f03112d0SStefano Zampini 1594f03112d0SStefano Zampini Level: advanced 1595f03112d0SStefano Zampini 1596f03112d0SStefano Zampini Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process. 1597f03112d0SStefano Zampini 1598db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatAssemblyEnd()`, `MAT_FINAL_ASSEMBLY` 1599f03112d0SStefano Zampini @*/ 1600f03112d0SStefano Zampini PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix) 1601f03112d0SStefano Zampini { 1602f03112d0SStefano Zampini PetscFunctionBegin; 1603f03112d0SStefano Zampini PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1604f03112d0SStefano Zampini PetscValidType(A,1); 1605f03112d0SStefano Zampini PetscValidLogicalCollectiveBool(A,fix,2); 1606cac4c232SBarry Smith PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix)); 1607f03112d0SStefano Zampini PetscFunctionReturn(0); 1608f03112d0SStefano Zampini } 1609f03112d0SStefano Zampini 1610f03112d0SStefano Zampini static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix) 1611f03112d0SStefano Zampini { 1612f03112d0SStefano Zampini Mat_IS *matis = (Mat_IS*)(A->data); 1613f03112d0SStefano Zampini 1614f03112d0SStefano Zampini PetscFunctionBegin; 1615f03112d0SStefano Zampini matis->locempty = fix; 1616f03112d0SStefano Zampini PetscFunctionReturn(0); 1617f03112d0SStefano Zampini } 1618f03112d0SStefano Zampini 1619f03112d0SStefano Zampini /*@ 1620a88811baSStefano Zampini MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix. 1621a88811baSStefano Zampini 1622d083f849SBarry Smith Collective 1623a88811baSStefano Zampini 1624a88811baSStefano Zampini Input Parameters: 1625a88811baSStefano Zampini + B - the matrix 1626a88811baSStefano Zampini . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1627a88811baSStefano Zampini (same value is used for all local rows) 1628a88811baSStefano Zampini . d_nnz - array containing the number of nonzeros in the various rows of the 1629a88811baSStefano Zampini DIAGONAL portion of the local submatrix (possibly different for each row) 1630a88811baSStefano Zampini or NULL, if d_nz is used to specify the nonzero structure. 1631a88811baSStefano Zampini The size of this array is equal to the number of local rows, i.e 'm'. 1632a88811baSStefano Zampini For matrices that will be factored, you must leave room for (and set) 1633a88811baSStefano Zampini the diagonal entry even if it is zero. 1634a88811baSStefano Zampini . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1635a88811baSStefano Zampini submatrix (same value is used for all local rows). 1636a88811baSStefano Zampini - o_nnz - array containing the number of nonzeros in the various rows of the 1637a88811baSStefano Zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 1638a88811baSStefano Zampini each row) or NULL, if o_nz is used to specify the nonzero 1639a88811baSStefano Zampini structure. The size of this array is equal to the number 1640a88811baSStefano Zampini of local rows, i.e 'm'. 1641a88811baSStefano Zampini 1642a88811baSStefano Zampini If the *_nnz parameter is given then the *_nz parameter is ignored 1643a88811baSStefano Zampini 1644a88811baSStefano Zampini Level: intermediate 1645a88811baSStefano Zampini 164695452b02SPatrick Sanan Notes: 164795452b02SPatrick Sanan This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition 1648a88811baSStefano Zampini from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local 1649a88811baSStefano Zampini matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 1650a88811baSStefano Zampini 1651db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateIS()`, `MatMPIAIJSetPreallocation()`, `MatISGetLocalMat()`, `MATIS` 1652a88811baSStefano Zampini @*/ 16532e1947a5SStefano Zampini PetscErrorCode MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 16542e1947a5SStefano Zampini { 16552e1947a5SStefano Zampini PetscFunctionBegin; 16562e1947a5SStefano Zampini PetscValidHeaderSpecific(B,MAT_CLASSID,1); 16572e1947a5SStefano Zampini PetscValidType(B,1); 1658cac4c232SBarry Smith PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz)); 16592e1947a5SStefano Zampini PetscFunctionReturn(0); 16602e1947a5SStefano Zampini } 16612e1947a5SStefano Zampini 1662844bd0d7SStefano Zampini /* this is used by DMDA */ 1663844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 16642e1947a5SStefano Zampini { 16652e1947a5SStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 166628f4e0baSStefano Zampini PetscInt bs,i,nlocalcols; 16672e1947a5SStefano Zampini 16682e1947a5SStefano Zampini PetscFunctionBegin; 16699566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 16704f2d7cafSStefano Zampini if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz; 16714f2d7cafSStefano Zampini else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i]; 16724f2d7cafSStefano Zampini 16734f2d7cafSStefano Zampini if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz; 16744f2d7cafSStefano Zampini else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i]; 16754f2d7cafSStefano Zampini 16769566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 16779566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A,NULL,&nlocalcols)); 16789566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(matis->A,&bs)); 16799566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 16804f2d7cafSStefano Zampini 16814f2d7cafSStefano Zampini for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols); 16829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata)); 16830f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE) 16849566063dSJacob Faibussowitsch PetscCall(MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL)); 16850f2f62c7SStefano Zampini #endif 16864f2d7cafSStefano Zampini 1687fc989267SStefano Zampini for (i=0;i<matis->sf->nleaves/bs;i++) { 1688fc989267SStefano Zampini PetscInt b; 1689fc989267SStefano Zampini 1690fc989267SStefano Zampini matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs; 1691fc989267SStefano Zampini for (b=1;b<bs;b++) { 1692fc989267SStefano Zampini matis->sf_leafdata[i] = PetscMax(matis->sf_leafdata[i],matis->sf_leafdata[i*bs+b]/bs); 1693fc989267SStefano Zampini } 1694fc989267SStefano Zampini } 16959566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata)); 16964f2d7cafSStefano Zampini 169700a59248SStefano Zampini nlocalcols /= bs; 169800a59248SStefano Zampini for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols - i); 16999566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata)); 17000f2f62c7SStefano Zampini 17010f2f62c7SStefano Zampini /* for other matrix types */ 17029566063dSJacob Faibussowitsch PetscCall(MatSetUp(matis->A)); 17032e1947a5SStefano Zampini PetscFunctionReturn(0); 17042e1947a5SStefano Zampini } 1705b4319ba4SBarry Smith 17063927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce) 17073927de2eSStefano Zampini { 17083927de2eSStefano Zampini Mat_IS *matis = (Mat_IS*)(A->data); 17093927de2eSStefano Zampini PetscInt *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership; 1710ecf5a873SStefano Zampini const PetscInt *global_indices_r,*global_indices_c; 17113927de2eSStefano Zampini PetscInt i,j,bs,rows,cols; 17123927de2eSStefano Zampini PetscInt lrows,lcols; 17133927de2eSStefano Zampini PetscInt local_rows,local_cols; 1714f03112d0SStefano Zampini PetscMPIInt size; 17153927de2eSStefano Zampini PetscBool isdense,issbaij; 17163927de2eSStefano Zampini 17173927de2eSStefano Zampini PetscFunctionBegin; 17189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size)); 17199566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&rows,&cols)); 17209566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A,&bs)); 17219566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A,&local_rows,&local_cols)); 17229566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense)); 17239566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij)); 17249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping,&global_indices_r)); 1725e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 17269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping,&global_indices_c)); 17270dfc91b7SStefano Zampini } else global_indices_c = global_indices_r; 1728ecf5a873SStefano Zampini 17299566063dSJacob Faibussowitsch if (issbaij) PetscCall(MatGetRowUpperTriangular(matis->A)); 17303927de2eSStefano Zampini /* 1731ecf5a873SStefano Zampini An SF reduce is needed to sum up properly on shared rows. 17323927de2eSStefano Zampini Note that generally preallocation is not exact, since it overestimates nonzeros 17333927de2eSStefano Zampini */ 17349566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,&lrows,&lcols)); 1735d0609cedSBarry Smith MatPreallocateBegin(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz); 17363927de2eSStefano Zampini /* All processes need to compute entire row ownership */ 17379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rows,&row_ownership)); 17389566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges)); 1739f03112d0SStefano Zampini for (i=0;i<size;i++) { 17405f80ce2aSJacob Faibussowitsch for (j=mat_ranges[i];j<mat_ranges[i+1];j++) row_ownership[j] = i; 17413927de2eSStefano Zampini } 17429566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges)); 17433927de2eSStefano Zampini 17443927de2eSStefano Zampini /* 17453927de2eSStefano Zampini my_dnz and my_onz contains exact contribution to preallocation from each local mat 17463927de2eSStefano Zampini then, they will be summed up properly. This way, preallocation is always sufficient 17473927de2eSStefano Zampini */ 17489566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz)); 17493927de2eSStefano Zampini /* preallocation as a MATAIJ */ 17503927de2eSStefano Zampini if (isdense) { /* special case for dense local matrices */ 17513927de2eSStefano Zampini for (i=0;i<local_rows;i++) { 175212dfadf8SStefano Zampini PetscInt owner = row_ownership[global_indices_r[i]]; 175312dfadf8SStefano Zampini for (j=0;j<local_cols;j++) { 1754ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[j]; 17553927de2eSStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */ 17563927de2eSStefano Zampini my_dnz[i] += 1; 17573927de2eSStefano Zampini } else { /* offdiag block */ 17583927de2eSStefano Zampini my_onz[i] += 1; 17593927de2eSStefano Zampini } 17603927de2eSStefano Zampini } 17613927de2eSStefano Zampini } 1762bb1015c3SStefano Zampini } else if (matis->A->ops->getrowij) { 1763bb1015c3SStefano Zampini const PetscInt *ii,*jj,*jptr; 1764bb1015c3SStefano Zampini PetscBool done; 17659566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done)); 17665f80ce2aSJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ"); 1767bb1015c3SStefano Zampini jptr = jj; 1768bb1015c3SStefano Zampini for (i=0;i<local_rows;i++) { 1769bb1015c3SStefano Zampini PetscInt index_row = global_indices_r[i]; 1770bb1015c3SStefano Zampini for (j=0;j<ii[i+1]-ii[i];j++,jptr++) { 1771bb1015c3SStefano Zampini PetscInt owner = row_ownership[index_row]; 1772bb1015c3SStefano Zampini PetscInt index_col = global_indices_c[*jptr]; 1773bb1015c3SStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */ 1774bb1015c3SStefano Zampini my_dnz[i] += 1; 1775bb1015c3SStefano Zampini } else { /* offdiag block */ 1776bb1015c3SStefano Zampini my_onz[i] += 1; 1777bb1015c3SStefano Zampini } 1778bb1015c3SStefano Zampini /* same as before, interchanging rows and cols */ 1779bb1015c3SStefano Zampini if (issbaij && index_col != index_row) { 1780bb1015c3SStefano Zampini owner = row_ownership[index_col]; 1781bb1015c3SStefano Zampini if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1]) { 1782bb1015c3SStefano Zampini my_dnz[*jptr] += 1; 1783bb1015c3SStefano Zampini } else { 1784bb1015c3SStefano Zampini my_onz[*jptr] += 1; 1785bb1015c3SStefano Zampini } 1786bb1015c3SStefano Zampini } 1787bb1015c3SStefano Zampini } 1788bb1015c3SStefano Zampini } 17899566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done)); 17905f80ce2aSJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ"); 1791bb1015c3SStefano Zampini } else { /* loop over rows and use MatGetRow */ 17923927de2eSStefano Zampini for (i=0;i<local_rows;i++) { 17933927de2eSStefano Zampini const PetscInt *cols; 1794ecf5a873SStefano Zampini PetscInt ncols,index_row = global_indices_r[i]; 17959566063dSJacob Faibussowitsch PetscCall(MatGetRow(matis->A,i,&ncols,&cols,NULL)); 17963927de2eSStefano Zampini for (j=0;j<ncols;j++) { 17973927de2eSStefano Zampini PetscInt owner = row_ownership[index_row]; 1798ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[cols[j]]; 17993927de2eSStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */ 18003927de2eSStefano Zampini my_dnz[i] += 1; 18013927de2eSStefano Zampini } else { /* offdiag block */ 18023927de2eSStefano Zampini my_onz[i] += 1; 18033927de2eSStefano Zampini } 18043927de2eSStefano Zampini /* same as before, interchanging rows and cols */ 1805d9a9e74cSStefano Zampini if (issbaij && index_col != index_row) { 18063927de2eSStefano Zampini owner = row_ownership[index_col]; 18073927de2eSStefano Zampini if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1]) { 1808d9a9e74cSStefano Zampini my_dnz[cols[j]] += 1; 18093927de2eSStefano Zampini } else { 1810d9a9e74cSStefano Zampini my_onz[cols[j]] += 1; 18113927de2eSStefano Zampini } 18123927de2eSStefano Zampini } 18133927de2eSStefano Zampini } 18149566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(matis->A,i,&ncols,&cols,NULL)); 18153927de2eSStefano Zampini } 18163927de2eSStefano Zampini } 1817ecf5a873SStefano Zampini if (global_indices_c != global_indices_r) { 18189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping,&global_indices_c)); 1819ecf5a873SStefano Zampini } 18209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping,&global_indices_r)); 18219566063dSJacob Faibussowitsch PetscCall(PetscFree(row_ownership)); 1822ecf5a873SStefano Zampini 1823ecf5a873SStefano Zampini /* Reduce my_dnz and my_onz */ 18243927de2eSStefano Zampini if (maxreduce) { 18259566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX)); 18269566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX)); 18279566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX)); 18289566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX)); 18293927de2eSStefano Zampini } else { 18309566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM)); 18319566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM)); 18329566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM)); 18339566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM)); 18343927de2eSStefano Zampini } 18359566063dSJacob Faibussowitsch PetscCall(PetscFree2(my_dnz,my_onz)); 18363927de2eSStefano Zampini 18373927de2eSStefano Zampini /* Resize preallocation if overestimated */ 18383927de2eSStefano Zampini for (i=0;i<lrows;i++) { 18393927de2eSStefano Zampini dnz[i] = PetscMin(dnz[i],lcols); 18403927de2eSStefano Zampini onz[i] = PetscMin(onz[i],cols-lcols); 18413927de2eSStefano Zampini } 18421670daf9Sstefano_zampini 18431670daf9Sstefano_zampini /* Set preallocation */ 18449566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B,A,A)); 18459566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B,0,dnz)); 18469566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(B,0,dnz,0,onz)); 184753b44cf5SStefano Zampini for (i=0;i<lrows;i+=bs) { 184853b44cf5SStefano Zampini PetscInt b, d = dnz[i],o = onz[i]; 184953b44cf5SStefano Zampini 185053b44cf5SStefano Zampini for (b=1;b<bs;b++) { 185153b44cf5SStefano Zampini d = PetscMax(d,dnz[i+b]); 185253b44cf5SStefano Zampini o = PetscMax(o,onz[i+b]); 185353b44cf5SStefano Zampini } 185453b44cf5SStefano Zampini dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs); 185553b44cf5SStefano Zampini onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs); 18563927de2eSStefano Zampini } 18579566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(B,bs,0,dnz)); 18589566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz)); 18599566063dSJacob Faibussowitsch PetscCall(MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz)); 1860d0609cedSBarry Smith MatPreallocateEnd(dnz,onz); 18619566063dSJacob Faibussowitsch if (issbaij) PetscCall(MatRestoreRowUpperTriangular(matis->A)); 18629566063dSJacob Faibussowitsch PetscCall(MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE)); 18633927de2eSStefano Zampini PetscFunctionReturn(0); 18643927de2eSStefano Zampini } 18653927de2eSStefano Zampini 1866487b449aSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M) 1867b7ce53b6SStefano Zampini { 1868b7ce53b6SStefano Zampini Mat_IS *matis = (Mat_IS*)(mat->data); 1869487b449aSStefano Zampini Mat local_mat,MT; 187053b44cf5SStefano Zampini PetscInt rbs,cbs,rows,cols,lrows,lcols; 1871b7ce53b6SStefano Zampini PetscInt local_rows,local_cols; 1872b9ed4604SStefano Zampini PetscBool isseqdense,isseqsbaij,isseqaij,isseqbaij; 1873f03112d0SStefano Zampini PetscMPIInt size; 18741683a169SBarry Smith const PetscScalar *array; 1875b7ce53b6SStefano Zampini 1876b7ce53b6SStefano Zampini PetscFunctionBegin; 18779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size)); 1878f03112d0SStefano Zampini if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) { 18791670daf9Sstefano_zampini Mat B; 188053b44cf5SStefano Zampini IS irows = NULL,icols = NULL; 1881487b449aSStefano Zampini PetscInt rbs,cbs; 18821670daf9Sstefano_zampini 18839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping,&rbs)); 18849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping,&cbs)); 188553b44cf5SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */ 188653b44cf5SStefano Zampini IS rows,cols; 188753b44cf5SStefano Zampini const PetscInt *ridxs,*cidxs; 188853b44cf5SStefano Zampini PetscInt i,nw,*work; 188953b44cf5SStefano Zampini 18909566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->rmapping,&ridxs)); 18919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping,&nw)); 189253b44cf5SStefano Zampini nw = nw/rbs; 18939566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nw,&work)); 189453b44cf5SStefano Zampini for (i=0;i<nw;i++) work[ridxs[i]] += 1; 189553b44cf5SStefano Zampini for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break; 189653b44cf5SStefano Zampini if (i == nw) { 18979566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows)); 18989566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(rows)); 18999566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rows,PETSC_DECIDE,&irows)); 19009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 190153b44cf5SStefano Zampini } 19029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->rmapping,&ridxs)); 19039566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 1904e432b41dSStefano Zampini if (irows && matis->rmapping != matis->cmapping) { 19059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->cmapping,&cidxs)); 19069566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping,&nw)); 190753b44cf5SStefano Zampini nw = nw/cbs; 19089566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nw,&work)); 190953b44cf5SStefano Zampini for (i=0;i<nw;i++) work[cidxs[i]] += 1; 191053b44cf5SStefano Zampini for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break; 191153b44cf5SStefano Zampini if (i == nw) { 19129566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols)); 19139566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(cols)); 19149566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(cols,PETSC_DECIDE,&icols)); 19159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 191653b44cf5SStefano Zampini } 19179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->cmapping,&cidxs)); 19189566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 191953b44cf5SStefano Zampini } else if (irows) { 19209566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)irows)); 192153b44cf5SStefano Zampini icols = irows; 192253b44cf5SStefano Zampini } 192353b44cf5SStefano Zampini } else { 19249566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows)); 19259566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols)); 19269566063dSJacob Faibussowitsch if (irows) PetscCall(PetscObjectReference((PetscObject)irows)); 19279566063dSJacob Faibussowitsch if (icols) PetscCall(PetscObjectReference((PetscObject)icols)); 192853b44cf5SStefano Zampini } 192953b44cf5SStefano Zampini if (!irows || !icols) { 19309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 19319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 193253b44cf5SStefano Zampini goto general_assembly; 193353b44cf5SStefano Zampini } 19349566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A,mtype,MAT_INITIAL_MATRIX,&B)); 1935487b449aSStefano Zampini if (reuse != MAT_INPLACE_MATRIX) { 19369566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B,irows,icols,reuse,M)); 19379566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows)); 19389566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols)); 1939487b449aSStefano Zampini } else { 1940487b449aSStefano Zampini Mat C; 1941487b449aSStefano Zampini 19429566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C)); 19439566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat,&C)); 1944487b449aSStefano Zampini } 19459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 19469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 19479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 19487c03b4e8SStefano Zampini PetscFunctionReturn(0); 19497c03b4e8SStefano Zampini } 195053b44cf5SStefano Zampini general_assembly: 19519566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat,&rows,&cols)); 19529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping,&rbs)); 19539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping,&cbs)); 19549566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat,&lrows,&lcols)); 19559566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A,&local_rows,&local_cols)); 19569566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense)); 19579566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij)); 19589566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij)); 19599566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij)); 1960aed4548fSBarry Smith PetscCheck(isseqdense || isseqaij || isseqbaij || isseqsbaij,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name); 196176bd3646SJed Brown if (PetscDefined (USE_DEBUG)) { 196276bd3646SJed Brown PetscBool lb[4],bb[4]; 196376bd3646SJed Brown 1964b9ed4604SStefano Zampini lb[0] = isseqdense; 1965b9ed4604SStefano Zampini lb[1] = isseqaij; 1966b9ed4604SStefano Zampini lb[2] = isseqbaij; 1967b9ed4604SStefano Zampini lb[3] = isseqsbaij; 19681c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat))); 1969aed4548fSBarry Smith PetscCheck(bb[0] || bb[1] || bb[2] || bb[3],PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type"); 197076bd3646SJed Brown } 1971b7ce53b6SStefano Zampini 1972487b449aSStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 19739566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&MT)); 19749566063dSJacob Faibussowitsch PetscCall(MatSetSizes(MT,lrows,lcols,rows,cols)); 19759566063dSJacob Faibussowitsch PetscCall(MatSetType(MT,mtype)); 19769566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(MT,rbs,cbs)); 19779566063dSJacob Faibussowitsch PetscCall(MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE)); 1978b7ce53b6SStefano Zampini } else { 197953b44cf5SStefano Zampini PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols; 1980487b449aSStefano Zampini 1981b7ce53b6SStefano Zampini /* some checks */ 1982487b449aSStefano Zampini MT = *M; 19839566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(MT,&mrbs,&mcbs)); 19849566063dSJacob Faibussowitsch PetscCall(MatGetSize(MT,&mrows,&mcols)); 19859566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(MT,&mlrows,&mlcols)); 198608401ef6SPierre Jolivet PetscCheck(mrows == rows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%" PetscInt_FMT " != %" PetscInt_FMT ")",rows,mrows); 198708401ef6SPierre Jolivet PetscCheck(mcols == cols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%" PetscInt_FMT " != %" PetscInt_FMT ")",cols,mcols); 198808401ef6SPierre Jolivet PetscCheck(mlrows == lrows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%" PetscInt_FMT " != %" PetscInt_FMT ")",lrows,mlrows); 198908401ef6SPierre Jolivet PetscCheck(mlcols == lcols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%" PetscInt_FMT " != %" PetscInt_FMT ")",lcols,mlcols); 199008401ef6SPierre Jolivet PetscCheck(mrbs == rbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%" PetscInt_FMT " != %" PetscInt_FMT ")",rbs,mrbs); 199108401ef6SPierre Jolivet PetscCheck(mcbs == cbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%" PetscInt_FMT " != %" PetscInt_FMT ")",cbs,mcbs); 19929566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(MT)); 1993b7ce53b6SStefano Zampini } 1994d9a9e74cSStefano Zampini 19958546b261SStefano Zampini if (isseqsbaij || isseqbaij) { 19969566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&local_mat)); 19978546b261SStefano Zampini isseqaij = PETSC_TRUE; 1998d9a9e74cSStefano Zampini } else { 19999566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 2000d9a9e74cSStefano Zampini local_mat = matis->A; 2001d9a9e74cSStefano Zampini } 2002686e3a49SStefano Zampini 2003b7ce53b6SStefano Zampini /* Set values */ 20049566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(MT,matis->rmapping,matis->cmapping)); 2005b9ed4604SStefano Zampini if (isseqdense) { /* special case for dense local matrices */ 200665066ba5SStefano Zampini PetscInt i,*dummy; 2007ecf5a873SStefano Zampini 20089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(local_rows,local_cols),&dummy)); 200965066ba5SStefano Zampini for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i; 20109566063dSJacob Faibussowitsch PetscCall(MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE)); 20119566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(local_mat,&array)); 20129566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES)); 20139566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(local_mat,&array)); 20149566063dSJacob Faibussowitsch PetscCall(PetscFree(dummy)); 2015686e3a49SStefano Zampini } else if (isseqaij) { 20166afe12f5SStefano Zampini const PetscInt *blocks; 20176afe12f5SStefano Zampini PetscInt i,nvtxs,*xadj,*adjncy, nb; 2018686e3a49SStefano Zampini PetscBool done; 20191683a169SBarry Smith PetscScalar *sarray; 2020686e3a49SStefano Zampini 20219566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done)); 202228b400f6SJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ"); 20239566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(local_mat,&sarray)); 20249566063dSJacob Faibussowitsch PetscCall(MatGetVariableBlockSizes(local_mat,&nb,&blocks)); 20256afe12f5SStefano Zampini if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */ 20266afe12f5SStefano Zampini PetscInt sum; 20276afe12f5SStefano Zampini 20286afe12f5SStefano Zampini for (i=0,sum=0;i<nb;i++) sum += blocks[i]; 20296afe12f5SStefano Zampini if (sum == nvtxs) { 20306afe12f5SStefano Zampini PetscInt r; 20316afe12f5SStefano Zampini 20326afe12f5SStefano Zampini for (i=0,r=0;i<nb;i++) { 20336bdcaf15SBarry Smith PetscAssert(blocks[i] == xadj[r+1] - xadj[r],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid block sizes prescribed for block %" PetscInt_FMT ": expected %" PetscInt_FMT ", got %" PetscInt_FMT,i,blocks[i],xadj[r+1] - xadj[r]); 20349566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],sarray+xadj[r],ADD_VALUES)); 20356afe12f5SStefano Zampini r += blocks[i]; 20366afe12f5SStefano Zampini } 20376afe12f5SStefano Zampini } else { 2038686e3a49SStefano Zampini for (i=0;i<nvtxs;i++) { 20399566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES)); 2040686e3a49SStefano Zampini } 20416afe12f5SStefano Zampini } 20426afe12f5SStefano Zampini } else { 20436afe12f5SStefano Zampini for (i=0;i<nvtxs;i++) { 20449566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES)); 20456afe12f5SStefano Zampini } 20466afe12f5SStefano Zampini } 20479566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done)); 204828b400f6SJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ"); 20499566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(local_mat,&sarray)); 2050686e3a49SStefano Zampini } else { /* very basic values insertion for all other matrix types */ 2051ecf5a873SStefano Zampini PetscInt i; 2052c0962df8SStefano Zampini 2053686e3a49SStefano Zampini for (i=0;i<local_rows;i++) { 2054686e3a49SStefano Zampini PetscInt j; 2055ecf5a873SStefano Zampini const PetscInt *local_indices_cols; 2056686e3a49SStefano Zampini 20579566063dSJacob Faibussowitsch PetscCall(MatGetRow(local_mat,i,&j,&local_indices_cols,&array)); 20589566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES)); 20599566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(local_mat,i,&j,&local_indices_cols,&array)); 2060686e3a49SStefano Zampini } 2061b7ce53b6SStefano Zampini } 20629566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY)); 20639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&local_mat)); 20649566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY)); 2065b9ed4604SStefano Zampini if (isseqdense) { 20669566063dSJacob Faibussowitsch PetscCall(MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE)); 2067487b449aSStefano Zampini } 2068487b449aSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 20699566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat,&MT)); 2070487b449aSStefano Zampini } else if (reuse == MAT_INITIAL_MATRIX) { 2071487b449aSStefano Zampini *M = MT; 2072b7ce53b6SStefano Zampini } 2073b7ce53b6SStefano Zampini PetscFunctionReturn(0); 2074b7ce53b6SStefano Zampini } 2075b7ce53b6SStefano Zampini 2076b7ce53b6SStefano Zampini /*@ 2077b7ce53b6SStefano Zampini MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format 2078b7ce53b6SStefano Zampini 2079d8d19677SJose E. Roman Input Parameters: 2080a2b725a8SWilliam Gropp + mat - the matrix (should be of type MATIS) 2081a2b725a8SWilliam Gropp - reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 2082b7ce53b6SStefano Zampini 2083b7ce53b6SStefano Zampini Output Parameter: 2084b7ce53b6SStefano Zampini . newmat - the matrix in AIJ format 2085b7ce53b6SStefano Zampini 2086b7ce53b6SStefano Zampini Level: developer 2087b7ce53b6SStefano Zampini 208895452b02SPatrick Sanan Notes: 2089487b449aSStefano Zampini This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface. 2090b7ce53b6SStefano Zampini 2091db781477SPatrick Sanan .seealso: `MATIS`, `MatConvert()` 2092b7ce53b6SStefano Zampini @*/ 2093b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat) 2094b7ce53b6SStefano Zampini { 2095b7ce53b6SStefano Zampini PetscFunctionBegin; 2096b7ce53b6SStefano Zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2097b7ce53b6SStefano Zampini PetscValidLogicalCollectiveEnum(mat,reuse,2); 2098b7ce53b6SStefano Zampini PetscValidPointer(newmat,3); 2099487b449aSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 2100b7ce53b6SStefano Zampini PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3); 2101b7ce53b6SStefano Zampini PetscCheckSameComm(mat,1,*newmat,3); 210208401ef6SPierre Jolivet PetscCheck(mat != *newmat,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix"); 2103b7ce53b6SStefano Zampini } 2104cac4c232SBarry Smith PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat)); 2105b7ce53b6SStefano Zampini PetscFunctionReturn(0); 2106b7ce53b6SStefano Zampini } 2107b7ce53b6SStefano Zampini 21088b9382cfSStefano Zampini static PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat) 2109ad6194a2SStefano Zampini { 2110ad6194a2SStefano Zampini Mat_IS *matis = (Mat_IS*)(mat->data); 2111c9225affSStefano Zampini PetscInt rbs,cbs,m,n,M,N; 2112ad6194a2SStefano Zampini Mat B,localmat; 2113ad6194a2SStefano Zampini 2114ad6194a2SStefano Zampini PetscFunctionBegin; 21159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs)); 21169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs)); 21179566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat,&M,&N)); 21189566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat,&m,&n)); 21199566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&B)); 21209566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B,m,n,M,N)); 21219566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B,rbs == cbs ? rbs : 1)); 21229566063dSJacob Faibussowitsch PetscCall(MatSetType(B,MATIS)); 21239566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B,matis->lmattype)); 21249566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B,mat->rmap->mapping,mat->cmap->mapping)); 21259566063dSJacob Faibussowitsch PetscCall(MatDuplicate(matis->A,op,&localmat)); 21269566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(localmat,matis->A->rmap->mapping,matis->A->cmap->mapping)); 21279566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B,localmat)); 21289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&localmat)); 21299566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 21309566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 2131ad6194a2SStefano Zampini *newmat = B; 2132ad6194a2SStefano Zampini PetscFunctionReturn(0); 2133ad6194a2SStefano Zampini } 2134ad6194a2SStefano Zampini 2135a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool *flg) 213669796d55SStefano Zampini { 213769796d55SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 213869796d55SStefano Zampini PetscBool local_sym; 213969796d55SStefano Zampini 214069796d55SStefano Zampini PetscFunctionBegin; 21419566063dSJacob Faibussowitsch PetscCall(MatIsHermitian(matis->A,tol,&local_sym)); 21421c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A))); 214369796d55SStefano Zampini PetscFunctionReturn(0); 214469796d55SStefano Zampini } 214569796d55SStefano Zampini 2146a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg) 214769796d55SStefano Zampini { 214869796d55SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 214969796d55SStefano Zampini PetscBool local_sym; 215069796d55SStefano Zampini 215169796d55SStefano Zampini PetscFunctionBegin; 2152e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 2153e432b41dSStefano Zampini *flg = PETSC_FALSE; 2154e432b41dSStefano Zampini PetscFunctionReturn(0); 2155e432b41dSStefano Zampini } 21569566063dSJacob Faibussowitsch PetscCall(MatIsSymmetric(matis->A,tol,&local_sym)); 21571c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A))); 215869796d55SStefano Zampini PetscFunctionReturn(0); 215969796d55SStefano Zampini } 216069796d55SStefano Zampini 216145471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool *flg) 216245471136SStefano Zampini { 216345471136SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 216445471136SStefano Zampini PetscBool local_sym; 216545471136SStefano Zampini 216645471136SStefano Zampini PetscFunctionBegin; 2167e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 216845471136SStefano Zampini *flg = PETSC_FALSE; 216945471136SStefano Zampini PetscFunctionReturn(0); 217045471136SStefano Zampini } 21719566063dSJacob Faibussowitsch PetscCall(MatIsStructurallySymmetric(matis->A,&local_sym)); 21721c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A))); 217345471136SStefano Zampini PetscFunctionReturn(0); 217445471136SStefano Zampini } 217545471136SStefano Zampini 2176a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A) 2177b4319ba4SBarry Smith { 2178b4319ba4SBarry Smith Mat_IS *b = (Mat_IS*)A->data; 2179b4319ba4SBarry Smith 2180b4319ba4SBarry Smith PetscFunctionBegin; 21819566063dSJacob Faibussowitsch PetscCall(PetscFree(b->bdiag)); 21829566063dSJacob Faibussowitsch PetscCall(PetscFree(b->lmattype)); 21839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 21849566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->cctx)); 21859566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->rctx)); 21869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->x)); 21879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->y)); 21889566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->counter)); 21899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_ris)); 21909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_cis)); 2191a8116848SStefano Zampini if (b->sf != b->csf) { 21929566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->csf)); 21939566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->csf_rootdata,b->csf_leafdata)); 2194f03112d0SStefano Zampini } else b->csf = NULL; 21959566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->sf)); 21969566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->sf_rootdata,b->sf_leafdata)); 21979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->rmapping)); 21989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->cmapping)); 2199*d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->dA)); 2200*d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->assembledA)); 22019566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 22029566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A,NULL)); 22039566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",NULL)); 22049566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL)); 22059566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL)); 22069566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL)); 22079566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL)); 22089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL)); 22099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL)); 22109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalToGlobalMapping_C",NULL)); 22119566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL)); 22129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL)); 22139566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL)); 22149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL)); 22159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL)); 22169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL)); 22179566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL)); 22189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOOLocal_C",NULL)); 22199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",NULL)); 22209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",NULL)); 2221b4319ba4SBarry Smith PetscFunctionReturn(0); 2222b4319ba4SBarry Smith } 2223b4319ba4SBarry Smith 2224a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y) 2225b4319ba4SBarry Smith { 2226b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 2227b4319ba4SBarry Smith PetscScalar zero = 0.0; 2228b4319ba4SBarry Smith 2229b4319ba4SBarry Smith PetscFunctionBegin; 2230b4319ba4SBarry Smith /* scatter the global vector x into the local work vector */ 22319566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD)); 22329566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD)); 2233b4319ba4SBarry Smith 2234b4319ba4SBarry Smith /* multiply the local matrix */ 22359566063dSJacob Faibussowitsch PetscCall(MatMult(is->A,is->x,is->y)); 2236b4319ba4SBarry Smith 2237b4319ba4SBarry Smith /* scatter product back into global memory */ 22389566063dSJacob Faibussowitsch PetscCall(VecSet(y,zero)); 22399566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE)); 22409566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE)); 2241b4319ba4SBarry Smith PetscFunctionReturn(0); 2242b4319ba4SBarry Smith } 2243b4319ba4SBarry Smith 2244a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 22452e74eeadSLisandro Dalcin { 2246650997f4SStefano Zampini Vec temp_vec; 22472e74eeadSLisandro Dalcin 22482e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 2249650997f4SStefano Zampini if (v3 != v2) { 22509566063dSJacob Faibussowitsch PetscCall(MatMult(A,v1,v3)); 22519566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3,1.0,v2)); 2252650997f4SStefano Zampini } else { 22539566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2,&temp_vec)); 22549566063dSJacob Faibussowitsch PetscCall(MatMult(A,v1,temp_vec)); 22559566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec,1.0,v2)); 22569566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec,v3)); 22579566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2258650997f4SStefano Zampini } 22592e74eeadSLisandro Dalcin PetscFunctionReturn(0); 22602e74eeadSLisandro Dalcin } 22612e74eeadSLisandro Dalcin 2262a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x) 22632e74eeadSLisandro Dalcin { 22642e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 22652e74eeadSLisandro Dalcin 2266e176bc59SStefano Zampini PetscFunctionBegin; 22672e74eeadSLisandro Dalcin /* scatter the global vector x into the local work vector */ 22689566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD)); 22699566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD)); 22702e74eeadSLisandro Dalcin 22712e74eeadSLisandro Dalcin /* multiply the local matrix */ 22729566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(is->A,is->y,is->x)); 22732e74eeadSLisandro Dalcin 22742e74eeadSLisandro Dalcin /* scatter product back into global vector */ 22759566063dSJacob Faibussowitsch PetscCall(VecSet(x,0)); 22769566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE)); 22779566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE)); 22782e74eeadSLisandro Dalcin PetscFunctionReturn(0); 22792e74eeadSLisandro Dalcin } 22802e74eeadSLisandro Dalcin 2281a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 22822e74eeadSLisandro Dalcin { 2283650997f4SStefano Zampini Vec temp_vec; 22842e74eeadSLisandro Dalcin 22852e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 2286650997f4SStefano Zampini if (v3 != v2) { 22879566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A,v1,v3)); 22889566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3,1.0,v2)); 2289650997f4SStefano Zampini } else { 22909566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2,&temp_vec)); 22919566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A,v1,temp_vec)); 22929566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec,1.0,v2)); 22939566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec,v3)); 22949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2295650997f4SStefano Zampini } 22962e74eeadSLisandro Dalcin PetscFunctionReturn(0); 22972e74eeadSLisandro Dalcin } 22982e74eeadSLisandro Dalcin 2299a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer) 2300b4319ba4SBarry Smith { 2301b4319ba4SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 2302b4319ba4SBarry Smith PetscViewer sviewer; 2303ee2491ecSStefano Zampini PetscBool isascii,view = PETSC_TRUE; 2304b4319ba4SBarry Smith 2305b4319ba4SBarry Smith PetscFunctionBegin; 23069566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii)); 2307ee2491ecSStefano Zampini if (isascii) { 2308ee2491ecSStefano Zampini PetscViewerFormat format; 2309ee2491ecSStefano Zampini 23109566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer,&format)); 2311ee2491ecSStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE; 2312ee2491ecSStefano Zampini } 2313ee2491ecSStefano Zampini if (!view) PetscFunctionReturn(0); 23149566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer)); 23159566063dSJacob Faibussowitsch PetscCall(MatView(a->A,sviewer)); 23169566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer)); 23179566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 2318b4319ba4SBarry Smith PetscFunctionReturn(0); 2319b4319ba4SBarry Smith } 2320b4319ba4SBarry Smith 2321b89f26deSStefano Zampini static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat,const PetscScalar **values) 2322b89f26deSStefano Zampini { 2323b89f26deSStefano Zampini Mat_IS *is = (Mat_IS*)mat->data; 2324b89f26deSStefano Zampini MPI_Datatype nodeType; 2325b89f26deSStefano Zampini const PetscScalar *lv; 2326b89f26deSStefano Zampini PetscInt bs; 2327b89f26deSStefano Zampini 2328b89f26deSStefano Zampini PetscFunctionBegin; 23299566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(mat,&bs)); 23309566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(is->A,bs)); 23319566063dSJacob Faibussowitsch PetscCall(MatInvertBlockDiagonal(is->A,&lv)); 2332b89f26deSStefano Zampini if (!is->bdiag) { 23339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bs*mat->rmap->n,&is->bdiag)); 2334b89f26deSStefano Zampini } 23359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(bs,MPIU_SCALAR,&nodeType)); 23369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType)); 23379566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(is->sf,nodeType,lv,is->bdiag,MPI_REPLACE)); 23389566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(is->sf,nodeType,lv,is->bdiag,MPI_REPLACE)); 23399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType)); 2340b89f26deSStefano Zampini if (values) *values = is->bdiag; 2341b89f26deSStefano Zampini PetscFunctionReturn(0); 2342b89f26deSStefano Zampini } 2343b89f26deSStefano Zampini 23448546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat A) 2345b4319ba4SBarry Smith { 2346e176bc59SStefano Zampini Vec cglobal,rglobal; 23478546b261SStefano Zampini IS from; 23488546b261SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 2349b89f26deSStefano Zampini PetscScalar sum; 23508546b261SStefano Zampini const PetscInt *garray; 23518546b261SStefano Zampini PetscInt nr,rbs,nc,cbs; 2352e432b41dSStefano Zampini VecType rtype; 2353b4319ba4SBarry Smith 2354b4319ba4SBarry Smith PetscFunctionBegin; 23559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping,&nr)); 23569566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping,&rbs)); 23579566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping,&nc)); 23589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping,&cbs)); 23599566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->x)); 23609566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->y)); 23619566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->counter)); 23629566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->rctx)); 23639566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->cctx)); 23649566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(is->A,&is->x,&is->y)); 23659566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y,PETSC_TRUE)); 23669566063dSJacob Faibussowitsch PetscCall(VecGetRootType_Private(is->y,&rtype)); 23679566063dSJacob Faibussowitsch PetscCall(PetscFree(A->defaultvectype)); 23689566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(rtype,&A->defaultvectype)); 23699566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A,&cglobal,&rglobal)); 23709566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(rglobal,PETSC_TRUE)); 23719566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping,&garray)); 23729566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from)); 23739566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(rglobal,from,is->y,NULL,&is->rctx)); 23749566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping,&garray)); 23759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 2376e432b41dSStefano Zampini if (is->rmapping != is->cmapping) { 23779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping,&garray)); 23789566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from)); 23799566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cglobal,from,is->x,NULL,&is->cctx)); 23809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping,&garray)); 23819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 23828546b261SStefano Zampini } else { 23839566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rctx)); 23848546b261SStefano Zampini is->cctx = is->rctx; 23858546b261SStefano Zampini } 23869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobal)); 2387b89f26deSStefano Zampini 23888546b261SStefano Zampini /* interface counter vector (local) */ 23899566063dSJacob Faibussowitsch PetscCall(VecDuplicate(is->y,&is->counter)); 23909566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter,PETSC_TRUE)); 23919566063dSJacob Faibussowitsch PetscCall(VecSet(is->y,1.)); 23929566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE)); 23939566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE)); 23949566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD)); 23959566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD)); 23969566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y,PETSC_FALSE)); 23979566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter,PETSC_FALSE)); 2398b89f26deSStefano Zampini 2399b89f26deSStefano Zampini /* special functions for block-diagonal matrices */ 24009566063dSJacob Faibussowitsch PetscCall(VecSum(rglobal,&sum)); 2401b89f26deSStefano Zampini A->ops->invertblockdiagonal = NULL; 2402e432b41dSStefano Zampini if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && is->rmapping == is->cmapping) A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS; 24039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rglobal)); 2404b0cc1f67SStefano Zampini 2405b0cc1f67SStefano Zampini /* setup SF for general purpose shared indices based communications */ 24069566063dSJacob Faibussowitsch PetscCall(MatISSetUpSF_IS(A)); 24078546b261SStefano Zampini PetscFunctionReturn(0); 24088546b261SStefano Zampini } 24098546b261SStefano Zampini 2410e432b41dSStefano Zampini static PetscErrorCode MatISFilterL2GMap(Mat A, ISLocalToGlobalMapping map, ISLocalToGlobalMapping *nmap, ISLocalToGlobalMapping *lmap) 2411e432b41dSStefano Zampini { 2412e432b41dSStefano Zampini IS is; 2413e432b41dSStefano Zampini ISLocalToGlobalMappingType l2gtype; 2414e432b41dSStefano Zampini const PetscInt *idxs; 2415e432b41dSStefano Zampini PetscHSetI ht; 2416e432b41dSStefano Zampini PetscInt *nidxs; 2417e432b41dSStefano Zampini PetscInt i,n,bs,c; 2418e432b41dSStefano Zampini PetscBool flg[] = {PETSC_FALSE,PETSC_FALSE}; 2419e432b41dSStefano Zampini 2420e432b41dSStefano Zampini PetscFunctionBegin; 24219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(map,&n)); 24229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(map,&bs)); 24239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(map,&idxs)); 24249566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 24259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n/bs,&nidxs)); 2426e432b41dSStefano Zampini for (i=0,c=0;i<n/bs;i++) { 2427e432b41dSStefano Zampini PetscBool missing; 2428e432b41dSStefano Zampini if (idxs[i] < 0) { flg[0] = PETSC_TRUE; continue; } 24299566063dSJacob Faibussowitsch PetscCall(PetscHSetIQueryAdd(ht,idxs[i],&missing)); 2430e432b41dSStefano Zampini if (!missing) flg[1] = PETSC_TRUE; 2431e432b41dSStefano Zampini else nidxs[c++] = idxs[i]; 2432e432b41dSStefano Zampini } 24339566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 24341c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(MPI_IN_PLACE,flg,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A))); 2435e432b41dSStefano Zampini if (!flg[0] && !flg[1]) { /* Entries are all non negative and unique */ 2436e432b41dSStefano Zampini *nmap = NULL; 2437e432b41dSStefano Zampini *lmap = NULL; 24389566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 24399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map,&idxs)); 2440e432b41dSStefano Zampini PetscFunctionReturn(0); 2441e432b41dSStefano Zampini } 2442e432b41dSStefano Zampini 2443e432b41dSStefano Zampini /* New l2g map without negative or repeated indices */ 24449566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),bs,c,nidxs,PETSC_USE_POINTER,&is)); 24459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,nmap)); 24469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 24479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetType(map,&l2gtype)); 24489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*nmap,l2gtype)); 2449e432b41dSStefano Zampini 2450e432b41dSStefano Zampini /* New local l2g map for repeated indices */ 24519566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(*nmap,IS_GTOLM_MASK,n/bs,idxs,NULL,nidxs)); 24529566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF,bs,n/bs,nidxs,PETSC_USE_POINTER,&is)); 24539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,lmap)); 24549566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2455e432b41dSStefano Zampini 24569566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 24579566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map,&idxs)); 2458e432b41dSStefano Zampini PetscFunctionReturn(0); 2459e432b41dSStefano Zampini } 2460e432b41dSStefano Zampini 24618546b261SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping) 24628546b261SStefano Zampini { 24638546b261SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 2464e432b41dSStefano Zampini ISLocalToGlobalMapping localrmapping = NULL, localcmapping = NULL; 2465e432b41dSStefano Zampini PetscBool cong, freem[] = { PETSC_FALSE, PETSC_FALSE }; 2466e432b41dSStefano Zampini PetscInt nr,rbs,nc,cbs; 24678546b261SStefano Zampini 24688546b261SStefano Zampini PetscFunctionBegin; 2469fc989267SStefano Zampini if (rmapping) PetscCheckSameComm(A,1,rmapping,2); 2470fc989267SStefano Zampini if (cmapping) PetscCheckSameComm(A,1,cmapping,3); 2471e432b41dSStefano Zampini 24729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->rmapping)); 24739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 24749566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 24759566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 24769566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A,&cong)); 2477e432b41dSStefano Zampini 2478fc989267SStefano Zampini /* If NULL, local space matches global space */ 2479fc989267SStefano Zampini if (!rmapping) { 2480fc989267SStefano Zampini IS is; 2481fc989267SStefano Zampini 24829566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->N,0,1,&is)); 24839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&rmapping)); 24849566063dSJacob Faibussowitsch if (A->rmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(rmapping,A->rmap->bs)); 24859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2486e432b41dSStefano Zampini freem[0] = PETSC_TRUE; 2487e432b41dSStefano Zampini if (!cmapping && cong && A->rmap->bs == A->cmap->bs) cmapping = rmapping; 2488e432b41dSStefano Zampini } else if (!is->islocalref) { /* check if the l2g map has negative or repeated entries */ 24899566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A,rmapping,&is->rmapping,&localrmapping)); 2490e432b41dSStefano Zampini if (rmapping == cmapping) { 24919566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2492e432b41dSStefano Zampini is->cmapping = is->rmapping; 24939566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)localrmapping)); 2494e432b41dSStefano Zampini localcmapping = localrmapping; 2495fc989267SStefano Zampini } 2496fc989267SStefano Zampini } 2497fc989267SStefano Zampini if (!cmapping) { 2498fc989267SStefano Zampini IS is; 2499fc989267SStefano Zampini 25009566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->N,0,1,&is)); 25019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&cmapping)); 25029566063dSJacob Faibussowitsch if (A->cmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(cmapping,A->cmap->bs)); 25039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2504e432b41dSStefano Zampini freem[1] = PETSC_TRUE; 2505e432b41dSStefano Zampini } else if (cmapping != rmapping && !is->islocalref) { /* check if the l2g map has negative or repeated entries */ 25069566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A,cmapping,&is->cmapping,&localcmapping)); 2507e432b41dSStefano Zampini } 2508e432b41dSStefano Zampini if (!is->rmapping) { 25099566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rmapping)); 2510e432b41dSStefano Zampini is->rmapping = rmapping; 2511e432b41dSStefano Zampini } 2512e432b41dSStefano Zampini if (!is->cmapping) { 25139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cmapping)); 2514e432b41dSStefano Zampini is->cmapping = cmapping; 2515fc989267SStefano Zampini } 2516fc989267SStefano Zampini 2517fc989267SStefano Zampini /* Clean up */ 25189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 2519872cf891SStefano Zampini if (is->csf != is->sf) { 25209566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->csf)); 25219566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->csf_rootdata,is->csf_leafdata)); 2522f03112d0SStefano Zampini } else is->csf = NULL; 25239566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->sf)); 25249566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->sf_rootdata,is->sf_leafdata)); 25259566063dSJacob Faibussowitsch PetscCall(PetscFree(is->bdiag)); 25263bbff08aSStefano Zampini 2527fc989267SStefano Zampini /* check if the two mappings are actually the same for square matrices since MATIS has some optimization for this case 2528fc989267SStefano Zampini (DOLFIN passes 2 different objects) */ 25299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping,&nr)); 25309566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping,&rbs)); 25319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping,&nc)); 25329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping,&cbs)); 2533e432b41dSStefano Zampini if (is->rmapping != is->cmapping && cong) { 2534e432b41dSStefano Zampini PetscBool same = PETSC_FALSE; 25356625354bSStefano Zampini if (nr == nc && cbs == rbs) { 25366625354bSStefano Zampini const PetscInt *idxs1,*idxs2; 25376625354bSStefano Zampini 25389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping,&idxs1)); 25399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping,&idxs2)); 25409566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1,idxs2,nr/rbs,&same)); 25419566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping,&idxs1)); 25429566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping,&idxs2)); 25436625354bSStefano Zampini } 25441c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(MPI_IN_PLACE,&same,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A))); 2545e432b41dSStefano Zampini if (same) { 25469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 25479566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2548e432b41dSStefano Zampini is->cmapping = is->rmapping; 2549e432b41dSStefano Zampini } 25506625354bSStefano Zampini } 25519566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->rmap,rbs)); 25529566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->cmap,cbs)); 2553e432b41dSStefano Zampini /* Pass the user defined maps to the layout */ 25549566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping)); 25559566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping)); 25569566063dSJacob Faibussowitsch if (freem[0]) PetscCall(ISLocalToGlobalMappingDestroy(&rmapping)); 25579566063dSJacob Faibussowitsch if (freem[1]) PetscCall(ISLocalToGlobalMappingDestroy(&cmapping)); 25586625354bSStefano Zampini 25596625354bSStefano Zampini /* Create the local matrix A */ 25609566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF,&is->A)); 25619566063dSJacob Faibussowitsch PetscCall(MatSetType(is->A,is->lmattype)); 25629566063dSJacob Faibussowitsch PetscCall(MatSetSizes(is->A,nr,nc,nr,nc)); 25639566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(is->A,rbs,cbs)); 25649566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(is->A,"is_")); 25659566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(is->A,((PetscObject)A)->prefix)); 25669566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->rmap)); 25679566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->cmap)); 25689566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(is->A,localrmapping,localcmapping)); 25699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localrmapping)); 25709566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localcmapping)); 2571b4319ba4SBarry Smith 2572fc989267SStefano Zampini /* setup scatters and local vectors for MatMult */ 25739566063dSJacob Faibussowitsch if (!is->islocalref) PetscCall(MatISSetUpScatters_Private(A)); 2574fc989267SStefano Zampini A->preallocated = PETSC_TRUE; 2575fc989267SStefano Zampini PetscFunctionReturn(0); 2576fc989267SStefano Zampini } 2577fc989267SStefano Zampini 2578fc989267SStefano Zampini static PetscErrorCode MatSetUp_IS(Mat A) 2579fc989267SStefano Zampini { 2580fc989267SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 2581fc989267SStefano Zampini 2582fc989267SStefano Zampini PetscFunctionBegin; 25839566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A,&rmap,&cmap)); 2584fc989267SStefano Zampini if (!rmap && !cmap) { 25859566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(A,NULL,NULL)); 2586fc989267SStefano Zampini } 2587b4319ba4SBarry Smith PetscFunctionReturn(0); 2588b4319ba4SBarry Smith } 2589b4319ba4SBarry Smith 2590a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 25912e74eeadSLisandro Dalcin { 25922e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)mat->data; 2593f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 25942e74eeadSLisandro Dalcin 25952e74eeadSLisandro Dalcin PetscFunctionBegin; 25969566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->rmapping,IS_GTOLM_MASK,m,rows,&m,rows_l)); 2597e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 25989566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->cmapping,IS_GTOLM_MASK,n,cols,&n,cols_l)); 25999566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A,m,rows_l,n,cols_l,values,addv)); 2600e432b41dSStefano Zampini } else { 26019566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A,m,rows_l,m,rows_l,values,addv)); 2602e432b41dSStefano Zampini } 26032e74eeadSLisandro Dalcin PetscFunctionReturn(0); 26042e74eeadSLisandro Dalcin } 26052e74eeadSLisandro Dalcin 2606a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 260797563a80SStefano Zampini { 260897563a80SStefano Zampini Mat_IS *is = (Mat_IS*)mat->data; 2609f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 261097563a80SStefano Zampini 261197563a80SStefano Zampini PetscFunctionBegin; 26129566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(is->rmapping,IS_GTOLM_MASK,m,rows,&m,rows_l)); 2613e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 26149566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->cmapping,IS_GTOLM_MASK,n,cols,&n,cols_l)); 26159566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv)); 2616e432b41dSStefano Zampini } else { 26179566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A,m,rows_l,n,rows_l,values,addv)); 2618e432b41dSStefano Zampini } 261997563a80SStefano Zampini PetscFunctionReturn(0); 262097563a80SStefano Zampini } 262197563a80SStefano Zampini 2622a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 2623b4319ba4SBarry Smith { 2624b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 2625b4319ba4SBarry Smith 2626b4319ba4SBarry Smith PetscFunctionBegin; 2627e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 26289566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(is->A,m,rows,n,cols,values,addv)); 2629872cf891SStefano Zampini } else { 26309566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A,m,rows,n,cols,values,addv)); 2631872cf891SStefano Zampini } 2632b4319ba4SBarry Smith PetscFunctionReturn(0); 2633b4319ba4SBarry Smith } 2634b4319ba4SBarry Smith 2635a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 2636f0006bf2SLisandro Dalcin { 2637f0006bf2SLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 2638f0006bf2SLisandro Dalcin 2639f0006bf2SLisandro Dalcin PetscFunctionBegin; 2640e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 26419566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv)); 2642b4f971dfSStefano Zampini } else { 26439566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv)); 2644b4f971dfSStefano Zampini } 2645f0006bf2SLisandro Dalcin PetscFunctionReturn(0); 2646f0006bf2SLisandro Dalcin } 2647f0006bf2SLisandro Dalcin 2648f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns) 2649f0ae7da4SStefano Zampini { 2650f0ae7da4SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 2651f0ae7da4SStefano Zampini 2652f0ae7da4SStefano Zampini PetscFunctionBegin; 2653f0ae7da4SStefano Zampini if (!n) { 2654f0ae7da4SStefano Zampini is->pure_neumann = PETSC_TRUE; 2655f0ae7da4SStefano Zampini } else { 2656f0ae7da4SStefano Zampini PetscInt i; 2657f0ae7da4SStefano Zampini is->pure_neumann = PETSC_FALSE; 2658f0ae7da4SStefano Zampini 2659f0ae7da4SStefano Zampini if (columns) { 26609566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns(is->A,n,rows,diag,NULL,NULL)); 2661f0ae7da4SStefano Zampini } else { 26629566063dSJacob Faibussowitsch PetscCall(MatZeroRows(is->A,n,rows,diag,NULL,NULL)); 2663f0ae7da4SStefano Zampini } 2664f0ae7da4SStefano Zampini if (diag != 0.) { 2665f0ae7da4SStefano Zampini const PetscScalar *array; 26669566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(is->counter,&array)); 2667f0ae7da4SStefano Zampini for (i=0; i<n; i++) { 26689566063dSJacob Faibussowitsch PetscCall(MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES)); 2669f0ae7da4SStefano Zampini } 26709566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(is->counter,&array)); 2671f0ae7da4SStefano Zampini } 26729566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY)); 26739566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY)); 2674f0ae7da4SStefano Zampini } 2675f0ae7da4SStefano Zampini PetscFunctionReturn(0); 2676f0ae7da4SStefano Zampini } 2677f0ae7da4SStefano Zampini 2678f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns) 26792e74eeadSLisandro Dalcin { 26806e520ac8SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 26816e520ac8SStefano Zampini PetscInt nr,nl,len,i; 26826e520ac8SStefano Zampini PetscInt *lrows; 26832e74eeadSLisandro Dalcin 26842e74eeadSLisandro Dalcin PetscFunctionBegin; 2685cf9c20a2SJed Brown if (PetscUnlikelyDebug(columns || diag != 0. || (x && b))) { 2686f0ae7da4SStefano Zampini PetscBool cong; 268726b0207aSStefano Zampini 26889566063dSJacob Faibussowitsch PetscCall(PetscLayoutCompare(A->rmap,A->cmap,&cong)); 268926b0207aSStefano Zampini cong = (PetscBool)(cong && matis->sf == matis->csf); 269008401ef6SPierre Jolivet PetscCheck(cong || !columns,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Columns can be zeroed if and only if A->rmap and A->cmap are congruent and the l2g maps are the same for MATIS"); 2691aed4548fSBarry Smith PetscCheck(cong || diag == 0.,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Nonzero diagonal value supported if and only if A->rmap and A->cmap are congruent and the l2g maps are the same for MATIS"); 2692aed4548fSBarry Smith PetscCheck(cong || !x || !b,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent, and the l2g maps be the same"); 2693f0ae7da4SStefano Zampini } 26946e520ac8SStefano Zampini /* get locally owned rows */ 26959566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(A->rmap,n,rows,&len,&lrows,NULL)); 26966e520ac8SStefano Zampini /* fix right hand side if needed */ 26976e520ac8SStefano Zampini if (x && b) { 26986e520ac8SStefano Zampini const PetscScalar *xx; 26996e520ac8SStefano Zampini PetscScalar *bb; 27006e520ac8SStefano Zampini 27019566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 27029566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 27036e520ac8SStefano Zampini for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]]; 27049566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 27059566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 27062e74eeadSLisandro Dalcin } 27076e520ac8SStefano Zampini /* get rows associated to the local matrices */ 27089566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A,&nl,NULL)); 27099566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata,nl)); 27109566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata,A->rmap->n)); 27116e520ac8SStefano Zampini for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1; 27129566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 27139566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 27149566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 27159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl,&lrows)); 27166e520ac8SStefano Zampini for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i; 27179566063dSJacob Faibussowitsch PetscCall(MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns)); 27189566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 2719*d0dbe9f7SStefano Zampini PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY)); 2720*d0dbe9f7SStefano Zampini PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY)); 27212e74eeadSLisandro Dalcin PetscFunctionReturn(0); 27222e74eeadSLisandro Dalcin } 27232e74eeadSLisandro Dalcin 2724f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 2725b4319ba4SBarry Smith { 2726b4319ba4SBarry Smith PetscFunctionBegin; 27279566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE)); 2728f0ae7da4SStefano Zampini PetscFunctionReturn(0); 2729f0ae7da4SStefano Zampini } 27302205254eSKarl Rupp 2731f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 2732f0ae7da4SStefano Zampini { 2733f0ae7da4SStefano Zampini PetscFunctionBegin; 27349566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE)); 2735b4319ba4SBarry Smith PetscFunctionReturn(0); 2736b4319ba4SBarry Smith } 2737b4319ba4SBarry Smith 2738a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type) 2739b4319ba4SBarry Smith { 2740b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 2741b4319ba4SBarry Smith 2742b4319ba4SBarry Smith PetscFunctionBegin; 27439566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A,type)); 2744b4319ba4SBarry Smith PetscFunctionReturn(0); 2745b4319ba4SBarry Smith } 2746b4319ba4SBarry Smith 2747a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type) 2748b4319ba4SBarry Smith { 2749b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 2750*d0dbe9f7SStefano Zampini PetscBool lnnz; 2751b4319ba4SBarry Smith 2752b4319ba4SBarry Smith PetscFunctionBegin; 27539566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A,type)); 2754872cf891SStefano Zampini /* fix for local empty rows/cols */ 2755872cf891SStefano Zampini if (is->locempty && type == MAT_FINAL_ASSEMBLY) { 2756872cf891SStefano Zampini Mat newlA; 2757f03112d0SStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 2758f03112d0SStefano Zampini IS nzr,nzc; 2759f03112d0SStefano Zampini PetscInt nr,nc,nnzr,nnzc; 2760f03112d0SStefano Zampini PetscBool lnewl2g,newl2g; 2761872cf891SStefano Zampini 27629566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A,&nr,&nc)); 27639566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr)); 2764f03112d0SStefano Zampini if (!nzr) { 27659566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr)); 2766872cf891SStefano Zampini } 27679566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc)); 2768f03112d0SStefano Zampini if (!nzc) { 27699566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc)); 2770872cf891SStefano Zampini } 27719566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzr,&nnzr)); 27729566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzc,&nnzc)); 2773e432b41dSStefano Zampini if (nnzr != nr || nnzc != nc) { /* need new global l2g map */ 2774f03112d0SStefano Zampini lnewl2g = PETSC_TRUE; 27759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A))); 2776f03112d0SStefano Zampini 2777872cf891SStefano Zampini /* extract valid submatrix */ 27789566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA)); 2779f03112d0SStefano Zampini } else { /* local matrix fully populated */ 2780f03112d0SStefano Zampini lnewl2g = PETSC_FALSE; 27819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A))); 27829566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->A)); 2783f03112d0SStefano Zampini newlA = is->A; 2784f03112d0SStefano Zampini } 2785e432b41dSStefano Zampini 2786f03112d0SStefano Zampini /* attach new global l2g map if needed */ 2787f03112d0SStefano Zampini if (newl2g) { 2788e432b41dSStefano Zampini IS zr,zc; 2789e432b41dSStefano Zampini const PetscInt *ridxs,*cidxs,*zridxs,*zcidxs; 2790e432b41dSStefano Zampini PetscInt *nidxs,i; 2791f03112d0SStefano Zampini 27929566063dSJacob Faibussowitsch PetscCall(ISComplement(nzr,0,nr,&zr)); 27939566063dSJacob Faibussowitsch PetscCall(ISComplement(nzc,0,nc,&zc)); 27949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(nr,nc),&nidxs)); 27959566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->rmapping,&ridxs)); 27969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->cmapping,&cidxs)); 27979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zr,&zridxs)); 27989566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zc,&zcidxs)); 27999566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zr,&nnzr)); 28009566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zc,&nnzc)); 2801e432b41dSStefano Zampini 28029566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs,ridxs,nr)); 2803e432b41dSStefano Zampini for (i = 0; i < nnzr; i++) nidxs[zridxs[i]] = -1; 28049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nr,nidxs,PETSC_COPY_VALUES,&rl2g)); 28059566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs,cidxs,nc)); 2806e432b41dSStefano Zampini for (i = 0; i < nnzc; i++) nidxs[zcidxs[i]] = -1; 28079566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nc,nidxs,PETSC_COPY_VALUES,&cl2g)); 2808e432b41dSStefano Zampini 28099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zr,&zridxs)); 28109566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zc,&zcidxs)); 28119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->rmapping,&ridxs)); 28129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->cmapping,&cidxs)); 28139566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 28149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 28159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zr)); 28169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zc)); 28179566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 28189566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(A,rl2g,cl2g)); 28199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 28209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 2821f03112d0SStefano Zampini } 28229566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(A,newlA)); 28239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlA)); 28249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 28259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 2826872cf891SStefano Zampini is->locempty = PETSC_FALSE; 2827f03112d0SStefano Zampini } 2828*d0dbe9f7SStefano Zampini lnnz = (PetscBool)(is->A->nonzerostate == is->lnnzstate); 2829*d0dbe9f7SStefano Zampini is->lnnzstate = is->A->nonzerostate; 2830*d0dbe9f7SStefano Zampini PetscCall(MPIU_Allreduce(MPI_IN_PLACE,&lnnz,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A))); 2831*d0dbe9f7SStefano Zampini if (lnnz) A->nonzerostate++; 2832b4319ba4SBarry Smith PetscFunctionReturn(0); 2833b4319ba4SBarry Smith } 2834b4319ba4SBarry Smith 2835a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local) 2836b4319ba4SBarry Smith { 2837b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)mat->data; 2838b4319ba4SBarry Smith 2839b4319ba4SBarry Smith PetscFunctionBegin; 2840b4319ba4SBarry Smith *local = is->A; 2841b4319ba4SBarry Smith PetscFunctionReturn(0); 2842b4319ba4SBarry Smith } 2843b4319ba4SBarry Smith 28443b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local) 28453b3b1effSJed Brown { 28463b3b1effSJed Brown PetscFunctionBegin; 28473b3b1effSJed Brown *local = NULL; 28483b3b1effSJed Brown PetscFunctionReturn(0); 28493b3b1effSJed Brown } 28503b3b1effSJed Brown 2851b4319ba4SBarry Smith /*@ 2852b4319ba4SBarry Smith MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix. 2853b4319ba4SBarry Smith 2854b4319ba4SBarry Smith Input Parameter: 2855b4319ba4SBarry Smith . mat - the matrix 2856b4319ba4SBarry Smith 2857b4319ba4SBarry Smith Output Parameter: 2858eb82efa4SStefano Zampini . local - the local matrix 2859b4319ba4SBarry Smith 2860b4319ba4SBarry Smith Level: advanced 2861b4319ba4SBarry Smith 2862b4319ba4SBarry Smith Notes: 2863b4319ba4SBarry Smith This can be called if you have precomputed the nonzero structure of the 2864b4319ba4SBarry Smith matrix and want to provide it to the inner matrix object to improve the performance 2865b4319ba4SBarry Smith of the MatSetValues() operation. 2866b4319ba4SBarry Smith 28673b3b1effSJed Brown Call MatISRestoreLocalMat() when finished with the local matrix. 286896a6f129SJed Brown 2869db781477SPatrick Sanan .seealso: `MATIS` 2870b4319ba4SBarry Smith @*/ 28717087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local) 2872b4319ba4SBarry Smith { 2873b4319ba4SBarry Smith PetscFunctionBegin; 28740700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2875b4319ba4SBarry Smith PetscValidPointer(local,2); 2876cac4c232SBarry Smith PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local)); 2877b4319ba4SBarry Smith PetscFunctionReturn(0); 2878b4319ba4SBarry Smith } 2879b4319ba4SBarry Smith 28803b3b1effSJed Brown /*@ 28813b3b1effSJed Brown MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat() 28823b3b1effSJed Brown 28833b3b1effSJed Brown Input Parameter: 28843b3b1effSJed Brown . mat - the matrix 28853b3b1effSJed Brown 28863b3b1effSJed Brown Output Parameter: 28873b3b1effSJed Brown . local - the local matrix 28883b3b1effSJed Brown 28893b3b1effSJed Brown Level: advanced 28903b3b1effSJed Brown 2891db781477SPatrick Sanan .seealso: `MATIS` 28923b3b1effSJed Brown @*/ 28933b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local) 28943b3b1effSJed Brown { 28953b3b1effSJed Brown PetscFunctionBegin; 28963b3b1effSJed Brown PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 28973b3b1effSJed Brown PetscValidPointer(local,2); 2898cac4c232SBarry Smith PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local)); 28993b3b1effSJed Brown PetscFunctionReturn(0); 29003b3b1effSJed Brown } 29013b3b1effSJed Brown 29028546b261SStefano Zampini static PetscErrorCode MatISSetLocalMatType_IS(Mat mat,MatType mtype) 29038546b261SStefano Zampini { 29048546b261SStefano Zampini Mat_IS *is = (Mat_IS*)mat->data; 29058546b261SStefano Zampini 29068546b261SStefano Zampini PetscFunctionBegin; 29078546b261SStefano Zampini if (is->A) { 29089566063dSJacob Faibussowitsch PetscCall(MatSetType(is->A,mtype)); 29098546b261SStefano Zampini } 29109566063dSJacob Faibussowitsch PetscCall(PetscFree(is->lmattype)); 29119566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(mtype,&is->lmattype)); 29128546b261SStefano Zampini PetscFunctionReturn(0); 29138546b261SStefano Zampini } 29148546b261SStefano Zampini 29158546b261SStefano Zampini /*@ 29168546b261SStefano Zampini MatISSetLocalMatType - Specifies the type of local matrix 29178546b261SStefano Zampini 2918d8d19677SJose E. Roman Input Parameters: 2919a2b725a8SWilliam Gropp + mat - the matrix 2920a2b725a8SWilliam Gropp - mtype - the local matrix type 29218546b261SStefano Zampini 29228546b261SStefano Zampini Output Parameter: 29238546b261SStefano Zampini 29248546b261SStefano Zampini Level: advanced 29258546b261SStefano Zampini 2926db781477SPatrick Sanan .seealso: `MATIS`, `MatSetType()`, `MatType` 29278546b261SStefano Zampini @*/ 29288546b261SStefano Zampini PetscErrorCode MatISSetLocalMatType(Mat mat,MatType mtype) 29298546b261SStefano Zampini { 29308546b261SStefano Zampini PetscFunctionBegin; 29318546b261SStefano Zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2932cac4c232SBarry Smith PetscUseMethod(mat,"MatISSetLocalMatType_C",(Mat,MatType),(mat,mtype)); 29338546b261SStefano Zampini PetscFunctionReturn(0); 29348546b261SStefano Zampini } 29358546b261SStefano Zampini 2936a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local) 29373b03a366Sstefano_zampini { 29383b03a366Sstefano_zampini Mat_IS *is = (Mat_IS*)mat->data; 29393b03a366Sstefano_zampini PetscInt nrows,ncols,orows,ocols; 29408546b261SStefano Zampini MatType mtype,otype; 29418546b261SStefano Zampini PetscBool sametype = PETSC_TRUE; 29423b03a366Sstefano_zampini 29433b03a366Sstefano_zampini PetscFunctionBegin; 2944e432b41dSStefano Zampini if (is->A && !is->islocalref) { 29459566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A,&orows,&ocols)); 29469566063dSJacob Faibussowitsch PetscCall(MatGetSize(local,&nrows,&ncols)); 2947aed4548fSBarry Smith PetscCheck(orows == nrows && ocols == ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %" PetscInt_FMT "x%" PetscInt_FMT " (you passed a %" PetscInt_FMT "x%" PetscInt_FMT " matrix)",orows,ocols,nrows,ncols); 29489566063dSJacob Faibussowitsch PetscCall(MatGetType(local,&mtype)); 29499566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A,&otype)); 29509566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype,otype,&sametype)); 29514e4c7dbeSStefano Zampini } 29529566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)local)); 29539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 29543b03a366Sstefano_zampini is->A = local; 29559566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A,&mtype)); 29569566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(mat,mtype)); 29578546b261SStefano Zampini if (!sametype && !is->islocalref) { 29589566063dSJacob Faibussowitsch PetscCall(MatISSetUpScatters_Private(mat)); 29598546b261SStefano Zampini } 29603b03a366Sstefano_zampini PetscFunctionReturn(0); 29613b03a366Sstefano_zampini } 29623b03a366Sstefano_zampini 29633b03a366Sstefano_zampini /*@ 2964eb82efa4SStefano Zampini MatISSetLocalMat - Replace the local matrix stored inside a MATIS object. 29653b03a366Sstefano_zampini 29668546b261SStefano Zampini Collective on Mat 29678546b261SStefano Zampini 2968d8d19677SJose E. Roman Input Parameters: 2969a2b725a8SWilliam Gropp + mat - the matrix 2970a2b725a8SWilliam Gropp - local - the local matrix 29713b03a366Sstefano_zampini 29723b03a366Sstefano_zampini Output Parameter: 29733b03a366Sstefano_zampini 29743b03a366Sstefano_zampini Level: advanced 29753b03a366Sstefano_zampini 29763b03a366Sstefano_zampini Notes: 29773b03a366Sstefano_zampini This can be called if you have precomputed the local matrix and 29783b03a366Sstefano_zampini want to provide it to the matrix object MATIS. 29793b03a366Sstefano_zampini 2980db781477SPatrick Sanan .seealso: `MATIS` 29813b03a366Sstefano_zampini @*/ 29823b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local) 29833b03a366Sstefano_zampini { 29843b03a366Sstefano_zampini PetscFunctionBegin; 29853b03a366Sstefano_zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2986b7ce53b6SStefano Zampini PetscValidHeaderSpecific(local,MAT_CLASSID,2); 2987cac4c232SBarry Smith PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local)); 29883b03a366Sstefano_zampini PetscFunctionReturn(0); 29893b03a366Sstefano_zampini } 29903b03a366Sstefano_zampini 2991a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A) 29926726f965SBarry Smith { 29936726f965SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 29946726f965SBarry Smith 29956726f965SBarry Smith PetscFunctionBegin; 29969566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(a->A)); 29976726f965SBarry Smith PetscFunctionReturn(0); 29986726f965SBarry Smith } 29996726f965SBarry Smith 3000a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a) 30012e74eeadSLisandro Dalcin { 30022e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 30032e74eeadSLisandro Dalcin 30042e74eeadSLisandro Dalcin PetscFunctionBegin; 30059566063dSJacob Faibussowitsch PetscCall(MatScale(is->A,a)); 30062e74eeadSLisandro Dalcin PetscFunctionReturn(0); 30072e74eeadSLisandro Dalcin } 30082e74eeadSLisandro Dalcin 3009a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 30102e74eeadSLisandro Dalcin { 30112e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 30122e74eeadSLisandro Dalcin 30132e74eeadSLisandro Dalcin PetscFunctionBegin; 30142e74eeadSLisandro Dalcin /* get diagonal of the local matrix */ 30159566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(is->A,is->y)); 30162e74eeadSLisandro Dalcin 30172e74eeadSLisandro Dalcin /* scatter diagonal back into global vector */ 30189566063dSJacob Faibussowitsch PetscCall(VecSet(v,0)); 30199566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE)); 30209566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE)); 30212e74eeadSLisandro Dalcin PetscFunctionReturn(0); 30222e74eeadSLisandro Dalcin } 30232e74eeadSLisandro Dalcin 3024a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg) 30256726f965SBarry Smith { 30266726f965SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 30276726f965SBarry Smith 30286726f965SBarry Smith PetscFunctionBegin; 30299566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A,op,flg)); 30306726f965SBarry Smith PetscFunctionReturn(0); 30316726f965SBarry Smith } 30326726f965SBarry Smith 3033f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str) 3034f26d0771SStefano Zampini { 3035f26d0771SStefano Zampini Mat_IS *y = (Mat_IS*)Y->data; 3036f26d0771SStefano Zampini Mat_IS *x; 3037f26d0771SStefano Zampini 3038f26d0771SStefano Zampini PetscFunctionBegin; 303976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 304076bd3646SJed Brown PetscBool ismatis; 30419566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis)); 304228b400f6SJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 304376bd3646SJed Brown } 3044f26d0771SStefano Zampini x = (Mat_IS*)X->data; 30459566063dSJacob Faibussowitsch PetscCall(MatAXPY(y->A,a,x->A,str)); 3046f26d0771SStefano Zampini PetscFunctionReturn(0); 3047f26d0771SStefano Zampini } 3048f26d0771SStefano Zampini 3049f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat) 3050f26d0771SStefano Zampini { 3051f26d0771SStefano Zampini Mat lA; 3052e432b41dSStefano Zampini Mat_IS *matis = (Mat_IS*)(A->data); 3053f26d0771SStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 3054f26d0771SStefano Zampini IS is; 3055f26d0771SStefano Zampini const PetscInt *rg,*rl; 3056f26d0771SStefano Zampini PetscInt nrg; 3057f26d0771SStefano Zampini PetscInt N,M,nrl,i,*idxs; 3058f26d0771SStefano Zampini 3059f26d0771SStefano Zampini PetscFunctionBegin; 30609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg)); 30619566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(row,&nrl)); 30629566063dSJacob Faibussowitsch PetscCall(ISGetIndices(row,&rl)); 30639566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg)); 306476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 306508401ef6SPierre Jolivet for (i=0; i<nrl; i++) PetscCheck(rl[i]<nrg,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row index %" PetscInt_FMT " -> %" PetscInt_FMT " greater then maximum possible %" PetscInt_FMT,i,rl[i],nrg); 306676bd3646SJed Brown } 30679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrg,&idxs)); 3068f26d0771SStefano Zampini /* map from [0,nrl) to row */ 3069f26d0771SStefano Zampini for (i=0;i<nrl;i++) idxs[i] = rl[i]; 3070f26d0771SStefano Zampini for (i=nrl;i<nrg;i++) idxs[i] = -1; 30719566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(row,&rl)); 30729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg)); 30739566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is)); 30749566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g)); 30759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3076f26d0771SStefano Zampini /* compute new l2g map for columns */ 3077e432b41dSStefano Zampini if (col != row || matis->rmapping != matis->cmapping || matis->A->rmap->mapping != matis->A->cmap->mapping) { 3078f26d0771SStefano Zampini const PetscInt *cg,*cl; 3079f26d0771SStefano Zampini PetscInt ncg; 3080f26d0771SStefano Zampini PetscInt ncl; 3081f26d0771SStefano Zampini 30829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg)); 30839566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(col,&ncl)); 30849566063dSJacob Faibussowitsch PetscCall(ISGetIndices(col,&cl)); 30859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg)); 308676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 308708401ef6SPierre Jolivet for (i=0; i<ncl; i++) PetscCheck(cl[i]<ncg,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local column index %" PetscInt_FMT " -> %" PetscInt_FMT " greater then maximum possible %" PetscInt_FMT,i,cl[i],ncg); 308876bd3646SJed Brown } 30899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncg,&idxs)); 3090f26d0771SStefano Zampini /* map from [0,ncl) to col */ 3091f26d0771SStefano Zampini for (i=0;i<ncl;i++) idxs[i] = cl[i]; 3092f26d0771SStefano Zampini for (i=ncl;i<ncg;i++) idxs[i] = -1; 30939566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(col,&cl)); 30949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg)); 30959566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is)); 30969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g)); 30979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3098f26d0771SStefano Zampini } else { 30999566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rl2g)); 3100f26d0771SStefano Zampini cl2g = rl2g; 3101f26d0771SStefano Zampini } 3102f26d0771SStefano Zampini /* create the MATIS submatrix */ 31039566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&M,&N)); 31049566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),submat)); 31059566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N)); 31069566063dSJacob Faibussowitsch PetscCall(MatSetType(*submat,MATIS)); 3107b0aa3428SStefano Zampini matis = (Mat_IS*)((*submat)->data); 3108f26d0771SStefano Zampini matis->islocalref = PETSC_TRUE; 31099566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*submat,rl2g,cl2g)); 31109566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A,&lA)); 31119566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*submat,lA)); 31129566063dSJacob Faibussowitsch PetscCall(MatSetUp(*submat)); 31139566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY)); 31149566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY)); 31159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 31169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3117e432b41dSStefano Zampini 3118f26d0771SStefano Zampini /* remove unsupported ops */ 31199566063dSJacob Faibussowitsch PetscCall(PetscMemzero((*submat)->ops,sizeof(struct _MatOps))); 3120f26d0771SStefano Zampini (*submat)->ops->destroy = MatDestroy_IS; 3121f26d0771SStefano Zampini (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 3122f26d0771SStefano Zampini (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 3123f26d0771SStefano Zampini (*submat)->ops->assemblybegin = MatAssemblyBegin_IS; 3124f26d0771SStefano Zampini (*submat)->ops->assemblyend = MatAssemblyEnd_IS; 3125f26d0771SStefano Zampini PetscFunctionReturn(0); 3126f26d0771SStefano Zampini } 3127f26d0771SStefano Zampini 3128872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A) 3129872cf891SStefano Zampini { 3130872cf891SStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 31318546b261SStefano Zampini char type[256]; 31328546b261SStefano Zampini PetscBool flg; 3133872cf891SStefano Zampini 3134872cf891SStefano Zampini PetscFunctionBegin; 3135d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject,"MATIS options"); 3136*d0dbe9f7SStefano Zampini PetscCall(PetscOptionsBool("-matis_keepassembled","Store an assembled version if needed","MatISKeepAssembled",a->keepassembled,&a->keepassembled,NULL)); 31379566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL)); 31389566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL)); 31399566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-matis_localmat_type","Matrix type","MatISSetLocalMatType",MatList,a->lmattype,type,256,&flg)); 31408546b261SStefano Zampini if (flg) { 31419566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(A,type)); 31428546b261SStefano Zampini } 31438546b261SStefano Zampini if (a->A) { 31449566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(a->A)); 31458546b261SStefano Zampini } 3146d0609cedSBarry Smith PetscOptionsHeadEnd(); 3147872cf891SStefano Zampini PetscFunctionReturn(0); 3148872cf891SStefano Zampini } 3149872cf891SStefano Zampini 3150284134d9SBarry Smith /*@ 31513c212e90SHong Zhang MatCreateIS - Creates a "process" unassembled matrix, assembled on each 3152284134d9SBarry Smith process but not across processes. 3153284134d9SBarry Smith 3154284134d9SBarry Smith Input Parameters: 3155284134d9SBarry Smith + comm - MPI communicator that will share the matrix 3156e176bc59SStefano Zampini . bs - block size of the matrix 3157df3898eeSBarry Smith . m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products 3158e176bc59SStefano Zampini . rmap - local to global map for rows 3159e176bc59SStefano Zampini - cmap - local to global map for cols 3160284134d9SBarry Smith 3161284134d9SBarry Smith Output Parameter: 3162284134d9SBarry Smith . A - the resulting matrix 3163284134d9SBarry Smith 31648e6c10adSSatish Balay Level: advanced 31658e6c10adSSatish Balay 316695452b02SPatrick Sanan Notes: 316795452b02SPatrick Sanan See MATIS for more details. 3168fc989267SStefano Zampini m and n are NOT related to the size of the map; they represent the size of the local parts of the distributed vectors 31696fdf41d1SStefano Zampini used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices. 3170fc989267SStefano Zampini If rmap (cmap) is NULL, then the local row (column) spaces matches the global space. 3171284134d9SBarry Smith 3172db781477SPatrick Sanan .seealso: `MATIS`, `MatSetLocalToGlobalMapping()` 3173284134d9SBarry Smith @*/ 3174e176bc59SStefano Zampini PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A) 3175284134d9SBarry Smith { 3176284134d9SBarry Smith PetscFunctionBegin; 31779566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,A)); 31789566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A,m,n,M,N)); 31796fdf41d1SStefano Zampini if (bs > 0) { 31809566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*A,bs)); 31816fdf41d1SStefano Zampini } 31829566063dSJacob Faibussowitsch PetscCall(MatSetType(*A,MATIS)); 31839566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*A,rmap,cmap)); 3184284134d9SBarry Smith PetscFunctionReturn(0); 3185284134d9SBarry Smith } 3186284134d9SBarry Smith 31878b9382cfSStefano Zampini static PetscErrorCode MatHasOperation_IS(Mat A, MatOperation op, PetscBool *has) 31888b9382cfSStefano Zampini { 31898b9382cfSStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3190*d0dbe9f7SStefano Zampini static MatOperation tobefiltered[] = { MATOP_MULT_ADD, MATOP_MULT_TRANSPOSE_ADD, MATOP_GET_DIAGONAL_BLOCK, MATOP_INCREASE_OVERLAP }; 31918b9382cfSStefano Zampini 31928b9382cfSStefano Zampini PetscFunctionBegin; 31938b9382cfSStefano Zampini *has = PETSC_FALSE; 31948b9382cfSStefano Zampini if (!((void**)A->ops)[op]) PetscFunctionReturn(0); 3195*d0dbe9f7SStefano Zampini *has = PETSC_TRUE; 3196*d0dbe9f7SStefano Zampini for (PetscInt i = 0; PETSC_STATIC_ARRAY_LENGTH(tobefiltered); i++) if (op == tobefiltered[i]) PetscFunctionReturn(0); 31979566063dSJacob Faibussowitsch PetscCall(MatHasOperation(a->A,op,has)); 31988b9382cfSStefano Zampini PetscFunctionReturn(0); 31998b9382cfSStefano Zampini } 32008b9382cfSStefano Zampini 3201e432b41dSStefano Zampini static PetscErrorCode MatSetValuesCOO_IS(Mat A,const PetscScalar v[],InsertMode imode) 3202e432b41dSStefano Zampini { 3203e432b41dSStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3204e432b41dSStefano Zampini 3205e432b41dSStefano Zampini PetscFunctionBegin; 32069566063dSJacob Faibussowitsch PetscCall(MatSetValuesCOO(a->A,v,imode)); 32079566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY)); 32089566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY)); 3209e432b41dSStefano Zampini PetscFunctionReturn(0); 3210e432b41dSStefano Zampini } 3211e432b41dSStefano Zampini 3212e432b41dSStefano Zampini static PetscErrorCode MatSetPreallocationCOOLocal_IS(Mat A,PetscCount ncoo,PetscInt coo_i[],PetscInt coo_j[]) 3213e432b41dSStefano Zampini { 3214e432b41dSStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3215e432b41dSStefano Zampini 3216e432b41dSStefano Zampini PetscFunctionBegin; 3217e432b41dSStefano Zampini PetscCheck(a->A,PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3218e432b41dSStefano Zampini if (a->A->rmap->mapping || a->A->cmap->mapping) { 32199566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOOLocal(a->A,ncoo,coo_i,coo_j)); 3220e432b41dSStefano Zampini } else { 32219566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOO(a->A,ncoo,coo_i,coo_j)); 3222e432b41dSStefano Zampini } 32239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",MatSetValuesCOO_IS)); 3224e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 3225e432b41dSStefano Zampini PetscFunctionReturn(0); 3226e432b41dSStefano Zampini } 3227e432b41dSStefano Zampini 3228e432b41dSStefano Zampini static PetscErrorCode MatSetPreallocationCOO_IS(Mat A,PetscCount ncoo,const PetscInt coo_i[],const PetscInt coo_j[]) 3229e432b41dSStefano Zampini { 3230e432b41dSStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3231e432b41dSStefano Zampini PetscInt *coo_il, *coo_jl, incoo; 3232e432b41dSStefano Zampini 3233e432b41dSStefano Zampini PetscFunctionBegin; 3234e432b41dSStefano Zampini PetscCheck(a->A,PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3235e432b41dSStefano Zampini PetscCheck(ncoo <= PETSC_MAX_INT,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"ncoo %" PetscCount_FMT " overflowed PetscInt; configure --with-64-bit-indices or request support",ncoo); 32369566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(ncoo,&coo_il,ncoo,&coo_jl)); 32379566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(a->rmapping,IS_GTOLM_MASK,ncoo,coo_i,&incoo,coo_il)); 32389566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(a->cmapping,IS_GTOLM_MASK,ncoo,coo_j,&incoo,coo_jl)); 32399566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOO(a->A,ncoo,coo_il,coo_jl)); 32409566063dSJacob Faibussowitsch PetscCall(PetscFree2(coo_il,coo_jl)); 32419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",MatSetValuesCOO_IS)); 3242e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 3243e432b41dSStefano Zampini PetscFunctionReturn(0); 3244e432b41dSStefano Zampini } 3245e432b41dSStefano Zampini 3246*d0dbe9f7SStefano Zampini static PetscErrorCode MatISGetAssembled_Private(Mat A, Mat *tA) 3247*d0dbe9f7SStefano Zampini { 3248*d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3249*d0dbe9f7SStefano Zampini PetscObjectState Astate, aAstate = PETSC_MIN_INT; 3250*d0dbe9f7SStefano Zampini PetscObjectState Annzstate, aAnnzstate = PETSC_MIN_INT; 3251*d0dbe9f7SStefano Zampini 3252*d0dbe9f7SStefano Zampini PetscFunctionBegin; 3253*d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A,&Astate)); 3254*d0dbe9f7SStefano Zampini Annzstate = A->nonzerostate; 3255*d0dbe9f7SStefano Zampini if (a->assembledA) { 3256*d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)a->assembledA,&aAstate)); 3257*d0dbe9f7SStefano Zampini aAnnzstate = a->assembledA->nonzerostate; 3258*d0dbe9f7SStefano Zampini } 3259*d0dbe9f7SStefano Zampini if (aAnnzstate != Annzstate) PetscCall(MatDestroy(&a->assembledA)); 3260*d0dbe9f7SStefano Zampini if (Astate != aAstate || !a->assembledA) { 3261*d0dbe9f7SStefano Zampini MatType aAtype; 3262*d0dbe9f7SStefano Zampini PetscMPIInt size; 3263*d0dbe9f7SStefano Zampini PetscInt rbs, cbs, bs; 3264*d0dbe9f7SStefano Zampini 3265*d0dbe9f7SStefano Zampini /* the assembled form is used as temporary storage for parallel operations 3266*d0dbe9f7SStefano Zampini like createsubmatrices and the like, do not waste device memory */ 3267*d0dbe9f7SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size)); 3268*d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->cmapping,&cbs)); 3269*d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->rmapping,&rbs)); 3270*d0dbe9f7SStefano Zampini bs = rbs == cbs ? rbs : 1; 3271*d0dbe9f7SStefano Zampini if (a->assembledA) PetscCall(MatGetType(a->assembledA,&aAtype)); 3272*d0dbe9f7SStefano Zampini else if (size > 1) aAtype = bs > 1 ? MATMPIBAIJ : MATMPIAIJ; 3273*d0dbe9f7SStefano Zampini else aAtype = bs > 1 ? MATSEQBAIJ : MATSEQAIJ; 3274*d0dbe9f7SStefano Zampini 3275*d0dbe9f7SStefano Zampini PetscCall(MatConvert(A,aAtype,a->assembledA ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX,&a->assembledA)); 3276*d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->assembledA,Astate)); 3277*d0dbe9f7SStefano Zampini a->assembledA->nonzerostate = Annzstate; 3278*d0dbe9f7SStefano Zampini } 3279*d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->assembledA)); 3280*d0dbe9f7SStefano Zampini *tA = a->assembledA; 3281*d0dbe9f7SStefano Zampini if (!a->keepassembled) PetscCall(MatDestroy(&a->assembledA)); 3282*d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3283*d0dbe9f7SStefano Zampini } 3284*d0dbe9f7SStefano Zampini 3285*d0dbe9f7SStefano Zampini static PetscErrorCode MatISRestoreAssembled_Private(Mat A, Mat *tA) 3286*d0dbe9f7SStefano Zampini { 3287*d0dbe9f7SStefano Zampini PetscFunctionBegin; 3288*d0dbe9f7SStefano Zampini PetscCall(MatDestroy(tA)); 3289*d0dbe9f7SStefano Zampini *tA = NULL; 3290*d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3291*d0dbe9f7SStefano Zampini } 3292*d0dbe9f7SStefano Zampini 3293*d0dbe9f7SStefano Zampini static PetscErrorCode MatGetDiagonalBlock_IS(Mat A, Mat *dA) 3294*d0dbe9f7SStefano Zampini { 3295*d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3296*d0dbe9f7SStefano Zampini PetscObjectState Astate, dAstate = PETSC_MIN_INT; 3297*d0dbe9f7SStefano Zampini 3298*d0dbe9f7SStefano Zampini PetscFunctionBegin; 3299*d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A,&Astate)); 3300*d0dbe9f7SStefano Zampini if (a->dA) PetscCall(PetscObjectStateGet((PetscObject)a->dA,&dAstate)); 3301*d0dbe9f7SStefano Zampini if (Astate != dAstate) { 3302*d0dbe9f7SStefano Zampini Mat tA; 3303*d0dbe9f7SStefano Zampini MatType ltype; 3304*d0dbe9f7SStefano Zampini 3305*d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&a->dA)); 3306*d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A,&tA)); 3307*d0dbe9f7SStefano Zampini PetscCall(MatGetDiagonalBlock(tA,&a->dA)); 3308*d0dbe9f7SStefano Zampini PetscCall(MatPropagateSymmetryOptions(tA,a->dA)); 3309*d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A,<ype)); 3310*d0dbe9f7SStefano Zampini PetscCall(MatConvert(a->dA,ltype,MAT_INPLACE_MATRIX,&a->dA)); 3311*d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->dA)); 3312*d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A,&tA)); 3313*d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->dA,Astate)); 3314*d0dbe9f7SStefano Zampini } 3315*d0dbe9f7SStefano Zampini *dA = a->dA; 3316*d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3317*d0dbe9f7SStefano Zampini } 3318*d0dbe9f7SStefano Zampini 3319*d0dbe9f7SStefano Zampini static PetscErrorCode MatCreateSubMatrices_IS(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse reuse,Mat *submat[]) 3320*d0dbe9f7SStefano Zampini { 3321*d0dbe9f7SStefano Zampini Mat tA; 3322*d0dbe9f7SStefano Zampini 3323*d0dbe9f7SStefano Zampini PetscFunctionBegin; 3324*d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A,&tA)); 3325*d0dbe9f7SStefano Zampini PetscCall(MatCreateSubMatrices(tA,n,irow,icol,reuse,submat)); 3326*d0dbe9f7SStefano Zampini /* MatCreateSubMatrices_MPIAIJ is a mess at the moment */ 3327*d0dbe9f7SStefano Zampini #if 0 3328*d0dbe9f7SStefano Zampini { 3329*d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3330*d0dbe9f7SStefano Zampini MatType ltype; 3331*d0dbe9f7SStefano Zampini VecType vtype; 3332*d0dbe9f7SStefano Zampini char *flg; 3333*d0dbe9f7SStefano Zampini 3334*d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A,<ype)); 3335*d0dbe9f7SStefano Zampini PetscCall(MatGetVecType(a->A,&vtype)); 3336*d0dbe9f7SStefano Zampini PetscCall(PetscStrstr(vtype,"cuda",&flg)); 3337*d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"hip",&flg)); 3338*d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"kokkos",&flg)); 3339*d0dbe9f7SStefano Zampini if (flg) { 3340*d0dbe9f7SStefano Zampini for (PetscInt i = 0; i < n; i++) { 3341*d0dbe9f7SStefano Zampini Mat sA = (*submat)[i]; 3342*d0dbe9f7SStefano Zampini 3343*d0dbe9f7SStefano Zampini PetscCall(MatConvert(sA,ltype,MAT_INPLACE_MATRIX,&sA)); 3344*d0dbe9f7SStefano Zampini (*submat)[i] = sA; 3345*d0dbe9f7SStefano Zampini } 3346*d0dbe9f7SStefano Zampini } 3347*d0dbe9f7SStefano Zampini } 3348*d0dbe9f7SStefano Zampini #endif 3349*d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A,&tA)); 3350*d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3351*d0dbe9f7SStefano Zampini } 3352*d0dbe9f7SStefano Zampini 3353*d0dbe9f7SStefano Zampini static PetscErrorCode MatIncreaseOverlap_IS(Mat A, PetscInt n, IS is[], PetscInt ov) 3354*d0dbe9f7SStefano Zampini { 3355*d0dbe9f7SStefano Zampini Mat tA; 3356*d0dbe9f7SStefano Zampini 3357*d0dbe9f7SStefano Zampini PetscFunctionBegin; 3358*d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A,&tA)); 3359*d0dbe9f7SStefano Zampini PetscCall(MatIncreaseOverlap(tA,n,is,ov)); 3360*d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A,&tA)); 3361*d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3362*d0dbe9f7SStefano Zampini } 3363*d0dbe9f7SStefano Zampini 3364e432b41dSStefano Zampini /*@ 3365e432b41dSStefano Zampini MatISGetLocalToGlobalMapping - Gets the local-to-global numbering of the MATIS object 3366e432b41dSStefano Zampini 3367e432b41dSStefano Zampini Not Collective 3368e432b41dSStefano Zampini 3369e432b41dSStefano Zampini Input Parameter: 3370e432b41dSStefano Zampini . A - the matrix 3371e432b41dSStefano Zampini 3372e432b41dSStefano Zampini Output Parameters: 3373e432b41dSStefano Zampini + rmapping - row mapping 3374e432b41dSStefano Zampini - cmapping - column mapping 3375e432b41dSStefano Zampini 3376e432b41dSStefano Zampini Notes: The returned map can be different from the one used to construct the MATIS object, since it will not contain negative or repeated indices. 3377e432b41dSStefano Zampini 3378e432b41dSStefano Zampini Level: advanced 3379e432b41dSStefano Zampini 3380db781477SPatrick Sanan .seealso: `MatSetLocalToGlobalMapping()` 3381e432b41dSStefano Zampini @*/ 3382e432b41dSStefano Zampini PetscErrorCode MatISGetLocalToGlobalMapping(Mat A,ISLocalToGlobalMapping *rmapping,ISLocalToGlobalMapping *cmapping) 3383e432b41dSStefano Zampini { 3384e432b41dSStefano Zampini PetscFunctionBegin; 3385e432b41dSStefano Zampini PetscValidHeaderSpecific(A,MAT_CLASSID,1); 3386e432b41dSStefano Zampini PetscValidType(A,1); 3387e432b41dSStefano Zampini if (rmapping) PetscValidPointer(rmapping,2); 3388e432b41dSStefano Zampini if (cmapping) PetscValidPointer(cmapping,3); 3389cac4c232SBarry Smith PetscUseMethod(A,"MatISGetLocalToGlobalMapping_C",(Mat,ISLocalToGlobalMapping*,ISLocalToGlobalMapping*),(A,rmapping,cmapping)); 3390e432b41dSStefano Zampini PetscFunctionReturn(0); 3391e432b41dSStefano Zampini } 3392e432b41dSStefano Zampini 3393e432b41dSStefano Zampini static PetscErrorCode MatISGetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping *r, ISLocalToGlobalMapping *c) 3394e432b41dSStefano Zampini { 3395e432b41dSStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3396e432b41dSStefano Zampini 3397e432b41dSStefano Zampini PetscFunctionBegin; 3398e432b41dSStefano Zampini if (r) *r = a->rmapping; 3399e432b41dSStefano Zampini if (c) *c = a->cmapping; 3400e432b41dSStefano Zampini PetscFunctionReturn(0); 3401e432b41dSStefano Zampini } 3402e432b41dSStefano Zampini 3403b4319ba4SBarry Smith /*MC 3404f26d0771SStefano Zampini MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP). 3405b89f26deSStefano Zampini This stores the matrices in globally unassembled form. Each processor assembles only its local Neumann problem and the parallel matrix vector 3406b4319ba4SBarry Smith product is handled "implicitly". 3407b4319ba4SBarry Smith 3408b4319ba4SBarry Smith Options Database Keys: 340975d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions() 341075d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns. 341175d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP(). 3412b4319ba4SBarry Smith 341395452b02SPatrick Sanan Notes: 341495452b02SPatrick Sanan Options prefix for the inner matrix are given by -is_mat_xxx 3415b4319ba4SBarry Smith 3416b4319ba4SBarry Smith You must call MatSetLocalToGlobalMapping() before using this matrix type. 3417b4319ba4SBarry Smith 3418b4319ba4SBarry Smith You can do matrix preallocation on the local matrix after you obtain it with 3419eb82efa4SStefano Zampini MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation() 3420b4319ba4SBarry Smith 3421b4319ba4SBarry Smith Level: advanced 3422b4319ba4SBarry Smith 3423db781477SPatrick Sanan .seealso: `Mat`, `MatISGetLocalMat()`, `MatSetLocalToGlobalMapping()`, `MatISSetPreallocation()`, `MatCreateIS()`, `PCBDDC`, `KSPFETIDP` 3424b4319ba4SBarry Smith 3425b4319ba4SBarry Smith M*/ 34268cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 3427b4319ba4SBarry Smith { 3428e432b41dSStefano Zampini Mat_IS *a; 3429b4319ba4SBarry Smith 3430b4319ba4SBarry Smith PetscFunctionBegin; 34319566063dSJacob Faibussowitsch PetscCall(PetscNewLog(A,&a)); 34329566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATAIJ,&a->lmattype)); 3433e432b41dSStefano Zampini A->data = (void*)a; 3434b4319ba4SBarry Smith 3435e176bc59SStefano Zampini /* matrix ops */ 34369566063dSJacob Faibussowitsch PetscCall(PetscMemzero(A->ops,sizeof(struct _MatOps))); 3437b4319ba4SBarry Smith A->ops->mult = MatMult_IS; 34382e74eeadSLisandro Dalcin A->ops->multadd = MatMultAdd_IS; 34392e74eeadSLisandro Dalcin A->ops->multtranspose = MatMultTranspose_IS; 34402e74eeadSLisandro Dalcin A->ops->multtransposeadd = MatMultTransposeAdd_IS; 3441b4319ba4SBarry Smith A->ops->destroy = MatDestroy_IS; 3442b4319ba4SBarry Smith A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 34432e74eeadSLisandro Dalcin A->ops->setvalues = MatSetValues_IS; 344498921651SStefano Zampini A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 3445b4319ba4SBarry Smith A->ops->setvalueslocal = MatSetValuesLocal_IS; 3446f0006bf2SLisandro Dalcin A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 34472e74eeadSLisandro Dalcin A->ops->zerorows = MatZeroRows_IS; 3448f0ae7da4SStefano Zampini A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 3449b4319ba4SBarry Smith A->ops->assemblybegin = MatAssemblyBegin_IS; 3450b4319ba4SBarry Smith A->ops->assemblyend = MatAssemblyEnd_IS; 3451b4319ba4SBarry Smith A->ops->view = MatView_IS; 34526726f965SBarry Smith A->ops->zeroentries = MatZeroEntries_IS; 34532e74eeadSLisandro Dalcin A->ops->scale = MatScale_IS; 34542e74eeadSLisandro Dalcin A->ops->getdiagonal = MatGetDiagonal_IS; 34556726f965SBarry Smith A->ops->setoption = MatSetOption_IS; 345669796d55SStefano Zampini A->ops->ishermitian = MatIsHermitian_IS; 345769796d55SStefano Zampini A->ops->issymmetric = MatIsSymmetric_IS; 345845471136SStefano Zampini A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS; 3459ad6194a2SStefano Zampini A->ops->duplicate = MatDuplicate_IS; 34606bd84002SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_IS; 34612b404112SStefano Zampini A->ops->copy = MatCopy_IS; 3462659959c5SStefano Zampini A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 34637dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_IS; 3464f26d0771SStefano Zampini A->ops->axpy = MatAXPY_IS; 34653fd1c9e7SStefano Zampini A->ops->diagonalset = MatDiagonalSet_IS; 34663fd1c9e7SStefano Zampini A->ops->shift = MatShift_IS; 3467d7f69cd0SStefano Zampini A->ops->transpose = MatTranspose_IS; 34687fa8f2d3SStefano Zampini A->ops->getinfo = MatGetInfo_IS; 3469ad219c80Sstefano_zampini A->ops->diagonalscale = MatDiagonalScale_IS; 3470872cf891SStefano Zampini A->ops->setfromoptions = MatSetFromOptions_IS; 3471fc989267SStefano Zampini A->ops->setup = MatSetUp_IS; 34728b9382cfSStefano Zampini A->ops->hasoperation = MatHasOperation_IS; 3473*d0dbe9f7SStefano Zampini A->ops->getdiagonalblock = MatGetDiagonalBlock_IS; 3474*d0dbe9f7SStefano Zampini A->ops->createsubmatrices = MatCreateSubMatrices_IS; 3475*d0dbe9f7SStefano Zampini A->ops->increaseoverlap = MatIncreaseOverlap_IS; 3476b4319ba4SBarry Smith 3477b7ce53b6SStefano Zampini /* special MATIS functions */ 34789566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",MatISSetLocalMatType_IS)); 34799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS)); 34809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS)); 34819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS)); 34829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ)); 34839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS)); 34849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS)); 34859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS)); 34869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalToGlobalMapping_C",MatISGetLocalToGlobalMapping_IS)); 34879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ)); 34889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ)); 34899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ)); 34909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ)); 34919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ)); 34929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ)); 34939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ)); 34949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOOLocal_C",MatSetPreallocationCOOLocal_IS)); 34959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",MatSetPreallocationCOO_IS)); 34969566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A,MATIS)); 3497b4319ba4SBarry Smith PetscFunctionReturn(0); 3498b4319ba4SBarry Smith } 3499