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*/ 1128f4e0baSStefano Zampini 12f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048 13f26d0771SStefano Zampini 14a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat); 15a72627d2SStefano Zampini 1628f4e0baSStefano Zampini #undef __FUNCT__ 175e3038f0Sstefano_zampini #define __FUNCT__ "MatConvert_Nest_IS" 185e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat) 195e3038f0Sstefano_zampini { 205e3038f0Sstefano_zampini Mat **nest,*snest,**rnest,lA,B; 215e3038f0Sstefano_zampini IS *iscol,*isrow,*islrow,*islcol; 225e3038f0Sstefano_zampini ISLocalToGlobalMapping rl2g,cl2g; 235e3038f0Sstefano_zampini MPI_Comm comm; 245e3038f0Sstefano_zampini PetscInt *lr,*lc,*lrb,*lcb,*l2gidxs; 255e3038f0Sstefano_zampini PetscInt sti,stl,i,j,nr,nc,rbs,cbs; 265e3038f0Sstefano_zampini PetscBool convert,lreuse; 275e3038f0Sstefano_zampini PetscErrorCode ierr; 285e3038f0Sstefano_zampini 295e3038f0Sstefano_zampini PetscFunctionBeginUser; 305e3038f0Sstefano_zampini ierr = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr); 315e3038f0Sstefano_zampini lreuse = PETSC_FALSE; 325e3038f0Sstefano_zampini rnest = NULL; 335e3038f0Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 345e3038f0Sstefano_zampini PetscBool ismatis,isnest; 355e3038f0Sstefano_zampini 365e3038f0Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr); 375e3038f0Sstefano_zampini if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type); 385e3038f0Sstefano_zampini ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 395e3038f0Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr); 405e3038f0Sstefano_zampini if (isnest) { 415e3038f0Sstefano_zampini ierr = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr); 425e3038f0Sstefano_zampini lreuse = (PetscBool)(i == nr && j == nc); 435e3038f0Sstefano_zampini if (!lreuse) rnest = NULL; 445e3038f0Sstefano_zampini } 455e3038f0Sstefano_zampini } 465e3038f0Sstefano_zampini ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 475e3038f0Sstefano_zampini ierr = PetscCalloc4(nr,&lr,nc,&lc,nr,&lrb,nc,&lcb);CHKERRQ(ierr); 485e3038f0Sstefano_zampini ierr = PetscCalloc5(nr,&isrow,nc,&iscol, 495e3038f0Sstefano_zampini nr,&islrow,nc,&islcol, 505e3038f0Sstefano_zampini nr*nc,&snest);CHKERRQ(ierr); 515e3038f0Sstefano_zampini ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr); 525e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 535e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 545e3038f0Sstefano_zampini PetscBool ismatis; 555e3038f0Sstefano_zampini PetscInt l1,l2,ij=i*nc+j; 565e3038f0Sstefano_zampini 575e3038f0Sstefano_zampini /* Null matrix pointers are allowed in MATNEST */ 585e3038f0Sstefano_zampini if (!nest[i][j]) continue; 595e3038f0Sstefano_zampini 605e3038f0Sstefano_zampini /* Nested matrices should be of type MATIS */ 615e3038f0Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr); 625e3038f0Sstefano_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); 635e3038f0Sstefano_zampini 645e3038f0Sstefano_zampini /* Check compatibility of local sizes */ 655e3038f0Sstefano_zampini ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr); 665e3038f0Sstefano_zampini ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr); 675e3038f0Sstefano_zampini if (!l1 || !l2) continue; 685e3038f0Sstefano_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); 695e3038f0Sstefano_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); 705e3038f0Sstefano_zampini lr[i] = l1; 715e3038f0Sstefano_zampini lc[j] = l2; 725e3038f0Sstefano_zampini ierr = MatGetBlockSizes(snest[ij],&l1,&l2);CHKERRQ(ierr); 735e3038f0Sstefano_zampini if (lrb[i] && l1 != lrb[i]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid block size %D != %D",i,j,lrb[i],l1); 745e3038f0Sstefano_zampini if (lcb[j] && l2 != lcb[j]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid block size %D != %D",i,j,lcb[j],l2); 755e3038f0Sstefano_zampini lrb[i] = l1; 765e3038f0Sstefano_zampini lcb[j] = l2; 775e3038f0Sstefano_zampini 785e3038f0Sstefano_zampini /* check compatibilty for local matrix reusage */ 795e3038f0Sstefano_zampini if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE; 805e3038f0Sstefano_zampini } 815e3038f0Sstefano_zampini } 825e3038f0Sstefano_zampini 835e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG) 845e3038f0Sstefano_zampini /* Check compatibility of l2g maps for rows */ 855e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 865e3038f0Sstefano_zampini rl2g = NULL; 875e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 885e3038f0Sstefano_zampini PetscInt n1,n2; 895e3038f0Sstefano_zampini 905e3038f0Sstefano_zampini if (!nest[i][j]) continue; 915e3038f0Sstefano_zampini ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr); 925e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr); 935e3038f0Sstefano_zampini if (!n1) continue; 945e3038f0Sstefano_zampini if (!rl2g) { 955e3038f0Sstefano_zampini rl2g = cl2g; 965e3038f0Sstefano_zampini } else { 975e3038f0Sstefano_zampini const PetscInt *idxs1,*idxs2; 985e3038f0Sstefano_zampini PetscBool same; 995e3038f0Sstefano_zampini 1005e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr); 1015e3038f0Sstefano_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); 1025e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr); 1035e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr); 1045e3038f0Sstefano_zampini ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr); 1055e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr); 1065e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr); 1075e3038f0Sstefano_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); 1085e3038f0Sstefano_zampini } 1095e3038f0Sstefano_zampini } 1105e3038f0Sstefano_zampini } 1115e3038f0Sstefano_zampini /* Check compatibility of l2g maps for columns */ 1125e3038f0Sstefano_zampini for (i=0;i<nc;i++) { 1135e3038f0Sstefano_zampini rl2g = NULL; 1145e3038f0Sstefano_zampini for (j=0;j<nr;j++) { 1155e3038f0Sstefano_zampini PetscInt n1,n2; 1165e3038f0Sstefano_zampini 1175e3038f0Sstefano_zampini if (!nest[j][i]) continue; 1185e3038f0Sstefano_zampini ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr); 1195e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr); 1205e3038f0Sstefano_zampini if (!n1) continue; 1215e3038f0Sstefano_zampini if (!rl2g) { 1225e3038f0Sstefano_zampini rl2g = cl2g; 1235e3038f0Sstefano_zampini } else { 1245e3038f0Sstefano_zampini const PetscInt *idxs1,*idxs2; 1255e3038f0Sstefano_zampini PetscBool same; 1265e3038f0Sstefano_zampini 1275e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr); 1285e3038f0Sstefano_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); 1295e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr); 1305e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr); 1315e3038f0Sstefano_zampini ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr); 1325e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr); 1335e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr); 1345e3038f0Sstefano_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); 1355e3038f0Sstefano_zampini } 1365e3038f0Sstefano_zampini } 1375e3038f0Sstefano_zampini } 1385e3038f0Sstefano_zampini #endif 1395e3038f0Sstefano_zampini 1405e3038f0Sstefano_zampini B = NULL; 1415e3038f0Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 1425e3038f0Sstefano_zampini /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */ 1435e3038f0Sstefano_zampini for (i=0,stl=0;i<nr;i++) stl += lr[i]; 1445e3038f0Sstefano_zampini ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr); 1455e3038f0Sstefano_zampini for (i=0,sti=0,stl=0;i<nr;i++) { 1465e3038f0Sstefano_zampini Mat usedmat; 1475e3038f0Sstefano_zampini Mat_IS *matis; 1485e3038f0Sstefano_zampini const PetscInt *idxs; 1495e3038f0Sstefano_zampini PetscInt n = lr[i]/lrb[i]; 1505e3038f0Sstefano_zampini 1515e3038f0Sstefano_zampini /* local IS for local NEST */ 1525e3038f0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr); 1535e3038f0Sstefano_zampini sti += n; 1545e3038f0Sstefano_zampini 1555e3038f0Sstefano_zampini /* l2gmap */ 1565e3038f0Sstefano_zampini j = 0; 1575e3038f0Sstefano_zampini usedmat = nest[i][j]; 1585e3038f0Sstefano_zampini while (!usedmat && j < nc) usedmat = nest[i][j++]; 1595e3038f0Sstefano_zampini matis = (Mat_IS*)(usedmat->data); 1605e3038f0Sstefano_zampini if (!matis->sf) { 1615e3038f0Sstefano_zampini ierr = MatISComputeSF_Private(usedmat);CHKERRQ(ierr); 1625e3038f0Sstefano_zampini } 1635e3038f0Sstefano_zampini ierr = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr); 1645e3038f0Sstefano_zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 1655e3038f0Sstefano_zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 1665e3038f0Sstefano_zampini ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr); 1675e3038f0Sstefano_zampini stl += lr[i]; 1685e3038f0Sstefano_zampini } 1695e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr); 1705e3038f0Sstefano_zampini 1715e3038f0Sstefano_zampini /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */ 1725e3038f0Sstefano_zampini for (i=0,stl=0;i<nc;i++) stl += lc[i]; 1735e3038f0Sstefano_zampini ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr); 1745e3038f0Sstefano_zampini for (i=0,sti=0,stl=0;i<nc;i++) { 1755e3038f0Sstefano_zampini Mat usedmat; 1765e3038f0Sstefano_zampini Mat_IS *matis; 1775e3038f0Sstefano_zampini const PetscInt *idxs; 1785e3038f0Sstefano_zampini PetscInt n = lc[i]/lcb[i]; 1795e3038f0Sstefano_zampini 1805e3038f0Sstefano_zampini /* local IS for local NEST */ 1815e3038f0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr); 1825e3038f0Sstefano_zampini sti += n; 1835e3038f0Sstefano_zampini 1845e3038f0Sstefano_zampini /* l2gmap */ 1855e3038f0Sstefano_zampini j = 0; 1865e3038f0Sstefano_zampini usedmat = nest[j][i]; 1875e3038f0Sstefano_zampini while (!usedmat && j < nr) usedmat = nest[j++][i]; 1885e3038f0Sstefano_zampini matis = (Mat_IS*)(usedmat->data); 1895e3038f0Sstefano_zampini if (!matis->sf) { 1905e3038f0Sstefano_zampini ierr = MatISComputeSF_Private(usedmat);CHKERRQ(ierr); 1915e3038f0Sstefano_zampini } 1925e3038f0Sstefano_zampini ierr = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr); 1935e3038f0Sstefano_zampini ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 1945e3038f0Sstefano_zampini ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 1955e3038f0Sstefano_zampini ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr); 1965e3038f0Sstefano_zampini stl += lc[i]; 1975e3038f0Sstefano_zampini } 1985e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr); 1995e3038f0Sstefano_zampini 2005e3038f0Sstefano_zampini /* Create MATIS */ 2015e3038f0Sstefano_zampini ierr = MatCreate(comm,&B);CHKERRQ(ierr); 2025e3038f0Sstefano_zampini ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 2035e3038f0Sstefano_zampini ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr); 2045e3038f0Sstefano_zampini ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr); 2055e3038f0Sstefano_zampini ierr = MatSetType(B,MATIS);CHKERRQ(ierr); 2065e3038f0Sstefano_zampini ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr); 2075e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 2085e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 2095e3038f0Sstefano_zampini ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr); 2105e3038f0Sstefano_zampini ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr); 2115e3038f0Sstefano_zampini ierr = MatDestroy(&lA);CHKERRQ(ierr); 2125e3038f0Sstefano_zampini ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2135e3038f0Sstefano_zampini ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2145e3038f0Sstefano_zampini if (reuse == MAT_INPLACE_MATRIX) { 2155e3038f0Sstefano_zampini ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 2165e3038f0Sstefano_zampini } else { 2175e3038f0Sstefano_zampini *newmat = B; 2185e3038f0Sstefano_zampini } 2195e3038f0Sstefano_zampini } else { 2205e3038f0Sstefano_zampini if (lreuse) { 2215e3038f0Sstefano_zampini ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 2225e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 2235e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 2245e3038f0Sstefano_zampini if (snest[i*nc+j]) { 2255e3038f0Sstefano_zampini ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr); 2265e3038f0Sstefano_zampini } 2275e3038f0Sstefano_zampini } 2285e3038f0Sstefano_zampini } 2295e3038f0Sstefano_zampini } else { 2305e3038f0Sstefano_zampini for (i=0,sti=0;i<nr;i++) { 2315e3038f0Sstefano_zampini PetscInt n = lr[i]/lrb[i]; 2325e3038f0Sstefano_zampini 2335e3038f0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr); 2345e3038f0Sstefano_zampini sti += n; 2355e3038f0Sstefano_zampini } 2365e3038f0Sstefano_zampini for (i=0,sti=0;i<nc;i++) { 2375e3038f0Sstefano_zampini PetscInt n = lc[i]/lcb[i]; 2385e3038f0Sstefano_zampini 2395e3038f0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr); 2405e3038f0Sstefano_zampini sti += n; 2415e3038f0Sstefano_zampini } 2425e3038f0Sstefano_zampini ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr); 2435e3038f0Sstefano_zampini ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr); 2445e3038f0Sstefano_zampini ierr = MatDestroy(&lA);CHKERRQ(ierr); 2455e3038f0Sstefano_zampini } 2465e3038f0Sstefano_zampini ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2475e3038f0Sstefano_zampini ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2485e3038f0Sstefano_zampini } 2495e3038f0Sstefano_zampini 2505e3038f0Sstefano_zampini /* Free workspace */ 2515e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 2525e3038f0Sstefano_zampini ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr); 2535e3038f0Sstefano_zampini } 2545e3038f0Sstefano_zampini for (i=0;i<nc;i++) { 2555e3038f0Sstefano_zampini ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr); 2565e3038f0Sstefano_zampini } 2575e3038f0Sstefano_zampini ierr = PetscFree4(lr,lc,lrb,lcb);CHKERRQ(ierr); 2585e3038f0Sstefano_zampini ierr = PetscFree5(isrow,iscol,islrow,islcol,snest);CHKERRQ(ierr); 2595e3038f0Sstefano_zampini 2605e3038f0Sstefano_zampini /* Create local matrix in MATNEST format */ 2615e3038f0Sstefano_zampini convert = PETSC_FALSE; 2625e3038f0Sstefano_zampini ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr); 2635e3038f0Sstefano_zampini if (convert) { 2645e3038f0Sstefano_zampini Mat M; 2655e3038f0Sstefano_zampini 2665e3038f0Sstefano_zampini ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 2675e3038f0Sstefano_zampini ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr); 2685e3038f0Sstefano_zampini ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr); 2695e3038f0Sstefano_zampini ierr = MatDestroy(&M);CHKERRQ(ierr); 2705e3038f0Sstefano_zampini } 2715e3038f0Sstefano_zampini 2725e3038f0Sstefano_zampini PetscFunctionReturn(0); 2735e3038f0Sstefano_zampini } 2745e3038f0Sstefano_zampini 2755e3038f0Sstefano_zampini #undef __FUNCT__ 276d7f69cd0SStefano Zampini #define __FUNCT__ "MatTranspose_IS" 277d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B) 278d7f69cd0SStefano Zampini { 279d7f69cd0SStefano Zampini Mat C,lC,lA; 280d7f69cd0SStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 281d7f69cd0SStefano Zampini PetscBool notset = PETSC_FALSE,cong = PETSC_TRUE; 282d7f69cd0SStefano Zampini PetscErrorCode ierr; 283d7f69cd0SStefano Zampini 284d7f69cd0SStefano Zampini PetscFunctionBegin; 285d7f69cd0SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 286d7f69cd0SStefano Zampini PetscBool rcong,ccong; 287d7f69cd0SStefano Zampini 288d7f69cd0SStefano Zampini ierr = PetscLayoutCompare((*B)->cmap,A->rmap,&rcong);CHKERRQ(ierr); 289d7f69cd0SStefano Zampini ierr = PetscLayoutCompare((*B)->rmap,A->cmap,&ccong);CHKERRQ(ierr); 290fa520230SStefano Zampini cong = (PetscBool)(rcong || ccong); 291d7f69cd0SStefano Zampini } 292d7f69cd0SStefano Zampini if (reuse == MAT_INITIAL_MATRIX || *B == A || !cong) { 293d7f69cd0SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 294d7f69cd0SStefano Zampini } else { 295d7f69cd0SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)*B,MATIS,¬set);CHKERRQ(ierr); 296d7f69cd0SStefano Zampini C = *B; 297d7f69cd0SStefano Zampini } 298d7f69cd0SStefano Zampini 299d7f69cd0SStefano Zampini if (!notset) { 300d7f69cd0SStefano Zampini ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr); 301d7f69cd0SStefano Zampini ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr); 302d7f69cd0SStefano Zampini ierr = MatSetType(C,MATIS);CHKERRQ(ierr); 303d7f69cd0SStefano Zampini ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr); 304d7f69cd0SStefano Zampini ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr); 305d7f69cd0SStefano Zampini } 306d7f69cd0SStefano Zampini 307d7f69cd0SStefano Zampini /* perform local transposition */ 308d7f69cd0SStefano Zampini ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr); 309d7f69cd0SStefano Zampini ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr); 310d7f69cd0SStefano Zampini ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr); 311d7f69cd0SStefano Zampini ierr = MatDestroy(&lC);CHKERRQ(ierr); 312d7f69cd0SStefano Zampini 313d7f69cd0SStefano Zampini ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 314d7f69cd0SStefano Zampini ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 315d7f69cd0SStefano Zampini 316d7f69cd0SStefano Zampini if (reuse == MAT_INITIAL_MATRIX || *B != A) { 317d7f69cd0SStefano Zampini if (!cong) { 318d7f69cd0SStefano Zampini ierr = MatDestroy(B);CHKERRQ(ierr); 319d7f69cd0SStefano Zampini } 320d7f69cd0SStefano Zampini *B = C; 321d7f69cd0SStefano Zampini } else { 322d7f69cd0SStefano Zampini ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr); 323d7f69cd0SStefano Zampini } 324d7f69cd0SStefano Zampini PetscFunctionReturn(0); 325d7f69cd0SStefano Zampini } 326d7f69cd0SStefano Zampini 327d7f69cd0SStefano Zampini #undef __FUNCT__ 3283fd1c9e7SStefano Zampini #define __FUNCT__ "MatDiagonalSet_IS" 3293fd1c9e7SStefano Zampini PetscErrorCode MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode) 3303fd1c9e7SStefano Zampini { 3313fd1c9e7SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 3323fd1c9e7SStefano Zampini PetscErrorCode ierr; 3333fd1c9e7SStefano Zampini 3343fd1c9e7SStefano Zampini PetscFunctionBegin; 3353fd1c9e7SStefano Zampini if (!D) { /* this code branch is used by MatShift_IS */ 3363fd1c9e7SStefano Zampini ierr = VecSet(is->y,1.);CHKERRQ(ierr); 3373fd1c9e7SStefano Zampini } else { 3383fd1c9e7SStefano Zampini ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3393fd1c9e7SStefano Zampini ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3403fd1c9e7SStefano Zampini } 3413fd1c9e7SStefano Zampini ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr); 3423fd1c9e7SStefano Zampini ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr); 3433fd1c9e7SStefano Zampini PetscFunctionReturn(0); 3443fd1c9e7SStefano Zampini } 3453fd1c9e7SStefano Zampini 3463fd1c9e7SStefano Zampini #undef __FUNCT__ 3473fd1c9e7SStefano Zampini #define __FUNCT__ "MatShift_IS" 3483fd1c9e7SStefano Zampini PetscErrorCode MatShift_IS(Mat A,PetscScalar a) 3493fd1c9e7SStefano Zampini { 3503fd1c9e7SStefano Zampini PetscErrorCode ierr; 3513fd1c9e7SStefano Zampini 3523fd1c9e7SStefano Zampini PetscFunctionBegin; 3533fd1c9e7SStefano Zampini ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr); 3543fd1c9e7SStefano Zampini PetscFunctionReturn(0); 3553fd1c9e7SStefano Zampini } 3563fd1c9e7SStefano Zampini 3573fd1c9e7SStefano Zampini #undef __FUNCT__ 358f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesLocal_SubMat_IS" 359f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 360f26d0771SStefano Zampini { 361f26d0771SStefano Zampini PetscErrorCode ierr; 362f26d0771SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 363f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 364f26d0771SStefano Zampini 365f26d0771SStefano Zampini PetscFunctionBegin; 366f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 367f26d0771SStefano 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); 368f26d0771SStefano Zampini #endif 369f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr); 370f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr); 371f26d0771SStefano Zampini ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 372f26d0771SStefano Zampini PetscFunctionReturn(0); 373f26d0771SStefano Zampini } 374f26d0771SStefano Zampini 375f26d0771SStefano Zampini #undef __FUNCT__ 376f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesBlockedLocal_SubMat_IS" 377f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 378f26d0771SStefano Zampini { 379f26d0771SStefano Zampini PetscErrorCode ierr; 380f26d0771SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 381f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 382f26d0771SStefano Zampini 383f26d0771SStefano Zampini PetscFunctionBegin; 384f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 385f26d0771SStefano 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); 386f26d0771SStefano Zampini #endif 387f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr); 388f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr); 389f26d0771SStefano Zampini ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 390f26d0771SStefano Zampini PetscFunctionReturn(0); 391f26d0771SStefano Zampini } 392f26d0771SStefano Zampini 393f26d0771SStefano Zampini #undef __FUNCT__ 394a8116848SStefano Zampini #define __FUNCT__ "PetscLayoutMapLocal_Private" 395f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs) 396a8116848SStefano Zampini { 397a8116848SStefano Zampini PetscInt *owners = map->range; 398a8116848SStefano Zampini PetscInt n = map->n; 399a8116848SStefano Zampini PetscSF sf; 400a8116848SStefano Zampini PetscInt *lidxs,*work = NULL; 401a8116848SStefano Zampini PetscSFNode *ridxs; 402a8116848SStefano Zampini PetscMPIInt rank; 403a8116848SStefano Zampini PetscInt r, p = 0, len = 0; 404a8116848SStefano Zampini PetscErrorCode ierr; 405a8116848SStefano Zampini 406a8116848SStefano Zampini PetscFunctionBegin; 407a8116848SStefano Zampini /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */ 408a8116848SStefano Zampini ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr); 409a8116848SStefano Zampini ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr); 410a8116848SStefano Zampini for (r = 0; r < n; ++r) lidxs[r] = -1; 411a8116848SStefano Zampini ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr); 412a8116848SStefano Zampini for (r = 0; r < N; ++r) { 413a8116848SStefano Zampini const PetscInt idx = idxs[r]; 414a8116848SStefano 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); 415a8116848SStefano Zampini if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */ 416a8116848SStefano Zampini ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr); 417a8116848SStefano Zampini } 418a8116848SStefano Zampini ridxs[r].rank = p; 419a8116848SStefano Zampini ridxs[r].index = idxs[r] - owners[p]; 420a8116848SStefano Zampini } 421a8116848SStefano Zampini ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr); 422a8116848SStefano Zampini ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr); 423a8116848SStefano Zampini ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr); 424a8116848SStefano Zampini ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr); 425f0ae7da4SStefano Zampini if (ogidxs) { /* communicate global idxs */ 426a8116848SStefano Zampini PetscInt cum = 0,start,*work2; 427f0ae7da4SStefano Zampini 428f0ae7da4SStefano Zampini ierr = PetscMalloc1(n,&work);CHKERRQ(ierr); 429a8116848SStefano Zampini ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr); 430a8116848SStefano Zampini for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++; 431a8116848SStefano Zampini ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr); 432a8116848SStefano Zampini start -= cum; 433a8116848SStefano Zampini cum = 0; 434a8116848SStefano Zampini for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++; 435a8116848SStefano Zampini ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr); 436a8116848SStefano Zampini ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr); 437a8116848SStefano Zampini ierr = PetscFree(work2);CHKERRQ(ierr); 438a8116848SStefano Zampini } 439a8116848SStefano Zampini ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 440a8116848SStefano Zampini /* Compress and put in indices */ 441a8116848SStefano Zampini for (r = 0; r < n; ++r) 442a8116848SStefano Zampini if (lidxs[r] >= 0) { 443a8116848SStefano Zampini if (work) work[len] = work[r]; 444a8116848SStefano Zampini lidxs[len++] = r; 445a8116848SStefano Zampini } 446a8116848SStefano Zampini if (on) *on = len; 447a8116848SStefano Zampini if (oidxs) *oidxs = lidxs; 448a8116848SStefano Zampini if (ogidxs) *ogidxs = work; 449a8116848SStefano Zampini PetscFunctionReturn(0); 450a8116848SStefano Zampini } 451a8116848SStefano Zampini 452a8116848SStefano Zampini #undef __FUNCT__ 453a8116848SStefano Zampini #define __FUNCT__ "MatGetSubMatrix_IS" 454a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat) 455a8116848SStefano Zampini { 456a8116848SStefano Zampini Mat locmat,newlocmat; 457a8116848SStefano Zampini Mat_IS *newmatis; 458a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG) 459a8116848SStefano Zampini Vec rtest,ltest; 460a8116848SStefano Zampini const PetscScalar *array; 461a8116848SStefano Zampini #endif 462a8116848SStefano Zampini const PetscInt *idxs; 463a8116848SStefano Zampini PetscInt i,m,n; 464a8116848SStefano Zampini PetscErrorCode ierr; 465a8116848SStefano Zampini 466a8116848SStefano Zampini PetscFunctionBegin; 467a8116848SStefano Zampini if (scall == MAT_REUSE_MATRIX) { 468a8116848SStefano Zampini PetscBool ismatis; 469a8116848SStefano Zampini 470a8116848SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr); 471a8116848SStefano Zampini if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type"); 472a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 473a8116848SStefano Zampini if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS"); 474a8116848SStefano Zampini if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS"); 475a8116848SStefano Zampini } 476a8116848SStefano Zampini /* irow and icol may not have duplicate entries */ 477a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG) 478a8116848SStefano Zampini ierr = MatCreateVecs(mat,<est,&rtest);CHKERRQ(ierr); 479a8116848SStefano Zampini ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr); 480a8116848SStefano Zampini ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr); 481a8116848SStefano Zampini for (i=0;i<n;i++) { 482a8116848SStefano Zampini ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr); 483a8116848SStefano Zampini } 484a8116848SStefano Zampini ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr); 485a8116848SStefano Zampini ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr); 486a8116848SStefano Zampini ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr); 487a8116848SStefano Zampini ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr); 488a8116848SStefano Zampini ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr); 489fd479f66SMatthew 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])); 490a8116848SStefano Zampini ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr); 491a8116848SStefano Zampini ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr); 492a8116848SStefano Zampini ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr); 493a8116848SStefano Zampini ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr); 494a8116848SStefano Zampini for (i=0;i<n;i++) { 495a8116848SStefano Zampini ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr); 496a8116848SStefano Zampini } 497a8116848SStefano Zampini ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr); 498a8116848SStefano Zampini ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr); 499a8116848SStefano Zampini ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr); 500a8116848SStefano Zampini ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr); 501a8116848SStefano Zampini ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr); 502fd479f66SMatthew 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])); 503a8116848SStefano Zampini ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr); 504a8116848SStefano Zampini ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr); 505a8116848SStefano Zampini ierr = VecDestroy(&rtest);CHKERRQ(ierr); 506a8116848SStefano Zampini ierr = VecDestroy(<est);CHKERRQ(ierr); 507a8116848SStefano Zampini #endif 508a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 509a8116848SStefano Zampini Mat_IS *matis = (Mat_IS*)mat->data; 510a8116848SStefano Zampini ISLocalToGlobalMapping rl2g; 511a8116848SStefano Zampini IS is; 512a8116848SStefano Zampini PetscInt *lidxs,*lgidxs,*newgidxs; 5136dd40735SStefano Zampini PetscInt ll,newloc; 514a8116848SStefano Zampini MPI_Comm comm; 515a8116848SStefano Zampini 516a8116848SStefano Zampini ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 517a8116848SStefano Zampini ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr); 518a8116848SStefano Zampini ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr); 519a8116848SStefano Zampini ierr = MatCreate(comm,newmat);CHKERRQ(ierr); 520a8116848SStefano Zampini ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr); 521a8116848SStefano Zampini ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 522a8116848SStefano Zampini /* communicate irow to their owners in the layout */ 523a8116848SStefano Zampini ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr); 524f0ae7da4SStefano Zampini ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr); 525a8116848SStefano Zampini ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr); 526a8116848SStefano Zampini if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */ 527a8116848SStefano Zampini ierr = MatISComputeSF_Private(mat);CHKERRQ(ierr); 528a8116848SStefano Zampini } 529a8116848SStefano Zampini ierr = PetscMemzero(matis->sf_rootdata,matis->sf_nroots*sizeof(PetscInt));CHKERRQ(ierr); 530a8116848SStefano Zampini for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1; 531a8116848SStefano Zampini ierr = PetscFree(lidxs);CHKERRQ(ierr); 532a8116848SStefano Zampini ierr = PetscFree(lgidxs);CHKERRQ(ierr); 533a8116848SStefano Zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 534a8116848SStefano Zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 535a8116848SStefano Zampini for (i=0,newloc=0;i<matis->sf_nleaves;i++) if (matis->sf_leafdata[i]) newloc++; 536a8116848SStefano Zampini ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr); 537a8116848SStefano Zampini ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr); 538a8116848SStefano Zampini for (i=0,newloc=0;i<matis->sf_nleaves;i++) 539a8116848SStefano Zampini if (matis->sf_leafdata[i]) { 540a8116848SStefano Zampini lidxs[newloc] = i; 541a8116848SStefano Zampini newgidxs[newloc++] = matis->sf_leafdata[i]-1; 542a8116848SStefano Zampini } 543a8116848SStefano Zampini ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 544a8116848SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 545a8116848SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 546a8116848SStefano Zampini /* local is to extract local submatrix */ 547a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 548a8116848SStefano Zampini ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr); 549a8116848SStefano Zampini if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */ 550a8116848SStefano Zampini PetscBool cong; 551a8116848SStefano Zampini ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr); 552a8116848SStefano Zampini if (cong) mat->congruentlayouts = 1; 553a8116848SStefano Zampini else mat->congruentlayouts = 0; 554a8116848SStefano Zampini } 555a8116848SStefano Zampini if (mat->congruentlayouts && irow == icol) { 556a8116848SStefano Zampini ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr); 557a8116848SStefano Zampini ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr); 558a8116848SStefano Zampini newmatis->getsub_cis = newmatis->getsub_ris; 559a8116848SStefano Zampini } else { 560a8116848SStefano Zampini ISLocalToGlobalMapping cl2g; 561a8116848SStefano Zampini 562a8116848SStefano Zampini /* communicate icol to their owners in the layout */ 563a8116848SStefano Zampini ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr); 564f0ae7da4SStefano Zampini ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr); 565a8116848SStefano Zampini ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr); 566a8116848SStefano Zampini ierr = PetscMemzero(matis->csf_rootdata,matis->csf_nroots*sizeof(PetscInt));CHKERRQ(ierr); 567a8116848SStefano Zampini for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1; 568a8116848SStefano Zampini ierr = PetscFree(lidxs);CHKERRQ(ierr); 569a8116848SStefano Zampini ierr = PetscFree(lgidxs);CHKERRQ(ierr); 570a8116848SStefano Zampini ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr); 571a8116848SStefano Zampini ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr); 572a8116848SStefano Zampini for (i=0,newloc=0;i<matis->csf_nleaves;i++) if (matis->csf_leafdata[i]) newloc++; 573a8116848SStefano Zampini ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr); 574a8116848SStefano Zampini ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr); 575a8116848SStefano Zampini for (i=0,newloc=0;i<matis->csf_nleaves;i++) 576a8116848SStefano Zampini if (matis->csf_leafdata[i]) { 577a8116848SStefano Zampini lidxs[newloc] = i; 578a8116848SStefano Zampini newgidxs[newloc++] = matis->csf_leafdata[i]-1; 579a8116848SStefano Zampini } 580a8116848SStefano Zampini ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 581a8116848SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 582a8116848SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 583a8116848SStefano Zampini /* local is to extract local submatrix */ 584a8116848SStefano Zampini ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr); 585a8116848SStefano Zampini ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr); 586a8116848SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 587a8116848SStefano Zampini } 588a8116848SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 589a8116848SStefano Zampini } else { 590a8116848SStefano Zampini ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr); 591a8116848SStefano Zampini } 592a8116848SStefano Zampini ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr); 593a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 594a8116848SStefano Zampini ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr); 595a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 596a8116848SStefano Zampini ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr); 597a8116848SStefano Zampini ierr = MatDestroy(&newlocmat);CHKERRQ(ierr); 598a8116848SStefano Zampini } 599a8116848SStefano Zampini ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 600a8116848SStefano Zampini ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 601a8116848SStefano Zampini PetscFunctionReturn(0); 602a8116848SStefano Zampini } 603a8116848SStefano Zampini 604a8116848SStefano Zampini #undef __FUNCT__ 6052b404112SStefano Zampini #define __FUNCT__ "MatCopy_IS" 606a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str) 6072b404112SStefano Zampini { 6082b404112SStefano Zampini Mat_IS *a = (Mat_IS*)A->data,*b; 6092b404112SStefano Zampini PetscBool ismatis; 6102b404112SStefano Zampini PetscErrorCode ierr; 6112b404112SStefano Zampini 6122b404112SStefano Zampini PetscFunctionBegin; 6132b404112SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr); 6142b404112SStefano Zampini if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented"); 6152b404112SStefano Zampini b = (Mat_IS*)B->data; 6162b404112SStefano Zampini ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr); 6172b404112SStefano Zampini PetscFunctionReturn(0); 6182b404112SStefano Zampini } 6192b404112SStefano Zampini 6202b404112SStefano Zampini #undef __FUNCT__ 6216bd84002SStefano Zampini #define __FUNCT__ "MatMissingDiagonal_IS" 622a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool *missing,PetscInt *d) 6236bd84002SStefano Zampini { 624527b2640SStefano Zampini Vec v; 625527b2640SStefano Zampini const PetscScalar *array; 626527b2640SStefano Zampini PetscInt i,n; 6276bd84002SStefano Zampini PetscErrorCode ierr; 6286bd84002SStefano Zampini 6296bd84002SStefano Zampini PetscFunctionBegin; 630527b2640SStefano Zampini *missing = PETSC_FALSE; 631527b2640SStefano Zampini ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr); 632527b2640SStefano Zampini ierr = MatGetDiagonal(A,v);CHKERRQ(ierr); 633527b2640SStefano Zampini ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 634527b2640SStefano Zampini ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr); 635527b2640SStefano Zampini for (i=0;i<n;i++) if (array[i] == 0.) break; 636527b2640SStefano Zampini ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr); 637527b2640SStefano Zampini ierr = VecDestroy(&v);CHKERRQ(ierr); 638527b2640SStefano Zampini if (i != n) *missing = PETSC_TRUE; 639527b2640SStefano Zampini if (d) { 640527b2640SStefano Zampini *d = -1; 641527b2640SStefano Zampini if (*missing) { 642527b2640SStefano Zampini PetscInt rstart; 643527b2640SStefano Zampini ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr); 644527b2640SStefano Zampini *d = i+rstart; 645527b2640SStefano Zampini } 646527b2640SStefano Zampini } 6476bd84002SStefano Zampini PetscFunctionReturn(0); 6486bd84002SStefano Zampini } 6496bd84002SStefano Zampini 6506bd84002SStefano Zampini #undef __FUNCT__ 65128f4e0baSStefano Zampini #define __FUNCT__ "MatISComputeSF_Private" 652a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat B) 65328f4e0baSStefano Zampini { 65428f4e0baSStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 65528f4e0baSStefano Zampini const PetscInt *gidxs; 65628f4e0baSStefano Zampini PetscErrorCode ierr; 65728f4e0baSStefano Zampini 65828f4e0baSStefano Zampini PetscFunctionBegin; 65928f4e0baSStefano Zampini ierr = MatGetSize(matis->A,&matis->sf_nleaves,NULL);CHKERRQ(ierr); 66028f4e0baSStefano Zampini ierr = MatGetLocalSize(B,&matis->sf_nroots,NULL);CHKERRQ(ierr); 66128f4e0baSStefano Zampini ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr); 6623bbff08aSStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr); 66328f4e0baSStefano Zampini ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,matis->sf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr); 6643bbff08aSStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr); 66528f4e0baSStefano Zampini ierr = PetscMalloc2(matis->sf_nroots,&matis->sf_rootdata,matis->sf_nleaves,&matis->sf_leafdata);CHKERRQ(ierr); 666a8116848SStefano Zampini if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */ 667a8116848SStefano Zampini ierr = MatGetSize(matis->A,NULL,&matis->csf_nleaves);CHKERRQ(ierr); 668a8116848SStefano Zampini ierr = MatGetLocalSize(B,NULL,&matis->csf_nroots);CHKERRQ(ierr); 669a8116848SStefano Zampini ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr); 670a8116848SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr); 671a8116848SStefano Zampini ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,matis->csf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr); 672a8116848SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr); 673a8116848SStefano Zampini ierr = PetscMalloc2(matis->csf_nroots,&matis->csf_rootdata,matis->csf_nleaves,&matis->csf_leafdata);CHKERRQ(ierr); 674a8116848SStefano Zampini } else { 675a8116848SStefano Zampini matis->csf = matis->sf; 676a8116848SStefano Zampini matis->csf_nleaves = matis->sf_nleaves; 677a8116848SStefano Zampini matis->csf_nroots = matis->sf_nroots; 678a8116848SStefano Zampini matis->csf_leafdata = matis->sf_leafdata; 679a8116848SStefano Zampini matis->csf_rootdata = matis->sf_rootdata; 680a8116848SStefano Zampini } 68128f4e0baSStefano Zampini PetscFunctionReturn(0); 68228f4e0baSStefano Zampini } 6832e1947a5SStefano Zampini 6842e1947a5SStefano Zampini #undef __FUNCT__ 6852e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation" 686eb82efa4SStefano Zampini /*@ 687a88811baSStefano Zampini MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix. 688a88811baSStefano Zampini 689a88811baSStefano Zampini Collective on MPI_Comm 690a88811baSStefano Zampini 691a88811baSStefano Zampini Input Parameters: 692a88811baSStefano Zampini + B - the matrix 693a88811baSStefano Zampini . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 694a88811baSStefano Zampini (same value is used for all local rows) 695a88811baSStefano Zampini . d_nnz - array containing the number of nonzeros in the various rows of the 696a88811baSStefano Zampini DIAGONAL portion of the local submatrix (possibly different for each row) 697a88811baSStefano Zampini or NULL, if d_nz is used to specify the nonzero structure. 698a88811baSStefano Zampini The size of this array is equal to the number of local rows, i.e 'm'. 699a88811baSStefano Zampini For matrices that will be factored, you must leave room for (and set) 700a88811baSStefano Zampini the diagonal entry even if it is zero. 701a88811baSStefano Zampini . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 702a88811baSStefano Zampini submatrix (same value is used for all local rows). 703a88811baSStefano Zampini - o_nnz - array containing the number of nonzeros in the various rows of the 704a88811baSStefano Zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 705a88811baSStefano Zampini each row) or NULL, if o_nz is used to specify the nonzero 706a88811baSStefano Zampini structure. The size of this array is equal to the number 707a88811baSStefano Zampini of local rows, i.e 'm'. 708a88811baSStefano Zampini 709a88811baSStefano Zampini If the *_nnz parameter is given then the *_nz parameter is ignored 710a88811baSStefano Zampini 711a88811baSStefano Zampini Level: intermediate 712a88811baSStefano Zampini 713a88811baSStefano Zampini Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition 714a88811baSStefano Zampini from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local 715a88811baSStefano Zampini matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 716a88811baSStefano Zampini 717a88811baSStefano Zampini .keywords: matrix 718a88811baSStefano Zampini 7193c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS 720a88811baSStefano Zampini @*/ 7212e1947a5SStefano Zampini PetscErrorCode MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 7222e1947a5SStefano Zampini { 7232e1947a5SStefano Zampini PetscErrorCode ierr; 7242e1947a5SStefano Zampini 7252e1947a5SStefano Zampini PetscFunctionBegin; 7262e1947a5SStefano Zampini PetscValidHeaderSpecific(B,MAT_CLASSID,1); 7272e1947a5SStefano Zampini PetscValidType(B,1); 7282e1947a5SStefano Zampini ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr); 7292e1947a5SStefano Zampini PetscFunctionReturn(0); 7302e1947a5SStefano Zampini } 7312e1947a5SStefano Zampini 7322e1947a5SStefano Zampini #undef __FUNCT__ 7332e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS" 7347230de76SStefano Zampini static PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 7352e1947a5SStefano Zampini { 7362e1947a5SStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 73728f4e0baSStefano Zampini PetscInt bs,i,nlocalcols; 7382e1947a5SStefano Zampini PetscErrorCode ierr; 7392e1947a5SStefano Zampini 7402e1947a5SStefano Zampini PetscFunctionBegin; 7416c4ed002SBarry Smith if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping"); 74228f4e0baSStefano Zampini if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */ 74328f4e0baSStefano Zampini ierr = MatISComputeSF_Private(B);CHKERRQ(ierr); 74428f4e0baSStefano Zampini } 7452e1947a5SStefano Zampini if (!d_nnz) { 74628f4e0baSStefano Zampini for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nz; 7472e1947a5SStefano Zampini } else { 74828f4e0baSStefano Zampini for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nnz[i]; 7492e1947a5SStefano Zampini } 7502e1947a5SStefano Zampini if (!o_nnz) { 75128f4e0baSStefano Zampini for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nz; 7522e1947a5SStefano Zampini } else { 75328f4e0baSStefano Zampini for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nnz[i]; 7542e1947a5SStefano Zampini } 75528f4e0baSStefano Zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 75628f4e0baSStefano Zampini ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr); 75728f4e0baSStefano Zampini ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr); 75828f4e0baSStefano Zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 75928f4e0baSStefano Zampini for (i=0;i<matis->sf_nleaves;i++) { 76028f4e0baSStefano Zampini matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols); 7612e1947a5SStefano Zampini } 76228f4e0baSStefano Zampini ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr); 76328f4e0baSStefano Zampini for (i=0;i<matis->sf_nleaves/bs;i++) { 76428f4e0baSStefano Zampini matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs; 7652e1947a5SStefano Zampini } 76628f4e0baSStefano Zampini ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 76728f4e0baSStefano Zampini for (i=0;i<matis->sf_nleaves/bs;i++) { 76828f4e0baSStefano Zampini matis->sf_leafdata[i] = matis->sf_leafdata[i]-i; 7692e1947a5SStefano Zampini } 77028f4e0baSStefano Zampini ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 7712e1947a5SStefano Zampini PetscFunctionReturn(0); 7722e1947a5SStefano Zampini } 773b4319ba4SBarry Smith 774b4319ba4SBarry Smith #undef __FUNCT__ 7753927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private" 7763927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce) 7773927de2eSStefano Zampini { 7783927de2eSStefano Zampini Mat_IS *matis = (Mat_IS*)(A->data); 7793927de2eSStefano Zampini PetscInt *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership; 780ecf5a873SStefano Zampini const PetscInt *global_indices_r,*global_indices_c; 7813927de2eSStefano Zampini PetscInt i,j,bs,rows,cols; 7823927de2eSStefano Zampini PetscInt lrows,lcols; 7833927de2eSStefano Zampini PetscInt local_rows,local_cols; 7843927de2eSStefano Zampini PetscMPIInt nsubdomains; 7853927de2eSStefano Zampini PetscBool isdense,issbaij; 7863927de2eSStefano Zampini PetscErrorCode ierr; 7873927de2eSStefano Zampini 7883927de2eSStefano Zampini PetscFunctionBegin; 7893927de2eSStefano Zampini ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr); 7903927de2eSStefano Zampini ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr); 7913927de2eSStefano Zampini ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 7923927de2eSStefano Zampini ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 7933927de2eSStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr); 7943927de2eSStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr); 795ecf5a873SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr); 796ecf5a873SStefano Zampini if (A->rmap->mapping != A->cmap->mapping) { 7977230de76SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr); 798ecf5a873SStefano Zampini } else { 799ecf5a873SStefano Zampini global_indices_c = global_indices_r; 800ecf5a873SStefano Zampini } 801ecf5a873SStefano Zampini 8023927de2eSStefano Zampini if (issbaij) { 8033927de2eSStefano Zampini ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr); 8043927de2eSStefano Zampini } 8053927de2eSStefano Zampini /* 806ecf5a873SStefano Zampini An SF reduce is needed to sum up properly on shared rows. 8073927de2eSStefano Zampini Note that generally preallocation is not exact, since it overestimates nonzeros 8083927de2eSStefano Zampini */ 8093927de2eSStefano Zampini if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */ 8103927de2eSStefano Zampini ierr = MatISComputeSF_Private(A);CHKERRQ(ierr); 8113927de2eSStefano Zampini } 8123927de2eSStefano Zampini ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr); 8133927de2eSStefano Zampini ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr); 8143927de2eSStefano Zampini /* All processes need to compute entire row ownership */ 8153927de2eSStefano Zampini ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr); 8163927de2eSStefano Zampini ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr); 8173927de2eSStefano Zampini for (i=0;i<nsubdomains;i++) { 8183927de2eSStefano Zampini for (j=mat_ranges[i];j<mat_ranges[i+1];j++) { 8193927de2eSStefano Zampini row_ownership[j] = i; 8203927de2eSStefano Zampini } 8213927de2eSStefano Zampini } 8227230de76SStefano Zampini ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr); 8233927de2eSStefano Zampini 8243927de2eSStefano Zampini /* 8253927de2eSStefano Zampini my_dnz and my_onz contains exact contribution to preallocation from each local mat 8263927de2eSStefano Zampini then, they will be summed up properly. This way, preallocation is always sufficient 8273927de2eSStefano Zampini */ 8283927de2eSStefano Zampini ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr); 8293927de2eSStefano Zampini /* preallocation as a MATAIJ */ 8303927de2eSStefano Zampini if (isdense) { /* special case for dense local matrices */ 8313927de2eSStefano Zampini for (i=0;i<local_rows;i++) { 832ecf5a873SStefano Zampini PetscInt index_row = global_indices_r[i]; 8333927de2eSStefano Zampini for (j=i;j<local_rows;j++) { 8343927de2eSStefano Zampini PetscInt owner = row_ownership[index_row]; 835ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[j]; 8363927de2eSStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 8373927de2eSStefano Zampini my_dnz[i] += 1; 8383927de2eSStefano Zampini } else { /* offdiag block */ 8393927de2eSStefano Zampini my_onz[i] += 1; 8403927de2eSStefano Zampini } 8413927de2eSStefano Zampini /* same as before, interchanging rows and cols */ 8423927de2eSStefano Zampini if (i != j) { 8433927de2eSStefano Zampini owner = row_ownership[index_col]; 8443927de2eSStefano Zampini if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 8453927de2eSStefano Zampini my_dnz[j] += 1; 8463927de2eSStefano Zampini } else { 8473927de2eSStefano Zampini my_onz[j] += 1; 8483927de2eSStefano Zampini } 8493927de2eSStefano Zampini } 8503927de2eSStefano Zampini } 8513927de2eSStefano Zampini } 852bb1015c3SStefano Zampini } else if (matis->A->ops->getrowij) { 853bb1015c3SStefano Zampini const PetscInt *ii,*jj,*jptr; 854bb1015c3SStefano Zampini PetscBool done; 855bb1015c3SStefano Zampini ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr); 856bb1015c3SStefano Zampini if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__); 857bb1015c3SStefano Zampini jptr = jj; 858bb1015c3SStefano Zampini for (i=0;i<local_rows;i++) { 859bb1015c3SStefano Zampini PetscInt index_row = global_indices_r[i]; 860bb1015c3SStefano Zampini for (j=0;j<ii[i+1]-ii[i];j++,jptr++) { 861bb1015c3SStefano Zampini PetscInt owner = row_ownership[index_row]; 862bb1015c3SStefano Zampini PetscInt index_col = global_indices_c[*jptr]; 863bb1015c3SStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 864bb1015c3SStefano Zampini my_dnz[i] += 1; 865bb1015c3SStefano Zampini } else { /* offdiag block */ 866bb1015c3SStefano Zampini my_onz[i] += 1; 867bb1015c3SStefano Zampini } 868bb1015c3SStefano Zampini /* same as before, interchanging rows and cols */ 869bb1015c3SStefano Zampini if (issbaij && index_col != index_row) { 870bb1015c3SStefano Zampini owner = row_ownership[index_col]; 871bb1015c3SStefano Zampini if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 872bb1015c3SStefano Zampini my_dnz[*jptr] += 1; 873bb1015c3SStefano Zampini } else { 874bb1015c3SStefano Zampini my_onz[*jptr] += 1; 875bb1015c3SStefano Zampini } 876bb1015c3SStefano Zampini } 877bb1015c3SStefano Zampini } 878bb1015c3SStefano Zampini } 879bb1015c3SStefano Zampini ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr); 880bb1015c3SStefano Zampini if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__); 881bb1015c3SStefano Zampini } else { /* loop over rows and use MatGetRow */ 8823927de2eSStefano Zampini for (i=0;i<local_rows;i++) { 8833927de2eSStefano Zampini const PetscInt *cols; 884ecf5a873SStefano Zampini PetscInt ncols,index_row = global_indices_r[i]; 8853927de2eSStefano Zampini ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 8863927de2eSStefano Zampini for (j=0;j<ncols;j++) { 8873927de2eSStefano Zampini PetscInt owner = row_ownership[index_row]; 888ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[cols[j]]; 8893927de2eSStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 8903927de2eSStefano Zampini my_dnz[i] += 1; 8913927de2eSStefano Zampini } else { /* offdiag block */ 8923927de2eSStefano Zampini my_onz[i] += 1; 8933927de2eSStefano Zampini } 8943927de2eSStefano Zampini /* same as before, interchanging rows and cols */ 895d9a9e74cSStefano Zampini if (issbaij && index_col != index_row) { 8963927de2eSStefano Zampini owner = row_ownership[index_col]; 8973927de2eSStefano Zampini if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 898d9a9e74cSStefano Zampini my_dnz[cols[j]] += 1; 8993927de2eSStefano Zampini } else { 900d9a9e74cSStefano Zampini my_onz[cols[j]] += 1; 9013927de2eSStefano Zampini } 9023927de2eSStefano Zampini } 9033927de2eSStefano Zampini } 9043927de2eSStefano Zampini ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 9053927de2eSStefano Zampini } 9063927de2eSStefano Zampini } 907ecf5a873SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr); 908ecf5a873SStefano Zampini if (global_indices_c != global_indices_r) { 9097230de76SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr); 910ecf5a873SStefano Zampini } 9113927de2eSStefano Zampini ierr = PetscFree(row_ownership);CHKERRQ(ierr); 912ecf5a873SStefano Zampini 913ecf5a873SStefano Zampini /* Reduce my_dnz and my_onz */ 9143927de2eSStefano Zampini if (maxreduce) { 9153927de2eSStefano Zampini ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 9163927de2eSStefano Zampini ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 917bb1015c3SStefano Zampini ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 9183927de2eSStefano Zampini ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 9193927de2eSStefano Zampini } else { 9203927de2eSStefano Zampini ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 9213927de2eSStefano Zampini ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 922bb1015c3SStefano Zampini ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 9233927de2eSStefano Zampini ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 9243927de2eSStefano Zampini } 9253927de2eSStefano Zampini ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr); 9263927de2eSStefano Zampini 9273927de2eSStefano Zampini /* Resize preallocation if overestimated */ 9283927de2eSStefano Zampini for (i=0;i<lrows;i++) { 9293927de2eSStefano Zampini dnz[i] = PetscMin(dnz[i],lcols); 9303927de2eSStefano Zampini onz[i] = PetscMin(onz[i],cols-lcols); 9313927de2eSStefano Zampini } 932*1670daf9Sstefano_zampini 933*1670daf9Sstefano_zampini /* Set preallocation */ 9343927de2eSStefano Zampini ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr); 9353927de2eSStefano Zampini for (i=0;i<lrows/bs;i++) { 9363927de2eSStefano Zampini dnz[i] = dnz[i*bs]/bs; 9373927de2eSStefano Zampini onz[i] = onz[i*bs]/bs; 9383927de2eSStefano Zampini } 9393927de2eSStefano Zampini ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 9403927de2eSStefano Zampini ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 9413927de2eSStefano Zampini ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 9423927de2eSStefano Zampini if (issbaij) { 9433927de2eSStefano Zampini ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr); 9443927de2eSStefano Zampini } 9453927de2eSStefano Zampini PetscFunctionReturn(0); 9463927de2eSStefano Zampini } 9473927de2eSStefano Zampini 9483927de2eSStefano Zampini #undef __FUNCT__ 949b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS" 9507230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M) 951b7ce53b6SStefano Zampini { 952b7ce53b6SStefano Zampini Mat_IS *matis = (Mat_IS*)(mat->data); 953d9a9e74cSStefano Zampini Mat local_mat; 954b7ce53b6SStefano Zampini /* info on mat */ 9553cfa4ea4SStefano Zampini PetscInt bs,rows,cols,lrows,lcols; 956b7ce53b6SStefano Zampini PetscInt local_rows,local_cols; 957686e3a49SStefano Zampini PetscBool isdense,issbaij,isseqaij; 9587c03b4e8SStefano Zampini PetscMPIInt nsubdomains; 959b7ce53b6SStefano Zampini /* values insertion */ 960b7ce53b6SStefano Zampini PetscScalar *array; 961b7ce53b6SStefano Zampini /* work */ 962b7ce53b6SStefano Zampini PetscErrorCode ierr; 963b7ce53b6SStefano Zampini 964b7ce53b6SStefano Zampini PetscFunctionBegin; 965b7ce53b6SStefano Zampini /* get info from mat */ 9667c03b4e8SStefano Zampini ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr); 9677c03b4e8SStefano Zampini if (nsubdomains == 1) { 968*1670daf9Sstefano_zampini Mat B; 969*1670daf9Sstefano_zampini IS rows,cols; 970*1670daf9Sstefano_zampini const PetscInt *ridxs,*cidxs; 971*1670daf9Sstefano_zampini 972*1670daf9Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr); 973*1670daf9Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr); 974*1670daf9Sstefano_zampini ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr); 975*1670daf9Sstefano_zampini ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr); 976*1670daf9Sstefano_zampini ierr = MatConvert(matis->A,MATAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr); 977*1670daf9Sstefano_zampini ierr = MatGetSubMatrix(B,rows,cols,reuse,M);CHKERRQ(ierr); 978*1670daf9Sstefano_zampini ierr = MatDestroy(&B);CHKERRQ(ierr); 979*1670daf9Sstefano_zampini ierr = ISDestroy(&cols);CHKERRQ(ierr); 980*1670daf9Sstefano_zampini ierr = ISDestroy(&rows);CHKERRQ(ierr); 981*1670daf9Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr); 982*1670daf9Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr); 9837c03b4e8SStefano Zampini PetscFunctionReturn(0); 9847c03b4e8SStefano Zampini } 985b7ce53b6SStefano Zampini ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr); 986b7ce53b6SStefano Zampini ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); 9873cfa4ea4SStefano Zampini ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr); 988b7ce53b6SStefano Zampini ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 989b7ce53b6SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr); 990686e3a49SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 991b7ce53b6SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr); 992b7ce53b6SStefano Zampini 993b7ce53b6SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 994b7ce53b6SStefano Zampini MatType new_mat_type; 9953927de2eSStefano Zampini PetscBool issbaij_red; 996b7ce53b6SStefano Zampini 997b7ce53b6SStefano Zampini /* determining new matrix type */ 998b2566f29SBarry Smith ierr = MPIU_Allreduce(&issbaij,&issbaij_red,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 999b7ce53b6SStefano Zampini if (issbaij_red) { 1000b7ce53b6SStefano Zampini new_mat_type = MATSBAIJ; 1001b7ce53b6SStefano Zampini } else { 1002b7ce53b6SStefano Zampini if (bs>1) { 1003b7ce53b6SStefano Zampini new_mat_type = MATBAIJ; 1004b7ce53b6SStefano Zampini } else { 1005b7ce53b6SStefano Zampini new_mat_type = MATAIJ; 1006b7ce53b6SStefano Zampini } 1007b7ce53b6SStefano Zampini } 1008b7ce53b6SStefano Zampini 10093927de2eSStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr); 10103cfa4ea4SStefano Zampini ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr); 10113927de2eSStefano Zampini ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr); 10123927de2eSStefano Zampini ierr = MatSetType(*M,new_mat_type);CHKERRQ(ierr); 10133927de2eSStefano Zampini ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr); 1014b7ce53b6SStefano Zampini } else { 10153cfa4ea4SStefano Zampini PetscInt mbs,mrows,mcols,mlrows,mlcols; 1016b7ce53b6SStefano Zampini /* some checks */ 1017b7ce53b6SStefano Zampini ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr); 1018b7ce53b6SStefano Zampini ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr); 10193cfa4ea4SStefano Zampini ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr); 10206c4ed002SBarry Smith if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows); 10216c4ed002SBarry Smith if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols); 10226c4ed002SBarry Smith if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows); 10236c4ed002SBarry Smith if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols); 10246c4ed002SBarry Smith if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs); 1025b7ce53b6SStefano Zampini ierr = MatZeroEntries(*M);CHKERRQ(ierr); 1026b7ce53b6SStefano Zampini } 1027d9a9e74cSStefano Zampini 1028d9a9e74cSStefano Zampini if (issbaij) { 1029d9a9e74cSStefano Zampini ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr); 1030d9a9e74cSStefano Zampini } else { 1031d9a9e74cSStefano Zampini ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 1032d9a9e74cSStefano Zampini local_mat = matis->A; 1033d9a9e74cSStefano Zampini } 1034686e3a49SStefano Zampini 1035b7ce53b6SStefano Zampini /* Set values */ 1036ecf5a873SStefano Zampini ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr); 1037b7ce53b6SStefano Zampini if (isdense) { /* special case for dense local matrices */ 1038ecf5a873SStefano Zampini PetscInt i,*dummy_rows,*dummy_cols; 1039ecf5a873SStefano Zampini 1040ecf5a873SStefano Zampini if (local_rows != local_cols) { 1041ecf5a873SStefano Zampini ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr); 1042ecf5a873SStefano Zampini for (i=0;i<local_rows;i++) dummy_rows[i] = i; 1043ecf5a873SStefano Zampini for (i=0;i<local_cols;i++) dummy_cols[i] = i; 1044ecf5a873SStefano Zampini } else { 1045ecf5a873SStefano Zampini ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr); 1046ecf5a873SStefano Zampini for (i=0;i<local_rows;i++) dummy_rows[i] = i; 1047ecf5a873SStefano Zampini dummy_cols = dummy_rows; 1048ecf5a873SStefano Zampini } 1049b7ce53b6SStefano Zampini ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 1050d9a9e74cSStefano Zampini ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr); 1051ecf5a873SStefano Zampini ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr); 1052d9a9e74cSStefano Zampini ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr); 1053ecf5a873SStefano Zampini if (dummy_rows != dummy_cols) { 1054ecf5a873SStefano Zampini ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr); 1055ecf5a873SStefano Zampini } else { 1056ecf5a873SStefano Zampini ierr = PetscFree(dummy_rows);CHKERRQ(ierr); 1057ecf5a873SStefano Zampini } 1058686e3a49SStefano Zampini } else if (isseqaij) { 1059ecf5a873SStefano Zampini PetscInt i,nvtxs,*xadj,*adjncy; 1060686e3a49SStefano Zampini PetscBool done; 1061686e3a49SStefano Zampini 1062d9a9e74cSStefano Zampini ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 1063bb1015c3SStefano Zampini if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__); 1064d9a9e74cSStefano Zampini ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr); 1065686e3a49SStefano Zampini for (i=0;i<nvtxs;i++) { 1066ecf5a873SStefano Zampini ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr); 1067686e3a49SStefano Zampini } 1068d9a9e74cSStefano Zampini ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 1069bb1015c3SStefano Zampini if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__); 1070d9a9e74cSStefano Zampini ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr); 1071686e3a49SStefano Zampini } else { /* very basic values insertion for all other matrix types */ 1072ecf5a873SStefano Zampini PetscInt i; 1073c0962df8SStefano Zampini 1074686e3a49SStefano Zampini for (i=0;i<local_rows;i++) { 1075686e3a49SStefano Zampini PetscInt j; 1076ecf5a873SStefano Zampini const PetscInt *local_indices_cols; 1077686e3a49SStefano Zampini 1078ecf5a873SStefano Zampini ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr); 1079ecf5a873SStefano Zampini ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr); 1080ecf5a873SStefano Zampini ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr); 1081686e3a49SStefano Zampini } 1082b7ce53b6SStefano Zampini } 1083b7ce53b6SStefano Zampini ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1084d9a9e74cSStefano Zampini ierr = MatDestroy(&local_mat);CHKERRQ(ierr); 1085b7ce53b6SStefano Zampini ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1086b7ce53b6SStefano Zampini if (isdense) { 1087b7ce53b6SStefano Zampini ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr); 1088b7ce53b6SStefano Zampini } 1089b7ce53b6SStefano Zampini PetscFunctionReturn(0); 1090b7ce53b6SStefano Zampini } 1091b7ce53b6SStefano Zampini 1092b7ce53b6SStefano Zampini #undef __FUNCT__ 1093b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ" 1094b7ce53b6SStefano Zampini /*@ 1095b7ce53b6SStefano Zampini MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format 1096b7ce53b6SStefano Zampini 1097b7ce53b6SStefano Zampini Input Parameter: 1098b7ce53b6SStefano Zampini . mat - the matrix (should be of type MATIS) 1099b7ce53b6SStefano Zampini . reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 1100b7ce53b6SStefano Zampini 1101b7ce53b6SStefano Zampini Output Parameter: 1102b7ce53b6SStefano Zampini . newmat - the matrix in AIJ format 1103b7ce53b6SStefano Zampini 1104b7ce53b6SStefano Zampini Level: developer 1105b7ce53b6SStefano Zampini 1106eb82efa4SStefano Zampini Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested. 1107b7ce53b6SStefano Zampini 1108b7ce53b6SStefano Zampini .seealso: MATIS 1109b7ce53b6SStefano Zampini @*/ 1110b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat) 1111b7ce53b6SStefano Zampini { 1112b7ce53b6SStefano Zampini PetscErrorCode ierr; 1113b7ce53b6SStefano Zampini 1114b7ce53b6SStefano Zampini PetscFunctionBegin; 1115b7ce53b6SStefano Zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1116b7ce53b6SStefano Zampini PetscValidLogicalCollectiveEnum(mat,reuse,2); 1117b7ce53b6SStefano Zampini PetscValidPointer(newmat,3); 1118b7ce53b6SStefano Zampini if (reuse != MAT_INITIAL_MATRIX) { 1119b7ce53b6SStefano Zampini PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3); 1120b7ce53b6SStefano Zampini PetscCheckSameComm(mat,1,*newmat,3); 11216c4ed002SBarry Smith if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix"); 1122b7ce53b6SStefano Zampini } 1123b7ce53b6SStefano Zampini ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr); 1124b7ce53b6SStefano Zampini PetscFunctionReturn(0); 1125b7ce53b6SStefano Zampini } 1126b7ce53b6SStefano Zampini 1127b7ce53b6SStefano Zampini #undef __FUNCT__ 1128ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS" 1129ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat) 1130ad6194a2SStefano Zampini { 1131ad6194a2SStefano Zampini PetscErrorCode ierr; 1132ad6194a2SStefano Zampini Mat_IS *matis = (Mat_IS*)(mat->data); 1133ad6194a2SStefano Zampini PetscInt bs,m,n,M,N; 1134ad6194a2SStefano Zampini Mat B,localmat; 1135ad6194a2SStefano Zampini 1136ad6194a2SStefano Zampini PetscFunctionBegin; 1137ad6194a2SStefano Zampini ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); 1138ad6194a2SStefano Zampini ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 1139ad6194a2SStefano Zampini ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr); 1140e176bc59SStefano Zampini ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr); 1141ad6194a2SStefano Zampini ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr); 1142ad6194a2SStefano Zampini ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr); 1143b3317aa8SStefano Zampini ierr = MatDestroy(&localmat);CHKERRQ(ierr); 1144ad6194a2SStefano Zampini ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1145ad6194a2SStefano Zampini ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1146ad6194a2SStefano Zampini *newmat = B; 1147ad6194a2SStefano Zampini PetscFunctionReturn(0); 1148ad6194a2SStefano Zampini } 1149ad6194a2SStefano Zampini 1150ad6194a2SStefano Zampini #undef __FUNCT__ 115169796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS" 1152a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool *flg) 115369796d55SStefano Zampini { 115469796d55SStefano Zampini PetscErrorCode ierr; 115569796d55SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 115669796d55SStefano Zampini PetscBool local_sym; 115769796d55SStefano Zampini 115869796d55SStefano Zampini PetscFunctionBegin; 115969796d55SStefano Zampini ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr); 1160b2566f29SBarry Smith ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 116169796d55SStefano Zampini PetscFunctionReturn(0); 116269796d55SStefano Zampini } 116369796d55SStefano Zampini 116469796d55SStefano Zampini #undef __FUNCT__ 116569796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS" 1166a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg) 116769796d55SStefano Zampini { 116869796d55SStefano Zampini PetscErrorCode ierr; 116969796d55SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 117069796d55SStefano Zampini PetscBool local_sym; 117169796d55SStefano Zampini 117269796d55SStefano Zampini PetscFunctionBegin; 117369796d55SStefano Zampini ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr); 1174b2566f29SBarry Smith ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 117569796d55SStefano Zampini PetscFunctionReturn(0); 117669796d55SStefano Zampini } 117769796d55SStefano Zampini 117869796d55SStefano Zampini #undef __FUNCT__ 1179b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS" 1180a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A) 1181b4319ba4SBarry Smith { 1182dfbe8321SBarry Smith PetscErrorCode ierr; 1183b4319ba4SBarry Smith Mat_IS *b = (Mat_IS*)A->data; 1184b4319ba4SBarry Smith 1185b4319ba4SBarry Smith PetscFunctionBegin; 11866bf464f9SBarry Smith ierr = MatDestroy(&b->A);CHKERRQ(ierr); 1187e176bc59SStefano Zampini ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr); 1188e176bc59SStefano Zampini ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr); 11896bf464f9SBarry Smith ierr = VecDestroy(&b->x);CHKERRQ(ierr); 11906bf464f9SBarry Smith ierr = VecDestroy(&b->y);CHKERRQ(ierr); 11913fd1c9e7SStefano Zampini ierr = VecDestroy(&b->counter);CHKERRQ(ierr); 1192a8116848SStefano Zampini ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr); 1193a8116848SStefano Zampini ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr); 1194a8116848SStefano Zampini if (b->sf != b->csf) { 1195a8116848SStefano Zampini ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr); 1196a8116848SStefano Zampini ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr); 1197a8116848SStefano Zampini } 119828f4e0baSStefano Zampini ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr); 119928f4e0baSStefano Zampini ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr); 1200bf0cc555SLisandro Dalcin ierr = PetscFree(A->data);CHKERRQ(ierr); 1201dbd8c25aSHong Zhang ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 1202bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr); 1203b7ce53b6SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr); 1204b7ce53b6SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr); 12052e1947a5SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr); 1206b4319ba4SBarry Smith PetscFunctionReturn(0); 1207b4319ba4SBarry Smith } 1208b4319ba4SBarry Smith 1209b4319ba4SBarry Smith #undef __FUNCT__ 1210b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS" 1211a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y) 1212b4319ba4SBarry Smith { 1213dfbe8321SBarry Smith PetscErrorCode ierr; 1214b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1215b4319ba4SBarry Smith PetscScalar zero = 0.0; 1216b4319ba4SBarry Smith 1217b4319ba4SBarry Smith PetscFunctionBegin; 1218b4319ba4SBarry Smith /* scatter the global vector x into the local work vector */ 1219e176bc59SStefano Zampini ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1220e176bc59SStefano Zampini ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1221b4319ba4SBarry Smith 1222b4319ba4SBarry Smith /* multiply the local matrix */ 1223b4319ba4SBarry Smith ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr); 1224b4319ba4SBarry Smith 1225b4319ba4SBarry Smith /* scatter product back into global memory */ 12262dcb1b2aSMatthew Knepley ierr = VecSet(y,zero);CHKERRQ(ierr); 1227e176bc59SStefano Zampini ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1228e176bc59SStefano Zampini ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1229b4319ba4SBarry Smith PetscFunctionReturn(0); 1230b4319ba4SBarry Smith } 1231b4319ba4SBarry Smith 1232b4319ba4SBarry Smith #undef __FUNCT__ 12332e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS" 1234a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 12352e74eeadSLisandro Dalcin { 1236650997f4SStefano Zampini Vec temp_vec; 12372e74eeadSLisandro Dalcin PetscErrorCode ierr; 12382e74eeadSLisandro Dalcin 12392e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 1240650997f4SStefano Zampini if (v3 != v2) { 1241650997f4SStefano Zampini ierr = MatMult(A,v1,v3);CHKERRQ(ierr); 1242650997f4SStefano Zampini ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 1243650997f4SStefano Zampini } else { 1244650997f4SStefano Zampini ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 1245650997f4SStefano Zampini ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr); 1246650997f4SStefano Zampini ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 1247650997f4SStefano Zampini ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 1248650997f4SStefano Zampini ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 1249650997f4SStefano Zampini } 12502e74eeadSLisandro Dalcin PetscFunctionReturn(0); 12512e74eeadSLisandro Dalcin } 12522e74eeadSLisandro Dalcin 12532e74eeadSLisandro Dalcin #undef __FUNCT__ 12542e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS" 1255a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x) 12562e74eeadSLisandro Dalcin { 12572e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 12582e74eeadSLisandro Dalcin PetscErrorCode ierr; 12592e74eeadSLisandro Dalcin 1260e176bc59SStefano Zampini PetscFunctionBegin; 12612e74eeadSLisandro Dalcin /* scatter the global vector x into the local work vector */ 1262e176bc59SStefano Zampini ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1263e176bc59SStefano Zampini ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 12642e74eeadSLisandro Dalcin 12652e74eeadSLisandro Dalcin /* multiply the local matrix */ 1266e176bc59SStefano Zampini ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr); 12672e74eeadSLisandro Dalcin 12682e74eeadSLisandro Dalcin /* scatter product back into global vector */ 1269e176bc59SStefano Zampini ierr = VecSet(x,0);CHKERRQ(ierr); 1270e176bc59SStefano Zampini ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1271e176bc59SStefano Zampini ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 12722e74eeadSLisandro Dalcin PetscFunctionReturn(0); 12732e74eeadSLisandro Dalcin } 12742e74eeadSLisandro Dalcin 12752e74eeadSLisandro Dalcin #undef __FUNCT__ 12762e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS" 1277a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 12782e74eeadSLisandro Dalcin { 1279650997f4SStefano Zampini Vec temp_vec; 12802e74eeadSLisandro Dalcin PetscErrorCode ierr; 12812e74eeadSLisandro Dalcin 12822e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 1283650997f4SStefano Zampini if (v3 != v2) { 1284650997f4SStefano Zampini ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr); 1285650997f4SStefano Zampini ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 1286650997f4SStefano Zampini } else { 1287650997f4SStefano Zampini ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 1288650997f4SStefano Zampini ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr); 1289650997f4SStefano Zampini ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 1290650997f4SStefano Zampini ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 1291650997f4SStefano Zampini ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 1292650997f4SStefano Zampini } 12932e74eeadSLisandro Dalcin PetscFunctionReturn(0); 12942e74eeadSLisandro Dalcin } 12952e74eeadSLisandro Dalcin 12962e74eeadSLisandro Dalcin #undef __FUNCT__ 1297b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS" 1298a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer) 1299b4319ba4SBarry Smith { 1300b4319ba4SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 1301dfbe8321SBarry Smith PetscErrorCode ierr; 1302b4319ba4SBarry Smith PetscViewer sviewer; 1303b4319ba4SBarry Smith 1304b4319ba4SBarry Smith PetscFunctionBegin; 13053f08860eSBarry Smith ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 1306b4319ba4SBarry Smith ierr = MatView(a->A,sviewer);CHKERRQ(ierr); 13073f08860eSBarry Smith ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 13086e520ac8SStefano Zampini ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1309b4319ba4SBarry Smith PetscFunctionReturn(0); 1310b4319ba4SBarry Smith } 1311b4319ba4SBarry Smith 1312b4319ba4SBarry Smith #undef __FUNCT__ 1313b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS" 1314a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping) 1315b4319ba4SBarry Smith { 1316dfbe8321SBarry Smith PetscErrorCode ierr; 1317e176bc59SStefano Zampini PetscInt nr,rbs,nc,cbs; 1318b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1319b4319ba4SBarry Smith IS from,to; 1320e176bc59SStefano Zampini Vec cglobal,rglobal; 1321b4319ba4SBarry Smith 1322b4319ba4SBarry Smith PetscFunctionBegin; 1323784ac674SJed Brown PetscCheckSameComm(A,1,rmapping,2); 1324e176bc59SStefano Zampini PetscCheckSameComm(A,1,cmapping,3); 13253bbff08aSStefano Zampini /* Destroy any previous data */ 132670cf5478SStefano Zampini ierr = VecDestroy(&is->x);CHKERRQ(ierr); 132770cf5478SStefano Zampini ierr = VecDestroy(&is->y);CHKERRQ(ierr); 13283fd1c9e7SStefano Zampini ierr = VecDestroy(&is->counter);CHKERRQ(ierr); 1329e176bc59SStefano Zampini ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr); 1330e176bc59SStefano Zampini ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr); 13311c47cb0fSStefano Zampini ierr = MatDestroy(&is->A);CHKERRQ(ierr); 133228f4e0baSStefano Zampini ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr); 133328f4e0baSStefano Zampini ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr); 13343bbff08aSStefano Zampini 13353bbff08aSStefano Zampini /* Setup Layout and set local to global maps */ 1336fc27028aSStefano Zampini ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 1337fc27028aSStefano Zampini ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 1338fa7f1dd8SStefano Zampini ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr); 1339fa7f1dd8SStefano Zampini ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr); 1340b4319ba4SBarry Smith 1341b4319ba4SBarry Smith /* Create the local matrix A */ 1342e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr); 1343e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr); 1344e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr); 1345e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr); 1346f69a0ea3SMatthew Knepley ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr); 1347e176bc59SStefano Zampini ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr); 1348e176bc59SStefano Zampini ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr); 1349e176bc59SStefano Zampini ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr); 1350ff130e51SJed Brown ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr); 1351ff130e51SJed Brown ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr); 1352b4319ba4SBarry Smith ierr = MatSetFromOptions(is->A);CHKERRQ(ierr); 1353b4319ba4SBarry Smith 1354f26d0771SStefano Zampini if (!is->islocalref) { /* setup scatters and local vectors for MatMult */ 1355b4319ba4SBarry Smith /* Create the local work vectors */ 13563bbff08aSStefano Zampini ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr); 1357b4319ba4SBarry Smith 1358e176bc59SStefano Zampini /* setup the global to local scatters */ 1359e176bc59SStefano Zampini ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr); 1360e176bc59SStefano Zampini ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr); 1361784ac674SJed Brown ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr); 1362e176bc59SStefano Zampini ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr); 1363e176bc59SStefano Zampini if (rmapping != cmapping) { 1364e176bc59SStefano Zampini ierr = ISDestroy(&to);CHKERRQ(ierr); 1365e176bc59SStefano Zampini ierr = ISDestroy(&from);CHKERRQ(ierr); 1366e176bc59SStefano Zampini ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr); 1367e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr); 1368e176bc59SStefano Zampini ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr); 1369e176bc59SStefano Zampini } else { 1370e176bc59SStefano Zampini ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr); 1371e176bc59SStefano Zampini is->cctx = is->rctx; 1372e176bc59SStefano Zampini } 13733fd1c9e7SStefano Zampini 13743fd1c9e7SStefano Zampini /* interface counter vector (local) */ 13753fd1c9e7SStefano Zampini ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr); 13763fd1c9e7SStefano Zampini ierr = VecSet(is->y,1.);CHKERRQ(ierr); 13773fd1c9e7SStefano Zampini ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 13783fd1c9e7SStefano Zampini ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 13793fd1c9e7SStefano Zampini ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 13803fd1c9e7SStefano Zampini ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 13813fd1c9e7SStefano Zampini 13823fd1c9e7SStefano Zampini /* free workspace */ 1383e176bc59SStefano Zampini ierr = VecDestroy(&rglobal);CHKERRQ(ierr); 1384e176bc59SStefano Zampini ierr = VecDestroy(&cglobal);CHKERRQ(ierr); 13856bf464f9SBarry Smith ierr = ISDestroy(&to);CHKERRQ(ierr); 13866bf464f9SBarry Smith ierr = ISDestroy(&from);CHKERRQ(ierr); 1387f26d0771SStefano Zampini } 138848ff6bf3SStefano Zampini ierr = MatSetUp(A);CHKERRQ(ierr); 1389b4319ba4SBarry Smith PetscFunctionReturn(0); 1390b4319ba4SBarry Smith } 1391b4319ba4SBarry Smith 13922e74eeadSLisandro Dalcin #undef __FUNCT__ 13932e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS" 1394a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 13952e74eeadSLisandro Dalcin { 13962e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)mat->data; 13972e74eeadSLisandro Dalcin PetscErrorCode ierr; 139897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 139997563a80SStefano Zampini PetscInt i,zm,zn; 140097563a80SStefano Zampini #endif 1401f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 14022e74eeadSLisandro Dalcin 14032e74eeadSLisandro Dalcin PetscFunctionBegin; 14042e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG) 1405f26d0771SStefano 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); 140697563a80SStefano Zampini /* count negative indices */ 140797563a80SStefano Zampini for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++; 140897563a80SStefano Zampini for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++; 14092e74eeadSLisandro Dalcin #endif 141097563a80SStefano Zampini ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr); 141197563a80SStefano Zampini ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr); 141297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 141397563a80SStefano Zampini /* count negative indices (should be the same as before) */ 141497563a80SStefano Zampini for (i=0;i<m;i++) if (rows_l[i] < 0) zm--; 141597563a80SStefano Zampini for (i=0;i<n;i++) if (cols_l[i] < 0) zn--; 141697563a80SStefano Zampini if (zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS"); 141797563a80SStefano Zampini if (zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS"); 141897563a80SStefano Zampini #endif 14192e74eeadSLisandro Dalcin ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 14202e74eeadSLisandro Dalcin PetscFunctionReturn(0); 14212e74eeadSLisandro Dalcin } 14222e74eeadSLisandro Dalcin 1423b4319ba4SBarry Smith #undef __FUNCT__ 142497563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS" 1425a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 142697563a80SStefano Zampini { 142797563a80SStefano Zampini Mat_IS *is = (Mat_IS*)mat->data; 142897563a80SStefano Zampini PetscErrorCode ierr; 142997563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 143097563a80SStefano Zampini PetscInt i,zm,zn; 143197563a80SStefano Zampini #endif 1432f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 143397563a80SStefano Zampini 143497563a80SStefano Zampini PetscFunctionBegin; 143597563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 1436f26d0771SStefano 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); 143797563a80SStefano Zampini /* count negative indices */ 143897563a80SStefano Zampini for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++; 143997563a80SStefano Zampini for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++; 144097563a80SStefano Zampini #endif 144197563a80SStefano Zampini ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr); 144297563a80SStefano Zampini ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr); 144397563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 144497563a80SStefano Zampini /* count negative indices (should be the same as before) */ 144597563a80SStefano Zampini for (i=0;i<m;i++) if (rows_l[i] < 0) zm--; 144697563a80SStefano Zampini for (i=0;i<n;i++) if (cols_l[i] < 0) zn--; 144797563a80SStefano Zampini if (zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS"); 144897563a80SStefano Zampini if (zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS"); 144997563a80SStefano Zampini #endif 145097563a80SStefano Zampini ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 145197563a80SStefano Zampini PetscFunctionReturn(0); 145297563a80SStefano Zampini } 145397563a80SStefano Zampini 145497563a80SStefano Zampini #undef __FUNCT__ 1455b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS" 1456a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1457b4319ba4SBarry Smith { 1458dfbe8321SBarry Smith PetscErrorCode ierr; 1459b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1460b4319ba4SBarry Smith 1461b4319ba4SBarry Smith PetscFunctionBegin; 1462b4319ba4SBarry Smith ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 1463b4319ba4SBarry Smith PetscFunctionReturn(0); 1464b4319ba4SBarry Smith } 1465b4319ba4SBarry Smith 1466b4319ba4SBarry Smith #undef __FUNCT__ 1467f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS" 1468a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1469f0006bf2SLisandro Dalcin { 1470f0006bf2SLisandro Dalcin PetscErrorCode ierr; 1471f0006bf2SLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 1472f0006bf2SLisandro Dalcin 1473f0006bf2SLisandro Dalcin PetscFunctionBegin; 1474f0006bf2SLisandro Dalcin ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 1475f0006bf2SLisandro Dalcin PetscFunctionReturn(0); 1476f0006bf2SLisandro Dalcin } 1477f0006bf2SLisandro Dalcin 1478f0006bf2SLisandro Dalcin #undef __FUNCT__ 1479f0ae7da4SStefano Zampini #define __FUNCT__ "MatISZeroRowsColumnsLocal_Private" 1480f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns) 1481f0ae7da4SStefano Zampini { 1482f0ae7da4SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 1483f0ae7da4SStefano Zampini PetscErrorCode ierr; 1484f0ae7da4SStefano Zampini 1485f0ae7da4SStefano Zampini PetscFunctionBegin; 1486f0ae7da4SStefano Zampini if (!n) { 1487f0ae7da4SStefano Zampini is->pure_neumann = PETSC_TRUE; 1488f0ae7da4SStefano Zampini } else { 1489f0ae7da4SStefano Zampini PetscInt i; 1490f0ae7da4SStefano Zampini is->pure_neumann = PETSC_FALSE; 1491f0ae7da4SStefano Zampini 1492f0ae7da4SStefano Zampini if (columns) { 1493f0ae7da4SStefano Zampini ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 1494f0ae7da4SStefano Zampini } else { 1495f0ae7da4SStefano Zampini ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 1496f0ae7da4SStefano Zampini } 1497f0ae7da4SStefano Zampini if (diag != 0.) { 1498f0ae7da4SStefano Zampini const PetscScalar *array; 1499f0ae7da4SStefano Zampini ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr); 1500f0ae7da4SStefano Zampini for (i=0; i<n; i++) { 1501f0ae7da4SStefano Zampini ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr); 1502f0ae7da4SStefano Zampini } 1503f0ae7da4SStefano Zampini ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr); 1504f0ae7da4SStefano Zampini } 1505f0ae7da4SStefano Zampini ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1506f0ae7da4SStefano Zampini ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1507f0ae7da4SStefano Zampini } 1508f0ae7da4SStefano Zampini PetscFunctionReturn(0); 1509f0ae7da4SStefano Zampini } 1510f0ae7da4SStefano Zampini 1511f0ae7da4SStefano Zampini #undef __FUNCT__ 1512f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_Private_IS" 1513f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns) 15142e74eeadSLisandro Dalcin { 15156e520ac8SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 15166e520ac8SStefano Zampini PetscInt nr,nl,len,i; 15176e520ac8SStefano Zampini PetscInt *lrows; 15182e74eeadSLisandro Dalcin PetscErrorCode ierr; 15192e74eeadSLisandro Dalcin 15202e74eeadSLisandro Dalcin PetscFunctionBegin; 1521f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG) 1522f0ae7da4SStefano Zampini if (columns || diag != 0. || (x && b)) { 1523f0ae7da4SStefano Zampini PetscBool cong; 1524f0ae7da4SStefano Zampini ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr); 1525f0ae7da4SStefano 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 for MATIS"); 1526f0ae7da4SStefano 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 for MATIS"); 1527f0ae7da4SStefano Zampini if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent"); 1528f0ae7da4SStefano Zampini } 1529f0ae7da4SStefano Zampini #endif 15306e520ac8SStefano Zampini /* get locally owned rows */ 1531f0ae7da4SStefano Zampini ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr); 15326e520ac8SStefano Zampini /* fix right hand side if needed */ 15336e520ac8SStefano Zampini if (x && b) { 15346e520ac8SStefano Zampini const PetscScalar *xx; 15356e520ac8SStefano Zampini PetscScalar *bb; 15366e520ac8SStefano Zampini 15376e520ac8SStefano Zampini ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr); 15386e520ac8SStefano Zampini ierr = VecGetArray(b, &bb);CHKERRQ(ierr); 15396e520ac8SStefano Zampini for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]]; 15406e520ac8SStefano Zampini ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr); 15416e520ac8SStefano Zampini ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr); 15422e74eeadSLisandro Dalcin } 15436e520ac8SStefano Zampini /* get rows associated to the local matrices */ 15446e520ac8SStefano Zampini if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */ 15456e520ac8SStefano Zampini ierr = MatISComputeSF_Private(A);CHKERRQ(ierr); 15466e520ac8SStefano Zampini } 15476e520ac8SStefano Zampini ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr); 15486e520ac8SStefano Zampini ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr); 15496e520ac8SStefano Zampini ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 15506e520ac8SStefano Zampini for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1; 15516e520ac8SStefano Zampini ierr = PetscFree(lrows);CHKERRQ(ierr); 15526e520ac8SStefano Zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 15536e520ac8SStefano Zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 15546e520ac8SStefano Zampini ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr); 15556e520ac8SStefano Zampini for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i; 1556f0ae7da4SStefano Zampini ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr); 15576e520ac8SStefano Zampini ierr = PetscFree(lrows);CHKERRQ(ierr); 15582e74eeadSLisandro Dalcin PetscFunctionReturn(0); 15592e74eeadSLisandro Dalcin } 15602e74eeadSLisandro Dalcin 15612e74eeadSLisandro Dalcin #undef __FUNCT__ 1562f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRows_IS" 1563f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1564b4319ba4SBarry Smith { 1565dfbe8321SBarry Smith PetscErrorCode ierr; 1566b4319ba4SBarry Smith 1567b4319ba4SBarry Smith PetscFunctionBegin; 1568f0ae7da4SStefano Zampini ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr); 1569f0ae7da4SStefano Zampini PetscFunctionReturn(0); 1570f0ae7da4SStefano Zampini } 15712205254eSKarl Rupp 1572f0ae7da4SStefano Zampini #undef __FUNCT__ 1573f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_IS" 1574f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1575f0ae7da4SStefano Zampini { 1576f0ae7da4SStefano Zampini PetscErrorCode ierr; 1577f0ae7da4SStefano Zampini 1578f0ae7da4SStefano Zampini PetscFunctionBegin; 1579f0ae7da4SStefano Zampini ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr); 1580b4319ba4SBarry Smith PetscFunctionReturn(0); 1581b4319ba4SBarry Smith } 1582b4319ba4SBarry Smith 1583b4319ba4SBarry Smith #undef __FUNCT__ 1584b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS" 1585a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type) 1586b4319ba4SBarry Smith { 1587b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1588dfbe8321SBarry Smith PetscErrorCode ierr; 1589b4319ba4SBarry Smith 1590b4319ba4SBarry Smith PetscFunctionBegin; 1591b4319ba4SBarry Smith ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr); 1592b4319ba4SBarry Smith PetscFunctionReturn(0); 1593b4319ba4SBarry Smith } 1594b4319ba4SBarry Smith 1595b4319ba4SBarry Smith #undef __FUNCT__ 1596b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS" 1597a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type) 1598b4319ba4SBarry Smith { 1599b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1600dfbe8321SBarry Smith PetscErrorCode ierr; 1601b4319ba4SBarry Smith 1602b4319ba4SBarry Smith PetscFunctionBegin; 1603b4319ba4SBarry Smith ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr); 1604b4319ba4SBarry Smith PetscFunctionReturn(0); 1605b4319ba4SBarry Smith } 1606b4319ba4SBarry Smith 1607b4319ba4SBarry Smith #undef __FUNCT__ 1608b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS" 1609a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local) 1610b4319ba4SBarry Smith { 1611b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)mat->data; 1612b4319ba4SBarry Smith 1613b4319ba4SBarry Smith PetscFunctionBegin; 1614b4319ba4SBarry Smith *local = is->A; 1615b4319ba4SBarry Smith PetscFunctionReturn(0); 1616b4319ba4SBarry Smith } 1617b4319ba4SBarry Smith 1618b4319ba4SBarry Smith #undef __FUNCT__ 1619b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat" 1620b4319ba4SBarry Smith /*@ 1621b4319ba4SBarry Smith MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix. 1622b4319ba4SBarry Smith 1623b4319ba4SBarry Smith Input Parameter: 1624b4319ba4SBarry Smith . mat - the matrix 1625b4319ba4SBarry Smith 1626b4319ba4SBarry Smith Output Parameter: 1627eb82efa4SStefano Zampini . local - the local matrix 1628b4319ba4SBarry Smith 1629b4319ba4SBarry Smith Level: advanced 1630b4319ba4SBarry Smith 1631b4319ba4SBarry Smith Notes: 1632b4319ba4SBarry Smith This can be called if you have precomputed the nonzero structure of the 1633b4319ba4SBarry Smith matrix and want to provide it to the inner matrix object to improve the performance 1634b4319ba4SBarry Smith of the MatSetValues() operation. 1635b4319ba4SBarry Smith 1636b4319ba4SBarry Smith .seealso: MATIS 1637b4319ba4SBarry Smith @*/ 16387087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local) 1639b4319ba4SBarry Smith { 16404ac538c5SBarry Smith PetscErrorCode ierr; 1641b4319ba4SBarry Smith 1642b4319ba4SBarry Smith PetscFunctionBegin; 16430700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1644b4319ba4SBarry Smith PetscValidPointer(local,2); 16454ac538c5SBarry Smith ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr); 1646b4319ba4SBarry Smith PetscFunctionReturn(0); 1647b4319ba4SBarry Smith } 1648b4319ba4SBarry Smith 16493b03a366Sstefano_zampini #undef __FUNCT__ 16503b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS" 1651a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local) 16523b03a366Sstefano_zampini { 16533b03a366Sstefano_zampini Mat_IS *is = (Mat_IS*)mat->data; 16543b03a366Sstefano_zampini PetscInt nrows,ncols,orows,ocols; 16553b03a366Sstefano_zampini PetscErrorCode ierr; 16563b03a366Sstefano_zampini 16573b03a366Sstefano_zampini PetscFunctionBegin; 16584e4c7dbeSStefano Zampini if (is->A) { 16593b03a366Sstefano_zampini ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr); 16603b03a366Sstefano_zampini ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr); 1661f0ae7da4SStefano 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); 16624e4c7dbeSStefano Zampini } 16633b03a366Sstefano_zampini ierr = PetscObjectReference((PetscObject)local);CHKERRQ(ierr); 16643b03a366Sstefano_zampini ierr = MatDestroy(&is->A);CHKERRQ(ierr); 16653b03a366Sstefano_zampini is->A = local; 16663b03a366Sstefano_zampini PetscFunctionReturn(0); 16673b03a366Sstefano_zampini } 16683b03a366Sstefano_zampini 16693b03a366Sstefano_zampini #undef __FUNCT__ 16703b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat" 16713b03a366Sstefano_zampini /*@ 1672eb82efa4SStefano Zampini MatISSetLocalMat - Replace the local matrix stored inside a MATIS object. 16733b03a366Sstefano_zampini 16743b03a366Sstefano_zampini Input Parameter: 16753b03a366Sstefano_zampini . mat - the matrix 1676eb82efa4SStefano Zampini . local - the local matrix 16773b03a366Sstefano_zampini 16783b03a366Sstefano_zampini Output Parameter: 16793b03a366Sstefano_zampini 16803b03a366Sstefano_zampini Level: advanced 16813b03a366Sstefano_zampini 16823b03a366Sstefano_zampini Notes: 16833b03a366Sstefano_zampini This can be called if you have precomputed the local matrix and 16843b03a366Sstefano_zampini want to provide it to the matrix object MATIS. 16853b03a366Sstefano_zampini 16863b03a366Sstefano_zampini .seealso: MATIS 16873b03a366Sstefano_zampini @*/ 16883b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local) 16893b03a366Sstefano_zampini { 16903b03a366Sstefano_zampini PetscErrorCode ierr; 16913b03a366Sstefano_zampini 16923b03a366Sstefano_zampini PetscFunctionBegin; 16933b03a366Sstefano_zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1694b7ce53b6SStefano Zampini PetscValidHeaderSpecific(local,MAT_CLASSID,2); 16953b03a366Sstefano_zampini ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr); 16963b03a366Sstefano_zampini PetscFunctionReturn(0); 16973b03a366Sstefano_zampini } 16983b03a366Sstefano_zampini 16996726f965SBarry Smith #undef __FUNCT__ 17006726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS" 1701a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A) 17026726f965SBarry Smith { 17036726f965SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 17046726f965SBarry Smith PetscErrorCode ierr; 17056726f965SBarry Smith 17066726f965SBarry Smith PetscFunctionBegin; 17076726f965SBarry Smith ierr = MatZeroEntries(a->A);CHKERRQ(ierr); 17086726f965SBarry Smith PetscFunctionReturn(0); 17096726f965SBarry Smith } 17106726f965SBarry Smith 17116726f965SBarry Smith #undef __FUNCT__ 17122e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS" 1713a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a) 17142e74eeadSLisandro Dalcin { 17152e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 17162e74eeadSLisandro Dalcin PetscErrorCode ierr; 17172e74eeadSLisandro Dalcin 17182e74eeadSLisandro Dalcin PetscFunctionBegin; 17192e74eeadSLisandro Dalcin ierr = MatScale(is->A,a);CHKERRQ(ierr); 17202e74eeadSLisandro Dalcin PetscFunctionReturn(0); 17212e74eeadSLisandro Dalcin } 17222e74eeadSLisandro Dalcin 17232e74eeadSLisandro Dalcin #undef __FUNCT__ 17242e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS" 1725a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 17262e74eeadSLisandro Dalcin { 17272e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 17282e74eeadSLisandro Dalcin PetscErrorCode ierr; 17292e74eeadSLisandro Dalcin 17302e74eeadSLisandro Dalcin PetscFunctionBegin; 17312e74eeadSLisandro Dalcin /* get diagonal of the local matrix */ 1732e176bc59SStefano Zampini ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr); 17332e74eeadSLisandro Dalcin 17342e74eeadSLisandro Dalcin /* scatter diagonal back into global vector */ 17352e74eeadSLisandro Dalcin ierr = VecSet(v,0);CHKERRQ(ierr); 1736e176bc59SStefano Zampini ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1737e176bc59SStefano Zampini ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 17382e74eeadSLisandro Dalcin PetscFunctionReturn(0); 17392e74eeadSLisandro Dalcin } 17402e74eeadSLisandro Dalcin 17412e74eeadSLisandro Dalcin #undef __FUNCT__ 17426726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS" 1743a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg) 17446726f965SBarry Smith { 17456726f965SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 17466726f965SBarry Smith PetscErrorCode ierr; 17476726f965SBarry Smith 17486726f965SBarry Smith PetscFunctionBegin; 17494e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 17506726f965SBarry Smith PetscFunctionReturn(0); 17516726f965SBarry Smith } 17526726f965SBarry Smith 1753284134d9SBarry Smith #undef __FUNCT__ 1754f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS" 1755f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str) 1756f26d0771SStefano Zampini { 1757f26d0771SStefano Zampini Mat_IS *y = (Mat_IS*)Y->data; 1758f26d0771SStefano Zampini Mat_IS *x; 1759f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1760f26d0771SStefano Zampini PetscBool ismatis; 1761f26d0771SStefano Zampini #endif 1762f26d0771SStefano Zampini PetscErrorCode ierr; 1763f26d0771SStefano Zampini 1764f26d0771SStefano Zampini PetscFunctionBegin; 1765f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1766f26d0771SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr); 1767f26d0771SStefano Zampini if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 1768f26d0771SStefano Zampini #endif 1769f26d0771SStefano Zampini x = (Mat_IS*)X->data; 1770f26d0771SStefano Zampini ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr); 1771f26d0771SStefano Zampini PetscFunctionReturn(0); 1772f26d0771SStefano Zampini } 1773f26d0771SStefano Zampini 1774f26d0771SStefano Zampini #undef __FUNCT__ 1775f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS" 1776f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat) 1777f26d0771SStefano Zampini { 1778f26d0771SStefano Zampini Mat lA; 1779f26d0771SStefano Zampini Mat_IS *matis; 1780f26d0771SStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 1781f26d0771SStefano Zampini IS is; 1782f26d0771SStefano Zampini const PetscInt *rg,*rl; 1783f26d0771SStefano Zampini PetscInt nrg; 1784f26d0771SStefano Zampini PetscInt N,M,nrl,i,*idxs; 1785f26d0771SStefano Zampini PetscErrorCode ierr; 1786f26d0771SStefano Zampini 1787f26d0771SStefano Zampini PetscFunctionBegin; 1788f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr); 1789f26d0771SStefano Zampini ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr); 1790f26d0771SStefano Zampini ierr = ISGetIndices(row,&rl);CHKERRQ(ierr); 1791f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr); 1792f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1793f0ae7da4SStefano 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); 1794f26d0771SStefano Zampini #endif 1795f26d0771SStefano Zampini ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr); 1796f26d0771SStefano Zampini /* map from [0,nrl) to row */ 1797f26d0771SStefano Zampini for (i=0;i<nrl;i++) idxs[i] = rl[i]; 1798f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1799f26d0771SStefano Zampini for (i=nrl;i<nrg;i++) idxs[i] = nrg; 1800f26d0771SStefano Zampini #else 1801f26d0771SStefano Zampini for (i=nrl;i<nrg;i++) idxs[i] = -1; 1802f26d0771SStefano Zampini #endif 1803f26d0771SStefano Zampini ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr); 1804f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr); 1805f26d0771SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 1806f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 1807f26d0771SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 1808f26d0771SStefano Zampini /* compute new l2g map for columns */ 1809f26d0771SStefano Zampini if (col != row || A->rmap->mapping != A->cmap->mapping) { 1810f26d0771SStefano Zampini const PetscInt *cg,*cl; 1811f26d0771SStefano Zampini PetscInt ncg; 1812f26d0771SStefano Zampini PetscInt ncl; 1813f26d0771SStefano Zampini 1814f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr); 1815f26d0771SStefano Zampini ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr); 1816f26d0771SStefano Zampini ierr = ISGetIndices(col,&cl);CHKERRQ(ierr); 1817f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr); 1818f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1819f0ae7da4SStefano 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); 1820f26d0771SStefano Zampini #endif 1821f26d0771SStefano Zampini ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr); 1822f26d0771SStefano Zampini /* map from [0,ncl) to col */ 1823f26d0771SStefano Zampini for (i=0;i<ncl;i++) idxs[i] = cl[i]; 1824f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1825f26d0771SStefano Zampini for (i=ncl;i<ncg;i++) idxs[i] = ncg; 1826f26d0771SStefano Zampini #else 1827f26d0771SStefano Zampini for (i=ncl;i<ncg;i++) idxs[i] = -1; 1828f26d0771SStefano Zampini #endif 1829f26d0771SStefano Zampini ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr); 1830f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr); 1831f26d0771SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 1832f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 1833f26d0771SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 1834f26d0771SStefano Zampini } else { 1835f26d0771SStefano Zampini ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr); 1836f26d0771SStefano Zampini cl2g = rl2g; 1837f26d0771SStefano Zampini } 1838f26d0771SStefano Zampini /* create the MATIS submatrix */ 1839f26d0771SStefano Zampini ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); 1840f26d0771SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr); 1841f26d0771SStefano Zampini ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 1842f26d0771SStefano Zampini ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr); 1843b0aa3428SStefano Zampini matis = (Mat_IS*)((*submat)->data); 1844f26d0771SStefano Zampini matis->islocalref = PETSC_TRUE; 1845f26d0771SStefano Zampini ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr); 1846f26d0771SStefano Zampini ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr); 1847f26d0771SStefano Zampini ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr); 1848f26d0771SStefano Zampini ierr = MatSetUp(*submat);CHKERRQ(ierr); 1849f26d0771SStefano Zampini ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1850f26d0771SStefano Zampini ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1851f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 1852f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 1853f26d0771SStefano Zampini /* remove unsupported ops */ 1854f26d0771SStefano Zampini ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 1855f26d0771SStefano Zampini (*submat)->ops->destroy = MatDestroy_IS; 1856f26d0771SStefano Zampini (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 1857f26d0771SStefano Zampini (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 1858f26d0771SStefano Zampini (*submat)->ops->assemblybegin = MatAssemblyBegin_IS; 1859f26d0771SStefano Zampini (*submat)->ops->assemblyend = MatAssemblyEnd_IS; 1860f26d0771SStefano Zampini PetscFunctionReturn(0); 1861f26d0771SStefano Zampini } 1862f26d0771SStefano Zampini 1863f26d0771SStefano Zampini #undef __FUNCT__ 1864284134d9SBarry Smith #define __FUNCT__ "MatCreateIS" 1865284134d9SBarry Smith /*@ 18663c212e90SHong Zhang MatCreateIS - Creates a "process" unassembled matrix, assembled on each 1867284134d9SBarry Smith process but not across processes. 1868284134d9SBarry Smith 1869284134d9SBarry Smith Input Parameters: 1870284134d9SBarry Smith + comm - MPI communicator that will share the matrix 1871e176bc59SStefano Zampini . bs - block size of the matrix 1872df3898eeSBarry Smith . m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products 1873e176bc59SStefano Zampini . rmap - local to global map for rows 1874e176bc59SStefano Zampini - cmap - local to global map for cols 1875284134d9SBarry Smith 1876284134d9SBarry Smith Output Parameter: 1877284134d9SBarry Smith . A - the resulting matrix 1878284134d9SBarry Smith 18798e6c10adSSatish Balay Level: advanced 18808e6c10adSSatish Balay 18813c212e90SHong Zhang Notes: See MATIS for more details. 18826fdf41d1SStefano Zampini m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors 18836fdf41d1SStefano Zampini used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices. 18843c212e90SHong Zhang If either rmap or cmap are NULL, then the matrix is assumed to be square. 1885284134d9SBarry Smith 1886284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping() 1887284134d9SBarry Smith @*/ 1888e176bc59SStefano Zampini PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A) 1889284134d9SBarry Smith { 1890284134d9SBarry Smith PetscErrorCode ierr; 1891284134d9SBarry Smith 1892284134d9SBarry Smith PetscFunctionBegin; 18936fdf41d1SStefano Zampini if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings"); 1894284134d9SBarry Smith ierr = MatCreate(comm,A);CHKERRQ(ierr); 18956fdf41d1SStefano Zampini if (bs > 0) { 1896d3ee2243SStefano Zampini ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr); 18976fdf41d1SStefano Zampini } 1898284134d9SBarry Smith ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr); 1899284134d9SBarry Smith ierr = MatSetType(*A,MATIS);CHKERRQ(ierr); 1900e176bc59SStefano Zampini if (rmap && cmap) { 1901e176bc59SStefano Zampini ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr); 1902e176bc59SStefano Zampini } else if (!rmap) { 1903e176bc59SStefano Zampini ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr); 1904e176bc59SStefano Zampini } else { 1905e176bc59SStefano Zampini ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr); 1906e176bc59SStefano Zampini } 1907284134d9SBarry Smith PetscFunctionReturn(0); 1908284134d9SBarry Smith } 1909284134d9SBarry Smith 1910b4319ba4SBarry Smith /*MC 1911f26d0771SStefano Zampini MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP). 1912b4319ba4SBarry Smith This stores the matrices in globally unassembled form. Each processor 1913b4319ba4SBarry Smith assembles only its local Neumann problem and the parallel matrix vector 1914b4319ba4SBarry Smith product is handled "implicitly". 1915b4319ba4SBarry Smith 1916b4319ba4SBarry Smith Operations Provided: 19176726f965SBarry Smith + MatMult() 19182e74eeadSLisandro Dalcin . MatMultAdd() 19192e74eeadSLisandro Dalcin . MatMultTranspose() 19202e74eeadSLisandro Dalcin . MatMultTransposeAdd() 19216726f965SBarry Smith . MatZeroEntries() 19226726f965SBarry Smith . MatSetOption() 19232e74eeadSLisandro Dalcin . MatZeroRows() 19242e74eeadSLisandro Dalcin . MatSetValues() 192597563a80SStefano Zampini . MatSetValuesBlocked() 19266726f965SBarry Smith . MatSetValuesLocal() 192797563a80SStefano Zampini . MatSetValuesBlockedLocal() 19282e74eeadSLisandro Dalcin . MatScale() 19292e74eeadSLisandro Dalcin . MatGetDiagonal() 19302b404112SStefano Zampini . MatMissingDiagonal() 19312b404112SStefano Zampini . MatDuplicate() 19322b404112SStefano Zampini . MatCopy() 1933f26d0771SStefano Zampini . MatAXPY() 1934f26d0771SStefano Zampini . MatGetSubMatrix() 1935f26d0771SStefano Zampini . MatGetLocalSubMatrix() 1936d7f69cd0SStefano Zampini . MatTranspose() 19376726f965SBarry Smith - MatSetLocalToGlobalMapping() 1938b4319ba4SBarry Smith 1939b4319ba4SBarry Smith Options Database Keys: 1940b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions() 1941b4319ba4SBarry Smith 1942b4319ba4SBarry Smith Notes: Options prefix for the inner matrix are given by -is_mat_xxx 1943b4319ba4SBarry Smith 1944b4319ba4SBarry Smith You must call MatSetLocalToGlobalMapping() before using this matrix type. 1945b4319ba4SBarry Smith 1946b4319ba4SBarry Smith You can do matrix preallocation on the local matrix after you obtain it with 1947eb82efa4SStefano Zampini MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation() 1948b4319ba4SBarry Smith 1949b4319ba4SBarry Smith Level: advanced 1950b4319ba4SBarry Smith 1951f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP 1952b4319ba4SBarry Smith 1953b4319ba4SBarry Smith M*/ 1954b4319ba4SBarry Smith 1955b4319ba4SBarry Smith #undef __FUNCT__ 1956b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS" 19578cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 1958b4319ba4SBarry Smith { 1959dfbe8321SBarry Smith PetscErrorCode ierr; 1960b4319ba4SBarry Smith Mat_IS *b; 1961b4319ba4SBarry Smith 1962b4319ba4SBarry Smith PetscFunctionBegin; 1963b00a9115SJed Brown ierr = PetscNewLog(A,&b);CHKERRQ(ierr); 1964b4319ba4SBarry Smith A->data = (void*)b; 1965b4319ba4SBarry Smith 1966e176bc59SStefano Zampini /* matrix ops */ 1967e176bc59SStefano Zampini ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 1968b4319ba4SBarry Smith A->ops->mult = MatMult_IS; 19692e74eeadSLisandro Dalcin A->ops->multadd = MatMultAdd_IS; 19702e74eeadSLisandro Dalcin A->ops->multtranspose = MatMultTranspose_IS; 19712e74eeadSLisandro Dalcin A->ops->multtransposeadd = MatMultTransposeAdd_IS; 1972b4319ba4SBarry Smith A->ops->destroy = MatDestroy_IS; 1973b4319ba4SBarry Smith A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 19742e74eeadSLisandro Dalcin A->ops->setvalues = MatSetValues_IS; 197598921651SStefano Zampini A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 1976b4319ba4SBarry Smith A->ops->setvalueslocal = MatSetValuesLocal_IS; 1977f0006bf2SLisandro Dalcin A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 19782e74eeadSLisandro Dalcin A->ops->zerorows = MatZeroRows_IS; 1979f0ae7da4SStefano Zampini A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 1980b4319ba4SBarry Smith A->ops->assemblybegin = MatAssemblyBegin_IS; 1981b4319ba4SBarry Smith A->ops->assemblyend = MatAssemblyEnd_IS; 1982b4319ba4SBarry Smith A->ops->view = MatView_IS; 19836726f965SBarry Smith A->ops->zeroentries = MatZeroEntries_IS; 19842e74eeadSLisandro Dalcin A->ops->scale = MatScale_IS; 19852e74eeadSLisandro Dalcin A->ops->getdiagonal = MatGetDiagonal_IS; 19866726f965SBarry Smith A->ops->setoption = MatSetOption_IS; 198769796d55SStefano Zampini A->ops->ishermitian = MatIsHermitian_IS; 198869796d55SStefano Zampini A->ops->issymmetric = MatIsSymmetric_IS; 1989ad6194a2SStefano Zampini A->ops->duplicate = MatDuplicate_IS; 19906bd84002SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_IS; 19912b404112SStefano Zampini A->ops->copy = MatCopy_IS; 1992659959c5SStefano Zampini A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 1993a8116848SStefano Zampini A->ops->getsubmatrix = MatGetSubMatrix_IS; 1994f26d0771SStefano Zampini A->ops->axpy = MatAXPY_IS; 19953fd1c9e7SStefano Zampini A->ops->diagonalset = MatDiagonalSet_IS; 19963fd1c9e7SStefano Zampini A->ops->shift = MatShift_IS; 1997d7f69cd0SStefano Zampini A->ops->transpose = MatTranspose_IS; 1998b4319ba4SBarry Smith 1999b7ce53b6SStefano Zampini /* special MATIS functions */ 2000bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr); 2001bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr); 2002b7ce53b6SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr); 20032e1947a5SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr); 200417667f90SBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr); 2005b4319ba4SBarry Smith PetscFunctionReturn(0); 2006b4319ba4SBarry Smith } 2007