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*/ 116989cf23SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h> 124f2d7cafSStefano Zampini #include <petsc/private/sfimpl.h> 1328f4e0baSStefano Zampini 14f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048 15b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode); 16b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode); 17f26d0771SStefano Zampini 185b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr) 195b003df0Sstefano_zampini { 205b003df0Sstefano_zampini MatISLocalFields lf = (MatISLocalFields)ptr; 215b003df0Sstefano_zampini PetscInt i; 225b003df0Sstefano_zampini PetscErrorCode ierr; 235b003df0Sstefano_zampini 24ab4d48faSStefano Zampini PetscFunctionBegin; 255b003df0Sstefano_zampini for (i=0;i<lf->nr;i++) { 265b003df0Sstefano_zampini ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr); 275b003df0Sstefano_zampini } 285b003df0Sstefano_zampini for (i=0;i<lf->nc;i++) { 295b003df0Sstefano_zampini ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr); 305b003df0Sstefano_zampini } 315b003df0Sstefano_zampini ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr); 325b003df0Sstefano_zampini ierr = PetscFree(lf);CHKERRQ(ierr); 335b003df0Sstefano_zampini PetscFunctionReturn(0); 345b003df0Sstefano_zampini } 35a72627d2SStefano Zampini 365b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyArray_Private(void *ptr) 377fa8f2d3SStefano Zampini { 386989cf23SStefano Zampini PetscErrorCode ierr; 396989cf23SStefano Zampini 406989cf23SStefano Zampini PetscFunctionBeginUser; 416989cf23SStefano Zampini ierr = PetscFree(ptr);CHKERRQ(ierr); 426989cf23SStefano Zampini PetscFunctionReturn(0); 436989cf23SStefano Zampini } 446989cf23SStefano Zampini 456989cf23SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat) 466989cf23SStefano Zampini { 476989cf23SStefano Zampini Mat_MPIAIJ *aij = (Mat_MPIAIJ*)A->data; 486989cf23SStefano Zampini Mat_SeqAIJ *diag = (Mat_SeqAIJ*)(aij->A->data); 496989cf23SStefano Zampini Mat_SeqAIJ *offd = (Mat_SeqAIJ*)(aij->B->data); 506989cf23SStefano Zampini Mat lA; 516989cf23SStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 526989cf23SStefano Zampini IS is; 536989cf23SStefano Zampini MPI_Comm comm; 546989cf23SStefano Zampini void *ptrs[2]; 556989cf23SStefano Zampini const char *names[2] = {"_convert_csr_aux","_convert_csr_data"}; 566989cf23SStefano Zampini PetscScalar *dd,*od,*aa,*data; 576989cf23SStefano Zampini PetscInt *di,*dj,*oi,*oj; 586989cf23SStefano Zampini PetscInt *aux,*ii,*jj; 59e363d98aSStefano Zampini PetscInt lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum; 606989cf23SStefano Zampini PetscErrorCode ierr; 616989cf23SStefano Zampini 62ab4d48faSStefano Zampini PetscFunctionBegin; 636989cf23SStefano Zampini ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 646989cf23SStefano Zampini if (!aij->garray) SETERRQ(comm,PETSC_ERR_SUP,"garray not present"); 656989cf23SStefano Zampini 666989cf23SStefano Zampini /* access relevant information from MPIAIJ */ 676989cf23SStefano Zampini ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr); 686989cf23SStefano Zampini ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr); 696989cf23SStefano Zampini ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr); 706989cf23SStefano Zampini di = diag->i; 716989cf23SStefano Zampini dj = diag->j; 726989cf23SStefano Zampini dd = diag->a; 736989cf23SStefano Zampini oc = aij->B->cmap->n; 746989cf23SStefano Zampini oi = offd->i; 756989cf23SStefano Zampini oj = offd->j; 766989cf23SStefano Zampini od = offd->a; 776989cf23SStefano Zampini nnz = diag->i[dr] + offd->i[dr]; 786989cf23SStefano Zampini 796989cf23SStefano Zampini /* generate l2g maps for rows and cols */ 806989cf23SStefano Zampini ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr); 816989cf23SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 826989cf23SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 83e363d98aSStefano Zampini if (dr) { 846989cf23SStefano Zampini ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr); 856989cf23SStefano Zampini for (i=0; i<dc; i++) aux[i] = i+stc; 866989cf23SStefano Zampini for (i=0; i<oc; i++) aux[i+dc] = aij->garray[i]; 876989cf23SStefano Zampini ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 88e363d98aSStefano Zampini lc = dc+oc; 89e363d98aSStefano Zampini } else { 90e363d98aSStefano Zampini ierr = ISCreateGeneral(comm,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 91e363d98aSStefano Zampini lc = 0; 92e363d98aSStefano Zampini } 936989cf23SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 946989cf23SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 956989cf23SStefano Zampini 966989cf23SStefano Zampini /* create MATIS object */ 976989cf23SStefano Zampini ierr = MatCreate(comm,newmat);CHKERRQ(ierr); 986989cf23SStefano Zampini ierr = MatSetSizes(*newmat,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 996989cf23SStefano Zampini ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr); 1006989cf23SStefano Zampini ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr); 1016989cf23SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 1026989cf23SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 1036989cf23SStefano Zampini 1046989cf23SStefano Zampini /* merge local matrices */ 1056989cf23SStefano Zampini ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr); 1066989cf23SStefano Zampini ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr); 1076989cf23SStefano Zampini ii = aux; 1086989cf23SStefano Zampini jj = aux+dr+1; 1096989cf23SStefano Zampini aa = data; 1106989cf23SStefano Zampini *ii = *(di++) + *(oi++); 1116989cf23SStefano Zampini for (jd=0,jo=0,cum=0;*ii<nnz;cum++) 1126989cf23SStefano Zampini { 1136989cf23SStefano Zampini for (;jd<*di;jd++) { *jj++ = *dj++; *aa++ = *dd++; } 1146989cf23SStefano Zampini for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; } 1156989cf23SStefano Zampini *(++ii) = *(di++) + *(oi++); 1166989cf23SStefano Zampini } 1176989cf23SStefano Zampini for (;cum<dr;cum++) *(++ii) = nnz; 1186989cf23SStefano Zampini ii = aux; 1196989cf23SStefano Zampini jj = aux+dr+1; 1206989cf23SStefano Zampini aa = data; 121e363d98aSStefano Zampini ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr); 1226989cf23SStefano Zampini 1236989cf23SStefano Zampini /* create containers to destroy the data */ 1246989cf23SStefano Zampini ptrs[0] = aux; 1256989cf23SStefano Zampini ptrs[1] = data; 1266989cf23SStefano Zampini for (i=0; i<2; i++) { 1276989cf23SStefano Zampini PetscContainer c; 1286989cf23SStefano Zampini 1296989cf23SStefano Zampini ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr); 1306989cf23SStefano Zampini ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr); 1315b003df0Sstefano_zampini ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyArray_Private);CHKERRQ(ierr); 1326989cf23SStefano Zampini ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr); 1336989cf23SStefano Zampini ierr = PetscContainerDestroy(&c);CHKERRQ(ierr); 1346989cf23SStefano Zampini } 1356989cf23SStefano Zampini 1366989cf23SStefano Zampini /* finalize matrix */ 1376989cf23SStefano Zampini ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr); 1386989cf23SStefano Zampini ierr = MatDestroy(&lA);CHKERRQ(ierr); 1396989cf23SStefano Zampini ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1406989cf23SStefano Zampini ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1416989cf23SStefano Zampini PetscFunctionReturn(0); 1426989cf23SStefano Zampini } 1436989cf23SStefano Zampini 144cf0a3239SStefano Zampini /*@ 1453d996552SStefano Zampini MatISSetUpSF - Setup star forest objects used by MatIS. 146cf0a3239SStefano Zampini 147cf0a3239SStefano Zampini Collective on MPI_Comm 148cf0a3239SStefano Zampini 149cf0a3239SStefano Zampini Input Parameters: 150cf0a3239SStefano Zampini + A - the matrix 151cf0a3239SStefano Zampini 152cf0a3239SStefano Zampini Level: advanced 153cf0a3239SStefano Zampini 1543d996552SStefano Zampini Notes: This function does not need to be called by the user. 155cf0a3239SStefano Zampini 156cf0a3239SStefano Zampini .keywords: matrix 157cf0a3239SStefano Zampini 158cf0a3239SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat() 159cf0a3239SStefano Zampini @*/ 160cf0a3239SStefano Zampini PetscErrorCode MatISSetUpSF(Mat A) 161cf0a3239SStefano Zampini { 1627fa8f2d3SStefano Zampini PetscErrorCode ierr; 1637fa8f2d3SStefano Zampini 1647fa8f2d3SStefano Zampini PetscFunctionBegin; 165cf0a3239SStefano Zampini PetscValidHeaderSpecific(A,MAT_CLASSID,1); 166cf0a3239SStefano Zampini PetscValidType(A,1); 167cf0a3239SStefano Zampini ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr); 1687fa8f2d3SStefano Zampini PetscFunctionReturn(0); 1697fa8f2d3SStefano Zampini } 1707fa8f2d3SStefano Zampini 1715e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat) 1725e3038f0Sstefano_zampini { 1735e3038f0Sstefano_zampini Mat **nest,*snest,**rnest,lA,B; 1745e3038f0Sstefano_zampini IS *iscol,*isrow,*islrow,*islcol; 1755e3038f0Sstefano_zampini ISLocalToGlobalMapping rl2g,cl2g; 1765e3038f0Sstefano_zampini MPI_Comm comm; 1775b003df0Sstefano_zampini PetscInt *lr,*lc,*l2gidxs; 1785b003df0Sstefano_zampini PetscInt i,j,nr,nc,rbs,cbs; 1799e7b2b25Sstefano_zampini PetscBool convert,lreuse,*istrans; 1805e3038f0Sstefano_zampini PetscErrorCode ierr; 1815e3038f0Sstefano_zampini 182ab4d48faSStefano Zampini PetscFunctionBegin; 1835e3038f0Sstefano_zampini ierr = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr); 1845e3038f0Sstefano_zampini lreuse = PETSC_FALSE; 1855e3038f0Sstefano_zampini rnest = NULL; 1865e3038f0Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 1875e3038f0Sstefano_zampini PetscBool ismatis,isnest; 1885e3038f0Sstefano_zampini 1895e3038f0Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr); 1905e3038f0Sstefano_zampini if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type); 1915e3038f0Sstefano_zampini ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 1925e3038f0Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr); 1935e3038f0Sstefano_zampini if (isnest) { 1945e3038f0Sstefano_zampini ierr = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr); 1955e3038f0Sstefano_zampini lreuse = (PetscBool)(i == nr && j == nc); 1965e3038f0Sstefano_zampini if (!lreuse) rnest = NULL; 1975e3038f0Sstefano_zampini } 1985e3038f0Sstefano_zampini } 1995e3038f0Sstefano_zampini ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 2005b003df0Sstefano_zampini ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr); 2019e7b2b25Sstefano_zampini ierr = PetscCalloc6(nr,&isrow,nc,&iscol, 2025e3038f0Sstefano_zampini nr,&islrow,nc,&islcol, 2039e7b2b25Sstefano_zampini nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr); 2045e3038f0Sstefano_zampini ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr); 2055e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 2065e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 2075e3038f0Sstefano_zampini PetscBool ismatis; 2089e7b2b25Sstefano_zampini PetscInt l1,l2,lb1,lb2,ij=i*nc+j; 2095e3038f0Sstefano_zampini 2105e3038f0Sstefano_zampini /* Null matrix pointers are allowed in MATNEST */ 2115e3038f0Sstefano_zampini if (!nest[i][j]) continue; 2125e3038f0Sstefano_zampini 2135e3038f0Sstefano_zampini /* Nested matrices should be of type MATIS */ 2149e7b2b25Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr); 2159e7b2b25Sstefano_zampini if (istrans[ij]) { 2169e7b2b25Sstefano_zampini Mat T,lT; 2179e7b2b25Sstefano_zampini ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr); 2189e7b2b25Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr); 2199e7b2b25Sstefano_zampini if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) (transposed) is not of type MATIS",i,j); 2209e7b2b25Sstefano_zampini ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr); 2219e7b2b25Sstefano_zampini ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr); 2229e7b2b25Sstefano_zampini } else { 2235e3038f0Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr); 2245e3038f0Sstefano_zampini if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) is not of type MATIS",i,j); 2259e7b2b25Sstefano_zampini ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr); 2269e7b2b25Sstefano_zampini } 2275e3038f0Sstefano_zampini 2285e3038f0Sstefano_zampini /* Check compatibility of local sizes */ 2295e3038f0Sstefano_zampini ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr); 2309e7b2b25Sstefano_zampini ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr); 2315e3038f0Sstefano_zampini if (!l1 || !l2) continue; 2325e3038f0Sstefano_zampini if (lr[i] && l1 != lr[i]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lr[i],l1); 2335e3038f0Sstefano_zampini if (lc[j] && l2 != lc[j]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lc[j],l2); 2345e3038f0Sstefano_zampini lr[i] = l1; 2355e3038f0Sstefano_zampini lc[j] = l2; 2365e3038f0Sstefano_zampini 2375e3038f0Sstefano_zampini /* check compatibilty for local matrix reusage */ 2385e3038f0Sstefano_zampini if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE; 2395e3038f0Sstefano_zampini } 2405e3038f0Sstefano_zampini } 2415e3038f0Sstefano_zampini 2425e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG) 2435e3038f0Sstefano_zampini /* Check compatibility of l2g maps for rows */ 2445e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 2455e3038f0Sstefano_zampini rl2g = NULL; 2465e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 2475e3038f0Sstefano_zampini PetscInt n1,n2; 2485e3038f0Sstefano_zampini 2495e3038f0Sstefano_zampini if (!nest[i][j]) continue; 2509e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 2519e7b2b25Sstefano_zampini Mat T; 2529e7b2b25Sstefano_zampini 2539e7b2b25Sstefano_zampini ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr); 2549e7b2b25Sstefano_zampini ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr); 2559e7b2b25Sstefano_zampini } else { 2565e3038f0Sstefano_zampini ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr); 2579e7b2b25Sstefano_zampini } 2585e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr); 2595e3038f0Sstefano_zampini if (!n1) continue; 2605e3038f0Sstefano_zampini if (!rl2g) { 2615e3038f0Sstefano_zampini rl2g = cl2g; 2625e3038f0Sstefano_zampini } else { 2635e3038f0Sstefano_zampini const PetscInt *idxs1,*idxs2; 2645e3038f0Sstefano_zampini PetscBool same; 2655e3038f0Sstefano_zampini 2665e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr); 2675e3038f0Sstefano_zampini if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap size %D != %D",i,j,n1,n2); 2685e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr); 2695e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr); 2705e3038f0Sstefano_zampini ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr); 2715e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr); 2725e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr); 2735e3038f0Sstefano_zampini if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap",i,j); 2745e3038f0Sstefano_zampini } 2755e3038f0Sstefano_zampini } 2765e3038f0Sstefano_zampini } 2775e3038f0Sstefano_zampini /* Check compatibility of l2g maps for columns */ 2785e3038f0Sstefano_zampini for (i=0;i<nc;i++) { 2795e3038f0Sstefano_zampini rl2g = NULL; 2805e3038f0Sstefano_zampini for (j=0;j<nr;j++) { 2815e3038f0Sstefano_zampini PetscInt n1,n2; 2825e3038f0Sstefano_zampini 2835e3038f0Sstefano_zampini if (!nest[j][i]) continue; 2849e7b2b25Sstefano_zampini if (istrans[j*nc+i]) { 2859e7b2b25Sstefano_zampini Mat T; 2869e7b2b25Sstefano_zampini 2879e7b2b25Sstefano_zampini ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr); 2889e7b2b25Sstefano_zampini ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr); 2899e7b2b25Sstefano_zampini } else { 2905e3038f0Sstefano_zampini ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr); 2919e7b2b25Sstefano_zampini } 2925e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr); 2935e3038f0Sstefano_zampini if (!n1) continue; 2945e3038f0Sstefano_zampini if (!rl2g) { 2955e3038f0Sstefano_zampini rl2g = cl2g; 2965e3038f0Sstefano_zampini } else { 2975e3038f0Sstefano_zampini const PetscInt *idxs1,*idxs2; 2985e3038f0Sstefano_zampini PetscBool same; 2995e3038f0Sstefano_zampini 3005e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr); 3015e3038f0Sstefano_zampini if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap size %D != %D",j,i,n1,n2); 3025e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr); 3035e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr); 3045e3038f0Sstefano_zampini ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr); 3055e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr); 3065e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr); 3075e3038f0Sstefano_zampini if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap",j,i); 3085e3038f0Sstefano_zampini } 3095e3038f0Sstefano_zampini } 3105e3038f0Sstefano_zampini } 3115e3038f0Sstefano_zampini #endif 3125e3038f0Sstefano_zampini 3135e3038f0Sstefano_zampini B = NULL; 3145e3038f0Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 3155b003df0Sstefano_zampini PetscInt stl; 3165b003df0Sstefano_zampini 3175e3038f0Sstefano_zampini /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */ 3185e3038f0Sstefano_zampini for (i=0,stl=0;i<nr;i++) stl += lr[i]; 3195e3038f0Sstefano_zampini ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr); 3205b003df0Sstefano_zampini for (i=0,stl=0;i<nr;i++) { 3215e3038f0Sstefano_zampini Mat usedmat; 3225e3038f0Sstefano_zampini Mat_IS *matis; 3235e3038f0Sstefano_zampini const PetscInt *idxs; 3245e3038f0Sstefano_zampini 3255e3038f0Sstefano_zampini /* local IS for local NEST */ 3265b003df0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr); 3275e3038f0Sstefano_zampini 3285e3038f0Sstefano_zampini /* l2gmap */ 3295e3038f0Sstefano_zampini j = 0; 3305e3038f0Sstefano_zampini usedmat = nest[i][j]; 3319e7b2b25Sstefano_zampini while (!usedmat && j < nc-1) usedmat = nest[i][++j]; 3329e7b2b25Sstefano_zampini if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat"); 3339e7b2b25Sstefano_zampini 3349e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 3359e7b2b25Sstefano_zampini Mat T; 3369e7b2b25Sstefano_zampini ierr = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr); 3379e7b2b25Sstefano_zampini usedmat = T; 3389e7b2b25Sstefano_zampini } 33982d73161Sstefano_zampini ierr = MatISSetUpSF(usedmat);CHKERRQ(ierr); 3405e3038f0Sstefano_zampini matis = (Mat_IS*)(usedmat->data); 3415e3038f0Sstefano_zampini ierr = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr); 3429e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 3439e7b2b25Sstefano_zampini ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 3449e7b2b25Sstefano_zampini ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 3459e7b2b25Sstefano_zampini } else { 3465e3038f0Sstefano_zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 3475e3038f0Sstefano_zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 3489e7b2b25Sstefano_zampini } 3495e3038f0Sstefano_zampini ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr); 3505e3038f0Sstefano_zampini stl += lr[i]; 3515e3038f0Sstefano_zampini } 3525e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr); 3535e3038f0Sstefano_zampini 3545e3038f0Sstefano_zampini /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */ 3555e3038f0Sstefano_zampini for (i=0,stl=0;i<nc;i++) stl += lc[i]; 3565e3038f0Sstefano_zampini ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr); 3575b003df0Sstefano_zampini for (i=0,stl=0;i<nc;i++) { 3585e3038f0Sstefano_zampini Mat usedmat; 3595e3038f0Sstefano_zampini Mat_IS *matis; 3605e3038f0Sstefano_zampini const PetscInt *idxs; 3615e3038f0Sstefano_zampini 3625e3038f0Sstefano_zampini /* local IS for local NEST */ 3635b003df0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr); 3645e3038f0Sstefano_zampini 3655e3038f0Sstefano_zampini /* l2gmap */ 3665e3038f0Sstefano_zampini j = 0; 3675e3038f0Sstefano_zampini usedmat = nest[j][i]; 3689e7b2b25Sstefano_zampini while (!usedmat && j < nr-1) usedmat = nest[++j][i]; 3699e7b2b25Sstefano_zampini if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat"); 3709e7b2b25Sstefano_zampini if (istrans[j*nc+i]) { 3719e7b2b25Sstefano_zampini Mat T; 3729e7b2b25Sstefano_zampini ierr = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr); 3739e7b2b25Sstefano_zampini usedmat = T; 3749e7b2b25Sstefano_zampini } 37582d73161Sstefano_zampini ierr = MatISSetUpSF(usedmat);CHKERRQ(ierr); 3765e3038f0Sstefano_zampini matis = (Mat_IS*)(usedmat->data); 3775e3038f0Sstefano_zampini ierr = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr); 3789e7b2b25Sstefano_zampini if (istrans[j*nc+i]) { 3799e7b2b25Sstefano_zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 3809e7b2b25Sstefano_zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 3819e7b2b25Sstefano_zampini } else { 3825e3038f0Sstefano_zampini ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 3835e3038f0Sstefano_zampini ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 3849e7b2b25Sstefano_zampini } 3855e3038f0Sstefano_zampini ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr); 3865e3038f0Sstefano_zampini stl += lc[i]; 3875e3038f0Sstefano_zampini } 3885e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr); 3895e3038f0Sstefano_zampini 3905e3038f0Sstefano_zampini /* Create MATIS */ 3915e3038f0Sstefano_zampini ierr = MatCreate(comm,&B);CHKERRQ(ierr); 3925e3038f0Sstefano_zampini ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 3935e3038f0Sstefano_zampini ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr); 3945e3038f0Sstefano_zampini ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr); 3955e3038f0Sstefano_zampini ierr = MatSetType(B,MATIS);CHKERRQ(ierr); 3965e3038f0Sstefano_zampini ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr); 3975e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 3985e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 3995e3038f0Sstefano_zampini ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr); 4009e7b2b25Sstefano_zampini for (i=0;i<nr*nc;i++) { 4019e7b2b25Sstefano_zampini if (istrans[i]) { 4029e7b2b25Sstefano_zampini ierr = MatDestroy(&snest[i]);CHKERRQ(ierr); 4039e7b2b25Sstefano_zampini } 4049e7b2b25Sstefano_zampini } 4055e3038f0Sstefano_zampini ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr); 4065e3038f0Sstefano_zampini ierr = MatDestroy(&lA);CHKERRQ(ierr); 4075e3038f0Sstefano_zampini ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4085e3038f0Sstefano_zampini ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4095e3038f0Sstefano_zampini if (reuse == MAT_INPLACE_MATRIX) { 4105e3038f0Sstefano_zampini ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 4115e3038f0Sstefano_zampini } else { 4125e3038f0Sstefano_zampini *newmat = B; 4135e3038f0Sstefano_zampini } 4145e3038f0Sstefano_zampini } else { 4155e3038f0Sstefano_zampini if (lreuse) { 4165e3038f0Sstefano_zampini ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 4175e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 4185e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 4195e3038f0Sstefano_zampini if (snest[i*nc+j]) { 4205e3038f0Sstefano_zampini ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr); 4219e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 4229e7b2b25Sstefano_zampini ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr); 4239e7b2b25Sstefano_zampini } 4245e3038f0Sstefano_zampini } 4255e3038f0Sstefano_zampini } 4265e3038f0Sstefano_zampini } 4275e3038f0Sstefano_zampini } else { 4285b003df0Sstefano_zampini PetscInt stl; 4295b003df0Sstefano_zampini for (i=0,stl=0;i<nr;i++) { 4305b003df0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr); 4315b003df0Sstefano_zampini stl += lr[i]; 4325e3038f0Sstefano_zampini } 4335b003df0Sstefano_zampini for (i=0,stl=0;i<nc;i++) { 4345b003df0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr); 4355b003df0Sstefano_zampini stl += lc[i]; 4365e3038f0Sstefano_zampini } 4375e3038f0Sstefano_zampini ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr); 438ab4d48faSStefano Zampini for (i=0;i<nr*nc;i++) { 4399e7b2b25Sstefano_zampini if (istrans[i]) { 4409e7b2b25Sstefano_zampini ierr = MatDestroy(&snest[i]);CHKERRQ(ierr); 4419e7b2b25Sstefano_zampini } 442ab4d48faSStefano Zampini } 4435e3038f0Sstefano_zampini ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr); 4445e3038f0Sstefano_zampini ierr = MatDestroy(&lA);CHKERRQ(ierr); 4455e3038f0Sstefano_zampini } 4465e3038f0Sstefano_zampini ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4475e3038f0Sstefano_zampini ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4485e3038f0Sstefano_zampini } 4495e3038f0Sstefano_zampini 4505b003df0Sstefano_zampini /* Create local matrix in MATNEST format */ 4515b003df0Sstefano_zampini convert = PETSC_FALSE; 4525b003df0Sstefano_zampini ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr); 4535b003df0Sstefano_zampini if (convert) { 4545b003df0Sstefano_zampini Mat M; 4555b003df0Sstefano_zampini MatISLocalFields lf; 4565b003df0Sstefano_zampini PetscContainer c; 4575b003df0Sstefano_zampini 4585b003df0Sstefano_zampini ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 4595b003df0Sstefano_zampini ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr); 4605b003df0Sstefano_zampini ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr); 4615b003df0Sstefano_zampini ierr = MatDestroy(&M);CHKERRQ(ierr); 4625b003df0Sstefano_zampini 4635b003df0Sstefano_zampini /* attach local fields to the matrix */ 4645b003df0Sstefano_zampini ierr = PetscNew(&lf);CHKERRQ(ierr); 4655b003df0Sstefano_zampini ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr); 4665b003df0Sstefano_zampini for (i=0;i<nr;i++) { 4675b003df0Sstefano_zampini PetscInt n,st; 4685b003df0Sstefano_zampini 4695b003df0Sstefano_zampini ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr); 4705b003df0Sstefano_zampini ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr); 4715b003df0Sstefano_zampini ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr); 4725b003df0Sstefano_zampini } 4735b003df0Sstefano_zampini for (i=0;i<nc;i++) { 4745b003df0Sstefano_zampini PetscInt n,st; 4755b003df0Sstefano_zampini 4765b003df0Sstefano_zampini ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr); 4775b003df0Sstefano_zampini ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr); 4785b003df0Sstefano_zampini ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr); 4795b003df0Sstefano_zampini } 4805b003df0Sstefano_zampini lf->nr = nr; 4815b003df0Sstefano_zampini lf->nc = nc; 4825b003df0Sstefano_zampini ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr); 4835b003df0Sstefano_zampini ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr); 4845b003df0Sstefano_zampini ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr); 4855b003df0Sstefano_zampini ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr); 4865b003df0Sstefano_zampini ierr = PetscContainerDestroy(&c);CHKERRQ(ierr); 4875b003df0Sstefano_zampini } 4885b003df0Sstefano_zampini 4895e3038f0Sstefano_zampini /* Free workspace */ 4905e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 4915e3038f0Sstefano_zampini ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr); 4925e3038f0Sstefano_zampini } 4935e3038f0Sstefano_zampini for (i=0;i<nc;i++) { 4945e3038f0Sstefano_zampini ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr); 4955e3038f0Sstefano_zampini } 4969e7b2b25Sstefano_zampini ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr); 4975b003df0Sstefano_zampini ierr = PetscFree2(lr,lc);CHKERRQ(ierr); 4985e3038f0Sstefano_zampini PetscFunctionReturn(0); 4995e3038f0Sstefano_zampini } 5005e3038f0Sstefano_zampini 501ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r) 502ad219c80Sstefano_zampini { 503ad219c80Sstefano_zampini Mat_IS *matis = (Mat_IS*)A->data; 504ad219c80Sstefano_zampini Vec ll,rr; 505ad219c80Sstefano_zampini const PetscScalar *Y,*X; 506ad219c80Sstefano_zampini PetscScalar *x,*y; 507ad219c80Sstefano_zampini PetscErrorCode ierr; 508ad219c80Sstefano_zampini 509ad219c80Sstefano_zampini PetscFunctionBegin; 510ad219c80Sstefano_zampini ierr = MatISSetUpSF(A);CHKERRQ(ierr); 511ad219c80Sstefano_zampini if (l) { 512ad219c80Sstefano_zampini ll = matis->y; 513ad219c80Sstefano_zampini ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr); 514ad219c80Sstefano_zampini ierr = VecGetArray(ll,&y);CHKERRQ(ierr); 515ad219c80Sstefano_zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr); 516ad219c80Sstefano_zampini } else { 517ad219c80Sstefano_zampini ll = NULL; 518ad219c80Sstefano_zampini } 519ad219c80Sstefano_zampini if (r) { 520ad219c80Sstefano_zampini rr = matis->x; 521ad219c80Sstefano_zampini ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr); 522ad219c80Sstefano_zampini ierr = VecGetArray(rr,&x);CHKERRQ(ierr); 523ad219c80Sstefano_zampini ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr); 524ad219c80Sstefano_zampini } else { 525ad219c80Sstefano_zampini rr = NULL; 526ad219c80Sstefano_zampini } 527ad219c80Sstefano_zampini if (ll) { 528ad219c80Sstefano_zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr); 529ad219c80Sstefano_zampini ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr); 530ad219c80Sstefano_zampini ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr); 531ad219c80Sstefano_zampini } 532ad219c80Sstefano_zampini if (rr) { 533ad219c80Sstefano_zampini ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr); 534ad219c80Sstefano_zampini ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr); 535ad219c80Sstefano_zampini ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr); 536ad219c80Sstefano_zampini } 537ad219c80Sstefano_zampini ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr); 538ad219c80Sstefano_zampini PetscFunctionReturn(0); 539ad219c80Sstefano_zampini } 540ad219c80Sstefano_zampini 5417fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo) 5427fa8f2d3SStefano Zampini { 5437fa8f2d3SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 5447fa8f2d3SStefano Zampini MatInfo info; 5457fa8f2d3SStefano Zampini PetscReal isend[6],irecv[6]; 5467fa8f2d3SStefano Zampini PetscInt bs; 5477fa8f2d3SStefano Zampini PetscErrorCode ierr; 5487fa8f2d3SStefano Zampini 5497fa8f2d3SStefano Zampini PetscFunctionBegin; 5507fa8f2d3SStefano Zampini ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 5517fa8f2d3SStefano Zampini if (matis->A->ops->getinfo) { 5527fa8f2d3SStefano Zampini ierr = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr); 5537fa8f2d3SStefano Zampini isend[0] = info.nz_used; 5547fa8f2d3SStefano Zampini isend[1] = info.nz_allocated; 5557fa8f2d3SStefano Zampini isend[2] = info.nz_unneeded; 5567fa8f2d3SStefano Zampini isend[3] = info.memory; 5577fa8f2d3SStefano Zampini isend[4] = info.mallocs; 5587fa8f2d3SStefano Zampini } else { 5597fa8f2d3SStefano Zampini isend[0] = 0.; 5607fa8f2d3SStefano Zampini isend[1] = 0.; 5617fa8f2d3SStefano Zampini isend[2] = 0.; 5627fa8f2d3SStefano Zampini isend[3] = 0.; 5637fa8f2d3SStefano Zampini isend[4] = 0.; 5647fa8f2d3SStefano Zampini } 5657fa8f2d3SStefano Zampini isend[5] = matis->A->num_ass; 5667fa8f2d3SStefano Zampini if (flag == MAT_LOCAL) { 5677fa8f2d3SStefano Zampini ginfo->nz_used = isend[0]; 5687fa8f2d3SStefano Zampini ginfo->nz_allocated = isend[1]; 5697fa8f2d3SStefano Zampini ginfo->nz_unneeded = isend[2]; 5707fa8f2d3SStefano Zampini ginfo->memory = isend[3]; 5717fa8f2d3SStefano Zampini ginfo->mallocs = isend[4]; 5727fa8f2d3SStefano Zampini ginfo->assemblies = isend[5]; 5737fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_MAX) { 5747fa8f2d3SStefano Zampini ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 5757fa8f2d3SStefano Zampini 5767fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 5777fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 5787fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 5797fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 5807fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 5817fa8f2d3SStefano Zampini ginfo->assemblies = irecv[5]; 5827fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_SUM) { 5837fa8f2d3SStefano Zampini ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 5847fa8f2d3SStefano Zampini 5857fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 5867fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 5877fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 5887fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 5897fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 5907fa8f2d3SStefano Zampini ginfo->assemblies = A->num_ass; 591d7f69cd0SStefano Zampini } 592d7f69cd0SStefano Zampini ginfo->block_size = bs; 593d7f69cd0SStefano Zampini ginfo->fill_ratio_given = 0; 594d7f69cd0SStefano Zampini ginfo->fill_ratio_needed = 0; 595d7f69cd0SStefano Zampini ginfo->factor_mallocs = 0; 5965e3038f0Sstefano_zampini PetscFunctionReturn(0); 5975e3038f0Sstefano_zampini } 5985e3038f0Sstefano_zampini 599d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B) 600d7f69cd0SStefano Zampini { 601d7f69cd0SStefano Zampini Mat C,lC,lA; 602d7f69cd0SStefano Zampini PetscErrorCode ierr; 603d7f69cd0SStefano Zampini 604d7f69cd0SStefano Zampini PetscFunctionBegin; 605cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) { 606cf37664fSBarry Smith ISLocalToGlobalMapping rl2g,cl2g; 607d7f69cd0SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 608d7f69cd0SStefano Zampini ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr); 609d7f69cd0SStefano Zampini ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr); 610d7f69cd0SStefano Zampini ierr = MatSetType(C,MATIS);CHKERRQ(ierr); 611d7f69cd0SStefano Zampini ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr); 612d7f69cd0SStefano Zampini ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr); 613cf37664fSBarry Smith } else { 614cf37664fSBarry Smith C = *B; 615d7f69cd0SStefano Zampini } 616d7f69cd0SStefano Zampini 617d7f69cd0SStefano Zampini /* perform local transposition */ 618d7f69cd0SStefano Zampini ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr); 619d7f69cd0SStefano Zampini ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr); 620d7f69cd0SStefano Zampini ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr); 621d7f69cd0SStefano Zampini ierr = MatDestroy(&lC);CHKERRQ(ierr); 622d7f69cd0SStefano Zampini 623cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 624d7f69cd0SStefano Zampini *B = C; 625d7f69cd0SStefano Zampini } else { 626d7f69cd0SStefano Zampini ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr); 627d7f69cd0SStefano Zampini } 6287aa7aec5Sstefano_zampini ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 6297aa7aec5Sstefano_zampini ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 630d7f69cd0SStefano Zampini PetscFunctionReturn(0); 631d7f69cd0SStefano Zampini } 632d7f69cd0SStefano Zampini 6333fd1c9e7SStefano Zampini PetscErrorCode MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode) 6343fd1c9e7SStefano Zampini { 6353fd1c9e7SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 6363fd1c9e7SStefano Zampini PetscErrorCode ierr; 6373fd1c9e7SStefano Zampini 6383fd1c9e7SStefano Zampini PetscFunctionBegin; 6394b89b9cdSStefano Zampini if (D) { /* MatShift_IS pass D = NULL */ 6403fd1c9e7SStefano Zampini ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 6413fd1c9e7SStefano Zampini ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 6423fd1c9e7SStefano Zampini } 6433fd1c9e7SStefano Zampini ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr); 6443fd1c9e7SStefano Zampini ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr); 6453fd1c9e7SStefano Zampini PetscFunctionReturn(0); 6463fd1c9e7SStefano Zampini } 6473fd1c9e7SStefano Zampini 6483fd1c9e7SStefano Zampini PetscErrorCode MatShift_IS(Mat A,PetscScalar a) 6493fd1c9e7SStefano Zampini { 6504b89b9cdSStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 6513fd1c9e7SStefano Zampini PetscErrorCode ierr; 6523fd1c9e7SStefano Zampini 6533fd1c9e7SStefano Zampini PetscFunctionBegin; 6544b89b9cdSStefano Zampini ierr = VecSet(is->y,a);CHKERRQ(ierr); 6553fd1c9e7SStefano Zampini ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr); 6563fd1c9e7SStefano Zampini PetscFunctionReturn(0); 6573fd1c9e7SStefano Zampini } 6583fd1c9e7SStefano Zampini 659f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 660f26d0771SStefano Zampini { 661f26d0771SStefano Zampini PetscErrorCode ierr; 662f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 663f26d0771SStefano Zampini 664f26d0771SStefano Zampini PetscFunctionBegin; 665f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 666f26d0771SStefano Zampini if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n); 667f26d0771SStefano Zampini #endif 668f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr); 669f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr); 670b4f971dfSStefano Zampini ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 671f26d0771SStefano Zampini PetscFunctionReturn(0); 672f26d0771SStefano Zampini } 673f26d0771SStefano Zampini 674f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 675f26d0771SStefano Zampini { 676f26d0771SStefano Zampini PetscErrorCode ierr; 677f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 678f26d0771SStefano Zampini 679f26d0771SStefano Zampini PetscFunctionBegin; 680f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 681f26d0771SStefano Zampini if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n); 682f26d0771SStefano Zampini #endif 683f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr); 684f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr); 685b4f971dfSStefano Zampini ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 686f26d0771SStefano Zampini PetscFunctionReturn(0); 687f26d0771SStefano Zampini } 688f26d0771SStefano Zampini 689f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs) 690a8116848SStefano Zampini { 691a8116848SStefano Zampini PetscInt *owners = map->range; 692a8116848SStefano Zampini PetscInt n = map->n; 693a8116848SStefano Zampini PetscSF sf; 694a8116848SStefano Zampini PetscInt *lidxs,*work = NULL; 695a8116848SStefano Zampini PetscSFNode *ridxs; 696a8116848SStefano Zampini PetscMPIInt rank; 697a8116848SStefano Zampini PetscInt r, p = 0, len = 0; 698a8116848SStefano Zampini PetscErrorCode ierr; 699a8116848SStefano Zampini 700a8116848SStefano Zampini PetscFunctionBegin; 701fd3a879cSJed Brown if (on) *on = 0; /* squelch -Wmaybe-uninitialized */ 702a8116848SStefano Zampini /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */ 703a8116848SStefano Zampini ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr); 704a8116848SStefano Zampini ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr); 705a8116848SStefano Zampini for (r = 0; r < n; ++r) lidxs[r] = -1; 706a8116848SStefano Zampini ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr); 707a8116848SStefano Zampini for (r = 0; r < N; ++r) { 708a8116848SStefano Zampini const PetscInt idx = idxs[r]; 709a8116848SStefano Zampini if (idx < 0 || map->N <= idx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index %D out of range [0,%D)",idx,map->N); 710a8116848SStefano Zampini if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */ 711a8116848SStefano Zampini ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr); 712a8116848SStefano Zampini } 713a8116848SStefano Zampini ridxs[r].rank = p; 714a8116848SStefano Zampini ridxs[r].index = idxs[r] - owners[p]; 715a8116848SStefano Zampini } 716a8116848SStefano Zampini ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr); 717a8116848SStefano Zampini ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr); 718a8116848SStefano Zampini ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr); 719a8116848SStefano Zampini ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr); 720f0ae7da4SStefano Zampini if (ogidxs) { /* communicate global idxs */ 721a8116848SStefano Zampini PetscInt cum = 0,start,*work2; 722f0ae7da4SStefano Zampini 723f0ae7da4SStefano Zampini ierr = PetscMalloc1(n,&work);CHKERRQ(ierr); 724a8116848SStefano Zampini ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr); 725a8116848SStefano Zampini for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++; 726a8116848SStefano Zampini ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr); 727a8116848SStefano Zampini start -= cum; 728a8116848SStefano Zampini cum = 0; 729a8116848SStefano Zampini for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++; 730a8116848SStefano Zampini ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr); 731a8116848SStefano Zampini ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr); 732a8116848SStefano Zampini ierr = PetscFree(work2);CHKERRQ(ierr); 733a8116848SStefano Zampini } 734a8116848SStefano Zampini ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 735a8116848SStefano Zampini /* Compress and put in indices */ 736a8116848SStefano Zampini for (r = 0; r < n; ++r) 737a8116848SStefano Zampini if (lidxs[r] >= 0) { 738a8116848SStefano Zampini if (work) work[len] = work[r]; 739a8116848SStefano Zampini lidxs[len++] = r; 740a8116848SStefano Zampini } 741a8116848SStefano Zampini if (on) *on = len; 742a8116848SStefano Zampini if (oidxs) *oidxs = lidxs; 743a8116848SStefano Zampini if (ogidxs) *ogidxs = work; 744a8116848SStefano Zampini PetscFunctionReturn(0); 745a8116848SStefano Zampini } 746a8116848SStefano Zampini 7477dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat) 748a8116848SStefano Zampini { 749a8116848SStefano Zampini Mat locmat,newlocmat; 750a8116848SStefano Zampini Mat_IS *newmatis; 751a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG) 752a8116848SStefano Zampini Vec rtest,ltest; 753a8116848SStefano Zampini const PetscScalar *array; 754a8116848SStefano Zampini #endif 755a8116848SStefano Zampini const PetscInt *idxs; 756a8116848SStefano Zampini PetscInt i,m,n; 757a8116848SStefano Zampini PetscErrorCode ierr; 758a8116848SStefano Zampini 759a8116848SStefano Zampini PetscFunctionBegin; 760a8116848SStefano Zampini if (scall == MAT_REUSE_MATRIX) { 761a8116848SStefano Zampini PetscBool ismatis; 762a8116848SStefano Zampini 763a8116848SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr); 764a8116848SStefano Zampini if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type"); 765a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 766a8116848SStefano Zampini if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS"); 767a8116848SStefano Zampini if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS"); 768a8116848SStefano Zampini } 769a8116848SStefano Zampini /* irow and icol may not have duplicate entries */ 770a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG) 771a8116848SStefano Zampini ierr = MatCreateVecs(mat,<est,&rtest);CHKERRQ(ierr); 772a8116848SStefano Zampini ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr); 773a8116848SStefano Zampini ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr); 774a8116848SStefano Zampini for (i=0;i<n;i++) { 775a8116848SStefano Zampini ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr); 776a8116848SStefano Zampini } 777a8116848SStefano Zampini ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr); 778a8116848SStefano Zampini ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr); 779a8116848SStefano Zampini ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr); 780a8116848SStefano Zampini ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr); 781a8116848SStefano Zampini ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr); 782fd479f66SMatthew G. Knepley for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Irow may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i])); 783a8116848SStefano Zampini ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr); 784a8116848SStefano Zampini ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr); 785a8116848SStefano Zampini ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr); 786a8116848SStefano Zampini ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr); 787a8116848SStefano Zampini for (i=0;i<n;i++) { 788a8116848SStefano Zampini ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr); 789a8116848SStefano Zampini } 790a8116848SStefano Zampini ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr); 791a8116848SStefano Zampini ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr); 792a8116848SStefano Zampini ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr); 793a8116848SStefano Zampini ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr); 794a8116848SStefano Zampini ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr); 795fd479f66SMatthew G. Knepley for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Icol may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i])); 796a8116848SStefano Zampini ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr); 797a8116848SStefano Zampini ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr); 798a8116848SStefano Zampini ierr = VecDestroy(&rtest);CHKERRQ(ierr); 799a8116848SStefano Zampini ierr = VecDestroy(<est);CHKERRQ(ierr); 800a8116848SStefano Zampini #endif 801a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 802a8116848SStefano Zampini Mat_IS *matis = (Mat_IS*)mat->data; 803a8116848SStefano Zampini ISLocalToGlobalMapping rl2g; 804a8116848SStefano Zampini IS is; 805a8116848SStefano Zampini PetscInt *lidxs,*lgidxs,*newgidxs; 806*306cf5c7SStefano Zampini PetscInt ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs; 807a8116848SStefano Zampini MPI_Comm comm; 808a8116848SStefano Zampini 809a8116848SStefano Zampini ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 810*306cf5c7SStefano Zampini ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr); 811*306cf5c7SStefano Zampini ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr); 812*306cf5c7SStefano Zampini ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr); 813*306cf5c7SStefano Zampini rbs = arbs == irbs ? irbs : 1; 814*306cf5c7SStefano Zampini cbs = acbs == icbs ? icbs : 1; 815a8116848SStefano Zampini ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr); 816a8116848SStefano Zampini ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr); 817a8116848SStefano Zampini ierr = MatCreate(comm,newmat);CHKERRQ(ierr); 818a8116848SStefano Zampini ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr); 819a8116848SStefano Zampini ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 820*306cf5c7SStefano Zampini ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr); 821a8116848SStefano Zampini /* communicate irow to their owners in the layout */ 822a8116848SStefano Zampini ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr); 823f0ae7da4SStefano Zampini ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr); 824a8116848SStefano Zampini ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr); 8253d996552SStefano Zampini ierr = MatISSetUpSF(mat);CHKERRQ(ierr); 8263d996552SStefano Zampini ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr); 827a8116848SStefano Zampini for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1; 828a8116848SStefano Zampini ierr = PetscFree(lidxs);CHKERRQ(ierr); 829a8116848SStefano Zampini ierr = PetscFree(lgidxs);CHKERRQ(ierr); 830a8116848SStefano Zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 831a8116848SStefano Zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 8323d996552SStefano Zampini for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++; 833a8116848SStefano Zampini ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr); 834a8116848SStefano Zampini ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr); 8353d996552SStefano Zampini for (i=0,newloc=0;i<matis->sf->nleaves;i++) 836a8116848SStefano Zampini if (matis->sf_leafdata[i]) { 837a8116848SStefano Zampini lidxs[newloc] = i; 838a8116848SStefano Zampini newgidxs[newloc++] = matis->sf_leafdata[i]-1; 839a8116848SStefano Zampini } 840a8116848SStefano Zampini ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 841a8116848SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 842*306cf5c7SStefano Zampini ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr); 843a8116848SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 844a8116848SStefano Zampini /* local is to extract local submatrix */ 845a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 846a8116848SStefano Zampini ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr); 847a8116848SStefano Zampini if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */ 848a8116848SStefano Zampini PetscBool cong; 84926b0207aSStefano Zampini 850a8116848SStefano Zampini ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr); 851a8116848SStefano Zampini if (cong) mat->congruentlayouts = 1; 852a8116848SStefano Zampini else mat->congruentlayouts = 0; 853a8116848SStefano Zampini } 854268753edSStefano Zampini if (mat->congruentlayouts && irow == icol && matis->csf == matis->sf) { 855a8116848SStefano Zampini ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr); 856a8116848SStefano Zampini ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr); 857a8116848SStefano Zampini newmatis->getsub_cis = newmatis->getsub_ris; 858a8116848SStefano Zampini } else { 859a8116848SStefano Zampini ISLocalToGlobalMapping cl2g; 860a8116848SStefano Zampini 861a8116848SStefano Zampini /* communicate icol to their owners in the layout */ 862a8116848SStefano Zampini ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr); 863f0ae7da4SStefano Zampini ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr); 864a8116848SStefano Zampini ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr); 8653d996552SStefano Zampini ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr); 866a8116848SStefano Zampini for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1; 867a8116848SStefano Zampini ierr = PetscFree(lidxs);CHKERRQ(ierr); 868a8116848SStefano Zampini ierr = PetscFree(lgidxs);CHKERRQ(ierr); 869a8116848SStefano Zampini ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr); 870a8116848SStefano Zampini ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr); 8713d996552SStefano Zampini for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++; 872a8116848SStefano Zampini ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr); 873a8116848SStefano Zampini ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr); 8743d996552SStefano Zampini for (i=0,newloc=0;i<matis->csf->nleaves;i++) 875a8116848SStefano Zampini if (matis->csf_leafdata[i]) { 876a8116848SStefano Zampini lidxs[newloc] = i; 877a8116848SStefano Zampini newgidxs[newloc++] = matis->csf_leafdata[i]-1; 878a8116848SStefano Zampini } 879a8116848SStefano Zampini ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 880a8116848SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 881*306cf5c7SStefano Zampini ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr); 882a8116848SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 883a8116848SStefano Zampini /* local is to extract local submatrix */ 884a8116848SStefano Zampini ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr); 885a8116848SStefano Zampini ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr); 886a8116848SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 887a8116848SStefano Zampini } 888a8116848SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 889a8116848SStefano Zampini } else { 890a8116848SStefano Zampini ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr); 891a8116848SStefano Zampini } 892a8116848SStefano Zampini ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr); 893a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 8947dae84e0SHong Zhang ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr); 895a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 896a8116848SStefano Zampini ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr); 897a8116848SStefano Zampini ierr = MatDestroy(&newlocmat);CHKERRQ(ierr); 898a8116848SStefano Zampini } 899a8116848SStefano Zampini ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 900a8116848SStefano Zampini ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 901a8116848SStefano Zampini PetscFunctionReturn(0); 902a8116848SStefano Zampini } 903a8116848SStefano Zampini 904a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str) 9052b404112SStefano Zampini { 9062b404112SStefano Zampini Mat_IS *a = (Mat_IS*)A->data,*b; 9072b404112SStefano Zampini PetscBool ismatis; 9082b404112SStefano Zampini PetscErrorCode ierr; 9092b404112SStefano Zampini 9102b404112SStefano Zampini PetscFunctionBegin; 9112b404112SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr); 9122b404112SStefano Zampini if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented"); 9132b404112SStefano Zampini b = (Mat_IS*)B->data; 9142b404112SStefano Zampini ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr); 915cdc753b6SBarry Smith ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr); 9162b404112SStefano Zampini PetscFunctionReturn(0); 9172b404112SStefano Zampini } 9182b404112SStefano Zampini 919a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool *missing,PetscInt *d) 9206bd84002SStefano Zampini { 921527b2640SStefano Zampini Vec v; 922527b2640SStefano Zampini const PetscScalar *array; 923527b2640SStefano Zampini PetscInt i,n; 9246bd84002SStefano Zampini PetscErrorCode ierr; 9256bd84002SStefano Zampini 9266bd84002SStefano Zampini PetscFunctionBegin; 927527b2640SStefano Zampini *missing = PETSC_FALSE; 928527b2640SStefano Zampini ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr); 929527b2640SStefano Zampini ierr = MatGetDiagonal(A,v);CHKERRQ(ierr); 930527b2640SStefano Zampini ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 931527b2640SStefano Zampini ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr); 932527b2640SStefano Zampini for (i=0;i<n;i++) if (array[i] == 0.) break; 933527b2640SStefano Zampini ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr); 934527b2640SStefano Zampini ierr = VecDestroy(&v);CHKERRQ(ierr); 935527b2640SStefano Zampini if (i != n) *missing = PETSC_TRUE; 936527b2640SStefano Zampini if (d) { 937527b2640SStefano Zampini *d = -1; 938527b2640SStefano Zampini if (*missing) { 939527b2640SStefano Zampini PetscInt rstart; 940527b2640SStefano Zampini ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr); 941527b2640SStefano Zampini *d = i+rstart; 942527b2640SStefano Zampini } 943527b2640SStefano Zampini } 9446bd84002SStefano Zampini PetscFunctionReturn(0); 9456bd84002SStefano Zampini } 9466bd84002SStefano Zampini 947cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B) 94828f4e0baSStefano Zampini { 94928f4e0baSStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 95028f4e0baSStefano Zampini const PetscInt *gidxs; 9514f2d7cafSStefano Zampini PetscInt nleaves; 95228f4e0baSStefano Zampini PetscErrorCode ierr; 95328f4e0baSStefano Zampini 95428f4e0baSStefano Zampini PetscFunctionBegin; 9554f2d7cafSStefano Zampini if (matis->sf) PetscFunctionReturn(0); 95628f4e0baSStefano Zampini ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr); 9573bbff08aSStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr); 9584f2d7cafSStefano Zampini ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr); 9594f2d7cafSStefano Zampini ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr); 9603bbff08aSStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr); 9614f2d7cafSStefano Zampini ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr); 962a8116848SStefano Zampini if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */ 9633d996552SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr); 964a8116848SStefano Zampini ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr); 965a8116848SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr); 9663d996552SStefano Zampini ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr); 967a8116848SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr); 9683d996552SStefano Zampini ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr); 969a8116848SStefano Zampini } else { 970a8116848SStefano Zampini matis->csf = matis->sf; 971a8116848SStefano Zampini matis->csf_leafdata = matis->sf_leafdata; 972a8116848SStefano Zampini matis->csf_rootdata = matis->sf_rootdata; 973a8116848SStefano Zampini } 97428f4e0baSStefano Zampini PetscFunctionReturn(0); 97528f4e0baSStefano Zampini } 9762e1947a5SStefano Zampini 977eb82efa4SStefano Zampini /*@ 978a88811baSStefano Zampini MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix. 979a88811baSStefano Zampini 980a88811baSStefano Zampini Collective on MPI_Comm 981a88811baSStefano Zampini 982a88811baSStefano Zampini Input Parameters: 983a88811baSStefano Zampini + B - the matrix 984a88811baSStefano Zampini . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 985a88811baSStefano Zampini (same value is used for all local rows) 986a88811baSStefano Zampini . d_nnz - array containing the number of nonzeros in the various rows of the 987a88811baSStefano Zampini DIAGONAL portion of the local submatrix (possibly different for each row) 988a88811baSStefano Zampini or NULL, if d_nz is used to specify the nonzero structure. 989a88811baSStefano Zampini The size of this array is equal to the number of local rows, i.e 'm'. 990a88811baSStefano Zampini For matrices that will be factored, you must leave room for (and set) 991a88811baSStefano Zampini the diagonal entry even if it is zero. 992a88811baSStefano Zampini . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 993a88811baSStefano Zampini submatrix (same value is used for all local rows). 994a88811baSStefano Zampini - o_nnz - array containing the number of nonzeros in the various rows of the 995a88811baSStefano Zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 996a88811baSStefano Zampini each row) or NULL, if o_nz is used to specify the nonzero 997a88811baSStefano Zampini structure. The size of this array is equal to the number 998a88811baSStefano Zampini of local rows, i.e 'm'. 999a88811baSStefano Zampini 1000a88811baSStefano Zampini If the *_nnz parameter is given then the *_nz parameter is ignored 1001a88811baSStefano Zampini 1002a88811baSStefano Zampini Level: intermediate 1003a88811baSStefano Zampini 1004a88811baSStefano Zampini Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition 1005a88811baSStefano Zampini from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local 1006a88811baSStefano Zampini matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 1007a88811baSStefano Zampini 1008a88811baSStefano Zampini .keywords: matrix 1009a88811baSStefano Zampini 10103c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS 1011a88811baSStefano Zampini @*/ 10122e1947a5SStefano Zampini PetscErrorCode MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 10132e1947a5SStefano Zampini { 10142e1947a5SStefano Zampini PetscErrorCode ierr; 10152e1947a5SStefano Zampini 10162e1947a5SStefano Zampini PetscFunctionBegin; 10172e1947a5SStefano Zampini PetscValidHeaderSpecific(B,MAT_CLASSID,1); 10182e1947a5SStefano Zampini PetscValidType(B,1); 10192e1947a5SStefano Zampini ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr); 10202e1947a5SStefano Zampini PetscFunctionReturn(0); 10212e1947a5SStefano Zampini } 10222e1947a5SStefano Zampini 10237230de76SStefano Zampini static PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 10242e1947a5SStefano Zampini { 10252e1947a5SStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 102628f4e0baSStefano Zampini PetscInt bs,i,nlocalcols; 10272e1947a5SStefano Zampini PetscErrorCode ierr; 10282e1947a5SStefano Zampini 10292e1947a5SStefano Zampini PetscFunctionBegin; 10306c4ed002SBarry Smith if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping"); 1031cf0a3239SStefano Zampini ierr = MatISSetUpSF(B);CHKERRQ(ierr); 10324f2d7cafSStefano Zampini 10334f2d7cafSStefano Zampini if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz; 10344f2d7cafSStefano Zampini else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i]; 10354f2d7cafSStefano Zampini 10364f2d7cafSStefano Zampini if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz; 10374f2d7cafSStefano Zampini else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i]; 10384f2d7cafSStefano Zampini 103928f4e0baSStefano Zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 104028f4e0baSStefano Zampini ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr); 104128f4e0baSStefano Zampini ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr); 104228f4e0baSStefano Zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 10434f2d7cafSStefano Zampini 10444f2d7cafSStefano Zampini for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols); 104528f4e0baSStefano Zampini ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr); 10460f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE) 10470f2f62c7SStefano Zampini ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr); 10480f2f62c7SStefano Zampini #endif 10494f2d7cafSStefano Zampini 10504f2d7cafSStefano Zampini for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs; 105128f4e0baSStefano Zampini ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 10524f2d7cafSStefano Zampini 10534f2d7cafSStefano Zampini for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i; 105428f4e0baSStefano Zampini ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 10550f2f62c7SStefano Zampini 10560f2f62c7SStefano Zampini /* for other matrix types */ 10570f2f62c7SStefano Zampini ierr = MatSetUp(matis->A);CHKERRQ(ierr); 10582e1947a5SStefano Zampini PetscFunctionReturn(0); 10592e1947a5SStefano Zampini } 1060b4319ba4SBarry Smith 10613927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce) 10623927de2eSStefano Zampini { 10633927de2eSStefano Zampini Mat_IS *matis = (Mat_IS*)(A->data); 10643927de2eSStefano Zampini PetscInt *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership; 1065ecf5a873SStefano Zampini const PetscInt *global_indices_r,*global_indices_c; 10663927de2eSStefano Zampini PetscInt i,j,bs,rows,cols; 10673927de2eSStefano Zampini PetscInt lrows,lcols; 10683927de2eSStefano Zampini PetscInt local_rows,local_cols; 10693927de2eSStefano Zampini PetscMPIInt nsubdomains; 10703927de2eSStefano Zampini PetscBool isdense,issbaij; 10713927de2eSStefano Zampini PetscErrorCode ierr; 10723927de2eSStefano Zampini 10733927de2eSStefano Zampini PetscFunctionBegin; 10743927de2eSStefano Zampini ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr); 10753927de2eSStefano Zampini ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr); 10763927de2eSStefano Zampini ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 10773927de2eSStefano Zampini ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 10783927de2eSStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr); 10793927de2eSStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr); 1080ecf5a873SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr); 1081ecf5a873SStefano Zampini if (A->rmap->mapping != A->cmap->mapping) { 10827230de76SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr); 1083ecf5a873SStefano Zampini } else { 1084ecf5a873SStefano Zampini global_indices_c = global_indices_r; 1085ecf5a873SStefano Zampini } 1086ecf5a873SStefano Zampini 10873927de2eSStefano Zampini if (issbaij) { 10883927de2eSStefano Zampini ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr); 10893927de2eSStefano Zampini } 10903927de2eSStefano Zampini /* 1091ecf5a873SStefano Zampini An SF reduce is needed to sum up properly on shared rows. 10923927de2eSStefano Zampini Note that generally preallocation is not exact, since it overestimates nonzeros 10933927de2eSStefano Zampini */ 1094cf0a3239SStefano Zampini ierr = MatISSetUpSF(A);CHKERRQ(ierr); 10953927de2eSStefano Zampini ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr); 10963927de2eSStefano Zampini ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr); 10973927de2eSStefano Zampini /* All processes need to compute entire row ownership */ 10983927de2eSStefano Zampini ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr); 10993927de2eSStefano Zampini ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr); 11003927de2eSStefano Zampini for (i=0;i<nsubdomains;i++) { 11013927de2eSStefano Zampini for (j=mat_ranges[i];j<mat_ranges[i+1];j++) { 11023927de2eSStefano Zampini row_ownership[j] = i; 11033927de2eSStefano Zampini } 11043927de2eSStefano Zampini } 11057230de76SStefano Zampini ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr); 11063927de2eSStefano Zampini 11073927de2eSStefano Zampini /* 11083927de2eSStefano Zampini my_dnz and my_onz contains exact contribution to preallocation from each local mat 11093927de2eSStefano Zampini then, they will be summed up properly. This way, preallocation is always sufficient 11103927de2eSStefano Zampini */ 11113927de2eSStefano Zampini ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr); 11123927de2eSStefano Zampini /* preallocation as a MATAIJ */ 11133927de2eSStefano Zampini if (isdense) { /* special case for dense local matrices */ 11143927de2eSStefano Zampini for (i=0;i<local_rows;i++) { 111512dfadf8SStefano Zampini PetscInt owner = row_ownership[global_indices_r[i]]; 111612dfadf8SStefano Zampini for (j=0;j<local_cols;j++) { 1117ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[j]; 11183927de2eSStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 11193927de2eSStefano Zampini my_dnz[i] += 1; 11203927de2eSStefano Zampini } else { /* offdiag block */ 11213927de2eSStefano Zampini my_onz[i] += 1; 11223927de2eSStefano Zampini } 11233927de2eSStefano Zampini } 11243927de2eSStefano Zampini } 1125bb1015c3SStefano Zampini } else if (matis->A->ops->getrowij) { 1126bb1015c3SStefano Zampini const PetscInt *ii,*jj,*jptr; 1127bb1015c3SStefano Zampini PetscBool done; 1128bb1015c3SStefano Zampini ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr); 1129938e1ff8SStefano Zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ"); 1130bb1015c3SStefano Zampini jptr = jj; 1131bb1015c3SStefano Zampini for (i=0;i<local_rows;i++) { 1132bb1015c3SStefano Zampini PetscInt index_row = global_indices_r[i]; 1133bb1015c3SStefano Zampini for (j=0;j<ii[i+1]-ii[i];j++,jptr++) { 1134bb1015c3SStefano Zampini PetscInt owner = row_ownership[index_row]; 1135bb1015c3SStefano Zampini PetscInt index_col = global_indices_c[*jptr]; 1136bb1015c3SStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 1137bb1015c3SStefano Zampini my_dnz[i] += 1; 1138bb1015c3SStefano Zampini } else { /* offdiag block */ 1139bb1015c3SStefano Zampini my_onz[i] += 1; 1140bb1015c3SStefano Zampini } 1141bb1015c3SStefano Zampini /* same as before, interchanging rows and cols */ 1142bb1015c3SStefano Zampini if (issbaij && index_col != index_row) { 1143bb1015c3SStefano Zampini owner = row_ownership[index_col]; 1144bb1015c3SStefano Zampini if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 1145bb1015c3SStefano Zampini my_dnz[*jptr] += 1; 1146bb1015c3SStefano Zampini } else { 1147bb1015c3SStefano Zampini my_onz[*jptr] += 1; 1148bb1015c3SStefano Zampini } 1149bb1015c3SStefano Zampini } 1150bb1015c3SStefano Zampini } 1151bb1015c3SStefano Zampini } 1152bb1015c3SStefano Zampini ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr); 1153938e1ff8SStefano Zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ"); 1154bb1015c3SStefano Zampini } else { /* loop over rows and use MatGetRow */ 11553927de2eSStefano Zampini for (i=0;i<local_rows;i++) { 11563927de2eSStefano Zampini const PetscInt *cols; 1157ecf5a873SStefano Zampini PetscInt ncols,index_row = global_indices_r[i]; 11583927de2eSStefano Zampini ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 11593927de2eSStefano Zampini for (j=0;j<ncols;j++) { 11603927de2eSStefano Zampini PetscInt owner = row_ownership[index_row]; 1161ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[cols[j]]; 11623927de2eSStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 11633927de2eSStefano Zampini my_dnz[i] += 1; 11643927de2eSStefano Zampini } else { /* offdiag block */ 11653927de2eSStefano Zampini my_onz[i] += 1; 11663927de2eSStefano Zampini } 11673927de2eSStefano Zampini /* same as before, interchanging rows and cols */ 1168d9a9e74cSStefano Zampini if (issbaij && index_col != index_row) { 11693927de2eSStefano Zampini owner = row_ownership[index_col]; 11703927de2eSStefano Zampini if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 1171d9a9e74cSStefano Zampini my_dnz[cols[j]] += 1; 11723927de2eSStefano Zampini } else { 1173d9a9e74cSStefano Zampini my_onz[cols[j]] += 1; 11743927de2eSStefano Zampini } 11753927de2eSStefano Zampini } 11763927de2eSStefano Zampini } 11773927de2eSStefano Zampini ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 11783927de2eSStefano Zampini } 11793927de2eSStefano Zampini } 1180ecf5a873SStefano Zampini if (global_indices_c != global_indices_r) { 11817230de76SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr); 1182ecf5a873SStefano Zampini } 11834f619741Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr); 11843927de2eSStefano Zampini ierr = PetscFree(row_ownership);CHKERRQ(ierr); 1185ecf5a873SStefano Zampini 1186ecf5a873SStefano Zampini /* Reduce my_dnz and my_onz */ 11873927de2eSStefano Zampini if (maxreduce) { 11883927de2eSStefano Zampini ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 11893927de2eSStefano Zampini ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 1190bb1015c3SStefano Zampini ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 11913927de2eSStefano Zampini ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 11923927de2eSStefano Zampini } else { 11933927de2eSStefano Zampini ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 11943927de2eSStefano Zampini ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 1195bb1015c3SStefano Zampini ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 11963927de2eSStefano Zampini ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 11973927de2eSStefano Zampini } 11983927de2eSStefano Zampini ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr); 11993927de2eSStefano Zampini 12003927de2eSStefano Zampini /* Resize preallocation if overestimated */ 12013927de2eSStefano Zampini for (i=0;i<lrows;i++) { 12023927de2eSStefano Zampini dnz[i] = PetscMin(dnz[i],lcols); 12033927de2eSStefano Zampini onz[i] = PetscMin(onz[i],cols-lcols); 12043927de2eSStefano Zampini } 12051670daf9Sstefano_zampini 12061670daf9Sstefano_zampini /* Set preallocation */ 1207268753edSStefano Zampini ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr); 12083927de2eSStefano Zampini ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr); 12093927de2eSStefano Zampini for (i=0;i<lrows/bs;i++) { 12103927de2eSStefano Zampini dnz[i] = dnz[i*bs]/bs; 12113927de2eSStefano Zampini onz[i] = onz[i*bs]/bs; 12123927de2eSStefano Zampini } 1213268753edSStefano Zampini ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr); 12143927de2eSStefano Zampini ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 12153927de2eSStefano Zampini ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 12163927de2eSStefano Zampini ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 12173927de2eSStefano Zampini if (issbaij) { 12183927de2eSStefano Zampini ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr); 12193927de2eSStefano Zampini } 12203927de2eSStefano Zampini PetscFunctionReturn(0); 12213927de2eSStefano Zampini } 12223927de2eSStefano Zampini 12237230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M) 1224b7ce53b6SStefano Zampini { 1225b7ce53b6SStefano Zampini Mat_IS *matis = (Mat_IS*)(mat->data); 1226d9a9e74cSStefano Zampini Mat local_mat; 1227b7ce53b6SStefano Zampini /* info on mat */ 12283cfa4ea4SStefano Zampini PetscInt bs,rows,cols,lrows,lcols; 1229b7ce53b6SStefano Zampini PetscInt local_rows,local_cols; 1230b9ed4604SStefano Zampini PetscBool isseqdense,isseqsbaij,isseqaij,isseqbaij; 1231b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG) 1232b9ed4604SStefano Zampini PetscBool lb[4],bb[4]; 1233b9ed4604SStefano Zampini #endif 12347c03b4e8SStefano Zampini PetscMPIInt nsubdomains; 1235b7ce53b6SStefano Zampini /* values insertion */ 1236b7ce53b6SStefano Zampini PetscScalar *array; 1237b7ce53b6SStefano Zampini /* work */ 1238b7ce53b6SStefano Zampini PetscErrorCode ierr; 1239b7ce53b6SStefano Zampini 1240b7ce53b6SStefano Zampini PetscFunctionBegin; 1241b7ce53b6SStefano Zampini /* get info from mat */ 12427c03b4e8SStefano Zampini ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr); 12437c03b4e8SStefano Zampini if (nsubdomains == 1) { 12441670daf9Sstefano_zampini Mat B; 12451670daf9Sstefano_zampini IS rows,cols; 1246acdf38a7Sstefano_zampini IS irows,icols; 12471670daf9Sstefano_zampini const PetscInt *ridxs,*cidxs; 12481670daf9Sstefano_zampini 12491670daf9Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr); 12501670daf9Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr); 12511670daf9Sstefano_zampini ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr); 12521670daf9Sstefano_zampini ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr); 1253acdf38a7Sstefano_zampini ierr = ISSetPermutation(rows);CHKERRQ(ierr); 1254acdf38a7Sstefano_zampini ierr = ISSetPermutation(cols);CHKERRQ(ierr); 1255acdf38a7Sstefano_zampini ierr = ISInvertPermutation(rows,mat->rmap->n,&irows);CHKERRQ(ierr); 1256acdf38a7Sstefano_zampini ierr = ISInvertPermutation(cols,mat->cmap->n,&icols);CHKERRQ(ierr); 1257268753edSStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr); 1258268753edSStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr); 1259acdf38a7Sstefano_zampini ierr = ISDestroy(&cols);CHKERRQ(ierr); 1260acdf38a7Sstefano_zampini ierr = ISDestroy(&rows);CHKERRQ(ierr); 12616104e0f1Sstefano_zampini ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr); 12627dae84e0SHong Zhang ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr); 1263acdf38a7Sstefano_zampini ierr = MatDestroy(&B);CHKERRQ(ierr); 1264acdf38a7Sstefano_zampini ierr = ISDestroy(&icols);CHKERRQ(ierr); 1265acdf38a7Sstefano_zampini ierr = ISDestroy(&irows);CHKERRQ(ierr); 12667c03b4e8SStefano Zampini PetscFunctionReturn(0); 12677c03b4e8SStefano Zampini } 1268b7ce53b6SStefano Zampini ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr); 1269b7ce53b6SStefano Zampini ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); 12703cfa4ea4SStefano Zampini ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr); 1271b7ce53b6SStefano Zampini ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 1272b9ed4604SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr); 12734099cc6bSBarry Smith ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 1274b9ed4604SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr); 1275b9ed4604SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr); 1276b9ed4604SStefano Zampini if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name); 1277b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG) 1278b9ed4604SStefano Zampini lb[0] = isseqdense; 1279b9ed4604SStefano Zampini lb[1] = isseqaij; 1280b9ed4604SStefano Zampini lb[2] = isseqbaij; 1281b9ed4604SStefano Zampini lb[3] = isseqsbaij; 1282b9ed4604SStefano Zampini ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1283b9ed4604SStefano Zampini if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type"); 1284b9ed4604SStefano Zampini #endif 1285b7ce53b6SStefano Zampini 1286b7ce53b6SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 12873927de2eSStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr); 12883cfa4ea4SStefano Zampini ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr); 1289b9ed4604SStefano Zampini if (!isseqsbaij) { 1290b9ed4604SStefano Zampini ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr); 1291b9ed4604SStefano Zampini } else { 1292b9ed4604SStefano Zampini ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr); 1293b9ed4604SStefano Zampini } 1294d59cf9ebSStefano Zampini ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr); 12953927de2eSStefano Zampini ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr); 1296b7ce53b6SStefano Zampini } else { 12973cfa4ea4SStefano Zampini PetscInt mbs,mrows,mcols,mlrows,mlcols; 1298b7ce53b6SStefano Zampini /* some checks */ 1299b7ce53b6SStefano Zampini ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr); 1300b7ce53b6SStefano Zampini ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr); 13013cfa4ea4SStefano Zampini ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr); 13026c4ed002SBarry Smith if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows); 13036c4ed002SBarry Smith if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols); 13046c4ed002SBarry Smith if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows); 13056c4ed002SBarry Smith if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols); 13066c4ed002SBarry Smith if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs); 1307b7ce53b6SStefano Zampini ierr = MatZeroEntries(*M);CHKERRQ(ierr); 1308b7ce53b6SStefano Zampini } 1309d9a9e74cSStefano Zampini 1310b9ed4604SStefano Zampini if (isseqsbaij) { 1311d9a9e74cSStefano Zampini ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr); 1312d9a9e74cSStefano Zampini } else { 1313d9a9e74cSStefano Zampini ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 1314d9a9e74cSStefano Zampini local_mat = matis->A; 1315d9a9e74cSStefano Zampini } 1316686e3a49SStefano Zampini 1317b7ce53b6SStefano Zampini /* Set values */ 1318ecf5a873SStefano Zampini ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr); 1319b9ed4604SStefano Zampini if (isseqdense) { /* special case for dense local matrices */ 132065066ba5SStefano Zampini PetscInt i,*dummy; 1321ecf5a873SStefano Zampini 132265066ba5SStefano Zampini ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr); 132365066ba5SStefano Zampini for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i; 1324b7ce53b6SStefano Zampini ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 1325d9a9e74cSStefano Zampini ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr); 132665066ba5SStefano Zampini ierr = MatSetValuesLocal(*M,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr); 1327d9a9e74cSStefano Zampini ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr); 132865066ba5SStefano Zampini ierr = PetscFree(dummy);CHKERRQ(ierr); 1329686e3a49SStefano Zampini } else if (isseqaij) { 1330ecf5a873SStefano Zampini PetscInt i,nvtxs,*xadj,*adjncy; 1331686e3a49SStefano Zampini PetscBool done; 1332686e3a49SStefano Zampini 1333d9a9e74cSStefano Zampini ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 1334938e1ff8SStefano Zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ"); 1335d9a9e74cSStefano Zampini ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr); 1336686e3a49SStefano Zampini for (i=0;i<nvtxs;i++) { 1337ecf5a873SStefano Zampini ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr); 1338686e3a49SStefano Zampini } 1339d9a9e74cSStefano Zampini ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 1340938e1ff8SStefano Zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ"); 1341d9a9e74cSStefano Zampini ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr); 1342686e3a49SStefano Zampini } else { /* very basic values insertion for all other matrix types */ 1343ecf5a873SStefano Zampini PetscInt i; 1344c0962df8SStefano Zampini 1345686e3a49SStefano Zampini for (i=0;i<local_rows;i++) { 1346686e3a49SStefano Zampini PetscInt j; 1347ecf5a873SStefano Zampini const PetscInt *local_indices_cols; 1348686e3a49SStefano Zampini 1349ecf5a873SStefano Zampini ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr); 1350ecf5a873SStefano Zampini ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr); 1351ecf5a873SStefano Zampini ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr); 1352686e3a49SStefano Zampini } 1353b7ce53b6SStefano Zampini } 1354b7ce53b6SStefano Zampini ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1355d9a9e74cSStefano Zampini ierr = MatDestroy(&local_mat);CHKERRQ(ierr); 1356b7ce53b6SStefano Zampini ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1357b9ed4604SStefano Zampini if (isseqdense) { 1358b7ce53b6SStefano Zampini ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr); 1359b7ce53b6SStefano Zampini } 1360b7ce53b6SStefano Zampini PetscFunctionReturn(0); 1361b7ce53b6SStefano Zampini } 1362b7ce53b6SStefano Zampini 1363b7ce53b6SStefano Zampini /*@ 1364b7ce53b6SStefano Zampini MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format 1365b7ce53b6SStefano Zampini 1366b7ce53b6SStefano Zampini Input Parameter: 1367b7ce53b6SStefano Zampini . mat - the matrix (should be of type MATIS) 1368b7ce53b6SStefano Zampini . reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 1369b7ce53b6SStefano Zampini 1370b7ce53b6SStefano Zampini Output Parameter: 1371b7ce53b6SStefano Zampini . newmat - the matrix in AIJ format 1372b7ce53b6SStefano Zampini 1373b7ce53b6SStefano Zampini Level: developer 1374b7ce53b6SStefano Zampini 1375eb82efa4SStefano Zampini Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested. 1376b7ce53b6SStefano Zampini 1377b7ce53b6SStefano Zampini .seealso: MATIS 1378b7ce53b6SStefano Zampini @*/ 1379b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat) 1380b7ce53b6SStefano Zampini { 1381b7ce53b6SStefano Zampini PetscErrorCode ierr; 1382b7ce53b6SStefano Zampini 1383b7ce53b6SStefano Zampini PetscFunctionBegin; 1384b7ce53b6SStefano Zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1385b7ce53b6SStefano Zampini PetscValidLogicalCollectiveEnum(mat,reuse,2); 1386b7ce53b6SStefano Zampini PetscValidPointer(newmat,3); 1387b7ce53b6SStefano Zampini if (reuse != MAT_INITIAL_MATRIX) { 1388b7ce53b6SStefano Zampini PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3); 1389b7ce53b6SStefano Zampini PetscCheckSameComm(mat,1,*newmat,3); 13906c4ed002SBarry Smith if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix"); 1391b7ce53b6SStefano Zampini } 1392b7ce53b6SStefano Zampini ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr); 1393b7ce53b6SStefano Zampini PetscFunctionReturn(0); 1394b7ce53b6SStefano Zampini } 1395b7ce53b6SStefano Zampini 1396ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat) 1397ad6194a2SStefano Zampini { 1398ad6194a2SStefano Zampini PetscErrorCode ierr; 1399ad6194a2SStefano Zampini Mat_IS *matis = (Mat_IS*)(mat->data); 1400ad6194a2SStefano Zampini PetscInt bs,m,n,M,N; 1401ad6194a2SStefano Zampini Mat B,localmat; 1402ad6194a2SStefano Zampini 1403ad6194a2SStefano Zampini PetscFunctionBegin; 1404ad6194a2SStefano Zampini ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); 1405ad6194a2SStefano Zampini ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 1406ad6194a2SStefano Zampini ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr); 1407e176bc59SStefano Zampini ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr); 1408ad6194a2SStefano Zampini ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr); 1409ad6194a2SStefano Zampini ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr); 1410b3317aa8SStefano Zampini ierr = MatDestroy(&localmat);CHKERRQ(ierr); 1411ad6194a2SStefano Zampini ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1412ad6194a2SStefano Zampini ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1413ad6194a2SStefano Zampini *newmat = B; 1414ad6194a2SStefano Zampini PetscFunctionReturn(0); 1415ad6194a2SStefano Zampini } 1416ad6194a2SStefano Zampini 1417a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool *flg) 141869796d55SStefano Zampini { 141969796d55SStefano Zampini PetscErrorCode ierr; 142069796d55SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 142169796d55SStefano Zampini PetscBool local_sym; 142269796d55SStefano Zampini 142369796d55SStefano Zampini PetscFunctionBegin; 142469796d55SStefano Zampini ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr); 1425b2566f29SBarry Smith ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 142669796d55SStefano Zampini PetscFunctionReturn(0); 142769796d55SStefano Zampini } 142869796d55SStefano Zampini 1429a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg) 143069796d55SStefano Zampini { 143169796d55SStefano Zampini PetscErrorCode ierr; 143269796d55SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 143369796d55SStefano Zampini PetscBool local_sym; 143469796d55SStefano Zampini 143569796d55SStefano Zampini PetscFunctionBegin; 143669796d55SStefano Zampini ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr); 1437b2566f29SBarry Smith ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 143869796d55SStefano Zampini PetscFunctionReturn(0); 143969796d55SStefano Zampini } 144069796d55SStefano Zampini 144145471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool *flg) 144245471136SStefano Zampini { 144345471136SStefano Zampini PetscErrorCode ierr; 144445471136SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 144545471136SStefano Zampini PetscBool local_sym; 144645471136SStefano Zampini 144745471136SStefano Zampini PetscFunctionBegin; 144845471136SStefano Zampini if (A->rmap->mapping != A->cmap->mapping) { 144945471136SStefano Zampini *flg = PETSC_FALSE; 145045471136SStefano Zampini PetscFunctionReturn(0); 145145471136SStefano Zampini } 145245471136SStefano Zampini ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr); 145345471136SStefano Zampini ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 145445471136SStefano Zampini PetscFunctionReturn(0); 145545471136SStefano Zampini } 145645471136SStefano Zampini 1457a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A) 1458b4319ba4SBarry Smith { 1459dfbe8321SBarry Smith PetscErrorCode ierr; 1460b4319ba4SBarry Smith Mat_IS *b = (Mat_IS*)A->data; 1461b4319ba4SBarry Smith 1462b4319ba4SBarry Smith PetscFunctionBegin; 14636bf464f9SBarry Smith ierr = MatDestroy(&b->A);CHKERRQ(ierr); 1464e176bc59SStefano Zampini ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr); 1465e176bc59SStefano Zampini ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr); 14666bf464f9SBarry Smith ierr = VecDestroy(&b->x);CHKERRQ(ierr); 14676bf464f9SBarry Smith ierr = VecDestroy(&b->y);CHKERRQ(ierr); 14683fd1c9e7SStefano Zampini ierr = VecDestroy(&b->counter);CHKERRQ(ierr); 1469a8116848SStefano Zampini ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr); 1470a8116848SStefano Zampini ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr); 1471a8116848SStefano Zampini if (b->sf != b->csf) { 1472a8116848SStefano Zampini ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr); 1473a8116848SStefano Zampini ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr); 1474a8116848SStefano Zampini } 147528f4e0baSStefano Zampini ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr); 147628f4e0baSStefano Zampini ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr); 1477bf0cc555SLisandro Dalcin ierr = PetscFree(A->data);CHKERRQ(ierr); 1478dbd8c25aSHong Zhang ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 1479bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr); 1480b7ce53b6SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr); 1481b7ce53b6SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr); 14822e1947a5SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr); 1483cf0a3239SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr); 1484b4319ba4SBarry Smith PetscFunctionReturn(0); 1485b4319ba4SBarry Smith } 1486b4319ba4SBarry Smith 1487a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y) 1488b4319ba4SBarry Smith { 1489dfbe8321SBarry Smith PetscErrorCode ierr; 1490b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1491b4319ba4SBarry Smith PetscScalar zero = 0.0; 1492b4319ba4SBarry Smith 1493b4319ba4SBarry Smith PetscFunctionBegin; 1494b4319ba4SBarry Smith /* scatter the global vector x into the local work vector */ 1495e176bc59SStefano Zampini ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1496e176bc59SStefano Zampini ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1497b4319ba4SBarry Smith 1498b4319ba4SBarry Smith /* multiply the local matrix */ 1499b4319ba4SBarry Smith ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr); 1500b4319ba4SBarry Smith 1501b4319ba4SBarry Smith /* scatter product back into global memory */ 15022dcb1b2aSMatthew Knepley ierr = VecSet(y,zero);CHKERRQ(ierr); 1503e176bc59SStefano Zampini ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1504e176bc59SStefano Zampini ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1505b4319ba4SBarry Smith PetscFunctionReturn(0); 1506b4319ba4SBarry Smith } 1507b4319ba4SBarry Smith 1508a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 15092e74eeadSLisandro Dalcin { 1510650997f4SStefano Zampini Vec temp_vec; 15112e74eeadSLisandro Dalcin PetscErrorCode ierr; 15122e74eeadSLisandro Dalcin 15132e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 1514650997f4SStefano Zampini if (v3 != v2) { 1515650997f4SStefano Zampini ierr = MatMult(A,v1,v3);CHKERRQ(ierr); 1516650997f4SStefano Zampini ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 1517650997f4SStefano Zampini } else { 1518650997f4SStefano Zampini ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 1519650997f4SStefano Zampini ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr); 1520650997f4SStefano Zampini ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 1521650997f4SStefano Zampini ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 1522650997f4SStefano Zampini ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 1523650997f4SStefano Zampini } 15242e74eeadSLisandro Dalcin PetscFunctionReturn(0); 15252e74eeadSLisandro Dalcin } 15262e74eeadSLisandro Dalcin 1527a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x) 15282e74eeadSLisandro Dalcin { 15292e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 15302e74eeadSLisandro Dalcin PetscErrorCode ierr; 15312e74eeadSLisandro Dalcin 1532e176bc59SStefano Zampini PetscFunctionBegin; 15332e74eeadSLisandro Dalcin /* scatter the global vector x into the local work vector */ 1534e176bc59SStefano Zampini ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1535e176bc59SStefano Zampini ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 15362e74eeadSLisandro Dalcin 15372e74eeadSLisandro Dalcin /* multiply the local matrix */ 1538e176bc59SStefano Zampini ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr); 15392e74eeadSLisandro Dalcin 15402e74eeadSLisandro Dalcin /* scatter product back into global vector */ 1541e176bc59SStefano Zampini ierr = VecSet(x,0);CHKERRQ(ierr); 1542e176bc59SStefano Zampini ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1543e176bc59SStefano Zampini ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 15442e74eeadSLisandro Dalcin PetscFunctionReturn(0); 15452e74eeadSLisandro Dalcin } 15462e74eeadSLisandro Dalcin 1547a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 15482e74eeadSLisandro Dalcin { 1549650997f4SStefano Zampini Vec temp_vec; 15502e74eeadSLisandro Dalcin PetscErrorCode ierr; 15512e74eeadSLisandro Dalcin 15522e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 1553650997f4SStefano Zampini if (v3 != v2) { 1554650997f4SStefano Zampini ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr); 1555650997f4SStefano Zampini ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 1556650997f4SStefano Zampini } else { 1557650997f4SStefano Zampini ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 1558650997f4SStefano Zampini ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr); 1559650997f4SStefano Zampini ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 1560650997f4SStefano Zampini ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 1561650997f4SStefano Zampini ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 1562650997f4SStefano Zampini } 15632e74eeadSLisandro Dalcin PetscFunctionReturn(0); 15642e74eeadSLisandro Dalcin } 15652e74eeadSLisandro Dalcin 1566a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer) 1567b4319ba4SBarry Smith { 1568b4319ba4SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 1569dfbe8321SBarry Smith PetscErrorCode ierr; 1570b4319ba4SBarry Smith PetscViewer sviewer; 1571ee2491ecSStefano Zampini PetscBool isascii,view = PETSC_TRUE; 1572b4319ba4SBarry Smith 1573b4319ba4SBarry Smith PetscFunctionBegin; 1574ee2491ecSStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 1575ee2491ecSStefano Zampini if (isascii) { 1576ee2491ecSStefano Zampini PetscViewerFormat format; 1577ee2491ecSStefano Zampini 1578ee2491ecSStefano Zampini ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 1579ee2491ecSStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE; 1580ee2491ecSStefano Zampini } 1581ee2491ecSStefano Zampini if (!view) PetscFunctionReturn(0); 15823f08860eSBarry Smith ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 1583b4319ba4SBarry Smith ierr = MatView(a->A,sviewer);CHKERRQ(ierr); 15843f08860eSBarry Smith ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 15856e520ac8SStefano Zampini ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1586b4319ba4SBarry Smith PetscFunctionReturn(0); 1587b4319ba4SBarry Smith } 1588b4319ba4SBarry Smith 1589a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping) 1590b4319ba4SBarry Smith { 1591dfbe8321SBarry Smith PetscErrorCode ierr; 1592e176bc59SStefano Zampini PetscInt nr,rbs,nc,cbs; 1593b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1594b4319ba4SBarry Smith IS from,to; 1595e176bc59SStefano Zampini Vec cglobal,rglobal; 1596b4319ba4SBarry Smith 1597b4319ba4SBarry Smith PetscFunctionBegin; 1598784ac674SJed Brown PetscCheckSameComm(A,1,rmapping,2); 1599e176bc59SStefano Zampini PetscCheckSameComm(A,1,cmapping,3); 16003bbff08aSStefano Zampini /* Destroy any previous data */ 160170cf5478SStefano Zampini ierr = VecDestroy(&is->x);CHKERRQ(ierr); 160270cf5478SStefano Zampini ierr = VecDestroy(&is->y);CHKERRQ(ierr); 16033fd1c9e7SStefano Zampini ierr = VecDestroy(&is->counter);CHKERRQ(ierr); 1604e176bc59SStefano Zampini ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr); 1605e176bc59SStefano Zampini ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr); 16061c47cb0fSStefano Zampini ierr = MatDestroy(&is->A);CHKERRQ(ierr); 1607872cf891SStefano Zampini if (is->csf != is->sf) { 1608872cf891SStefano Zampini ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr); 1609872cf891SStefano Zampini ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr); 1610872cf891SStefano Zampini } 161128f4e0baSStefano Zampini ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr); 161228f4e0baSStefano Zampini ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr); 16133bbff08aSStefano Zampini 16143bbff08aSStefano Zampini /* Setup Layout and set local to global maps */ 1615fc27028aSStefano Zampini ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 1616fc27028aSStefano Zampini ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 1617fa7f1dd8SStefano Zampini ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr); 1618fa7f1dd8SStefano Zampini ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr); 1619b4319ba4SBarry Smith 1620b4319ba4SBarry Smith /* Create the local matrix A */ 1621e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr); 1622e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr); 1623e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr); 1624e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr); 1625f69a0ea3SMatthew Knepley ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr); 1626e176bc59SStefano Zampini ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr); 1627e176bc59SStefano Zampini ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr); 1628e176bc59SStefano Zampini ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr); 1629ff130e51SJed Brown ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr); 1630ff130e51SJed Brown ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr); 1631b4319ba4SBarry Smith ierr = MatSetFromOptions(is->A);CHKERRQ(ierr); 1632c77832edSStefano Zampini ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr); 1633c77832edSStefano Zampini ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr); 1634b4319ba4SBarry Smith 1635f26d0771SStefano Zampini if (!is->islocalref) { /* setup scatters and local vectors for MatMult */ 1636b4319ba4SBarry Smith /* Create the local work vectors */ 16373bbff08aSStefano Zampini ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr); 1638b4319ba4SBarry Smith 1639e176bc59SStefano Zampini /* setup the global to local scatters */ 1640e176bc59SStefano Zampini ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr); 1641e176bc59SStefano Zampini ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr); 1642784ac674SJed Brown ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr); 1643e176bc59SStefano Zampini ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr); 1644e176bc59SStefano Zampini if (rmapping != cmapping) { 1645e176bc59SStefano Zampini ierr = ISDestroy(&to);CHKERRQ(ierr); 1646e176bc59SStefano Zampini ierr = ISDestroy(&from);CHKERRQ(ierr); 1647e176bc59SStefano Zampini ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr); 1648e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr); 1649e176bc59SStefano Zampini ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr); 1650e176bc59SStefano Zampini } else { 1651e176bc59SStefano Zampini ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr); 1652e176bc59SStefano Zampini is->cctx = is->rctx; 1653e176bc59SStefano Zampini } 16543fd1c9e7SStefano Zampini 16553fd1c9e7SStefano Zampini /* interface counter vector (local) */ 16563fd1c9e7SStefano Zampini ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr); 16573fd1c9e7SStefano Zampini ierr = VecSet(is->y,1.);CHKERRQ(ierr); 16583fd1c9e7SStefano Zampini ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 16593fd1c9e7SStefano Zampini ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 16603fd1c9e7SStefano Zampini ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 16613fd1c9e7SStefano Zampini ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 16623fd1c9e7SStefano Zampini 16633fd1c9e7SStefano Zampini /* free workspace */ 1664e176bc59SStefano Zampini ierr = VecDestroy(&rglobal);CHKERRQ(ierr); 1665e176bc59SStefano Zampini ierr = VecDestroy(&cglobal);CHKERRQ(ierr); 16666bf464f9SBarry Smith ierr = ISDestroy(&to);CHKERRQ(ierr); 16676bf464f9SBarry Smith ierr = ISDestroy(&from);CHKERRQ(ierr); 1668f26d0771SStefano Zampini } 166948ff6bf3SStefano Zampini ierr = MatSetUp(A);CHKERRQ(ierr); 1670b4319ba4SBarry Smith PetscFunctionReturn(0); 1671b4319ba4SBarry Smith } 1672b4319ba4SBarry Smith 1673a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 16742e74eeadSLisandro Dalcin { 16752e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)mat->data; 16762e74eeadSLisandro Dalcin PetscErrorCode ierr; 167797563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 167897563a80SStefano Zampini PetscInt i,zm,zn; 167997563a80SStefano Zampini #endif 1680f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 16812e74eeadSLisandro Dalcin 16822e74eeadSLisandro Dalcin PetscFunctionBegin; 16832e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG) 1684f26d0771SStefano Zampini if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n); 168597563a80SStefano Zampini /* count negative indices */ 168697563a80SStefano Zampini for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++; 168797563a80SStefano Zampini for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++; 16882e74eeadSLisandro Dalcin #endif 168997563a80SStefano Zampini ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr); 169097563a80SStefano Zampini ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr); 169197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 169297563a80SStefano Zampini /* count negative indices (should be the same as before) */ 169397563a80SStefano Zampini for (i=0;i<m;i++) if (rows_l[i] < 0) zm--; 169497563a80SStefano Zampini for (i=0;i<n;i++) if (cols_l[i] < 0) zn--; 1695b4f971dfSStefano Zampini if (!is->A->rmap->mapping && zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS"); 1696b4f971dfSStefano Zampini if (!is->A->cmap->mapping && zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS"); 169797563a80SStefano Zampini #endif 16982e74eeadSLisandro Dalcin ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 16992e74eeadSLisandro Dalcin PetscFunctionReturn(0); 17002e74eeadSLisandro Dalcin } 17012e74eeadSLisandro Dalcin 1702a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 170397563a80SStefano Zampini { 170497563a80SStefano Zampini Mat_IS *is = (Mat_IS*)mat->data; 170597563a80SStefano Zampini PetscErrorCode ierr; 170697563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 170797563a80SStefano Zampini PetscInt i,zm,zn; 170897563a80SStefano Zampini #endif 1709f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 171097563a80SStefano Zampini 171197563a80SStefano Zampini PetscFunctionBegin; 171297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 1713f26d0771SStefano Zampini if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n); 171497563a80SStefano Zampini /* count negative indices */ 171597563a80SStefano Zampini for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++; 171697563a80SStefano Zampini for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++; 171797563a80SStefano Zampini #endif 171897563a80SStefano Zampini ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr); 171997563a80SStefano Zampini ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr); 172097563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 172197563a80SStefano Zampini /* count negative indices (should be the same as before) */ 172297563a80SStefano Zampini for (i=0;i<m;i++) if (rows_l[i] < 0) zm--; 172397563a80SStefano Zampini for (i=0;i<n;i++) if (cols_l[i] < 0) zn--; 1724b4f971dfSStefano Zampini if (!is->A->rmap->mapping && zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS"); 1725b4f971dfSStefano Zampini if (!is->A->cmap->mapping && zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS"); 172697563a80SStefano Zampini #endif 1727d59cf9ebSStefano Zampini ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 172897563a80SStefano Zampini PetscFunctionReturn(0); 172997563a80SStefano Zampini } 173097563a80SStefano Zampini 1731a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1732b4319ba4SBarry Smith { 1733dfbe8321SBarry Smith PetscErrorCode ierr; 1734b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1735b4319ba4SBarry Smith 1736b4319ba4SBarry Smith PetscFunctionBegin; 1737b4f971dfSStefano Zampini if (is->A->rmap->mapping) { 1738872cf891SStefano Zampini ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 1739872cf891SStefano Zampini } else { 1740b4319ba4SBarry Smith ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 1741872cf891SStefano Zampini } 1742b4319ba4SBarry Smith PetscFunctionReturn(0); 1743b4319ba4SBarry Smith } 1744b4319ba4SBarry Smith 1745a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1746f0006bf2SLisandro Dalcin { 1747f0006bf2SLisandro Dalcin PetscErrorCode ierr; 1748f0006bf2SLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 1749f0006bf2SLisandro Dalcin 1750f0006bf2SLisandro Dalcin PetscFunctionBegin; 1751b4f971dfSStefano Zampini if (is->A->rmap->mapping) { 1752b4f971dfSStefano Zampini #if defined(PETSC_USE_DEBUG) 1753b4f971dfSStefano Zampini PetscInt ibs,bs; 1754b4f971dfSStefano Zampini 1755b4f971dfSStefano Zampini ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr); 1756b4f971dfSStefano Zampini ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr); 1757b4f971dfSStefano Zampini if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs); 1758b4f971dfSStefano Zampini #endif 1759b4f971dfSStefano Zampini ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 1760b4f971dfSStefano Zampini } else { 1761f0006bf2SLisandro Dalcin ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 1762b4f971dfSStefano Zampini } 1763f0006bf2SLisandro Dalcin PetscFunctionReturn(0); 1764f0006bf2SLisandro Dalcin } 1765f0006bf2SLisandro Dalcin 1766f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns) 1767f0ae7da4SStefano Zampini { 1768f0ae7da4SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 1769f0ae7da4SStefano Zampini PetscErrorCode ierr; 1770f0ae7da4SStefano Zampini 1771f0ae7da4SStefano Zampini PetscFunctionBegin; 1772f0ae7da4SStefano Zampini if (!n) { 1773f0ae7da4SStefano Zampini is->pure_neumann = PETSC_TRUE; 1774f0ae7da4SStefano Zampini } else { 1775f0ae7da4SStefano Zampini PetscInt i; 1776f0ae7da4SStefano Zampini is->pure_neumann = PETSC_FALSE; 1777f0ae7da4SStefano Zampini 1778f0ae7da4SStefano Zampini if (columns) { 1779f0ae7da4SStefano Zampini ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 1780f0ae7da4SStefano Zampini } else { 1781f0ae7da4SStefano Zampini ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 1782f0ae7da4SStefano Zampini } 1783f0ae7da4SStefano Zampini if (diag != 0.) { 1784f0ae7da4SStefano Zampini const PetscScalar *array; 1785f0ae7da4SStefano Zampini ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr); 1786f0ae7da4SStefano Zampini for (i=0; i<n; i++) { 1787f0ae7da4SStefano Zampini ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr); 1788f0ae7da4SStefano Zampini } 1789f0ae7da4SStefano Zampini ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr); 1790f0ae7da4SStefano Zampini } 1791f0ae7da4SStefano Zampini ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1792f0ae7da4SStefano Zampini ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1793f0ae7da4SStefano Zampini } 1794f0ae7da4SStefano Zampini PetscFunctionReturn(0); 1795f0ae7da4SStefano Zampini } 1796f0ae7da4SStefano Zampini 1797f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns) 17982e74eeadSLisandro Dalcin { 17996e520ac8SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 18006e520ac8SStefano Zampini PetscInt nr,nl,len,i; 18016e520ac8SStefano Zampini PetscInt *lrows; 18022e74eeadSLisandro Dalcin PetscErrorCode ierr; 18032e74eeadSLisandro Dalcin 18042e74eeadSLisandro Dalcin PetscFunctionBegin; 1805f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG) 1806f0ae7da4SStefano Zampini if (columns || diag != 0. || (x && b)) { 1807f0ae7da4SStefano Zampini PetscBool cong; 180826b0207aSStefano Zampini 1809f0ae7da4SStefano Zampini ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr); 181026b0207aSStefano Zampini cong = (PetscBool)(cong && matis->sf == matis->csf); 1811268753edSStefano Zampini if (!cong && columns) SETERRQ(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"); 1812268753edSStefano Zampini if (!cong && diag != 0.) SETERRQ(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"); 1813268753edSStefano Zampini if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent, and the l2g maps be the same"); 1814f0ae7da4SStefano Zampini } 1815f0ae7da4SStefano Zampini #endif 18166e520ac8SStefano Zampini /* get locally owned rows */ 1817f0ae7da4SStefano Zampini ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr); 18186e520ac8SStefano Zampini /* fix right hand side if needed */ 18196e520ac8SStefano Zampini if (x && b) { 18206e520ac8SStefano Zampini const PetscScalar *xx; 18216e520ac8SStefano Zampini PetscScalar *bb; 18226e520ac8SStefano Zampini 18236e520ac8SStefano Zampini ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr); 18246e520ac8SStefano Zampini ierr = VecGetArray(b, &bb);CHKERRQ(ierr); 18256e520ac8SStefano Zampini for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]]; 18266e520ac8SStefano Zampini ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr); 18276e520ac8SStefano Zampini ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr); 18282e74eeadSLisandro Dalcin } 18296e520ac8SStefano Zampini /* get rows associated to the local matrices */ 18303d996552SStefano Zampini ierr = MatISSetUpSF(A);CHKERRQ(ierr); 18316e520ac8SStefano Zampini ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr); 18326e520ac8SStefano Zampini ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr); 18336e520ac8SStefano Zampini ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 18346e520ac8SStefano Zampini for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1; 18356e520ac8SStefano Zampini ierr = PetscFree(lrows);CHKERRQ(ierr); 18366e520ac8SStefano Zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 18376e520ac8SStefano Zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 18386e520ac8SStefano Zampini ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr); 18396e520ac8SStefano Zampini for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i; 1840f0ae7da4SStefano Zampini ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr); 18416e520ac8SStefano Zampini ierr = PetscFree(lrows);CHKERRQ(ierr); 18422e74eeadSLisandro Dalcin PetscFunctionReturn(0); 18432e74eeadSLisandro Dalcin } 18442e74eeadSLisandro Dalcin 1845f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1846b4319ba4SBarry Smith { 1847dfbe8321SBarry Smith PetscErrorCode ierr; 1848b4319ba4SBarry Smith 1849b4319ba4SBarry Smith PetscFunctionBegin; 1850f0ae7da4SStefano Zampini ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr); 1851f0ae7da4SStefano Zampini PetscFunctionReturn(0); 1852f0ae7da4SStefano Zampini } 18532205254eSKarl Rupp 1854f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1855f0ae7da4SStefano Zampini { 1856f0ae7da4SStefano Zampini PetscErrorCode ierr; 1857f0ae7da4SStefano Zampini 1858f0ae7da4SStefano Zampini PetscFunctionBegin; 1859f0ae7da4SStefano Zampini ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr); 1860b4319ba4SBarry Smith PetscFunctionReturn(0); 1861b4319ba4SBarry Smith } 1862b4319ba4SBarry Smith 1863a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type) 1864b4319ba4SBarry Smith { 1865b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1866dfbe8321SBarry Smith PetscErrorCode ierr; 1867b4319ba4SBarry Smith 1868b4319ba4SBarry Smith PetscFunctionBegin; 1869b4319ba4SBarry Smith ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr); 1870b4319ba4SBarry Smith PetscFunctionReturn(0); 1871b4319ba4SBarry Smith } 1872b4319ba4SBarry Smith 1873a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type) 1874b4319ba4SBarry Smith { 1875b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1876dfbe8321SBarry Smith PetscErrorCode ierr; 1877b4319ba4SBarry Smith 1878b4319ba4SBarry Smith PetscFunctionBegin; 1879b4319ba4SBarry Smith ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr); 1880872cf891SStefano Zampini /* fix for local empty rows/cols */ 1881872cf891SStefano Zampini if (is->locempty && type == MAT_FINAL_ASSEMBLY) { 1882872cf891SStefano Zampini Mat newlA; 1883872cf891SStefano Zampini ISLocalToGlobalMapping l2g; 1884872cf891SStefano Zampini IS tis; 1885872cf891SStefano Zampini const PetscScalar *v; 1886872cf891SStefano Zampini PetscInt i,n,cf,*loce,*locf; 1887872cf891SStefano Zampini PetscBool sym; 1888872cf891SStefano Zampini 1889872cf891SStefano Zampini ierr = MatGetRowMaxAbs(is->A,is->y,NULL);CHKERRQ(ierr); 1890872cf891SStefano Zampini ierr = MatIsSymmetric(is->A,PETSC_SMALL,&sym);CHKERRQ(ierr); 1891872cf891SStefano Zampini if (!sym) SETERRQ(PetscObjectComm((PetscObject)is->A),PETSC_ERR_SUP,"Not yet implemented for unsymmetric case"); 1892872cf891SStefano Zampini ierr = VecGetLocalSize(is->y,&n);CHKERRQ(ierr); 1893872cf891SStefano Zampini ierr = PetscMalloc1(n,&loce);CHKERRQ(ierr); 1894872cf891SStefano Zampini ierr = PetscMalloc1(n,&locf);CHKERRQ(ierr); 1895872cf891SStefano Zampini ierr = VecGetArrayRead(is->y,&v);CHKERRQ(ierr); 1896872cf891SStefano Zampini for (i=0,cf=0;i<n;i++) { 1897872cf891SStefano Zampini if (v[i] == 0.0) { 1898872cf891SStefano Zampini loce[i] = -1; 1899872cf891SStefano Zampini } else { 1900872cf891SStefano Zampini loce[i] = cf; 1901872cf891SStefano Zampini locf[cf++] = i; 1902872cf891SStefano Zampini } 1903872cf891SStefano Zampini } 1904872cf891SStefano Zampini ierr = VecRestoreArrayRead(is->y,&v);CHKERRQ(ierr); 1905872cf891SStefano Zampini /* extract valid submatrix */ 1906872cf891SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A),cf,locf,PETSC_USE_POINTER,&tis);CHKERRQ(ierr); 1907e5b89577SStefano Zampini ierr = MatCreateSubMatrix(is->A,tis,tis,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr); 1908872cf891SStefano Zampini ierr = ISDestroy(&tis);CHKERRQ(ierr); 1909872cf891SStefano Zampini /* attach local l2g map for successive calls of MatSetValues */ 1910872cf891SStefano Zampini ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is->A),1,n,loce,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr); 1911872cf891SStefano Zampini ierr = MatSetLocalToGlobalMapping(newlA,l2g,l2g);CHKERRQ(ierr); 1912872cf891SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr); 1913872cf891SStefano Zampini /* attach new global l2g map */ 1914872cf891SStefano Zampini ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,cf,locf,locf);CHKERRQ(ierr); 1915872cf891SStefano Zampini ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,cf,locf,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr); 1916872cf891SStefano Zampini ierr = MatSetLocalToGlobalMapping(A,l2g,l2g);CHKERRQ(ierr); 1917872cf891SStefano Zampini ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr); 1918872cf891SStefano Zampini ierr = MatDestroy(&newlA);CHKERRQ(ierr); 1919872cf891SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr); 1920872cf891SStefano Zampini } 1921872cf891SStefano Zampini is->locempty = PETSC_FALSE; 1922b4319ba4SBarry Smith PetscFunctionReturn(0); 1923b4319ba4SBarry Smith } 1924b4319ba4SBarry Smith 1925a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local) 1926b4319ba4SBarry Smith { 1927b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)mat->data; 1928b4319ba4SBarry Smith 1929b4319ba4SBarry Smith PetscFunctionBegin; 1930b4319ba4SBarry Smith *local = is->A; 1931b4319ba4SBarry Smith PetscFunctionReturn(0); 1932b4319ba4SBarry Smith } 1933b4319ba4SBarry Smith 19343b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local) 19353b3b1effSJed Brown { 19363b3b1effSJed Brown PetscFunctionBegin; 19373b3b1effSJed Brown *local = NULL; 19383b3b1effSJed Brown PetscFunctionReturn(0); 19393b3b1effSJed Brown } 19403b3b1effSJed Brown 1941b4319ba4SBarry Smith /*@ 1942b4319ba4SBarry Smith MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix. 1943b4319ba4SBarry Smith 1944b4319ba4SBarry Smith Input Parameter: 1945b4319ba4SBarry Smith . mat - the matrix 1946b4319ba4SBarry Smith 1947b4319ba4SBarry Smith Output Parameter: 1948eb82efa4SStefano Zampini . local - the local matrix 1949b4319ba4SBarry Smith 1950b4319ba4SBarry Smith Level: advanced 1951b4319ba4SBarry Smith 1952b4319ba4SBarry Smith Notes: 1953b4319ba4SBarry Smith This can be called if you have precomputed the nonzero structure of the 1954b4319ba4SBarry Smith matrix and want to provide it to the inner matrix object to improve the performance 1955b4319ba4SBarry Smith of the MatSetValues() operation. 1956b4319ba4SBarry Smith 19573b3b1effSJed Brown Call MatISRestoreLocalMat() when finished with the local matrix. 195896a6f129SJed Brown 1959b4319ba4SBarry Smith .seealso: MATIS 1960b4319ba4SBarry Smith @*/ 19617087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local) 1962b4319ba4SBarry Smith { 19634ac538c5SBarry Smith PetscErrorCode ierr; 1964b4319ba4SBarry Smith 1965b4319ba4SBarry Smith PetscFunctionBegin; 19660700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1967b4319ba4SBarry Smith PetscValidPointer(local,2); 19684ac538c5SBarry Smith ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr); 1969b4319ba4SBarry Smith PetscFunctionReturn(0); 1970b4319ba4SBarry Smith } 1971b4319ba4SBarry Smith 19723b3b1effSJed Brown /*@ 19733b3b1effSJed Brown MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat() 19743b3b1effSJed Brown 19753b3b1effSJed Brown Input Parameter: 19763b3b1effSJed Brown . mat - the matrix 19773b3b1effSJed Brown 19783b3b1effSJed Brown Output Parameter: 19793b3b1effSJed Brown . local - the local matrix 19803b3b1effSJed Brown 19813b3b1effSJed Brown Level: advanced 19823b3b1effSJed Brown 19833b3b1effSJed Brown .seealso: MATIS 19843b3b1effSJed Brown @*/ 19853b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local) 19863b3b1effSJed Brown { 19873b3b1effSJed Brown PetscErrorCode ierr; 19883b3b1effSJed Brown 19893b3b1effSJed Brown PetscFunctionBegin; 19903b3b1effSJed Brown PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 19913b3b1effSJed Brown PetscValidPointer(local,2); 19923b3b1effSJed Brown ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr); 19933b3b1effSJed Brown PetscFunctionReturn(0); 19943b3b1effSJed Brown } 19953b3b1effSJed Brown 1996a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local) 19973b03a366Sstefano_zampini { 19983b03a366Sstefano_zampini Mat_IS *is = (Mat_IS*)mat->data; 19993b03a366Sstefano_zampini PetscInt nrows,ncols,orows,ocols; 20003b03a366Sstefano_zampini PetscErrorCode ierr; 20013b03a366Sstefano_zampini 20023b03a366Sstefano_zampini PetscFunctionBegin; 20034e4c7dbeSStefano Zampini if (is->A) { 20043b03a366Sstefano_zampini ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr); 20053b03a366Sstefano_zampini ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr); 2006f0ae7da4SStefano Zampini if (orows != nrows || ocols != ncols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %Dx%D (you passed a %Dx%D matrix)",orows,ocols,nrows,ncols); 20074e4c7dbeSStefano Zampini } 20083b03a366Sstefano_zampini ierr = PetscObjectReference((PetscObject)local);CHKERRQ(ierr); 20093b03a366Sstefano_zampini ierr = MatDestroy(&is->A);CHKERRQ(ierr); 20103b03a366Sstefano_zampini is->A = local; 20113b03a366Sstefano_zampini PetscFunctionReturn(0); 20123b03a366Sstefano_zampini } 20133b03a366Sstefano_zampini 20143b03a366Sstefano_zampini /*@ 2015eb82efa4SStefano Zampini MatISSetLocalMat - Replace the local matrix stored inside a MATIS object. 20163b03a366Sstefano_zampini 20173b03a366Sstefano_zampini Input Parameter: 20183b03a366Sstefano_zampini . mat - the matrix 2019eb82efa4SStefano Zampini . local - the local matrix 20203b03a366Sstefano_zampini 20213b03a366Sstefano_zampini Output Parameter: 20223b03a366Sstefano_zampini 20233b03a366Sstefano_zampini Level: advanced 20243b03a366Sstefano_zampini 20253b03a366Sstefano_zampini Notes: 20263b03a366Sstefano_zampini This can be called if you have precomputed the local matrix and 20273b03a366Sstefano_zampini want to provide it to the matrix object MATIS. 20283b03a366Sstefano_zampini 20293b03a366Sstefano_zampini .seealso: MATIS 20303b03a366Sstefano_zampini @*/ 20313b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local) 20323b03a366Sstefano_zampini { 20333b03a366Sstefano_zampini PetscErrorCode ierr; 20343b03a366Sstefano_zampini 20353b03a366Sstefano_zampini PetscFunctionBegin; 20363b03a366Sstefano_zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2037b7ce53b6SStefano Zampini PetscValidHeaderSpecific(local,MAT_CLASSID,2); 20383b03a366Sstefano_zampini ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr); 20393b03a366Sstefano_zampini PetscFunctionReturn(0); 20403b03a366Sstefano_zampini } 20413b03a366Sstefano_zampini 2042a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A) 20436726f965SBarry Smith { 20446726f965SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 20456726f965SBarry Smith PetscErrorCode ierr; 20466726f965SBarry Smith 20476726f965SBarry Smith PetscFunctionBegin; 20486726f965SBarry Smith ierr = MatZeroEntries(a->A);CHKERRQ(ierr); 20496726f965SBarry Smith PetscFunctionReturn(0); 20506726f965SBarry Smith } 20516726f965SBarry Smith 2052a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a) 20532e74eeadSLisandro Dalcin { 20542e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 20552e74eeadSLisandro Dalcin PetscErrorCode ierr; 20562e74eeadSLisandro Dalcin 20572e74eeadSLisandro Dalcin PetscFunctionBegin; 20582e74eeadSLisandro Dalcin ierr = MatScale(is->A,a);CHKERRQ(ierr); 20592e74eeadSLisandro Dalcin PetscFunctionReturn(0); 20602e74eeadSLisandro Dalcin } 20612e74eeadSLisandro Dalcin 2062a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 20632e74eeadSLisandro Dalcin { 20642e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 20652e74eeadSLisandro Dalcin PetscErrorCode ierr; 20662e74eeadSLisandro Dalcin 20672e74eeadSLisandro Dalcin PetscFunctionBegin; 20682e74eeadSLisandro Dalcin /* get diagonal of the local matrix */ 2069e176bc59SStefano Zampini ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr); 20702e74eeadSLisandro Dalcin 20712e74eeadSLisandro Dalcin /* scatter diagonal back into global vector */ 20722e74eeadSLisandro Dalcin ierr = VecSet(v,0);CHKERRQ(ierr); 2073e176bc59SStefano Zampini ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2074e176bc59SStefano Zampini ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 20752e74eeadSLisandro Dalcin PetscFunctionReturn(0); 20762e74eeadSLisandro Dalcin } 20772e74eeadSLisandro Dalcin 2078a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg) 20796726f965SBarry Smith { 20806726f965SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 20816726f965SBarry Smith PetscErrorCode ierr; 20826726f965SBarry Smith 20836726f965SBarry Smith PetscFunctionBegin; 20844e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 20856726f965SBarry Smith PetscFunctionReturn(0); 20866726f965SBarry Smith } 20876726f965SBarry Smith 2088f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str) 2089f26d0771SStefano Zampini { 2090f26d0771SStefano Zampini Mat_IS *y = (Mat_IS*)Y->data; 2091f26d0771SStefano Zampini Mat_IS *x; 2092f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 2093f26d0771SStefano Zampini PetscBool ismatis; 2094f26d0771SStefano Zampini #endif 2095f26d0771SStefano Zampini PetscErrorCode ierr; 2096f26d0771SStefano Zampini 2097f26d0771SStefano Zampini PetscFunctionBegin; 2098f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 2099f26d0771SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr); 2100f26d0771SStefano Zampini if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 2101f26d0771SStefano Zampini #endif 2102f26d0771SStefano Zampini x = (Mat_IS*)X->data; 2103f26d0771SStefano Zampini ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr); 2104f26d0771SStefano Zampini PetscFunctionReturn(0); 2105f26d0771SStefano Zampini } 2106f26d0771SStefano Zampini 2107f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat) 2108f26d0771SStefano Zampini { 2109f26d0771SStefano Zampini Mat lA; 2110f26d0771SStefano Zampini Mat_IS *matis; 2111f26d0771SStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 2112f26d0771SStefano Zampini IS is; 2113f26d0771SStefano Zampini const PetscInt *rg,*rl; 2114f26d0771SStefano Zampini PetscInt nrg; 2115f26d0771SStefano Zampini PetscInt N,M,nrl,i,*idxs; 2116f26d0771SStefano Zampini PetscErrorCode ierr; 2117f26d0771SStefano Zampini 2118f26d0771SStefano Zampini PetscFunctionBegin; 2119f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr); 2120f26d0771SStefano Zampini ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr); 2121f26d0771SStefano Zampini ierr = ISGetIndices(row,&rl);CHKERRQ(ierr); 2122f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr); 2123f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 2124f0ae7da4SStefano Zampini for (i=0;i<nrl;i++) if (rl[i]>=nrg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row index %D -> %D greater than maximum possible %D",i,rl[i],nrg); 2125f26d0771SStefano Zampini #endif 2126f26d0771SStefano Zampini ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr); 2127f26d0771SStefano Zampini /* map from [0,nrl) to row */ 2128f26d0771SStefano Zampini for (i=0;i<nrl;i++) idxs[i] = rl[i]; 2129f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 2130f26d0771SStefano Zampini for (i=nrl;i<nrg;i++) idxs[i] = nrg; 2131f26d0771SStefano Zampini #else 2132f26d0771SStefano Zampini for (i=nrl;i<nrg;i++) idxs[i] = -1; 2133f26d0771SStefano Zampini #endif 2134f26d0771SStefano Zampini ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr); 2135f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr); 2136f26d0771SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 2137f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 2138f26d0771SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 2139f26d0771SStefano Zampini /* compute new l2g map for columns */ 2140f26d0771SStefano Zampini if (col != row || A->rmap->mapping != A->cmap->mapping) { 2141f26d0771SStefano Zampini const PetscInt *cg,*cl; 2142f26d0771SStefano Zampini PetscInt ncg; 2143f26d0771SStefano Zampini PetscInt ncl; 2144f26d0771SStefano Zampini 2145f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr); 2146f26d0771SStefano Zampini ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr); 2147f26d0771SStefano Zampini ierr = ISGetIndices(col,&cl);CHKERRQ(ierr); 2148f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr); 2149f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 2150f0ae7da4SStefano Zampini for (i=0;i<ncl;i++) if (cl[i]>=ncg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local column index %D -> %D greater than maximum possible %D",i,cl[i],ncg); 2151f26d0771SStefano Zampini #endif 2152f26d0771SStefano Zampini ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr); 2153f26d0771SStefano Zampini /* map from [0,ncl) to col */ 2154f26d0771SStefano Zampini for (i=0;i<ncl;i++) idxs[i] = cl[i]; 2155f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 2156f26d0771SStefano Zampini for (i=ncl;i<ncg;i++) idxs[i] = ncg; 2157f26d0771SStefano Zampini #else 2158f26d0771SStefano Zampini for (i=ncl;i<ncg;i++) idxs[i] = -1; 2159f26d0771SStefano Zampini #endif 2160f26d0771SStefano Zampini ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr); 2161f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr); 2162f26d0771SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 2163f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 2164f26d0771SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 2165f26d0771SStefano Zampini } else { 2166f26d0771SStefano Zampini ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr); 2167f26d0771SStefano Zampini cl2g = rl2g; 2168f26d0771SStefano Zampini } 2169f26d0771SStefano Zampini /* create the MATIS submatrix */ 2170f26d0771SStefano Zampini ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); 2171f26d0771SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr); 2172f26d0771SStefano Zampini ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 2173f26d0771SStefano Zampini ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr); 2174b0aa3428SStefano Zampini matis = (Mat_IS*)((*submat)->data); 2175f26d0771SStefano Zampini matis->islocalref = PETSC_TRUE; 2176f26d0771SStefano Zampini ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr); 2177f26d0771SStefano Zampini ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr); 2178f26d0771SStefano Zampini ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr); 2179f26d0771SStefano Zampini ierr = MatSetUp(*submat);CHKERRQ(ierr); 2180f26d0771SStefano Zampini ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2181f26d0771SStefano Zampini ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2182f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 2183f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 2184f26d0771SStefano Zampini /* remove unsupported ops */ 2185f26d0771SStefano Zampini ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 2186f26d0771SStefano Zampini (*submat)->ops->destroy = MatDestroy_IS; 2187f26d0771SStefano Zampini (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 2188f26d0771SStefano Zampini (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 2189f26d0771SStefano Zampini (*submat)->ops->assemblybegin = MatAssemblyBegin_IS; 2190f26d0771SStefano Zampini (*submat)->ops->assemblyend = MatAssemblyEnd_IS; 2191f26d0771SStefano Zampini PetscFunctionReturn(0); 2192f26d0771SStefano Zampini } 2193f26d0771SStefano Zampini 2194872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A) 2195872cf891SStefano Zampini { 2196872cf891SStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 2197872cf891SStefano Zampini PetscErrorCode ierr; 2198872cf891SStefano Zampini 2199872cf891SStefano Zampini PetscFunctionBegin; 2200872cf891SStefano Zampini ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr); 2201872cf891SStefano Zampini ierr = PetscObjectOptionsBegin((PetscObject)A); 2202872cf891SStefano Zampini ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns",NULL,a->locempty,&a->locempty,NULL);CHKERRQ(ierr); 2203872cf891SStefano Zampini ierr = PetscOptionsEnd();CHKERRQ(ierr); 2204872cf891SStefano Zampini PetscFunctionReturn(0); 2205872cf891SStefano Zampini } 2206872cf891SStefano Zampini 2207284134d9SBarry Smith /*@ 22083c212e90SHong Zhang MatCreateIS - Creates a "process" unassembled matrix, assembled on each 2209284134d9SBarry Smith process but not across processes. 2210284134d9SBarry Smith 2211284134d9SBarry Smith Input Parameters: 2212284134d9SBarry Smith + comm - MPI communicator that will share the matrix 2213e176bc59SStefano Zampini . bs - block size of the matrix 2214df3898eeSBarry Smith . m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products 2215e176bc59SStefano Zampini . rmap - local to global map for rows 2216e176bc59SStefano Zampini - cmap - local to global map for cols 2217284134d9SBarry Smith 2218284134d9SBarry Smith Output Parameter: 2219284134d9SBarry Smith . A - the resulting matrix 2220284134d9SBarry Smith 22218e6c10adSSatish Balay Level: advanced 22228e6c10adSSatish Balay 22233c212e90SHong Zhang Notes: See MATIS for more details. 22246fdf41d1SStefano Zampini m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors 22256fdf41d1SStefano Zampini used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices. 22263c212e90SHong Zhang If either rmap or cmap are NULL, then the matrix is assumed to be square. 2227284134d9SBarry Smith 2228284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping() 2229284134d9SBarry Smith @*/ 2230e176bc59SStefano Zampini PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A) 2231284134d9SBarry Smith { 2232284134d9SBarry Smith PetscErrorCode ierr; 2233284134d9SBarry Smith 2234284134d9SBarry Smith PetscFunctionBegin; 22356fdf41d1SStefano Zampini if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings"); 2236284134d9SBarry Smith ierr = MatCreate(comm,A);CHKERRQ(ierr); 2237284134d9SBarry Smith ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr); 22386fdf41d1SStefano Zampini if (bs > 0) { 2239284134d9SBarry Smith ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr); 22406fdf41d1SStefano Zampini } 2241284134d9SBarry Smith ierr = MatSetType(*A,MATIS);CHKERRQ(ierr); 2242e176bc59SStefano Zampini if (rmap && cmap) { 2243e176bc59SStefano Zampini ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr); 2244e176bc59SStefano Zampini } else if (!rmap) { 2245e176bc59SStefano Zampini ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr); 2246e176bc59SStefano Zampini } else { 2247e176bc59SStefano Zampini ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr); 2248e176bc59SStefano Zampini } 2249284134d9SBarry Smith PetscFunctionReturn(0); 2250284134d9SBarry Smith } 2251284134d9SBarry Smith 2252b4319ba4SBarry Smith /*MC 2253f26d0771SStefano Zampini MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP). 2254b4319ba4SBarry Smith This stores the matrices in globally unassembled form. Each processor 2255b4319ba4SBarry Smith assembles only its local Neumann problem and the parallel matrix vector 2256b4319ba4SBarry Smith product is handled "implicitly". 2257b4319ba4SBarry Smith 2258b4319ba4SBarry Smith Operations Provided: 22596726f965SBarry Smith + MatMult() 22602e74eeadSLisandro Dalcin . MatMultAdd() 22612e74eeadSLisandro Dalcin . MatMultTranspose() 22622e74eeadSLisandro Dalcin . MatMultTransposeAdd() 22636726f965SBarry Smith . MatZeroEntries() 22646726f965SBarry Smith . MatSetOption() 22652e74eeadSLisandro Dalcin . MatZeroRows() 22662e74eeadSLisandro Dalcin . MatSetValues() 226797563a80SStefano Zampini . MatSetValuesBlocked() 22686726f965SBarry Smith . MatSetValuesLocal() 226997563a80SStefano Zampini . MatSetValuesBlockedLocal() 22702e74eeadSLisandro Dalcin . MatScale() 22712e74eeadSLisandro Dalcin . MatGetDiagonal() 22722b404112SStefano Zampini . MatMissingDiagonal() 22732b404112SStefano Zampini . MatDuplicate() 22742b404112SStefano Zampini . MatCopy() 2275f26d0771SStefano Zampini . MatAXPY() 22767dae84e0SHong Zhang . MatCreateSubMatrix() 2277f26d0771SStefano Zampini . MatGetLocalSubMatrix() 2278d7f69cd0SStefano Zampini . MatTranspose() 22796726f965SBarry Smith - MatSetLocalToGlobalMapping() 2280b4319ba4SBarry Smith 2281b4319ba4SBarry Smith Options Database Keys: 2282b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions() 2283b4319ba4SBarry Smith 2284b4319ba4SBarry Smith Notes: Options prefix for the inner matrix are given by -is_mat_xxx 2285b4319ba4SBarry Smith 2286b4319ba4SBarry Smith You must call MatSetLocalToGlobalMapping() before using this matrix type. 2287b4319ba4SBarry Smith 2288b4319ba4SBarry Smith You can do matrix preallocation on the local matrix after you obtain it with 2289eb82efa4SStefano Zampini MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation() 2290b4319ba4SBarry Smith 2291b4319ba4SBarry Smith Level: advanced 2292b4319ba4SBarry Smith 2293f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP 2294b4319ba4SBarry Smith 2295b4319ba4SBarry Smith M*/ 2296b4319ba4SBarry Smith 22978cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 2298b4319ba4SBarry Smith { 2299dfbe8321SBarry Smith PetscErrorCode ierr; 2300b4319ba4SBarry Smith Mat_IS *b; 2301b4319ba4SBarry Smith 2302b4319ba4SBarry Smith PetscFunctionBegin; 2303b00a9115SJed Brown ierr = PetscNewLog(A,&b);CHKERRQ(ierr); 2304b4319ba4SBarry Smith A->data = (void*)b; 2305b4319ba4SBarry Smith 2306e176bc59SStefano Zampini /* matrix ops */ 2307e176bc59SStefano Zampini ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 2308b4319ba4SBarry Smith A->ops->mult = MatMult_IS; 23092e74eeadSLisandro Dalcin A->ops->multadd = MatMultAdd_IS; 23102e74eeadSLisandro Dalcin A->ops->multtranspose = MatMultTranspose_IS; 23112e74eeadSLisandro Dalcin A->ops->multtransposeadd = MatMultTransposeAdd_IS; 2312b4319ba4SBarry Smith A->ops->destroy = MatDestroy_IS; 2313b4319ba4SBarry Smith A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 23142e74eeadSLisandro Dalcin A->ops->setvalues = MatSetValues_IS; 231598921651SStefano Zampini A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 2316b4319ba4SBarry Smith A->ops->setvalueslocal = MatSetValuesLocal_IS; 2317f0006bf2SLisandro Dalcin A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 23182e74eeadSLisandro Dalcin A->ops->zerorows = MatZeroRows_IS; 2319f0ae7da4SStefano Zampini A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 2320b4319ba4SBarry Smith A->ops->assemblybegin = MatAssemblyBegin_IS; 2321b4319ba4SBarry Smith A->ops->assemblyend = MatAssemblyEnd_IS; 2322b4319ba4SBarry Smith A->ops->view = MatView_IS; 23236726f965SBarry Smith A->ops->zeroentries = MatZeroEntries_IS; 23242e74eeadSLisandro Dalcin A->ops->scale = MatScale_IS; 23252e74eeadSLisandro Dalcin A->ops->getdiagonal = MatGetDiagonal_IS; 23266726f965SBarry Smith A->ops->setoption = MatSetOption_IS; 232769796d55SStefano Zampini A->ops->ishermitian = MatIsHermitian_IS; 232869796d55SStefano Zampini A->ops->issymmetric = MatIsSymmetric_IS; 232945471136SStefano Zampini A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS; 2330ad6194a2SStefano Zampini A->ops->duplicate = MatDuplicate_IS; 23316bd84002SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_IS; 23322b404112SStefano Zampini A->ops->copy = MatCopy_IS; 2333659959c5SStefano Zampini A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 23347dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_IS; 2335f26d0771SStefano Zampini A->ops->axpy = MatAXPY_IS; 23363fd1c9e7SStefano Zampini A->ops->diagonalset = MatDiagonalSet_IS; 23373fd1c9e7SStefano Zampini A->ops->shift = MatShift_IS; 2338d7f69cd0SStefano Zampini A->ops->transpose = MatTranspose_IS; 23397fa8f2d3SStefano Zampini A->ops->getinfo = MatGetInfo_IS; 2340ad219c80Sstefano_zampini A->ops->diagonalscale = MatDiagonalScale_IS; 2341872cf891SStefano Zampini A->ops->setfromoptions = MatSetFromOptions_IS; 2342b4319ba4SBarry Smith 2343b7ce53b6SStefano Zampini /* special MATIS functions */ 2344bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr); 23453b3b1effSJed Brown ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr); 2346bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr); 2347b7ce53b6SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr); 23482e1947a5SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr); 2349cf0a3239SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr); 235017667f90SBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr); 2351b4319ba4SBarry Smith PetscFunctionReturn(0); 2352b4319ba4SBarry Smith } 2353