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 10c6db04a5SJed Brown #include <../src/mat/impls/is/matis.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 } 2259566063dSJacob Faibussowitsch PetscCallMPI(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)); 3702c71b3e2SJacob Faibussowitsch PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure"); 3719566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(matis->rmapping,&n,&ecount,&eneighs)); 3722c71b3e2SJacob Faibussowitsch PetscCheckFalse(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)); 3942c71b3e2SJacob Faibussowitsch PetscCheckFalse(!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; 412c9225affSStefano Zampini PetscErrorCode ierr; 413c9225affSStefano Zampini 414c9225affSStefano Zampini PetscFunctionBegin; 4159566063dSJacob Faibussowitsch ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"MatIS l2g disassembling options","Mat");PetscCall(ierr); 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)); 4179566063dSJacob Faibussowitsch ierr = PetscOptionsEnd();PetscCall(ierr); 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 4549566063dSJacob Faibussowitsch PetscCallMPI(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 */ 4659566063dSJacob Faibussowitsch ierr = MatPreallocateInitialize(comm,A->rmap->n,A->cmap->n,dnz,onz);PetscCall(ierr); 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 } 5072c71b3e2SJacob Faibussowitsch PetscCheckFalse(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 } 5342c71b3e2SJacob Faibussowitsch PetscCheckFalse(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)); 5709566063dSJacob Faibussowitsch ierr = MatPreallocateFinalize(dnz,onz);PetscCall(ierr); 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: 585fabe8965SStefano Zampini if (ismpiaij) { 5869566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray)); 587fabe8965SStefano Zampini } else if (ismpibaij) { 5889566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray)); 58998921bdaSJacob Faibussowitsch } else SETERRQ(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name); 59028b400f6SJacob Faibussowitsch PetscCheck(garray,comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present"); 591c9225affSStefano Zampini if (A->rmap->n) { 592fabe8965SStefano Zampini PetscInt dc,oc,stc,*aux; 593c9225affSStefano Zampini 5949566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,NULL,&dc)); 5959566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Ao,NULL,&oc)); 5969566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A,&stc,NULL)); 5979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc+oc)/bs,&aux)); 598c9225affSStefano Zampini for (i=0; i<dc/bs; i++) aux[i] = i+stc/bs; 599c9225affSStefano Zampini for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i]; 6009566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is)); 601c9225affSStefano Zampini } else { 6029566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,1,0,NULL,PETSC_OWN_POINTER,&is)); 603c9225affSStefano Zampini } 6049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,l2g)); 6059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 606fabe8965SStefano Zampini break; 607fabe8965SStefano Zampini default: 60898921bdaSJacob Faibussowitsch SETERRQ(comm,PETSC_ERR_ARG_WRONG,"Unsupported l2g disassembling type %d",mode); 609c9225affSStefano Zampini } 610c9225affSStefano Zampini PetscFunctionReturn(0); 611c9225affSStefano Zampini } 612c9225affSStefano Zampini 613c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat) 614c9225affSStefano Zampini { 615c9225affSStefano Zampini Mat lA,Ad,Ao,B = NULL; 6166989cf23SStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 6176989cf23SStefano Zampini IS is; 6186989cf23SStefano Zampini MPI_Comm comm; 6196989cf23SStefano Zampini void *ptrs[2]; 6206989cf23SStefano Zampini const char *names[2] = {"_convert_csr_aux","_convert_csr_data"}; 621c9225affSStefano Zampini const PetscInt *garray; 6226989cf23SStefano Zampini PetscScalar *dd,*od,*aa,*data; 623c9225affSStefano Zampini const PetscInt *di,*dj,*oi,*oj; 624c9225affSStefano Zampini const PetscInt *odi,*odj,*ooi,*ooj; 6256989cf23SStefano Zampini PetscInt *aux,*ii,*jj; 626c9225affSStefano Zampini PetscInt bs,lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum; 627c9225affSStefano Zampini PetscBool flg,ismpiaij,ismpibaij,was_inplace = PETSC_FALSE; 628c9225affSStefano Zampini PetscMPIInt size; 6296989cf23SStefano Zampini 630ab4d48faSStefano Zampini PetscFunctionBegin; 6319566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A,&comm)); 6329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm,&size)); 633c9225affSStefano Zampini if (size == 1) { 6349566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqXAIJ_IS(A,type,reuse,newmat)); 635c9225affSStefano Zampini PetscFunctionReturn(0); 636c9225affSStefano Zampini } 637c9225affSStefano Zampini if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) { 6389566063dSJacob Faibussowitsch PetscCall(MatMPIXAIJComputeLocalToGlobalMapping_Private(A,&rl2g)); 6399566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&B)); 6409566063dSJacob Faibussowitsch PetscCall(MatSetType(B,MATIS)); 6419566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N)); 6429566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B,rl2g,rl2g)); 6439566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A,&bs)); 6449566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B,bs)); 6459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 646c9225affSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE; 647c9225affSStefano Zampini reuse = MAT_REUSE_MATRIX; 648c9225affSStefano Zampini } 649c9225affSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 650c9225affSStefano Zampini Mat *newlA, lA; 651c9225affSStefano Zampini IS rows, cols; 652c9225affSStefano Zampini const PetscInt *ridx, *cidx; 653c9225affSStefano Zampini PetscInt rbs, cbs, nr, nc; 654c9225affSStefano Zampini 655c9225affSStefano Zampini if (!B) B = *newmat; 6569566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(B,&rl2g,&cl2g)); 6579566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g,&ridx)); 6589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g,&cidx)); 6599566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&nr)); 6609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&nc)); 6619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g,&rbs)); 6629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g,&cbs)); 6639566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,rbs,nr/rbs,ridx,PETSC_USE_POINTER,&rows)); 664c9225affSStefano Zampini if (rl2g != cl2g) { 6659566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,cbs,nc/cbs,cidx,PETSC_USE_POINTER,&cols)); 666c9225affSStefano Zampini } else { 6679566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rows)); 668c9225affSStefano Zampini cols = rows; 669c9225affSStefano Zampini } 6709566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(B,&lA)); 6719566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A,1,&rows,&cols,MAT_INITIAL_MATRIX,&newlA)); 6729566063dSJacob Faibussowitsch PetscCall(MatConvert(newlA[0],MATSEQAIJ,MAT_INPLACE_MATRIX,&newlA[0])); 6739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&ridx)); 6749566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&cidx)); 6759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 6769566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 677c9225affSStefano Zampini if (!lA->preallocated) { /* first time */ 6789566063dSJacob Faibussowitsch PetscCall(MatDuplicate(newlA[0],MAT_COPY_VALUES,&lA)); 6799566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B,lA)); 6809566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)lA)); 681c9225affSStefano Zampini } 6829566063dSJacob Faibussowitsch PetscCall(MatCopy(newlA[0],lA,SAME_NONZERO_PATTERN)); 6839566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices(1,&newlA)); 6849566063dSJacob Faibussowitsch PetscCall(MatISScaleDisassembling_Private(B)); 6859566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 6869566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 6879566063dSJacob Faibussowitsch if (was_inplace) PetscCall(MatHeaderReplace(A,&B)); 688c9225affSStefano Zampini else *newmat = B; 689c9225affSStefano Zampini PetscFunctionReturn(0); 690c9225affSStefano Zampini } 691c9225affSStefano Zampini /* rectangular case, just compress out the column space */ 6929566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij)); 6939566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij)); 694c9225affSStefano Zampini if (ismpiaij) { 695c9225affSStefano Zampini bs = 1; 6969566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray)); 697c9225affSStefano Zampini } else if (ismpibaij) { 6989566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A,&bs)); 6999566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray)); 7009566063dSJacob Faibussowitsch PetscCall(MatConvert(Ad,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ad)); 7019566063dSJacob Faibussowitsch PetscCall(MatConvert(Ao,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ao)); 70298921bdaSJacob Faibussowitsch } else SETERRQ(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name); 7039566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Ad,&dd)); 7049566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Ao,&od)); 70528b400f6SJacob Faibussowitsch PetscCheck(garray,comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present"); 7066989cf23SStefano Zampini 7076989cf23SStefano Zampini /* access relevant information from MPIAIJ */ 7089566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A,&str,NULL)); 7099566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A,&stc,NULL)); 7109566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,&dr,&dc)); 7119566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Ao,NULL,&oc)); 7129566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&di,&dj,&flg)); 71328b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure"); 7149566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&oi,&oj,&flg)); 71528b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure"); 716c9225affSStefano Zampini nnz = di[dr] + oi[dr]; 717c9225affSStefano Zampini /* store original pointers to be restored later */ 718c9225affSStefano Zampini odi = di; odj = dj; ooi = oi; ooj = oj; 7196989cf23SStefano Zampini 7206989cf23SStefano Zampini /* generate l2g maps for rows and cols */ 7219566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm,dr/bs,str/bs,1,&is)); 722c9225affSStefano Zampini if (bs > 1) { 723c9225affSStefano Zampini IS is2; 724c9225affSStefano Zampini 7259566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is,&i)); 7269566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is,(const PetscInt**)&aux)); 7279566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,bs,i,aux,PETSC_COPY_VALUES,&is2)); 7289566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is,(const PetscInt**)&aux)); 7299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 730c9225affSStefano Zampini is = is2; 731c9225affSStefano Zampini } 7329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g)); 7339566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 734e363d98aSStefano Zampini if (dr) { 7359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc+oc)/bs,&aux)); 736c9225affSStefano Zampini for (i=0; i<dc/bs; i++) aux[i] = i+stc/bs; 737c9225affSStefano Zampini for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i]; 7389566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is)); 739e363d98aSStefano Zampini lc = dc+oc; 740e363d98aSStefano Zampini } else { 7419566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm,bs,0,NULL,PETSC_OWN_POINTER,&is)); 742e363d98aSStefano Zampini lc = 0; 743e363d98aSStefano Zampini } 7449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g)); 7459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 7466989cf23SStefano Zampini 7476989cf23SStefano Zampini /* create MATIS object */ 7489566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&B)); 7499566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B,dr,dc,PETSC_DECIDE,PETSC_DECIDE)); 7509566063dSJacob Faibussowitsch PetscCall(MatSetType(B,MATIS)); 7519566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B,bs)); 7529566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B,rl2g,cl2g)); 7539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 7549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 7556989cf23SStefano Zampini 7566989cf23SStefano Zampini /* merge local matrices */ 7579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz+dr+1,&aux)); 7589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz,&data)); 7596989cf23SStefano Zampini ii = aux; 7606989cf23SStefano Zampini jj = aux+dr+1; 7616989cf23SStefano Zampini aa = data; 7626989cf23SStefano Zampini *ii = *(di++) + *(oi++); 7636989cf23SStefano Zampini for (jd=0,jo=0,cum=0;*ii<nnz;cum++) 7646989cf23SStefano Zampini { 7656989cf23SStefano Zampini for (;jd<*di;jd++) { *jj++ = *dj++; *aa++ = *dd++; } 7666989cf23SStefano Zampini for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; } 7676989cf23SStefano Zampini *(++ii) = *(di++) + *(oi++); 7686989cf23SStefano Zampini } 7696989cf23SStefano Zampini for (;cum<dr;cum++) *(++ii) = nnz; 770c9225affSStefano Zampini 7719566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&odi,&odj,&flg)); 77228b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure"); 7739566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&ooi,&ooj,&flg)); 77428b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure"); 7759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Ad,&dd)); 7769566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Ao,&od)); 777c9225affSStefano Zampini 7786989cf23SStefano Zampini ii = aux; 7796989cf23SStefano Zampini jj = aux+dr+1; 7806989cf23SStefano Zampini aa = data; 7819566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA)); 7826989cf23SStefano Zampini 7836989cf23SStefano Zampini /* create containers to destroy the data */ 7846989cf23SStefano Zampini ptrs[0] = aux; 7856989cf23SStefano Zampini ptrs[1] = data; 7866989cf23SStefano Zampini for (i=0; i<2; i++) { 7876989cf23SStefano Zampini PetscContainer c; 7886989cf23SStefano Zampini 7899566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF,&c)); 7909566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c,ptrs[i])); 7919566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault)); 7929566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c)); 7939566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 7946989cf23SStefano Zampini } 795c9225affSStefano Zampini if (ismpibaij) { /* destroy converted local matrices */ 7969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ad)); 7979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ao)); 798c9225affSStefano Zampini } 7996989cf23SStefano Zampini 8006989cf23SStefano Zampini /* finalize matrix */ 8019566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B,lA)); 8029566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 8039566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 8049566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 805c9225affSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 8069566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&B)); 807c9225affSStefano Zampini } else *newmat = B; 8086989cf23SStefano Zampini PetscFunctionReturn(0); 8096989cf23SStefano Zampini } 8106989cf23SStefano Zampini 8115e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat) 8125e3038f0Sstefano_zampini { 8135e3038f0Sstefano_zampini Mat **nest,*snest,**rnest,lA,B; 8145e3038f0Sstefano_zampini IS *iscol,*isrow,*islrow,*islcol; 8155e3038f0Sstefano_zampini ISLocalToGlobalMapping rl2g,cl2g; 8165e3038f0Sstefano_zampini MPI_Comm comm; 8175b003df0Sstefano_zampini PetscInt *lr,*lc,*l2gidxs; 8185b003df0Sstefano_zampini PetscInt i,j,nr,nc,rbs,cbs; 8199e7b2b25Sstefano_zampini PetscBool convert,lreuse,*istrans; 8205e3038f0Sstefano_zampini 821ab4d48faSStefano Zampini PetscFunctionBegin; 8229566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(A,&nr,&nc,&nest)); 8235e3038f0Sstefano_zampini lreuse = PETSC_FALSE; 8245e3038f0Sstefano_zampini rnest = NULL; 8255e3038f0Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 8265e3038f0Sstefano_zampini PetscBool ismatis,isnest; 8275e3038f0Sstefano_zampini 8289566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis)); 82928b400f6SJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type_name); 8309566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat,&lA)); 8319566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest)); 8325e3038f0Sstefano_zampini if (isnest) { 8339566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(lA,&i,&j,&rnest)); 8345e3038f0Sstefano_zampini lreuse = (PetscBool)(i == nr && j == nc); 8355e3038f0Sstefano_zampini if (!lreuse) rnest = NULL; 8365e3038f0Sstefano_zampini } 8375e3038f0Sstefano_zampini } 8389566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A,&comm)); 8399566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nr,&lr,nc,&lc)); 8409566063dSJacob Faibussowitsch PetscCall(PetscCalloc6(nr,&isrow,nc,&iscol,nr,&islrow,nc,&islcol,nr*nc,&snest,nr*nc,&istrans)); 8419566063dSJacob Faibussowitsch PetscCall(MatNestGetISs(A,isrow,iscol)); 8425e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 8435e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 8445e3038f0Sstefano_zampini PetscBool ismatis; 8459e7b2b25Sstefano_zampini PetscInt l1,l2,lb1,lb2,ij=i*nc+j; 8465e3038f0Sstefano_zampini 8475e3038f0Sstefano_zampini /* Null matrix pointers are allowed in MATNEST */ 8485e3038f0Sstefano_zampini if (!nest[i][j]) continue; 8495e3038f0Sstefano_zampini 8505e3038f0Sstefano_zampini /* Nested matrices should be of type MATIS */ 8519566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij])); 8529e7b2b25Sstefano_zampini if (istrans[ij]) { 8539e7b2b25Sstefano_zampini Mat T,lT; 8549566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[i][j],&T)); 8559566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis)); 85628b400f6SJacob 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); 8579566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(T,&lT)); 8589566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(lT,&snest[ij])); 8599e7b2b25Sstefano_zampini } else { 8609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis)); 86128b400f6SJacob 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); 8629566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(nest[i][j],&snest[ij])); 8639e7b2b25Sstefano_zampini } 8645e3038f0Sstefano_zampini 8655e3038f0Sstefano_zampini /* Check compatibility of local sizes */ 8669566063dSJacob Faibussowitsch PetscCall(MatGetSize(snest[ij],&l1,&l2)); 8679566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(snest[ij],&lb1,&lb2)); 8685e3038f0Sstefano_zampini if (!l1 || !l2) continue; 8692c71b3e2SJacob Faibussowitsch PetscCheckFalse(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); 8702c71b3e2SJacob Faibussowitsch PetscCheckFalse(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); 8715e3038f0Sstefano_zampini lr[i] = l1; 8725e3038f0Sstefano_zampini lc[j] = l2; 8735e3038f0Sstefano_zampini 8745e3038f0Sstefano_zampini /* check compatibilty for local matrix reusage */ 8755e3038f0Sstefano_zampini if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE; 8765e3038f0Sstefano_zampini } 8775e3038f0Sstefano_zampini } 8785e3038f0Sstefano_zampini 87976bd3646SJed Brown if (PetscDefined (USE_DEBUG)) { 8805e3038f0Sstefano_zampini /* Check compatibility of l2g maps for rows */ 8815e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 8825e3038f0Sstefano_zampini rl2g = NULL; 8835e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 8845e3038f0Sstefano_zampini PetscInt n1,n2; 8855e3038f0Sstefano_zampini 8865e3038f0Sstefano_zampini if (!nest[i][j]) continue; 8879e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 8889e7b2b25Sstefano_zampini Mat T; 8899e7b2b25Sstefano_zampini 8909566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[i][j],&T)); 8919566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(T,NULL,&cl2g)); 8929e7b2b25Sstefano_zampini } else { 8939566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL)); 8949e7b2b25Sstefano_zampini } 8959566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&n1)); 8965e3038f0Sstefano_zampini if (!n1) continue; 8975e3038f0Sstefano_zampini if (!rl2g) { 8985e3038f0Sstefano_zampini rl2g = cl2g; 8995e3038f0Sstefano_zampini } else { 9005e3038f0Sstefano_zampini const PetscInt *idxs1,*idxs2; 9015e3038f0Sstefano_zampini PetscBool same; 9025e3038f0Sstefano_zampini 9039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&n2)); 9042c71b3e2SJacob Faibussowitsch PetscCheckFalse(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); 9059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(cl2g,&idxs1)); 9069566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(rl2g,&idxs2)); 9079566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1,idxs2,n1,&same)); 9089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1)); 9099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2)); 91028b400f6SJacob 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); 9115e3038f0Sstefano_zampini } 9125e3038f0Sstefano_zampini } 9135e3038f0Sstefano_zampini } 9145e3038f0Sstefano_zampini /* Check compatibility of l2g maps for columns */ 9155e3038f0Sstefano_zampini for (i=0;i<nc;i++) { 9165e3038f0Sstefano_zampini rl2g = NULL; 9175e3038f0Sstefano_zampini for (j=0;j<nr;j++) { 9185e3038f0Sstefano_zampini PetscInt n1,n2; 9195e3038f0Sstefano_zampini 9205e3038f0Sstefano_zampini if (!nest[j][i]) continue; 9219e7b2b25Sstefano_zampini if (istrans[j*nc+i]) { 9229e7b2b25Sstefano_zampini Mat T; 9239e7b2b25Sstefano_zampini 9249566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[j][i],&T)); 9259566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(T,&cl2g,NULL)); 9269e7b2b25Sstefano_zampini } else { 9279566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g)); 9289e7b2b25Sstefano_zampini } 9299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&n1)); 9305e3038f0Sstefano_zampini if (!n1) continue; 9315e3038f0Sstefano_zampini if (!rl2g) { 9325e3038f0Sstefano_zampini rl2g = cl2g; 9335e3038f0Sstefano_zampini } else { 9345e3038f0Sstefano_zampini const PetscInt *idxs1,*idxs2; 9355e3038f0Sstefano_zampini PetscBool same; 9365e3038f0Sstefano_zampini 9379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&n2)); 9382c71b3e2SJacob Faibussowitsch PetscCheckFalse(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); 9399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(cl2g,&idxs1)); 9409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(rl2g,&idxs2)); 9419566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1,idxs2,n1,&same)); 9429566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1)); 9439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2)); 94428b400f6SJacob 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); 9455e3038f0Sstefano_zampini } 9465e3038f0Sstefano_zampini } 9475e3038f0Sstefano_zampini } 94876bd3646SJed Brown } 9495e3038f0Sstefano_zampini 9505e3038f0Sstefano_zampini B = NULL; 9515e3038f0Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 9525b003df0Sstefano_zampini PetscInt stl; 9535b003df0Sstefano_zampini 9545e3038f0Sstefano_zampini /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */ 9555e3038f0Sstefano_zampini for (i=0,stl=0;i<nr;i++) stl += lr[i]; 9569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stl,&l2gidxs)); 9575b003df0Sstefano_zampini for (i=0,stl=0;i<nr;i++) { 9585e3038f0Sstefano_zampini Mat usedmat; 9595e3038f0Sstefano_zampini Mat_IS *matis; 9605e3038f0Sstefano_zampini const PetscInt *idxs; 9615e3038f0Sstefano_zampini 9625e3038f0Sstefano_zampini /* local IS for local NEST */ 9639566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i])); 9645e3038f0Sstefano_zampini 9655e3038f0Sstefano_zampini /* l2gmap */ 9665e3038f0Sstefano_zampini j = 0; 9675e3038f0Sstefano_zampini usedmat = nest[i][j]; 9689e7b2b25Sstefano_zampini while (!usedmat && j < nc-1) usedmat = nest[i][++j]; 96928b400f6SJacob Faibussowitsch PetscCheck(usedmat,comm,PETSC_ERR_SUP,"Cannot find valid row mat"); 9709e7b2b25Sstefano_zampini 9719e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 9729e7b2b25Sstefano_zampini Mat T; 9739566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(usedmat,&T)); 9749e7b2b25Sstefano_zampini usedmat = T; 9759e7b2b25Sstefano_zampini } 9765e3038f0Sstefano_zampini matis = (Mat_IS*)(usedmat->data); 9779566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow[i],&idxs)); 9789e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 9799566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 9809566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 9819e7b2b25Sstefano_zampini } else { 9829566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 9839566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 9849e7b2b25Sstefano_zampini } 9859566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow[i],&idxs)); 9865e3038f0Sstefano_zampini stl += lr[i]; 9875e3038f0Sstefano_zampini } 9889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g)); 9895e3038f0Sstefano_zampini 9905e3038f0Sstefano_zampini /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */ 9915e3038f0Sstefano_zampini for (i=0,stl=0;i<nc;i++) stl += lc[i]; 9929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stl,&l2gidxs)); 9935b003df0Sstefano_zampini for (i=0,stl=0;i<nc;i++) { 9945e3038f0Sstefano_zampini Mat usedmat; 9955e3038f0Sstefano_zampini Mat_IS *matis; 9965e3038f0Sstefano_zampini const PetscInt *idxs; 9975e3038f0Sstefano_zampini 9985e3038f0Sstefano_zampini /* local IS for local NEST */ 9999566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i])); 10005e3038f0Sstefano_zampini 10015e3038f0Sstefano_zampini /* l2gmap */ 10025e3038f0Sstefano_zampini j = 0; 10035e3038f0Sstefano_zampini usedmat = nest[j][i]; 10049e7b2b25Sstefano_zampini while (!usedmat && j < nr-1) usedmat = nest[++j][i]; 100528b400f6SJacob Faibussowitsch PetscCheck(usedmat,comm,PETSC_ERR_SUP,"Cannot find valid column mat"); 10069e7b2b25Sstefano_zampini if (istrans[j*nc+i]) { 10079e7b2b25Sstefano_zampini Mat T; 10089566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(usedmat,&T)); 10099e7b2b25Sstefano_zampini usedmat = T; 10109e7b2b25Sstefano_zampini } 10115e3038f0Sstefano_zampini matis = (Mat_IS*)(usedmat->data); 10129566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol[i],&idxs)); 10139e7b2b25Sstefano_zampini if (istrans[j*nc+i]) { 10149566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 10159566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 10169e7b2b25Sstefano_zampini } else { 10179566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 10189566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE)); 10199e7b2b25Sstefano_zampini } 10209566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol[i],&idxs)); 10215e3038f0Sstefano_zampini stl += lc[i]; 10225e3038f0Sstefano_zampini } 10239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g)); 10245e3038f0Sstefano_zampini 10255e3038f0Sstefano_zampini /* Create MATIS */ 10269566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&B)); 10279566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N)); 10289566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(A,&rbs,&cbs)); 10299566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B,rbs,cbs)); 10309566063dSJacob Faibussowitsch PetscCall(MatSetType(B,MATIS)); 10319566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B,MATNEST)); 10328546b261SStefano Zampini { /* hack : avoid setup of scatters */ 10338546b261SStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 10348546b261SStefano Zampini matis->islocalref = PETSC_TRUE; 10358546b261SStefano Zampini } 10369566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B,rl2g,cl2g)); 10379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 10389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 10399566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA)); 10409566063dSJacob Faibussowitsch PetscCall(MatNestSetVecType(lA,VECNEST)); 10419e7b2b25Sstefano_zampini for (i=0;i<nr*nc;i++) { 10429e7b2b25Sstefano_zampini if (istrans[i]) { 10439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snest[i])); 10449e7b2b25Sstefano_zampini } 10459e7b2b25Sstefano_zampini } 10469566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B,lA)); 10479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 10488546b261SStefano Zampini { /* hack : setup of scatters done here */ 10498546b261SStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 10508546b261SStefano Zampini 10518546b261SStefano Zampini matis->islocalref = PETSC_FALSE; 10529566063dSJacob Faibussowitsch PetscCall(MatISSetUpScatters_Private(B)); 10538546b261SStefano Zampini } 10549566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 10559566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 10565e3038f0Sstefano_zampini if (reuse == MAT_INPLACE_MATRIX) { 10579566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&B)); 10585e3038f0Sstefano_zampini } else { 10595e3038f0Sstefano_zampini *newmat = B; 10605e3038f0Sstefano_zampini } 10615e3038f0Sstefano_zampini } else { 10625e3038f0Sstefano_zampini if (lreuse) { 10639566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat,&lA)); 10645e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 10655e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 10665e3038f0Sstefano_zampini if (snest[i*nc+j]) { 10679566063dSJacob Faibussowitsch PetscCall(MatNestSetSubMat(lA,i,j,snest[i*nc+j])); 10689e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 10699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snest[i*nc+j])); 10709e7b2b25Sstefano_zampini } 10715e3038f0Sstefano_zampini } 10725e3038f0Sstefano_zampini } 10735e3038f0Sstefano_zampini } 10745e3038f0Sstefano_zampini } else { 10755b003df0Sstefano_zampini PetscInt stl; 10765b003df0Sstefano_zampini for (i=0,stl=0;i<nr;i++) { 10779566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i])); 10785b003df0Sstefano_zampini stl += lr[i]; 10795e3038f0Sstefano_zampini } 10805b003df0Sstefano_zampini for (i=0,stl=0;i<nc;i++) { 10819566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i])); 10825b003df0Sstefano_zampini stl += lc[i]; 10835e3038f0Sstefano_zampini } 10849566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA)); 1085ab4d48faSStefano Zampini for (i=0;i<nr*nc;i++) { 10869e7b2b25Sstefano_zampini if (istrans[i]) { 10879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snest[i])); 10889e7b2b25Sstefano_zampini } 1089ab4d48faSStefano Zampini } 10909566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat,lA)); 10919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 10925e3038f0Sstefano_zampini } 10939566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY)); 10949566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY)); 10955e3038f0Sstefano_zampini } 10965e3038f0Sstefano_zampini 10975b003df0Sstefano_zampini /* Create local matrix in MATNEST format */ 10985b003df0Sstefano_zampini convert = PETSC_FALSE; 10999566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL)); 11005b003df0Sstefano_zampini if (convert) { 11015b003df0Sstefano_zampini Mat M; 11025b003df0Sstefano_zampini MatISLocalFields lf; 11035b003df0Sstefano_zampini PetscContainer c; 11045b003df0Sstefano_zampini 11059566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat,&lA)); 11069566063dSJacob Faibussowitsch PetscCall(MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M)); 11079566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat,M)); 11089566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 11095b003df0Sstefano_zampini 11105b003df0Sstefano_zampini /* attach local fields to the matrix */ 11119566063dSJacob Faibussowitsch PetscCall(PetscNew(&lf)); 11129566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nr,&lf->rf,nc,&lf->cf)); 11135b003df0Sstefano_zampini for (i=0;i<nr;i++) { 11145b003df0Sstefano_zampini PetscInt n,st; 11155b003df0Sstefano_zampini 11169566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islrow[i],&n)); 11179566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(islrow[i],&st,NULL)); 11189566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm,n,st,1,&lf->rf[i])); 11195b003df0Sstefano_zampini } 11205b003df0Sstefano_zampini for (i=0;i<nc;i++) { 11215b003df0Sstefano_zampini PetscInt n,st; 11225b003df0Sstefano_zampini 11239566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islcol[i],&n)); 11249566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(islcol[i],&st,NULL)); 11259566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm,n,st,1,&lf->cf[i])); 11265b003df0Sstefano_zampini } 11275b003df0Sstefano_zampini lf->nr = nr; 11285b003df0Sstefano_zampini lf->nc = nc; 11299566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c)); 11309566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c,lf)); 11319566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private)); 11329566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c)); 11339566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 11345b003df0Sstefano_zampini } 11355b003df0Sstefano_zampini 11365e3038f0Sstefano_zampini /* Free workspace */ 11375e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 11389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&islrow[i])); 11395e3038f0Sstefano_zampini } 11405e3038f0Sstefano_zampini for (i=0;i<nc;i++) { 11419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&islcol[i])); 11425e3038f0Sstefano_zampini } 11439566063dSJacob Faibussowitsch PetscCall(PetscFree6(isrow,iscol,islrow,islcol,snest,istrans)); 11449566063dSJacob Faibussowitsch PetscCall(PetscFree2(lr,lc)); 11455e3038f0Sstefano_zampini PetscFunctionReturn(0); 11465e3038f0Sstefano_zampini } 11475e3038f0Sstefano_zampini 1148ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r) 1149ad219c80Sstefano_zampini { 1150ad219c80Sstefano_zampini Mat_IS *matis = (Mat_IS*)A->data; 1151ad219c80Sstefano_zampini Vec ll,rr; 1152ad219c80Sstefano_zampini const PetscScalar *Y,*X; 1153ad219c80Sstefano_zampini PetscScalar *x,*y; 1154ad219c80Sstefano_zampini 1155ad219c80Sstefano_zampini PetscFunctionBegin; 1156ad219c80Sstefano_zampini if (l) { 1157ad219c80Sstefano_zampini ll = matis->y; 11589566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(l,&Y)); 11599566063dSJacob Faibussowitsch PetscCall(VecGetArray(ll,&y)); 11609566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y,MPI_REPLACE)); 1161ad219c80Sstefano_zampini } else { 1162ad219c80Sstefano_zampini ll = NULL; 1163ad219c80Sstefano_zampini } 1164ad219c80Sstefano_zampini if (r) { 1165ad219c80Sstefano_zampini rr = matis->x; 11669566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(r,&X)); 11679566063dSJacob Faibussowitsch PetscCall(VecGetArray(rr,&x)); 11689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x,MPI_REPLACE)); 1169ad219c80Sstefano_zampini } else { 1170ad219c80Sstefano_zampini rr = NULL; 1171ad219c80Sstefano_zampini } 1172ad219c80Sstefano_zampini if (ll) { 11739566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y,MPI_REPLACE)); 11749566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(l,&Y)); 11759566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(ll,&y)); 1176ad219c80Sstefano_zampini } 1177ad219c80Sstefano_zampini if (rr) { 11789566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x,MPI_REPLACE)); 11799566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(r,&X)); 11809566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(rr,&x)); 1181ad219c80Sstefano_zampini } 11829566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(matis->A,ll,rr)); 1183ad219c80Sstefano_zampini PetscFunctionReturn(0); 1184ad219c80Sstefano_zampini } 1185ad219c80Sstefano_zampini 11867fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo) 11877fa8f2d3SStefano Zampini { 11887fa8f2d3SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 11897fa8f2d3SStefano Zampini MatInfo info; 11903966268fSBarry Smith PetscLogDouble isend[6],irecv[6]; 11917fa8f2d3SStefano Zampini PetscInt bs; 11927fa8f2d3SStefano Zampini 11937fa8f2d3SStefano Zampini PetscFunctionBegin; 11949566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A,&bs)); 1195a2ccb5f9Sstefano_zampini if (matis->A->ops->getinfo) { 11969566063dSJacob Faibussowitsch PetscCall(MatGetInfo(matis->A,MAT_LOCAL,&info)); 11977fa8f2d3SStefano Zampini isend[0] = info.nz_used; 11987fa8f2d3SStefano Zampini isend[1] = info.nz_allocated; 11997fa8f2d3SStefano Zampini isend[2] = info.nz_unneeded; 12007fa8f2d3SStefano Zampini isend[3] = info.memory; 12017fa8f2d3SStefano Zampini isend[4] = info.mallocs; 1202a2ccb5f9Sstefano_zampini } else { 1203a2ccb5f9Sstefano_zampini isend[0] = 0.; 1204a2ccb5f9Sstefano_zampini isend[1] = 0.; 1205a2ccb5f9Sstefano_zampini isend[2] = 0.; 1206a2ccb5f9Sstefano_zampini isend[3] = 0.; 1207a2ccb5f9Sstefano_zampini isend[4] = 0.; 1208a2ccb5f9Sstefano_zampini } 1209314ce898Sstefano_zampini isend[5] = matis->A->num_ass; 12107fa8f2d3SStefano Zampini if (flag == MAT_LOCAL) { 12117fa8f2d3SStefano Zampini ginfo->nz_used = isend[0]; 12127fa8f2d3SStefano Zampini ginfo->nz_allocated = isend[1]; 12137fa8f2d3SStefano Zampini ginfo->nz_unneeded = isend[2]; 12147fa8f2d3SStefano Zampini ginfo->memory = isend[3]; 12157fa8f2d3SStefano Zampini ginfo->mallocs = isend[4]; 1216314ce898Sstefano_zampini ginfo->assemblies = isend[5]; 12177fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_MAX) { 12189566063dSJacob Faibussowitsch PetscCallMPI(MPIU_Allreduce(isend,irecv,6,MPIU_PETSCLOGDOUBLE,MPI_MAX,PetscObjectComm((PetscObject)A))); 12197fa8f2d3SStefano Zampini 12207fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 12217fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 12227fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 12237fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 12247fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 1225314ce898Sstefano_zampini ginfo->assemblies = irecv[5]; 12267fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_SUM) { 12279566063dSJacob Faibussowitsch PetscCallMPI(MPIU_Allreduce(isend,irecv,5,MPIU_PETSCLOGDOUBLE,MPI_SUM,PetscObjectComm((PetscObject)A))); 12287fa8f2d3SStefano Zampini 12297fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 12307fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 12317fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 12327fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 12337fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 12347fa8f2d3SStefano Zampini ginfo->assemblies = A->num_ass; 12357fa8f2d3SStefano Zampini } 12367fa8f2d3SStefano Zampini ginfo->block_size = bs; 12377fa8f2d3SStefano Zampini ginfo->fill_ratio_given = 0; 12387fa8f2d3SStefano Zampini ginfo->fill_ratio_needed = 0; 12397fa8f2d3SStefano Zampini ginfo->factor_mallocs = 0; 12405e3038f0Sstefano_zampini PetscFunctionReturn(0); 12415e3038f0Sstefano_zampini } 12425e3038f0Sstefano_zampini 12438b9382cfSStefano Zampini static PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B) 1244d7f69cd0SStefano Zampini { 1245d7f69cd0SStefano Zampini Mat C,lC,lA; 1246d7f69cd0SStefano Zampini 1247d7f69cd0SStefano Zampini PetscFunctionBegin; 1248cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) { 1249cf37664fSBarry Smith ISLocalToGlobalMapping rl2g,cl2g; 12509566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&C)); 12519566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N)); 12529566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs))); 12539566063dSJacob Faibussowitsch PetscCall(MatSetType(C,MATIS)); 12549566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A,&rl2g,&cl2g)); 12559566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(C,cl2g,rl2g)); 1256e432b41dSStefano Zampini } else C = *B; 1257d7f69cd0SStefano Zampini 1258d7f69cd0SStefano Zampini /* perform local transposition */ 12599566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A,&lA)); 12609566063dSJacob Faibussowitsch PetscCall(MatTranspose(lA,MAT_INITIAL_MATRIX,&lC)); 12619566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(lC,lA->cmap->mapping,lA->rmap->mapping)); 12629566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(C,lC)); 12639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lC)); 1264d7f69cd0SStefano Zampini 1265cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 1266d7f69cd0SStefano Zampini *B = C; 1267d7f69cd0SStefano Zampini } else { 12689566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(A,&C)); 1269d7f69cd0SStefano Zampini } 12709566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY)); 12719566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY)); 1272d7f69cd0SStefano Zampini PetscFunctionReturn(0); 1273d7f69cd0SStefano Zampini } 1274d7f69cd0SStefano Zampini 12758b9382cfSStefano Zampini static PetscErrorCode MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode) 12763fd1c9e7SStefano Zampini { 12773fd1c9e7SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 12783fd1c9e7SStefano Zampini 12793fd1c9e7SStefano Zampini PetscFunctionBegin; 12804b89b9cdSStefano Zampini if (D) { /* MatShift_IS pass D = NULL */ 12819566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD)); 12829566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD)); 12833fd1c9e7SStefano Zampini } 12849566063dSJacob Faibussowitsch PetscCall(VecPointwiseDivide(is->y,is->y,is->counter)); 12859566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(is->A,is->y,insmode)); 12863fd1c9e7SStefano Zampini PetscFunctionReturn(0); 12873fd1c9e7SStefano Zampini } 12883fd1c9e7SStefano Zampini 12898b9382cfSStefano Zampini static PetscErrorCode MatShift_IS(Mat A,PetscScalar a) 12903fd1c9e7SStefano Zampini { 12914b89b9cdSStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 12923fd1c9e7SStefano Zampini 12933fd1c9e7SStefano Zampini PetscFunctionBegin; 12949566063dSJacob Faibussowitsch PetscCall(VecSet(is->y,a)); 12959566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_IS(A,NULL,ADD_VALUES)); 12963fd1c9e7SStefano Zampini PetscFunctionReturn(0); 12973fd1c9e7SStefano Zampini } 12983fd1c9e7SStefano Zampini 1299f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1300f26d0771SStefano Zampini { 1301f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1302f26d0771SStefano Zampini 1303f26d0771SStefano Zampini PetscFunctionBegin; 13042c71b3e2SJacob Faibussowitsch PetscCheckFalse(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); 13059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l)); 13069566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l)); 13079566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv)); 1308f26d0771SStefano Zampini PetscFunctionReturn(0); 1309f26d0771SStefano Zampini } 1310f26d0771SStefano Zampini 1311f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1312f26d0771SStefano Zampini { 1313f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1314f26d0771SStefano Zampini 1315f26d0771SStefano Zampini PetscFunctionBegin; 13162c71b3e2SJacob Faibussowitsch PetscCheckFalse(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); 13179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l)); 13189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l)); 13199566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv)); 1320f26d0771SStefano Zampini PetscFunctionReturn(0); 1321f26d0771SStefano Zampini } 1322f26d0771SStefano Zampini 13237dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat) 1324a8116848SStefano Zampini { 1325a8116848SStefano Zampini Mat locmat,newlocmat; 1326a8116848SStefano Zampini Mat_IS *newmatis; 1327a8116848SStefano Zampini const PetscInt *idxs; 1328a8116848SStefano Zampini PetscInt i,m,n; 1329a8116848SStefano Zampini 1330a8116848SStefano Zampini PetscFunctionBegin; 1331a8116848SStefano Zampini if (scall == MAT_REUSE_MATRIX) { 1332a8116848SStefano Zampini PetscBool ismatis; 1333a8116848SStefano Zampini 13349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis)); 133528b400f6SJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type"); 1336a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 133728b400f6SJacob Faibussowitsch PetscCheck(newmatis->getsub_ris,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS"); 133828b400f6SJacob Faibussowitsch PetscCheck(newmatis->getsub_cis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS"); 1339a8116848SStefano Zampini } 1340a8116848SStefano Zampini /* irow and icol may not have duplicate entries */ 134176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 134276bd3646SJed Brown Vec rtest,ltest; 134376bd3646SJed Brown const PetscScalar *array; 134476bd3646SJed Brown 13459566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(mat,<est,&rtest)); 13469566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(irow,&n)); 13479566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irow,&idxs)); 1348a8116848SStefano Zampini for (i=0;i<n;i++) { 13499566063dSJacob Faibussowitsch PetscCall(VecSetValue(rtest,idxs[i],1.0,ADD_VALUES)); 1350a8116848SStefano Zampini } 13519566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(rtest)); 13529566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(rtest)); 13539566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rtest,&n)); 13549566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(rtest,&m,NULL)); 13559566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(rtest,&array)); 13562c71b3e2SJacob Faibussowitsch for (i=0;i<n;i++) PetscCheckFalse(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])); 13579566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(rtest,&array)); 13589566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irow,&idxs)); 13599566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(icol,&n)); 13609566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icol,&idxs)); 1361a8116848SStefano Zampini for (i=0;i<n;i++) { 13629566063dSJacob Faibussowitsch PetscCall(VecSetValue(ltest,idxs[i],1.0,ADD_VALUES)); 1363a8116848SStefano Zampini } 13649566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(ltest)); 13659566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(ltest)); 13669566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ltest,&n)); 13679566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(ltest,&m,NULL)); 13689566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(ltest,&array)); 13692c71b3e2SJacob Faibussowitsch for (i=0;i<n;i++) PetscCheckFalse(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])); 13709566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(ltest,&array)); 13719566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icol,&idxs)); 13729566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rtest)); 13739566063dSJacob Faibussowitsch PetscCall(VecDestroy(<est)); 137476bd3646SJed Brown } 1375a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 1376a8116848SStefano Zampini Mat_IS *matis = (Mat_IS*)mat->data; 1377a8116848SStefano Zampini ISLocalToGlobalMapping rl2g; 1378a8116848SStefano Zampini IS is; 1379a8116848SStefano Zampini PetscInt *lidxs,*lgidxs,*newgidxs; 1380306cf5c7SStefano Zampini PetscInt ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs; 138194342113SStefano Zampini PetscBool cong; 1382a8116848SStefano Zampini MPI_Comm comm; 1383a8116848SStefano Zampini 13849566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat,&comm)); 13859566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(mat,&arbs,&acbs)); 13869566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(irow,&irbs)); 13879566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(icol,&icbs)); 1388306cf5c7SStefano Zampini rbs = arbs == irbs ? irbs : 1; 1389306cf5c7SStefano Zampini cbs = acbs == icbs ? icbs : 1; 13909566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(irow,&m)); 13919566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(icol,&n)); 13929566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,newmat)); 13939566063dSJacob Faibussowitsch PetscCall(MatSetType(*newmat,MATIS)); 13949566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE)); 13959566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(*newmat,rbs,cbs)); 1396a8116848SStefano Zampini /* communicate irow to their owners in the layout */ 13979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irow,&idxs)); 13989566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs)); 13999566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irow,&idxs)); 14009566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata,matis->sf->nroots)); 1401a8116848SStefano Zampini for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1; 14029566063dSJacob Faibussowitsch PetscCall(PetscFree(lidxs)); 14039566063dSJacob Faibussowitsch PetscCall(PetscFree(lgidxs)); 14049566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 14059566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 14063d996552SStefano Zampini for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++; 14079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc,&newgidxs)); 14089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc,&lidxs)); 14093d996552SStefano Zampini for (i=0,newloc=0;i<matis->sf->nleaves;i++) 1410a8116848SStefano Zampini if (matis->sf_leafdata[i]) { 1411a8116848SStefano Zampini lidxs[newloc] = i; 1412a8116848SStefano Zampini newgidxs[newloc++] = matis->sf_leafdata[i]-1; 1413a8116848SStefano Zampini } 14149566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is)); 14159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g)); 14169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(rl2g,rbs)); 14179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1418a8116848SStefano Zampini /* local is to extract local submatrix */ 1419a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 14209566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris)); 14219566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(mat,&cong)); 142294342113SStefano Zampini if (cong && irow == icol && matis->csf == matis->sf) { 14239566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g)); 14249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)newmatis->getsub_ris)); 1425a8116848SStefano Zampini newmatis->getsub_cis = newmatis->getsub_ris; 1426a8116848SStefano Zampini } else { 1427a8116848SStefano Zampini ISLocalToGlobalMapping cl2g; 1428a8116848SStefano Zampini 1429a8116848SStefano Zampini /* communicate icol to their owners in the layout */ 14309566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icol,&idxs)); 14319566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs)); 14329566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icol,&idxs)); 14339566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->csf_rootdata,matis->csf->nroots)); 1434a8116848SStefano Zampini for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1; 14359566063dSJacob Faibussowitsch PetscCall(PetscFree(lidxs)); 14369566063dSJacob Faibussowitsch PetscCall(PetscFree(lgidxs)); 14379566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata,MPI_REPLACE)); 14389566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata,MPI_REPLACE)); 14393d996552SStefano Zampini for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++; 14409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc,&newgidxs)); 14419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc,&lidxs)); 14423d996552SStefano Zampini for (i=0,newloc=0;i<matis->csf->nleaves;i++) 1443a8116848SStefano Zampini if (matis->csf_leafdata[i]) { 1444a8116848SStefano Zampini lidxs[newloc] = i; 1445a8116848SStefano Zampini newgidxs[newloc++] = matis->csf_leafdata[i]-1; 1446a8116848SStefano Zampini } 14479566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is)); 14489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g)); 14499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(cl2g,cbs)); 14509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1451a8116848SStefano Zampini /* local is to extract local submatrix */ 14529566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis)); 14539566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g)); 14549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 1455a8116848SStefano Zampini } 14569566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 1457a8116848SStefano Zampini } else { 14589566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat,&newlocmat)); 1459a8116848SStefano Zampini } 14609566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat,&locmat)); 1461a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 14629566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat)); 1463a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 14649566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat,newlocmat)); 14659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlocmat)); 1466a8116848SStefano Zampini } 14679566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY)); 14689566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY)); 1469a8116848SStefano Zampini PetscFunctionReturn(0); 1470a8116848SStefano Zampini } 1471a8116848SStefano Zampini 1472a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str) 14732b404112SStefano Zampini { 14742b404112SStefano Zampini Mat_IS *a = (Mat_IS*)A->data,*b; 14752b404112SStefano Zampini PetscBool ismatis; 14762b404112SStefano Zampini 14772b404112SStefano Zampini PetscFunctionBegin; 14789566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis)); 147928b400f6SJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented"); 14802b404112SStefano Zampini b = (Mat_IS*)B->data; 14819566063dSJacob Faibussowitsch PetscCall(MatCopy(a->A,b->A,str)); 14829566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 14832b404112SStefano Zampini PetscFunctionReturn(0); 14842b404112SStefano Zampini } 14852b404112SStefano Zampini 1486a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool *missing,PetscInt *d) 14876bd84002SStefano Zampini { 1488527b2640SStefano Zampini Vec v; 1489527b2640SStefano Zampini const PetscScalar *array; 1490527b2640SStefano Zampini PetscInt i,n; 14916bd84002SStefano Zampini 14926bd84002SStefano Zampini PetscFunctionBegin; 1493527b2640SStefano Zampini *missing = PETSC_FALSE; 14949566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A,NULL,&v)); 14959566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(A,v)); 14969566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v,&n)); 14979566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v,&array)); 1498527b2640SStefano Zampini for (i=0;i<n;i++) if (array[i] == 0.) break; 14999566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v,&array)); 15009566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 1501527b2640SStefano Zampini if (i != n) *missing = PETSC_TRUE; 1502527b2640SStefano Zampini if (d) { 1503527b2640SStefano Zampini *d = -1; 1504527b2640SStefano Zampini if (*missing) { 1505527b2640SStefano Zampini PetscInt rstart; 15069566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A,&rstart,NULL)); 1507527b2640SStefano Zampini *d = i+rstart; 1508527b2640SStefano Zampini } 1509527b2640SStefano Zampini } 15106bd84002SStefano Zampini PetscFunctionReturn(0); 15116bd84002SStefano Zampini } 15126bd84002SStefano Zampini 1513cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B) 151428f4e0baSStefano Zampini { 151528f4e0baSStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 151628f4e0baSStefano Zampini const PetscInt *gidxs; 15174f2d7cafSStefano Zampini PetscInt nleaves; 151828f4e0baSStefano Zampini 151928f4e0baSStefano Zampini PetscFunctionBegin; 15204f2d7cafSStefano Zampini if (matis->sf) PetscFunctionReturn(0); 15219566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf)); 15229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping,&gidxs)); 15239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping,&nleaves)); 15249566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs)); 15259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping,&gidxs)); 15269566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata)); 1527e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { /* setup SF for columns */ 15289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping,&nleaves)); 15299566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf)); 15309566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping,&gidxs)); 15319566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs)); 15329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping,&gidxs)); 15339566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata)); 1534a8116848SStefano Zampini } else { 1535a8116848SStefano Zampini matis->csf = matis->sf; 1536a8116848SStefano Zampini matis->csf_leafdata = matis->sf_leafdata; 1537a8116848SStefano Zampini matis->csf_rootdata = matis->sf_rootdata; 1538a8116848SStefano Zampini } 153928f4e0baSStefano Zampini PetscFunctionReturn(0); 154028f4e0baSStefano Zampini } 15412e1947a5SStefano Zampini 1542eb82efa4SStefano Zampini /*@ 154375d48cdbSStefano Zampini MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP. 154475d48cdbSStefano Zampini 1545d083f849SBarry Smith Collective 154675d48cdbSStefano Zampini 154775d48cdbSStefano Zampini Input Parameters: 154875d48cdbSStefano Zampini + A - the matrix 154975d48cdbSStefano Zampini - store - the boolean flag 155075d48cdbSStefano Zampini 155175d48cdbSStefano Zampini Level: advanced 155275d48cdbSStefano Zampini 155375d48cdbSStefano Zampini Notes: 155475d48cdbSStefano Zampini 155575d48cdbSStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP() 155675d48cdbSStefano Zampini @*/ 155775d48cdbSStefano Zampini PetscErrorCode MatISStoreL2L(Mat A, PetscBool store) 155875d48cdbSStefano Zampini { 155975d48cdbSStefano Zampini PetscFunctionBegin; 156075d48cdbSStefano Zampini PetscValidHeaderSpecific(A,MAT_CLASSID,1); 156175d48cdbSStefano Zampini PetscValidType(A,1); 156275d48cdbSStefano Zampini PetscValidLogicalCollectiveBool(A,store,2); 1563*cac4c232SBarry Smith PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store)); 156475d48cdbSStefano Zampini PetscFunctionReturn(0); 156575d48cdbSStefano Zampini } 156675d48cdbSStefano Zampini 156775d48cdbSStefano Zampini static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store) 156875d48cdbSStefano Zampini { 156975d48cdbSStefano Zampini Mat_IS *matis = (Mat_IS*)(A->data); 157075d48cdbSStefano Zampini 157175d48cdbSStefano Zampini PetscFunctionBegin; 157275d48cdbSStefano Zampini matis->storel2l = store; 157375d48cdbSStefano Zampini if (!store) { 15749566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL)); 157575d48cdbSStefano Zampini } 157675d48cdbSStefano Zampini PetscFunctionReturn(0); 157775d48cdbSStefano Zampini } 157875d48cdbSStefano Zampini 157975d48cdbSStefano Zampini /*@ 1580f03112d0SStefano Zampini MatISFixLocalEmpty - Compress out zero local rows from the local matrices 1581f03112d0SStefano Zampini 1582d083f849SBarry Smith Collective 1583f03112d0SStefano Zampini 1584f03112d0SStefano Zampini Input Parameters: 1585f03112d0SStefano Zampini + A - the matrix 1586f03112d0SStefano Zampini - fix - the boolean flag 1587f03112d0SStefano Zampini 1588f03112d0SStefano Zampini Level: advanced 1589f03112d0SStefano Zampini 1590f03112d0SStefano Zampini Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process. 1591f03112d0SStefano Zampini 1592f03112d0SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatAssemblyEnd(), MAT_FINAL_ASSEMBLY 1593f03112d0SStefano Zampini @*/ 1594f03112d0SStefano Zampini PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix) 1595f03112d0SStefano Zampini { 1596f03112d0SStefano Zampini PetscFunctionBegin; 1597f03112d0SStefano Zampini PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1598f03112d0SStefano Zampini PetscValidType(A,1); 1599f03112d0SStefano Zampini PetscValidLogicalCollectiveBool(A,fix,2); 1600*cac4c232SBarry Smith PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix)); 1601f03112d0SStefano Zampini PetscFunctionReturn(0); 1602f03112d0SStefano Zampini } 1603f03112d0SStefano Zampini 1604f03112d0SStefano Zampini static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix) 1605f03112d0SStefano Zampini { 1606f03112d0SStefano Zampini Mat_IS *matis = (Mat_IS*)(A->data); 1607f03112d0SStefano Zampini 1608f03112d0SStefano Zampini PetscFunctionBegin; 1609f03112d0SStefano Zampini matis->locempty = fix; 1610f03112d0SStefano Zampini PetscFunctionReturn(0); 1611f03112d0SStefano Zampini } 1612f03112d0SStefano Zampini 1613f03112d0SStefano Zampini /*@ 1614a88811baSStefano Zampini MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix. 1615a88811baSStefano Zampini 1616d083f849SBarry Smith Collective 1617a88811baSStefano Zampini 1618a88811baSStefano Zampini Input Parameters: 1619a88811baSStefano Zampini + B - the matrix 1620a88811baSStefano Zampini . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1621a88811baSStefano Zampini (same value is used for all local rows) 1622a88811baSStefano Zampini . d_nnz - array containing the number of nonzeros in the various rows of the 1623a88811baSStefano Zampini DIAGONAL portion of the local submatrix (possibly different for each row) 1624a88811baSStefano Zampini or NULL, if d_nz is used to specify the nonzero structure. 1625a88811baSStefano Zampini The size of this array is equal to the number of local rows, i.e 'm'. 1626a88811baSStefano Zampini For matrices that will be factored, you must leave room for (and set) 1627a88811baSStefano Zampini the diagonal entry even if it is zero. 1628a88811baSStefano Zampini . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1629a88811baSStefano Zampini submatrix (same value is used for all local rows). 1630a88811baSStefano Zampini - o_nnz - array containing the number of nonzeros in the various rows of the 1631a88811baSStefano Zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 1632a88811baSStefano Zampini each row) or NULL, if o_nz is used to specify the nonzero 1633a88811baSStefano Zampini structure. The size of this array is equal to the number 1634a88811baSStefano Zampini of local rows, i.e 'm'. 1635a88811baSStefano Zampini 1636a88811baSStefano Zampini If the *_nnz parameter is given then the *_nz parameter is ignored 1637a88811baSStefano Zampini 1638a88811baSStefano Zampini Level: intermediate 1639a88811baSStefano Zampini 164095452b02SPatrick Sanan Notes: 164195452b02SPatrick Sanan This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition 1642a88811baSStefano Zampini from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local 1643a88811baSStefano Zampini matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 1644a88811baSStefano Zampini 16453c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS 1646a88811baSStefano Zampini @*/ 16472e1947a5SStefano Zampini PetscErrorCode MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 16482e1947a5SStefano Zampini { 16492e1947a5SStefano Zampini PetscFunctionBegin; 16502e1947a5SStefano Zampini PetscValidHeaderSpecific(B,MAT_CLASSID,1); 16512e1947a5SStefano Zampini PetscValidType(B,1); 1652*cac4c232SBarry Smith PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz)); 16532e1947a5SStefano Zampini PetscFunctionReturn(0); 16542e1947a5SStefano Zampini } 16552e1947a5SStefano Zampini 1656844bd0d7SStefano Zampini /* this is used by DMDA */ 1657844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 16582e1947a5SStefano Zampini { 16592e1947a5SStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 166028f4e0baSStefano Zampini PetscInt bs,i,nlocalcols; 16612e1947a5SStefano Zampini 16622e1947a5SStefano Zampini PetscFunctionBegin; 16639566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 16644f2d7cafSStefano Zampini if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz; 16654f2d7cafSStefano Zampini else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i]; 16664f2d7cafSStefano Zampini 16674f2d7cafSStefano Zampini if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz; 16684f2d7cafSStefano Zampini else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i]; 16694f2d7cafSStefano Zampini 16709566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 16719566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A,NULL,&nlocalcols)); 16729566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(matis->A,&bs)); 16739566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 16744f2d7cafSStefano Zampini 16754f2d7cafSStefano Zampini for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols); 16769566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata)); 16770f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE) 16789566063dSJacob Faibussowitsch PetscCall(MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL)); 16790f2f62c7SStefano Zampini #endif 16804f2d7cafSStefano Zampini 1681fc989267SStefano Zampini for (i=0;i<matis->sf->nleaves/bs;i++) { 1682fc989267SStefano Zampini PetscInt b; 1683fc989267SStefano Zampini 1684fc989267SStefano Zampini matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs; 1685fc989267SStefano Zampini for (b=1;b<bs;b++) { 1686fc989267SStefano Zampini matis->sf_leafdata[i] = PetscMax(matis->sf_leafdata[i],matis->sf_leafdata[i*bs+b]/bs); 1687fc989267SStefano Zampini } 1688fc989267SStefano Zampini } 16899566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata)); 16904f2d7cafSStefano Zampini 169100a59248SStefano Zampini nlocalcols /= bs; 169200a59248SStefano Zampini for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols - i); 16939566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata)); 16940f2f62c7SStefano Zampini 16950f2f62c7SStefano Zampini /* for other matrix types */ 16969566063dSJacob Faibussowitsch PetscCall(MatSetUp(matis->A)); 16972e1947a5SStefano Zampini PetscFunctionReturn(0); 16982e1947a5SStefano Zampini } 1699b4319ba4SBarry Smith 17003927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce) 17013927de2eSStefano Zampini { 17023927de2eSStefano Zampini Mat_IS *matis = (Mat_IS*)(A->data); 17033927de2eSStefano Zampini PetscInt *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership; 1704ecf5a873SStefano Zampini const PetscInt *global_indices_r,*global_indices_c; 17053927de2eSStefano Zampini PetscInt i,j,bs,rows,cols; 17063927de2eSStefano Zampini PetscInt lrows,lcols; 17073927de2eSStefano Zampini PetscInt local_rows,local_cols; 1708f03112d0SStefano Zampini PetscMPIInt size; 17093927de2eSStefano Zampini PetscBool isdense,issbaij; 17103927de2eSStefano Zampini PetscErrorCode ierr; 17113927de2eSStefano Zampini 17123927de2eSStefano Zampini PetscFunctionBegin; 17139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size)); 17149566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&rows,&cols)); 17159566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A,&bs)); 17169566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A,&local_rows,&local_cols)); 17179566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense)); 17189566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij)); 17199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping,&global_indices_r)); 1720e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 17219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping,&global_indices_c)); 17220dfc91b7SStefano Zampini } else global_indices_c = global_indices_r; 1723ecf5a873SStefano Zampini 17249566063dSJacob Faibussowitsch if (issbaij) PetscCall(MatGetRowUpperTriangular(matis->A)); 17253927de2eSStefano Zampini /* 1726ecf5a873SStefano Zampini An SF reduce is needed to sum up properly on shared rows. 17273927de2eSStefano Zampini Note that generally preallocation is not exact, since it overestimates nonzeros 17283927de2eSStefano Zampini */ 17299566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,&lrows,&lcols)); 17309566063dSJacob Faibussowitsch ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);PetscCall(ierr); 17313927de2eSStefano Zampini /* All processes need to compute entire row ownership */ 17329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rows,&row_ownership)); 17339566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges)); 1734f03112d0SStefano Zampini for (i=0;i<size;i++) { 17355f80ce2aSJacob Faibussowitsch for (j=mat_ranges[i];j<mat_ranges[i+1];j++) row_ownership[j] = i; 17363927de2eSStefano Zampini } 17379566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges)); 17383927de2eSStefano Zampini 17393927de2eSStefano Zampini /* 17403927de2eSStefano Zampini my_dnz and my_onz contains exact contribution to preallocation from each local mat 17413927de2eSStefano Zampini then, they will be summed up properly. This way, preallocation is always sufficient 17423927de2eSStefano Zampini */ 17439566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz)); 17443927de2eSStefano Zampini /* preallocation as a MATAIJ */ 17453927de2eSStefano Zampini if (isdense) { /* special case for dense local matrices */ 17463927de2eSStefano Zampini for (i=0;i<local_rows;i++) { 174712dfadf8SStefano Zampini PetscInt owner = row_ownership[global_indices_r[i]]; 174812dfadf8SStefano Zampini for (j=0;j<local_cols;j++) { 1749ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[j]; 17503927de2eSStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */ 17513927de2eSStefano Zampini my_dnz[i] += 1; 17523927de2eSStefano Zampini } else { /* offdiag block */ 17533927de2eSStefano Zampini my_onz[i] += 1; 17543927de2eSStefano Zampini } 17553927de2eSStefano Zampini } 17563927de2eSStefano Zampini } 1757bb1015c3SStefano Zampini } else if (matis->A->ops->getrowij) { 1758bb1015c3SStefano Zampini const PetscInt *ii,*jj,*jptr; 1759bb1015c3SStefano Zampini PetscBool done; 17609566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done)); 17615f80ce2aSJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ"); 1762bb1015c3SStefano Zampini jptr = jj; 1763bb1015c3SStefano Zampini for (i=0;i<local_rows;i++) { 1764bb1015c3SStefano Zampini PetscInt index_row = global_indices_r[i]; 1765bb1015c3SStefano Zampini for (j=0;j<ii[i+1]-ii[i];j++,jptr++) { 1766bb1015c3SStefano Zampini PetscInt owner = row_ownership[index_row]; 1767bb1015c3SStefano Zampini PetscInt index_col = global_indices_c[*jptr]; 1768bb1015c3SStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */ 1769bb1015c3SStefano Zampini my_dnz[i] += 1; 1770bb1015c3SStefano Zampini } else { /* offdiag block */ 1771bb1015c3SStefano Zampini my_onz[i] += 1; 1772bb1015c3SStefano Zampini } 1773bb1015c3SStefano Zampini /* same as before, interchanging rows and cols */ 1774bb1015c3SStefano Zampini if (issbaij && index_col != index_row) { 1775bb1015c3SStefano Zampini owner = row_ownership[index_col]; 1776bb1015c3SStefano Zampini if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1]) { 1777bb1015c3SStefano Zampini my_dnz[*jptr] += 1; 1778bb1015c3SStefano Zampini } else { 1779bb1015c3SStefano Zampini my_onz[*jptr] += 1; 1780bb1015c3SStefano Zampini } 1781bb1015c3SStefano Zampini } 1782bb1015c3SStefano Zampini } 1783bb1015c3SStefano Zampini } 17849566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done)); 17855f80ce2aSJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ"); 1786bb1015c3SStefano Zampini } else { /* loop over rows and use MatGetRow */ 17873927de2eSStefano Zampini for (i=0;i<local_rows;i++) { 17883927de2eSStefano Zampini const PetscInt *cols; 1789ecf5a873SStefano Zampini PetscInt ncols,index_row = global_indices_r[i]; 17909566063dSJacob Faibussowitsch PetscCall(MatGetRow(matis->A,i,&ncols,&cols,NULL)); 17913927de2eSStefano Zampini for (j=0;j<ncols;j++) { 17923927de2eSStefano Zampini PetscInt owner = row_ownership[index_row]; 1793ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[cols[j]]; 17943927de2eSStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */ 17953927de2eSStefano Zampini my_dnz[i] += 1; 17963927de2eSStefano Zampini } else { /* offdiag block */ 17973927de2eSStefano Zampini my_onz[i] += 1; 17983927de2eSStefano Zampini } 17993927de2eSStefano Zampini /* same as before, interchanging rows and cols */ 1800d9a9e74cSStefano Zampini if (issbaij && index_col != index_row) { 18013927de2eSStefano Zampini owner = row_ownership[index_col]; 18023927de2eSStefano Zampini if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1]) { 1803d9a9e74cSStefano Zampini my_dnz[cols[j]] += 1; 18043927de2eSStefano Zampini } else { 1805d9a9e74cSStefano Zampini my_onz[cols[j]] += 1; 18063927de2eSStefano Zampini } 18073927de2eSStefano Zampini } 18083927de2eSStefano Zampini } 18099566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(matis->A,i,&ncols,&cols,NULL)); 18103927de2eSStefano Zampini } 18113927de2eSStefano Zampini } 1812ecf5a873SStefano Zampini if (global_indices_c != global_indices_r) { 18139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping,&global_indices_c)); 1814ecf5a873SStefano Zampini } 18159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping,&global_indices_r)); 18169566063dSJacob Faibussowitsch PetscCall(PetscFree(row_ownership)); 1817ecf5a873SStefano Zampini 1818ecf5a873SStefano Zampini /* Reduce my_dnz and my_onz */ 18193927de2eSStefano Zampini if (maxreduce) { 18209566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX)); 18219566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX)); 18229566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX)); 18239566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX)); 18243927de2eSStefano Zampini } else { 18259566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM)); 18269566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM)); 18279566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM)); 18289566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM)); 18293927de2eSStefano Zampini } 18309566063dSJacob Faibussowitsch PetscCall(PetscFree2(my_dnz,my_onz)); 18313927de2eSStefano Zampini 18323927de2eSStefano Zampini /* Resize preallocation if overestimated */ 18333927de2eSStefano Zampini for (i=0;i<lrows;i++) { 18343927de2eSStefano Zampini dnz[i] = PetscMin(dnz[i],lcols); 18353927de2eSStefano Zampini onz[i] = PetscMin(onz[i],cols-lcols); 18363927de2eSStefano Zampini } 18371670daf9Sstefano_zampini 18381670daf9Sstefano_zampini /* Set preallocation */ 18399566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B,A,A)); 18409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B,0,dnz)); 18419566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(B,0,dnz,0,onz)); 184253b44cf5SStefano Zampini for (i=0;i<lrows;i+=bs) { 184353b44cf5SStefano Zampini PetscInt b, d = dnz[i],o = onz[i]; 184453b44cf5SStefano Zampini 184553b44cf5SStefano Zampini for (b=1;b<bs;b++) { 184653b44cf5SStefano Zampini d = PetscMax(d,dnz[i+b]); 184753b44cf5SStefano Zampini o = PetscMax(o,onz[i+b]); 184853b44cf5SStefano Zampini } 184953b44cf5SStefano Zampini dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs); 185053b44cf5SStefano Zampini onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs); 18513927de2eSStefano Zampini } 18529566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(B,bs,0,dnz)); 18539566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz)); 18549566063dSJacob Faibussowitsch PetscCall(MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz)); 18559566063dSJacob Faibussowitsch ierr = MatPreallocateFinalize(dnz,onz);PetscCall(ierr); 18569566063dSJacob Faibussowitsch if (issbaij) PetscCall(MatRestoreRowUpperTriangular(matis->A)); 18579566063dSJacob Faibussowitsch PetscCall(MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE)); 18583927de2eSStefano Zampini PetscFunctionReturn(0); 18593927de2eSStefano Zampini } 18603927de2eSStefano Zampini 1861487b449aSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M) 1862b7ce53b6SStefano Zampini { 1863b7ce53b6SStefano Zampini Mat_IS *matis = (Mat_IS*)(mat->data); 1864487b449aSStefano Zampini Mat local_mat,MT; 186553b44cf5SStefano Zampini PetscInt rbs,cbs,rows,cols,lrows,lcols; 1866b7ce53b6SStefano Zampini PetscInt local_rows,local_cols; 1867b9ed4604SStefano Zampini PetscBool isseqdense,isseqsbaij,isseqaij,isseqbaij; 1868f03112d0SStefano Zampini PetscMPIInt size; 18691683a169SBarry Smith const PetscScalar *array; 1870b7ce53b6SStefano Zampini 1871b7ce53b6SStefano Zampini PetscFunctionBegin; 18729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size)); 1873f03112d0SStefano Zampini if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) { 18741670daf9Sstefano_zampini Mat B; 187553b44cf5SStefano Zampini IS irows = NULL,icols = NULL; 1876487b449aSStefano Zampini PetscInt rbs,cbs; 18771670daf9Sstefano_zampini 18789566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping,&rbs)); 18799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping,&cbs)); 188053b44cf5SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */ 188153b44cf5SStefano Zampini IS rows,cols; 188253b44cf5SStefano Zampini const PetscInt *ridxs,*cidxs; 188353b44cf5SStefano Zampini PetscInt i,nw,*work; 188453b44cf5SStefano Zampini 18859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->rmapping,&ridxs)); 18869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping,&nw)); 188753b44cf5SStefano Zampini nw = nw/rbs; 18889566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nw,&work)); 188953b44cf5SStefano Zampini for (i=0;i<nw;i++) work[ridxs[i]] += 1; 189053b44cf5SStefano Zampini for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break; 189153b44cf5SStefano Zampini if (i == nw) { 18929566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows)); 18939566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(rows)); 18949566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rows,PETSC_DECIDE,&irows)); 18959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 189653b44cf5SStefano Zampini } 18979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->rmapping,&ridxs)); 18989566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 1899e432b41dSStefano Zampini if (irows && matis->rmapping != matis->cmapping) { 19009566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->cmapping,&cidxs)); 19019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping,&nw)); 190253b44cf5SStefano Zampini nw = nw/cbs; 19039566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nw,&work)); 190453b44cf5SStefano Zampini for (i=0;i<nw;i++) work[cidxs[i]] += 1; 190553b44cf5SStefano Zampini for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break; 190653b44cf5SStefano Zampini if (i == nw) { 19079566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols)); 19089566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(cols)); 19099566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(cols,PETSC_DECIDE,&icols)); 19109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 191153b44cf5SStefano Zampini } 19129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->cmapping,&cidxs)); 19139566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 191453b44cf5SStefano Zampini } else if (irows) { 19159566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)irows)); 191653b44cf5SStefano Zampini icols = irows; 191753b44cf5SStefano Zampini } 191853b44cf5SStefano Zampini } else { 19199566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows)); 19209566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols)); 19219566063dSJacob Faibussowitsch if (irows) PetscCall(PetscObjectReference((PetscObject)irows)); 19229566063dSJacob Faibussowitsch if (icols) PetscCall(PetscObjectReference((PetscObject)icols)); 192353b44cf5SStefano Zampini } 192453b44cf5SStefano Zampini if (!irows || !icols) { 19259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 19269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 192753b44cf5SStefano Zampini goto general_assembly; 192853b44cf5SStefano Zampini } 19299566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A,mtype,MAT_INITIAL_MATRIX,&B)); 1930487b449aSStefano Zampini if (reuse != MAT_INPLACE_MATRIX) { 19319566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B,irows,icols,reuse,M)); 19329566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows)); 19339566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols)); 1934487b449aSStefano Zampini } else { 1935487b449aSStefano Zampini Mat C; 1936487b449aSStefano Zampini 19379566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C)); 19389566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat,&C)); 1939487b449aSStefano Zampini } 19409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 19419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 19429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 19437c03b4e8SStefano Zampini PetscFunctionReturn(0); 19447c03b4e8SStefano Zampini } 194553b44cf5SStefano Zampini general_assembly: 19469566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat,&rows,&cols)); 19479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping,&rbs)); 19489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping,&cbs)); 19499566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat,&lrows,&lcols)); 19509566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A,&local_rows,&local_cols)); 19519566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense)); 19529566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij)); 19539566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij)); 19549566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij)); 19552c71b3e2SJacob Faibussowitsch PetscCheckFalse(!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name); 195676bd3646SJed Brown if (PetscDefined (USE_DEBUG)) { 195776bd3646SJed Brown PetscBool lb[4],bb[4]; 195876bd3646SJed Brown 1959b9ed4604SStefano Zampini lb[0] = isseqdense; 1960b9ed4604SStefano Zampini lb[1] = isseqaij; 1961b9ed4604SStefano Zampini lb[2] = isseqbaij; 1962b9ed4604SStefano Zampini lb[3] = isseqsbaij; 19639566063dSJacob Faibussowitsch PetscCallMPI(MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat))); 19642c71b3e2SJacob Faibussowitsch PetscCheckFalse(!bb[0] && !bb[1] && !bb[2] && !bb[3],PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type"); 196576bd3646SJed Brown } 1966b7ce53b6SStefano Zampini 1967487b449aSStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 19689566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&MT)); 19699566063dSJacob Faibussowitsch PetscCall(MatSetSizes(MT,lrows,lcols,rows,cols)); 19709566063dSJacob Faibussowitsch PetscCall(MatSetType(MT,mtype)); 19719566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(MT,rbs,cbs)); 19729566063dSJacob Faibussowitsch PetscCall(MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE)); 1973b7ce53b6SStefano Zampini } else { 197453b44cf5SStefano Zampini PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols; 1975487b449aSStefano Zampini 1976b7ce53b6SStefano Zampini /* some checks */ 1977487b449aSStefano Zampini MT = *M; 19789566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(MT,&mrbs,&mcbs)); 19799566063dSJacob Faibussowitsch PetscCall(MatGetSize(MT,&mrows,&mcols)); 19809566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(MT,&mlrows,&mlcols)); 19812c71b3e2SJacob Faibussowitsch PetscCheckFalse(mrows != rows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%" PetscInt_FMT " != %" PetscInt_FMT ")",rows,mrows); 19822c71b3e2SJacob Faibussowitsch PetscCheckFalse(mcols != cols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%" PetscInt_FMT " != %" PetscInt_FMT ")",cols,mcols); 19832c71b3e2SJacob Faibussowitsch PetscCheckFalse(mlrows != lrows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%" PetscInt_FMT " != %" PetscInt_FMT ")",lrows,mlrows); 19842c71b3e2SJacob Faibussowitsch PetscCheckFalse(mlcols != lcols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%" PetscInt_FMT " != %" PetscInt_FMT ")",lcols,mlcols); 19852c71b3e2SJacob Faibussowitsch PetscCheckFalse(mrbs != rbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%" PetscInt_FMT " != %" PetscInt_FMT ")",rbs,mrbs); 19862c71b3e2SJacob Faibussowitsch PetscCheckFalse(mcbs != cbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%" PetscInt_FMT " != %" PetscInt_FMT ")",cbs,mcbs); 19879566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(MT)); 1988b7ce53b6SStefano Zampini } 1989d9a9e74cSStefano Zampini 19908546b261SStefano Zampini if (isseqsbaij || isseqbaij) { 19919566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&local_mat)); 19928546b261SStefano Zampini isseqaij = PETSC_TRUE; 1993d9a9e74cSStefano Zampini } else { 19949566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 1995d9a9e74cSStefano Zampini local_mat = matis->A; 1996d9a9e74cSStefano Zampini } 1997686e3a49SStefano Zampini 1998b7ce53b6SStefano Zampini /* Set values */ 19999566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(MT,matis->rmapping,matis->cmapping)); 2000b9ed4604SStefano Zampini if (isseqdense) { /* special case for dense local matrices */ 200165066ba5SStefano Zampini PetscInt i,*dummy; 2002ecf5a873SStefano Zampini 20039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(local_rows,local_cols),&dummy)); 200465066ba5SStefano Zampini for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i; 20059566063dSJacob Faibussowitsch PetscCall(MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE)); 20069566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(local_mat,&array)); 20079566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES)); 20089566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(local_mat,&array)); 20099566063dSJacob Faibussowitsch PetscCall(PetscFree(dummy)); 2010686e3a49SStefano Zampini } else if (isseqaij) { 20116afe12f5SStefano Zampini const PetscInt *blocks; 20126afe12f5SStefano Zampini PetscInt i,nvtxs,*xadj,*adjncy, nb; 2013686e3a49SStefano Zampini PetscBool done; 20141683a169SBarry Smith PetscScalar *sarray; 2015686e3a49SStefano Zampini 20169566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done)); 201728b400f6SJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ"); 20189566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(local_mat,&sarray)); 20199566063dSJacob Faibussowitsch PetscCall(MatGetVariableBlockSizes(local_mat,&nb,&blocks)); 20206afe12f5SStefano Zampini if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */ 20216afe12f5SStefano Zampini PetscInt sum; 20226afe12f5SStefano Zampini 20236afe12f5SStefano Zampini for (i=0,sum=0;i<nb;i++) sum += blocks[i]; 20246afe12f5SStefano Zampini if (sum == nvtxs) { 20256afe12f5SStefano Zampini PetscInt r; 20266afe12f5SStefano Zampini 20276afe12f5SStefano Zampini for (i=0,r=0;i<nb;i++) { 20286bdcaf15SBarry 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]); 20299566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],sarray+xadj[r],ADD_VALUES)); 20306afe12f5SStefano Zampini r += blocks[i]; 20316afe12f5SStefano Zampini } 20326afe12f5SStefano Zampini } else { 2033686e3a49SStefano Zampini for (i=0;i<nvtxs;i++) { 20349566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES)); 2035686e3a49SStefano Zampini } 20366afe12f5SStefano Zampini } 20376afe12f5SStefano Zampini } else { 20386afe12f5SStefano 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)); 20406afe12f5SStefano Zampini } 20416afe12f5SStefano Zampini } 20429566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done)); 204328b400f6SJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ"); 20449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(local_mat,&sarray)); 2045686e3a49SStefano Zampini } else { /* very basic values insertion for all other matrix types */ 2046ecf5a873SStefano Zampini PetscInt i; 2047c0962df8SStefano Zampini 2048686e3a49SStefano Zampini for (i=0;i<local_rows;i++) { 2049686e3a49SStefano Zampini PetscInt j; 2050ecf5a873SStefano Zampini const PetscInt *local_indices_cols; 2051686e3a49SStefano Zampini 20529566063dSJacob Faibussowitsch PetscCall(MatGetRow(local_mat,i,&j,&local_indices_cols,&array)); 20539566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES)); 20549566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(local_mat,i,&j,&local_indices_cols,&array)); 2055686e3a49SStefano Zampini } 2056b7ce53b6SStefano Zampini } 20579566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY)); 20589566063dSJacob Faibussowitsch PetscCall(MatDestroy(&local_mat)); 20599566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY)); 2060b9ed4604SStefano Zampini if (isseqdense) { 20619566063dSJacob Faibussowitsch PetscCall(MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE)); 2062487b449aSStefano Zampini } 2063487b449aSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 20649566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat,&MT)); 2065487b449aSStefano Zampini } else if (reuse == MAT_INITIAL_MATRIX) { 2066487b449aSStefano Zampini *M = MT; 2067b7ce53b6SStefano Zampini } 2068b7ce53b6SStefano Zampini PetscFunctionReturn(0); 2069b7ce53b6SStefano Zampini } 2070b7ce53b6SStefano Zampini 2071b7ce53b6SStefano Zampini /*@ 2072b7ce53b6SStefano Zampini MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format 2073b7ce53b6SStefano Zampini 2074d8d19677SJose E. Roman Input Parameters: 2075a2b725a8SWilliam Gropp + mat - the matrix (should be of type MATIS) 2076a2b725a8SWilliam Gropp - reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 2077b7ce53b6SStefano Zampini 2078b7ce53b6SStefano Zampini Output Parameter: 2079b7ce53b6SStefano Zampini . newmat - the matrix in AIJ format 2080b7ce53b6SStefano Zampini 2081b7ce53b6SStefano Zampini Level: developer 2082b7ce53b6SStefano Zampini 208395452b02SPatrick Sanan Notes: 2084487b449aSStefano Zampini This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface. 2085b7ce53b6SStefano Zampini 2086487b449aSStefano Zampini .seealso: MATIS, MatConvert() 2087b7ce53b6SStefano Zampini @*/ 2088b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat) 2089b7ce53b6SStefano Zampini { 2090b7ce53b6SStefano Zampini PetscFunctionBegin; 2091b7ce53b6SStefano Zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2092b7ce53b6SStefano Zampini PetscValidLogicalCollectiveEnum(mat,reuse,2); 2093b7ce53b6SStefano Zampini PetscValidPointer(newmat,3); 2094487b449aSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 2095b7ce53b6SStefano Zampini PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3); 2096b7ce53b6SStefano Zampini PetscCheckSameComm(mat,1,*newmat,3); 20972c71b3e2SJacob Faibussowitsch PetscCheckFalse(mat == *newmat,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix"); 2098b7ce53b6SStefano Zampini } 2099*cac4c232SBarry Smith PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat)); 2100b7ce53b6SStefano Zampini PetscFunctionReturn(0); 2101b7ce53b6SStefano Zampini } 2102b7ce53b6SStefano Zampini 21038b9382cfSStefano Zampini static PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat) 2104ad6194a2SStefano Zampini { 2105ad6194a2SStefano Zampini Mat_IS *matis = (Mat_IS*)(mat->data); 2106c9225affSStefano Zampini PetscInt rbs,cbs,m,n,M,N; 2107ad6194a2SStefano Zampini Mat B,localmat; 2108ad6194a2SStefano Zampini 2109ad6194a2SStefano Zampini PetscFunctionBegin; 21109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs)); 21119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs)); 21129566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat,&M,&N)); 21139566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat,&m,&n)); 21149566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&B)); 21159566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B,m,n,M,N)); 21169566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B,rbs == cbs ? rbs : 1)); 21179566063dSJacob Faibussowitsch PetscCall(MatSetType(B,MATIS)); 21189566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B,matis->lmattype)); 21199566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B,mat->rmap->mapping,mat->cmap->mapping)); 21209566063dSJacob Faibussowitsch PetscCall(MatDuplicate(matis->A,op,&localmat)); 21219566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(localmat,matis->A->rmap->mapping,matis->A->cmap->mapping)); 21229566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B,localmat)); 21239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&localmat)); 21249566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 21259566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 2126ad6194a2SStefano Zampini *newmat = B; 2127ad6194a2SStefano Zampini PetscFunctionReturn(0); 2128ad6194a2SStefano Zampini } 2129ad6194a2SStefano Zampini 2130a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool *flg) 213169796d55SStefano Zampini { 213269796d55SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 213369796d55SStefano Zampini PetscBool local_sym; 213469796d55SStefano Zampini 213569796d55SStefano Zampini PetscFunctionBegin; 21369566063dSJacob Faibussowitsch PetscCall(MatIsHermitian(matis->A,tol,&local_sym)); 21379566063dSJacob Faibussowitsch PetscCallMPI(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A))); 213869796d55SStefano Zampini PetscFunctionReturn(0); 213969796d55SStefano Zampini } 214069796d55SStefano Zampini 2141a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg) 214269796d55SStefano Zampini { 214369796d55SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 214469796d55SStefano Zampini PetscBool local_sym; 214569796d55SStefano Zampini 214669796d55SStefano Zampini PetscFunctionBegin; 2147e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 2148e432b41dSStefano Zampini *flg = PETSC_FALSE; 2149e432b41dSStefano Zampini PetscFunctionReturn(0); 2150e432b41dSStefano Zampini } 21519566063dSJacob Faibussowitsch PetscCall(MatIsSymmetric(matis->A,tol,&local_sym)); 21529566063dSJacob Faibussowitsch PetscCallMPI(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A))); 215369796d55SStefano Zampini PetscFunctionReturn(0); 215469796d55SStefano Zampini } 215569796d55SStefano Zampini 215645471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool *flg) 215745471136SStefano Zampini { 215845471136SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 215945471136SStefano Zampini PetscBool local_sym; 216045471136SStefano Zampini 216145471136SStefano Zampini PetscFunctionBegin; 2162e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 216345471136SStefano Zampini *flg = PETSC_FALSE; 216445471136SStefano Zampini PetscFunctionReturn(0); 216545471136SStefano Zampini } 21669566063dSJacob Faibussowitsch PetscCall(MatIsStructurallySymmetric(matis->A,&local_sym)); 21679566063dSJacob Faibussowitsch PetscCallMPI(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A))); 216845471136SStefano Zampini PetscFunctionReturn(0); 216945471136SStefano Zampini } 217045471136SStefano Zampini 2171a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A) 2172b4319ba4SBarry Smith { 2173b4319ba4SBarry Smith Mat_IS *b = (Mat_IS*)A->data; 2174b4319ba4SBarry Smith 2175b4319ba4SBarry Smith PetscFunctionBegin; 21769566063dSJacob Faibussowitsch PetscCall(PetscFree(b->bdiag)); 21779566063dSJacob Faibussowitsch PetscCall(PetscFree(b->lmattype)); 21789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 21799566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->cctx)); 21809566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->rctx)); 21819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->x)); 21829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->y)); 21839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->counter)); 21849566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_ris)); 21859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_cis)); 2186a8116848SStefano Zampini if (b->sf != b->csf) { 21879566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->csf)); 21889566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->csf_rootdata,b->csf_leafdata)); 2189f03112d0SStefano Zampini } else b->csf = NULL; 21909566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->sf)); 21919566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->sf_rootdata,b->sf_leafdata)); 21929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->rmapping)); 21939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->cmapping)); 21949566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 21959566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A,NULL)); 21969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",NULL)); 21979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL)); 21989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL)); 21999566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL)); 22009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL)); 22019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL)); 22029566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL)); 22039566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalToGlobalMapping_C",NULL)); 22049566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL)); 22059566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL)); 22069566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL)); 22079566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL)); 22089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL)); 22099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL)); 22109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL)); 22119566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOOLocal_C",NULL)); 22129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",NULL)); 22139566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",NULL)); 2214b4319ba4SBarry Smith PetscFunctionReturn(0); 2215b4319ba4SBarry Smith } 2216b4319ba4SBarry Smith 2217a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y) 2218b4319ba4SBarry Smith { 2219b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 2220b4319ba4SBarry Smith PetscScalar zero = 0.0; 2221b4319ba4SBarry Smith 2222b4319ba4SBarry Smith PetscFunctionBegin; 2223b4319ba4SBarry Smith /* scatter the global vector x into the local work vector */ 22249566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD)); 22259566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD)); 2226b4319ba4SBarry Smith 2227b4319ba4SBarry Smith /* multiply the local matrix */ 22289566063dSJacob Faibussowitsch PetscCall(MatMult(is->A,is->x,is->y)); 2229b4319ba4SBarry Smith 2230b4319ba4SBarry Smith /* scatter product back into global memory */ 22319566063dSJacob Faibussowitsch PetscCall(VecSet(y,zero)); 22329566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE)); 22339566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE)); 2234b4319ba4SBarry Smith PetscFunctionReturn(0); 2235b4319ba4SBarry Smith } 2236b4319ba4SBarry Smith 2237a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 22382e74eeadSLisandro Dalcin { 2239650997f4SStefano Zampini Vec temp_vec; 22402e74eeadSLisandro Dalcin 22412e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 2242650997f4SStefano Zampini if (v3 != v2) { 22439566063dSJacob Faibussowitsch PetscCall(MatMult(A,v1,v3)); 22449566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3,1.0,v2)); 2245650997f4SStefano Zampini } else { 22469566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2,&temp_vec)); 22479566063dSJacob Faibussowitsch PetscCall(MatMult(A,v1,temp_vec)); 22489566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec,1.0,v2)); 22499566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec,v3)); 22509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2251650997f4SStefano Zampini } 22522e74eeadSLisandro Dalcin PetscFunctionReturn(0); 22532e74eeadSLisandro Dalcin } 22542e74eeadSLisandro Dalcin 2255a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x) 22562e74eeadSLisandro Dalcin { 22572e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 22582e74eeadSLisandro Dalcin 2259e176bc59SStefano Zampini PetscFunctionBegin; 22602e74eeadSLisandro Dalcin /* scatter the global vector x into the local work vector */ 22619566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD)); 22629566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD)); 22632e74eeadSLisandro Dalcin 22642e74eeadSLisandro Dalcin /* multiply the local matrix */ 22659566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(is->A,is->y,is->x)); 22662e74eeadSLisandro Dalcin 22672e74eeadSLisandro Dalcin /* scatter product back into global vector */ 22689566063dSJacob Faibussowitsch PetscCall(VecSet(x,0)); 22699566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE)); 22709566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE)); 22712e74eeadSLisandro Dalcin PetscFunctionReturn(0); 22722e74eeadSLisandro Dalcin } 22732e74eeadSLisandro Dalcin 2274a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 22752e74eeadSLisandro Dalcin { 2276650997f4SStefano Zampini Vec temp_vec; 22772e74eeadSLisandro Dalcin 22782e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 2279650997f4SStefano Zampini if (v3 != v2) { 22809566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A,v1,v3)); 22819566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3,1.0,v2)); 2282650997f4SStefano Zampini } else { 22839566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2,&temp_vec)); 22849566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A,v1,temp_vec)); 22859566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec,1.0,v2)); 22869566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec,v3)); 22879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2288650997f4SStefano Zampini } 22892e74eeadSLisandro Dalcin PetscFunctionReturn(0); 22902e74eeadSLisandro Dalcin } 22912e74eeadSLisandro Dalcin 2292a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer) 2293b4319ba4SBarry Smith { 2294b4319ba4SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 2295b4319ba4SBarry Smith PetscViewer sviewer; 2296ee2491ecSStefano Zampini PetscBool isascii,view = PETSC_TRUE; 2297b4319ba4SBarry Smith 2298b4319ba4SBarry Smith PetscFunctionBegin; 22999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii)); 2300ee2491ecSStefano Zampini if (isascii) { 2301ee2491ecSStefano Zampini PetscViewerFormat format; 2302ee2491ecSStefano Zampini 23039566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer,&format)); 2304ee2491ecSStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE; 2305ee2491ecSStefano Zampini } 2306ee2491ecSStefano Zampini if (!view) PetscFunctionReturn(0); 23079566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer)); 23089566063dSJacob Faibussowitsch PetscCall(MatView(a->A,sviewer)); 23099566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer)); 23109566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 2311b4319ba4SBarry Smith PetscFunctionReturn(0); 2312b4319ba4SBarry Smith } 2313b4319ba4SBarry Smith 2314b89f26deSStefano Zampini static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat,const PetscScalar **values) 2315b89f26deSStefano Zampini { 2316b89f26deSStefano Zampini Mat_IS *is = (Mat_IS*)mat->data; 2317b89f26deSStefano Zampini MPI_Datatype nodeType; 2318b89f26deSStefano Zampini const PetscScalar *lv; 2319b89f26deSStefano Zampini PetscInt bs; 2320b89f26deSStefano Zampini 2321b89f26deSStefano Zampini PetscFunctionBegin; 23229566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(mat,&bs)); 23239566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(is->A,bs)); 23249566063dSJacob Faibussowitsch PetscCall(MatInvertBlockDiagonal(is->A,&lv)); 2325b89f26deSStefano Zampini if (!is->bdiag) { 23269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bs*mat->rmap->n,&is->bdiag)); 2327b89f26deSStefano Zampini } 23289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(bs,MPIU_SCALAR,&nodeType)); 23299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType)); 23309566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(is->sf,nodeType,lv,is->bdiag,MPI_REPLACE)); 23319566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(is->sf,nodeType,lv,is->bdiag,MPI_REPLACE)); 23329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType)); 2333b89f26deSStefano Zampini if (values) *values = is->bdiag; 2334b89f26deSStefano Zampini PetscFunctionReturn(0); 2335b89f26deSStefano Zampini } 2336b89f26deSStefano Zampini 23378546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat A) 2338b4319ba4SBarry Smith { 2339e176bc59SStefano Zampini Vec cglobal,rglobal; 23408546b261SStefano Zampini IS from; 23418546b261SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 2342b89f26deSStefano Zampini PetscScalar sum; 23438546b261SStefano Zampini const PetscInt *garray; 23448546b261SStefano Zampini PetscInt nr,rbs,nc,cbs; 2345e432b41dSStefano Zampini VecType rtype; 2346b4319ba4SBarry Smith 2347b4319ba4SBarry Smith PetscFunctionBegin; 23489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping,&nr)); 23499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping,&rbs)); 23509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping,&nc)); 23519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping,&cbs)); 23529566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->x)); 23539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->y)); 23549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->counter)); 23559566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->rctx)); 23569566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->cctx)); 23579566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(is->A,&is->x,&is->y)); 23589566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y,PETSC_TRUE)); 23599566063dSJacob Faibussowitsch PetscCall(VecGetRootType_Private(is->y,&rtype)); 23609566063dSJacob Faibussowitsch PetscCall(PetscFree(A->defaultvectype)); 23619566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(rtype,&A->defaultvectype)); 23629566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A,&cglobal,&rglobal)); 23639566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(rglobal,PETSC_TRUE)); 23649566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping,&garray)); 23659566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from)); 23669566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(rglobal,from,is->y,NULL,&is->rctx)); 23679566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping,&garray)); 23689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 2369e432b41dSStefano Zampini if (is->rmapping != is->cmapping) { 23709566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping,&garray)); 23719566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from)); 23729566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cglobal,from,is->x,NULL,&is->cctx)); 23739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping,&garray)); 23749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 23758546b261SStefano Zampini } else { 23769566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rctx)); 23778546b261SStefano Zampini is->cctx = is->rctx; 23788546b261SStefano Zampini } 23799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobal)); 2380b89f26deSStefano Zampini 23818546b261SStefano Zampini /* interface counter vector (local) */ 23829566063dSJacob Faibussowitsch PetscCall(VecDuplicate(is->y,&is->counter)); 23839566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter,PETSC_TRUE)); 23849566063dSJacob Faibussowitsch PetscCall(VecSet(is->y,1.)); 23859566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE)); 23869566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE)); 23879566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD)); 23889566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD)); 23899566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y,PETSC_FALSE)); 23909566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter,PETSC_FALSE)); 2391b89f26deSStefano Zampini 2392b89f26deSStefano Zampini /* special functions for block-diagonal matrices */ 23939566063dSJacob Faibussowitsch PetscCall(VecSum(rglobal,&sum)); 2394b89f26deSStefano Zampini A->ops->invertblockdiagonal = NULL; 2395e432b41dSStefano Zampini if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && is->rmapping == is->cmapping) A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS; 23969566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rglobal)); 2397b0cc1f67SStefano Zampini 2398b0cc1f67SStefano Zampini /* setup SF for general purpose shared indices based communications */ 23999566063dSJacob Faibussowitsch PetscCall(MatISSetUpSF_IS(A)); 24008546b261SStefano Zampini PetscFunctionReturn(0); 24018546b261SStefano Zampini } 24028546b261SStefano Zampini 2403e432b41dSStefano Zampini static PetscErrorCode MatISFilterL2GMap(Mat A, ISLocalToGlobalMapping map, ISLocalToGlobalMapping *nmap, ISLocalToGlobalMapping *lmap) 2404e432b41dSStefano Zampini { 2405e432b41dSStefano Zampini IS is; 2406e432b41dSStefano Zampini ISLocalToGlobalMappingType l2gtype; 2407e432b41dSStefano Zampini const PetscInt *idxs; 2408e432b41dSStefano Zampini PetscHSetI ht; 2409e432b41dSStefano Zampini PetscInt *nidxs; 2410e432b41dSStefano Zampini PetscInt i,n,bs,c; 2411e432b41dSStefano Zampini PetscBool flg[] = {PETSC_FALSE,PETSC_FALSE}; 2412e432b41dSStefano Zampini 2413e432b41dSStefano Zampini PetscFunctionBegin; 24149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(map,&n)); 24159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(map,&bs)); 24169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(map,&idxs)); 24179566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 24189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n/bs,&nidxs)); 2419e432b41dSStefano Zampini for (i=0,c=0;i<n/bs;i++) { 2420e432b41dSStefano Zampini PetscBool missing; 2421e432b41dSStefano Zampini if (idxs[i] < 0) { flg[0] = PETSC_TRUE; continue; } 24229566063dSJacob Faibussowitsch PetscCall(PetscHSetIQueryAdd(ht,idxs[i],&missing)); 2423e432b41dSStefano Zampini if (!missing) flg[1] = PETSC_TRUE; 2424e432b41dSStefano Zampini else nidxs[c++] = idxs[i]; 2425e432b41dSStefano Zampini } 24269566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 24279566063dSJacob Faibussowitsch PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE,flg,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A))); 2428e432b41dSStefano Zampini if (!flg[0] && !flg[1]) { /* Entries are all non negative and unique */ 2429e432b41dSStefano Zampini *nmap = NULL; 2430e432b41dSStefano Zampini *lmap = NULL; 24319566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 24329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map,&idxs)); 2433e432b41dSStefano Zampini PetscFunctionReturn(0); 2434e432b41dSStefano Zampini } 2435e432b41dSStefano Zampini 2436e432b41dSStefano Zampini /* New l2g map without negative or repeated indices */ 24379566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),bs,c,nidxs,PETSC_USE_POINTER,&is)); 24389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,nmap)); 24399566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 24409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetType(map,&l2gtype)); 24419566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*nmap,l2gtype)); 2442e432b41dSStefano Zampini 2443e432b41dSStefano Zampini /* New local l2g map for repeated indices */ 24449566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(*nmap,IS_GTOLM_MASK,n/bs,idxs,NULL,nidxs)); 24459566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF,bs,n/bs,nidxs,PETSC_USE_POINTER,&is)); 24469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,lmap)); 24479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2448e432b41dSStefano Zampini 24499566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 24509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map,&idxs)); 2451e432b41dSStefano Zampini PetscFunctionReturn(0); 2452e432b41dSStefano Zampini } 2453e432b41dSStefano Zampini 24548546b261SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping) 24558546b261SStefano Zampini { 24568546b261SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 2457e432b41dSStefano Zampini ISLocalToGlobalMapping localrmapping = NULL, localcmapping = NULL; 2458e432b41dSStefano Zampini PetscBool cong, freem[] = { PETSC_FALSE, PETSC_FALSE }; 2459e432b41dSStefano Zampini PetscInt nr,rbs,nc,cbs; 24608546b261SStefano Zampini 24618546b261SStefano Zampini PetscFunctionBegin; 2462fc989267SStefano Zampini if (rmapping) PetscCheckSameComm(A,1,rmapping,2); 2463fc989267SStefano Zampini if (cmapping) PetscCheckSameComm(A,1,cmapping,3); 2464e432b41dSStefano Zampini 24659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->rmapping)); 24669566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 24679566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 24689566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 24699566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A,&cong)); 2470e432b41dSStefano Zampini 2471fc989267SStefano Zampini /* If NULL, local space matches global space */ 2472fc989267SStefano Zampini if (!rmapping) { 2473fc989267SStefano Zampini IS is; 2474fc989267SStefano Zampini 24759566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->N,0,1,&is)); 24769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&rmapping)); 24779566063dSJacob Faibussowitsch if (A->rmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(rmapping,A->rmap->bs)); 24789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2479e432b41dSStefano Zampini freem[0] = PETSC_TRUE; 2480e432b41dSStefano Zampini if (!cmapping && cong && A->rmap->bs == A->cmap->bs) cmapping = rmapping; 2481e432b41dSStefano Zampini } else if (!is->islocalref) { /* check if the l2g map has negative or repeated entries */ 24829566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A,rmapping,&is->rmapping,&localrmapping)); 2483e432b41dSStefano Zampini if (rmapping == cmapping) { 24849566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2485e432b41dSStefano Zampini is->cmapping = is->rmapping; 24869566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)localrmapping)); 2487e432b41dSStefano Zampini localcmapping = localrmapping; 2488fc989267SStefano Zampini } 2489fc989267SStefano Zampini } 2490fc989267SStefano Zampini if (!cmapping) { 2491fc989267SStefano Zampini IS is; 2492fc989267SStefano Zampini 24939566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->N,0,1,&is)); 24949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&cmapping)); 24959566063dSJacob Faibussowitsch if (A->cmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(cmapping,A->cmap->bs)); 24969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2497e432b41dSStefano Zampini freem[1] = PETSC_TRUE; 2498e432b41dSStefano Zampini } else if (cmapping != rmapping && !is->islocalref) { /* check if the l2g map has negative or repeated entries */ 24999566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A,cmapping,&is->cmapping,&localcmapping)); 2500e432b41dSStefano Zampini } 2501e432b41dSStefano Zampini if (!is->rmapping) { 25029566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rmapping)); 2503e432b41dSStefano Zampini is->rmapping = rmapping; 2504e432b41dSStefano Zampini } 2505e432b41dSStefano Zampini if (!is->cmapping) { 25069566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cmapping)); 2507e432b41dSStefano Zampini is->cmapping = cmapping; 2508fc989267SStefano Zampini } 2509fc989267SStefano Zampini 2510fc989267SStefano Zampini /* Clean up */ 25119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 2512872cf891SStefano Zampini if (is->csf != is->sf) { 25139566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->csf)); 25149566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->csf_rootdata,is->csf_leafdata)); 2515f03112d0SStefano Zampini } else is->csf = NULL; 25169566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->sf)); 25179566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->sf_rootdata,is->sf_leafdata)); 25189566063dSJacob Faibussowitsch PetscCall(PetscFree(is->bdiag)); 25193bbff08aSStefano Zampini 2520fc989267SStefano Zampini /* check if the two mappings are actually the same for square matrices since MATIS has some optimization for this case 2521fc989267SStefano Zampini (DOLFIN passes 2 different objects) */ 25229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping,&nr)); 25239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping,&rbs)); 25249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping,&nc)); 25259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping,&cbs)); 2526e432b41dSStefano Zampini if (is->rmapping != is->cmapping && cong) { 2527e432b41dSStefano Zampini PetscBool same = PETSC_FALSE; 25286625354bSStefano Zampini if (nr == nc && cbs == rbs) { 25296625354bSStefano Zampini const PetscInt *idxs1,*idxs2; 25306625354bSStefano Zampini 25319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping,&idxs1)); 25329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping,&idxs2)); 25339566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1,idxs2,nr/rbs,&same)); 25349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping,&idxs1)); 25359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping,&idxs2)); 25366625354bSStefano Zampini } 25379566063dSJacob Faibussowitsch PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE,&same,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A))); 2538e432b41dSStefano Zampini if (same) { 25399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 25409566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2541e432b41dSStefano Zampini is->cmapping = is->rmapping; 2542e432b41dSStefano Zampini } 25436625354bSStefano Zampini } 25449566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->rmap,rbs)); 25459566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->cmap,cbs)); 2546e432b41dSStefano Zampini /* Pass the user defined maps to the layout */ 25479566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping)); 25489566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping)); 25499566063dSJacob Faibussowitsch if (freem[0]) PetscCall(ISLocalToGlobalMappingDestroy(&rmapping)); 25509566063dSJacob Faibussowitsch if (freem[1]) PetscCall(ISLocalToGlobalMappingDestroy(&cmapping)); 25516625354bSStefano Zampini 25526625354bSStefano Zampini /* Create the local matrix A */ 25539566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF,&is->A)); 25549566063dSJacob Faibussowitsch PetscCall(MatSetType(is->A,is->lmattype)); 25559566063dSJacob Faibussowitsch PetscCall(MatSetSizes(is->A,nr,nc,nr,nc)); 25569566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(is->A,rbs,cbs)); 25579566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(is->A,"is_")); 25589566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(is->A,((PetscObject)A)->prefix)); 25599566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->rmap)); 25609566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->cmap)); 25619566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(is->A,localrmapping,localcmapping)); 25629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localrmapping)); 25639566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localcmapping)); 2564b4319ba4SBarry Smith 2565fc989267SStefano Zampini /* setup scatters and local vectors for MatMult */ 25669566063dSJacob Faibussowitsch if (!is->islocalref) PetscCall(MatISSetUpScatters_Private(A)); 2567fc989267SStefano Zampini A->preallocated = PETSC_TRUE; 2568fc989267SStefano Zampini PetscFunctionReturn(0); 2569fc989267SStefano Zampini } 2570fc989267SStefano Zampini 2571fc989267SStefano Zampini static PetscErrorCode MatSetUp_IS(Mat A) 2572fc989267SStefano Zampini { 2573fc989267SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 2574fc989267SStefano Zampini 2575fc989267SStefano Zampini PetscFunctionBegin; 25769566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A,&rmap,&cmap)); 2577fc989267SStefano Zampini if (!rmap && !cmap) { 25789566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(A,NULL,NULL)); 2579fc989267SStefano Zampini } 2580b4319ba4SBarry Smith PetscFunctionReturn(0); 2581b4319ba4SBarry Smith } 2582b4319ba4SBarry Smith 2583a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 25842e74eeadSLisandro Dalcin { 25852e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)mat->data; 2586f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 25872e74eeadSLisandro Dalcin 25882e74eeadSLisandro Dalcin PetscFunctionBegin; 25899566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->rmapping,IS_GTOLM_MASK,m,rows,&m,rows_l)); 2590e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 25919566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->cmapping,IS_GTOLM_MASK,n,cols,&n,cols_l)); 25929566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A,m,rows_l,n,cols_l,values,addv)); 2593e432b41dSStefano Zampini } else { 25949566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A,m,rows_l,m,rows_l,values,addv)); 2595e432b41dSStefano Zampini } 25962e74eeadSLisandro Dalcin PetscFunctionReturn(0); 25972e74eeadSLisandro Dalcin } 25982e74eeadSLisandro Dalcin 2599a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 260097563a80SStefano Zampini { 260197563a80SStefano Zampini Mat_IS *is = (Mat_IS*)mat->data; 2602f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 260397563a80SStefano Zampini 260497563a80SStefano Zampini PetscFunctionBegin; 26059566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(is->rmapping,IS_GTOLM_MASK,m,rows,&m,rows_l)); 2606e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 26079566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->cmapping,IS_GTOLM_MASK,n,cols,&n,cols_l)); 26089566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv)); 2609e432b41dSStefano Zampini } else { 26109566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A,m,rows_l,n,rows_l,values,addv)); 2611e432b41dSStefano Zampini } 261297563a80SStefano Zampini PetscFunctionReturn(0); 261397563a80SStefano Zampini } 261497563a80SStefano Zampini 2615a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 2616b4319ba4SBarry Smith { 2617b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 2618b4319ba4SBarry Smith 2619b4319ba4SBarry Smith PetscFunctionBegin; 2620e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 26219566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(is->A,m,rows,n,cols,values,addv)); 2622872cf891SStefano Zampini } else { 26239566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A,m,rows,n,cols,values,addv)); 2624872cf891SStefano Zampini } 2625b4319ba4SBarry Smith PetscFunctionReturn(0); 2626b4319ba4SBarry Smith } 2627b4319ba4SBarry Smith 2628a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 2629f0006bf2SLisandro Dalcin { 2630f0006bf2SLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 2631f0006bf2SLisandro Dalcin 2632f0006bf2SLisandro Dalcin PetscFunctionBegin; 2633e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 26349566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv)); 2635b4f971dfSStefano Zampini } else { 26369566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv)); 2637b4f971dfSStefano Zampini } 2638f0006bf2SLisandro Dalcin PetscFunctionReturn(0); 2639f0006bf2SLisandro Dalcin } 2640f0006bf2SLisandro Dalcin 2641f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns) 2642f0ae7da4SStefano Zampini { 2643f0ae7da4SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 2644f0ae7da4SStefano Zampini 2645f0ae7da4SStefano Zampini PetscFunctionBegin; 2646f0ae7da4SStefano Zampini if (!n) { 2647f0ae7da4SStefano Zampini is->pure_neumann = PETSC_TRUE; 2648f0ae7da4SStefano Zampini } else { 2649f0ae7da4SStefano Zampini PetscInt i; 2650f0ae7da4SStefano Zampini is->pure_neumann = PETSC_FALSE; 2651f0ae7da4SStefano Zampini 2652f0ae7da4SStefano Zampini if (columns) { 26539566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns(is->A,n,rows,diag,NULL,NULL)); 2654f0ae7da4SStefano Zampini } else { 26559566063dSJacob Faibussowitsch PetscCall(MatZeroRows(is->A,n,rows,diag,NULL,NULL)); 2656f0ae7da4SStefano Zampini } 2657f0ae7da4SStefano Zampini if (diag != 0.) { 2658f0ae7da4SStefano Zampini const PetscScalar *array; 26599566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(is->counter,&array)); 2660f0ae7da4SStefano Zampini for (i=0; i<n; i++) { 26619566063dSJacob Faibussowitsch PetscCall(MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES)); 2662f0ae7da4SStefano Zampini } 26639566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(is->counter,&array)); 2664f0ae7da4SStefano Zampini } 26659566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY)); 26669566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY)); 2667f0ae7da4SStefano Zampini } 2668f0ae7da4SStefano Zampini PetscFunctionReturn(0); 2669f0ae7da4SStefano Zampini } 2670f0ae7da4SStefano Zampini 2671f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns) 26722e74eeadSLisandro Dalcin { 26736e520ac8SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 26746e520ac8SStefano Zampini PetscInt nr,nl,len,i; 26756e520ac8SStefano Zampini PetscInt *lrows; 26762e74eeadSLisandro Dalcin 26772e74eeadSLisandro Dalcin PetscFunctionBegin; 2678cf9c20a2SJed Brown if (PetscUnlikelyDebug(columns || diag != 0. || (x && b))) { 2679f0ae7da4SStefano Zampini PetscBool cong; 268026b0207aSStefano Zampini 26819566063dSJacob Faibussowitsch PetscCall(PetscLayoutCompare(A->rmap,A->cmap,&cong)); 268226b0207aSStefano Zampini cong = (PetscBool)(cong && matis->sf == matis->csf); 26832c71b3e2SJacob Faibussowitsch PetscCheckFalse(!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"); 26842c71b3e2SJacob Faibussowitsch PetscCheckFalse(!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"); 26852c71b3e2SJacob Faibussowitsch PetscCheckFalse(!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"); 2686f0ae7da4SStefano Zampini } 26876e520ac8SStefano Zampini /* get locally owned rows */ 26889566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(A->rmap,n,rows,&len,&lrows,NULL)); 26896e520ac8SStefano Zampini /* fix right hand side if needed */ 26906e520ac8SStefano Zampini if (x && b) { 26916e520ac8SStefano Zampini const PetscScalar *xx; 26926e520ac8SStefano Zampini PetscScalar *bb; 26936e520ac8SStefano Zampini 26949566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 26959566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 26966e520ac8SStefano Zampini for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]]; 26979566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 26989566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 26992e74eeadSLisandro Dalcin } 27006e520ac8SStefano Zampini /* get rows associated to the local matrices */ 27019566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A,&nl,NULL)); 27029566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata,nl)); 27039566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata,A->rmap->n)); 27046e520ac8SStefano Zampini for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1; 27059566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 27069566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 27079566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 27089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl,&lrows)); 27096e520ac8SStefano Zampini for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i; 27109566063dSJacob Faibussowitsch PetscCall(MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns)); 27119566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 27122e74eeadSLisandro Dalcin PetscFunctionReturn(0); 27132e74eeadSLisandro Dalcin } 27142e74eeadSLisandro Dalcin 2715f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 2716b4319ba4SBarry Smith { 2717b4319ba4SBarry Smith PetscFunctionBegin; 27189566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE)); 2719f0ae7da4SStefano Zampini PetscFunctionReturn(0); 2720f0ae7da4SStefano Zampini } 27212205254eSKarl Rupp 2722f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 2723f0ae7da4SStefano Zampini { 2724f0ae7da4SStefano Zampini PetscFunctionBegin; 27259566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE)); 2726b4319ba4SBarry Smith PetscFunctionReturn(0); 2727b4319ba4SBarry Smith } 2728b4319ba4SBarry Smith 2729a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type) 2730b4319ba4SBarry Smith { 2731b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 2732b4319ba4SBarry Smith 2733b4319ba4SBarry Smith PetscFunctionBegin; 27349566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A,type)); 2735b4319ba4SBarry Smith PetscFunctionReturn(0); 2736b4319ba4SBarry Smith } 2737b4319ba4SBarry Smith 2738a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type) 2739b4319ba4SBarry Smith { 2740b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 2741b4319ba4SBarry Smith 2742b4319ba4SBarry Smith PetscFunctionBegin; 27439566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A,type)); 2744872cf891SStefano Zampini /* fix for local empty rows/cols */ 2745872cf891SStefano Zampini if (is->locempty && type == MAT_FINAL_ASSEMBLY) { 2746872cf891SStefano Zampini Mat newlA; 2747f03112d0SStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 2748f03112d0SStefano Zampini IS nzr,nzc; 2749f03112d0SStefano Zampini PetscInt nr,nc,nnzr,nnzc; 2750f03112d0SStefano Zampini PetscBool lnewl2g,newl2g; 2751872cf891SStefano Zampini 27529566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A,&nr,&nc)); 27539566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr)); 2754f03112d0SStefano Zampini if (!nzr) { 27559566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr)); 2756872cf891SStefano Zampini } 27579566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc)); 2758f03112d0SStefano Zampini if (!nzc) { 27599566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc)); 2760872cf891SStefano Zampini } 27619566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzr,&nnzr)); 27629566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzc,&nnzc)); 2763e432b41dSStefano Zampini if (nnzr != nr || nnzc != nc) { /* need new global l2g map */ 2764f03112d0SStefano Zampini lnewl2g = PETSC_TRUE; 27659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A))); 2766f03112d0SStefano Zampini 2767872cf891SStefano Zampini /* extract valid submatrix */ 27689566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA)); 2769f03112d0SStefano Zampini } else { /* local matrix fully populated */ 2770f03112d0SStefano Zampini lnewl2g = PETSC_FALSE; 27719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A))); 27729566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->A)); 2773f03112d0SStefano Zampini newlA = is->A; 2774f03112d0SStefano Zampini } 2775e432b41dSStefano Zampini 2776f03112d0SStefano Zampini /* attach new global l2g map if needed */ 2777f03112d0SStefano Zampini if (newl2g) { 2778e432b41dSStefano Zampini IS zr,zc; 2779e432b41dSStefano Zampini const PetscInt *ridxs,*cidxs,*zridxs,*zcidxs; 2780e432b41dSStefano Zampini PetscInt *nidxs,i; 2781f03112d0SStefano Zampini 27829566063dSJacob Faibussowitsch PetscCall(ISComplement(nzr,0,nr,&zr)); 27839566063dSJacob Faibussowitsch PetscCall(ISComplement(nzc,0,nc,&zc)); 27849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(nr,nc),&nidxs)); 27859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->rmapping,&ridxs)); 27869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->cmapping,&cidxs)); 27879566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zr,&zridxs)); 27889566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zc,&zcidxs)); 27899566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zr,&nnzr)); 27909566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zc,&nnzc)); 2791e432b41dSStefano Zampini 27929566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs,ridxs,nr)); 2793e432b41dSStefano Zampini for (i = 0; i < nnzr; i++) nidxs[zridxs[i]] = -1; 27949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nr,nidxs,PETSC_COPY_VALUES,&rl2g)); 27959566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs,cidxs,nc)); 2796e432b41dSStefano Zampini for (i = 0; i < nnzc; i++) nidxs[zcidxs[i]] = -1; 27979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nc,nidxs,PETSC_COPY_VALUES,&cl2g)); 2798e432b41dSStefano Zampini 27999566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zr,&zridxs)); 28009566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zc,&zcidxs)); 28019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->rmapping,&ridxs)); 28029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->cmapping,&cidxs)); 28039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 28049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 28059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zr)); 28069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zc)); 28079566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 28089566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(A,rl2g,cl2g)); 28099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 28109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 2811f03112d0SStefano Zampini } 28129566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(A,newlA)); 28139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlA)); 28149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 28159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 2816872cf891SStefano Zampini is->locempty = PETSC_FALSE; 2817f03112d0SStefano Zampini } 2818b4319ba4SBarry Smith PetscFunctionReturn(0); 2819b4319ba4SBarry Smith } 2820b4319ba4SBarry Smith 2821a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local) 2822b4319ba4SBarry Smith { 2823b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)mat->data; 2824b4319ba4SBarry Smith 2825b4319ba4SBarry Smith PetscFunctionBegin; 2826b4319ba4SBarry Smith *local = is->A; 2827b4319ba4SBarry Smith PetscFunctionReturn(0); 2828b4319ba4SBarry Smith } 2829b4319ba4SBarry Smith 28303b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local) 28313b3b1effSJed Brown { 28323b3b1effSJed Brown PetscFunctionBegin; 28333b3b1effSJed Brown *local = NULL; 28343b3b1effSJed Brown PetscFunctionReturn(0); 28353b3b1effSJed Brown } 28363b3b1effSJed Brown 2837b4319ba4SBarry Smith /*@ 2838b4319ba4SBarry Smith MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix. 2839b4319ba4SBarry Smith 2840b4319ba4SBarry Smith Input Parameter: 2841b4319ba4SBarry Smith . mat - the matrix 2842b4319ba4SBarry Smith 2843b4319ba4SBarry Smith Output Parameter: 2844eb82efa4SStefano Zampini . local - the local matrix 2845b4319ba4SBarry Smith 2846b4319ba4SBarry Smith Level: advanced 2847b4319ba4SBarry Smith 2848b4319ba4SBarry Smith Notes: 2849b4319ba4SBarry Smith This can be called if you have precomputed the nonzero structure of the 2850b4319ba4SBarry Smith matrix and want to provide it to the inner matrix object to improve the performance 2851b4319ba4SBarry Smith of the MatSetValues() operation. 2852b4319ba4SBarry Smith 28533b3b1effSJed Brown Call MatISRestoreLocalMat() when finished with the local matrix. 285496a6f129SJed Brown 2855b4319ba4SBarry Smith .seealso: MATIS 2856b4319ba4SBarry Smith @*/ 28577087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local) 2858b4319ba4SBarry Smith { 2859b4319ba4SBarry Smith PetscFunctionBegin; 28600700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2861b4319ba4SBarry Smith PetscValidPointer(local,2); 2862*cac4c232SBarry Smith PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local)); 2863b4319ba4SBarry Smith PetscFunctionReturn(0); 2864b4319ba4SBarry Smith } 2865b4319ba4SBarry Smith 28663b3b1effSJed Brown /*@ 28673b3b1effSJed Brown MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat() 28683b3b1effSJed Brown 28693b3b1effSJed Brown Input Parameter: 28703b3b1effSJed Brown . mat - the matrix 28713b3b1effSJed Brown 28723b3b1effSJed Brown Output Parameter: 28733b3b1effSJed Brown . local - the local matrix 28743b3b1effSJed Brown 28753b3b1effSJed Brown Level: advanced 28763b3b1effSJed Brown 28773b3b1effSJed Brown .seealso: MATIS 28783b3b1effSJed Brown @*/ 28793b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local) 28803b3b1effSJed Brown { 28813b3b1effSJed Brown PetscFunctionBegin; 28823b3b1effSJed Brown PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 28833b3b1effSJed Brown PetscValidPointer(local,2); 2884*cac4c232SBarry Smith PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local)); 28853b3b1effSJed Brown PetscFunctionReturn(0); 28863b3b1effSJed Brown } 28873b3b1effSJed Brown 28888546b261SStefano Zampini static PetscErrorCode MatISSetLocalMatType_IS(Mat mat,MatType mtype) 28898546b261SStefano Zampini { 28908546b261SStefano Zampini Mat_IS *is = (Mat_IS*)mat->data; 28918546b261SStefano Zampini 28928546b261SStefano Zampini PetscFunctionBegin; 28938546b261SStefano Zampini if (is->A) { 28949566063dSJacob Faibussowitsch PetscCall(MatSetType(is->A,mtype)); 28958546b261SStefano Zampini } 28969566063dSJacob Faibussowitsch PetscCall(PetscFree(is->lmattype)); 28979566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(mtype,&is->lmattype)); 28988546b261SStefano Zampini PetscFunctionReturn(0); 28998546b261SStefano Zampini } 29008546b261SStefano Zampini 29018546b261SStefano Zampini /*@ 29028546b261SStefano Zampini MatISSetLocalMatType - Specifies the type of local matrix 29038546b261SStefano Zampini 2904d8d19677SJose E. Roman Input Parameters: 2905a2b725a8SWilliam Gropp + mat - the matrix 2906a2b725a8SWilliam Gropp - mtype - the local matrix type 29078546b261SStefano Zampini 29088546b261SStefano Zampini Output Parameter: 29098546b261SStefano Zampini 29108546b261SStefano Zampini Level: advanced 29118546b261SStefano Zampini 29128546b261SStefano Zampini .seealso: MATIS, MatSetType(), MatType 29138546b261SStefano Zampini @*/ 29148546b261SStefano Zampini PetscErrorCode MatISSetLocalMatType(Mat mat,MatType mtype) 29158546b261SStefano Zampini { 29168546b261SStefano Zampini PetscFunctionBegin; 29178546b261SStefano Zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2918*cac4c232SBarry Smith PetscUseMethod(mat,"MatISSetLocalMatType_C",(Mat,MatType),(mat,mtype)); 29198546b261SStefano Zampini PetscFunctionReturn(0); 29208546b261SStefano Zampini } 29218546b261SStefano Zampini 2922a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local) 29233b03a366Sstefano_zampini { 29243b03a366Sstefano_zampini Mat_IS *is = (Mat_IS*)mat->data; 29253b03a366Sstefano_zampini PetscInt nrows,ncols,orows,ocols; 29268546b261SStefano Zampini MatType mtype,otype; 29278546b261SStefano Zampini PetscBool sametype = PETSC_TRUE; 29283b03a366Sstefano_zampini 29293b03a366Sstefano_zampini PetscFunctionBegin; 2930e432b41dSStefano Zampini if (is->A && !is->islocalref) { 29319566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A,&orows,&ocols)); 29329566063dSJacob Faibussowitsch PetscCall(MatGetSize(local,&nrows,&ncols)); 29332c71b3e2SJacob Faibussowitsch PetscCheckFalse(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); 29349566063dSJacob Faibussowitsch PetscCall(MatGetType(local,&mtype)); 29359566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A,&otype)); 29369566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype,otype,&sametype)); 29374e4c7dbeSStefano Zampini } 29389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)local)); 29399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 29403b03a366Sstefano_zampini is->A = local; 29419566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A,&mtype)); 29429566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(mat,mtype)); 29438546b261SStefano Zampini if (!sametype && !is->islocalref) { 29449566063dSJacob Faibussowitsch PetscCall(MatISSetUpScatters_Private(mat)); 29458546b261SStefano Zampini } 29463b03a366Sstefano_zampini PetscFunctionReturn(0); 29473b03a366Sstefano_zampini } 29483b03a366Sstefano_zampini 29493b03a366Sstefano_zampini /*@ 2950eb82efa4SStefano Zampini MatISSetLocalMat - Replace the local matrix stored inside a MATIS object. 29513b03a366Sstefano_zampini 29528546b261SStefano Zampini Collective on Mat 29538546b261SStefano Zampini 2954d8d19677SJose E. Roman Input Parameters: 2955a2b725a8SWilliam Gropp + mat - the matrix 2956a2b725a8SWilliam Gropp - local - the local matrix 29573b03a366Sstefano_zampini 29583b03a366Sstefano_zampini Output Parameter: 29593b03a366Sstefano_zampini 29603b03a366Sstefano_zampini Level: advanced 29613b03a366Sstefano_zampini 29623b03a366Sstefano_zampini Notes: 29633b03a366Sstefano_zampini This can be called if you have precomputed the local matrix and 29643b03a366Sstefano_zampini want to provide it to the matrix object MATIS. 29653b03a366Sstefano_zampini 29663b03a366Sstefano_zampini .seealso: MATIS 29673b03a366Sstefano_zampini @*/ 29683b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local) 29693b03a366Sstefano_zampini { 29703b03a366Sstefano_zampini PetscFunctionBegin; 29713b03a366Sstefano_zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2972b7ce53b6SStefano Zampini PetscValidHeaderSpecific(local,MAT_CLASSID,2); 2973*cac4c232SBarry Smith PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local)); 29743b03a366Sstefano_zampini PetscFunctionReturn(0); 29753b03a366Sstefano_zampini } 29763b03a366Sstefano_zampini 2977a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A) 29786726f965SBarry Smith { 29796726f965SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 29806726f965SBarry Smith 29816726f965SBarry Smith PetscFunctionBegin; 29829566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(a->A)); 29836726f965SBarry Smith PetscFunctionReturn(0); 29846726f965SBarry Smith } 29856726f965SBarry Smith 2986a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a) 29872e74eeadSLisandro Dalcin { 29882e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 29892e74eeadSLisandro Dalcin 29902e74eeadSLisandro Dalcin PetscFunctionBegin; 29919566063dSJacob Faibussowitsch PetscCall(MatScale(is->A,a)); 29922e74eeadSLisandro Dalcin PetscFunctionReturn(0); 29932e74eeadSLisandro Dalcin } 29942e74eeadSLisandro Dalcin 2995a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 29962e74eeadSLisandro Dalcin { 29972e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 29982e74eeadSLisandro Dalcin 29992e74eeadSLisandro Dalcin PetscFunctionBegin; 30002e74eeadSLisandro Dalcin /* get diagonal of the local matrix */ 30019566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(is->A,is->y)); 30022e74eeadSLisandro Dalcin 30032e74eeadSLisandro Dalcin /* scatter diagonal back into global vector */ 30049566063dSJacob Faibussowitsch PetscCall(VecSet(v,0)); 30059566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE)); 30069566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE)); 30072e74eeadSLisandro Dalcin PetscFunctionReturn(0); 30082e74eeadSLisandro Dalcin } 30092e74eeadSLisandro Dalcin 3010a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg) 30116726f965SBarry Smith { 30126726f965SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 30136726f965SBarry Smith 30146726f965SBarry Smith PetscFunctionBegin; 30159566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A,op,flg)); 30166726f965SBarry Smith PetscFunctionReturn(0); 30176726f965SBarry Smith } 30186726f965SBarry Smith 3019f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str) 3020f26d0771SStefano Zampini { 3021f26d0771SStefano Zampini Mat_IS *y = (Mat_IS*)Y->data; 3022f26d0771SStefano Zampini Mat_IS *x; 3023f26d0771SStefano Zampini 3024f26d0771SStefano Zampini PetscFunctionBegin; 302576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 302676bd3646SJed Brown PetscBool ismatis; 30279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis)); 302828b400f6SJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 302976bd3646SJed Brown } 3030f26d0771SStefano Zampini x = (Mat_IS*)X->data; 30319566063dSJacob Faibussowitsch PetscCall(MatAXPY(y->A,a,x->A,str)); 3032f26d0771SStefano Zampini PetscFunctionReturn(0); 3033f26d0771SStefano Zampini } 3034f26d0771SStefano Zampini 3035f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat) 3036f26d0771SStefano Zampini { 3037f26d0771SStefano Zampini Mat lA; 3038e432b41dSStefano Zampini Mat_IS *matis = (Mat_IS*)(A->data); 3039f26d0771SStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 3040f26d0771SStefano Zampini IS is; 3041f26d0771SStefano Zampini const PetscInt *rg,*rl; 3042f26d0771SStefano Zampini PetscInt nrg; 3043f26d0771SStefano Zampini PetscInt N,M,nrl,i,*idxs; 3044f26d0771SStefano Zampini 3045f26d0771SStefano Zampini PetscFunctionBegin; 30469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg)); 30479566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(row,&nrl)); 30489566063dSJacob Faibussowitsch PetscCall(ISGetIndices(row,&rl)); 30499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg)); 305076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 30512c71b3e2SJacob Faibussowitsch for (i=0; i<nrl; i++) PetscCheckFalse(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); 305276bd3646SJed Brown } 30539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrg,&idxs)); 3054f26d0771SStefano Zampini /* map from [0,nrl) to row */ 3055f26d0771SStefano Zampini for (i=0;i<nrl;i++) idxs[i] = rl[i]; 3056f26d0771SStefano Zampini for (i=nrl;i<nrg;i++) idxs[i] = -1; 30579566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(row,&rl)); 30589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg)); 30599566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is)); 30609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g)); 30619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3062f26d0771SStefano Zampini /* compute new l2g map for columns */ 3063e432b41dSStefano Zampini if (col != row || matis->rmapping != matis->cmapping || matis->A->rmap->mapping != matis->A->cmap->mapping) { 3064f26d0771SStefano Zampini const PetscInt *cg,*cl; 3065f26d0771SStefano Zampini PetscInt ncg; 3066f26d0771SStefano Zampini PetscInt ncl; 3067f26d0771SStefano Zampini 30689566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg)); 30699566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(col,&ncl)); 30709566063dSJacob Faibussowitsch PetscCall(ISGetIndices(col,&cl)); 30719566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg)); 307276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 30732c71b3e2SJacob Faibussowitsch for (i=0; i<ncl; i++) PetscCheckFalse(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); 307476bd3646SJed Brown } 30759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncg,&idxs)); 3076f26d0771SStefano Zampini /* map from [0,ncl) to col */ 3077f26d0771SStefano Zampini for (i=0;i<ncl;i++) idxs[i] = cl[i]; 3078f26d0771SStefano Zampini for (i=ncl;i<ncg;i++) idxs[i] = -1; 30799566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(col,&cl)); 30809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg)); 30819566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is)); 30829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g)); 30839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3084f26d0771SStefano Zampini } else { 30859566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rl2g)); 3086f26d0771SStefano Zampini cl2g = rl2g; 3087f26d0771SStefano Zampini } 3088f26d0771SStefano Zampini /* create the MATIS submatrix */ 30899566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&M,&N)); 30909566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),submat)); 30919566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N)); 30929566063dSJacob Faibussowitsch PetscCall(MatSetType(*submat,MATIS)); 3093b0aa3428SStefano Zampini matis = (Mat_IS*)((*submat)->data); 3094f26d0771SStefano Zampini matis->islocalref = PETSC_TRUE; 30959566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*submat,rl2g,cl2g)); 30969566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A,&lA)); 30979566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*submat,lA)); 30989566063dSJacob Faibussowitsch PetscCall(MatSetUp(*submat)); 30999566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY)); 31009566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY)); 31019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 31029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3103e432b41dSStefano Zampini 3104f26d0771SStefano Zampini /* remove unsupported ops */ 31059566063dSJacob Faibussowitsch PetscCall(PetscMemzero((*submat)->ops,sizeof(struct _MatOps))); 3106f26d0771SStefano Zampini (*submat)->ops->destroy = MatDestroy_IS; 3107f26d0771SStefano Zampini (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 3108f26d0771SStefano Zampini (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 3109f26d0771SStefano Zampini (*submat)->ops->assemblybegin = MatAssemblyBegin_IS; 3110f26d0771SStefano Zampini (*submat)->ops->assemblyend = MatAssemblyEnd_IS; 3111f26d0771SStefano Zampini PetscFunctionReturn(0); 3112f26d0771SStefano Zampini } 3113f26d0771SStefano Zampini 3114872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A) 3115872cf891SStefano Zampini { 3116872cf891SStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 31178546b261SStefano Zampini char type[256]; 31188546b261SStefano Zampini PetscBool flg; 3119872cf891SStefano Zampini 3120872cf891SStefano Zampini PetscFunctionBegin; 31219566063dSJacob Faibussowitsch PetscCall(PetscOptionsHead(PetscOptionsObject,"MATIS options")); 31229566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL)); 31239566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL)); 31249566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-matis_localmat_type","Matrix type","MatISSetLocalMatType",MatList,a->lmattype,type,256,&flg)); 31258546b261SStefano Zampini if (flg) { 31269566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(A,type)); 31278546b261SStefano Zampini } 31288546b261SStefano Zampini if (a->A) { 31299566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(a->A)); 31308546b261SStefano Zampini } 31319566063dSJacob Faibussowitsch PetscCall(PetscOptionsTail()); 3132872cf891SStefano Zampini PetscFunctionReturn(0); 3133872cf891SStefano Zampini } 3134872cf891SStefano Zampini 3135284134d9SBarry Smith /*@ 31363c212e90SHong Zhang MatCreateIS - Creates a "process" unassembled matrix, assembled on each 3137284134d9SBarry Smith process but not across processes. 3138284134d9SBarry Smith 3139284134d9SBarry Smith Input Parameters: 3140284134d9SBarry Smith + comm - MPI communicator that will share the matrix 3141e176bc59SStefano Zampini . bs - block size of the matrix 3142df3898eeSBarry Smith . m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products 3143e176bc59SStefano Zampini . rmap - local to global map for rows 3144e176bc59SStefano Zampini - cmap - local to global map for cols 3145284134d9SBarry Smith 3146284134d9SBarry Smith Output Parameter: 3147284134d9SBarry Smith . A - the resulting matrix 3148284134d9SBarry Smith 31498e6c10adSSatish Balay Level: advanced 31508e6c10adSSatish Balay 315195452b02SPatrick Sanan Notes: 315295452b02SPatrick Sanan See MATIS for more details. 3153fc989267SStefano 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 31546fdf41d1SStefano Zampini used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices. 3155fc989267SStefano Zampini If rmap (cmap) is NULL, then the local row (column) spaces matches the global space. 3156284134d9SBarry Smith 3157284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping() 3158284134d9SBarry Smith @*/ 3159e176bc59SStefano Zampini PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A) 3160284134d9SBarry Smith { 3161284134d9SBarry Smith PetscFunctionBegin; 31629566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,A)); 31639566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A,m,n,M,N)); 31646fdf41d1SStefano Zampini if (bs > 0) { 31659566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*A,bs)); 31666fdf41d1SStefano Zampini } 31679566063dSJacob Faibussowitsch PetscCall(MatSetType(*A,MATIS)); 31689566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*A,rmap,cmap)); 3169284134d9SBarry Smith PetscFunctionReturn(0); 3170284134d9SBarry Smith } 3171284134d9SBarry Smith 31728b9382cfSStefano Zampini static PetscErrorCode MatHasOperation_IS(Mat A, MatOperation op, PetscBool *has) 31738b9382cfSStefano Zampini { 31748b9382cfSStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 31758b9382cfSStefano Zampini 31768b9382cfSStefano Zampini PetscFunctionBegin; 31778b9382cfSStefano Zampini *has = PETSC_FALSE; 31788b9382cfSStefano Zampini if (!((void**)A->ops)[op]) PetscFunctionReturn(0); 31799566063dSJacob Faibussowitsch PetscCall(MatHasOperation(a->A,op,has)); 31808b9382cfSStefano Zampini PetscFunctionReturn(0); 31818b9382cfSStefano Zampini } 31828b9382cfSStefano Zampini 3183e432b41dSStefano Zampini static PetscErrorCode MatSetValuesCOO_IS(Mat A,const PetscScalar v[],InsertMode imode) 3184e432b41dSStefano Zampini { 3185e432b41dSStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3186e432b41dSStefano Zampini 3187e432b41dSStefano Zampini PetscFunctionBegin; 31889566063dSJacob Faibussowitsch PetscCall(MatSetValuesCOO(a->A,v,imode)); 31899566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY)); 31909566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY)); 3191e432b41dSStefano Zampini PetscFunctionReturn(0); 3192e432b41dSStefano Zampini } 3193e432b41dSStefano Zampini 3194e432b41dSStefano Zampini static PetscErrorCode MatSetPreallocationCOOLocal_IS(Mat A,PetscCount ncoo,PetscInt coo_i[],PetscInt coo_j[]) 3195e432b41dSStefano Zampini { 3196e432b41dSStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3197e432b41dSStefano Zampini 3198e432b41dSStefano Zampini PetscFunctionBegin; 3199e432b41dSStefano Zampini PetscCheck(a->A,PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3200e432b41dSStefano Zampini if (a->A->rmap->mapping || a->A->cmap->mapping) { 32019566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOOLocal(a->A,ncoo,coo_i,coo_j)); 3202e432b41dSStefano Zampini } else { 32039566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOO(a->A,ncoo,coo_i,coo_j)); 3204e432b41dSStefano Zampini } 32059566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",MatSetValuesCOO_IS)); 3206e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 3207e432b41dSStefano Zampini PetscFunctionReturn(0); 3208e432b41dSStefano Zampini } 3209e432b41dSStefano Zampini 3210e432b41dSStefano Zampini static PetscErrorCode MatSetPreallocationCOO_IS(Mat A,PetscCount ncoo,const PetscInt coo_i[],const PetscInt coo_j[]) 3211e432b41dSStefano Zampini { 3212e432b41dSStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3213e432b41dSStefano Zampini PetscInt *coo_il, *coo_jl, incoo; 3214e432b41dSStefano Zampini 3215e432b41dSStefano Zampini PetscFunctionBegin; 3216e432b41dSStefano Zampini PetscCheck(a->A,PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3217e432b41dSStefano 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); 32189566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(ncoo,&coo_il,ncoo,&coo_jl)); 32199566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(a->rmapping,IS_GTOLM_MASK,ncoo,coo_i,&incoo,coo_il)); 32209566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(a->cmapping,IS_GTOLM_MASK,ncoo,coo_j,&incoo,coo_jl)); 32219566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOO(a->A,ncoo,coo_il,coo_jl)); 32229566063dSJacob Faibussowitsch PetscCall(PetscFree2(coo_il,coo_jl)); 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 /*@ 3229e432b41dSStefano Zampini MatISGetLocalToGlobalMapping - Gets the local-to-global numbering of the MATIS object 3230e432b41dSStefano Zampini 3231e432b41dSStefano Zampini Not Collective 3232e432b41dSStefano Zampini 3233e432b41dSStefano Zampini Input Parameter: 3234e432b41dSStefano Zampini . A - the matrix 3235e432b41dSStefano Zampini 3236e432b41dSStefano Zampini Output Parameters: 3237e432b41dSStefano Zampini + rmapping - row mapping 3238e432b41dSStefano Zampini - cmapping - column mapping 3239e432b41dSStefano Zampini 3240e432b41dSStefano 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. 3241e432b41dSStefano Zampini 3242e432b41dSStefano Zampini Level: advanced 3243e432b41dSStefano Zampini 3244e432b41dSStefano Zampini .seealso: MatSetLocalToGlobalMapping() 3245e432b41dSStefano Zampini @*/ 3246e432b41dSStefano Zampini PetscErrorCode MatISGetLocalToGlobalMapping(Mat A,ISLocalToGlobalMapping *rmapping,ISLocalToGlobalMapping *cmapping) 3247e432b41dSStefano Zampini { 3248e432b41dSStefano Zampini PetscFunctionBegin; 3249e432b41dSStefano Zampini PetscValidHeaderSpecific(A,MAT_CLASSID,1); 3250e432b41dSStefano Zampini PetscValidType(A,1); 3251e432b41dSStefano Zampini if (rmapping) PetscValidPointer(rmapping,2); 3252e432b41dSStefano Zampini if (cmapping) PetscValidPointer(cmapping,3); 3253*cac4c232SBarry Smith PetscUseMethod(A,"MatISGetLocalToGlobalMapping_C",(Mat,ISLocalToGlobalMapping*,ISLocalToGlobalMapping*),(A,rmapping,cmapping)); 3254e432b41dSStefano Zampini PetscFunctionReturn(0); 3255e432b41dSStefano Zampini } 3256e432b41dSStefano Zampini 3257e432b41dSStefano Zampini static PetscErrorCode MatISGetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping *r, ISLocalToGlobalMapping *c) 3258e432b41dSStefano Zampini { 3259e432b41dSStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3260e432b41dSStefano Zampini 3261e432b41dSStefano Zampini PetscFunctionBegin; 3262e432b41dSStefano Zampini if (r) *r = a->rmapping; 3263e432b41dSStefano Zampini if (c) *c = a->cmapping; 3264e432b41dSStefano Zampini PetscFunctionReturn(0); 3265e432b41dSStefano Zampini } 3266e432b41dSStefano Zampini 3267b4319ba4SBarry Smith /*MC 3268f26d0771SStefano Zampini MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP). 3269b89f26deSStefano Zampini This stores the matrices in globally unassembled form. Each processor assembles only its local Neumann problem and the parallel matrix vector 3270b4319ba4SBarry Smith product is handled "implicitly". 3271b4319ba4SBarry Smith 3272b4319ba4SBarry Smith Options Database Keys: 327375d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions() 327475d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns. 327575d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP(). 3276b4319ba4SBarry Smith 327795452b02SPatrick Sanan Notes: 327895452b02SPatrick Sanan Options prefix for the inner matrix are given by -is_mat_xxx 3279b4319ba4SBarry Smith 3280b4319ba4SBarry Smith You must call MatSetLocalToGlobalMapping() before using this matrix type. 3281b4319ba4SBarry Smith 3282b4319ba4SBarry Smith You can do matrix preallocation on the local matrix after you obtain it with 3283eb82efa4SStefano Zampini MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation() 3284b4319ba4SBarry Smith 3285b4319ba4SBarry Smith Level: advanced 3286b4319ba4SBarry Smith 3287f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP 3288b4319ba4SBarry Smith 3289b4319ba4SBarry Smith M*/ 32908cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 3291b4319ba4SBarry Smith { 3292e432b41dSStefano Zampini Mat_IS *a; 3293b4319ba4SBarry Smith 3294b4319ba4SBarry Smith PetscFunctionBegin; 32959566063dSJacob Faibussowitsch PetscCall(PetscNewLog(A,&a)); 32969566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATAIJ,&a->lmattype)); 3297e432b41dSStefano Zampini A->data = (void*)a; 3298b4319ba4SBarry Smith 3299e176bc59SStefano Zampini /* matrix ops */ 33009566063dSJacob Faibussowitsch PetscCall(PetscMemzero(A->ops,sizeof(struct _MatOps))); 3301b4319ba4SBarry Smith A->ops->mult = MatMult_IS; 33022e74eeadSLisandro Dalcin A->ops->multadd = MatMultAdd_IS; 33032e74eeadSLisandro Dalcin A->ops->multtranspose = MatMultTranspose_IS; 33042e74eeadSLisandro Dalcin A->ops->multtransposeadd = MatMultTransposeAdd_IS; 3305b4319ba4SBarry Smith A->ops->destroy = MatDestroy_IS; 3306b4319ba4SBarry Smith A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 33072e74eeadSLisandro Dalcin A->ops->setvalues = MatSetValues_IS; 330898921651SStefano Zampini A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 3309b4319ba4SBarry Smith A->ops->setvalueslocal = MatSetValuesLocal_IS; 3310f0006bf2SLisandro Dalcin A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 33112e74eeadSLisandro Dalcin A->ops->zerorows = MatZeroRows_IS; 3312f0ae7da4SStefano Zampini A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 3313b4319ba4SBarry Smith A->ops->assemblybegin = MatAssemblyBegin_IS; 3314b4319ba4SBarry Smith A->ops->assemblyend = MatAssemblyEnd_IS; 3315b4319ba4SBarry Smith A->ops->view = MatView_IS; 33166726f965SBarry Smith A->ops->zeroentries = MatZeroEntries_IS; 33172e74eeadSLisandro Dalcin A->ops->scale = MatScale_IS; 33182e74eeadSLisandro Dalcin A->ops->getdiagonal = MatGetDiagonal_IS; 33196726f965SBarry Smith A->ops->setoption = MatSetOption_IS; 332069796d55SStefano Zampini A->ops->ishermitian = MatIsHermitian_IS; 332169796d55SStefano Zampini A->ops->issymmetric = MatIsSymmetric_IS; 332245471136SStefano Zampini A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS; 3323ad6194a2SStefano Zampini A->ops->duplicate = MatDuplicate_IS; 33246bd84002SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_IS; 33252b404112SStefano Zampini A->ops->copy = MatCopy_IS; 3326659959c5SStefano Zampini A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 33277dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_IS; 3328f26d0771SStefano Zampini A->ops->axpy = MatAXPY_IS; 33293fd1c9e7SStefano Zampini A->ops->diagonalset = MatDiagonalSet_IS; 33303fd1c9e7SStefano Zampini A->ops->shift = MatShift_IS; 3331d7f69cd0SStefano Zampini A->ops->transpose = MatTranspose_IS; 33327fa8f2d3SStefano Zampini A->ops->getinfo = MatGetInfo_IS; 3333ad219c80Sstefano_zampini A->ops->diagonalscale = MatDiagonalScale_IS; 3334872cf891SStefano Zampini A->ops->setfromoptions = MatSetFromOptions_IS; 3335fc989267SStefano Zampini A->ops->setup = MatSetUp_IS; 33368b9382cfSStefano Zampini A->ops->hasoperation = MatHasOperation_IS; 3337b4319ba4SBarry Smith 3338b7ce53b6SStefano Zampini /* special MATIS functions */ 33399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",MatISSetLocalMatType_IS)); 33409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS)); 33419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS)); 33429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS)); 33439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ)); 33449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS)); 33459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS)); 33469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS)); 33479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalToGlobalMapping_C",MatISGetLocalToGlobalMapping_IS)); 33489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ)); 33499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ)); 33509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ)); 33519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ)); 33529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ)); 33539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ)); 33549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ)); 33559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOOLocal_C",MatSetPreallocationCOOLocal_IS)); 33569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",MatSetPreallocationCOO_IS)); 33579566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A,MATIS)); 3358b4319ba4SBarry Smith PetscFunctionReturn(0); 3359b4319ba4SBarry Smith } 3360