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__ 177fa8f2d3SStefano Zampini #define __FUNCT__ "MatGetInfo_IS" 187fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo) 197fa8f2d3SStefano Zampini { 207fa8f2d3SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 217fa8f2d3SStefano Zampini MatInfo info; 22314ce898Sstefano_zampini PetscReal isend[6],irecv[6]; 237fa8f2d3SStefano Zampini PetscInt bs; 247fa8f2d3SStefano Zampini PetscErrorCode ierr; 257fa8f2d3SStefano Zampini 267fa8f2d3SStefano Zampini PetscFunctionBegin; 277fa8f2d3SStefano Zampini ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 28a2ccb5f9Sstefano_zampini if (matis->A->ops->getinfo) { 297fa8f2d3SStefano Zampini ierr = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr); 307fa8f2d3SStefano Zampini isend[0] = info.nz_used; 317fa8f2d3SStefano Zampini isend[1] = info.nz_allocated; 327fa8f2d3SStefano Zampini isend[2] = info.nz_unneeded; 337fa8f2d3SStefano Zampini isend[3] = info.memory; 347fa8f2d3SStefano Zampini isend[4] = info.mallocs; 35a2ccb5f9Sstefano_zampini } else { 36a2ccb5f9Sstefano_zampini isend[0] = 0.; 37a2ccb5f9Sstefano_zampini isend[1] = 0.; 38a2ccb5f9Sstefano_zampini isend[2] = 0.; 39a2ccb5f9Sstefano_zampini isend[3] = 0.; 40a2ccb5f9Sstefano_zampini isend[4] = 0.; 41a2ccb5f9Sstefano_zampini } 42314ce898Sstefano_zampini isend[5] = matis->A->num_ass; 437fa8f2d3SStefano Zampini if (flag == MAT_LOCAL) { 447fa8f2d3SStefano Zampini ginfo->nz_used = isend[0]; 457fa8f2d3SStefano Zampini ginfo->nz_allocated = isend[1]; 467fa8f2d3SStefano Zampini ginfo->nz_unneeded = isend[2]; 477fa8f2d3SStefano Zampini ginfo->memory = isend[3]; 487fa8f2d3SStefano Zampini ginfo->mallocs = isend[4]; 49314ce898Sstefano_zampini ginfo->assemblies = isend[5]; 507fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_MAX) { 51314ce898Sstefano_zampini ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 527fa8f2d3SStefano Zampini 537fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 547fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 557fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 567fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 577fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 58314ce898Sstefano_zampini ginfo->assemblies = irecv[5]; 597fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_SUM) { 607fa8f2d3SStefano Zampini ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 617fa8f2d3SStefano Zampini 627fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 637fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 647fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 657fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 667fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 677fa8f2d3SStefano Zampini ginfo->assemblies = A->num_ass; 687fa8f2d3SStefano Zampini } 697fa8f2d3SStefano Zampini ginfo->block_size = bs; 707fa8f2d3SStefano Zampini ginfo->fill_ratio_given = 0; 717fa8f2d3SStefano Zampini ginfo->fill_ratio_needed = 0; 727fa8f2d3SStefano Zampini ginfo->factor_mallocs = 0; 737fa8f2d3SStefano Zampini PetscFunctionReturn(0); 747fa8f2d3SStefano Zampini } 757fa8f2d3SStefano Zampini 767fa8f2d3SStefano Zampini #undef __FUNCT__ 775e3038f0Sstefano_zampini #define __FUNCT__ "MatConvert_Nest_IS" 785e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat) 795e3038f0Sstefano_zampini { 805e3038f0Sstefano_zampini Mat **nest,*snest,**rnest,lA,B; 815e3038f0Sstefano_zampini IS *iscol,*isrow,*islrow,*islcol; 825e3038f0Sstefano_zampini ISLocalToGlobalMapping rl2g,cl2g; 835e3038f0Sstefano_zampini MPI_Comm comm; 845e3038f0Sstefano_zampini PetscInt *lr,*lc,*lrb,*lcb,*l2gidxs; 855e3038f0Sstefano_zampini PetscInt sti,stl,i,j,nr,nc,rbs,cbs; 86*9e7b2b25Sstefano_zampini PetscBool convert,lreuse,*istrans; 875e3038f0Sstefano_zampini PetscErrorCode ierr; 885e3038f0Sstefano_zampini 895e3038f0Sstefano_zampini PetscFunctionBeginUser; 905e3038f0Sstefano_zampini ierr = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr); 915e3038f0Sstefano_zampini lreuse = PETSC_FALSE; 925e3038f0Sstefano_zampini rnest = NULL; 935e3038f0Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 945e3038f0Sstefano_zampini PetscBool ismatis,isnest; 955e3038f0Sstefano_zampini 965e3038f0Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr); 975e3038f0Sstefano_zampini if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type); 985e3038f0Sstefano_zampini ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 995e3038f0Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr); 1005e3038f0Sstefano_zampini if (isnest) { 1015e3038f0Sstefano_zampini ierr = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr); 1025e3038f0Sstefano_zampini lreuse = (PetscBool)(i == nr && j == nc); 1035e3038f0Sstefano_zampini if (!lreuse) rnest = NULL; 1045e3038f0Sstefano_zampini } 1055e3038f0Sstefano_zampini } 1065e3038f0Sstefano_zampini ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 1075e3038f0Sstefano_zampini ierr = PetscCalloc4(nr,&lr,nc,&lc,nr,&lrb,nc,&lcb);CHKERRQ(ierr); 108*9e7b2b25Sstefano_zampini ierr = PetscCalloc6(nr,&isrow,nc,&iscol, 1095e3038f0Sstefano_zampini nr,&islrow,nc,&islcol, 110*9e7b2b25Sstefano_zampini nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr); 1115e3038f0Sstefano_zampini ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr); 1125e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 1135e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 1145e3038f0Sstefano_zampini PetscBool ismatis; 115*9e7b2b25Sstefano_zampini PetscInt l1,l2,lb1,lb2,ij=i*nc+j; 1165e3038f0Sstefano_zampini 1175e3038f0Sstefano_zampini /* Null matrix pointers are allowed in MATNEST */ 1185e3038f0Sstefano_zampini if (!nest[i][j]) continue; 1195e3038f0Sstefano_zampini 1205e3038f0Sstefano_zampini /* Nested matrices should be of type MATIS */ 121*9e7b2b25Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr); 122*9e7b2b25Sstefano_zampini if (istrans[ij]) { 123*9e7b2b25Sstefano_zampini Mat T,lT; 124*9e7b2b25Sstefano_zampini ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr); 125*9e7b2b25Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr); 126*9e7b2b25Sstefano_zampini if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) (transposed) is not of type MATIS",i,j); 127*9e7b2b25Sstefano_zampini ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr); 128*9e7b2b25Sstefano_zampini ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr); 129*9e7b2b25Sstefano_zampini } else { 1305e3038f0Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr); 1315e3038f0Sstefano_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); 132*9e7b2b25Sstefano_zampini ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr); 133*9e7b2b25Sstefano_zampini } 1345e3038f0Sstefano_zampini 1355e3038f0Sstefano_zampini /* Check compatibility of local sizes */ 1365e3038f0Sstefano_zampini ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr); 137*9e7b2b25Sstefano_zampini ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr); 1385e3038f0Sstefano_zampini if (!l1 || !l2) continue; 1395e3038f0Sstefano_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); 1405e3038f0Sstefano_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); 1415e3038f0Sstefano_zampini lr[i] = l1; 1425e3038f0Sstefano_zampini lc[j] = l2; 143*9e7b2b25Sstefano_zampini if (lrb[i] && lb1 != 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],lb1); 144*9e7b2b25Sstefano_zampini if (lcb[j] && lb2 != 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],lb2); 145*9e7b2b25Sstefano_zampini lrb[i] = lb1; 146*9e7b2b25Sstefano_zampini lcb[j] = lb2; 1475e3038f0Sstefano_zampini 1485e3038f0Sstefano_zampini /* check compatibilty for local matrix reusage */ 1495e3038f0Sstefano_zampini if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE; 1505e3038f0Sstefano_zampini } 1515e3038f0Sstefano_zampini } 1525e3038f0Sstefano_zampini 1535e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG) 1545e3038f0Sstefano_zampini /* Check compatibility of l2g maps for rows */ 1555e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 1565e3038f0Sstefano_zampini rl2g = NULL; 1575e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 1585e3038f0Sstefano_zampini PetscInt n1,n2; 1595e3038f0Sstefano_zampini 1605e3038f0Sstefano_zampini if (!nest[i][j]) continue; 161*9e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 162*9e7b2b25Sstefano_zampini Mat T; 163*9e7b2b25Sstefano_zampini 164*9e7b2b25Sstefano_zampini ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr); 165*9e7b2b25Sstefano_zampini ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr); 166*9e7b2b25Sstefano_zampini } else { 1675e3038f0Sstefano_zampini ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr); 168*9e7b2b25Sstefano_zampini } 1695e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr); 1705e3038f0Sstefano_zampini if (!n1) continue; 1715e3038f0Sstefano_zampini if (!rl2g) { 1725e3038f0Sstefano_zampini rl2g = cl2g; 1735e3038f0Sstefano_zampini } else { 1745e3038f0Sstefano_zampini const PetscInt *idxs1,*idxs2; 1755e3038f0Sstefano_zampini PetscBool same; 1765e3038f0Sstefano_zampini 1775e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr); 1785e3038f0Sstefano_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); 1795e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr); 1805e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr); 1815e3038f0Sstefano_zampini ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr); 1825e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr); 1835e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr); 1845e3038f0Sstefano_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); 1855e3038f0Sstefano_zampini } 1865e3038f0Sstefano_zampini } 1875e3038f0Sstefano_zampini } 1885e3038f0Sstefano_zampini /* Check compatibility of l2g maps for columns */ 1895e3038f0Sstefano_zampini for (i=0;i<nc;i++) { 1905e3038f0Sstefano_zampini rl2g = NULL; 1915e3038f0Sstefano_zampini for (j=0;j<nr;j++) { 1925e3038f0Sstefano_zampini PetscInt n1,n2; 1935e3038f0Sstefano_zampini 1945e3038f0Sstefano_zampini if (!nest[j][i]) continue; 195*9e7b2b25Sstefano_zampini if (istrans[j*nc+i]) { 196*9e7b2b25Sstefano_zampini Mat T; 197*9e7b2b25Sstefano_zampini 198*9e7b2b25Sstefano_zampini ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr); 199*9e7b2b25Sstefano_zampini ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr); 200*9e7b2b25Sstefano_zampini } else { 2015e3038f0Sstefano_zampini ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr); 202*9e7b2b25Sstefano_zampini } 2035e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr); 2045e3038f0Sstefano_zampini if (!n1) continue; 2055e3038f0Sstefano_zampini if (!rl2g) { 2065e3038f0Sstefano_zampini rl2g = cl2g; 2075e3038f0Sstefano_zampini } else { 2085e3038f0Sstefano_zampini const PetscInt *idxs1,*idxs2; 2095e3038f0Sstefano_zampini PetscBool same; 2105e3038f0Sstefano_zampini 2115e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr); 2125e3038f0Sstefano_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); 2135e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr); 2145e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr); 2155e3038f0Sstefano_zampini ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr); 2165e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr); 2175e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr); 2185e3038f0Sstefano_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); 2195e3038f0Sstefano_zampini } 2205e3038f0Sstefano_zampini } 2215e3038f0Sstefano_zampini } 2225e3038f0Sstefano_zampini #endif 2235e3038f0Sstefano_zampini 2245e3038f0Sstefano_zampini B = NULL; 2255e3038f0Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 2265e3038f0Sstefano_zampini /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */ 2275e3038f0Sstefano_zampini for (i=0,stl=0;i<nr;i++) stl += lr[i]; 2285e3038f0Sstefano_zampini ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr); 2295e3038f0Sstefano_zampini for (i=0,sti=0,stl=0;i<nr;i++) { 2305e3038f0Sstefano_zampini Mat usedmat; 2315e3038f0Sstefano_zampini Mat_IS *matis; 2325e3038f0Sstefano_zampini const PetscInt *idxs; 2335e3038f0Sstefano_zampini PetscInt n = lr[i]/lrb[i]; 2345e3038f0Sstefano_zampini 2355e3038f0Sstefano_zampini /* local IS for local NEST */ 2365e3038f0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr); 2375e3038f0Sstefano_zampini sti += n; 2385e3038f0Sstefano_zampini 2395e3038f0Sstefano_zampini /* l2gmap */ 2405e3038f0Sstefano_zampini j = 0; 2415e3038f0Sstefano_zampini usedmat = nest[i][j]; 242*9e7b2b25Sstefano_zampini while (!usedmat && j < nc-1) usedmat = nest[i][++j]; 243*9e7b2b25Sstefano_zampini if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat"); 244*9e7b2b25Sstefano_zampini 245*9e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 246*9e7b2b25Sstefano_zampini Mat T; 247*9e7b2b25Sstefano_zampini ierr = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr); 248*9e7b2b25Sstefano_zampini usedmat = T; 249*9e7b2b25Sstefano_zampini } 2505e3038f0Sstefano_zampini matis = (Mat_IS*)(usedmat->data); 2515e3038f0Sstefano_zampini if (!matis->sf) { 2525e3038f0Sstefano_zampini ierr = MatISComputeSF_Private(usedmat);CHKERRQ(ierr); 2535e3038f0Sstefano_zampini } 2545e3038f0Sstefano_zampini ierr = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr); 255*9e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 256*9e7b2b25Sstefano_zampini ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 257*9e7b2b25Sstefano_zampini ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 258*9e7b2b25Sstefano_zampini } else { 2595e3038f0Sstefano_zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 2605e3038f0Sstefano_zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 261*9e7b2b25Sstefano_zampini } 2625e3038f0Sstefano_zampini ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr); 2635e3038f0Sstefano_zampini stl += lr[i]; 2645e3038f0Sstefano_zampini } 2655e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr); 2665e3038f0Sstefano_zampini 2675e3038f0Sstefano_zampini /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */ 2685e3038f0Sstefano_zampini for (i=0,stl=0;i<nc;i++) stl += lc[i]; 2695e3038f0Sstefano_zampini ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr); 2705e3038f0Sstefano_zampini for (i=0,sti=0,stl=0;i<nc;i++) { 2715e3038f0Sstefano_zampini Mat usedmat; 2725e3038f0Sstefano_zampini Mat_IS *matis; 2735e3038f0Sstefano_zampini const PetscInt *idxs; 2745e3038f0Sstefano_zampini PetscInt n = lc[i]/lcb[i]; 2755e3038f0Sstefano_zampini 2765e3038f0Sstefano_zampini /* local IS for local NEST */ 2775e3038f0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr); 2785e3038f0Sstefano_zampini sti += n; 2795e3038f0Sstefano_zampini 2805e3038f0Sstefano_zampini /* l2gmap */ 2815e3038f0Sstefano_zampini j = 0; 2825e3038f0Sstefano_zampini usedmat = nest[j][i]; 283*9e7b2b25Sstefano_zampini while (!usedmat && j < nr-1) usedmat = nest[++j][i]; 284*9e7b2b25Sstefano_zampini if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat"); 285*9e7b2b25Sstefano_zampini if (istrans[j*nc+i]) { 286*9e7b2b25Sstefano_zampini Mat T; 287*9e7b2b25Sstefano_zampini ierr = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr); 288*9e7b2b25Sstefano_zampini usedmat = T; 289*9e7b2b25Sstefano_zampini } 2905e3038f0Sstefano_zampini matis = (Mat_IS*)(usedmat->data); 2915e3038f0Sstefano_zampini if (!matis->sf) { 2925e3038f0Sstefano_zampini ierr = MatISComputeSF_Private(usedmat);CHKERRQ(ierr); 2935e3038f0Sstefano_zampini } 2945e3038f0Sstefano_zampini ierr = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr); 295*9e7b2b25Sstefano_zampini if (istrans[j*nc+i]) { 296*9e7b2b25Sstefano_zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 297*9e7b2b25Sstefano_zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 298*9e7b2b25Sstefano_zampini } else { 2995e3038f0Sstefano_zampini ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 3005e3038f0Sstefano_zampini ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 301*9e7b2b25Sstefano_zampini } 3025e3038f0Sstefano_zampini ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr); 3035e3038f0Sstefano_zampini stl += lc[i]; 3045e3038f0Sstefano_zampini } 3055e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr); 3065e3038f0Sstefano_zampini 3075e3038f0Sstefano_zampini /* Create MATIS */ 3085e3038f0Sstefano_zampini ierr = MatCreate(comm,&B);CHKERRQ(ierr); 3095e3038f0Sstefano_zampini ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 3105e3038f0Sstefano_zampini ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr); 3115e3038f0Sstefano_zampini ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr); 3125e3038f0Sstefano_zampini ierr = MatSetType(B,MATIS);CHKERRQ(ierr); 3135e3038f0Sstefano_zampini ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr); 3145e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 3155e3038f0Sstefano_zampini ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 3165e3038f0Sstefano_zampini ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr); 317*9e7b2b25Sstefano_zampini for (i=0;i<nr*nc;i++) { 318*9e7b2b25Sstefano_zampini if (istrans[i]) { 319*9e7b2b25Sstefano_zampini ierr = MatDestroy(&snest[i]);CHKERRQ(ierr); 320*9e7b2b25Sstefano_zampini } 321*9e7b2b25Sstefano_zampini } 3225e3038f0Sstefano_zampini ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr); 3235e3038f0Sstefano_zampini ierr = MatDestroy(&lA);CHKERRQ(ierr); 3245e3038f0Sstefano_zampini ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3255e3038f0Sstefano_zampini ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3265e3038f0Sstefano_zampini if (reuse == MAT_INPLACE_MATRIX) { 3275e3038f0Sstefano_zampini ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 3285e3038f0Sstefano_zampini } else { 3295e3038f0Sstefano_zampini *newmat = B; 3305e3038f0Sstefano_zampini } 3315e3038f0Sstefano_zampini } else { 3325e3038f0Sstefano_zampini if (lreuse) { 3335e3038f0Sstefano_zampini ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 3345e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 3355e3038f0Sstefano_zampini for (j=0;j<nc;j++) { 3365e3038f0Sstefano_zampini if (snest[i*nc+j]) { 3375e3038f0Sstefano_zampini ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr); 338*9e7b2b25Sstefano_zampini if (istrans[i*nc+j]) { 339*9e7b2b25Sstefano_zampini ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr); 340*9e7b2b25Sstefano_zampini } 3415e3038f0Sstefano_zampini } 3425e3038f0Sstefano_zampini } 3435e3038f0Sstefano_zampini } 3445e3038f0Sstefano_zampini } else { 3455e3038f0Sstefano_zampini for (i=0,sti=0;i<nr;i++) { 3465e3038f0Sstefano_zampini PetscInt n = lr[i]/lrb[i]; 3475e3038f0Sstefano_zampini 3485e3038f0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr); 3495e3038f0Sstefano_zampini sti += n; 3505e3038f0Sstefano_zampini } 3515e3038f0Sstefano_zampini for (i=0,sti=0;i<nc;i++) { 3525e3038f0Sstefano_zampini PetscInt n = lc[i]/lcb[i]; 3535e3038f0Sstefano_zampini 3545e3038f0Sstefano_zampini ierr = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr); 3555e3038f0Sstefano_zampini sti += n; 3565e3038f0Sstefano_zampini } 3575e3038f0Sstefano_zampini ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr); 358*9e7b2b25Sstefano_zampini if (istrans[i]) { 359*9e7b2b25Sstefano_zampini ierr = MatDestroy(&snest[i]);CHKERRQ(ierr); 360*9e7b2b25Sstefano_zampini } 3615e3038f0Sstefano_zampini ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr); 3625e3038f0Sstefano_zampini ierr = MatDestroy(&lA);CHKERRQ(ierr); 3635e3038f0Sstefano_zampini } 3645e3038f0Sstefano_zampini ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3655e3038f0Sstefano_zampini ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3665e3038f0Sstefano_zampini } 3675e3038f0Sstefano_zampini 3685e3038f0Sstefano_zampini /* Free workspace */ 3695e3038f0Sstefano_zampini for (i=0;i<nr;i++) { 3705e3038f0Sstefano_zampini ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr); 3715e3038f0Sstefano_zampini } 3725e3038f0Sstefano_zampini for (i=0;i<nc;i++) { 3735e3038f0Sstefano_zampini ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr); 3745e3038f0Sstefano_zampini } 3755e3038f0Sstefano_zampini ierr = PetscFree4(lr,lc,lrb,lcb);CHKERRQ(ierr); 376*9e7b2b25Sstefano_zampini ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr); 3775e3038f0Sstefano_zampini 3785e3038f0Sstefano_zampini /* Create local matrix in MATNEST format */ 3795e3038f0Sstefano_zampini convert = PETSC_FALSE; 3805e3038f0Sstefano_zampini ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr); 3815e3038f0Sstefano_zampini if (convert) { 3825e3038f0Sstefano_zampini Mat M; 3835e3038f0Sstefano_zampini 3845e3038f0Sstefano_zampini ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 3855e3038f0Sstefano_zampini ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr); 3865e3038f0Sstefano_zampini ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr); 3875e3038f0Sstefano_zampini ierr = MatDestroy(&M);CHKERRQ(ierr); 3885e3038f0Sstefano_zampini } 3895e3038f0Sstefano_zampini PetscFunctionReturn(0); 3905e3038f0Sstefano_zampini } 3915e3038f0Sstefano_zampini 3925e3038f0Sstefano_zampini #undef __FUNCT__ 393d7f69cd0SStefano Zampini #define __FUNCT__ "MatTranspose_IS" 394d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B) 395d7f69cd0SStefano Zampini { 396d7f69cd0SStefano Zampini Mat C,lC,lA; 397d7f69cd0SStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 398d7f69cd0SStefano Zampini PetscBool notset = PETSC_FALSE,cong = PETSC_TRUE; 399d7f69cd0SStefano Zampini PetscErrorCode ierr; 400d7f69cd0SStefano Zampini 401d7f69cd0SStefano Zampini PetscFunctionBegin; 402d7f69cd0SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 403d7f69cd0SStefano Zampini PetscBool rcong,ccong; 404d7f69cd0SStefano Zampini 405d7f69cd0SStefano Zampini ierr = PetscLayoutCompare((*B)->cmap,A->rmap,&rcong);CHKERRQ(ierr); 406d7f69cd0SStefano Zampini ierr = PetscLayoutCompare((*B)->rmap,A->cmap,&ccong);CHKERRQ(ierr); 407fa520230SStefano Zampini cong = (PetscBool)(rcong || ccong); 408d7f69cd0SStefano Zampini } 409d7f69cd0SStefano Zampini if (reuse == MAT_INITIAL_MATRIX || *B == A || !cong) { 410d7f69cd0SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 411d7f69cd0SStefano Zampini } else { 412d7f69cd0SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)*B,MATIS,¬set);CHKERRQ(ierr); 413d7f69cd0SStefano Zampini C = *B; 414d7f69cd0SStefano Zampini } 415d7f69cd0SStefano Zampini 416d7f69cd0SStefano Zampini if (!notset) { 417d7f69cd0SStefano Zampini ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr); 418d7f69cd0SStefano Zampini ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr); 419d7f69cd0SStefano Zampini ierr = MatSetType(C,MATIS);CHKERRQ(ierr); 420d7f69cd0SStefano Zampini ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr); 421d7f69cd0SStefano Zampini ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr); 422d7f69cd0SStefano Zampini } 423d7f69cd0SStefano Zampini 424d7f69cd0SStefano Zampini /* perform local transposition */ 425d7f69cd0SStefano Zampini ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr); 426d7f69cd0SStefano Zampini ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr); 427d7f69cd0SStefano Zampini ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr); 428d7f69cd0SStefano Zampini ierr = MatDestroy(&lC);CHKERRQ(ierr); 429d7f69cd0SStefano Zampini 430d7f69cd0SStefano Zampini ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 431d7f69cd0SStefano Zampini ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 432d7f69cd0SStefano Zampini 433d7f69cd0SStefano Zampini if (reuse == MAT_INITIAL_MATRIX || *B != A) { 434d7f69cd0SStefano Zampini if (!cong) { 435d7f69cd0SStefano Zampini ierr = MatDestroy(B);CHKERRQ(ierr); 436d7f69cd0SStefano Zampini } 437d7f69cd0SStefano Zampini *B = C; 438d7f69cd0SStefano Zampini } else { 439d7f69cd0SStefano Zampini ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr); 440d7f69cd0SStefano Zampini } 441d7f69cd0SStefano Zampini PetscFunctionReturn(0); 442d7f69cd0SStefano Zampini } 443d7f69cd0SStefano Zampini 444d7f69cd0SStefano Zampini #undef __FUNCT__ 4453fd1c9e7SStefano Zampini #define __FUNCT__ "MatDiagonalSet_IS" 4463fd1c9e7SStefano Zampini PetscErrorCode MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode) 4473fd1c9e7SStefano Zampini { 4483fd1c9e7SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 4493fd1c9e7SStefano Zampini PetscErrorCode ierr; 4503fd1c9e7SStefano Zampini 4513fd1c9e7SStefano Zampini PetscFunctionBegin; 4523fd1c9e7SStefano Zampini if (!D) { /* this code branch is used by MatShift_IS */ 4533fd1c9e7SStefano Zampini ierr = VecSet(is->y,1.);CHKERRQ(ierr); 4543fd1c9e7SStefano Zampini } else { 4553fd1c9e7SStefano Zampini ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4563fd1c9e7SStefano Zampini ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4573fd1c9e7SStefano Zampini } 4583fd1c9e7SStefano Zampini ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr); 4593fd1c9e7SStefano Zampini ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr); 4603fd1c9e7SStefano Zampini PetscFunctionReturn(0); 4613fd1c9e7SStefano Zampini } 4623fd1c9e7SStefano Zampini 4633fd1c9e7SStefano Zampini #undef __FUNCT__ 4643fd1c9e7SStefano Zampini #define __FUNCT__ "MatShift_IS" 4653fd1c9e7SStefano Zampini PetscErrorCode MatShift_IS(Mat A,PetscScalar a) 4663fd1c9e7SStefano Zampini { 4673fd1c9e7SStefano Zampini PetscErrorCode ierr; 4683fd1c9e7SStefano Zampini 4693fd1c9e7SStefano Zampini PetscFunctionBegin; 4703fd1c9e7SStefano Zampini ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr); 4713fd1c9e7SStefano Zampini PetscFunctionReturn(0); 4723fd1c9e7SStefano Zampini } 4733fd1c9e7SStefano Zampini 4743fd1c9e7SStefano Zampini #undef __FUNCT__ 475f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesLocal_SubMat_IS" 476f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 477f26d0771SStefano Zampini { 478f26d0771SStefano Zampini PetscErrorCode ierr; 479f26d0771SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 480f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 481f26d0771SStefano Zampini 482f26d0771SStefano Zampini PetscFunctionBegin; 483f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 484f26d0771SStefano 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); 485f26d0771SStefano Zampini #endif 486f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr); 487f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr); 488f26d0771SStefano Zampini ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 489f26d0771SStefano Zampini PetscFunctionReturn(0); 490f26d0771SStefano Zampini } 491f26d0771SStefano Zampini 492f26d0771SStefano Zampini #undef __FUNCT__ 493f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesBlockedLocal_SubMat_IS" 494f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 495f26d0771SStefano Zampini { 496f26d0771SStefano Zampini PetscErrorCode ierr; 497f26d0771SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 498f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 499f26d0771SStefano Zampini 500f26d0771SStefano Zampini PetscFunctionBegin; 501f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 502f26d0771SStefano 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); 503f26d0771SStefano Zampini #endif 504f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr); 505f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr); 506f26d0771SStefano Zampini ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 507f26d0771SStefano Zampini PetscFunctionReturn(0); 508f26d0771SStefano Zampini } 509f26d0771SStefano Zampini 510f26d0771SStefano Zampini #undef __FUNCT__ 511a8116848SStefano Zampini #define __FUNCT__ "PetscLayoutMapLocal_Private" 512f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs) 513a8116848SStefano Zampini { 514a8116848SStefano Zampini PetscInt *owners = map->range; 515a8116848SStefano Zampini PetscInt n = map->n; 516a8116848SStefano Zampini PetscSF sf; 517a8116848SStefano Zampini PetscInt *lidxs,*work = NULL; 518a8116848SStefano Zampini PetscSFNode *ridxs; 519a8116848SStefano Zampini PetscMPIInt rank; 520a8116848SStefano Zampini PetscInt r, p = 0, len = 0; 521a8116848SStefano Zampini PetscErrorCode ierr; 522a8116848SStefano Zampini 523a8116848SStefano Zampini PetscFunctionBegin; 524fd3a879cSJed Brown if (on) *on = 0; /* squelch -Wmaybe-uninitialized */ 525a8116848SStefano Zampini /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */ 526a8116848SStefano Zampini ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr); 527a8116848SStefano Zampini ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr); 528a8116848SStefano Zampini for (r = 0; r < n; ++r) lidxs[r] = -1; 529a8116848SStefano Zampini ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr); 530a8116848SStefano Zampini for (r = 0; r < N; ++r) { 531a8116848SStefano Zampini const PetscInt idx = idxs[r]; 532a8116848SStefano 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); 533a8116848SStefano Zampini if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */ 534a8116848SStefano Zampini ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr); 535a8116848SStefano Zampini } 536a8116848SStefano Zampini ridxs[r].rank = p; 537a8116848SStefano Zampini ridxs[r].index = idxs[r] - owners[p]; 538a8116848SStefano Zampini } 539a8116848SStefano Zampini ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr); 540a8116848SStefano Zampini ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr); 541a8116848SStefano Zampini ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr); 542a8116848SStefano Zampini ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr); 543f0ae7da4SStefano Zampini if (ogidxs) { /* communicate global idxs */ 544a8116848SStefano Zampini PetscInt cum = 0,start,*work2; 545f0ae7da4SStefano Zampini 546f0ae7da4SStefano Zampini ierr = PetscMalloc1(n,&work);CHKERRQ(ierr); 547a8116848SStefano Zampini ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr); 548a8116848SStefano Zampini for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++; 549a8116848SStefano Zampini ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr); 550a8116848SStefano Zampini start -= cum; 551a8116848SStefano Zampini cum = 0; 552a8116848SStefano Zampini for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++; 553a8116848SStefano Zampini ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr); 554a8116848SStefano Zampini ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr); 555a8116848SStefano Zampini ierr = PetscFree(work2);CHKERRQ(ierr); 556a8116848SStefano Zampini } 557a8116848SStefano Zampini ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 558a8116848SStefano Zampini /* Compress and put in indices */ 559a8116848SStefano Zampini for (r = 0; r < n; ++r) 560a8116848SStefano Zampini if (lidxs[r] >= 0) { 561a8116848SStefano Zampini if (work) work[len] = work[r]; 562a8116848SStefano Zampini lidxs[len++] = r; 563a8116848SStefano Zampini } 564a8116848SStefano Zampini if (on) *on = len; 565a8116848SStefano Zampini if (oidxs) *oidxs = lidxs; 566a8116848SStefano Zampini if (ogidxs) *ogidxs = work; 567a8116848SStefano Zampini PetscFunctionReturn(0); 568a8116848SStefano Zampini } 569a8116848SStefano Zampini 570a8116848SStefano Zampini #undef __FUNCT__ 571a8116848SStefano Zampini #define __FUNCT__ "MatGetSubMatrix_IS" 572a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat) 573a8116848SStefano Zampini { 574a8116848SStefano Zampini Mat locmat,newlocmat; 575a8116848SStefano Zampini Mat_IS *newmatis; 576a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG) 577a8116848SStefano Zampini Vec rtest,ltest; 578a8116848SStefano Zampini const PetscScalar *array; 579a8116848SStefano Zampini #endif 580a8116848SStefano Zampini const PetscInt *idxs; 581a8116848SStefano Zampini PetscInt i,m,n; 582a8116848SStefano Zampini PetscErrorCode ierr; 583a8116848SStefano Zampini 584a8116848SStefano Zampini PetscFunctionBegin; 585a8116848SStefano Zampini if (scall == MAT_REUSE_MATRIX) { 586a8116848SStefano Zampini PetscBool ismatis; 587a8116848SStefano Zampini 588a8116848SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr); 589a8116848SStefano Zampini if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type"); 590a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 591a8116848SStefano Zampini if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS"); 592a8116848SStefano Zampini if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS"); 593a8116848SStefano Zampini } 594a8116848SStefano Zampini /* irow and icol may not have duplicate entries */ 595a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG) 596a8116848SStefano Zampini ierr = MatCreateVecs(mat,<est,&rtest);CHKERRQ(ierr); 597a8116848SStefano Zampini ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr); 598a8116848SStefano Zampini ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr); 599a8116848SStefano Zampini for (i=0;i<n;i++) { 600a8116848SStefano Zampini ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr); 601a8116848SStefano Zampini } 602a8116848SStefano Zampini ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr); 603a8116848SStefano Zampini ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr); 604a8116848SStefano Zampini ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr); 605a8116848SStefano Zampini ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr); 606a8116848SStefano Zampini ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr); 607fd479f66SMatthew 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])); 608a8116848SStefano Zampini ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr); 609a8116848SStefano Zampini ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr); 610a8116848SStefano Zampini ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr); 611a8116848SStefano Zampini ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr); 612a8116848SStefano Zampini for (i=0;i<n;i++) { 613a8116848SStefano Zampini ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr); 614a8116848SStefano Zampini } 615a8116848SStefano Zampini ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr); 616a8116848SStefano Zampini ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr); 617a8116848SStefano Zampini ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr); 618a8116848SStefano Zampini ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr); 619a8116848SStefano Zampini ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr); 620fd479f66SMatthew 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])); 621a8116848SStefano Zampini ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr); 622a8116848SStefano Zampini ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr); 623a8116848SStefano Zampini ierr = VecDestroy(&rtest);CHKERRQ(ierr); 624a8116848SStefano Zampini ierr = VecDestroy(<est);CHKERRQ(ierr); 625a8116848SStefano Zampini #endif 626a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 627a8116848SStefano Zampini Mat_IS *matis = (Mat_IS*)mat->data; 628a8116848SStefano Zampini ISLocalToGlobalMapping rl2g; 629a8116848SStefano Zampini IS is; 630a8116848SStefano Zampini PetscInt *lidxs,*lgidxs,*newgidxs; 6316dd40735SStefano Zampini PetscInt ll,newloc; 632a8116848SStefano Zampini MPI_Comm comm; 633a8116848SStefano Zampini 634a8116848SStefano Zampini ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 635a8116848SStefano Zampini ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr); 636a8116848SStefano Zampini ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr); 637a8116848SStefano Zampini ierr = MatCreate(comm,newmat);CHKERRQ(ierr); 638a8116848SStefano Zampini ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr); 639a8116848SStefano Zampini ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 640a8116848SStefano Zampini /* communicate irow to their owners in the layout */ 641a8116848SStefano Zampini ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr); 642f0ae7da4SStefano Zampini ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr); 643a8116848SStefano Zampini ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr); 644a8116848SStefano Zampini if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */ 645a8116848SStefano Zampini ierr = MatISComputeSF_Private(mat);CHKERRQ(ierr); 646a8116848SStefano Zampini } 647a8116848SStefano Zampini ierr = PetscMemzero(matis->sf_rootdata,matis->sf_nroots*sizeof(PetscInt));CHKERRQ(ierr); 648a8116848SStefano Zampini for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1; 649a8116848SStefano Zampini ierr = PetscFree(lidxs);CHKERRQ(ierr); 650a8116848SStefano Zampini ierr = PetscFree(lgidxs);CHKERRQ(ierr); 651a8116848SStefano Zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 652a8116848SStefano Zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 653a8116848SStefano Zampini for (i=0,newloc=0;i<matis->sf_nleaves;i++) if (matis->sf_leafdata[i]) newloc++; 654a8116848SStefano Zampini ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr); 655a8116848SStefano Zampini ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr); 656a8116848SStefano Zampini for (i=0,newloc=0;i<matis->sf_nleaves;i++) 657a8116848SStefano Zampini if (matis->sf_leafdata[i]) { 658a8116848SStefano Zampini lidxs[newloc] = i; 659a8116848SStefano Zampini newgidxs[newloc++] = matis->sf_leafdata[i]-1; 660a8116848SStefano Zampini } 661a8116848SStefano Zampini ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 662a8116848SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 663a8116848SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 664a8116848SStefano Zampini /* local is to extract local submatrix */ 665a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 666a8116848SStefano Zampini ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr); 667a8116848SStefano Zampini if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */ 668a8116848SStefano Zampini PetscBool cong; 669a8116848SStefano Zampini ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr); 670a8116848SStefano Zampini if (cong) mat->congruentlayouts = 1; 671a8116848SStefano Zampini else mat->congruentlayouts = 0; 672a8116848SStefano Zampini } 673a8116848SStefano Zampini if (mat->congruentlayouts && irow == icol) { 674a8116848SStefano Zampini ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr); 675a8116848SStefano Zampini ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr); 676a8116848SStefano Zampini newmatis->getsub_cis = newmatis->getsub_ris; 677a8116848SStefano Zampini } else { 678a8116848SStefano Zampini ISLocalToGlobalMapping cl2g; 679a8116848SStefano Zampini 680a8116848SStefano Zampini /* communicate icol to their owners in the layout */ 681a8116848SStefano Zampini ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr); 682f0ae7da4SStefano Zampini ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr); 683a8116848SStefano Zampini ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr); 684a8116848SStefano Zampini ierr = PetscMemzero(matis->csf_rootdata,matis->csf_nroots*sizeof(PetscInt));CHKERRQ(ierr); 685a8116848SStefano Zampini for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1; 686a8116848SStefano Zampini ierr = PetscFree(lidxs);CHKERRQ(ierr); 687a8116848SStefano Zampini ierr = PetscFree(lgidxs);CHKERRQ(ierr); 688a8116848SStefano Zampini ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr); 689a8116848SStefano Zampini ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr); 690a8116848SStefano Zampini for (i=0,newloc=0;i<matis->csf_nleaves;i++) if (matis->csf_leafdata[i]) newloc++; 691a8116848SStefano Zampini ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr); 692a8116848SStefano Zampini ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr); 693a8116848SStefano Zampini for (i=0,newloc=0;i<matis->csf_nleaves;i++) 694a8116848SStefano Zampini if (matis->csf_leafdata[i]) { 695a8116848SStefano Zampini lidxs[newloc] = i; 696a8116848SStefano Zampini newgidxs[newloc++] = matis->csf_leafdata[i]-1; 697a8116848SStefano Zampini } 698a8116848SStefano Zampini ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 699a8116848SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 700a8116848SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 701a8116848SStefano Zampini /* local is to extract local submatrix */ 702a8116848SStefano Zampini ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr); 703a8116848SStefano Zampini ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr); 704a8116848SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 705a8116848SStefano Zampini } 706a8116848SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 707a8116848SStefano Zampini } else { 708a8116848SStefano Zampini ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr); 709a8116848SStefano Zampini } 710a8116848SStefano Zampini ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr); 711a8116848SStefano Zampini newmatis = (Mat_IS*)(*newmat)->data; 712a8116848SStefano Zampini ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr); 713a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 714a8116848SStefano Zampini ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr); 715a8116848SStefano Zampini ierr = MatDestroy(&newlocmat);CHKERRQ(ierr); 716a8116848SStefano Zampini } 717a8116848SStefano Zampini ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 718a8116848SStefano Zampini ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 719a8116848SStefano Zampini PetscFunctionReturn(0); 720a8116848SStefano Zampini } 721a8116848SStefano Zampini 722a8116848SStefano Zampini #undef __FUNCT__ 7232b404112SStefano Zampini #define __FUNCT__ "MatCopy_IS" 724a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str) 7252b404112SStefano Zampini { 7262b404112SStefano Zampini Mat_IS *a = (Mat_IS*)A->data,*b; 7272b404112SStefano Zampini PetscBool ismatis; 7282b404112SStefano Zampini PetscErrorCode ierr; 7292b404112SStefano Zampini 7302b404112SStefano Zampini PetscFunctionBegin; 7312b404112SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr); 7322b404112SStefano Zampini if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented"); 7332b404112SStefano Zampini b = (Mat_IS*)B->data; 7342b404112SStefano Zampini ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr); 7352b404112SStefano Zampini PetscFunctionReturn(0); 7362b404112SStefano Zampini } 7372b404112SStefano Zampini 7382b404112SStefano Zampini #undef __FUNCT__ 7396bd84002SStefano Zampini #define __FUNCT__ "MatMissingDiagonal_IS" 740a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool *missing,PetscInt *d) 7416bd84002SStefano Zampini { 742527b2640SStefano Zampini Vec v; 743527b2640SStefano Zampini const PetscScalar *array; 744527b2640SStefano Zampini PetscInt i,n; 7456bd84002SStefano Zampini PetscErrorCode ierr; 7466bd84002SStefano Zampini 7476bd84002SStefano Zampini PetscFunctionBegin; 748527b2640SStefano Zampini *missing = PETSC_FALSE; 749527b2640SStefano Zampini ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr); 750527b2640SStefano Zampini ierr = MatGetDiagonal(A,v);CHKERRQ(ierr); 751527b2640SStefano Zampini ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 752527b2640SStefano Zampini ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr); 753527b2640SStefano Zampini for (i=0;i<n;i++) if (array[i] == 0.) break; 754527b2640SStefano Zampini ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr); 755527b2640SStefano Zampini ierr = VecDestroy(&v);CHKERRQ(ierr); 756527b2640SStefano Zampini if (i != n) *missing = PETSC_TRUE; 757527b2640SStefano Zampini if (d) { 758527b2640SStefano Zampini *d = -1; 759527b2640SStefano Zampini if (*missing) { 760527b2640SStefano Zampini PetscInt rstart; 761527b2640SStefano Zampini ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr); 762527b2640SStefano Zampini *d = i+rstart; 763527b2640SStefano Zampini } 764527b2640SStefano Zampini } 7656bd84002SStefano Zampini PetscFunctionReturn(0); 7666bd84002SStefano Zampini } 7676bd84002SStefano Zampini 7686bd84002SStefano Zampini #undef __FUNCT__ 76928f4e0baSStefano Zampini #define __FUNCT__ "MatISComputeSF_Private" 770a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat B) 77128f4e0baSStefano Zampini { 77228f4e0baSStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 77328f4e0baSStefano Zampini const PetscInt *gidxs; 77428f4e0baSStefano Zampini PetscErrorCode ierr; 77528f4e0baSStefano Zampini 77628f4e0baSStefano Zampini PetscFunctionBegin; 77728f4e0baSStefano Zampini ierr = MatGetSize(matis->A,&matis->sf_nleaves,NULL);CHKERRQ(ierr); 77828f4e0baSStefano Zampini ierr = MatGetLocalSize(B,&matis->sf_nroots,NULL);CHKERRQ(ierr); 77928f4e0baSStefano Zampini ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr); 7803bbff08aSStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr); 78128f4e0baSStefano Zampini ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,matis->sf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr); 7823bbff08aSStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr); 78328f4e0baSStefano Zampini ierr = PetscMalloc2(matis->sf_nroots,&matis->sf_rootdata,matis->sf_nleaves,&matis->sf_leafdata);CHKERRQ(ierr); 784a8116848SStefano Zampini if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */ 785a8116848SStefano Zampini ierr = MatGetSize(matis->A,NULL,&matis->csf_nleaves);CHKERRQ(ierr); 786a8116848SStefano Zampini ierr = MatGetLocalSize(B,NULL,&matis->csf_nroots);CHKERRQ(ierr); 787a8116848SStefano Zampini ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr); 788a8116848SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr); 789a8116848SStefano Zampini ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,matis->csf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr); 790a8116848SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr); 791a8116848SStefano Zampini ierr = PetscMalloc2(matis->csf_nroots,&matis->csf_rootdata,matis->csf_nleaves,&matis->csf_leafdata);CHKERRQ(ierr); 792a8116848SStefano Zampini } else { 793a8116848SStefano Zampini matis->csf = matis->sf; 794a8116848SStefano Zampini matis->csf_nleaves = matis->sf_nleaves; 795a8116848SStefano Zampini matis->csf_nroots = matis->sf_nroots; 796a8116848SStefano Zampini matis->csf_leafdata = matis->sf_leafdata; 797a8116848SStefano Zampini matis->csf_rootdata = matis->sf_rootdata; 798a8116848SStefano Zampini } 79928f4e0baSStefano Zampini PetscFunctionReturn(0); 80028f4e0baSStefano Zampini } 8012e1947a5SStefano Zampini 8022e1947a5SStefano Zampini #undef __FUNCT__ 8032e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation" 804eb82efa4SStefano Zampini /*@ 805a88811baSStefano Zampini MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix. 806a88811baSStefano Zampini 807a88811baSStefano Zampini Collective on MPI_Comm 808a88811baSStefano Zampini 809a88811baSStefano Zampini Input Parameters: 810a88811baSStefano Zampini + B - the matrix 811a88811baSStefano Zampini . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 812a88811baSStefano Zampini (same value is used for all local rows) 813a88811baSStefano Zampini . d_nnz - array containing the number of nonzeros in the various rows of the 814a88811baSStefano Zampini DIAGONAL portion of the local submatrix (possibly different for each row) 815a88811baSStefano Zampini or NULL, if d_nz is used to specify the nonzero structure. 816a88811baSStefano Zampini The size of this array is equal to the number of local rows, i.e 'm'. 817a88811baSStefano Zampini For matrices that will be factored, you must leave room for (and set) 818a88811baSStefano Zampini the diagonal entry even if it is zero. 819a88811baSStefano Zampini . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 820a88811baSStefano Zampini submatrix (same value is used for all local rows). 821a88811baSStefano Zampini - o_nnz - array containing the number of nonzeros in the various rows of the 822a88811baSStefano Zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 823a88811baSStefano Zampini each row) or NULL, if o_nz is used to specify the nonzero 824a88811baSStefano Zampini structure. The size of this array is equal to the number 825a88811baSStefano Zampini of local rows, i.e 'm'. 826a88811baSStefano Zampini 827a88811baSStefano Zampini If the *_nnz parameter is given then the *_nz parameter is ignored 828a88811baSStefano Zampini 829a88811baSStefano Zampini Level: intermediate 830a88811baSStefano Zampini 831a88811baSStefano Zampini Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition 832a88811baSStefano Zampini from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local 833a88811baSStefano Zampini matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 834a88811baSStefano Zampini 835a88811baSStefano Zampini .keywords: matrix 836a88811baSStefano Zampini 8373c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS 838a88811baSStefano Zampini @*/ 8392e1947a5SStefano Zampini PetscErrorCode MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 8402e1947a5SStefano Zampini { 8412e1947a5SStefano Zampini PetscErrorCode ierr; 8422e1947a5SStefano Zampini 8432e1947a5SStefano Zampini PetscFunctionBegin; 8442e1947a5SStefano Zampini PetscValidHeaderSpecific(B,MAT_CLASSID,1); 8452e1947a5SStefano Zampini PetscValidType(B,1); 8462e1947a5SStefano Zampini ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr); 8472e1947a5SStefano Zampini PetscFunctionReturn(0); 8482e1947a5SStefano Zampini } 8492e1947a5SStefano Zampini 8502e1947a5SStefano Zampini #undef __FUNCT__ 8512e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS" 8527230de76SStefano Zampini static PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 8532e1947a5SStefano Zampini { 8542e1947a5SStefano Zampini Mat_IS *matis = (Mat_IS*)(B->data); 85528f4e0baSStefano Zampini PetscInt bs,i,nlocalcols; 8562e1947a5SStefano Zampini PetscErrorCode ierr; 8572e1947a5SStefano Zampini 8582e1947a5SStefano Zampini PetscFunctionBegin; 8596c4ed002SBarry Smith if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping"); 86028f4e0baSStefano Zampini if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */ 86128f4e0baSStefano Zampini ierr = MatISComputeSF_Private(B);CHKERRQ(ierr); 86228f4e0baSStefano Zampini } 8632e1947a5SStefano Zampini if (!d_nnz) { 86428f4e0baSStefano Zampini for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nz; 8652e1947a5SStefano Zampini } else { 86628f4e0baSStefano Zampini for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nnz[i]; 8672e1947a5SStefano Zampini } 8682e1947a5SStefano Zampini if (!o_nnz) { 86928f4e0baSStefano Zampini for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nz; 8702e1947a5SStefano Zampini } else { 87128f4e0baSStefano Zampini for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nnz[i]; 8722e1947a5SStefano Zampini } 87328f4e0baSStefano Zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 87428f4e0baSStefano Zampini ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr); 87528f4e0baSStefano Zampini ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr); 87628f4e0baSStefano Zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 87728f4e0baSStefano Zampini for (i=0;i<matis->sf_nleaves;i++) { 87828f4e0baSStefano Zampini matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols); 8792e1947a5SStefano Zampini } 88028f4e0baSStefano Zampini ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr); 88128f4e0baSStefano Zampini for (i=0;i<matis->sf_nleaves/bs;i++) { 88228f4e0baSStefano Zampini matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs; 8832e1947a5SStefano Zampini } 88428f4e0baSStefano Zampini ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 88528f4e0baSStefano Zampini for (i=0;i<matis->sf_nleaves/bs;i++) { 88628f4e0baSStefano Zampini matis->sf_leafdata[i] = matis->sf_leafdata[i]-i; 8872e1947a5SStefano Zampini } 88828f4e0baSStefano Zampini ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 8892e1947a5SStefano Zampini PetscFunctionReturn(0); 8902e1947a5SStefano Zampini } 891b4319ba4SBarry Smith 892b4319ba4SBarry Smith #undef __FUNCT__ 8933927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private" 8943927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce) 8953927de2eSStefano Zampini { 8963927de2eSStefano Zampini Mat_IS *matis = (Mat_IS*)(A->data); 8973927de2eSStefano Zampini PetscInt *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership; 898ecf5a873SStefano Zampini const PetscInt *global_indices_r,*global_indices_c; 8993927de2eSStefano Zampini PetscInt i,j,bs,rows,cols; 9003927de2eSStefano Zampini PetscInt lrows,lcols; 9013927de2eSStefano Zampini PetscInt local_rows,local_cols; 9023927de2eSStefano Zampini PetscMPIInt nsubdomains; 9033927de2eSStefano Zampini PetscBool isdense,issbaij; 9043927de2eSStefano Zampini PetscErrorCode ierr; 9053927de2eSStefano Zampini 9063927de2eSStefano Zampini PetscFunctionBegin; 9073927de2eSStefano Zampini ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr); 9083927de2eSStefano Zampini ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr); 9093927de2eSStefano Zampini ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 9103927de2eSStefano Zampini ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 9113927de2eSStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr); 9123927de2eSStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr); 913ecf5a873SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr); 914ecf5a873SStefano Zampini if (A->rmap->mapping != A->cmap->mapping) { 9157230de76SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr); 916ecf5a873SStefano Zampini } else { 917ecf5a873SStefano Zampini global_indices_c = global_indices_r; 918ecf5a873SStefano Zampini } 919ecf5a873SStefano Zampini 9203927de2eSStefano Zampini if (issbaij) { 9213927de2eSStefano Zampini ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr); 9223927de2eSStefano Zampini } 9233927de2eSStefano Zampini /* 924ecf5a873SStefano Zampini An SF reduce is needed to sum up properly on shared rows. 9253927de2eSStefano Zampini Note that generally preallocation is not exact, since it overestimates nonzeros 9263927de2eSStefano Zampini */ 9273927de2eSStefano Zampini if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */ 9283927de2eSStefano Zampini ierr = MatISComputeSF_Private(A);CHKERRQ(ierr); 9293927de2eSStefano Zampini } 9303927de2eSStefano Zampini ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr); 9313927de2eSStefano Zampini ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr); 9323927de2eSStefano Zampini /* All processes need to compute entire row ownership */ 9333927de2eSStefano Zampini ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr); 9343927de2eSStefano Zampini ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr); 9353927de2eSStefano Zampini for (i=0;i<nsubdomains;i++) { 9363927de2eSStefano Zampini for (j=mat_ranges[i];j<mat_ranges[i+1];j++) { 9373927de2eSStefano Zampini row_ownership[j] = i; 9383927de2eSStefano Zampini } 9393927de2eSStefano Zampini } 9407230de76SStefano Zampini ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr); 9413927de2eSStefano Zampini 9423927de2eSStefano Zampini /* 9433927de2eSStefano Zampini my_dnz and my_onz contains exact contribution to preallocation from each local mat 9443927de2eSStefano Zampini then, they will be summed up properly. This way, preallocation is always sufficient 9453927de2eSStefano Zampini */ 9463927de2eSStefano Zampini ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr); 9473927de2eSStefano Zampini /* preallocation as a MATAIJ */ 9483927de2eSStefano Zampini if (isdense) { /* special case for dense local matrices */ 9493927de2eSStefano Zampini for (i=0;i<local_rows;i++) { 950ecf5a873SStefano Zampini PetscInt index_row = global_indices_r[i]; 9513927de2eSStefano Zampini for (j=i;j<local_rows;j++) { 9523927de2eSStefano Zampini PetscInt owner = row_ownership[index_row]; 953ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[j]; 9543927de2eSStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 9553927de2eSStefano Zampini my_dnz[i] += 1; 9563927de2eSStefano Zampini } else { /* offdiag block */ 9573927de2eSStefano Zampini my_onz[i] += 1; 9583927de2eSStefano Zampini } 9593927de2eSStefano Zampini /* same as before, interchanging rows and cols */ 9603927de2eSStefano Zampini if (i != j) { 9613927de2eSStefano Zampini owner = row_ownership[index_col]; 9623927de2eSStefano Zampini if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 9633927de2eSStefano Zampini my_dnz[j] += 1; 9643927de2eSStefano Zampini } else { 9653927de2eSStefano Zampini my_onz[j] += 1; 9663927de2eSStefano Zampini } 9673927de2eSStefano Zampini } 9683927de2eSStefano Zampini } 9693927de2eSStefano Zampini } 970bb1015c3SStefano Zampini } else if (matis->A->ops->getrowij) { 971bb1015c3SStefano Zampini const PetscInt *ii,*jj,*jptr; 972bb1015c3SStefano Zampini PetscBool done; 973bb1015c3SStefano Zampini ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr); 974bb1015c3SStefano Zampini if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__); 975bb1015c3SStefano Zampini jptr = jj; 976bb1015c3SStefano Zampini for (i=0;i<local_rows;i++) { 977bb1015c3SStefano Zampini PetscInt index_row = global_indices_r[i]; 978bb1015c3SStefano Zampini for (j=0;j<ii[i+1]-ii[i];j++,jptr++) { 979bb1015c3SStefano Zampini PetscInt owner = row_ownership[index_row]; 980bb1015c3SStefano Zampini PetscInt index_col = global_indices_c[*jptr]; 981bb1015c3SStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 982bb1015c3SStefano Zampini my_dnz[i] += 1; 983bb1015c3SStefano Zampini } else { /* offdiag block */ 984bb1015c3SStefano Zampini my_onz[i] += 1; 985bb1015c3SStefano Zampini } 986bb1015c3SStefano Zampini /* same as before, interchanging rows and cols */ 987bb1015c3SStefano Zampini if (issbaij && index_col != index_row) { 988bb1015c3SStefano Zampini owner = row_ownership[index_col]; 989bb1015c3SStefano Zampini if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 990bb1015c3SStefano Zampini my_dnz[*jptr] += 1; 991bb1015c3SStefano Zampini } else { 992bb1015c3SStefano Zampini my_onz[*jptr] += 1; 993bb1015c3SStefano Zampini } 994bb1015c3SStefano Zampini } 995bb1015c3SStefano Zampini } 996bb1015c3SStefano Zampini } 997bb1015c3SStefano Zampini ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr); 998bb1015c3SStefano Zampini if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__); 999bb1015c3SStefano Zampini } else { /* loop over rows and use MatGetRow */ 10003927de2eSStefano Zampini for (i=0;i<local_rows;i++) { 10013927de2eSStefano Zampini const PetscInt *cols; 1002ecf5a873SStefano Zampini PetscInt ncols,index_row = global_indices_r[i]; 10033927de2eSStefano Zampini ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 10043927de2eSStefano Zampini for (j=0;j<ncols;j++) { 10053927de2eSStefano Zampini PetscInt owner = row_ownership[index_row]; 1006ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[cols[j]]; 10073927de2eSStefano Zampini if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 10083927de2eSStefano Zampini my_dnz[i] += 1; 10093927de2eSStefano Zampini } else { /* offdiag block */ 10103927de2eSStefano Zampini my_onz[i] += 1; 10113927de2eSStefano Zampini } 10123927de2eSStefano Zampini /* same as before, interchanging rows and cols */ 1013d9a9e74cSStefano Zampini if (issbaij && index_col != index_row) { 10143927de2eSStefano Zampini owner = row_ownership[index_col]; 10153927de2eSStefano Zampini if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 1016d9a9e74cSStefano Zampini my_dnz[cols[j]] += 1; 10173927de2eSStefano Zampini } else { 1018d9a9e74cSStefano Zampini my_onz[cols[j]] += 1; 10193927de2eSStefano Zampini } 10203927de2eSStefano Zampini } 10213927de2eSStefano Zampini } 10223927de2eSStefano Zampini ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 10233927de2eSStefano Zampini } 10243927de2eSStefano Zampini } 1025ecf5a873SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr); 1026ecf5a873SStefano Zampini if (global_indices_c != global_indices_r) { 10277230de76SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr); 1028ecf5a873SStefano Zampini } 10293927de2eSStefano Zampini ierr = PetscFree(row_ownership);CHKERRQ(ierr); 1030ecf5a873SStefano Zampini 1031ecf5a873SStefano Zampini /* Reduce my_dnz and my_onz */ 10323927de2eSStefano Zampini if (maxreduce) { 10333927de2eSStefano Zampini ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 10343927de2eSStefano Zampini ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 1035bb1015c3SStefano Zampini ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 10363927de2eSStefano Zampini ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 10373927de2eSStefano Zampini } else { 10383927de2eSStefano Zampini ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 10393927de2eSStefano Zampini ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 1040bb1015c3SStefano Zampini ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 10413927de2eSStefano Zampini ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 10423927de2eSStefano Zampini } 10433927de2eSStefano Zampini ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr); 10443927de2eSStefano Zampini 10453927de2eSStefano Zampini /* Resize preallocation if overestimated */ 10463927de2eSStefano Zampini for (i=0;i<lrows;i++) { 10473927de2eSStefano Zampini dnz[i] = PetscMin(dnz[i],lcols); 10483927de2eSStefano Zampini onz[i] = PetscMin(onz[i],cols-lcols); 10493927de2eSStefano Zampini } 10501670daf9Sstefano_zampini 10511670daf9Sstefano_zampini /* Set preallocation */ 10523927de2eSStefano Zampini ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr); 10533927de2eSStefano Zampini for (i=0;i<lrows/bs;i++) { 10543927de2eSStefano Zampini dnz[i] = dnz[i*bs]/bs; 10553927de2eSStefano Zampini onz[i] = onz[i*bs]/bs; 10563927de2eSStefano Zampini } 10573927de2eSStefano Zampini ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 10583927de2eSStefano Zampini ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 10593927de2eSStefano Zampini ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 10603927de2eSStefano Zampini if (issbaij) { 10613927de2eSStefano Zampini ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr); 10623927de2eSStefano Zampini } 10633927de2eSStefano Zampini PetscFunctionReturn(0); 10643927de2eSStefano Zampini } 10653927de2eSStefano Zampini 10663927de2eSStefano Zampini #undef __FUNCT__ 1067b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS" 10687230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M) 1069b7ce53b6SStefano Zampini { 1070b7ce53b6SStefano Zampini Mat_IS *matis = (Mat_IS*)(mat->data); 1071d9a9e74cSStefano Zampini Mat local_mat; 1072b7ce53b6SStefano Zampini /* info on mat */ 10733cfa4ea4SStefano Zampini PetscInt bs,rows,cols,lrows,lcols; 1074b7ce53b6SStefano Zampini PetscInt local_rows,local_cols; 1075686e3a49SStefano Zampini PetscBool isdense,issbaij,isseqaij; 10767c03b4e8SStefano Zampini PetscMPIInt nsubdomains; 1077b7ce53b6SStefano Zampini /* values insertion */ 1078b7ce53b6SStefano Zampini PetscScalar *array; 1079b7ce53b6SStefano Zampini /* work */ 1080b7ce53b6SStefano Zampini PetscErrorCode ierr; 1081b7ce53b6SStefano Zampini 1082b7ce53b6SStefano Zampini PetscFunctionBegin; 1083b7ce53b6SStefano Zampini /* get info from mat */ 10847c03b4e8SStefano Zampini ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr); 10857c03b4e8SStefano Zampini if (nsubdomains == 1) { 10861670daf9Sstefano_zampini Mat B; 10871670daf9Sstefano_zampini IS rows,cols; 10881670daf9Sstefano_zampini const PetscInt *ridxs,*cidxs; 10891670daf9Sstefano_zampini 10901670daf9Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr); 10911670daf9Sstefano_zampini ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr); 10921670daf9Sstefano_zampini ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr); 10931670daf9Sstefano_zampini ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr); 10941670daf9Sstefano_zampini ierr = MatConvert(matis->A,MATAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr); 10951670daf9Sstefano_zampini ierr = MatGetSubMatrix(B,rows,cols,reuse,M);CHKERRQ(ierr); 10961670daf9Sstefano_zampini ierr = MatDestroy(&B);CHKERRQ(ierr); 10971670daf9Sstefano_zampini ierr = ISDestroy(&cols);CHKERRQ(ierr); 10981670daf9Sstefano_zampini ierr = ISDestroy(&rows);CHKERRQ(ierr); 10991670daf9Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr); 11001670daf9Sstefano_zampini ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr); 11017c03b4e8SStefano Zampini PetscFunctionReturn(0); 11027c03b4e8SStefano Zampini } 1103b7ce53b6SStefano Zampini ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr); 1104b7ce53b6SStefano Zampini ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); 11053cfa4ea4SStefano Zampini ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr); 1106b7ce53b6SStefano Zampini ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 1107b7ce53b6SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr); 1108686e3a49SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 1109b7ce53b6SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr); 1110b7ce53b6SStefano Zampini 1111b7ce53b6SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 1112b7ce53b6SStefano Zampini MatType new_mat_type; 11133927de2eSStefano Zampini PetscBool issbaij_red; 1114b7ce53b6SStefano Zampini 1115b7ce53b6SStefano Zampini /* determining new matrix type */ 1116b2566f29SBarry Smith ierr = MPIU_Allreduce(&issbaij,&issbaij_red,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1117b7ce53b6SStefano Zampini if (issbaij_red) { 1118b7ce53b6SStefano Zampini new_mat_type = MATSBAIJ; 1119b7ce53b6SStefano Zampini } else { 1120b7ce53b6SStefano Zampini if (bs>1) { 1121b7ce53b6SStefano Zampini new_mat_type = MATBAIJ; 1122b7ce53b6SStefano Zampini } else { 1123b7ce53b6SStefano Zampini new_mat_type = MATAIJ; 1124b7ce53b6SStefano Zampini } 1125b7ce53b6SStefano Zampini } 1126b7ce53b6SStefano Zampini 11273927de2eSStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr); 11283cfa4ea4SStefano Zampini ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr); 11293927de2eSStefano Zampini ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr); 11303927de2eSStefano Zampini ierr = MatSetType(*M,new_mat_type);CHKERRQ(ierr); 11313927de2eSStefano Zampini ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr); 1132b7ce53b6SStefano Zampini } else { 11333cfa4ea4SStefano Zampini PetscInt mbs,mrows,mcols,mlrows,mlcols; 1134b7ce53b6SStefano Zampini /* some checks */ 1135b7ce53b6SStefano Zampini ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr); 1136b7ce53b6SStefano Zampini ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr); 11373cfa4ea4SStefano Zampini ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr); 11386c4ed002SBarry Smith if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows); 11396c4ed002SBarry Smith if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols); 11406c4ed002SBarry Smith if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows); 11416c4ed002SBarry Smith if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols); 11426c4ed002SBarry Smith if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs); 1143b7ce53b6SStefano Zampini ierr = MatZeroEntries(*M);CHKERRQ(ierr); 1144b7ce53b6SStefano Zampini } 1145d9a9e74cSStefano Zampini 1146d9a9e74cSStefano Zampini if (issbaij) { 1147d9a9e74cSStefano Zampini ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr); 1148d9a9e74cSStefano Zampini } else { 1149d9a9e74cSStefano Zampini ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 1150d9a9e74cSStefano Zampini local_mat = matis->A; 1151d9a9e74cSStefano Zampini } 1152686e3a49SStefano Zampini 1153b7ce53b6SStefano Zampini /* Set values */ 1154ecf5a873SStefano Zampini ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr); 1155b7ce53b6SStefano Zampini if (isdense) { /* special case for dense local matrices */ 1156ecf5a873SStefano Zampini PetscInt i,*dummy_rows,*dummy_cols; 1157ecf5a873SStefano Zampini 1158ecf5a873SStefano Zampini if (local_rows != local_cols) { 1159ecf5a873SStefano Zampini ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr); 1160ecf5a873SStefano Zampini for (i=0;i<local_rows;i++) dummy_rows[i] = i; 1161ecf5a873SStefano Zampini for (i=0;i<local_cols;i++) dummy_cols[i] = i; 1162ecf5a873SStefano Zampini } else { 1163ecf5a873SStefano Zampini ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr); 1164ecf5a873SStefano Zampini for (i=0;i<local_rows;i++) dummy_rows[i] = i; 1165ecf5a873SStefano Zampini dummy_cols = dummy_rows; 1166ecf5a873SStefano Zampini } 1167b7ce53b6SStefano Zampini ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 1168d9a9e74cSStefano Zampini ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr); 1169ecf5a873SStefano Zampini ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr); 1170d9a9e74cSStefano Zampini ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr); 1171ecf5a873SStefano Zampini if (dummy_rows != dummy_cols) { 1172ecf5a873SStefano Zampini ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr); 1173ecf5a873SStefano Zampini } else { 1174ecf5a873SStefano Zampini ierr = PetscFree(dummy_rows);CHKERRQ(ierr); 1175ecf5a873SStefano Zampini } 1176686e3a49SStefano Zampini } else if (isseqaij) { 1177ecf5a873SStefano Zampini PetscInt i,nvtxs,*xadj,*adjncy; 1178686e3a49SStefano Zampini PetscBool done; 1179686e3a49SStefano Zampini 1180d9a9e74cSStefano Zampini ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 1181bb1015c3SStefano Zampini if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__); 1182d9a9e74cSStefano Zampini ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr); 1183686e3a49SStefano Zampini for (i=0;i<nvtxs;i++) { 1184ecf5a873SStefano Zampini ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr); 1185686e3a49SStefano Zampini } 1186d9a9e74cSStefano Zampini ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 1187bb1015c3SStefano Zampini if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__); 1188d9a9e74cSStefano Zampini ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr); 1189686e3a49SStefano Zampini } else { /* very basic values insertion for all other matrix types */ 1190ecf5a873SStefano Zampini PetscInt i; 1191c0962df8SStefano Zampini 1192686e3a49SStefano Zampini for (i=0;i<local_rows;i++) { 1193686e3a49SStefano Zampini PetscInt j; 1194ecf5a873SStefano Zampini const PetscInt *local_indices_cols; 1195686e3a49SStefano Zampini 1196ecf5a873SStefano Zampini ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr); 1197ecf5a873SStefano Zampini ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr); 1198ecf5a873SStefano Zampini ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr); 1199686e3a49SStefano Zampini } 1200b7ce53b6SStefano Zampini } 1201b7ce53b6SStefano Zampini ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1202d9a9e74cSStefano Zampini ierr = MatDestroy(&local_mat);CHKERRQ(ierr); 1203b7ce53b6SStefano Zampini ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1204b7ce53b6SStefano Zampini if (isdense) { 1205b7ce53b6SStefano Zampini ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr); 1206b7ce53b6SStefano Zampini } 1207b7ce53b6SStefano Zampini PetscFunctionReturn(0); 1208b7ce53b6SStefano Zampini } 1209b7ce53b6SStefano Zampini 1210b7ce53b6SStefano Zampini #undef __FUNCT__ 1211b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ" 1212b7ce53b6SStefano Zampini /*@ 1213b7ce53b6SStefano Zampini MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format 1214b7ce53b6SStefano Zampini 1215b7ce53b6SStefano Zampini Input Parameter: 1216b7ce53b6SStefano Zampini . mat - the matrix (should be of type MATIS) 1217b7ce53b6SStefano Zampini . reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 1218b7ce53b6SStefano Zampini 1219b7ce53b6SStefano Zampini Output Parameter: 1220b7ce53b6SStefano Zampini . newmat - the matrix in AIJ format 1221b7ce53b6SStefano Zampini 1222b7ce53b6SStefano Zampini Level: developer 1223b7ce53b6SStefano Zampini 1224eb82efa4SStefano Zampini Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested. 1225b7ce53b6SStefano Zampini 1226b7ce53b6SStefano Zampini .seealso: MATIS 1227b7ce53b6SStefano Zampini @*/ 1228b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat) 1229b7ce53b6SStefano Zampini { 1230b7ce53b6SStefano Zampini PetscErrorCode ierr; 1231b7ce53b6SStefano Zampini 1232b7ce53b6SStefano Zampini PetscFunctionBegin; 1233b7ce53b6SStefano Zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1234b7ce53b6SStefano Zampini PetscValidLogicalCollectiveEnum(mat,reuse,2); 1235b7ce53b6SStefano Zampini PetscValidPointer(newmat,3); 1236b7ce53b6SStefano Zampini if (reuse != MAT_INITIAL_MATRIX) { 1237b7ce53b6SStefano Zampini PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3); 1238b7ce53b6SStefano Zampini PetscCheckSameComm(mat,1,*newmat,3); 12396c4ed002SBarry Smith if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix"); 1240b7ce53b6SStefano Zampini } 1241b7ce53b6SStefano Zampini ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr); 1242b7ce53b6SStefano Zampini PetscFunctionReturn(0); 1243b7ce53b6SStefano Zampini } 1244b7ce53b6SStefano Zampini 1245b7ce53b6SStefano Zampini #undef __FUNCT__ 1246ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS" 1247ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat) 1248ad6194a2SStefano Zampini { 1249ad6194a2SStefano Zampini PetscErrorCode ierr; 1250ad6194a2SStefano Zampini Mat_IS *matis = (Mat_IS*)(mat->data); 1251ad6194a2SStefano Zampini PetscInt bs,m,n,M,N; 1252ad6194a2SStefano Zampini Mat B,localmat; 1253ad6194a2SStefano Zampini 1254ad6194a2SStefano Zampini PetscFunctionBegin; 1255ad6194a2SStefano Zampini ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); 1256ad6194a2SStefano Zampini ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 1257ad6194a2SStefano Zampini ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr); 1258e176bc59SStefano Zampini ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr); 1259ad6194a2SStefano Zampini ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr); 1260ad6194a2SStefano Zampini ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr); 1261b3317aa8SStefano Zampini ierr = MatDestroy(&localmat);CHKERRQ(ierr); 1262ad6194a2SStefano Zampini ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1263ad6194a2SStefano Zampini ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1264ad6194a2SStefano Zampini *newmat = B; 1265ad6194a2SStefano Zampini PetscFunctionReturn(0); 1266ad6194a2SStefano Zampini } 1267ad6194a2SStefano Zampini 1268ad6194a2SStefano Zampini #undef __FUNCT__ 126969796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS" 1270a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool *flg) 127169796d55SStefano Zampini { 127269796d55SStefano Zampini PetscErrorCode ierr; 127369796d55SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 127469796d55SStefano Zampini PetscBool local_sym; 127569796d55SStefano Zampini 127669796d55SStefano Zampini PetscFunctionBegin; 127769796d55SStefano Zampini ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr); 1278b2566f29SBarry Smith ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 127969796d55SStefano Zampini PetscFunctionReturn(0); 128069796d55SStefano Zampini } 128169796d55SStefano Zampini 128269796d55SStefano Zampini #undef __FUNCT__ 128369796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS" 1284a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg) 128569796d55SStefano Zampini { 128669796d55SStefano Zampini PetscErrorCode ierr; 128769796d55SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 128869796d55SStefano Zampini PetscBool local_sym; 128969796d55SStefano Zampini 129069796d55SStefano Zampini PetscFunctionBegin; 129169796d55SStefano Zampini ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr); 1292b2566f29SBarry Smith ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 129369796d55SStefano Zampini PetscFunctionReturn(0); 129469796d55SStefano Zampini } 129569796d55SStefano Zampini 129669796d55SStefano Zampini #undef __FUNCT__ 1297b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS" 1298a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A) 1299b4319ba4SBarry Smith { 1300dfbe8321SBarry Smith PetscErrorCode ierr; 1301b4319ba4SBarry Smith Mat_IS *b = (Mat_IS*)A->data; 1302b4319ba4SBarry Smith 1303b4319ba4SBarry Smith PetscFunctionBegin; 13046bf464f9SBarry Smith ierr = MatDestroy(&b->A);CHKERRQ(ierr); 1305e176bc59SStefano Zampini ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr); 1306e176bc59SStefano Zampini ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr); 13076bf464f9SBarry Smith ierr = VecDestroy(&b->x);CHKERRQ(ierr); 13086bf464f9SBarry Smith ierr = VecDestroy(&b->y);CHKERRQ(ierr); 13093fd1c9e7SStefano Zampini ierr = VecDestroy(&b->counter);CHKERRQ(ierr); 1310a8116848SStefano Zampini ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr); 1311a8116848SStefano Zampini ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr); 1312a8116848SStefano Zampini if (b->sf != b->csf) { 1313a8116848SStefano Zampini ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr); 1314a8116848SStefano Zampini ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr); 1315a8116848SStefano Zampini } 131628f4e0baSStefano Zampini ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr); 131728f4e0baSStefano Zampini ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr); 1318bf0cc555SLisandro Dalcin ierr = PetscFree(A->data);CHKERRQ(ierr); 1319dbd8c25aSHong Zhang ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 1320bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr); 1321b7ce53b6SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr); 1322b7ce53b6SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr); 13232e1947a5SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr); 1324b4319ba4SBarry Smith PetscFunctionReturn(0); 1325b4319ba4SBarry Smith } 1326b4319ba4SBarry Smith 1327b4319ba4SBarry Smith #undef __FUNCT__ 1328b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS" 1329a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y) 1330b4319ba4SBarry Smith { 1331dfbe8321SBarry Smith PetscErrorCode ierr; 1332b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1333b4319ba4SBarry Smith PetscScalar zero = 0.0; 1334b4319ba4SBarry Smith 1335b4319ba4SBarry Smith PetscFunctionBegin; 1336b4319ba4SBarry Smith /* scatter the global vector x into the local work vector */ 1337e176bc59SStefano Zampini ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1338e176bc59SStefano Zampini ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1339b4319ba4SBarry Smith 1340b4319ba4SBarry Smith /* multiply the local matrix */ 1341b4319ba4SBarry Smith ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr); 1342b4319ba4SBarry Smith 1343b4319ba4SBarry Smith /* scatter product back into global memory */ 13442dcb1b2aSMatthew Knepley ierr = VecSet(y,zero);CHKERRQ(ierr); 1345e176bc59SStefano Zampini ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1346e176bc59SStefano Zampini ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1347b4319ba4SBarry Smith PetscFunctionReturn(0); 1348b4319ba4SBarry Smith } 1349b4319ba4SBarry Smith 1350b4319ba4SBarry Smith #undef __FUNCT__ 13512e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS" 1352a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 13532e74eeadSLisandro Dalcin { 1354650997f4SStefano Zampini Vec temp_vec; 13552e74eeadSLisandro Dalcin PetscErrorCode ierr; 13562e74eeadSLisandro Dalcin 13572e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 1358650997f4SStefano Zampini if (v3 != v2) { 1359650997f4SStefano Zampini ierr = MatMult(A,v1,v3);CHKERRQ(ierr); 1360650997f4SStefano Zampini ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 1361650997f4SStefano Zampini } else { 1362650997f4SStefano Zampini ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 1363650997f4SStefano Zampini ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr); 1364650997f4SStefano Zampini ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 1365650997f4SStefano Zampini ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 1366650997f4SStefano Zampini ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 1367650997f4SStefano Zampini } 13682e74eeadSLisandro Dalcin PetscFunctionReturn(0); 13692e74eeadSLisandro Dalcin } 13702e74eeadSLisandro Dalcin 13712e74eeadSLisandro Dalcin #undef __FUNCT__ 13722e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS" 1373a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x) 13742e74eeadSLisandro Dalcin { 13752e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 13762e74eeadSLisandro Dalcin PetscErrorCode ierr; 13772e74eeadSLisandro Dalcin 1378e176bc59SStefano Zampini PetscFunctionBegin; 13792e74eeadSLisandro Dalcin /* scatter the global vector x into the local work vector */ 1380e176bc59SStefano Zampini ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1381e176bc59SStefano Zampini ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 13822e74eeadSLisandro Dalcin 13832e74eeadSLisandro Dalcin /* multiply the local matrix */ 1384e176bc59SStefano Zampini ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr); 13852e74eeadSLisandro Dalcin 13862e74eeadSLisandro Dalcin /* scatter product back into global vector */ 1387e176bc59SStefano Zampini ierr = VecSet(x,0);CHKERRQ(ierr); 1388e176bc59SStefano Zampini ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1389e176bc59SStefano Zampini ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 13902e74eeadSLisandro Dalcin PetscFunctionReturn(0); 13912e74eeadSLisandro Dalcin } 13922e74eeadSLisandro Dalcin 13932e74eeadSLisandro Dalcin #undef __FUNCT__ 13942e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS" 1395a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 13962e74eeadSLisandro Dalcin { 1397650997f4SStefano Zampini Vec temp_vec; 13982e74eeadSLisandro Dalcin PetscErrorCode ierr; 13992e74eeadSLisandro Dalcin 14002e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 1401650997f4SStefano Zampini if (v3 != v2) { 1402650997f4SStefano Zampini ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr); 1403650997f4SStefano Zampini ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 1404650997f4SStefano Zampini } else { 1405650997f4SStefano Zampini ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 1406650997f4SStefano Zampini ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr); 1407650997f4SStefano Zampini ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 1408650997f4SStefano Zampini ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 1409650997f4SStefano Zampini ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 1410650997f4SStefano Zampini } 14112e74eeadSLisandro Dalcin PetscFunctionReturn(0); 14122e74eeadSLisandro Dalcin } 14132e74eeadSLisandro Dalcin 14142e74eeadSLisandro Dalcin #undef __FUNCT__ 1415b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS" 1416a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer) 1417b4319ba4SBarry Smith { 1418b4319ba4SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 1419dfbe8321SBarry Smith PetscErrorCode ierr; 1420b4319ba4SBarry Smith PetscViewer sviewer; 1421b4319ba4SBarry Smith 1422b4319ba4SBarry Smith PetscFunctionBegin; 14233f08860eSBarry Smith ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 1424b4319ba4SBarry Smith ierr = MatView(a->A,sviewer);CHKERRQ(ierr); 14253f08860eSBarry Smith ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 14266e520ac8SStefano Zampini ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1427b4319ba4SBarry Smith PetscFunctionReturn(0); 1428b4319ba4SBarry Smith } 1429b4319ba4SBarry Smith 1430b4319ba4SBarry Smith #undef __FUNCT__ 1431b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS" 1432a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping) 1433b4319ba4SBarry Smith { 1434dfbe8321SBarry Smith PetscErrorCode ierr; 1435e176bc59SStefano Zampini PetscInt nr,rbs,nc,cbs; 1436b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1437b4319ba4SBarry Smith IS from,to; 1438e176bc59SStefano Zampini Vec cglobal,rglobal; 1439b4319ba4SBarry Smith 1440b4319ba4SBarry Smith PetscFunctionBegin; 1441784ac674SJed Brown PetscCheckSameComm(A,1,rmapping,2); 1442e176bc59SStefano Zampini PetscCheckSameComm(A,1,cmapping,3); 14433bbff08aSStefano Zampini /* Destroy any previous data */ 144470cf5478SStefano Zampini ierr = VecDestroy(&is->x);CHKERRQ(ierr); 144570cf5478SStefano Zampini ierr = VecDestroy(&is->y);CHKERRQ(ierr); 14463fd1c9e7SStefano Zampini ierr = VecDestroy(&is->counter);CHKERRQ(ierr); 1447e176bc59SStefano Zampini ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr); 1448e176bc59SStefano Zampini ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr); 14491c47cb0fSStefano Zampini ierr = MatDestroy(&is->A);CHKERRQ(ierr); 145028f4e0baSStefano Zampini ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr); 145128f4e0baSStefano Zampini ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr); 14523bbff08aSStefano Zampini 14533bbff08aSStefano Zampini /* Setup Layout and set local to global maps */ 1454fc27028aSStefano Zampini ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 1455fc27028aSStefano Zampini ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 1456fa7f1dd8SStefano Zampini ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr); 1457fa7f1dd8SStefano Zampini ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr); 1458b4319ba4SBarry Smith 1459b4319ba4SBarry Smith /* Create the local matrix A */ 1460e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr); 1461e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr); 1462e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr); 1463e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr); 1464f69a0ea3SMatthew Knepley ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr); 1465e176bc59SStefano Zampini ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr); 1466e176bc59SStefano Zampini ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr); 1467e176bc59SStefano Zampini ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr); 1468ff130e51SJed Brown ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr); 1469ff130e51SJed Brown ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr); 1470b4319ba4SBarry Smith ierr = MatSetFromOptions(is->A);CHKERRQ(ierr); 1471b4319ba4SBarry Smith 1472f26d0771SStefano Zampini if (!is->islocalref) { /* setup scatters and local vectors for MatMult */ 1473b4319ba4SBarry Smith /* Create the local work vectors */ 14743bbff08aSStefano Zampini ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr); 1475b4319ba4SBarry Smith 1476e176bc59SStefano Zampini /* setup the global to local scatters */ 1477e176bc59SStefano Zampini ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr); 1478e176bc59SStefano Zampini ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr); 1479784ac674SJed Brown ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr); 1480e176bc59SStefano Zampini ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr); 1481e176bc59SStefano Zampini if (rmapping != cmapping) { 1482e176bc59SStefano Zampini ierr = ISDestroy(&to);CHKERRQ(ierr); 1483e176bc59SStefano Zampini ierr = ISDestroy(&from);CHKERRQ(ierr); 1484e176bc59SStefano Zampini ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr); 1485e176bc59SStefano Zampini ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr); 1486e176bc59SStefano Zampini ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr); 1487e176bc59SStefano Zampini } else { 1488e176bc59SStefano Zampini ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr); 1489e176bc59SStefano Zampini is->cctx = is->rctx; 1490e176bc59SStefano Zampini } 14913fd1c9e7SStefano Zampini 14923fd1c9e7SStefano Zampini /* interface counter vector (local) */ 14933fd1c9e7SStefano Zampini ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr); 14943fd1c9e7SStefano Zampini ierr = VecSet(is->y,1.);CHKERRQ(ierr); 14953fd1c9e7SStefano Zampini ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 14963fd1c9e7SStefano Zampini ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 14973fd1c9e7SStefano Zampini ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 14983fd1c9e7SStefano Zampini ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 14993fd1c9e7SStefano Zampini 15003fd1c9e7SStefano Zampini /* free workspace */ 1501e176bc59SStefano Zampini ierr = VecDestroy(&rglobal);CHKERRQ(ierr); 1502e176bc59SStefano Zampini ierr = VecDestroy(&cglobal);CHKERRQ(ierr); 15036bf464f9SBarry Smith ierr = ISDestroy(&to);CHKERRQ(ierr); 15046bf464f9SBarry Smith ierr = ISDestroy(&from);CHKERRQ(ierr); 1505f26d0771SStefano Zampini } 150648ff6bf3SStefano Zampini ierr = MatSetUp(A);CHKERRQ(ierr); 1507b4319ba4SBarry Smith PetscFunctionReturn(0); 1508b4319ba4SBarry Smith } 1509b4319ba4SBarry Smith 15102e74eeadSLisandro Dalcin #undef __FUNCT__ 15112e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS" 1512a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 15132e74eeadSLisandro Dalcin { 15142e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)mat->data; 15152e74eeadSLisandro Dalcin PetscErrorCode ierr; 151697563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 151797563a80SStefano Zampini PetscInt i,zm,zn; 151897563a80SStefano Zampini #endif 1519f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 15202e74eeadSLisandro Dalcin 15212e74eeadSLisandro Dalcin PetscFunctionBegin; 15222e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG) 1523f26d0771SStefano 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); 152497563a80SStefano Zampini /* count negative indices */ 152597563a80SStefano Zampini for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++; 152697563a80SStefano Zampini for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++; 15272e74eeadSLisandro Dalcin #endif 152897563a80SStefano Zampini ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr); 152997563a80SStefano Zampini ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr); 153097563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 153197563a80SStefano Zampini /* count negative indices (should be the same as before) */ 153297563a80SStefano Zampini for (i=0;i<m;i++) if (rows_l[i] < 0) zm--; 153397563a80SStefano Zampini for (i=0;i<n;i++) if (cols_l[i] < 0) zn--; 153497563a80SStefano 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"); 153597563a80SStefano 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"); 153697563a80SStefano Zampini #endif 15372e74eeadSLisandro Dalcin ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 15382e74eeadSLisandro Dalcin PetscFunctionReturn(0); 15392e74eeadSLisandro Dalcin } 15402e74eeadSLisandro Dalcin 1541b4319ba4SBarry Smith #undef __FUNCT__ 154297563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS" 1543a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 154497563a80SStefano Zampini { 154597563a80SStefano Zampini Mat_IS *is = (Mat_IS*)mat->data; 154697563a80SStefano Zampini PetscErrorCode ierr; 154797563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 154897563a80SStefano Zampini PetscInt i,zm,zn; 154997563a80SStefano Zampini #endif 1550f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 155197563a80SStefano Zampini 155297563a80SStefano Zampini PetscFunctionBegin; 155397563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 1554f26d0771SStefano 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); 155597563a80SStefano Zampini /* count negative indices */ 155697563a80SStefano Zampini for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++; 155797563a80SStefano Zampini for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++; 155897563a80SStefano Zampini #endif 155997563a80SStefano Zampini ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr); 156097563a80SStefano Zampini ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr); 156197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG) 156297563a80SStefano Zampini /* count negative indices (should be the same as before) */ 156397563a80SStefano Zampini for (i=0;i<m;i++) if (rows_l[i] < 0) zm--; 156497563a80SStefano Zampini for (i=0;i<n;i++) if (cols_l[i] < 0) zn--; 156597563a80SStefano 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"); 156697563a80SStefano 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"); 156797563a80SStefano Zampini #endif 156897563a80SStefano Zampini ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 156997563a80SStefano Zampini PetscFunctionReturn(0); 157097563a80SStefano Zampini } 157197563a80SStefano Zampini 157297563a80SStefano Zampini #undef __FUNCT__ 1573b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS" 1574a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1575b4319ba4SBarry Smith { 1576dfbe8321SBarry Smith PetscErrorCode ierr; 1577b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1578b4319ba4SBarry Smith 1579b4319ba4SBarry Smith PetscFunctionBegin; 1580b4319ba4SBarry Smith ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 1581b4319ba4SBarry Smith PetscFunctionReturn(0); 1582b4319ba4SBarry Smith } 1583b4319ba4SBarry Smith 1584b4319ba4SBarry Smith #undef __FUNCT__ 1585f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS" 1586a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1587f0006bf2SLisandro Dalcin { 1588f0006bf2SLisandro Dalcin PetscErrorCode ierr; 1589f0006bf2SLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 1590f0006bf2SLisandro Dalcin 1591f0006bf2SLisandro Dalcin PetscFunctionBegin; 1592f0006bf2SLisandro Dalcin ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 1593f0006bf2SLisandro Dalcin PetscFunctionReturn(0); 1594f0006bf2SLisandro Dalcin } 1595f0006bf2SLisandro Dalcin 1596f0006bf2SLisandro Dalcin #undef __FUNCT__ 1597f0ae7da4SStefano Zampini #define __FUNCT__ "MatISZeroRowsColumnsLocal_Private" 1598f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns) 1599f0ae7da4SStefano Zampini { 1600f0ae7da4SStefano Zampini Mat_IS *is = (Mat_IS*)A->data; 1601f0ae7da4SStefano Zampini PetscErrorCode ierr; 1602f0ae7da4SStefano Zampini 1603f0ae7da4SStefano Zampini PetscFunctionBegin; 1604f0ae7da4SStefano Zampini if (!n) { 1605f0ae7da4SStefano Zampini is->pure_neumann = PETSC_TRUE; 1606f0ae7da4SStefano Zampini } else { 1607f0ae7da4SStefano Zampini PetscInt i; 1608f0ae7da4SStefano Zampini is->pure_neumann = PETSC_FALSE; 1609f0ae7da4SStefano Zampini 1610f0ae7da4SStefano Zampini if (columns) { 1611f0ae7da4SStefano Zampini ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 1612f0ae7da4SStefano Zampini } else { 1613f0ae7da4SStefano Zampini ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 1614f0ae7da4SStefano Zampini } 1615f0ae7da4SStefano Zampini if (diag != 0.) { 1616f0ae7da4SStefano Zampini const PetscScalar *array; 1617f0ae7da4SStefano Zampini ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr); 1618f0ae7da4SStefano Zampini for (i=0; i<n; i++) { 1619f0ae7da4SStefano Zampini ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr); 1620f0ae7da4SStefano Zampini } 1621f0ae7da4SStefano Zampini ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr); 1622f0ae7da4SStefano Zampini } 1623f0ae7da4SStefano Zampini ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1624f0ae7da4SStefano Zampini ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1625f0ae7da4SStefano Zampini } 1626f0ae7da4SStefano Zampini PetscFunctionReturn(0); 1627f0ae7da4SStefano Zampini } 1628f0ae7da4SStefano Zampini 1629f0ae7da4SStefano Zampini #undef __FUNCT__ 1630f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_Private_IS" 1631f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns) 16322e74eeadSLisandro Dalcin { 16336e520ac8SStefano Zampini Mat_IS *matis = (Mat_IS*)A->data; 16346e520ac8SStefano Zampini PetscInt nr,nl,len,i; 16356e520ac8SStefano Zampini PetscInt *lrows; 16362e74eeadSLisandro Dalcin PetscErrorCode ierr; 16372e74eeadSLisandro Dalcin 16382e74eeadSLisandro Dalcin PetscFunctionBegin; 1639f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG) 1640f0ae7da4SStefano Zampini if (columns || diag != 0. || (x && b)) { 1641f0ae7da4SStefano Zampini PetscBool cong; 1642f0ae7da4SStefano Zampini ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr); 1643f0ae7da4SStefano 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"); 1644f0ae7da4SStefano 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"); 1645f0ae7da4SStefano Zampini if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent"); 1646f0ae7da4SStefano Zampini } 1647f0ae7da4SStefano Zampini #endif 16486e520ac8SStefano Zampini /* get locally owned rows */ 1649f0ae7da4SStefano Zampini ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr); 16506e520ac8SStefano Zampini /* fix right hand side if needed */ 16516e520ac8SStefano Zampini if (x && b) { 16526e520ac8SStefano Zampini const PetscScalar *xx; 16536e520ac8SStefano Zampini PetscScalar *bb; 16546e520ac8SStefano Zampini 16556e520ac8SStefano Zampini ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr); 16566e520ac8SStefano Zampini ierr = VecGetArray(b, &bb);CHKERRQ(ierr); 16576e520ac8SStefano Zampini for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]]; 16586e520ac8SStefano Zampini ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr); 16596e520ac8SStefano Zampini ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr); 16602e74eeadSLisandro Dalcin } 16616e520ac8SStefano Zampini /* get rows associated to the local matrices */ 16626e520ac8SStefano Zampini if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */ 16636e520ac8SStefano Zampini ierr = MatISComputeSF_Private(A);CHKERRQ(ierr); 16646e520ac8SStefano Zampini } 16656e520ac8SStefano Zampini ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr); 16666e520ac8SStefano Zampini ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr); 16676e520ac8SStefano Zampini ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 16686e520ac8SStefano Zampini for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1; 16696e520ac8SStefano Zampini ierr = PetscFree(lrows);CHKERRQ(ierr); 16706e520ac8SStefano Zampini ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 16716e520ac8SStefano Zampini ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 16726e520ac8SStefano Zampini ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr); 16736e520ac8SStefano Zampini for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i; 1674f0ae7da4SStefano Zampini ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr); 16756e520ac8SStefano Zampini ierr = PetscFree(lrows);CHKERRQ(ierr); 16762e74eeadSLisandro Dalcin PetscFunctionReturn(0); 16772e74eeadSLisandro Dalcin } 16782e74eeadSLisandro Dalcin 16792e74eeadSLisandro Dalcin #undef __FUNCT__ 1680f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRows_IS" 1681f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1682b4319ba4SBarry Smith { 1683dfbe8321SBarry Smith PetscErrorCode ierr; 1684b4319ba4SBarry Smith 1685b4319ba4SBarry Smith PetscFunctionBegin; 1686f0ae7da4SStefano Zampini ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr); 1687f0ae7da4SStefano Zampini PetscFunctionReturn(0); 1688f0ae7da4SStefano Zampini } 16892205254eSKarl Rupp 1690f0ae7da4SStefano Zampini #undef __FUNCT__ 1691f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_IS" 1692f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 1693f0ae7da4SStefano Zampini { 1694f0ae7da4SStefano Zampini PetscErrorCode ierr; 1695f0ae7da4SStefano Zampini 1696f0ae7da4SStefano Zampini PetscFunctionBegin; 1697f0ae7da4SStefano Zampini ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr); 1698b4319ba4SBarry Smith PetscFunctionReturn(0); 1699b4319ba4SBarry Smith } 1700b4319ba4SBarry Smith 1701b4319ba4SBarry Smith #undef __FUNCT__ 1702b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS" 1703a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type) 1704b4319ba4SBarry Smith { 1705b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1706dfbe8321SBarry Smith PetscErrorCode ierr; 1707b4319ba4SBarry Smith 1708b4319ba4SBarry Smith PetscFunctionBegin; 1709b4319ba4SBarry Smith ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr); 1710b4319ba4SBarry Smith PetscFunctionReturn(0); 1711b4319ba4SBarry Smith } 1712b4319ba4SBarry Smith 1713b4319ba4SBarry Smith #undef __FUNCT__ 1714b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS" 1715a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type) 1716b4319ba4SBarry Smith { 1717b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)A->data; 1718dfbe8321SBarry Smith PetscErrorCode ierr; 1719b4319ba4SBarry Smith 1720b4319ba4SBarry Smith PetscFunctionBegin; 1721b4319ba4SBarry Smith ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr); 1722b4319ba4SBarry Smith PetscFunctionReturn(0); 1723b4319ba4SBarry Smith } 1724b4319ba4SBarry Smith 1725b4319ba4SBarry Smith #undef __FUNCT__ 1726b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS" 1727a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local) 1728b4319ba4SBarry Smith { 1729b4319ba4SBarry Smith Mat_IS *is = (Mat_IS*)mat->data; 1730b4319ba4SBarry Smith 1731b4319ba4SBarry Smith PetscFunctionBegin; 1732b4319ba4SBarry Smith *local = is->A; 1733b4319ba4SBarry Smith PetscFunctionReturn(0); 1734b4319ba4SBarry Smith } 1735b4319ba4SBarry Smith 1736b4319ba4SBarry Smith #undef __FUNCT__ 1737b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat" 1738b4319ba4SBarry Smith /*@ 1739b4319ba4SBarry Smith MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix. 1740b4319ba4SBarry Smith 1741b4319ba4SBarry Smith Input Parameter: 1742b4319ba4SBarry Smith . mat - the matrix 1743b4319ba4SBarry Smith 1744b4319ba4SBarry Smith Output Parameter: 1745eb82efa4SStefano Zampini . local - the local matrix 1746b4319ba4SBarry Smith 1747b4319ba4SBarry Smith Level: advanced 1748b4319ba4SBarry Smith 1749b4319ba4SBarry Smith Notes: 1750b4319ba4SBarry Smith This can be called if you have precomputed the nonzero structure of the 1751b4319ba4SBarry Smith matrix and want to provide it to the inner matrix object to improve the performance 1752b4319ba4SBarry Smith of the MatSetValues() operation. 1753b4319ba4SBarry Smith 1754b4319ba4SBarry Smith .seealso: MATIS 1755b4319ba4SBarry Smith @*/ 17567087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local) 1757b4319ba4SBarry Smith { 17584ac538c5SBarry Smith PetscErrorCode ierr; 1759b4319ba4SBarry Smith 1760b4319ba4SBarry Smith PetscFunctionBegin; 17610700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1762b4319ba4SBarry Smith PetscValidPointer(local,2); 17634ac538c5SBarry Smith ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr); 1764b4319ba4SBarry Smith PetscFunctionReturn(0); 1765b4319ba4SBarry Smith } 1766b4319ba4SBarry Smith 17673b03a366Sstefano_zampini #undef __FUNCT__ 17683b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS" 1769a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local) 17703b03a366Sstefano_zampini { 17713b03a366Sstefano_zampini Mat_IS *is = (Mat_IS*)mat->data; 17723b03a366Sstefano_zampini PetscInt nrows,ncols,orows,ocols; 17733b03a366Sstefano_zampini PetscErrorCode ierr; 17743b03a366Sstefano_zampini 17753b03a366Sstefano_zampini PetscFunctionBegin; 17764e4c7dbeSStefano Zampini if (is->A) { 17773b03a366Sstefano_zampini ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr); 17783b03a366Sstefano_zampini ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr); 1779f0ae7da4SStefano 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); 17804e4c7dbeSStefano Zampini } 17813b03a366Sstefano_zampini ierr = PetscObjectReference((PetscObject)local);CHKERRQ(ierr); 17823b03a366Sstefano_zampini ierr = MatDestroy(&is->A);CHKERRQ(ierr); 17833b03a366Sstefano_zampini is->A = local; 17843b03a366Sstefano_zampini PetscFunctionReturn(0); 17853b03a366Sstefano_zampini } 17863b03a366Sstefano_zampini 17873b03a366Sstefano_zampini #undef __FUNCT__ 17883b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat" 17893b03a366Sstefano_zampini /*@ 1790eb82efa4SStefano Zampini MatISSetLocalMat - Replace the local matrix stored inside a MATIS object. 17913b03a366Sstefano_zampini 17923b03a366Sstefano_zampini Input Parameter: 17933b03a366Sstefano_zampini . mat - the matrix 1794eb82efa4SStefano Zampini . local - the local matrix 17953b03a366Sstefano_zampini 17963b03a366Sstefano_zampini Output Parameter: 17973b03a366Sstefano_zampini 17983b03a366Sstefano_zampini Level: advanced 17993b03a366Sstefano_zampini 18003b03a366Sstefano_zampini Notes: 18013b03a366Sstefano_zampini This can be called if you have precomputed the local matrix and 18023b03a366Sstefano_zampini want to provide it to the matrix object MATIS. 18033b03a366Sstefano_zampini 18043b03a366Sstefano_zampini .seealso: MATIS 18053b03a366Sstefano_zampini @*/ 18063b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local) 18073b03a366Sstefano_zampini { 18083b03a366Sstefano_zampini PetscErrorCode ierr; 18093b03a366Sstefano_zampini 18103b03a366Sstefano_zampini PetscFunctionBegin; 18113b03a366Sstefano_zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1812b7ce53b6SStefano Zampini PetscValidHeaderSpecific(local,MAT_CLASSID,2); 18133b03a366Sstefano_zampini ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr); 18143b03a366Sstefano_zampini PetscFunctionReturn(0); 18153b03a366Sstefano_zampini } 18163b03a366Sstefano_zampini 18176726f965SBarry Smith #undef __FUNCT__ 18186726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS" 1819a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A) 18206726f965SBarry Smith { 18216726f965SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 18226726f965SBarry Smith PetscErrorCode ierr; 18236726f965SBarry Smith 18246726f965SBarry Smith PetscFunctionBegin; 18256726f965SBarry Smith ierr = MatZeroEntries(a->A);CHKERRQ(ierr); 18266726f965SBarry Smith PetscFunctionReturn(0); 18276726f965SBarry Smith } 18286726f965SBarry Smith 18296726f965SBarry Smith #undef __FUNCT__ 18302e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS" 1831a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a) 18322e74eeadSLisandro Dalcin { 18332e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 18342e74eeadSLisandro Dalcin PetscErrorCode ierr; 18352e74eeadSLisandro Dalcin 18362e74eeadSLisandro Dalcin PetscFunctionBegin; 18372e74eeadSLisandro Dalcin ierr = MatScale(is->A,a);CHKERRQ(ierr); 18382e74eeadSLisandro Dalcin PetscFunctionReturn(0); 18392e74eeadSLisandro Dalcin } 18402e74eeadSLisandro Dalcin 18412e74eeadSLisandro Dalcin #undef __FUNCT__ 18422e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS" 1843a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 18442e74eeadSLisandro Dalcin { 18452e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS*)A->data; 18462e74eeadSLisandro Dalcin PetscErrorCode ierr; 18472e74eeadSLisandro Dalcin 18482e74eeadSLisandro Dalcin PetscFunctionBegin; 18492e74eeadSLisandro Dalcin /* get diagonal of the local matrix */ 1850e176bc59SStefano Zampini ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr); 18512e74eeadSLisandro Dalcin 18522e74eeadSLisandro Dalcin /* scatter diagonal back into global vector */ 18532e74eeadSLisandro Dalcin ierr = VecSet(v,0);CHKERRQ(ierr); 1854e176bc59SStefano Zampini ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1855e176bc59SStefano Zampini ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 18562e74eeadSLisandro Dalcin PetscFunctionReturn(0); 18572e74eeadSLisandro Dalcin } 18582e74eeadSLisandro Dalcin 18592e74eeadSLisandro Dalcin #undef __FUNCT__ 18606726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS" 1861a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg) 18626726f965SBarry Smith { 18636726f965SBarry Smith Mat_IS *a = (Mat_IS*)A->data; 18646726f965SBarry Smith PetscErrorCode ierr; 18656726f965SBarry Smith 18666726f965SBarry Smith PetscFunctionBegin; 18674e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 18686726f965SBarry Smith PetscFunctionReturn(0); 18696726f965SBarry Smith } 18706726f965SBarry Smith 1871284134d9SBarry Smith #undef __FUNCT__ 1872f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS" 1873f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str) 1874f26d0771SStefano Zampini { 1875f26d0771SStefano Zampini Mat_IS *y = (Mat_IS*)Y->data; 1876f26d0771SStefano Zampini Mat_IS *x; 1877f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1878f26d0771SStefano Zampini PetscBool ismatis; 1879f26d0771SStefano Zampini #endif 1880f26d0771SStefano Zampini PetscErrorCode ierr; 1881f26d0771SStefano Zampini 1882f26d0771SStefano Zampini PetscFunctionBegin; 1883f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1884f26d0771SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr); 1885f26d0771SStefano Zampini if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 1886f26d0771SStefano Zampini #endif 1887f26d0771SStefano Zampini x = (Mat_IS*)X->data; 1888f26d0771SStefano Zampini ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr); 1889f26d0771SStefano Zampini PetscFunctionReturn(0); 1890f26d0771SStefano Zampini } 1891f26d0771SStefano Zampini 1892f26d0771SStefano Zampini #undef __FUNCT__ 1893f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS" 1894f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat) 1895f26d0771SStefano Zampini { 1896f26d0771SStefano Zampini Mat lA; 1897f26d0771SStefano Zampini Mat_IS *matis; 1898f26d0771SStefano Zampini ISLocalToGlobalMapping rl2g,cl2g; 1899f26d0771SStefano Zampini IS is; 1900f26d0771SStefano Zampini const PetscInt *rg,*rl; 1901f26d0771SStefano Zampini PetscInt nrg; 1902f26d0771SStefano Zampini PetscInt N,M,nrl,i,*idxs; 1903f26d0771SStefano Zampini PetscErrorCode ierr; 1904f26d0771SStefano Zampini 1905f26d0771SStefano Zampini PetscFunctionBegin; 1906f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr); 1907f26d0771SStefano Zampini ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr); 1908f26d0771SStefano Zampini ierr = ISGetIndices(row,&rl);CHKERRQ(ierr); 1909f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr); 1910f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1911f0ae7da4SStefano 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); 1912f26d0771SStefano Zampini #endif 1913f26d0771SStefano Zampini ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr); 1914f26d0771SStefano Zampini /* map from [0,nrl) to row */ 1915f26d0771SStefano Zampini for (i=0;i<nrl;i++) idxs[i] = rl[i]; 1916f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1917f26d0771SStefano Zampini for (i=nrl;i<nrg;i++) idxs[i] = nrg; 1918f26d0771SStefano Zampini #else 1919f26d0771SStefano Zampini for (i=nrl;i<nrg;i++) idxs[i] = -1; 1920f26d0771SStefano Zampini #endif 1921f26d0771SStefano Zampini ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr); 1922f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr); 1923f26d0771SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 1924f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 1925f26d0771SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 1926f26d0771SStefano Zampini /* compute new l2g map for columns */ 1927f26d0771SStefano Zampini if (col != row || A->rmap->mapping != A->cmap->mapping) { 1928f26d0771SStefano Zampini const PetscInt *cg,*cl; 1929f26d0771SStefano Zampini PetscInt ncg; 1930f26d0771SStefano Zampini PetscInt ncl; 1931f26d0771SStefano Zampini 1932f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr); 1933f26d0771SStefano Zampini ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr); 1934f26d0771SStefano Zampini ierr = ISGetIndices(col,&cl);CHKERRQ(ierr); 1935f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr); 1936f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1937f0ae7da4SStefano 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); 1938f26d0771SStefano Zampini #endif 1939f26d0771SStefano Zampini ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr); 1940f26d0771SStefano Zampini /* map from [0,ncl) to col */ 1941f26d0771SStefano Zampini for (i=0;i<ncl;i++) idxs[i] = cl[i]; 1942f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG) 1943f26d0771SStefano Zampini for (i=ncl;i<ncg;i++) idxs[i] = ncg; 1944f26d0771SStefano Zampini #else 1945f26d0771SStefano Zampini for (i=ncl;i<ncg;i++) idxs[i] = -1; 1946f26d0771SStefano Zampini #endif 1947f26d0771SStefano Zampini ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr); 1948f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr); 1949f26d0771SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 1950f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 1951f26d0771SStefano Zampini ierr = ISDestroy(&is);CHKERRQ(ierr); 1952f26d0771SStefano Zampini } else { 1953f26d0771SStefano Zampini ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr); 1954f26d0771SStefano Zampini cl2g = rl2g; 1955f26d0771SStefano Zampini } 1956f26d0771SStefano Zampini /* create the MATIS submatrix */ 1957f26d0771SStefano Zampini ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); 1958f26d0771SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr); 1959f26d0771SStefano Zampini ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 1960f26d0771SStefano Zampini ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr); 1961b0aa3428SStefano Zampini matis = (Mat_IS*)((*submat)->data); 1962f26d0771SStefano Zampini matis->islocalref = PETSC_TRUE; 1963f26d0771SStefano Zampini ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr); 1964f26d0771SStefano Zampini ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr); 1965f26d0771SStefano Zampini ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr); 1966f26d0771SStefano Zampini ierr = MatSetUp(*submat);CHKERRQ(ierr); 1967f26d0771SStefano Zampini ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1968f26d0771SStefano Zampini ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1969f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 1970f26d0771SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 1971f26d0771SStefano Zampini /* remove unsupported ops */ 1972f26d0771SStefano Zampini ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 1973f26d0771SStefano Zampini (*submat)->ops->destroy = MatDestroy_IS; 1974f26d0771SStefano Zampini (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 1975f26d0771SStefano Zampini (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 1976f26d0771SStefano Zampini (*submat)->ops->assemblybegin = MatAssemblyBegin_IS; 1977f26d0771SStefano Zampini (*submat)->ops->assemblyend = MatAssemblyEnd_IS; 1978f26d0771SStefano Zampini PetscFunctionReturn(0); 1979f26d0771SStefano Zampini } 1980f26d0771SStefano Zampini 1981f26d0771SStefano Zampini #undef __FUNCT__ 1982284134d9SBarry Smith #define __FUNCT__ "MatCreateIS" 1983284134d9SBarry Smith /*@ 19843c212e90SHong Zhang MatCreateIS - Creates a "process" unassembled matrix, assembled on each 1985284134d9SBarry Smith process but not across processes. 1986284134d9SBarry Smith 1987284134d9SBarry Smith Input Parameters: 1988284134d9SBarry Smith + comm - MPI communicator that will share the matrix 1989e176bc59SStefano Zampini . bs - block size of the matrix 1990df3898eeSBarry Smith . m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products 1991e176bc59SStefano Zampini . rmap - local to global map for rows 1992e176bc59SStefano Zampini - cmap - local to global map for cols 1993284134d9SBarry Smith 1994284134d9SBarry Smith Output Parameter: 1995284134d9SBarry Smith . A - the resulting matrix 1996284134d9SBarry Smith 19978e6c10adSSatish Balay Level: advanced 19988e6c10adSSatish Balay 19993c212e90SHong Zhang Notes: See MATIS for more details. 20006fdf41d1SStefano Zampini m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors 20016fdf41d1SStefano Zampini used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices. 20023c212e90SHong Zhang If either rmap or cmap are NULL, then the matrix is assumed to be square. 2003284134d9SBarry Smith 2004284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping() 2005284134d9SBarry Smith @*/ 2006e176bc59SStefano Zampini PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A) 2007284134d9SBarry Smith { 2008284134d9SBarry Smith PetscErrorCode ierr; 2009284134d9SBarry Smith 2010284134d9SBarry Smith PetscFunctionBegin; 20116fdf41d1SStefano Zampini if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings"); 2012284134d9SBarry Smith ierr = MatCreate(comm,A);CHKERRQ(ierr); 20136fdf41d1SStefano Zampini if (bs > 0) { 2014d3ee2243SStefano Zampini ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr); 20156fdf41d1SStefano Zampini } 2016284134d9SBarry Smith ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr); 2017284134d9SBarry Smith ierr = MatSetType(*A,MATIS);CHKERRQ(ierr); 2018e176bc59SStefano Zampini if (rmap && cmap) { 2019e176bc59SStefano Zampini ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr); 2020e176bc59SStefano Zampini } else if (!rmap) { 2021e176bc59SStefano Zampini ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr); 2022e176bc59SStefano Zampini } else { 2023e176bc59SStefano Zampini ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr); 2024e176bc59SStefano Zampini } 2025284134d9SBarry Smith PetscFunctionReturn(0); 2026284134d9SBarry Smith } 2027284134d9SBarry Smith 2028b4319ba4SBarry Smith /*MC 2029f26d0771SStefano Zampini MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP). 2030b4319ba4SBarry Smith This stores the matrices in globally unassembled form. Each processor 2031b4319ba4SBarry Smith assembles only its local Neumann problem and the parallel matrix vector 2032b4319ba4SBarry Smith product is handled "implicitly". 2033b4319ba4SBarry Smith 2034b4319ba4SBarry Smith Operations Provided: 20356726f965SBarry Smith + MatMult() 20362e74eeadSLisandro Dalcin . MatMultAdd() 20372e74eeadSLisandro Dalcin . MatMultTranspose() 20382e74eeadSLisandro Dalcin . MatMultTransposeAdd() 20396726f965SBarry Smith . MatZeroEntries() 20406726f965SBarry Smith . MatSetOption() 20412e74eeadSLisandro Dalcin . MatZeroRows() 20422e74eeadSLisandro Dalcin . MatSetValues() 204397563a80SStefano Zampini . MatSetValuesBlocked() 20446726f965SBarry Smith . MatSetValuesLocal() 204597563a80SStefano Zampini . MatSetValuesBlockedLocal() 20462e74eeadSLisandro Dalcin . MatScale() 20472e74eeadSLisandro Dalcin . MatGetDiagonal() 20482b404112SStefano Zampini . MatMissingDiagonal() 20492b404112SStefano Zampini . MatDuplicate() 20502b404112SStefano Zampini . MatCopy() 2051f26d0771SStefano Zampini . MatAXPY() 2052f26d0771SStefano Zampini . MatGetSubMatrix() 2053f26d0771SStefano Zampini . MatGetLocalSubMatrix() 2054d7f69cd0SStefano Zampini . MatTranspose() 20556726f965SBarry Smith - MatSetLocalToGlobalMapping() 2056b4319ba4SBarry Smith 2057b4319ba4SBarry Smith Options Database Keys: 2058b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions() 2059b4319ba4SBarry Smith 2060b4319ba4SBarry Smith Notes: Options prefix for the inner matrix are given by -is_mat_xxx 2061b4319ba4SBarry Smith 2062b4319ba4SBarry Smith You must call MatSetLocalToGlobalMapping() before using this matrix type. 2063b4319ba4SBarry Smith 2064b4319ba4SBarry Smith You can do matrix preallocation on the local matrix after you obtain it with 2065eb82efa4SStefano Zampini MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation() 2066b4319ba4SBarry Smith 2067b4319ba4SBarry Smith Level: advanced 2068b4319ba4SBarry Smith 2069f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP 2070b4319ba4SBarry Smith 2071b4319ba4SBarry Smith M*/ 2072b4319ba4SBarry Smith 2073b4319ba4SBarry Smith #undef __FUNCT__ 2074b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS" 20758cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 2076b4319ba4SBarry Smith { 2077dfbe8321SBarry Smith PetscErrorCode ierr; 2078b4319ba4SBarry Smith Mat_IS *b; 2079b4319ba4SBarry Smith 2080b4319ba4SBarry Smith PetscFunctionBegin; 2081b00a9115SJed Brown ierr = PetscNewLog(A,&b);CHKERRQ(ierr); 2082b4319ba4SBarry Smith A->data = (void*)b; 2083b4319ba4SBarry Smith 2084e176bc59SStefano Zampini /* matrix ops */ 2085e176bc59SStefano Zampini ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 2086b4319ba4SBarry Smith A->ops->mult = MatMult_IS; 20872e74eeadSLisandro Dalcin A->ops->multadd = MatMultAdd_IS; 20882e74eeadSLisandro Dalcin A->ops->multtranspose = MatMultTranspose_IS; 20892e74eeadSLisandro Dalcin A->ops->multtransposeadd = MatMultTransposeAdd_IS; 2090b4319ba4SBarry Smith A->ops->destroy = MatDestroy_IS; 2091b4319ba4SBarry Smith A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 20922e74eeadSLisandro Dalcin A->ops->setvalues = MatSetValues_IS; 209398921651SStefano Zampini A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 2094b4319ba4SBarry Smith A->ops->setvalueslocal = MatSetValuesLocal_IS; 2095f0006bf2SLisandro Dalcin A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 20962e74eeadSLisandro Dalcin A->ops->zerorows = MatZeroRows_IS; 2097f0ae7da4SStefano Zampini A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 2098b4319ba4SBarry Smith A->ops->assemblybegin = MatAssemblyBegin_IS; 2099b4319ba4SBarry Smith A->ops->assemblyend = MatAssemblyEnd_IS; 2100b4319ba4SBarry Smith A->ops->view = MatView_IS; 21016726f965SBarry Smith A->ops->zeroentries = MatZeroEntries_IS; 21022e74eeadSLisandro Dalcin A->ops->scale = MatScale_IS; 21032e74eeadSLisandro Dalcin A->ops->getdiagonal = MatGetDiagonal_IS; 21046726f965SBarry Smith A->ops->setoption = MatSetOption_IS; 210569796d55SStefano Zampini A->ops->ishermitian = MatIsHermitian_IS; 210669796d55SStefano Zampini A->ops->issymmetric = MatIsSymmetric_IS; 2107ad6194a2SStefano Zampini A->ops->duplicate = MatDuplicate_IS; 21086bd84002SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_IS; 21092b404112SStefano Zampini A->ops->copy = MatCopy_IS; 2110659959c5SStefano Zampini A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 2111a8116848SStefano Zampini A->ops->getsubmatrix = MatGetSubMatrix_IS; 2112f26d0771SStefano Zampini A->ops->axpy = MatAXPY_IS; 21133fd1c9e7SStefano Zampini A->ops->diagonalset = MatDiagonalSet_IS; 21143fd1c9e7SStefano Zampini A->ops->shift = MatShift_IS; 2115d7f69cd0SStefano Zampini A->ops->transpose = MatTranspose_IS; 21167fa8f2d3SStefano Zampini A->ops->getinfo = MatGetInfo_IS; 2117b4319ba4SBarry Smith 2118b7ce53b6SStefano Zampini /* special MATIS functions */ 2119bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr); 2120bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr); 2121b7ce53b6SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr); 21222e1947a5SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr); 212317667f90SBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr); 2124b4319ba4SBarry Smith PetscFunctionReturn(0); 2125b4319ba4SBarry Smith } 2126