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__ 17*5e3038f0Sstefano_zampini #define __FUNCT__ "MatConvert_Nest_IS" 18*5e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat) 19*5e3038f0Sstefano_zampini { 20*5e3038f0Sstefano_zampini Mat **nest,*snest,**rnest,lA,B; 21*5e3038f0Sstefano_zampini IS *iscol,*isrow,*islrow,*islcol; 22*5e3038f0Sstefano_zampini ISLocalToGlobalMapping rl2g,cl2g; 23*5e3038f0Sstefano_zampini MPI_Comm comm; 24*5e3038f0Sstefano_zampini PetscInt *lr,*lc,*lrb,*lcb,*l2gidxs; 25*5e3038f0Sstefano_zampini PetscInt sti,stl,i,j,nr,nc,rbs,cbs; 26*5e3038f0Sstefano_zampini PetscBool convert,lreuse; 27*5e3038f0Sstefano_zampini PetscErrorCode ierr; 28*5e3038f0Sstefano_zampini 29*5e3038f0Sstefano_zampini PetscFunctionBeginUser; 30*5e3038f0Sstefano_zampini ierr = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr); 31*5e3038f0Sstefano_zampini lreuse = PETSC_FALSE; 32*5e3038f0Sstefano_zampini rnest = NULL; 33*5e3038f0Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 34*5e3038f0Sstefano_zampini PetscBool ismatis,isnest; 35*5e3038f0Sstefano_zampini 36*5e3038f0Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr); 37*5e3038f0Sstefano_zampini if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type); 38*5e3038f0Sstefano_zampini ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 39*5e3038f0Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr); 40*5e3038f0Sstefano_zampini if (isnest) { 41*5e3038f0Sstefano_zampini ierr = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr); 42*5e3038f0Sstefano_zampini lreuse = (PetscBool)(i == nr && j == nc); 43*5e3038f0Sstefano_zampini if (!lreuse) rnest = NULL; 44*5e3038f0Sstefano_zampini } 45*5e3038f0Sstefano_zampini } 46*5e3038f0Sstefano_zampini ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 47*5e3038f0Sstefano_zampini ierr = PetscCalloc4(nr,&lr,nc,&lc,nr,&lrb,nc,&lcb);CHKERRQ(ierr); 48*5e3038f0Sstefano_zampini ierr = PetscCalloc5(nr,&isrow,nc,&iscol, 49*5e3038f0Sstefano_zampini nr,&islrow,nc,&islcol, 50*5e3038f0Sstefano_zampini nr*nc,&snest);CHKERRQ(ierr); 51*5e3038f0Sstefano_zampini ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr); 52*5e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 53*5e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 54*5e3038f0Sstefano_zampini PetscBool ismatis; 55*5e3038f0Sstefano_zampini PetscInt l1,l2,ij=i*nc+j; 56*5e3038f0Sstefano_zampini 57*5e3038f0Sstefano_zampini /* Null matrix pointers are allowed in MATNEST */ 58*5e3038f0Sstefano_zampini if (!nest[i][j]) continue; 59*5e3038f0Sstefano_zampini 60*5e3038f0Sstefano_zampini /* Nested matrices should be of type MATIS */ 61*5e3038f0Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr); 62*5e3038f0Sstefano_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); 63*5e3038f0Sstefano_zampini 64*5e3038f0Sstefano_zampini /* Check compatibility of local sizes */ 65*5e3038f0Sstefano_zampini ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr); 66*5e3038f0Sstefano_zampini ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr); 67*5e3038f0Sstefano_zampini if (!l1 || !l2) continue; 68*5e3038f0Sstefano_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); 69*5e3038f0Sstefano_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); 70*5e3038f0Sstefano_zampini lr[i] = l1; 71*5e3038f0Sstefano_zampini lc[j] = l2; 72*5e3038f0Sstefano_zampini ierr = MatGetBlockSizes(snest[ij],&l1,&l2);CHKERRQ(ierr); 73*5e3038f0Sstefano_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); 74*5e3038f0Sstefano_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); 75*5e3038f0Sstefano_zampini lrb[i] = l1; 76*5e3038f0Sstefano_zampini lcb[j] = l2; 77*5e3038f0Sstefano_zampini 78*5e3038f0Sstefano_zampini /* check compatibilty for local matrix reusage */ 79*5e3038f0Sstefano_zampini if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE; 80*5e3038f0Sstefano_zampini } 81*5e3038f0Sstefano_zampini } 82*5e3038f0Sstefano_zampini 83*5e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG) 84*5e3038f0Sstefano_zampini /* Check compatibility of l2g maps for rows */ 85*5e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 86*5e3038f0Sstefano_zampini rl2g = NULL; 87*5e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 88*5e3038f0Sstefano_zampini PetscInt n1,n2; 89*5e3038f0Sstefano_zampini 90*5e3038f0Sstefano_zampini if (!nest[i][j]) continue; 91*5e3038f0Sstefano_zampini ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr); 92*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr); 93*5e3038f0Sstefano_zampini if (!n1) continue; 94*5e3038f0Sstefano_zampini if (!rl2g) { 95*5e3038f0Sstefano_zampini rl2g = cl2g; 96*5e3038f0Sstefano_zampini } else { 97*5e3038f0Sstefano_zampini const PetscInt *idxs1,*idxs2; 98*5e3038f0Sstefano_zampini PetscBool same; 99*5e3038f0Sstefano_zampini 100*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr); 101*5e3038f0Sstefano_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); 102*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr); 103*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr); 104*5e3038f0Sstefano_zampini ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr); 105*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr); 106*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr); 107*5e3038f0Sstefano_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); 108*5e3038f0Sstefano_zampini } 109*5e3038f0Sstefano_zampini } 110*5e3038f0Sstefano_zampini } 111*5e3038f0Sstefano_zampini /* Check compatibility of l2g maps for columns */ 112*5e3038f0Sstefano_zampini for (i=0;i<nc;i++) { 113*5e3038f0Sstefano_zampini rl2g = NULL; 114*5e3038f0Sstefano_zampini for (j=0;j<nr;j++) { 115*5e3038f0Sstefano_zampini PetscInt n1,n2; 116*5e3038f0Sstefano_zampini 117*5e3038f0Sstefano_zampini if (!nest[j][i]) continue; 118*5e3038f0Sstefano_zampini ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr); 119*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr); 120*5e3038f0Sstefano_zampini if (!n1) continue; 121*5e3038f0Sstefano_zampini if (!rl2g) { 122*5e3038f0Sstefano_zampini rl2g = cl2g; 123*5e3038f0Sstefano_zampini } else { 124*5e3038f0Sstefano_zampini const PetscInt *idxs1,*idxs2; 125*5e3038f0Sstefano_zampini PetscBool same; 126*5e3038f0Sstefano_zampini 127*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr); 128*5e3038f0Sstefano_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); 129*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr); 130*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr); 131*5e3038f0Sstefano_zampini ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr); 132*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr); 133*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr); 134*5e3038f0Sstefano_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); 135*5e3038f0Sstefano_zampini } 136*5e3038f0Sstefano_zampini } 137*5e3038f0Sstefano_zampini } 138*5e3038f0Sstefano_zampini #endif 139*5e3038f0Sstefano_zampini 140*5e3038f0Sstefano_zampini B = NULL; 141*5e3038f0Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 142*5e3038f0Sstefano_zampini /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */ 143*5e3038f0Sstefano_zampini for (i=0,stl=0;i<nr;i++) stl += lr[i]; 144*5e3038f0Sstefano_zampini ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr); 145*5e3038f0Sstefano_zampini for (i=0,sti=0,stl=0;i<nr;i++) { 146*5e3038f0Sstefano_zampini Mat usedmat; 147*5e3038f0Sstefano_zampini Mat_IS *matis; 148*5e3038f0Sstefano_zampini const PetscInt *idxs; 149*5e3038f0Sstefano_zampini PetscInt n = lr[i]/lrb[i]; 150*5e3038f0Sstefano_zampini 151*5e3038f0Sstefano_zampini /* local IS for local NEST */ 152*5e3038f0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr); 153*5e3038f0Sstefano_zampini sti += n; 154*5e3038f0Sstefano_zampini 155*5e3038f0Sstefano_zampini /* l2gmap */ 156*5e3038f0Sstefano_zampini j = 0; 157*5e3038f0Sstefano_zampini usedmat = nest[i][j]; 158*5e3038f0Sstefano_zampini while (!usedmat && j < nc) usedmat = nest[i][j++]; 159*5e3038f0Sstefano_zampini matis = (Mat_IS*)(usedmat->data); 160*5e3038f0Sstefano_zampini if (!matis->sf) { 161*5e3038f0Sstefano_zampini ierr = MatISComputeSF_Private(usedmat);CHKERRQ(ierr); 162*5e3038f0Sstefano_zampini } 163*5e3038f0Sstefano_zampini ierr = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr); 164*5e3038f0Sstefano_zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 165*5e3038f0Sstefano_zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 166*5e3038f0Sstefano_zampini ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr); 167*5e3038f0Sstefano_zampini stl += lr[i]; 168*5e3038f0Sstefano_zampini } 169*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr); 170*5e3038f0Sstefano_zampini 171*5e3038f0Sstefano_zampini /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */ 172*5e3038f0Sstefano_zampini for (i=0,stl=0;i<nc;i++) stl += lc[i]; 173*5e3038f0Sstefano_zampini ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr); 174*5e3038f0Sstefano_zampini for (i=0,sti=0,stl=0;i<nc;i++) { 175*5e3038f0Sstefano_zampini Mat usedmat; 176*5e3038f0Sstefano_zampini Mat_IS *matis; 177*5e3038f0Sstefano_zampini const PetscInt *idxs; 178*5e3038f0Sstefano_zampini PetscInt n = lc[i]/lcb[i]; 179*5e3038f0Sstefano_zampini 180*5e3038f0Sstefano_zampini /* local IS for local NEST */ 181*5e3038f0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr); 182*5e3038f0Sstefano_zampini sti += n; 183*5e3038f0Sstefano_zampini 184*5e3038f0Sstefano_zampini /* l2gmap */ 185*5e3038f0Sstefano_zampini j = 0; 186*5e3038f0Sstefano_zampini usedmat = nest[j][i]; 187*5e3038f0Sstefano_zampini while (!usedmat && j < nr) usedmat = nest[j++][i]; 188*5e3038f0Sstefano_zampini matis = (Mat_IS*)(usedmat->data); 189*5e3038f0Sstefano_zampini if (!matis->sf) { 190*5e3038f0Sstefano_zampini ierr = MatISComputeSF_Private(usedmat);CHKERRQ(ierr); 191*5e3038f0Sstefano_zampini } 192*5e3038f0Sstefano_zampini ierr = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr); 193*5e3038f0Sstefano_zampini ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 194*5e3038f0Sstefano_zampini ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 195*5e3038f0Sstefano_zampini ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr); 196*5e3038f0Sstefano_zampini stl += lc[i]; 197*5e3038f0Sstefano_zampini } 198*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr); 199*5e3038f0Sstefano_zampini 200*5e3038f0Sstefano_zampini /* Create MATIS */ 201*5e3038f0Sstefano_zampini ierr = MatCreate(comm,&B);CHKERRQ(ierr); 202*5e3038f0Sstefano_zampini ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 203*5e3038f0Sstefano_zampini ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr); 204*5e3038f0Sstefano_zampini ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr); 205*5e3038f0Sstefano_zampini ierr = MatSetType(B,MATIS);CHKERRQ(ierr); 206*5e3038f0Sstefano_zampini ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr); 207*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 208*5e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 209*5e3038f0Sstefano_zampini ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr); 210*5e3038f0Sstefano_zampini ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr); 211*5e3038f0Sstefano_zampini ierr = MatDestroy(&lA);CHKERRQ(ierr); 212*5e3038f0Sstefano_zampini ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 213*5e3038f0Sstefano_zampini ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 214*5e3038f0Sstefano_zampini if (reuse == MAT_INPLACE_MATRIX) { 215*5e3038f0Sstefano_zampini ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 216*5e3038f0Sstefano_zampini } else { 217*5e3038f0Sstefano_zampini *newmat = B; 218*5e3038f0Sstefano_zampini } 219*5e3038f0Sstefano_zampini } else { 220*5e3038f0Sstefano_zampini if (lreuse) { 221*5e3038f0Sstefano_zampini ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 222*5e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 223*5e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 224*5e3038f0Sstefano_zampini if (snest[i*nc+j]) { 225*5e3038f0Sstefano_zampini ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr); 226*5e3038f0Sstefano_zampini } 227*5e3038f0Sstefano_zampini } 228*5e3038f0Sstefano_zampini } 229*5e3038f0Sstefano_zampini } else { 230*5e3038f0Sstefano_zampini for (i=0,sti=0;i<nr;i++) { 231*5e3038f0Sstefano_zampini PetscInt n = lr[i]/lrb[i]; 232*5e3038f0Sstefano_zampini 233*5e3038f0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr); 234*5e3038f0Sstefano_zampini sti += n; 235*5e3038f0Sstefano_zampini } 236*5e3038f0Sstefano_zampini for (i=0,sti=0;i<nc;i++) { 237*5e3038f0Sstefano_zampini PetscInt n = lc[i]/lcb[i]; 238*5e3038f0Sstefano_zampini 239*5e3038f0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr); 240*5e3038f0Sstefano_zampini sti += n; 241*5e3038f0Sstefano_zampini } 242*5e3038f0Sstefano_zampini ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr); 243*5e3038f0Sstefano_zampini ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr); 244*5e3038f0Sstefano_zampini ierr = MatDestroy(&lA);CHKERRQ(ierr); 245*5e3038f0Sstefano_zampini } 246*5e3038f0Sstefano_zampini ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 247*5e3038f0Sstefano_zampini ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 248*5e3038f0Sstefano_zampini } 249*5e3038f0Sstefano_zampini 250*5e3038f0Sstefano_zampini /* Free workspace */ 251*5e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 252*5e3038f0Sstefano_zampini ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr); 253*5e3038f0Sstefano_zampini } 254*5e3038f0Sstefano_zampini for (i=0;i<nc;i++) { 255*5e3038f0Sstefano_zampini ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr); 256*5e3038f0Sstefano_zampini } 257*5e3038f0Sstefano_zampini ierr = PetscFree4(lr,lc,lrb,lcb);CHKERRQ(ierr); 258*5e3038f0Sstefano_zampini ierr = PetscFree5(isrow,iscol,islrow,islcol,snest);CHKERRQ(ierr); 259*5e3038f0Sstefano_zampini 260*5e3038f0Sstefano_zampini /* Create local matrix in MATNEST format */ 261*5e3038f0Sstefano_zampini convert = PETSC_FALSE; 262*5e3038f0Sstefano_zampini ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr); 263*5e3038f0Sstefano_zampini if (convert) { 264*5e3038f0Sstefano_zampini Mat M; 265*5e3038f0Sstefano_zampini 266*5e3038f0Sstefano_zampini ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 267*5e3038f0Sstefano_zampini ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr); 268*5e3038f0Sstefano_zampini ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr); 269*5e3038f0Sstefano_zampini ierr = MatDestroy(&M);CHKERRQ(ierr); 270*5e3038f0Sstefano_zampini } 271*5e3038f0Sstefano_zampini 272*5e3038f0Sstefano_zampini PetscFunctionReturn(0); 273*5e3038f0Sstefano_zampini } 274*5e3038f0Sstefano_zampini 275*5e3038f0Sstefano_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 } 9323927de2eSStefano Zampini /* set preallocation */ 9333927de2eSStefano Zampini ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr); 9343927de2eSStefano Zampini for (i=0;i<lrows/bs;i++) { 9353927de2eSStefano Zampini dnz[i] = dnz[i*bs]/bs; 9363927de2eSStefano Zampini onz[i] = onz[i*bs]/bs; 9373927de2eSStefano Zampini } 9383927de2eSStefano Zampini ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 9393927de2eSStefano Zampini ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 9403927de2eSStefano Zampini ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 9413927de2eSStefano Zampini if (issbaij) { 9423927de2eSStefano Zampini ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr); 9433927de2eSStefano Zampini } 9443927de2eSStefano Zampini PetscFunctionReturn(0); 9453927de2eSStefano Zampini } 9463927de2eSStefano Zampini 9473927de2eSStefano Zampini #undef __FUNCT__ 948b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS" 9497230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M) 950b7ce53b6SStefano Zampini { 951b7ce53b6SStefano Zampini Mat_IS *matis = (Mat_IS*)(mat->data); 952d9a9e74cSStefano Zampini Mat local_mat; 953b7ce53b6SStefano Zampini /* info on mat */ 9543cfa4ea4SStefano Zampini PetscInt bs,rows,cols,lrows,lcols; 955b7ce53b6SStefano Zampini PetscInt local_rows,local_cols; 956686e3a49SStefano Zampini PetscBool isdense,issbaij,isseqaij; 9577c03b4e8SStefano Zampini PetscMPIInt nsubdomains; 958b7ce53b6SStefano Zampini /* values insertion */ 959b7ce53b6SStefano Zampini PetscScalar *array; 960b7ce53b6SStefano Zampini /* work */ 961b7ce53b6SStefano Zampini PetscErrorCode ierr; 962b7ce53b6SStefano Zampini 963b7ce53b6SStefano Zampini PetscFunctionBegin; 964b7ce53b6SStefano Zampini /* get info from mat */ 9657c03b4e8SStefano Zampini ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr); 9667c03b4e8SStefano Zampini if (nsubdomains == 1) { 9677c03b4e8SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 9687c03b4e8SStefano Zampini ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&(*M));CHKERRQ(ierr); 9697c03b4e8SStefano Zampini } else { 9707c03b4e8SStefano Zampini ierr = MatCopy(matis->A,*M,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 9717c03b4e8SStefano Zampini } 9727c03b4e8SStefano Zampini PetscFunctionReturn(0); 9737c03b4e8SStefano Zampini } 974b7ce53b6SStefano Zampini ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr); 975b7ce53b6SStefano Zampini ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); 9763cfa4ea4SStefano Zampini ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr); 977b7ce53b6SStefano Zampini ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 978b7ce53b6SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr); 979686e3a49SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 980b7ce53b6SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr); 981b7ce53b6SStefano Zampini 982b7ce53b6SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 983b7ce53b6SStefano Zampini MatType new_mat_type; 9843927de2eSStefano Zampini PetscBool issbaij_red; 985b7ce53b6SStefano Zampini 986b7ce53b6SStefano Zampini /* determining new matrix type */ 987b2566f29SBarry Smith ierr = MPIU_Allreduce(&issbaij,&issbaij_red,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 988b7ce53b6SStefano Zampini if (issbaij_red) { 989b7ce53b6SStefano Zampini new_mat_type = MATSBAIJ; 990b7ce53b6SStefano Zampini } else { 991b7ce53b6SStefano Zampini if (bs>1) { 992b7ce53b6SStefano Zampini new_mat_type = MATBAIJ; 993b7ce53b6SStefano Zampini } else { 994b7ce53b6SStefano Zampini new_mat_type = MATAIJ; 995b7ce53b6SStefano Zampini } 996b7ce53b6SStefano Zampini } 997b7ce53b6SStefano Zampini 9983927de2eSStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr); 9993cfa4ea4SStefano Zampini ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr); 10003927de2eSStefano Zampini ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr); 10013927de2eSStefano Zampini ierr = MatSetType(*M,new_mat_type);CHKERRQ(ierr); 10023927de2eSStefano Zampini ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr); 1003b7ce53b6SStefano Zampini } else { 10043cfa4ea4SStefano Zampini PetscInt mbs,mrows,mcols,mlrows,mlcols; 1005b7ce53b6SStefano Zampini /* some checks */ 1006b7ce53b6SStefano Zampini ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr); 1007b7ce53b6SStefano Zampini ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr); 10083cfa4ea4SStefano Zampini ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr); 10096c4ed002SBarry Smith if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows); 10106c4ed002SBarry Smith if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols); 10116c4ed002SBarry Smith if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows); 10126c4ed002SBarry Smith if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols); 10136c4ed002SBarry Smith if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs); 1014b7ce53b6SStefano Zampini ierr = MatZeroEntries(*M);CHKERRQ(ierr); 1015b7ce53b6SStefano Zampini } 1016d9a9e74cSStefano Zampini 1017d9a9e74cSStefano Zampini if (issbaij) { 1018d9a9e74cSStefano Zampini ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr); 1019d9a9e74cSStefano Zampini } else { 1020d9a9e74cSStefano Zampini ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 1021d9a9e74cSStefano Zampini local_mat = matis->A; 1022d9a9e74cSStefano Zampini } 1023686e3a49SStefano Zampini 1024b7ce53b6SStefano Zampini /* Set values */ 1025ecf5a873SStefano Zampini ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr); 1026b7ce53b6SStefano Zampini if (isdense) { /* special case for dense local matrices */ 1027ecf5a873SStefano Zampini PetscInt i,*dummy_rows,*dummy_cols; 1028ecf5a873SStefano Zampini 1029ecf5a873SStefano Zampini if (local_rows != local_cols) { 1030ecf5a873SStefano Zampini ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr); 1031ecf5a873SStefano Zampini for (i=0;i<local_rows;i++) dummy_rows[i] = i; 1032ecf5a873SStefano Zampini for (i=0;i<local_cols;i++) dummy_cols[i] = i; 1033ecf5a873SStefano Zampini } else { 1034ecf5a873SStefano Zampini ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr); 1035ecf5a873SStefano Zampini for (i=0;i<local_rows;i++) dummy_rows[i] = i; 1036ecf5a873SStefano Zampini dummy_cols = dummy_rows; 1037ecf5a873SStefano Zampini } 1038b7ce53b6SStefano Zampini ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 1039d9a9e74cSStefano Zampini ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr); 1040ecf5a873SStefano Zampini ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr); 1041d9a9e74cSStefano Zampini ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr); 1042ecf5a873SStefano Zampini if (dummy_rows != dummy_cols) { 1043ecf5a873SStefano Zampini ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr); 1044ecf5a873SStefano Zampini } else { 1045ecf5a873SStefano Zampini ierr = PetscFree(dummy_rows);CHKERRQ(ierr); 1046ecf5a873SStefano Zampini } 1047686e3a49SStefano Zampini } else if (isseqaij) { 1048ecf5a873SStefano Zampini PetscInt i,nvtxs,*xadj,*adjncy; 1049686e3a49SStefano Zampini PetscBool done; 1050686e3a49SStefano Zampini 1051d9a9e74cSStefano Zampini ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 1052bb1015c3SStefano Zampini if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__); 1053d9a9e74cSStefano Zampini ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr); 1054686e3a49SStefano Zampini for (i=0;i<nvtxs;i++) { 1055ecf5a873SStefano Zampini ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr); 1056686e3a49SStefano Zampini } 1057d9a9e74cSStefano Zampini ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 1058bb1015c3SStefano Zampini if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__); 1059d9a9e74cSStefano Zampini ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr); 1060686e3a49SStefano Zampini } else { /* very basic values insertion for all other matrix types */ 1061ecf5a873SStefano Zampini PetscInt i; 1062c0962df8SStefano Zampini 1063686e3a49SStefano Zampini for (i=0;i<local_rows;i++) { 1064686e3a49SStefano Zampini PetscInt j; 1065ecf5a873SStefano Zampini const PetscInt *local_indices_cols; 1066686e3a49SStefano Zampini 1067ecf5a873SStefano Zampini ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr); 1068ecf5a873SStefano Zampini ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr); 1069ecf5a873SStefano Zampini ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr); 1070686e3a49SStefano Zampini } 1071b7ce53b6SStefano Zampini } 1072b7ce53b6SStefano Zampini ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1073d9a9e74cSStefano Zampini ierr = MatDestroy(&local_mat);CHKERRQ(ierr); 1074b7ce53b6SStefano Zampini ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1075b7ce53b6SStefano Zampini if (isdense) { 1076b7ce53b6SStefano Zampini ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr); 1077b7ce53b6SStefano Zampini } 1078b7ce53b6SStefano Zampini PetscFunctionReturn(0); 1079b7ce53b6SStefano Zampini } 1080b7ce53b6SStefano Zampini 1081b7ce53b6SStefano Zampini #undef __FUNCT__ 1082b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ" 1083b7ce53b6SStefano Zampini /*@ 1084b7ce53b6SStefano Zampini MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format 1085b7ce53b6SStefano Zampini 1086b7ce53b6SStefano Zampini Input Parameter: 1087b7ce53b6SStefano Zampini . mat - the matrix (should be of type MATIS) 1088b7ce53b6SStefano Zampini . reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 1089b7ce53b6SStefano Zampini 1090b7ce53b6SStefano Zampini Output Parameter: 1091b7ce53b6SStefano Zampini . newmat - the matrix in AIJ format 1092b7ce53b6SStefano Zampini 1093b7ce53b6SStefano Zampini Level: developer 1094b7ce53b6SStefano Zampini 1095eb82efa4SStefano Zampini Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested. 1096b7ce53b6SStefano Zampini 1097b7ce53b6SStefano Zampini .seealso: MATIS 1098b7ce53b6SStefano Zampini @*/ 1099b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat) 1100b7ce53b6SStefano Zampini { 1101b7ce53b6SStefano Zampini PetscErrorCode ierr; 1102b7ce53b6SStefano Zampini 1103b7ce53b6SStefano Zampini PetscFunctionBegin; 1104b7ce53b6SStefano Zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1105b7ce53b6SStefano Zampini PetscValidLogicalCollectiveEnum(mat,reuse,2); 1106b7ce53b6SStefano Zampini PetscValidPointer(newmat,3); 1107b7ce53b6SStefano Zampini if (reuse != MAT_INITIAL_MATRIX) { 1108b7ce53b6SStefano Zampini PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3); 1109b7ce53b6SStefano Zampini PetscCheckSameComm(mat,1,*newmat,3); 11106c4ed002SBarry Smith if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix"); 1111b7ce53b6SStefano Zampini } 1112b7ce53b6SStefano Zampini ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr); 1113b7ce53b6SStefano Zampini PetscFunctionReturn(0); 1114b7ce53b6SStefano Zampini } 1115b7ce53b6SStefano Zampini 1116b7ce53b6SStefano Zampini #undef __FUNCT__ 1117ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS" 1118ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat) 1119ad6194a2SStefano Zampini { 1120ad6194a2SStefano Zampini PetscErrorCode ierr; 1121ad6194a2SStefano Zampini Mat_IS *matis = (Mat_IS*)(mat->data); 1122ad6194a2SStefano Zampini PetscInt bs,m,n,M,N; 1123ad6194a2SStefano Zampini Mat B,localmat; 1124ad6194a2SStefano Zampini 1125ad6194a2SStefano Zampini PetscFunctionBegin; 1126ad6194a2SStefano Zampini ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); 1127ad6194a2SStefano Zampini ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 1128ad6194a2SStefano Zampini ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr); 1129e176bc59SStefano Zampini ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr); 1130ad6194a2SStefano Zampini ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr); 1131ad6194a2SStefano Zampini ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr); 1132b3317aa8SStefano Zampini ierr = MatDestroy(&localmat);CHKERRQ(ierr); 1133ad6194a2SStefano Zampini ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1134ad6194a2SStefano Zampini ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1135ad6194a2SStefano Zampini *newmat = B; 1136ad6194a2SStefano Zampini PetscFunctionReturn(0); 1137ad6194a2SStefano Zampini } 1138ad6194a2SStefano Zampini 1139ad6194a2SStefano Zampini #undef __FUNCT__ 114069796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS" 1141a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool *flg) 114269796d55SStefano Zampini { 114369796d55SStefano Zampini PetscErrorCode ierr; 114469796d55SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 114569796d55SStefano Zampini PetscBool local_sym; 114669796d55SStefano Zampini 114769796d55SStefano Zampini PetscFunctionBegin; 114869796d55SStefano Zampini ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr); 1149b2566f29SBarry Smith ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 115069796d55SStefano Zampini PetscFunctionReturn(0); 115169796d55SStefano Zampini } 115269796d55SStefano Zampini 115369796d55SStefano Zampini #undef __FUNCT__ 115469796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS" 1155a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg) 115669796d55SStefano Zampini { 115769796d55SStefano Zampini PetscErrorCode ierr; 115869796d55SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 115969796d55SStefano Zampini PetscBool local_sym; 116069796d55SStefano Zampini 116169796d55SStefano Zampini PetscFunctionBegin; 116269796d55SStefano Zampini ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr); 1163b2566f29SBarry Smith ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 116469796d55SStefano Zampini PetscFunctionReturn(0); 116569796d55SStefano Zampini } 116669796d55SStefano Zampini 116769796d55SStefano Zampini #undef __FUNCT__ 1168b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS" 1169a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A) 1170b4319ba4SBarry Smith { 1171dfbe8321SBarry Smith PetscErrorCode ierr; 1172b4319ba4SBarry Smith Mat_IS *b = (Mat_IS*)A->data; 1173b4319ba4SBarry Smith 1174b4319ba4SBarry Smith PetscFunctionBegin; 11756bf464f9SBarry Smith ierr = MatDestroy(&b->A);CHKERRQ(ierr); 1176e176bc59SStefano Zampini ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr); 1177e176bc59SStefano Zampini ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr); 11786bf464f9SBarry Smith ierr = VecDestroy(&b->x);CHKERRQ(ierr); 11796bf464f9SBarry Smith ierr = VecDestroy(&b->y);CHKERRQ(ierr); 11803fd1c9e7SStefano Zampini ierr = VecDestroy(&b->counter);CHKERRQ(ierr); 1181a8116848SStefano Zampini ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr); 1182a8116848SStefano Zampini ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr); 1183a8116848SStefano Zampini if (b->sf != b->csf) { 1184a8116848SStefano Zampini ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr); 1185a8116848SStefano Zampini ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr); 1186a8116848SStefano Zampini } 118728f4e0baSStefano Zampini ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr); 118828f4e0baSStefano Zampini ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr); 1189bf0cc555SLisandro Dalcin ierr = PetscFree(A->data);CHKERRQ(ierr); 1190dbd8c25aSHong Zhang ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 1191bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr); 1192b7ce53b6SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr); 1193b7ce53b6SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr); 11942e1947a5SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr); 1195b4319ba4SBarry Smith PetscFunctionReturn(0); 1196b4319ba4SBarry Smith } 1197b4319ba4SBarry Smith 1198b4319ba4SBarry Smith #undef __FUNCT__ 1199b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS" 1200a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y) 1201b4319ba4SBarry Smith { 1202dfbe8321SBarry Smith PetscErrorCode ierr; 1203b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1204b4319ba4SBarry Smith PetscScalar zero = 0.0; 1205b4319ba4SBarry Smith 1206b4319ba4SBarry Smith PetscFunctionBegin; 1207b4319ba4SBarry Smith /* scatter the global vector x into the local work vector */ 1208e176bc59SStefano Zampini ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1209e176bc59SStefano Zampini ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1210b4319ba4SBarry Smith 1211b4319ba4SBarry Smith /* multiply the local matrix */ 1212b4319ba4SBarry Smith ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr); 1213b4319ba4SBarry Smith 1214b4319ba4SBarry Smith /* scatter product back into global memory */ 12152dcb1b2aSMatthew Knepley ierr = VecSet(y,zero);CHKERRQ(ierr); 1216e176bc59SStefano Zampini ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1217e176bc59SStefano Zampini ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1218b4319ba4SBarry Smith PetscFunctionReturn(0); 1219b4319ba4SBarry Smith } 1220b4319ba4SBarry Smith 1221b4319ba4SBarry Smith #undef __FUNCT__ 12222e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS" 1223a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 12242e74eeadSLisandro Dalcin { 1225650997f4SStefano Zampini Vec temp_vec; 12262e74eeadSLisandro Dalcin PetscErrorCode ierr; 12272e74eeadSLisandro Dalcin 12282e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 1229650997f4SStefano Zampini if (v3 != v2) { 1230650997f4SStefano Zampini ierr = MatMult(A,v1,v3);CHKERRQ(ierr); 1231650997f4SStefano Zampini ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 1232650997f4SStefano Zampini } else { 1233650997f4SStefano Zampini ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 1234650997f4SStefano Zampini ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr); 1235650997f4SStefano Zampini ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 1236650997f4SStefano Zampini ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 1237650997f4SStefano Zampini ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 1238650997f4SStefano Zampini } 12392e74eeadSLisandro Dalcin PetscFunctionReturn(0); 12402e74eeadSLisandro Dalcin } 12412e74eeadSLisandro Dalcin 12422e74eeadSLisandro Dalcin #undef __FUNCT__ 12432e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS" 1244a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x) 12452e74eeadSLisandro Dalcin { 12462e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 12472e74eeadSLisandro Dalcin PetscErrorCode ierr; 12482e74eeadSLisandro Dalcin 1249e176bc59SStefano Zampini PetscFunctionBegin; 12502e74eeadSLisandro Dalcin /* scatter the global vector x into the local work vector */ 1251e176bc59SStefano Zampini ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1252e176bc59SStefano Zampini ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 12532e74eeadSLisandro Dalcin 12542e74eeadSLisandro Dalcin /* multiply the local matrix */ 1255e176bc59SStefano Zampini ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr); 12562e74eeadSLisandro Dalcin 12572e74eeadSLisandro Dalcin /* scatter product back into global vector */ 1258e176bc59SStefano Zampini ierr = VecSet(x,0);CHKERRQ(ierr); 1259e176bc59SStefano Zampini ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1260e176bc59SStefano Zampini ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 12612e74eeadSLisandro Dalcin PetscFunctionReturn(0); 12622e74eeadSLisandro Dalcin } 12632e74eeadSLisandro Dalcin 12642e74eeadSLisandro Dalcin #undef __FUNCT__ 12652e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS" 1266a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 12672e74eeadSLisandro Dalcin { 1268650997f4SStefano Zampini Vec temp_vec; 12692e74eeadSLisandro Dalcin PetscErrorCode ierr; 12702e74eeadSLisandro Dalcin 12712e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 1272650997f4SStefano Zampini if (v3 != v2) { 1273650997f4SStefano Zampini ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr); 1274650997f4SStefano Zampini ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 1275650997f4SStefano Zampini } else { 1276650997f4SStefano Zampini ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 1277650997f4SStefano Zampini ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr); 1278650997f4SStefano Zampini ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 1279650997f4SStefano Zampini ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 1280650997f4SStefano Zampini ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 1281650997f4SStefano Zampini } 12822e74eeadSLisandro Dalcin PetscFunctionReturn(0); 12832e74eeadSLisandro Dalcin } 12842e74eeadSLisandro Dalcin 12852e74eeadSLisandro Dalcin #undef __FUNCT__ 1286b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS" 1287a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer) 1288b4319ba4SBarry Smith { 1289b4319ba4SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 1290dfbe8321SBarry Smith PetscErrorCode ierr; 1291b4319ba4SBarry Smith PetscViewer sviewer; 1292b4319ba4SBarry Smith 1293b4319ba4SBarry Smith PetscFunctionBegin; 12943f08860eSBarry Smith ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 1295b4319ba4SBarry Smith ierr = MatView(a->A,sviewer);CHKERRQ(ierr); 12963f08860eSBarry Smith ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 12976e520ac8SStefano Zampini ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1298b4319ba4SBarry Smith PetscFunctionReturn(0); 1299b4319ba4SBarry Smith } 1300b4319ba4SBarry Smith 1301b4319ba4SBarry Smith #undef __FUNCT__ 1302b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS" 1303a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping) 1304b4319ba4SBarry Smith { 1305dfbe8321SBarry Smith PetscErrorCode ierr; 1306e176bc59SStefano Zampini PetscInt nr,rbs,nc,cbs; 1307b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1308b4319ba4SBarry Smith IS from,to; 1309e176bc59SStefano Zampini Vec cglobal,rglobal; 1310b4319ba4SBarry Smith 1311b4319ba4SBarry Smith PetscFunctionBegin; 1312784ac674SJed Brown PetscCheckSameComm(A,1,rmapping,2); 1313e176bc59SStefano Zampini PetscCheckSameComm(A,1,cmapping,3); 13143bbff08aSStefano Zampini /* Destroy any previous data */ 131570cf5478SStefano Zampini ierr = VecDestroy(&is->x);CHKERRQ(ierr); 131670cf5478SStefano Zampini ierr = VecDestroy(&is->y);CHKERRQ(ierr); 13173fd1c9e7SStefano Zampini ierr = VecDestroy(&is->counter);CHKERRQ(ierr); 1318e176bc59SStefano Zampini ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr); 1319e176bc59SStefano Zampini ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr); 13201c47cb0fSStefano Zampini ierr = MatDestroy(&is->A);CHKERRQ(ierr); 132128f4e0baSStefano Zampini ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr); 132228f4e0baSStefano Zampini ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr); 13233bbff08aSStefano Zampini 13243bbff08aSStefano Zampini /* Setup Layout and set local to global maps */ 1325fc27028aSStefano Zampini ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 1326fc27028aSStefano Zampini ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 1327fa7f1dd8SStefano Zampini ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr); 1328fa7f1dd8SStefano Zampini ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr); 1329b4319ba4SBarry Smith 1330b4319ba4SBarry Smith /* Create the local matrix A */ 1331e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr); 1332e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr); 1333e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr); 1334e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr); 1335f69a0ea3SMatthew Knepley ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr); 1336e176bc59SStefano Zampini ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr); 1337e176bc59SStefano Zampini ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr); 1338e176bc59SStefano Zampini ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr); 1339ff130e51SJed Brown ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr); 1340ff130e51SJed Brown ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr); 1341b4319ba4SBarry Smith ierr = MatSetFromOptions(is->A);CHKERRQ(ierr); 1342b4319ba4SBarry Smith 1343f26d0771SStefano Zampini if (!is->islocalref) { /* setup scatters and local vectors for MatMult */ 1344b4319ba4SBarry Smith /* Create the local work vectors */ 13453bbff08aSStefano Zampini ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr); 1346b4319ba4SBarry Smith 1347e176bc59SStefano Zampini /* setup the global to local scatters */ 1348e176bc59SStefano Zampini ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr); 1349e176bc59SStefano Zampini ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr); 1350784ac674SJed Brown ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr); 1351e176bc59SStefano Zampini ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr); 1352e176bc59SStefano Zampini if (rmapping != cmapping) { 1353e176bc59SStefano Zampini ierr = ISDestroy(&to);CHKERRQ(ierr); 1354e176bc59SStefano Zampini ierr = ISDestroy(&from);CHKERRQ(ierr); 1355e176bc59SStefano Zampini ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr); 1356e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr); 1357e176bc59SStefano Zampini ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr); 1358e176bc59SStefano Zampini } else { 1359e176bc59SStefano Zampini ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr); 1360e176bc59SStefano Zampini is->cctx = is->rctx; 1361e176bc59SStefano Zampini } 13623fd1c9e7SStefano Zampini 13633fd1c9e7SStefano Zampini /* interface counter vector (local) */ 13643fd1c9e7SStefano Zampini ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr); 13653fd1c9e7SStefano Zampini ierr = VecSet(is->y,1.);CHKERRQ(ierr); 13663fd1c9e7SStefano Zampini ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 13673fd1c9e7SStefano Zampini ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 13683fd1c9e7SStefano Zampini ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 13693fd1c9e7SStefano Zampini ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 13703fd1c9e7SStefano Zampini 13713fd1c9e7SStefano Zampini /* free workspace */ 1372e176bc59SStefano Zampini ierr = VecDestroy(&rglobal);CHKERRQ(ierr); 1373e176bc59SStefano Zampini ierr = VecDestroy(&cglobal);CHKERRQ(ierr); 13746bf464f9SBarry Smith ierr = ISDestroy(&to);CHKERRQ(ierr); 13756bf464f9SBarry Smith ierr = ISDestroy(&from);CHKERRQ(ierr); 1376f26d0771SStefano Zampini } 137748ff6bf3SStefano Zampini ierr = MatSetUp(A);CHKERRQ(ierr); 1378b4319ba4SBarry Smith PetscFunctionReturn(0); 1379b4319ba4SBarry Smith } 1380b4319ba4SBarry Smith 13812e74eeadSLisandro Dalcin #undef __FUNCT__ 13822e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS" 1383a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 13842e74eeadSLisandro Dalcin { 13852e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)mat->data; 13862e74eeadSLisandro Dalcin PetscErrorCode ierr; 138797563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 138897563a80SStefano Zampini PetscInt i,zm,zn; 138997563a80SStefano Zampini #endif 1390f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 13912e74eeadSLisandro Dalcin 13922e74eeadSLisandro Dalcin PetscFunctionBegin; 13932e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG) 1394f26d0771SStefano 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); 139597563a80SStefano Zampini /* count negative indices */ 139697563a80SStefano Zampini for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++; 139797563a80SStefano Zampini for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++; 13982e74eeadSLisandro Dalcin #endif 139997563a80SStefano Zampini ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr); 140097563a80SStefano Zampini ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr); 140197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 140297563a80SStefano Zampini /* count negative indices (should be the same as before) */ 140397563a80SStefano Zampini for (i=0;i<m;i++) if (rows_l[i] < 0) zm--; 140497563a80SStefano Zampini for (i=0;i<n;i++) if (cols_l[i] < 0) zn--; 140597563a80SStefano 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"); 140697563a80SStefano 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"); 140797563a80SStefano Zampini #endif 14082e74eeadSLisandro Dalcin ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 14092e74eeadSLisandro Dalcin PetscFunctionReturn(0); 14102e74eeadSLisandro Dalcin } 14112e74eeadSLisandro Dalcin 1412b4319ba4SBarry Smith #undef __FUNCT__ 141397563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS" 1414a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 141597563a80SStefano Zampini { 141697563a80SStefano Zampini Mat_IS *is = (Mat_IS*)mat->data; 141797563a80SStefano Zampini PetscErrorCode ierr; 141897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 141997563a80SStefano Zampini PetscInt i,zm,zn; 142097563a80SStefano Zampini #endif 1421f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 142297563a80SStefano Zampini 142397563a80SStefano Zampini PetscFunctionBegin; 142497563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 1425f26d0771SStefano 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); 142697563a80SStefano Zampini /* count negative indices */ 142797563a80SStefano Zampini for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++; 142897563a80SStefano Zampini for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++; 142997563a80SStefano Zampini #endif 143097563a80SStefano Zampini ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr); 143197563a80SStefano Zampini ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr); 143297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 143397563a80SStefano Zampini /* count negative indices (should be the same as before) */ 143497563a80SStefano Zampini for (i=0;i<m;i++) if (rows_l[i] < 0) zm--; 143597563a80SStefano Zampini for (i=0;i<n;i++) if (cols_l[i] < 0) zn--; 143697563a80SStefano 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"); 143797563a80SStefano 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"); 143897563a80SStefano Zampini #endif 143997563a80SStefano Zampini ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 144097563a80SStefano Zampini PetscFunctionReturn(0); 144197563a80SStefano Zampini } 144297563a80SStefano Zampini 144397563a80SStefano Zampini #undef __FUNCT__ 1444b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS" 1445a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1446b4319ba4SBarry Smith { 1447dfbe8321SBarry Smith PetscErrorCode ierr; 1448b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1449b4319ba4SBarry Smith 1450b4319ba4SBarry Smith PetscFunctionBegin; 1451b4319ba4SBarry Smith ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 1452b4319ba4SBarry Smith PetscFunctionReturn(0); 1453b4319ba4SBarry Smith } 1454b4319ba4SBarry Smith 1455b4319ba4SBarry Smith #undef __FUNCT__ 1456f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS" 1457a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1458f0006bf2SLisandro Dalcin { 1459f0006bf2SLisandro Dalcin PetscErrorCode ierr; 1460f0006bf2SLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 1461f0006bf2SLisandro Dalcin 1462f0006bf2SLisandro Dalcin PetscFunctionBegin; 1463f0006bf2SLisandro Dalcin ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 1464f0006bf2SLisandro Dalcin PetscFunctionReturn(0); 1465f0006bf2SLisandro Dalcin } 1466f0006bf2SLisandro Dalcin 1467f0006bf2SLisandro Dalcin #undef __FUNCT__ 1468f0ae7da4SStefano Zampini #define __FUNCT__ "MatISZeroRowsColumnsLocal_Private" 1469f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns) 1470f0ae7da4SStefano Zampini { 1471f0ae7da4SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 1472f0ae7da4SStefano Zampini PetscErrorCode ierr; 1473f0ae7da4SStefano Zampini 1474f0ae7da4SStefano Zampini PetscFunctionBegin; 1475f0ae7da4SStefano Zampini if (!n) { 1476f0ae7da4SStefano Zampini is->pure_neumann = PETSC_TRUE; 1477f0ae7da4SStefano Zampini } else { 1478f0ae7da4SStefano Zampini PetscInt i; 1479f0ae7da4SStefano Zampini is->pure_neumann = PETSC_FALSE; 1480f0ae7da4SStefano Zampini 1481f0ae7da4SStefano Zampini if (columns) { 1482f0ae7da4SStefano Zampini ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 1483f0ae7da4SStefano Zampini } else { 1484f0ae7da4SStefano Zampini ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 1485f0ae7da4SStefano Zampini } 1486f0ae7da4SStefano Zampini if (diag != 0.) { 1487f0ae7da4SStefano Zampini const PetscScalar *array; 1488f0ae7da4SStefano Zampini ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr); 1489f0ae7da4SStefano Zampini for (i=0; i<n; i++) { 1490f0ae7da4SStefano Zampini ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr); 1491f0ae7da4SStefano Zampini } 1492f0ae7da4SStefano Zampini ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr); 1493f0ae7da4SStefano Zampini } 1494f0ae7da4SStefano Zampini ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1495f0ae7da4SStefano Zampini ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1496f0ae7da4SStefano Zampini } 1497f0ae7da4SStefano Zampini PetscFunctionReturn(0); 1498f0ae7da4SStefano Zampini } 1499f0ae7da4SStefano Zampini 1500f0ae7da4SStefano Zampini #undef __FUNCT__ 1501f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_Private_IS" 1502f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns) 15032e74eeadSLisandro Dalcin { 15046e520ac8SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 15056e520ac8SStefano Zampini PetscInt nr,nl,len,i; 15066e520ac8SStefano Zampini PetscInt *lrows; 15072e74eeadSLisandro Dalcin PetscErrorCode ierr; 15082e74eeadSLisandro Dalcin 15092e74eeadSLisandro Dalcin PetscFunctionBegin; 1510f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG) 1511f0ae7da4SStefano Zampini if (columns || diag != 0. || (x && b)) { 1512f0ae7da4SStefano Zampini PetscBool cong; 1513f0ae7da4SStefano Zampini ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr); 1514f0ae7da4SStefano 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"); 1515f0ae7da4SStefano 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"); 1516f0ae7da4SStefano Zampini if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent"); 1517f0ae7da4SStefano Zampini } 1518f0ae7da4SStefano Zampini #endif 15196e520ac8SStefano Zampini /* get locally owned rows */ 1520f0ae7da4SStefano Zampini ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr); 15216e520ac8SStefano Zampini /* fix right hand side if needed */ 15226e520ac8SStefano Zampini if (x && b) { 15236e520ac8SStefano Zampini const PetscScalar *xx; 15246e520ac8SStefano Zampini PetscScalar *bb; 15256e520ac8SStefano Zampini 15266e520ac8SStefano Zampini ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr); 15276e520ac8SStefano Zampini ierr = VecGetArray(b, &bb);CHKERRQ(ierr); 15286e520ac8SStefano Zampini for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]]; 15296e520ac8SStefano Zampini ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr); 15306e520ac8SStefano Zampini ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr); 15312e74eeadSLisandro Dalcin } 15326e520ac8SStefano Zampini /* get rows associated to the local matrices */ 15336e520ac8SStefano Zampini if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */ 15346e520ac8SStefano Zampini ierr = MatISComputeSF_Private(A);CHKERRQ(ierr); 15356e520ac8SStefano Zampini } 15366e520ac8SStefano Zampini ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr); 15376e520ac8SStefano Zampini ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr); 15386e520ac8SStefano Zampini ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 15396e520ac8SStefano Zampini for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1; 15406e520ac8SStefano Zampini ierr = PetscFree(lrows);CHKERRQ(ierr); 15416e520ac8SStefano Zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 15426e520ac8SStefano Zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 15436e520ac8SStefano Zampini ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr); 15446e520ac8SStefano Zampini for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i; 1545f0ae7da4SStefano Zampini ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr); 15466e520ac8SStefano Zampini ierr = PetscFree(lrows);CHKERRQ(ierr); 15472e74eeadSLisandro Dalcin PetscFunctionReturn(0); 15482e74eeadSLisandro Dalcin } 15492e74eeadSLisandro Dalcin 15502e74eeadSLisandro Dalcin #undef __FUNCT__ 1551f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRows_IS" 1552f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1553b4319ba4SBarry Smith { 1554dfbe8321SBarry Smith PetscErrorCode ierr; 1555b4319ba4SBarry Smith 1556b4319ba4SBarry Smith PetscFunctionBegin; 1557f0ae7da4SStefano Zampini ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr); 1558f0ae7da4SStefano Zampini PetscFunctionReturn(0); 1559f0ae7da4SStefano Zampini } 15602205254eSKarl Rupp 1561f0ae7da4SStefano Zampini #undef __FUNCT__ 1562f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_IS" 1563f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1564f0ae7da4SStefano Zampini { 1565f0ae7da4SStefano Zampini PetscErrorCode ierr; 1566f0ae7da4SStefano Zampini 1567f0ae7da4SStefano Zampini PetscFunctionBegin; 1568f0ae7da4SStefano Zampini ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr); 1569b4319ba4SBarry Smith PetscFunctionReturn(0); 1570b4319ba4SBarry Smith } 1571b4319ba4SBarry Smith 1572b4319ba4SBarry Smith #undef __FUNCT__ 1573b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS" 1574a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type) 1575b4319ba4SBarry Smith { 1576b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1577dfbe8321SBarry Smith PetscErrorCode ierr; 1578b4319ba4SBarry Smith 1579b4319ba4SBarry Smith PetscFunctionBegin; 1580b4319ba4SBarry Smith ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr); 1581b4319ba4SBarry Smith PetscFunctionReturn(0); 1582b4319ba4SBarry Smith } 1583b4319ba4SBarry Smith 1584b4319ba4SBarry Smith #undef __FUNCT__ 1585b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS" 1586a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type) 1587b4319ba4SBarry Smith { 1588b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1589dfbe8321SBarry Smith PetscErrorCode ierr; 1590b4319ba4SBarry Smith 1591b4319ba4SBarry Smith PetscFunctionBegin; 1592b4319ba4SBarry Smith ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr); 1593b4319ba4SBarry Smith PetscFunctionReturn(0); 1594b4319ba4SBarry Smith } 1595b4319ba4SBarry Smith 1596b4319ba4SBarry Smith #undef __FUNCT__ 1597b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS" 1598a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local) 1599b4319ba4SBarry Smith { 1600b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)mat->data; 1601b4319ba4SBarry Smith 1602b4319ba4SBarry Smith PetscFunctionBegin; 1603b4319ba4SBarry Smith *local = is->A; 1604b4319ba4SBarry Smith PetscFunctionReturn(0); 1605b4319ba4SBarry Smith } 1606b4319ba4SBarry Smith 1607b4319ba4SBarry Smith #undef __FUNCT__ 1608b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat" 1609b4319ba4SBarry Smith /*@ 1610b4319ba4SBarry Smith MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix. 1611b4319ba4SBarry Smith 1612b4319ba4SBarry Smith Input Parameter: 1613b4319ba4SBarry Smith . mat - the matrix 1614b4319ba4SBarry Smith 1615b4319ba4SBarry Smith Output Parameter: 1616eb82efa4SStefano Zampini . local - the local matrix 1617b4319ba4SBarry Smith 1618b4319ba4SBarry Smith Level: advanced 1619b4319ba4SBarry Smith 1620b4319ba4SBarry Smith Notes: 1621b4319ba4SBarry Smith This can be called if you have precomputed the nonzero structure of the 1622b4319ba4SBarry Smith matrix and want to provide it to the inner matrix object to improve the performance 1623b4319ba4SBarry Smith of the MatSetValues() operation. 1624b4319ba4SBarry Smith 1625b4319ba4SBarry Smith .seealso: MATIS 1626b4319ba4SBarry Smith @*/ 16277087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local) 1628b4319ba4SBarry Smith { 16294ac538c5SBarry Smith PetscErrorCode ierr; 1630b4319ba4SBarry Smith 1631b4319ba4SBarry Smith PetscFunctionBegin; 16320700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1633b4319ba4SBarry Smith PetscValidPointer(local,2); 16344ac538c5SBarry Smith ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr); 1635b4319ba4SBarry Smith PetscFunctionReturn(0); 1636b4319ba4SBarry Smith } 1637b4319ba4SBarry Smith 16383b03a366Sstefano_zampini #undef __FUNCT__ 16393b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS" 1640a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local) 16413b03a366Sstefano_zampini { 16423b03a366Sstefano_zampini Mat_IS *is = (Mat_IS*)mat->data; 16433b03a366Sstefano_zampini PetscInt nrows,ncols,orows,ocols; 16443b03a366Sstefano_zampini PetscErrorCode ierr; 16453b03a366Sstefano_zampini 16463b03a366Sstefano_zampini PetscFunctionBegin; 16474e4c7dbeSStefano Zampini if (is->A) { 16483b03a366Sstefano_zampini ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr); 16493b03a366Sstefano_zampini ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr); 1650f0ae7da4SStefano 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); 16514e4c7dbeSStefano Zampini } 16523b03a366Sstefano_zampini ierr = PetscObjectReference((PetscObject)local);CHKERRQ(ierr); 16533b03a366Sstefano_zampini ierr = MatDestroy(&is->A);CHKERRQ(ierr); 16543b03a366Sstefano_zampini is->A = local; 16553b03a366Sstefano_zampini PetscFunctionReturn(0); 16563b03a366Sstefano_zampini } 16573b03a366Sstefano_zampini 16583b03a366Sstefano_zampini #undef __FUNCT__ 16593b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat" 16603b03a366Sstefano_zampini /*@ 1661eb82efa4SStefano Zampini MatISSetLocalMat - Replace the local matrix stored inside a MATIS object. 16623b03a366Sstefano_zampini 16633b03a366Sstefano_zampini Input Parameter: 16643b03a366Sstefano_zampini . mat - the matrix 1665eb82efa4SStefano Zampini . local - the local matrix 16663b03a366Sstefano_zampini 16673b03a366Sstefano_zampini Output Parameter: 16683b03a366Sstefano_zampini 16693b03a366Sstefano_zampini Level: advanced 16703b03a366Sstefano_zampini 16713b03a366Sstefano_zampini Notes: 16723b03a366Sstefano_zampini This can be called if you have precomputed the local matrix and 16733b03a366Sstefano_zampini want to provide it to the matrix object MATIS. 16743b03a366Sstefano_zampini 16753b03a366Sstefano_zampini .seealso: MATIS 16763b03a366Sstefano_zampini @*/ 16773b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local) 16783b03a366Sstefano_zampini { 16793b03a366Sstefano_zampini PetscErrorCode ierr; 16803b03a366Sstefano_zampini 16813b03a366Sstefano_zampini PetscFunctionBegin; 16823b03a366Sstefano_zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1683b7ce53b6SStefano Zampini PetscValidHeaderSpecific(local,MAT_CLASSID,2); 16843b03a366Sstefano_zampini ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr); 16853b03a366Sstefano_zampini PetscFunctionReturn(0); 16863b03a366Sstefano_zampini } 16873b03a366Sstefano_zampini 16886726f965SBarry Smith #undef __FUNCT__ 16896726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS" 1690a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A) 16916726f965SBarry Smith { 16926726f965SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 16936726f965SBarry Smith PetscErrorCode ierr; 16946726f965SBarry Smith 16956726f965SBarry Smith PetscFunctionBegin; 16966726f965SBarry Smith ierr = MatZeroEntries(a->A);CHKERRQ(ierr); 16976726f965SBarry Smith PetscFunctionReturn(0); 16986726f965SBarry Smith } 16996726f965SBarry Smith 17006726f965SBarry Smith #undef __FUNCT__ 17012e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS" 1702a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a) 17032e74eeadSLisandro Dalcin { 17042e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 17052e74eeadSLisandro Dalcin PetscErrorCode ierr; 17062e74eeadSLisandro Dalcin 17072e74eeadSLisandro Dalcin PetscFunctionBegin; 17082e74eeadSLisandro Dalcin ierr = MatScale(is->A,a);CHKERRQ(ierr); 17092e74eeadSLisandro Dalcin PetscFunctionReturn(0); 17102e74eeadSLisandro Dalcin } 17112e74eeadSLisandro Dalcin 17122e74eeadSLisandro Dalcin #undef __FUNCT__ 17132e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS" 1714a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 17152e74eeadSLisandro Dalcin { 17162e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 17172e74eeadSLisandro Dalcin PetscErrorCode ierr; 17182e74eeadSLisandro Dalcin 17192e74eeadSLisandro Dalcin PetscFunctionBegin; 17202e74eeadSLisandro Dalcin /* get diagonal of the local matrix */ 1721e176bc59SStefano Zampini ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr); 17222e74eeadSLisandro Dalcin 17232e74eeadSLisandro Dalcin /* scatter diagonal back into global vector */ 17242e74eeadSLisandro Dalcin ierr = VecSet(v,0);CHKERRQ(ierr); 1725e176bc59SStefano Zampini ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1726e176bc59SStefano Zampini ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 17272e74eeadSLisandro Dalcin PetscFunctionReturn(0); 17282e74eeadSLisandro Dalcin } 17292e74eeadSLisandro Dalcin 17302e74eeadSLisandro Dalcin #undef __FUNCT__ 17316726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS" 1732a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg) 17336726f965SBarry Smith { 17346726f965SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 17356726f965SBarry Smith PetscErrorCode ierr; 17366726f965SBarry Smith 17376726f965SBarry Smith PetscFunctionBegin; 17384e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 17396726f965SBarry Smith PetscFunctionReturn(0); 17406726f965SBarry Smith } 17416726f965SBarry Smith 1742284134d9SBarry Smith #undef __FUNCT__ 1743f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS" 1744f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str) 1745f26d0771SStefano Zampini { 1746f26d0771SStefano Zampini Mat_IS *y = (Mat_IS*)Y->data; 1747f26d0771SStefano Zampini Mat_IS *x; 1748f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1749f26d0771SStefano Zampini PetscBool ismatis; 1750f26d0771SStefano Zampini #endif 1751f26d0771SStefano Zampini PetscErrorCode ierr; 1752f26d0771SStefano Zampini 1753f26d0771SStefano Zampini PetscFunctionBegin; 1754f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1755f26d0771SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr); 1756f26d0771SStefano Zampini if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 1757f26d0771SStefano Zampini #endif 1758f26d0771SStefano Zampini x = (Mat_IS*)X->data; 1759f26d0771SStefano Zampini ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr); 1760f26d0771SStefano Zampini PetscFunctionReturn(0); 1761f26d0771SStefano Zampini } 1762f26d0771SStefano Zampini 1763f26d0771SStefano Zampini #undef __FUNCT__ 1764f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS" 1765f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat) 1766f26d0771SStefano Zampini { 1767f26d0771SStefano Zampini Mat lA; 1768f26d0771SStefano Zampini Mat_IS *matis; 1769f26d0771SStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 1770f26d0771SStefano Zampini IS is; 1771f26d0771SStefano Zampini const PetscInt *rg,*rl; 1772f26d0771SStefano Zampini PetscInt nrg; 1773f26d0771SStefano Zampini PetscInt N,M,nrl,i,*idxs; 1774f26d0771SStefano Zampini PetscErrorCode ierr; 1775f26d0771SStefano Zampini 1776f26d0771SStefano Zampini PetscFunctionBegin; 1777f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr); 1778f26d0771SStefano Zampini ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr); 1779f26d0771SStefano Zampini ierr = ISGetIndices(row,&rl);CHKERRQ(ierr); 1780f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr); 1781f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1782f0ae7da4SStefano 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); 1783f26d0771SStefano Zampini #endif 1784f26d0771SStefano Zampini ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr); 1785f26d0771SStefano Zampini /* map from [0,nrl) to row */ 1786f26d0771SStefano Zampini for (i=0;i<nrl;i++) idxs[i] = rl[i]; 1787f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1788f26d0771SStefano Zampini for (i=nrl;i<nrg;i++) idxs[i] = nrg; 1789f26d0771SStefano Zampini #else 1790f26d0771SStefano Zampini for (i=nrl;i<nrg;i++) idxs[i] = -1; 1791f26d0771SStefano Zampini #endif 1792f26d0771SStefano Zampini ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr); 1793f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr); 1794f26d0771SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 1795f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 1796f26d0771SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 1797f26d0771SStefano Zampini /* compute new l2g map for columns */ 1798f26d0771SStefano Zampini if (col != row || A->rmap->mapping != A->cmap->mapping) { 1799f26d0771SStefano Zampini const PetscInt *cg,*cl; 1800f26d0771SStefano Zampini PetscInt ncg; 1801f26d0771SStefano Zampini PetscInt ncl; 1802f26d0771SStefano Zampini 1803f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr); 1804f26d0771SStefano Zampini ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr); 1805f26d0771SStefano Zampini ierr = ISGetIndices(col,&cl);CHKERRQ(ierr); 1806f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr); 1807f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1808f0ae7da4SStefano 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); 1809f26d0771SStefano Zampini #endif 1810f26d0771SStefano Zampini ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr); 1811f26d0771SStefano Zampini /* map from [0,ncl) to col */ 1812f26d0771SStefano Zampini for (i=0;i<ncl;i++) idxs[i] = cl[i]; 1813f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1814f26d0771SStefano Zampini for (i=ncl;i<ncg;i++) idxs[i] = ncg; 1815f26d0771SStefano Zampini #else 1816f26d0771SStefano Zampini for (i=ncl;i<ncg;i++) idxs[i] = -1; 1817f26d0771SStefano Zampini #endif 1818f26d0771SStefano Zampini ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr); 1819f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr); 1820f26d0771SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 1821f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 1822f26d0771SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 1823f26d0771SStefano Zampini } else { 1824f26d0771SStefano Zampini ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr); 1825f26d0771SStefano Zampini cl2g = rl2g; 1826f26d0771SStefano Zampini } 1827f26d0771SStefano Zampini /* create the MATIS submatrix */ 1828f26d0771SStefano Zampini ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); 1829f26d0771SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr); 1830f26d0771SStefano Zampini ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 1831f26d0771SStefano Zampini ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr); 1832b0aa3428SStefano Zampini matis = (Mat_IS*)((*submat)->data); 1833f26d0771SStefano Zampini matis->islocalref = PETSC_TRUE; 1834f26d0771SStefano Zampini ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr); 1835f26d0771SStefano Zampini ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr); 1836f26d0771SStefano Zampini ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr); 1837f26d0771SStefano Zampini ierr = MatSetUp(*submat);CHKERRQ(ierr); 1838f26d0771SStefano Zampini ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1839f26d0771SStefano Zampini ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1840f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 1841f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 1842f26d0771SStefano Zampini /* remove unsupported ops */ 1843f26d0771SStefano Zampini ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 1844f26d0771SStefano Zampini (*submat)->ops->destroy = MatDestroy_IS; 1845f26d0771SStefano Zampini (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 1846f26d0771SStefano Zampini (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 1847f26d0771SStefano Zampini (*submat)->ops->assemblybegin = MatAssemblyBegin_IS; 1848f26d0771SStefano Zampini (*submat)->ops->assemblyend = MatAssemblyEnd_IS; 1849f26d0771SStefano Zampini PetscFunctionReturn(0); 1850f26d0771SStefano Zampini } 1851f26d0771SStefano Zampini 1852f26d0771SStefano Zampini #undef __FUNCT__ 1853284134d9SBarry Smith #define __FUNCT__ "MatCreateIS" 1854284134d9SBarry Smith /*@ 18553c212e90SHong Zhang MatCreateIS - Creates a "process" unassembled matrix, assembled on each 1856284134d9SBarry Smith process but not across processes. 1857284134d9SBarry Smith 1858284134d9SBarry Smith Input Parameters: 1859284134d9SBarry Smith + comm - MPI communicator that will share the matrix 1860e176bc59SStefano Zampini . bs - block size of the matrix 1861df3898eeSBarry Smith . m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products 1862e176bc59SStefano Zampini . rmap - local to global map for rows 1863e176bc59SStefano Zampini - cmap - local to global map for cols 1864284134d9SBarry Smith 1865284134d9SBarry Smith Output Parameter: 1866284134d9SBarry Smith . A - the resulting matrix 1867284134d9SBarry Smith 18688e6c10adSSatish Balay Level: advanced 18698e6c10adSSatish Balay 18703c212e90SHong Zhang Notes: See MATIS for more details. 18716fdf41d1SStefano Zampini m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors 18726fdf41d1SStefano Zampini used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices. 18733c212e90SHong Zhang If either rmap or cmap are NULL, then the matrix is assumed to be square. 1874284134d9SBarry Smith 1875284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping() 1876284134d9SBarry Smith @*/ 1877e176bc59SStefano Zampini PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A) 1878284134d9SBarry Smith { 1879284134d9SBarry Smith PetscErrorCode ierr; 1880284134d9SBarry Smith 1881284134d9SBarry Smith PetscFunctionBegin; 18826fdf41d1SStefano Zampini if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings"); 1883284134d9SBarry Smith ierr = MatCreate(comm,A);CHKERRQ(ierr); 18846fdf41d1SStefano Zampini if (bs > 0) { 1885d3ee2243SStefano Zampini ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr); 18866fdf41d1SStefano Zampini } 1887284134d9SBarry Smith ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr); 1888284134d9SBarry Smith ierr = MatSetType(*A,MATIS);CHKERRQ(ierr); 1889e176bc59SStefano Zampini if (rmap && cmap) { 1890e176bc59SStefano Zampini ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr); 1891e176bc59SStefano Zampini } else if (!rmap) { 1892e176bc59SStefano Zampini ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr); 1893e176bc59SStefano Zampini } else { 1894e176bc59SStefano Zampini ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr); 1895e176bc59SStefano Zampini } 1896284134d9SBarry Smith PetscFunctionReturn(0); 1897284134d9SBarry Smith } 1898284134d9SBarry Smith 1899b4319ba4SBarry Smith /*MC 1900f26d0771SStefano Zampini MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP). 1901b4319ba4SBarry Smith This stores the matrices in globally unassembled form. Each processor 1902b4319ba4SBarry Smith assembles only its local Neumann problem and the parallel matrix vector 1903b4319ba4SBarry Smith product is handled "implicitly". 1904b4319ba4SBarry Smith 1905b4319ba4SBarry Smith Operations Provided: 19066726f965SBarry Smith + MatMult() 19072e74eeadSLisandro Dalcin . MatMultAdd() 19082e74eeadSLisandro Dalcin . MatMultTranspose() 19092e74eeadSLisandro Dalcin . MatMultTransposeAdd() 19106726f965SBarry Smith . MatZeroEntries() 19116726f965SBarry Smith . MatSetOption() 19122e74eeadSLisandro Dalcin . MatZeroRows() 19132e74eeadSLisandro Dalcin . MatSetValues() 191497563a80SStefano Zampini . MatSetValuesBlocked() 19156726f965SBarry Smith . MatSetValuesLocal() 191697563a80SStefano Zampini . MatSetValuesBlockedLocal() 19172e74eeadSLisandro Dalcin . MatScale() 19182e74eeadSLisandro Dalcin . MatGetDiagonal() 19192b404112SStefano Zampini . MatMissingDiagonal() 19202b404112SStefano Zampini . MatDuplicate() 19212b404112SStefano Zampini . MatCopy() 1922f26d0771SStefano Zampini . MatAXPY() 1923f26d0771SStefano Zampini . MatGetSubMatrix() 1924f26d0771SStefano Zampini . MatGetLocalSubMatrix() 1925d7f69cd0SStefano Zampini . MatTranspose() 19266726f965SBarry Smith - MatSetLocalToGlobalMapping() 1927b4319ba4SBarry Smith 1928b4319ba4SBarry Smith Options Database Keys: 1929b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions() 1930b4319ba4SBarry Smith 1931b4319ba4SBarry Smith Notes: Options prefix for the inner matrix are given by -is_mat_xxx 1932b4319ba4SBarry Smith 1933b4319ba4SBarry Smith You must call MatSetLocalToGlobalMapping() before using this matrix type. 1934b4319ba4SBarry Smith 1935b4319ba4SBarry Smith You can do matrix preallocation on the local matrix after you obtain it with 1936eb82efa4SStefano Zampini MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation() 1937b4319ba4SBarry Smith 1938b4319ba4SBarry Smith Level: advanced 1939b4319ba4SBarry Smith 1940f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP 1941b4319ba4SBarry Smith 1942b4319ba4SBarry Smith M*/ 1943b4319ba4SBarry Smith 1944b4319ba4SBarry Smith #undef __FUNCT__ 1945b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS" 19468cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 1947b4319ba4SBarry Smith { 1948dfbe8321SBarry Smith PetscErrorCode ierr; 1949b4319ba4SBarry Smith Mat_IS *b; 1950b4319ba4SBarry Smith 1951b4319ba4SBarry Smith PetscFunctionBegin; 1952b00a9115SJed Brown ierr = PetscNewLog(A,&b);CHKERRQ(ierr); 1953b4319ba4SBarry Smith A->data = (void*)b; 1954b4319ba4SBarry Smith 1955e176bc59SStefano Zampini /* matrix ops */ 1956e176bc59SStefano Zampini ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 1957b4319ba4SBarry Smith A->ops->mult = MatMult_IS; 19582e74eeadSLisandro Dalcin A->ops->multadd = MatMultAdd_IS; 19592e74eeadSLisandro Dalcin A->ops->multtranspose = MatMultTranspose_IS; 19602e74eeadSLisandro Dalcin A->ops->multtransposeadd = MatMultTransposeAdd_IS; 1961b4319ba4SBarry Smith A->ops->destroy = MatDestroy_IS; 1962b4319ba4SBarry Smith A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 19632e74eeadSLisandro Dalcin A->ops->setvalues = MatSetValues_IS; 196498921651SStefano Zampini A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 1965b4319ba4SBarry Smith A->ops->setvalueslocal = MatSetValuesLocal_IS; 1966f0006bf2SLisandro Dalcin A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 19672e74eeadSLisandro Dalcin A->ops->zerorows = MatZeroRows_IS; 1968f0ae7da4SStefano Zampini A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 1969b4319ba4SBarry Smith A->ops->assemblybegin = MatAssemblyBegin_IS; 1970b4319ba4SBarry Smith A->ops->assemblyend = MatAssemblyEnd_IS; 1971b4319ba4SBarry Smith A->ops->view = MatView_IS; 19726726f965SBarry Smith A->ops->zeroentries = MatZeroEntries_IS; 19732e74eeadSLisandro Dalcin A->ops->scale = MatScale_IS; 19742e74eeadSLisandro Dalcin A->ops->getdiagonal = MatGetDiagonal_IS; 19756726f965SBarry Smith A->ops->setoption = MatSetOption_IS; 197669796d55SStefano Zampini A->ops->ishermitian = MatIsHermitian_IS; 197769796d55SStefano Zampini A->ops->issymmetric = MatIsSymmetric_IS; 1978ad6194a2SStefano Zampini A->ops->duplicate = MatDuplicate_IS; 19796bd84002SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_IS; 19802b404112SStefano Zampini A->ops->copy = MatCopy_IS; 1981659959c5SStefano Zampini A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 1982a8116848SStefano Zampini A->ops->getsubmatrix = MatGetSubMatrix_IS; 1983f26d0771SStefano Zampini A->ops->axpy = MatAXPY_IS; 19843fd1c9e7SStefano Zampini A->ops->diagonalset = MatDiagonalSet_IS; 19853fd1c9e7SStefano Zampini A->ops->shift = MatShift_IS; 1986d7f69cd0SStefano Zampini A->ops->transpose = MatTranspose_IS; 1987b4319ba4SBarry Smith 1988b7ce53b6SStefano Zampini /* special MATIS functions */ 1989bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr); 1990bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr); 1991b7ce53b6SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr); 19922e1947a5SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr); 199317667f90SBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr); 1994b4319ba4SBarry Smith PetscFunctionReturn(0); 1995b4319ba4SBarry Smith } 1996