11cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h> 2ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h> 3ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h> 4837cedc9SStefano Zampini #include <../src/mat/impls/dense/seq/dense.h> 5c80a6c00SStefano Zampini #include <petscdmplex.h> 6674ae819SStefano Zampini #include <petscblaslapack.h> 7daf8a457SStefano Zampini #include <petsc/private/sfimpl.h> 8c80a6c00SStefano Zampini #include <petsc/private/dmpleximpl.h> 97620a527SStefano Zampini #include <petscdmda.h> 10674ae819SStefano Zampini 111e0482f5SStefano Zampini static PetscErrorCode MatMPIAIJRestrict(Mat,MPI_Comm,Mat*); 121e0482f5SStefano Zampini 13f498cd09SStefano Zampini /* if range is true, it returns B s.t. span{B} = range(A) 14f498cd09SStefano Zampini if range is false, it returns B s.t. range(B) _|_ range(A) */ 15f498cd09SStefano Zampini PetscErrorCode MatDenseOrthogonalRangeOrComplement(Mat A, PetscBool range, PetscInt lw, PetscScalar *work, PetscReal *rwork, Mat *B) 16a13144ffSStefano Zampini { 17a13144ffSStefano Zampini PetscScalar *uwork,*data,*U, ds = 0.; 18a13144ffSStefano Zampini PetscReal *sing; 19a13144ffSStefano Zampini PetscBLASInt bM,bN,lwork,lierr,di = 1; 20a13144ffSStefano Zampini PetscInt ulw,i,nr,nc,n; 21abee2b68SSebastian Grimberg #if defined(PETSC_USE_COMPLEX) 22abee2b68SSebastian Grimberg PetscReal *rwork2; 23abee2b68SSebastian Grimberg #endif 24a13144ffSStefano Zampini 25a13144ffSStefano Zampini PetscFunctionBegin; 265f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(A,&nr,&nc)); 27a13144ffSStefano Zampini if (!nr || !nc) PetscFunctionReturn(0); 28a13144ffSStefano Zampini 29a13144ffSStefano Zampini /* workspace */ 30a13144ffSStefano Zampini if (!work) { 31a13144ffSStefano Zampini ulw = PetscMax(PetscMax(1,5*PetscMin(nr,nc)),3*PetscMin(nr,nc)+PetscMax(nr,nc)); 325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(ulw,&uwork)); 33a13144ffSStefano Zampini } else { 34a13144ffSStefano Zampini ulw = lw; 35a13144ffSStefano Zampini uwork = work; 36a13144ffSStefano Zampini } 37a13144ffSStefano Zampini n = PetscMin(nr,nc); 38a13144ffSStefano Zampini if (!rwork) { 395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n,&sing)); 40a13144ffSStefano Zampini } else { 41a13144ffSStefano Zampini sing = rwork; 42a13144ffSStefano Zampini } 43a13144ffSStefano Zampini 44a13144ffSStefano Zampini /* SVD */ 455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nr*nr,&U)); 465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(nr,&bM)); 475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(nc,&bN)); 485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(ulw,&lwork)); 495f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(A,&data)); 505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 51abee2b68SSebastian Grimberg #if !defined(PETSC_USE_COMPLEX) 52a13144ffSStefano Zampini PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,&lierr)); 53abee2b68SSebastian Grimberg #else 545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(5*n,&rwork2)); 55abee2b68SSebastian Grimberg PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("A","N",&bM,&bN,data,&bM,sing,U,&bM,&ds,&di,uwork,&lwork,rwork2,&lierr)); 565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(rwork2)); 57abee2b68SSebastian Grimberg #endif 585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 59*28b400f6SJacob Faibussowitsch PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr); 605f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(A,&data)); 61a13144ffSStefano Zampini for (i=0;i<n;i++) if (sing[i] < PETSC_SMALL) break; 62a13144ffSStefano Zampini if (!rwork) { 635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(sing)); 64a13144ffSStefano Zampini } 65a13144ffSStefano Zampini if (!work) { 665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(uwork)); 67a13144ffSStefano Zampini } 68a13144ffSStefano Zampini /* create B */ 69f498cd09SStefano Zampini if (!range) { 705f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,nr,nr-i,NULL,B)); 715f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(*B,&data)); 725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(data,U+nr*i,(nr-i)*nr)); 73f498cd09SStefano Zampini } else { 745f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,nr,i,NULL,B)); 755f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(*B,&data)); 765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(data,U,i*nr)); 77f498cd09SStefano Zampini } 785f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(*B,&data)); 795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(U)); 80a13144ffSStefano Zampini PetscFunctionReturn(0); 81a13144ffSStefano Zampini } 82a13144ffSStefano Zampini 831e0482f5SStefano Zampini /* TODO REMOVE */ 841e0482f5SStefano Zampini #if defined(PRINT_GDET) 851e0482f5SStefano Zampini static int inc = 0; 861e0482f5SStefano Zampini static int lev = 0; 871e0482f5SStefano Zampini #endif 881e0482f5SStefano Zampini 891e0482f5SStefano Zampini PetscErrorCode PCBDDCComputeNedelecChangeEdge(Mat lG, IS edge, IS extrow, IS extcol, IS corners, Mat* Gins, Mat* GKins, PetscScalar cvals[2], PetscScalar *work, PetscReal *rwork) 90a13144ffSStefano Zampini { 91a13144ffSStefano Zampini Mat GE,GEd; 92a13144ffSStefano Zampini PetscInt rsize,csize,esize; 93a13144ffSStefano Zampini PetscScalar *ptr; 94a13144ffSStefano Zampini 95a13144ffSStefano Zampini PetscFunctionBegin; 965f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(edge,&esize)); 97c3c0e390SStefano Zampini if (!esize) PetscFunctionReturn(0); 985f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(extrow,&rsize)); 995f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(extcol,&csize)); 100a13144ffSStefano Zampini 101a13144ffSStefano Zampini /* gradients */ 102a13144ffSStefano Zampini ptr = work + 5*esize; 1035f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(lG,extrow,extcol,MAT_INITIAL_MATRIX,&GE)); 1045f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,rsize,csize,ptr,Gins)); 1055f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,Gins)); 1065f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&GE)); 107a13144ffSStefano Zampini 108a13144ffSStefano Zampini /* constants */ 109a13144ffSStefano Zampini ptr += rsize*csize; 1105f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,esize,csize,ptr,&GEd)); 1115f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(lG,edge,extcol,MAT_INITIAL_MATRIX,&GE)); 1125f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(GE,MATSEQDENSE,MAT_REUSE_MATRIX,&GEd)); 1135f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&GE)); 1145f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseOrthogonalRangeOrComplement(GEd,PETSC_FALSE,5*esize,work,rwork,GKins)); 1155f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&GEd)); 1161e0482f5SStefano Zampini 1171e0482f5SStefano Zampini if (corners) { 1181e0482f5SStefano Zampini Mat GEc; 1191683a169SBarry Smith const PetscScalar *vals; 1201683a169SBarry Smith PetscScalar v; 1211e0482f5SStefano Zampini 1225f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(lG,edge,corners,MAT_INITIAL_MATRIX,&GEc)); 1235f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeMatMult(GEc,*GKins,MAT_INITIAL_MATRIX,1.0,&GEd)); 1245f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(GEd,&vals)); 125637e8532SStefano Zampini /* v = PetscAbsScalar(vals[0]) */; 126637e8532SStefano Zampini v = 1.; 1271e0482f5SStefano Zampini cvals[0] = vals[0]/v; 1281e0482f5SStefano Zampini cvals[1] = vals[1]/v; 1295f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(GEd,&vals)); 1305f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(*GKins,1./v)); 1311e0482f5SStefano Zampini #if defined(PRINT_GDET) 1321e0482f5SStefano Zampini { 1331e0482f5SStefano Zampini PetscViewer viewer; 1341e0482f5SStefano Zampini char filename[256]; 1351e0482f5SStefano Zampini sprintf(filename,"Gdet_l%d_r%d_cc%d.m",lev,PetscGlobalRank,inc++); 1365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer)); 1375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB)); 1385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)GEc,"GEc")); 1395f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(GEc,viewer)); 1405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)(*GKins),"GK")); 1415f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(*GKins,viewer)); 1425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)GEd,"Gproj")); 1435f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(GEd,viewer)); 1445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 1451e0482f5SStefano Zampini } 1461e0482f5SStefano Zampini #endif 1475f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&GEd)); 1485f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&GEc)); 1491e0482f5SStefano Zampini } 1501e0482f5SStefano Zampini 151a13144ffSStefano Zampini PetscFunctionReturn(0); 152a13144ffSStefano Zampini } 153a13144ffSStefano Zampini 154a13144ffSStefano Zampini PetscErrorCode PCBDDCNedelecSupport(PC pc) 155a13144ffSStefano Zampini { 156a13144ffSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 157a13144ffSStefano Zampini Mat_IS *matis = (Mat_IS*)pc->pmat->data; 1580569b399SStefano Zampini Mat G,T,conn,lG,lGt,lGis,lGall,lGe,lGinit; 159eee23b56SStefano Zampini Vec tvec; 160a13144ffSStefano Zampini PetscSF sfv; 1611e0482f5SStefano Zampini ISLocalToGlobalMapping el2g,vl2g,fl2g,al2g; 162a13144ffSStefano Zampini MPI_Comm comm; 163c2151214SStefano Zampini IS lned,primals,allprimals,nedfieldlocal; 164c2151214SStefano Zampini IS *eedges,*extrows,*extcols,*alleedges; 1657d871cd7SStefano Zampini PetscBT btv,bte,btvc,btb,btbd,btvcand,btvi,btee,bter; 166a13144ffSStefano Zampini PetscScalar *vals,*work; 167a13144ffSStefano Zampini PetscReal *rwork; 168a13144ffSStefano Zampini const PetscInt *idxs,*ii,*jj,*iit,*jjt; 1691e0482f5SStefano Zampini PetscInt ne,nv,Lv,order,n,field; 170a13144ffSStefano Zampini PetscInt n_neigh,*neigh,*n_shared,**shared; 171eee23b56SStefano Zampini PetscInt i,j,extmem,cum,maxsize,nee; 172b03ebc13SStefano Zampini PetscInt *extrow,*extrowcum,*marks,*vmarks,*gidxs; 173a13144ffSStefano Zampini PetscInt *sfvleaves,*sfvroots; 174b03ebc13SStefano Zampini PetscInt *corners,*cedges; 175637e8532SStefano Zampini PetscInt *ecount,**eneighs,*vcount,**vneighs; 176b03ebc13SStefano Zampini PetscInt *emarks; 177213b8bfaSStefano Zampini PetscBool print,eerr,done,lrc[2],conforming,global,singular,setprimal; 178a13144ffSStefano Zampini PetscErrorCode ierr; 179a13144ffSStefano Zampini 180a13144ffSStefano Zampini PetscFunctionBegin; 181213b8bfaSStefano Zampini /* If the discrete gradient is defined for a subset of dofs and global is true, 182213b8bfaSStefano Zampini it assumes G is given in global ordering for all the dofs. 183213b8bfaSStefano Zampini Otherwise, the ordering is global for the Nedelec field */ 184213b8bfaSStefano Zampini order = pcbddc->nedorder; 185213b8bfaSStefano Zampini conforming = pcbddc->conforming; 186213b8bfaSStefano Zampini field = pcbddc->nedfield; 187213b8bfaSStefano Zampini global = pcbddc->nedglobal; 188213b8bfaSStefano Zampini setprimal = PETSC_FALSE; 189a13144ffSStefano Zampini print = PETSC_FALSE; 190213b8bfaSStefano Zampini singular = PETSC_FALSE; 191a13144ffSStefano Zampini 192213b8bfaSStefano Zampini /* Command line customization */ 193213b8bfaSStefano Zampini ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC Nedelec options","PC");CHKERRQ(ierr); 1945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-pc_bddc_nedelec_field_primal","All edge dofs set as primals: Toselli's algorithm C",NULL,setprimal,&setprimal,NULL)); 1955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-pc_bddc_nedelec_singular","Infer nullspace from discrete gradient",NULL,singular,&singular,NULL)); 1965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-pc_bddc_nedelec_order","Test variable order code (to be removed)",NULL,order,&order,NULL)); 197213b8bfaSStefano Zampini /* print debug info TODO: to be removed */ 1985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-pc_bddc_nedelec_print","Print debug info",NULL,print,&print,NULL)); 199213b8bfaSStefano Zampini ierr = PetscOptionsEnd();CHKERRQ(ierr); 200213b8bfaSStefano Zampini 201213b8bfaSStefano Zampini /* Return if there are no edges in the decomposition and the problem is not singular */ 2025f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalToGlobalMapping(pc->pmat,&al2g,NULL)); 2035f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetSize(al2g,&n)); 2045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)pc,&comm)); 205213b8bfaSStefano Zampini if (!singular) { 2065f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(matis->counter,(const PetscScalar**)&vals)); 207a13144ffSStefano Zampini lrc[0] = PETSC_FALSE; 208c2151214SStefano Zampini for (i=0;i<n;i++) { 209a13144ffSStefano Zampini if (PetscRealPart(vals[i]) > 2.) { 210a13144ffSStefano Zampini lrc[0] = PETSC_TRUE; 211a13144ffSStefano Zampini break; 212a13144ffSStefano Zampini } 213a13144ffSStefano Zampini } 2145f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals)); 2155f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&lrc[0],&lrc[1],1,MPIU_BOOL,MPI_LOR,comm)); 216a13144ffSStefano Zampini if (!lrc[1]) PetscFunctionReturn(0); 217213b8bfaSStefano Zampini } 218a13144ffSStefano Zampini 219213b8bfaSStefano Zampini /* Get Nedelec field */ 2202c71b3e2SJacob Faibussowitsch PetscCheckFalse(pcbddc->n_ISForDofsLocal && field >= pcbddc->n_ISForDofsLocal,comm,PETSC_ERR_USER,"Invalid field for Nedelec %D: number of fields is %D",field,pcbddc->n_ISForDofsLocal); 221213b8bfaSStefano Zampini if (pcbddc->n_ISForDofsLocal && field >= 0) { 2225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field])); 223c2151214SStefano Zampini nedfieldlocal = pcbddc->ISForDofsLocal[field]; 2245f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(nedfieldlocal,&ne)); 225213b8bfaSStefano Zampini } else if (!pcbddc->n_ISForDofsLocal && field != PETSC_DECIDE) { 226213b8bfaSStefano Zampini ne = n; 227213b8bfaSStefano Zampini nedfieldlocal = NULL; 228213b8bfaSStefano Zampini global = PETSC_TRUE; 229213b8bfaSStefano Zampini } else if (field == PETSC_DECIDE) { 230213b8bfaSStefano Zampini PetscInt rst,ren,*idx; 231213b8bfaSStefano Zampini 2325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(matis->sf_leafdata,n)); 2335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n)); 2345f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(pcbddc->discretegradient,&rst,&ren)); 235213b8bfaSStefano Zampini for (i=rst;i<ren;i++) { 236213b8bfaSStefano Zampini PetscInt nc; 237213b8bfaSStefano Zampini 2385f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(pcbddc->discretegradient,i,&nc,NULL,NULL)); 239213b8bfaSStefano Zampini if (nc > 1) matis->sf_rootdata[i-rst] = 1; 2405f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(pcbddc->discretegradient,i,&nc,NULL,NULL)); 241213b8bfaSStefano Zampini } 2425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 2435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 2445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n,&idx)); 245213b8bfaSStefano Zampini for (i=0,ne=0;i<n;i++) if (matis->sf_leafdata[i]) idx[ne++] = i; 2465f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm,ne,idx,PETSC_OWN_POINTER,&nedfieldlocal)); 247213b8bfaSStefano Zampini } else { 248213b8bfaSStefano Zampini SETERRQ(comm,PETSC_ERR_USER,"When multiple fields are present, the Nedelec field has to be specified"); 249213b8bfaSStefano Zampini } 250213b8bfaSStefano Zampini 251213b8bfaSStefano Zampini /* Sanity checks */ 2522c71b3e2SJacob Faibussowitsch PetscCheckFalse(!order && !conforming,comm,PETSC_ERR_SUP,"Variable order and non-conforming spaces are not supported at the same time"); 253*28b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->user_ChangeOfBasisMatrix,comm,PETSC_ERR_SUP,"Cannot generate Nedelec support with user defined change of basis"); 2542c71b3e2SJacob Faibussowitsch PetscCheckFalse(order && ne%order,PETSC_COMM_SELF,PETSC_ERR_USER,"The number of local edge dofs %D it's not a multiple of the order %D",ne,order); 255213b8bfaSStefano Zampini 256213b8bfaSStefano Zampini /* Just set primal dofs and return */ 2571e0482f5SStefano Zampini if (setprimal) { 258eee23b56SStefano Zampini IS enedfieldlocal; 259eee23b56SStefano Zampini PetscInt *eidxs; 260eee23b56SStefano Zampini 2615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(ne,&eidxs)); 2625f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(matis->counter,(const PetscScalar**)&vals)); 263213b8bfaSStefano Zampini if (nedfieldlocal) { 2645f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(nedfieldlocal,&idxs)); 265eee23b56SStefano Zampini for (i=0,cum=0;i<ne;i++) { 266eee23b56SStefano Zampini if (PetscRealPart(vals[idxs[i]]) > 2.) { 267eee23b56SStefano Zampini eidxs[cum++] = idxs[i]; 268eee23b56SStefano Zampini } 269eee23b56SStefano Zampini } 2705f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(nedfieldlocal,&idxs)); 271213b8bfaSStefano Zampini } else { 272213b8bfaSStefano Zampini for (i=0,cum=0;i<ne;i++) { 273213b8bfaSStefano Zampini if (PetscRealPart(vals[i]) > 2.) { 274213b8bfaSStefano Zampini eidxs[cum++] = i; 275213b8bfaSStefano Zampini } 276213b8bfaSStefano Zampini } 277213b8bfaSStefano Zampini } 2785f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(matis->counter,(const PetscScalar**)&vals)); 2795f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm,cum,eidxs,PETSC_COPY_VALUES,&enedfieldlocal)); 2805f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetPrimalVerticesLocalIS(pc,enedfieldlocal)); 2815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(eidxs)); 2825f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&nedfieldlocal)); 2835f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&enedfieldlocal)); 2841e0482f5SStefano Zampini PetscFunctionReturn(0); 2851e0482f5SStefano Zampini } 286a13144ffSStefano Zampini 287213b8bfaSStefano Zampini /* Compute some l2g maps */ 288213b8bfaSStefano Zampini if (nedfieldlocal) { 289c2151214SStefano Zampini IS is; 290c2151214SStefano Zampini 291c2151214SStefano Zampini /* need to map from the local Nedelec field to local numbering */ 2925f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(nedfieldlocal,&fl2g)); 2931e0482f5SStefano Zampini /* need to map from the local Nedelec field to global numbering for the whole dofs*/ 2945f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApplyIS(al2g,nedfieldlocal,&is)); 2955f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(is,&al2g)); 2961e0482f5SStefano Zampini /* need to map from the local Nedelec field to global numbering (for Nedelec only) */ 2971e0482f5SStefano Zampini if (global) { 2985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)al2g)); 2991e0482f5SStefano Zampini el2g = al2g; 3001e0482f5SStefano Zampini } else { 3011e0482f5SStefano Zampini IS gis; 3021e0482f5SStefano Zampini 3035f80ce2aSJacob Faibussowitsch CHKERRQ(ISRenumber(is,NULL,NULL,&gis)); 3045f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(gis,&el2g)); 3055f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&gis)); 3061e0482f5SStefano Zampini } 3075f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is)); 308c2151214SStefano Zampini } else { 3091e0482f5SStefano Zampini /* restore default */ 3101e0482f5SStefano Zampini pcbddc->nedfield = -1; 3111e0482f5SStefano Zampini /* one ref for the destruction of al2g, one for el2g */ 3125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)al2g)); 3135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)al2g)); 3141e0482f5SStefano Zampini el2g = al2g; 315c2151214SStefano Zampini fl2g = NULL; 316c2151214SStefano Zampini } 317a13144ffSStefano Zampini 318213b8bfaSStefano Zampini /* Start communication to drop connections for interior edges (for cc analysis only) */ 3195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(matis->sf_leafdata,n)); 3205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n)); 321c2151214SStefano Zampini if (nedfieldlocal) { 3225f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(nedfieldlocal,&idxs)); 323c2151214SStefano Zampini for (i=0;i<ne;i++) matis->sf_leafdata[idxs[i]] = 1; 3245f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(nedfieldlocal,&idxs)); 325c2151214SStefano Zampini } else { 326c2151214SStefano Zampini for (i=0;i<ne;i++) matis->sf_leafdata[i] = 1; 327c2151214SStefano Zampini } 3285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM)); 3295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPI_SUM)); 330213b8bfaSStefano Zampini 331213b8bfaSStefano Zampini if (!singular) { /* drop connections with interior edges to avoid unneeded communications and memory movements */ 3325f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(pcbddc->discretegradient,MAT_COPY_VALUES,&G)); 3335f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(G,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE)); 3341e0482f5SStefano Zampini if (global) { 3351e0482f5SStefano Zampini PetscInt rst; 3361e0482f5SStefano Zampini 3375f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(G,&rst,NULL)); 338c2151214SStefano Zampini for (i=0,cum=0;i<pc->pmat->rmap->n;i++) { 339c2151214SStefano Zampini if (matis->sf_rootdata[i] < 2) { 340c2151214SStefano Zampini matis->sf_rootdata[cum++] = i + rst; 341c2151214SStefano Zampini } 342c2151214SStefano Zampini } 3435f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(G,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE)); 3445f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroRows(G,cum,matis->sf_rootdata,0.,NULL,NULL)); 3451e0482f5SStefano Zampini } else { 3461e0482f5SStefano Zampini PetscInt *tbz; 3471e0482f5SStefano Zampini 3485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(ne,&tbz)); 3495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 3505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 3515f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(nedfieldlocal,&idxs)); 3521e0482f5SStefano Zampini for (i=0,cum=0;i<ne;i++) 3531e0482f5SStefano Zampini if (matis->sf_leafdata[idxs[i]] == 1) 3541e0482f5SStefano Zampini tbz[cum++] = i; 3555f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(nedfieldlocal,&idxs)); 3565f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(el2g,cum,tbz,tbz)); 3575f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroRows(G,cum,tbz,0.,NULL,NULL)); 3585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(tbz)); 3591e0482f5SStefano Zampini } 360213b8bfaSStefano Zampini } else { /* we need the entire G to infer the nullspace */ 3615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)pcbddc->discretegradient)); 362213b8bfaSStefano Zampini G = pcbddc->discretegradient; 363213b8bfaSStefano Zampini } 364a13144ffSStefano Zampini 365a13144ffSStefano Zampini /* Extract subdomain relevant rows of G */ 3665f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetIndices(el2g,&idxs)); 3675f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm,ne,idxs,PETSC_USE_POINTER,&lned)); 3685f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(G,lned,NULL,MAT_INITIAL_MATRIX,&lGall)); 3695f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreIndices(el2g,&idxs)); 3705f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&lned)); 3715f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(lGall,MATIS,MAT_INITIAL_MATRIX,&lGis)); 3725f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&lGall)); 3735f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(lGis,&lG)); 374a13144ffSStefano Zampini 375213b8bfaSStefano Zampini /* SF for nodal dofs communications */ 3765f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(G,NULL,&Lv)); 3775f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalToGlobalMapping(lGis,NULL,&vl2g)); 3785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)vl2g)); 3795f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetSize(vl2g,&nv)); 3805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreate(comm,&sfv)); 3815f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetIndices(vl2g,&idxs)); 3825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraphLayout(sfv,lGis->cmap,nv,NULL,PETSC_OWN_POINTER,idxs)); 3835f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreIndices(vl2g,&idxs)); 384213b8bfaSStefano Zampini i = singular ? 2 : 1; 3855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(i*nv,&sfvleaves,i*Lv,&sfvroots)); 386a13144ffSStefano Zampini 3871e0482f5SStefano Zampini /* Destroy temporary G created in MATIS format and modified G */ 3885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)lG)); 3895f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&lGis)); 3905f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&G)); 391a13144ffSStefano Zampini 392213b8bfaSStefano Zampini if (print) { 3935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)lG,"initial_lG")); 3945f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(lG,NULL)); 395213b8bfaSStefano Zampini } 396213b8bfaSStefano Zampini 397213b8bfaSStefano Zampini /* Save lG for values insertion in change of basis */ 3985f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(lG,MAT_COPY_VALUES,&lGinit)); 3990569b399SStefano Zampini 400a13144ffSStefano Zampini /* Analyze the edge-nodes connections (duplicate lG) */ 4015f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(lG,MAT_COPY_VALUES,&lGe)); 4025f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(lGe,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE)); 4035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(nv,&btv)); 4045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(ne,&bte)); 4055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(ne,&btb)); 4065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(ne,&btbd)); 4075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(nv,&btvcand)); 408a13144ffSStefano Zampini /* need to import the boundary specification to ensure the 409a13144ffSStefano Zampini proper detection of coarse edges' endpoints */ 410a13144ffSStefano Zampini if (pcbddc->DirichletBoundariesLocal) { 411c2151214SStefano Zampini IS is; 412c2151214SStefano Zampini 413c2151214SStefano Zampini if (fl2g) { 4145f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->DirichletBoundariesLocal,&is)); 415c2151214SStefano Zampini } else { 416c2151214SStefano Zampini is = pcbddc->DirichletBoundariesLocal; 417c2151214SStefano Zampini } 4185f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(is,&cum)); 4195f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(is,&idxs)); 420a13144ffSStefano Zampini for (i=0;i<cum;i++) { 421a13144ffSStefano Zampini if (idxs[i] >= 0) { 4225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btb,idxs[i])); 4235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btbd,idxs[i])); 424a13144ffSStefano Zampini } 425a13144ffSStefano Zampini } 4265f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(is,&idxs)); 427c2151214SStefano Zampini if (fl2g) { 4285f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is)); 429c2151214SStefano Zampini } 430a13144ffSStefano Zampini } 431a13144ffSStefano Zampini if (pcbddc->NeumannBoundariesLocal) { 432c2151214SStefano Zampini IS is; 433c2151214SStefano Zampini 434c2151214SStefano Zampini if (fl2g) { 4355f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_MASK,pcbddc->NeumannBoundariesLocal,&is)); 436c2151214SStefano Zampini } else { 437c2151214SStefano Zampini is = pcbddc->NeumannBoundariesLocal; 438c2151214SStefano Zampini } 4395f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(is,&cum)); 4405f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(is,&idxs)); 441a13144ffSStefano Zampini for (i=0;i<cum;i++) { 442a13144ffSStefano Zampini if (idxs[i] >= 0) { 4435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btb,idxs[i])); 444a13144ffSStefano Zampini } 445a13144ffSStefano Zampini } 4465f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(is,&idxs)); 447c2151214SStefano Zampini if (fl2g) { 4485f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is)); 449a13144ffSStefano Zampini } 450c2151214SStefano Zampini } 451c2151214SStefano Zampini 452213b8bfaSStefano Zampini /* Count neighs per dof */ 4535f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetNodeInfo(el2g,NULL,&ecount,&eneighs)); 4545f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetNodeInfo(vl2g,NULL,&vcount,&vneighs)); 455637e8532SStefano Zampini 4567d871cd7SStefano Zampini /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs 4577d871cd7SStefano Zampini for proper detection of coarse edges' endpoints */ 4585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(ne,&btee)); 45962b0c6f7SStefano Zampini for (i=0;i<ne;i++) { 460b63b1311SStefano Zampini if ((ecount[i] > 2 && !PetscBTLookup(btbd,i)) || (ecount[i] == 2 && PetscBTLookup(btb,i))) { 4615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btee,i)); 46262b0c6f7SStefano Zampini } 46362b0c6f7SStefano Zampini } 4645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(ne,&marks)); 46562b0c6f7SStefano Zampini if (!conforming) { 4665f80ce2aSJacob Faibussowitsch CHKERRQ(MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt)); 4675f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done)); 46862b0c6f7SStefano Zampini } 4695f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 4705f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJGetArray(lGe,&vals)); 47162b0c6f7SStefano Zampini cum = 0; 472a13144ffSStefano Zampini for (i=0;i<ne;i++) { 473dec27d64SStefano Zampini /* eliminate rows corresponding to edge dofs belonging to coarse faces */ 47462b0c6f7SStefano Zampini if (!PetscBTLookup(btee,i)) { 475a13144ffSStefano Zampini marks[cum++] = i; 476dec27d64SStefano Zampini continue; 477dec27d64SStefano Zampini } 478dec27d64SStefano Zampini /* set badly connected edge dofs as primal */ 47962b0c6f7SStefano Zampini if (!conforming) { 48062b0c6f7SStefano Zampini if (ii[i+1]-ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */ 481a13144ffSStefano Zampini marks[cum++] = i; 4825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(bte,i)); 483a13144ffSStefano Zampini for (j=ii[i];j<ii[i+1];j++) { 4845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btv,jj[j])); 485a13144ffSStefano Zampini } 48662b0c6f7SStefano Zampini } else { 48762b0c6f7SStefano Zampini /* every edge dofs should be connected trough a certain number of nodal dofs 48862b0c6f7SStefano Zampini to other edge dofs belonging to coarse edges 48962b0c6f7SStefano Zampini - at most 2 endpoints 49062b0c6f7SStefano Zampini - order-1 interior nodal dofs 49162b0c6f7SStefano Zampini - no undefined nodal dofs (nconn < order) 49262b0c6f7SStefano Zampini */ 49362b0c6f7SStefano Zampini PetscInt ends = 0,ints = 0, undef = 0; 49462b0c6f7SStefano Zampini for (j=ii[i];j<ii[i+1];j++) { 49562b0c6f7SStefano Zampini PetscInt v = jj[j],k; 49662b0c6f7SStefano Zampini PetscInt nconn = iit[v+1]-iit[v]; 49762b0c6f7SStefano Zampini for (k=iit[v];k<iit[v+1];k++) if (!PetscBTLookup(btee,jjt[k])) nconn--; 49862b0c6f7SStefano Zampini if (nconn > order) ends++; 49962b0c6f7SStefano Zampini else if (nconn == order) ints++; 50062b0c6f7SStefano Zampini else undef++; 50162b0c6f7SStefano Zampini } 50262b0c6f7SStefano Zampini if (undef || ends > 2 || ints != order -1) { 50362b0c6f7SStefano Zampini marks[cum++] = i; 5045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(bte,i)); 50562b0c6f7SStefano Zampini for (j=ii[i];j<ii[i+1];j++) { 5065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btv,jj[j])); 50762b0c6f7SStefano Zampini } 50862b0c6f7SStefano Zampini } 50962b0c6f7SStefano Zampini } 510a13144ffSStefano Zampini } 511dec27d64SStefano Zampini /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */ 512dec27d64SStefano Zampini if (!order && ii[i+1] != ii[i]) { 513dec27d64SStefano Zampini PetscScalar val = 1./(ii[i+1]-ii[i]-1); 514dec27d64SStefano Zampini for (j=ii[i];j<ii[i+1];j++) vals[j] = val; 515a13144ffSStefano Zampini } 516dec27d64SStefano Zampini } 5175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&btee)); 5185f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJRestoreArray(lGe,&vals)); 5195f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 52062b0c6f7SStefano Zampini if (!conforming) { 5215f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done)); 5225f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&lGt)); 52362b0c6f7SStefano Zampini } 5245f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroRows(lGe,cum,marks,0.,NULL,NULL)); 525637e8532SStefano Zampini 526b03ebc13SStefano Zampini /* identify splitpoints and corner candidates */ 5275f80ce2aSJacob Faibussowitsch CHKERRQ(MatTranspose(lGe,MAT_INITIAL_MATRIX,&lGt)); 528a13144ffSStefano Zampini if (print) { 5295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)lGe,"edgerestr_lG")); 5305f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(lGe,NULL)); 5315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)lGt,"edgerestr_lGt")); 5325f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(lGt,NULL)); 533a13144ffSStefano Zampini } 5345f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 5355f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJGetArray(lGt,&vals)); 536a13144ffSStefano Zampini for (i=0;i<nv;i++) { 537637e8532SStefano Zampini PetscInt ord = order, test = ii[i+1]-ii[i], vc = vcount[i]; 5387d871cd7SStefano Zampini PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE; 539b03ebc13SStefano Zampini if (!order) { /* variable order */ 540dec27d64SStefano Zampini PetscReal vorder = 0.; 541dec27d64SStefano Zampini 542dec27d64SStefano Zampini for (j=ii[i];j<ii[i+1];j++) vorder += PetscRealPart(vals[j]); 543dec27d64SStefano Zampini test = PetscFloorReal(vorder+10.*PETSC_SQRT_MACHINE_EPSILON); 5442c71b3e2SJacob Faibussowitsch PetscCheckFalse(vorder-test > PETSC_SQRT_MACHINE_EPSILON,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected value for vorder: %g (%D)",vorder,test); 545dec27d64SStefano Zampini ord = 1; 546dec27d64SStefano Zampini } 5476bdcaf15SBarry Smith PetscAssert(test%ord == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected number of edge dofs %" PetscInt_FMT " connected with nodal dof %" PetscInt_FMT " with order %" PetscInt_FMT,test,i,ord); 548637e8532SStefano Zampini for (j=ii[i];j<ii[i+1] && sneighs;j++) { 5497d871cd7SStefano Zampini if (PetscBTLookup(btbd,jj[j])) { 5507d871cd7SStefano Zampini bdir = PETSC_TRUE; 5517d871cd7SStefano Zampini break; 5527d871cd7SStefano Zampini } 553637e8532SStefano Zampini if (vc != ecount[jj[j]]) { 554637e8532SStefano Zampini sneighs = PETSC_FALSE; 555637e8532SStefano Zampini } else { 556637e8532SStefano Zampini PetscInt k,*vn = vneighs[i], *en = eneighs[jj[j]]; 557637e8532SStefano Zampini for (k=0;k<vc;k++) { 558637e8532SStefano Zampini if (vn[k] != en[k]) { 559637e8532SStefano Zampini sneighs = PETSC_FALSE; 560637e8532SStefano Zampini break; 561637e8532SStefano Zampini } 562637e8532SStefano Zampini } 563637e8532SStefano Zampini } 564637e8532SStefano Zampini } 5657d871cd7SStefano Zampini if (!sneighs || test >= 3*ord || bdir) { /* splitpoints */ 5666080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF,"SPLITPOINT %D (%D %D %D)\n",i,!sneighs,test >= 3*ord,bdir); 5675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btv,i)); 568dec27d64SStefano Zampini } else if (test == ord) { 569b03ebc13SStefano Zampini if (order == 1 || (!order && ii[i+1]-ii[i] == 1)) { 5706080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF,"ENDPOINT %D\n",i); 5715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btv,i)); 572a13144ffSStefano Zampini } else { 5736080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF,"CORNER CANDIDATE %D\n",i); 5745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btvcand,i)); 575a13144ffSStefano Zampini } 576a13144ffSStefano Zampini } 577a13144ffSStefano Zampini } 5785f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreNodeInfo(el2g,NULL,&ecount,&eneighs)); 5795f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreNodeInfo(vl2g,NULL,&vcount,&vneighs)); 5805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&btbd)); 581b03ebc13SStefano Zampini 582b03ebc13SStefano Zampini /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */ 583b03ebc13SStefano Zampini if (order != 1) { 584b03ebc13SStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF,"INSPECTING CANDIDATES\n"); 5855f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done)); 586b03ebc13SStefano Zampini for (i=0;i<nv;i++) { 587b03ebc13SStefano Zampini if (PetscBTLookup(btvcand,i)) { 588b03ebc13SStefano Zampini PetscBool found = PETSC_FALSE; 589b03ebc13SStefano Zampini for (j=ii[i];j<ii[i+1] && !found;j++) { 590b03ebc13SStefano Zampini PetscInt k,e = jj[j]; 591b03ebc13SStefano Zampini if (PetscBTLookup(bte,e)) continue; 592b03ebc13SStefano Zampini for (k=iit[e];k<iit[e+1];k++) { 593b03ebc13SStefano Zampini PetscInt v = jjt[k]; 594b03ebc13SStefano Zampini if (v != i && PetscBTLookup(btvcand,v)) { 595b03ebc13SStefano Zampini found = PETSC_TRUE; 596b03ebc13SStefano Zampini break; 597b03ebc13SStefano Zampini } 598b03ebc13SStefano Zampini } 599b03ebc13SStefano Zampini } 600b03ebc13SStefano Zampini if (!found) { 6016080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," CANDIDATE %D CLEARED\n",i); 6025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTClear(btvcand,i)); 603b03ebc13SStefano Zampini } else { 6046080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," CANDIDATE %D ACCEPTED\n",i); 605b03ebc13SStefano Zampini } 606b03ebc13SStefano Zampini } 607b03ebc13SStefano Zampini } 6085f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(lGe,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done)); 609b03ebc13SStefano Zampini } 6105f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJRestoreArray(lGt,&vals)); 6115f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 6125f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&lGe)); 613a13144ffSStefano Zampini 614a13144ffSStefano Zampini /* Get the local G^T explicitly */ 6155f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&lGt)); 6165f80ce2aSJacob Faibussowitsch CHKERRQ(MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt)); 6175f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(lGt,MAT_KEEP_NONZERO_PATTERN,PETSC_FALSE)); 618a13144ffSStefano Zampini 6194e64d54eSstefano_zampini /* Mark interior nodal dofs */ 6205f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared)); 6215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(nv,&btvi)); 622a13144ffSStefano Zampini for (i=1;i<n_neigh;i++) { 623a13144ffSStefano Zampini for (j=0;j<n_shared[i];j++) { 6245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btvi,shared[i][j])); 625a13144ffSStefano Zampini } 626a13144ffSStefano Zampini } 6275f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreInfo(vl2g,&n_neigh,&neigh,&n_shared,&shared)); 628a13144ffSStefano Zampini 629a13144ffSStefano Zampini /* communicate corners and splitpoints */ 6305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nv,&vmarks)); 6315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(sfvleaves,nv)); 6325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(sfvroots,Lv)); 633a13144ffSStefano Zampini for (i=0;i<nv;i++) if (PetscUnlikely(PetscBTLookup(btv,i))) sfvleaves[i] = 1; 634a13144ffSStefano Zampini 635a13144ffSStefano Zampini if (print) { 636a13144ffSStefano Zampini IS tbz; 637a13144ffSStefano Zampini 638a13144ffSStefano Zampini cum = 0; 639a13144ffSStefano Zampini for (i=0;i<nv;i++) 640a13144ffSStefano Zampini if (sfvleaves[i]) 641a13144ffSStefano Zampini vmarks[cum++] = i; 642a13144ffSStefano Zampini 6435f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz)); 6445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_local")); 6455f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(tbz,NULL)); 6465f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&tbz)); 647a13144ffSStefano Zampini } 648a13144ffSStefano Zampini 6495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceBegin(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM)); 6505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceEnd(sfv,MPIU_INT,sfvleaves,sfvroots,MPI_SUM)); 6515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sfv,MPIU_INT,sfvroots,sfvleaves,MPI_REPLACE)); 6525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sfv,MPIU_INT,sfvroots,sfvleaves,MPI_REPLACE)); 653a13144ffSStefano Zampini 6544e64d54eSstefano_zampini /* Zero rows of lGt corresponding to identified corners 6554e64d54eSstefano_zampini and interior nodal dofs */ 656a13144ffSStefano Zampini cum = 0; 657a13144ffSStefano Zampini for (i=0;i<nv;i++) { 658a13144ffSStefano Zampini if (sfvleaves[i]) { 659a13144ffSStefano Zampini vmarks[cum++] = i; 6605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btv,i)); 661a13144ffSStefano Zampini } 6624e64d54eSstefano_zampini if (!PetscBTLookup(btvi,i)) vmarks[cum++] = i; 663a13144ffSStefano Zampini } 6645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&btvi)); 665a13144ffSStefano Zampini if (print) { 666a13144ffSStefano Zampini IS tbz; 667a13144ffSStefano Zampini 6685f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,cum,vmarks,PETSC_COPY_VALUES,&tbz)); 6695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)tbz,"corners_to_be_zeroed_with_interior")); 6705f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(tbz,NULL)); 6715f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&tbz)); 672a13144ffSStefano Zampini } 6735f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroRows(lGt,cum,vmarks,0.,NULL,NULL)); 6745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vmarks)); 6755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfv)); 6765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(sfvleaves,sfvroots)); 677a13144ffSStefano Zampini 678a13144ffSStefano Zampini /* Recompute G */ 6795f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&lG)); 6805f80ce2aSJacob Faibussowitsch CHKERRQ(MatTranspose(lGt,MAT_INITIAL_MATRIX,&lG)); 681a13144ffSStefano Zampini if (print) { 6825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)lG,"used_lG")); 6835f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(lG,NULL)); 6845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)lGt,"used_lGt")); 6855f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(lGt,NULL)); 686a13144ffSStefano Zampini } 687a13144ffSStefano Zampini 688a13144ffSStefano Zampini /* Get primal dofs (if any) */ 689a13144ffSStefano Zampini cum = 0; 690a13144ffSStefano Zampini for (i=0;i<ne;i++) { 691a13144ffSStefano Zampini if (PetscUnlikely(PetscBTLookup(bte,i))) marks[cum++] = i; 692a13144ffSStefano Zampini } 693c2151214SStefano Zampini if (fl2g) { 6945f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(fl2g,cum,marks,marks)); 695c2151214SStefano Zampini } 6965f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm,cum,marks,PETSC_COPY_VALUES,&primals)); 697a13144ffSStefano Zampini if (print) { 6985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)primals,"prescribed_primal_dofs")); 6995f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(primals,NULL)); 700a13144ffSStefano Zampini } 7015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&bte)); 702c2151214SStefano Zampini /* TODO: what if the user passed in some of them ? */ 7035f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetPrimalVerticesLocalIS(pc,primals)); 7045f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&primals)); 705a13144ffSStefano Zampini 706a13144ffSStefano Zampini /* Compute edge connectivity */ 7075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject)lG,"econn_")); 7084222ddf1SHong Zhang 7094222ddf1SHong Zhang /* Symbolic conn = lG*lGt */ 7105f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductCreate(lG,lGt,NULL,&conn)); 7115f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSetType(conn,MATPRODUCT_AB)); 7125f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSetAlgorithm(conn,"default")); 7135f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSetFill(conn,PETSC_DEFAULT)); 7145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject)conn,"econn_")); 7155f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSetFromOptions(conn)); 7165f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSymbolic(conn)); 7174222ddf1SHong Zhang 7185f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 719c2151214SStefano Zampini if (fl2g) { 720c2151214SStefano Zampini PetscBT btf; 721c2151214SStefano Zampini PetscInt *iia,*jja,*iiu,*jju; 722c2151214SStefano Zampini PetscBool rest = PETSC_FALSE,free = PETSC_FALSE; 723c2151214SStefano Zampini 724c2151214SStefano Zampini /* create CSR for all local dofs */ 7255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n+1,&iia)); 726c2151214SStefano Zampini if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */ 7272c71b3e2SJacob Faibussowitsch PetscCheckFalse(pcbddc->mat_graph->nvtxs_csr != n,PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid size of CSR graph %D. Should be %D",pcbddc->mat_graph->nvtxs_csr,n); 728c2151214SStefano Zampini iiu = pcbddc->mat_graph->xadj; 729c2151214SStefano Zampini jju = pcbddc->mat_graph->adjncy; 730c2151214SStefano Zampini } else if (pcbddc->use_local_adj) { 731c2151214SStefano Zampini rest = PETSC_TRUE; 7325f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done)); 733c2151214SStefano Zampini } else { 734c2151214SStefano Zampini free = PETSC_TRUE; 7355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(n+1,&iiu,n,&jju)); 736c2151214SStefano Zampini iiu[0] = 0; 737c2151214SStefano Zampini for (i=0;i<n;i++) { 738c2151214SStefano Zampini iiu[i+1] = i+1; 739c2151214SStefano Zampini jju[i] = -1; 740d904f53bSStefano Zampini } 741c2151214SStefano Zampini } 742c2151214SStefano Zampini 743c2151214SStefano Zampini /* import sizes of CSR */ 744c2151214SStefano Zampini iia[0] = 0; 745c2151214SStefano Zampini for (i=0;i<n;i++) iia[i+1] = iiu[i+1]-iiu[i]; 746c2151214SStefano Zampini 747c2151214SStefano Zampini /* overwrite entries corresponding to the Nedelec field */ 7485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(n,&btf)); 7495f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(nedfieldlocal,&idxs)); 750c2151214SStefano Zampini for (i=0;i<ne;i++) { 7515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btf,idxs[i])); 752c2151214SStefano Zampini iia[idxs[i]+1] = ii[i+1]-ii[i]; 753c2151214SStefano Zampini } 754c2151214SStefano Zampini 755c2151214SStefano Zampini /* iia in CSR */ 756c2151214SStefano Zampini for (i=0;i<n;i++) iia[i+1] += iia[i]; 757c2151214SStefano Zampini 758c2151214SStefano Zampini /* jja in CSR */ 7595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(iia[n],&jja)); 760c2151214SStefano Zampini for (i=0;i<n;i++) 761c2151214SStefano Zampini if (!PetscBTLookup(btf,i)) 762c2151214SStefano Zampini for (j=0;j<iiu[i+1]-iiu[i];j++) 763c2151214SStefano Zampini jja[iia[i]+j] = jju[iiu[i]+j]; 764c2151214SStefano Zampini 765c2151214SStefano Zampini /* map edge dofs connectivity */ 7661e0482f5SStefano Zampini if (jj) { 7675f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(fl2g,ii[ne],jj,(PetscInt *)jj)); 768c2151214SStefano Zampini for (i=0;i<ne;i++) { 769c2151214SStefano Zampini PetscInt e = idxs[i]; 770c2151214SStefano Zampini for (j=0;j<ii[i+1]-ii[i];j++) jja[iia[e]+j] = jj[ii[i]+j]; 771c2151214SStefano Zampini } 7721e0482f5SStefano Zampini } 7735f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(nedfieldlocal,&idxs)); 7745f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetLocalAdjacencyGraph(pc,n,iia,jja,PETSC_OWN_POINTER)); 775c2151214SStefano Zampini if (rest) { 7765f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&i,(const PetscInt**)&iiu,(const PetscInt**)&jju,&done)); 777c2151214SStefano Zampini } 778c2151214SStefano Zampini if (free) { 7795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(iiu,jju)); 780c2151214SStefano Zampini } 7815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&btf)); 782c2151214SStefano Zampini } else { 7835f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetLocalAdjacencyGraph(pc,n,ii,jj,PETSC_USE_POINTER)); 784c2151214SStefano Zampini } 785c2151214SStefano Zampini 786a13144ffSStefano Zampini /* Analyze interface for edge dofs */ 7875f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCAnalyzeInterface(pc)); 788213b8bfaSStefano Zampini pcbddc->mat_graph->twodim = PETSC_FALSE; 789a13144ffSStefano Zampini 790a13144ffSStefano Zampini /* Get coarse edges in the edge space */ 7915f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals)); 7925f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(conn,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 793a13144ffSStefano Zampini 794c2151214SStefano Zampini if (fl2g) { 7955f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals)); 7965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nee,&eedges)); 797c2151214SStefano Zampini for (i=0;i<nee;i++) { 7985f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i])); 799c2151214SStefano Zampini } 800c2151214SStefano Zampini } else { 801c2151214SStefano Zampini eedges = alleedges; 802c2151214SStefano Zampini primals = allprimals; 803c2151214SStefano Zampini } 804c2151214SStefano Zampini 805a13144ffSStefano Zampini /* Mark fine edge dofs with their coarse edge id */ 8065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(marks,ne)); 8075f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(primals,&cum)); 8085f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(primals,&idxs)); 809c2151214SStefano Zampini for (i=0;i<cum;i++) marks[idxs[i]] = nee+1; 8105f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(primals,&idxs)); 811c2151214SStefano Zampini if (print) { 8125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs")); 8135f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(primals,NULL)); 814c2151214SStefano Zampini } 815c2151214SStefano Zampini 816c2151214SStefano Zampini maxsize = 0; 817a13144ffSStefano Zampini for (i=0;i<nee;i++) { 818a13144ffSStefano Zampini PetscInt size,mark = i+1; 819a13144ffSStefano Zampini 8205f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(eedges[i],&size)); 8215f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(eedges[i],&idxs)); 822a13144ffSStefano Zampini for (j=0;j<size;j++) marks[idxs[j]] = mark; 8235f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(eedges[i],&idxs)); 824a13144ffSStefano Zampini maxsize = PetscMax(maxsize,size); 825a13144ffSStefano Zampini } 826a13144ffSStefano Zampini 827a13144ffSStefano Zampini /* Find coarse edge endpoints */ 8285f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 8295f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done)); 830a13144ffSStefano Zampini for (i=0;i<nee;i++) { 831a13144ffSStefano Zampini PetscInt mark = i+1,size; 832a13144ffSStefano Zampini 8335f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(eedges[i],&size)); 8341e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 835*28b400f6SJacob Faibussowitsch PetscCheck(size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i); 8365f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(eedges[i],&idxs)); 837a13144ffSStefano Zampini if (print) { 8385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"ENDPOINTS ANALYSIS EDGE %D\n",i)); 8395f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(eedges[i],NULL)); 840a13144ffSStefano Zampini } 841a13144ffSStefano Zampini for (j=0;j<size;j++) { 842a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 8436080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," idx %D\n",ee); 844a13144ffSStefano Zampini for (k=ii[ee];k<ii[ee+1];k++) { 8456080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," inspect %D\n",jj[k]); 846a13144ffSStefano Zampini if (PetscBTLookup(btv,jj[k])) { 8476080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," corner found (already set) %D\n",jj[k]); 848a13144ffSStefano Zampini } else if (PetscBTLookup(btvcand,jj[k])) { /* is it ok? */ 849a13144ffSStefano Zampini PetscInt k2; 850a13144ffSStefano Zampini PetscBool corner = PETSC_FALSE; 851a13144ffSStefano Zampini for (k2 = iit[jj[k]];k2 < iit[jj[k]+1];k2++) { 8526080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," INSPECTING %D: mark %D (ref mark %D), boundary %D\n",jjt[k2],marks[jjt[k2]],mark,!!PetscBTLookup(btb,jjt[k2])); 853c2151214SStefano Zampini /* it's a corner if either is connected with an edge dof belonging to a different cc or 854c2151214SStefano Zampini if the edge dof lie on the natural part of the boundary */ 855c2151214SStefano Zampini if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb,jjt[k2]))) { 856a13144ffSStefano Zampini corner = PETSC_TRUE; 857a13144ffSStefano Zampini break; 858a13144ffSStefano Zampini } 859a13144ffSStefano Zampini } 860a13144ffSStefano Zampini if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */ 8616080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," corner found %D\n",jj[k]); 8625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btv,jj[k])); 863a13144ffSStefano Zampini } else { 864a13144ffSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," no corners found\n"); 865a13144ffSStefano Zampini } 866a13144ffSStefano Zampini } 867a13144ffSStefano Zampini } 868a13144ffSStefano Zampini } 8695f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(eedges[i],&idxs)); 870a13144ffSStefano Zampini } 8715f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done)); 8725f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 8735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&btb)); 874a13144ffSStefano Zampini 875a13144ffSStefano Zampini /* Reset marked primal dofs */ 8765f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(primals,&cum)); 8775f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(primals,&idxs)); 878a13144ffSStefano Zampini for (i=0;i<cum;i++) marks[idxs[i]] = 0; 8795f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(primals,&idxs)); 880a13144ffSStefano Zampini 8810569b399SStefano Zampini /* Now use the initial lG */ 8825f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&lG)); 8835f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&lGt)); 8840569b399SStefano Zampini lG = lGinit; 8855f80ce2aSJacob Faibussowitsch CHKERRQ(MatTranspose(lG,MAT_INITIAL_MATRIX,&lGt)); 8860569b399SStefano Zampini 887a13144ffSStefano Zampini /* Compute extended cols indices */ 8885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(nv,&btvc)); 8895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(nee,&bter)); 8905f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 8915f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJGetMaxRowNonzeros(lG,&i)); 892a13144ffSStefano Zampini i *= maxsize; 8935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(nee,&extcols)); 8945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(i,&extrow,i,&gidxs)); 895a13144ffSStefano Zampini eerr = PETSC_FALSE; 896a13144ffSStefano Zampini for (i=0;i<nee;i++) { 897b03ebc13SStefano Zampini PetscInt size,found = 0; 898a13144ffSStefano Zampini 899a13144ffSStefano Zampini cum = 0; 9005f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(eedges[i],&size)); 9011e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 902*28b400f6SJacob Faibussowitsch PetscCheck(size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i); 9035f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(eedges[i],&idxs)); 9045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTMemzero(nv,btvc)); 905a13144ffSStefano Zampini for (j=0;j<size;j++) { 906a13144ffSStefano Zampini PetscInt k,ee = idxs[j]; 907b03ebc13SStefano Zampini for (k=ii[ee];k<ii[ee+1];k++) { 908b03ebc13SStefano Zampini PetscInt vv = jj[k]; 909b03ebc13SStefano Zampini if (!PetscBTLookup(btv,vv)) extrow[cum++] = vv; 910b03ebc13SStefano Zampini else if (!PetscBTLookupSet(btvc,vv)) found++; 911b03ebc13SStefano Zampini } 912a13144ffSStefano Zampini } 9135f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(eedges[i],&idxs)); 9145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortRemoveDupsInt(&cum,extrow)); 9155f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs)); 9165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortIntWithArray(cum,gidxs,extrow)); 9175f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i])); 918a13144ffSStefano Zampini /* it may happen that endpoints are not defined at this point 919a13144ffSStefano Zampini if it is the case, mark this edge for a second pass */ 920b03ebc13SStefano Zampini if (cum != size -1 || found != 2) { 9215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(bter,i)); 922a13144ffSStefano Zampini if (print) { 9235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)eedges[i],"error_edge")); 9245f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(eedges[i],NULL)); 9255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)extcols[i],"error_extcol")); 9265f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(extcols[i],NULL)); 927a13144ffSStefano Zampini } 928a13144ffSStefano Zampini eerr = PETSC_TRUE; 929a13144ffSStefano Zampini } 930a13144ffSStefano Zampini } 931*28b400f6SJacob Faibussowitsch /* PetscCheck(!eerr,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */ 9325f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&eerr,&done,1,MPIU_BOOL,MPI_LOR,comm)); 933a13144ffSStefano Zampini if (done) { 934a13144ffSStefano Zampini PetscInt *newprimals; 935a13144ffSStefano Zampini 9365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(ne,&newprimals)); 9375f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(primals,&cum)); 9385f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(primals,&idxs)); 9395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(newprimals,idxs,cum)); 9405f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(primals,&idxs)); 9415f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done)); 9426080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF,"DOING SECOND PASS (eerr %D)\n",eerr); 943a13144ffSStefano Zampini for (i=0;i<nee;i++) { 944b03ebc13SStefano Zampini PetscBool has_candidates = PETSC_FALSE; 945b03ebc13SStefano Zampini if (PetscBTLookup(bter,i)) { 946a13144ffSStefano Zampini PetscInt size,mark = i+1; 947a13144ffSStefano Zampini 9485f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(eedges[i],&size)); 9495f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(eedges[i],&idxs)); 950c2151214SStefano Zampini /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */ 951a13144ffSStefano Zampini for (j=0;j<size;j++) { 952a13144ffSStefano Zampini PetscInt k,ee = idxs[j]; 9536080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF,"Inspecting edge dof %D [%D %D)\n",ee,ii[ee],ii[ee+1]); 954a13144ffSStefano Zampini for (k=ii[ee];k<ii[ee+1];k++) { 955a13144ffSStefano Zampini /* set all candidates located on the edge as corners */ 956a13144ffSStefano Zampini if (PetscBTLookup(btvcand,jj[k])) { 957a13144ffSStefano Zampini PetscInt k2,vv = jj[k]; 958b03ebc13SStefano Zampini has_candidates = PETSC_TRUE; 9596080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," Candidate set to vertex %D\n",vv); 9605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btv,vv)); 961a13144ffSStefano Zampini /* set all edge dofs connected to candidate as primals */ 962a13144ffSStefano Zampini for (k2=iit[vv];k2<iit[vv+1];k2++) { 963a13144ffSStefano Zampini if (marks[jjt[k2]] == mark) { 964a13144ffSStefano Zampini PetscInt k3,ee2 = jjt[k2]; 9656080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," Connected edge dof set to primal %D\n",ee2); 966a13144ffSStefano Zampini newprimals[cum++] = ee2; 967a13144ffSStefano Zampini /* finally set the new corners */ 968a13144ffSStefano Zampini for (k3=ii[ee2];k3<ii[ee2+1];k3++) { 9696080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," Connected nodal dof set to vertex %D\n",jj[k3]); 9705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btv,jj[k3])); 971a13144ffSStefano Zampini } 972a13144ffSStefano Zampini } 973a13144ffSStefano Zampini } 974b03ebc13SStefano Zampini } else { 9756080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," Not a candidate vertex %D\n",jj[k]); 976a13144ffSStefano Zampini } 977a13144ffSStefano Zampini } 978a13144ffSStefano Zampini } 979b03ebc13SStefano Zampini if (!has_candidates) { /* circular edge */ 980b03ebc13SStefano Zampini PetscInt k, ee = idxs[0],*tmarks; 981b03ebc13SStefano Zampini 9825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(ne,&tmarks)); 9836080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," Circular edge %D\n",i); 984b03ebc13SStefano Zampini for (k=ii[ee];k<ii[ee+1];k++) { 985b03ebc13SStefano Zampini PetscInt k2; 9866080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," Set to corner %D\n",jj[k]); 9875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btv,jj[k])); 988b03ebc13SStefano Zampini for (k2=iit[jj[k]];k2<iit[jj[k]+1];k2++) tmarks[jjt[k2]]++; 989b03ebc13SStefano Zampini } 990b03ebc13SStefano Zampini for (j=0;j<size;j++) { 991b03ebc13SStefano Zampini if (tmarks[idxs[j]] > 1) { 9926080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF," Edge dof set to primal %D\n",idxs[j]); 993b03ebc13SStefano Zampini newprimals[cum++] = idxs[j]; 994b03ebc13SStefano Zampini } 995b03ebc13SStefano Zampini } 9965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(tmarks)); 997b03ebc13SStefano Zampini } 9985f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(eedges[i],&idxs)); 999a13144ffSStefano Zampini } 10005f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&extcols[i])); 1001a13144ffSStefano Zampini } 10025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(extcols)); 10035f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&iit,&jjt,&done)); 10045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortRemoveDupsInt(&cum,newprimals)); 1005c2151214SStefano Zampini if (fl2g) { 10065f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(fl2g,cum,newprimals,newprimals)); 10075f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&primals)); 1008c2151214SStefano Zampini for (i=0;i<nee;i++) { 10095f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&eedges[i])); 1010c2151214SStefano Zampini } 10115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(eedges)); 1012c2151214SStefano Zampini } 10135f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals)); 10145f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm,cum,newprimals,PETSC_COPY_VALUES,&primals)); 10155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(newprimals)); 10165f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetPrimalVerticesLocalIS(pc,primals)); 10175f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&primals)); 10185f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCAnalyzeInterface(pc)); 1019213b8bfaSStefano Zampini pcbddc->mat_graph->twodim = PETSC_FALSE; 10205f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals)); 1021c2151214SStefano Zampini if (fl2g) { 10225f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,allprimals,&primals)); 10235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nee,&eedges)); 1024c2151214SStefano Zampini for (i=0;i<nee;i++) { 10255f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApplyIS(fl2g,IS_GTOLM_DROP,alleedges[i],&eedges[i])); 1026c2151214SStefano Zampini } 1027c2151214SStefano Zampini } else { 1028c2151214SStefano Zampini eedges = alleedges; 1029c2151214SStefano Zampini primals = allprimals; 1030c2151214SStefano Zampini } 10315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(nee,&extcols)); 1032a13144ffSStefano Zampini 1033a13144ffSStefano Zampini /* Mark again */ 10345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(marks,ne)); 1035a13144ffSStefano Zampini for (i=0;i<nee;i++) { 1036a13144ffSStefano Zampini PetscInt size,mark = i+1; 1037a13144ffSStefano Zampini 10385f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(eedges[i],&size)); 10395f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(eedges[i],&idxs)); 1040a13144ffSStefano Zampini for (j=0;j<size;j++) marks[idxs[j]] = mark; 10415f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(eedges[i],&idxs)); 1042a13144ffSStefano Zampini } 1043a13144ffSStefano Zampini if (print) { 10445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)primals,"obtained_primal_dofs_secondpass")); 10455f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(primals,NULL)); 1046a13144ffSStefano Zampini } 1047a13144ffSStefano Zampini 1048a13144ffSStefano Zampini /* Recompute extended cols */ 1049a13144ffSStefano Zampini eerr = PETSC_FALSE; 1050a13144ffSStefano Zampini for (i=0;i<nee;i++) { 1051a13144ffSStefano Zampini PetscInt size; 1052a13144ffSStefano Zampini 1053a13144ffSStefano Zampini cum = 0; 10545f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(eedges[i],&size)); 10551e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 1056*28b400f6SJacob Faibussowitsch PetscCheck(size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i); 10575f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(eedges[i],&idxs)); 1058a13144ffSStefano Zampini for (j=0;j<size;j++) { 1059a13144ffSStefano Zampini PetscInt k,ee = idxs[j]; 10601e0482f5SStefano Zampini for (k=ii[ee];k<ii[ee+1];k++) if (!PetscBTLookup(btv,jj[k])) extrow[cum++] = jj[k]; 1061a13144ffSStefano Zampini } 10625f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(eedges[i],&idxs)); 10635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortRemoveDupsInt(&cum,extrow)); 10645f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(vl2g,cum,extrow,gidxs)); 10655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortIntWithArray(cum,gidxs,extrow)); 10665f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,cum,extrow,PETSC_COPY_VALUES,&extcols[i])); 1067a13144ffSStefano Zampini if (cum != size -1) { 1068a13144ffSStefano Zampini if (print) { 10695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)eedges[i],"error_edge_secondpass")); 10705f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(eedges[i],NULL)); 10715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)extcols[i],"error_extcol_secondpass")); 10725f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(extcols[i],NULL)); 1073a13144ffSStefano Zampini } 1074a13144ffSStefano Zampini eerr = PETSC_TRUE; 1075a13144ffSStefano Zampini } 1076a13144ffSStefano Zampini } 1077a13144ffSStefano Zampini } 10785f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 10795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(extrow,gidxs)); 10805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&bter)); 10815f80ce2aSJacob Faibussowitsch if (print) CHKERRQ(PCBDDCGraphASCIIView(pcbddc->mat_graph,5,PETSC_VIEWER_STDOUT_SELF)); 1082a13144ffSStefano Zampini /* an error should not occur at this point */ 1083*28b400f6SJacob Faibussowitsch PetscCheck(!eerr,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL SECOND PASS"); 1084a13144ffSStefano Zampini 10854e64d54eSstefano_zampini /* Check the number of endpoints */ 10865f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 10875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(2*nee,&corners)); 10885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nee,&cedges)); 10894e64d54eSstefano_zampini for (i=0;i<nee;i++) { 1090b03ebc13SStefano Zampini PetscInt size, found = 0, gc[2]; 10914e64d54eSstefano_zampini 1092b03ebc13SStefano Zampini /* init with defaults */ 1093b03ebc13SStefano Zampini cedges[i] = corners[i*2] = corners[i*2+1] = -1; 10945f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(eedges[i],&size)); 10951e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 1096*28b400f6SJacob Faibussowitsch PetscCheck(size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected zero sized edge %D",i); 10975f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(eedges[i],&idxs)); 10985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTMemzero(nv,btvc)); 10994e64d54eSstefano_zampini for (j=0;j<size;j++) { 11004e64d54eSstefano_zampini PetscInt k,ee = idxs[j]; 11014e64d54eSstefano_zampini for (k=ii[ee];k<ii[ee+1];k++) { 11024e64d54eSstefano_zampini PetscInt vv = jj[k]; 11034e64d54eSstefano_zampini if (PetscBTLookup(btv,vv) && !PetscBTLookupSet(btvc,vv)) { 11042c71b3e2SJacob Faibussowitsch PetscCheckFalse(found == 2,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found more then two corners for edge %D",i); 1105b03ebc13SStefano Zampini corners[i*2+found++] = vv; 11064e64d54eSstefano_zampini } 11074e64d54eSstefano_zampini } 11084e64d54eSstefano_zampini } 1109b03ebc13SStefano Zampini if (found != 2) { 1110b03ebc13SStefano Zampini PetscInt e; 1111b03ebc13SStefano Zampini if (fl2g) { 11125f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(fl2g,1,idxs,&e)); 1113b03ebc13SStefano Zampini } else { 1114b03ebc13SStefano Zampini e = idxs[0]; 1115b03ebc13SStefano Zampini } 111698921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Found %D corners for edge %D (astart %D, estart %D)",found,i,e,idxs[0]); 1117b03ebc13SStefano Zampini } 1118eee23b56SStefano Zampini 1119eee23b56SStefano Zampini /* get primal dof index on this coarse edge */ 11205f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(vl2g,2,corners+2*i,gc)); 1121b03ebc13SStefano Zampini if (gc[0] > gc[1]) { 1122b03ebc13SStefano Zampini PetscInt swap = corners[2*i]; 1123b03ebc13SStefano Zampini corners[2*i] = corners[2*i+1]; 1124b03ebc13SStefano Zampini corners[2*i+1] = swap; 1125b03ebc13SStefano Zampini } 1126eee23b56SStefano Zampini cedges[i] = idxs[size-1]; 11275f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(eedges[i],&idxs)); 11286080607fSStefano Zampini if (print) PetscPrintf(PETSC_COMM_SELF,"EDGE %D: ce %D, corners (%D,%D)\n",i,cedges[i],corners[2*i],corners[2*i+1]); 11294e64d54eSstefano_zampini } 11305f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(lG,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 11315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&btvc)); 11324e64d54eSstefano_zampini 113376bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 1134a13144ffSStefano Zampini /* Inspects columns of lG (rows of lGt) and make sure the change of basis will 1135a13144ffSStefano Zampini not interfere with neighbouring coarse edges */ 11365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nee+1,&emarks)); 11375f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 1138a13144ffSStefano Zampini for (i=0;i<nv;i++) { 1139a13144ffSStefano Zampini PetscInt emax = 0,eemax = 0; 1140a13144ffSStefano Zampini 1141a13144ffSStefano Zampini if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue; 11425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(emarks,nee+1)); 1143a13144ffSStefano Zampini for (j=ii[i];j<ii[i+1];j++) emarks[marks[jj[j]]]++; 1144a13144ffSStefano Zampini for (j=1;j<nee+1;j++) { 1145a13144ffSStefano Zampini if (emax < emarks[j]) { 1146a13144ffSStefano Zampini emax = emarks[j]; 1147a13144ffSStefano Zampini eemax = j; 1148a13144ffSStefano Zampini } 1149a13144ffSStefano Zampini } 1150a13144ffSStefano Zampini /* not relevant for edges */ 1151a13144ffSStefano Zampini if (!eemax) continue; 1152a13144ffSStefano Zampini 1153a13144ffSStefano Zampini for (j=ii[i];j<ii[i+1];j++) { 1154a13144ffSStefano Zampini if (marks[jj[j]] && marks[jj[j]] != eemax) { 115598921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Found 2 coarse edges (id %D and %D) connected through the %D nodal dof at edge dof %D",marks[jj[j]]-1,eemax,i,jj[j]); 1156a13144ffSStefano Zampini } 1157a13144ffSStefano Zampini } 1158a13144ffSStefano Zampini } 11595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(emarks)); 11605f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 116176bd3646SJed Brown } 1162a13144ffSStefano Zampini 1163a13144ffSStefano Zampini /* Compute extended rows indices for edge blocks of the change of basis */ 11645f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 11655f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJGetMaxRowNonzeros(lGt,&extmem)); 1166a13144ffSStefano Zampini extmem *= maxsize; 11675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(extmem*nee,&extrow)); 11685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nee,&extrows)); 11695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(nee,&extrowcum)); 1170a13144ffSStefano Zampini for (i=0;i<nv;i++) { 1171a13144ffSStefano Zampini PetscInt mark = 0,size,start; 1172213b8bfaSStefano Zampini 1173a13144ffSStefano Zampini if (ii[i+1]==ii[i] || PetscBTLookup(btv,i)) continue; 1174a13144ffSStefano Zampini for (j=ii[i];j<ii[i+1];j++) 1175a13144ffSStefano Zampini if (marks[jj[j]] && !mark) 1176a13144ffSStefano Zampini mark = marks[jj[j]]; 1177a13144ffSStefano Zampini 1178a13144ffSStefano Zampini /* not relevant */ 1179a13144ffSStefano Zampini if (!mark) continue; 1180a13144ffSStefano Zampini 1181a13144ffSStefano Zampini /* import extended row */ 1182a13144ffSStefano Zampini mark--; 1183a13144ffSStefano Zampini start = mark*extmem+extrowcum[mark]; 1184a13144ffSStefano Zampini size = ii[i+1]-ii[i]; 11852c71b3e2SJacob Faibussowitsch PetscCheckFalse(extrowcum[mark] + size > extmem,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not enough memory allocated %D > %D",extrowcum[mark] + size,extmem); 11865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(extrow+start,jj+ii[i],size)); 1187a13144ffSStefano Zampini extrowcum[mark] += size; 1188a13144ffSStefano Zampini } 11895f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(lGt,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&done)); 11905f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&lGt)); 11915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(marks)); 1192213b8bfaSStefano Zampini 1193213b8bfaSStefano Zampini /* Compress extrows */ 1194a13144ffSStefano Zampini cum = 0; 1195a13144ffSStefano Zampini for (i=0;i<nee;i++) { 1196a13144ffSStefano Zampini PetscInt size = extrowcum[i],*start = extrow + i*extmem; 11975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortRemoveDupsInt(&size,start)); 11985f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,size,start,PETSC_USE_POINTER,&extrows[i])); 1199a13144ffSStefano Zampini cum = PetscMax(cum,size); 1200a13144ffSStefano Zampini } 12015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(extrowcum)); 12025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&btv)); 12035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&btvcand)); 1204a13144ffSStefano Zampini 1205a13144ffSStefano Zampini /* Workspace for lapack inner calls and VecSetValues */ 12065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2((5+cum+maxsize)*maxsize,&work,maxsize,&rwork)); 1207a13144ffSStefano Zampini 1208a13144ffSStefano Zampini /* Create change of basis matrix (preallocation can be improved) */ 12095f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(comm,&T)); 1210c2151214SStefano Zampini ierr = MatSetSizes(T,pc->pmat->rmap->n,pc->pmat->rmap->n, 1211c2151214SStefano Zampini pc->pmat->rmap->N,pc->pmat->rmap->N);CHKERRQ(ierr); 12125f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(T,MATAIJ)); 12135f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJSetPreallocation(T,10,NULL)); 12145f80ce2aSJacob Faibussowitsch CHKERRQ(MatMPIAIJSetPreallocation(T,10,NULL,10,NULL)); 12155f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetLocalToGlobalMapping(T,al2g,al2g)); 12165f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(T,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE)); 12175f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(T,MAT_ROW_ORIENTED,PETSC_FALSE)); 12185f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&al2g)); 1219a13144ffSStefano Zampini 1220a13144ffSStefano Zampini /* Defaults to identity */ 12215f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(pc->pmat,&tvec,NULL)); 12225f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(tvec,1.0)); 12235f80ce2aSJacob Faibussowitsch CHKERRQ(MatDiagonalSet(T,tvec,INSERT_VALUES)); 12245f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&tvec)); 1225a13144ffSStefano Zampini 12261e0482f5SStefano Zampini /* Create discrete gradient for the coarser level if needed */ 12275f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->nedcG)); 12285f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->nedclocal)); 12291e0482f5SStefano Zampini if (pcbddc->current_level < pcbddc->max_levels) { 12301e0482f5SStefano Zampini ISLocalToGlobalMapping cel2g,cvl2g; 12311e0482f5SStefano Zampini IS wis,gwis; 12321e0482f5SStefano Zampini PetscInt cnv,cne; 12331e0482f5SStefano Zampini 12345f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm,nee,cedges,PETSC_COPY_VALUES,&wis)); 12351e0482f5SStefano Zampini if (fl2g) { 12365f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApplyIS(fl2g,wis,&pcbddc->nedclocal)); 12371e0482f5SStefano Zampini } else { 12385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)wis)); 12391e0482f5SStefano Zampini pcbddc->nedclocal = wis; 12401e0482f5SStefano Zampini } 12415f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApplyIS(el2g,wis,&gwis)); 12425f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&wis)); 12435f80ce2aSJacob Faibussowitsch CHKERRQ(ISRenumber(gwis,NULL,&cne,&wis)); 12445f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(wis,&cel2g)); 12455f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&wis)); 12465f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&gwis)); 12471e0482f5SStefano Zampini 12485f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm,2*nee,corners,PETSC_USE_POINTER,&wis)); 12495f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApplyIS(vl2g,wis,&gwis)); 12505f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&wis)); 12515f80ce2aSJacob Faibussowitsch CHKERRQ(ISRenumber(gwis,NULL,&cnv,&wis)); 12525f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(wis,&cvl2g)); 12535f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&wis)); 12545f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&gwis)); 12551e0482f5SStefano Zampini 12565f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(comm,&pcbddc->nedcG)); 12575f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(pcbddc->nedcG,PETSC_DECIDE,PETSC_DECIDE,cne,cnv)); 12585f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(pcbddc->nedcG,MATAIJ)); 12595f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJSetPreallocation(pcbddc->nedcG,2,NULL)); 12605f80ce2aSJacob Faibussowitsch CHKERRQ(MatMPIAIJSetPreallocation(pcbddc->nedcG,2,NULL,2,NULL)); 12615f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetLocalToGlobalMapping(pcbddc->nedcG,cel2g,cvl2g)); 12625f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&cel2g)); 12635f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&cvl2g)); 12641e0482f5SStefano Zampini } 12655f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&vl2g)); 12661e0482f5SStefano Zampini 12671e0482f5SStefano Zampini #if defined(PRINT_GDET) 12681e0482f5SStefano Zampini inc = 0; 12691e0482f5SStefano Zampini lev = pcbddc->current_level; 12701e0482f5SStefano Zampini #endif 1271213b8bfaSStefano Zampini 1272213b8bfaSStefano Zampini /* Insert values in the change of basis matrix */ 1273a13144ffSStefano Zampini for (i=0;i<nee;i++) { 1274a13144ffSStefano Zampini Mat Gins = NULL, GKins = NULL; 12751e0482f5SStefano Zampini IS cornersis = NULL; 12761e0482f5SStefano Zampini PetscScalar cvals[2]; 1277a13144ffSStefano Zampini 12781e0482f5SStefano Zampini if (pcbddc->nedcG) { 12795f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,2,corners+2*i,PETSC_USE_POINTER,&cornersis)); 12801e0482f5SStefano Zampini } 12815f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCComputeNedelecChangeEdge(lG,eedges[i],extrows[i],extcols[i],cornersis,&Gins,&GKins,cvals,work,rwork)); 1282a13144ffSStefano Zampini if (Gins && GKins) { 12831683a169SBarry Smith const PetscScalar *data; 1284a13144ffSStefano Zampini const PetscInt *rows,*cols; 1285a13144ffSStefano Zampini PetscInt nrh,nch,nrc,ncc; 1286a13144ffSStefano Zampini 12875f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(eedges[i],&cols)); 1288a13144ffSStefano Zampini /* H1 */ 12895f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(extrows[i],&rows)); 12905f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(Gins,&nrh,&nch)); 12915f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(Gins,&data)); 12925f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValuesLocal(T,nrh,rows,nch,cols,data,INSERT_VALUES)); 12935f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(Gins,&data)); 12945f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(extrows[i],&rows)); 1295a13144ffSStefano Zampini /* complement */ 12965f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(GKins,&nrc,&ncc)); 1297*28b400f6SJacob Faibussowitsch PetscCheck(ncc,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Constant function has not been generated for coarse edge %D",i); 12982c71b3e2SJacob Faibussowitsch PetscCheckFalse(ncc + nch != nrc,PETSC_COMM_SELF,PETSC_ERR_PLIB,"The sum of the number of columns of GKins %D and Gins %D does not match %D for coarse edge %D",ncc,nch,nrc,i); 12992c71b3e2SJacob Faibussowitsch PetscCheckFalse(ncc != 1 && pcbddc->nedcG,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot generate the coarse discrete gradient for coarse edge %D with ncc %D",i,ncc); 13005f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(GKins,&data)); 13015f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValuesLocal(T,nrc,cols,ncc,cols+nch,data,INSERT_VALUES)); 13025f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(GKins,&data)); 13031e0482f5SStefano Zampini 13041e0482f5SStefano Zampini /* coarse discrete gradient */ 13051e0482f5SStefano Zampini if (pcbddc->nedcG) { 13061e0482f5SStefano Zampini PetscInt cols[2]; 13071e0482f5SStefano Zampini 13081e0482f5SStefano Zampini cols[0] = 2*i; 13091e0482f5SStefano Zampini cols[1] = 2*i+1; 13105f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValuesLocal(pcbddc->nedcG,1,&i,2,cols,cvals,INSERT_VALUES)); 13111e0482f5SStefano Zampini } 13125f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(eedges[i],&cols)); 1313a13144ffSStefano Zampini } 13145f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&extrows[i])); 13155f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&extcols[i])); 13165f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&cornersis)); 13175f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Gins)); 13185f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&GKins)); 1319a13144ffSStefano Zampini } 13205f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&el2g)); 1321a13144ffSStefano Zampini 1322a13144ffSStefano Zampini /* Start assembling */ 13235f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(T,MAT_FINAL_ASSEMBLY)); 13241e0482f5SStefano Zampini if (pcbddc->nedcG) { 13255f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(pcbddc->nedcG,MAT_FINAL_ASSEMBLY)); 13261e0482f5SStefano Zampini } 1327a13144ffSStefano Zampini 1328a13144ffSStefano Zampini /* Free */ 1329c2151214SStefano Zampini if (fl2g) { 13305f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&primals)); 1331c2151214SStefano Zampini for (i=0;i<nee;i++) { 13325f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&eedges[i])); 1333c2151214SStefano Zampini } 13345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(eedges)); 1335c2151214SStefano Zampini } 1336eee23b56SStefano Zampini 1337eee23b56SStefano Zampini /* hack mat_graph with primal dofs on the coarse edges */ 1338eee23b56SStefano Zampini { 1339eee23b56SStefano Zampini PCBDDCGraph graph = pcbddc->mat_graph; 1340eee23b56SStefano Zampini PetscInt *oqueue = graph->queue; 1341eee23b56SStefano Zampini PetscInt *ocptr = graph->cptr; 1342eee23b56SStefano Zampini PetscInt ncc,*idxs; 1343eee23b56SStefano Zampini 1344eee23b56SStefano Zampini /* find first primal edge */ 1345eee23b56SStefano Zampini if (pcbddc->nedclocal) { 13465f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcbddc->nedclocal,(const PetscInt**)&idxs)); 1347eee23b56SStefano Zampini } else { 1348eee23b56SStefano Zampini if (fl2g) { 13495f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(fl2g,nee,cedges,cedges)); 1350eee23b56SStefano Zampini } 1351eee23b56SStefano Zampini idxs = cedges; 1352eee23b56SStefano Zampini } 1353eee23b56SStefano Zampini cum = 0; 1354eee23b56SStefano Zampini while (cum < nee && cedges[cum] < 0) cum++; 1355eee23b56SStefano Zampini 1356eee23b56SStefano Zampini /* adapt connected components */ 13575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(graph->nvtxs+1,&graph->cptr,ocptr[graph->ncc],&graph->queue)); 1358eee23b56SStefano Zampini graph->cptr[0] = 0; 1359eee23b56SStefano Zampini for (i=0,ncc=0;i<graph->ncc;i++) { 1360eee23b56SStefano Zampini PetscInt lc = ocptr[i+1]-ocptr[i]; 1361eee23b56SStefano Zampini if (cum != nee && oqueue[ocptr[i+1]-1] == cedges[cum]) { /* this cc has a primal dof */ 1362eee23b56SStefano Zampini graph->cptr[ncc+1] = graph->cptr[ncc]+1; 1363eee23b56SStefano Zampini graph->queue[graph->cptr[ncc]] = cedges[cum]; 1364eee23b56SStefano Zampini ncc++; 1365eee23b56SStefano Zampini lc--; 1366eee23b56SStefano Zampini cum++; 1367eee23b56SStefano Zampini while (cum < nee && cedges[cum] < 0) cum++; 1368eee23b56SStefano Zampini } 1369eee23b56SStefano Zampini graph->cptr[ncc+1] = graph->cptr[ncc] + lc; 1370eee23b56SStefano Zampini for (j=0;j<lc;j++) graph->queue[graph->cptr[ncc]+j] = oqueue[ocptr[i]+j]; 1371eee23b56SStefano Zampini ncc++; 1372eee23b56SStefano Zampini } 1373eee23b56SStefano Zampini graph->ncc = ncc; 1374eee23b56SStefano Zampini if (pcbddc->nedclocal) { 13755f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcbddc->nedclocal,(const PetscInt**)&idxs)); 1376eee23b56SStefano Zampini } 13775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(ocptr,oqueue)); 1378eee23b56SStefano Zampini } 13795f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&fl2g)); 13805f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,&nee,&alleedges,&allprimals)); 13815f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphResetCSR(pcbddc->mat_graph)); 13825f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&conn)); 1383eee23b56SStefano Zampini 13845f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&nedfieldlocal)); 13855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(extrow)); 13865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(work,rwork)); 13875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(corners)); 13885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(cedges)); 13895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(extrows)); 13905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(extcols)); 13915f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&lG)); 1392a13144ffSStefano Zampini 1393a13144ffSStefano Zampini /* Complete assembling */ 13945f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(T,MAT_FINAL_ASSEMBLY)); 13951e0482f5SStefano Zampini if (pcbddc->nedcG) { 13965f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(pcbddc->nedcG,MAT_FINAL_ASSEMBLY)); 13971e0482f5SStefano Zampini #if 0 13985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G")); 13995f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(pcbddc->nedcG,NULL)); 14001e0482f5SStefano Zampini #endif 14011e0482f5SStefano Zampini } 1402a13144ffSStefano Zampini 1403a13144ffSStefano Zampini /* set change of basis */ 14045f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetChangeOfBasisMat(pc,T,singular)); 14055f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&T)); 1406a13144ffSStefano Zampini 1407a13144ffSStefano Zampini PetscFunctionReturn(0); 1408a13144ffSStefano Zampini } 1409a13144ffSStefano Zampini 1410d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights, 1411d8203eabSStefano Zampini and these can be collinear -> so cheat with MatNullSpaceCreate 1412d8203eabSStefano Zampini and create a suitable set of basis vectors first */ 1413d8203eabSStefano Zampini PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp) 1414d8203eabSStefano Zampini { 1415d8203eabSStefano Zampini PetscInt i; 1416d8203eabSStefano Zampini 1417d8203eabSStefano Zampini PetscFunctionBegin; 1418d8203eabSStefano Zampini for (i=0;i<nvecs;i++) { 1419d8203eabSStefano Zampini PetscInt first,last; 1420d8203eabSStefano Zampini 14215f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetOwnershipRange(quad_vecs[i],&first,&last)); 14222c71b3e2SJacob Faibussowitsch PetscCheckFalse(last-first < 2*nvecs && has_const,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented"); 1423d8203eabSStefano Zampini if (i>=first && i < last) { 1424d8203eabSStefano Zampini PetscScalar *data; 14255f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(quad_vecs[i],&data)); 1426d8203eabSStefano Zampini if (!has_const) { 1427d8203eabSStefano Zampini data[i-first] = 1.; 1428d8203eabSStefano Zampini } else { 142986fa73c5SStefano Zampini data[2*i-first] = 1./PetscSqrtReal(2.); 143086fa73c5SStefano Zampini data[2*i-first+1] = -1./PetscSqrtReal(2.); 1431d8203eabSStefano Zampini } 14325f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(quad_vecs[i],&data)); 1433d8203eabSStefano Zampini } 14345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectStateIncrease((PetscObject)quad_vecs[i])); 1435d8203eabSStefano Zampini } 14365f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceCreate(comm,has_const,nvecs,quad_vecs,nnsp)); 1437d8203eabSStefano Zampini for (i=0;i<nvecs;i++) { /* reset vectors */ 1438d8203eabSStefano Zampini PetscInt first,last; 14395f80ce2aSJacob Faibussowitsch CHKERRQ(VecLockReadPop(quad_vecs[i])); 14405f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetOwnershipRange(quad_vecs[i],&first,&last)); 1441d8203eabSStefano Zampini if (i>=first && i < last) { 1442d8203eabSStefano Zampini PetscScalar *data; 14435f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(quad_vecs[i],&data)); 1444d8203eabSStefano Zampini if (!has_const) { 1445d8203eabSStefano Zampini data[i-first] = 0.; 1446d8203eabSStefano Zampini } else { 144786fa73c5SStefano Zampini data[2*i-first] = 0.; 144886fa73c5SStefano Zampini data[2*i-first+1] = 0.; 1449d8203eabSStefano Zampini } 14505f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(quad_vecs[i],&data)); 1451d8203eabSStefano Zampini } 14525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectStateIncrease((PetscObject)quad_vecs[i])); 14535f80ce2aSJacob Faibussowitsch CHKERRQ(VecLockReadPush(quad_vecs[i])); 1454d8203eabSStefano Zampini } 1455d8203eabSStefano Zampini PetscFunctionReturn(0); 1456d8203eabSStefano Zampini } 1457d8203eabSStefano Zampini 14588ae0ca82SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp) 1459669cc0f4SStefano Zampini { 1460a198735bSStefano Zampini Mat loc_divudotp; 1461fa23a32eSStefano Zampini Vec p,v,vins,quad_vec,*quad_vecs; 14628ae0ca82SStefano Zampini ISLocalToGlobalMapping map; 1463669cc0f4SStefano Zampini PetscScalar *vals; 1464669cc0f4SStefano Zampini const PetscScalar *array; 14650f04eeffSStefano Zampini PetscInt i,maxneighs = 0,maxsize,*gidxs; 1466a040e873SStefano Zampini PetscInt n_neigh,*neigh,*n_shared,**shared; 14671ae86dd6SStefano Zampini PetscMPIInt rank; 1468669cc0f4SStefano Zampini 1469669cc0f4SStefano Zampini PetscFunctionBegin; 14705f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared)); 14710f04eeffSStefano Zampini for (i=0;i<n_neigh;i++) maxneighs = PetscMax(graph->count[shared[i][0]]+1,maxneighs); 14725f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(MPI_IN_PLACE,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A))); 14738037d520SStefano Zampini if (!maxneighs) { 14745f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared)); 14758037d520SStefano Zampini *nnsp = NULL; 14768037d520SStefano Zampini PetscFunctionReturn(0); 1477669cc0f4SStefano Zampini } 1478669cc0f4SStefano Zampini maxsize = 0; 1479a040e873SStefano Zampini for (i=0;i<n_neigh;i++) maxsize = PetscMax(n_shared[i],maxsize); 14805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(maxsize,&gidxs,maxsize,&vals)); 1481669cc0f4SStefano Zampini /* create vectors to hold quadrature weights */ 14825f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(A,&quad_vec,NULL)); 14838ae0ca82SStefano Zampini if (!transpose) { 14845f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalToGlobalMapping(A,&map,NULL)); 14858ae0ca82SStefano Zampini } else { 14865f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalToGlobalMapping(A,NULL,&map)); 14878ae0ca82SStefano Zampini } 14885f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs)); 14895f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&quad_vec)); 14905f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp)); 1491669cc0f4SStefano Zampini for (i=0;i<maxneighs;i++) { 14925f80ce2aSJacob Faibussowitsch CHKERRQ(VecLockReadPop(quad_vecs[i])); 1493669cc0f4SStefano Zampini } 1494d8203eabSStefano Zampini 1495669cc0f4SStefano Zampini /* compute local quad vec */ 14965f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(divudotp,&loc_divudotp)); 14978ae0ca82SStefano Zampini if (!transpose) { 14985f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(loc_divudotp,&v,&p)); 14998ae0ca82SStefano Zampini } else { 15005f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(loc_divudotp,&p,&v)); 15018ae0ca82SStefano Zampini } 15025f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(p,1.)); 15038ae0ca82SStefano Zampini if (!transpose) { 15045f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(loc_divudotp,p,v)); 15058ae0ca82SStefano Zampini } else { 15065f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(loc_divudotp,p,v)); 15078ae0ca82SStefano Zampini } 1508fa23a32eSStefano Zampini if (vl2l) { 1509187c917aSStefano Zampini Mat lA; 1510187c917aSStefano Zampini VecScatter sc; 1511187c917aSStefano Zampini 15125f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(A,&lA)); 15135f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(lA,&vins,NULL)); 15145f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterCreate(v,NULL,vins,vl2l,&sc)); 15155f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD)); 15165f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(sc,v,vins,INSERT_VALUES,SCATTER_FORWARD)); 15175f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterDestroy(&sc)); 1518fa23a32eSStefano Zampini } else { 1519fa23a32eSStefano Zampini vins = v; 1520fa23a32eSStefano Zampini } 15215f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(vins,&array)); 15225f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&p)); 15239a962809SStefano Zampini 15241ae86dd6SStefano Zampini /* insert in global quadrature vecs */ 15255f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank)); 15260f04eeffSStefano Zampini for (i=1;i<n_neigh;i++) { 1527669cc0f4SStefano Zampini const PetscInt *idxs; 1528669cc0f4SStefano Zampini PetscInt idx,nn,j; 1529669cc0f4SStefano Zampini 1530a040e873SStefano Zampini idxs = shared[i]; 1531a040e873SStefano Zampini nn = n_shared[i]; 1532669cc0f4SStefano Zampini for (j=0;j<nn;j++) vals[j] = array[idxs[j]]; 15335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx)); 1534669cc0f4SStefano Zampini idx = -(idx+1); 15352c71b3e2SJacob Faibussowitsch PetscCheckFalse(idx < 0 || idx >= maxneighs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid index %D not in [0,%D)",idx,maxneighs); 15365f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(map,nn,idxs,gidxs)); 15375f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(quad_vecs[idx],nn,gidxs,vals,INSERT_VALUES)); 1538669cc0f4SStefano Zampini } 15395f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreInfo(graph->l2gmap,&n_neigh,&neigh,&n_shared,&shared)); 15405f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(vins,&array)); 1541fa23a32eSStefano Zampini if (vl2l) { 15425f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&vins)); 1543fa23a32eSStefano Zampini } 15445f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&v)); 15455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(gidxs,vals)); 1546669cc0f4SStefano Zampini 1547669cc0f4SStefano Zampini /* assemble near null space */ 1548669cc0f4SStefano Zampini for (i=0;i<maxneighs;i++) { 15495f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(quad_vecs[i])); 1550669cc0f4SStefano Zampini } 1551669cc0f4SStefano Zampini for (i=0;i<maxneighs;i++) { 15525f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(quad_vecs[i])); 15535f80ce2aSJacob Faibussowitsch CHKERRQ(VecViewFromOptions(quad_vecs[i],NULL,"-pc_bddc_quad_vecs_view")); 15545f80ce2aSJacob Faibussowitsch CHKERRQ(VecLockReadPush(quad_vecs[i])); 1555669cc0f4SStefano Zampini } 15565f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroyVecs(maxneighs,&quad_vecs)); 1557669cc0f4SStefano Zampini PetscFunctionReturn(0); 1558669cc0f4SStefano Zampini } 1559669cc0f4SStefano Zampini 15607620a527SStefano Zampini PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv) 15617620a527SStefano Zampini { 15627620a527SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 15637620a527SStefano Zampini 15647620a527SStefano Zampini PetscFunctionBegin; 15657620a527SStefano Zampini if (primalv) { 15667620a527SStefano Zampini if (pcbddc->user_primal_vertices_local) { 15677620a527SStefano Zampini IS list[2], newp; 15687620a527SStefano Zampini 15697620a527SStefano Zampini list[0] = primalv; 15707620a527SStefano Zampini list[1] = pcbddc->user_primal_vertices_local; 15715f80ce2aSJacob Faibussowitsch CHKERRQ(ISConcatenate(PetscObjectComm((PetscObject)pc),2,list,&newp)); 15725f80ce2aSJacob Faibussowitsch CHKERRQ(ISSortRemoveDups(newp)); 15735f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&list[1])); 15747620a527SStefano Zampini pcbddc->user_primal_vertices_local = newp; 15757620a527SStefano Zampini } else { 15765f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetPrimalVerticesLocalIS(pc,primalv)); 15777620a527SStefano Zampini } 15787620a527SStefano Zampini } 15797620a527SStefano Zampini PetscFunctionReturn(0); 15807620a527SStefano Zampini } 1581669cc0f4SStefano Zampini 15821c7a958bSStefano Zampini static PetscErrorCode func_coords_private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *out, void *ctx) 15831c7a958bSStefano Zampini { 15841c7a958bSStefano Zampini PetscInt f, *comp = (PetscInt *)ctx; 15851c7a958bSStefano Zampini 15861c7a958bSStefano Zampini PetscFunctionBegin; 15871c7a958bSStefano Zampini for (f=0;f<Nf;f++) out[f] = X[*comp]; 15881c7a958bSStefano Zampini PetscFunctionReturn(0); 15891c7a958bSStefano Zampini } 1590674ae819SStefano Zampini 15911f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc) 15921f4df5f7SStefano Zampini { 15931f4df5f7SStefano Zampini PetscErrorCode ierr; 15941f4df5f7SStefano Zampini Vec local,global; 15951f4df5f7SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 15961f4df5f7SStefano Zampini Mat_IS *matis = (Mat_IS*)pc->pmat->data; 15975c5e10d6SStefano Zampini PetscBool monolithic = PETSC_FALSE; 15981f4df5f7SStefano Zampini 15991f4df5f7SStefano Zampini PetscFunctionBegin; 16005c5e10d6SStefano Zampini ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC topology options","PC");CHKERRQ(ierr); 16015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-pc_bddc_monolithic","Discard any information on dofs splitting",NULL,monolithic,&monolithic,NULL)); 16025c5e10d6SStefano Zampini ierr = PetscOptionsEnd();CHKERRQ(ierr); 16031f4df5f7SStefano Zampini /* need to convert from global to local topology information and remove references to information in global ordering */ 16045f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(pc->pmat,&global,NULL)); 16055f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(matis->A,&local,NULL)); 16065f80ce2aSJacob Faibussowitsch CHKERRQ(VecBindToCPU(global,PETSC_TRUE)); 16075f80ce2aSJacob Faibussowitsch CHKERRQ(VecBindToCPU(local,PETSC_TRUE)); 16086a8fc67bSStefano Zampini if (monolithic) { /* just get block size to properly compute vertices */ 16096a8fc67bSStefano Zampini if (pcbddc->vertex_size == 1) { 16105f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetBlockSize(pc->pmat,&pcbddc->vertex_size)); 16116a8fc67bSStefano Zampini } 16126a8fc67bSStefano Zampini goto boundary; 16136a8fc67bSStefano Zampini } 16145c5e10d6SStefano Zampini 16151f4df5f7SStefano Zampini if (pcbddc->user_provided_isfordofs) { 16161f4df5f7SStefano Zampini if (pcbddc->n_ISForDofs) { 16171f4df5f7SStefano Zampini PetscInt i; 16180c85b387SStefano Zampini 16195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal)); 16201f4df5f7SStefano Zampini for (i=0;i<pcbddc->n_ISForDofs;i++) { 16210c85b387SStefano Zampini PetscInt bs; 16220c85b387SStefano Zampini 16235f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i])); 16245f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetBlockSize(pcbddc->ISForDofs[i],&bs)); 16255f80ce2aSJacob Faibussowitsch CHKERRQ(ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs)); 16265f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->ISForDofs[i])); 16271f4df5f7SStefano Zampini } 16281f4df5f7SStefano Zampini pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs; 16291f4df5f7SStefano Zampini pcbddc->n_ISForDofs = 0; 16305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddc->ISForDofs)); 16311f4df5f7SStefano Zampini } 16321f4df5f7SStefano Zampini } else { 163321ef3d20SStefano Zampini if (!pcbddc->n_ISForDofsLocal) { /* field split not present */ 163421ef3d20SStefano Zampini DM dm; 163521ef3d20SStefano Zampini 16365f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetDM(pc->pmat, &dm)); 16374f819b78SStefano Zampini if (!dm) { 16385f80ce2aSJacob Faibussowitsch CHKERRQ(PCGetDM(pc, &dm)); 163921ef3d20SStefano Zampini } 164021ef3d20SStefano Zampini if (dm) { 164121ef3d20SStefano Zampini IS *fields; 164221ef3d20SStefano Zampini PetscInt nf,i; 16430c85b387SStefano Zampini 16445f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateFieldDecomposition(dm,&nf,NULL,&fields,NULL)); 16455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nf,&pcbddc->ISForDofsLocal)); 164621ef3d20SStefano Zampini for (i=0;i<nf;i++) { 16470c85b387SStefano Zampini PetscInt bs; 16480c85b387SStefano Zampini 16495f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGlobalToLocal(matis->rctx,global,local,fields[i],&pcbddc->ISForDofsLocal[i])); 16505f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetBlockSize(fields[i],&bs)); 16515f80ce2aSJacob Faibussowitsch CHKERRQ(ISSetBlockSize(pcbddc->ISForDofsLocal[i],bs)); 16525f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&fields[i])); 165321ef3d20SStefano Zampini } 16545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(fields)); 165521ef3d20SStefano Zampini pcbddc->n_ISForDofsLocal = nf; 165621ef3d20SStefano Zampini } else { /* See if MATIS has fields attached by the conversion from MatNest */ 165721ef3d20SStefano Zampini PetscContainer c; 165821ef3d20SStefano Zampini 16595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject)pc->pmat,"_convert_nest_lfields",(PetscObject*)&c)); 166021ef3d20SStefano Zampini if (c) { 166121ef3d20SStefano Zampini MatISLocalFields lf; 16625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscContainerGetPointer(c,(void**)&lf)); 16635f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetDofsSplittingLocal(pc,lf->nr,lf->rf)); 166421ef3d20SStefano Zampini } else { /* fallback, create the default fields if bs > 1 */ 16651f4df5f7SStefano Zampini PetscInt i, n = matis->A->rmap->n; 16665f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetBlockSize(pc->pmat,&i)); 166721ef3d20SStefano Zampini if (i > 1) { 1668986cdee1SStefano Zampini pcbddc->n_ISForDofsLocal = i; 16695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal)); 16701f4df5f7SStefano Zampini for (i=0;i<pcbddc->n_ISForDofsLocal;i++) { 16715f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i])); 16721f4df5f7SStefano Zampini } 16731f4df5f7SStefano Zampini } 167421ef3d20SStefano Zampini } 167521ef3d20SStefano Zampini } 16767a0e7b2cSstefano_zampini } else { 16777a0e7b2cSstefano_zampini PetscInt i; 16787a0e7b2cSstefano_zampini for (i=0;i<pcbddc->n_ISForDofsLocal;i++) { 16795f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->ISForDofsLocal[i])); 16807a0e7b2cSstefano_zampini } 16811f4df5f7SStefano Zampini } 1682986cdee1SStefano Zampini } 16831f4df5f7SStefano Zampini 16845c5e10d6SStefano Zampini boundary: 16851f4df5f7SStefano Zampini if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { 16865f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal)); 16877a0e7b2cSstefano_zampini } else if (pcbddc->DirichletBoundariesLocal) { 16885f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCConsistencyCheckIS(pc,MPI_LAND,&pcbddc->DirichletBoundariesLocal)); 16891f4df5f7SStefano Zampini } 16901f4df5f7SStefano Zampini if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { 16915f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal)); 16927a0e7b2cSstefano_zampini } else if (pcbddc->NeumannBoundariesLocal) { 16935f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->NeumannBoundariesLocal)); 16941f4df5f7SStefano Zampini } 16951f4df5f7SStefano Zampini if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) { 16965f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local)); 16971f4df5f7SStefano Zampini } 16985f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&global)); 16995f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&local)); 17007620a527SStefano Zampini /* detect local disconnected subdomains if requested (use matis->A) */ 17017620a527SStefano Zampini if (pcbddc->detect_disconnected) { 17027620a527SStefano Zampini IS primalv = NULL; 17037620a527SStefano Zampini PetscInt i; 17048361f951SStefano Zampini PetscBool filter = pcbddc->detect_disconnected_filter; 17057a0e7b2cSstefano_zampini 17067620a527SStefano Zampini for (i=0;i<pcbddc->n_local_subs;i++) { 17075f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->local_subs[i])); 17087620a527SStefano Zampini } 17095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddc->local_subs)); 17105f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCDetectDisconnectedComponents(pc,filter,&pcbddc->n_local_subs,&pcbddc->local_subs,&primalv)); 17115f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCAddPrimalVerticesLocalIS(pc,primalv)); 17125f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&primalv)); 17137620a527SStefano Zampini } 17147620a527SStefano Zampini /* early stage corner detection */ 17157620a527SStefano Zampini { 17167620a527SStefano Zampini DM dm; 17177620a527SStefano Zampini 17185f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetDM(pc->pmat,&dm)); 17194f819b78SStefano Zampini if (!dm) { 17205f80ce2aSJacob Faibussowitsch CHKERRQ(PCGetDM(pc,&dm)); 17214f819b78SStefano Zampini } 17227620a527SStefano Zampini if (dm) { 17237620a527SStefano Zampini PetscBool isda; 17247620a527SStefano Zampini 17255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda)); 17267620a527SStefano Zampini if (isda) { 17277620a527SStefano Zampini ISLocalToGlobalMapping l2l; 17287620a527SStefano Zampini IS corners; 17297620a527SStefano Zampini Mat lA; 17304f819b78SStefano Zampini PetscBool gl,lo; 17317620a527SStefano Zampini 17324f819b78SStefano Zampini { 17334f819b78SStefano Zampini Vec cvec; 17344f819b78SStefano Zampini const PetscScalar *coords; 17354f819b78SStefano Zampini PetscInt dof,n,cdim; 17364f819b78SStefano Zampini PetscBool memc = PETSC_TRUE; 17374f819b78SStefano Zampini 17385f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); 17395f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinates(dm,&cvec)); 17405f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(cvec,&n)); 17415f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetBlockSize(cvec,&cdim)); 17424f819b78SStefano Zampini n /= cdim; 17435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddc->mat_graph->coords)); 17445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(dof*n*cdim,&pcbddc->mat_graph->coords)); 17455f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(cvec,&coords)); 17464f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 17474f819b78SStefano Zampini memc = PETSC_FALSE; 17484f819b78SStefano Zampini #endif 17494f819b78SStefano Zampini if (dof != 1) memc = PETSC_FALSE; 17504f819b78SStefano Zampini if (memc) { 17515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(pcbddc->mat_graph->coords,coords,cdim*n*dof)); 17524f819b78SStefano Zampini } else { /* BDDC graph does not use any blocked information, we need to replicate the data */ 17534f819b78SStefano Zampini PetscReal *bcoords = pcbddc->mat_graph->coords; 17544f819b78SStefano Zampini PetscInt i, b, d; 17554f819b78SStefano Zampini 17564f819b78SStefano Zampini for (i=0;i<n;i++) { 17574f819b78SStefano Zampini for (b=0;b<dof;b++) { 17584f819b78SStefano Zampini for (d=0;d<cdim;d++) { 17594f819b78SStefano Zampini bcoords[i*dof*cdim + b*cdim + d] = PetscRealPart(coords[i*cdim+d]); 17604f819b78SStefano Zampini } 17614f819b78SStefano Zampini } 17624f819b78SStefano Zampini } 17634f819b78SStefano Zampini } 17645f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(cvec,&coords)); 17654f819b78SStefano Zampini pcbddc->mat_graph->cdim = cdim; 17664f819b78SStefano Zampini pcbddc->mat_graph->cnloc = dof*n; 17674f819b78SStefano Zampini pcbddc->mat_graph->cloc = PETSC_FALSE; 17684f819b78SStefano Zampini } 17695f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetSubdomainCornersIS(dm,&corners)); 17705f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(pc->pmat,&lA)); 17715f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalToGlobalMapping(lA,&l2l,NULL)); 17725f80ce2aSJacob Faibussowitsch CHKERRQ(MatISRestoreLocalMat(pc->pmat,&lA)); 17734f819b78SStefano Zampini lo = (PetscBool)(l2l && corners); 17745f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&lo,&gl,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc))); 17754f819b78SStefano Zampini if (gl) { /* From PETSc's DMDA */ 17767620a527SStefano Zampini const PetscInt *idx; 177772ed36d8SStefano Zampini PetscInt dof,bs,*idxout,n; 17787620a527SStefano Zampini 17795f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); 17805f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetBlockSize(l2l,&bs)); 17815f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(corners,&n)); 17825f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(corners,&idx)); 178372ed36d8SStefano Zampini if (bs == dof) { 17845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n,&idxout)); 17855f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApplyBlock(l2l,n,idx,idxout)); 178672ed36d8SStefano Zampini } else { /* the original DMDA local-to-local map have been modified */ 178772ed36d8SStefano Zampini PetscInt i,d; 178872ed36d8SStefano Zampini 17895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(dof*n,&idxout)); 179072ed36d8SStefano Zampini for (i=0;i<n;i++) for (d=0;d<dof;d++) idxout[dof*i+d] = dof*idx[i]+d; 17915f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(l2l,dof*n,idxout,idxout)); 179272ed36d8SStefano Zampini 179372ed36d8SStefano Zampini bs = 1; 179472ed36d8SStefano Zampini n *= dof; 179572ed36d8SStefano Zampini } 17965f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(corners,&idx)); 17975f80ce2aSJacob Faibussowitsch CHKERRQ(DMDARestoreSubdomainCornersIS(dm,&corners)); 17985f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateBlock(PetscObjectComm((PetscObject)pc),bs,n,idxout,PETSC_OWN_POINTER,&corners)); 17995f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCAddPrimalVerticesLocalIS(pc,corners)); 18005f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&corners)); 18011c7a958bSStefano Zampini pcbddc->corner_selected = PETSC_TRUE; 18024f819b78SStefano Zampini pcbddc->corner_selection = PETSC_TRUE; 18034f819b78SStefano Zampini } 18044f819b78SStefano Zampini if (corners) { 18055f80ce2aSJacob Faibussowitsch CHKERRQ(DMDARestoreSubdomainCornersIS(dm,&corners)); 18067620a527SStefano Zampini } 18077620a527SStefano Zampini } 18087620a527SStefano Zampini } 18097620a527SStefano Zampini } 18101c7a958bSStefano Zampini if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) { 18111c7a958bSStefano Zampini DM dm; 18121c7a958bSStefano Zampini 18135f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetDM(pc->pmat,&dm)); 18144f819b78SStefano Zampini if (!dm) { 18155f80ce2aSJacob Faibussowitsch CHKERRQ(PCGetDM(pc,&dm)); 18161c7a958bSStefano Zampini } 18174f819b78SStefano Zampini if (dm) { /* this can get very expensive, I need to find a faster alternative */ 18181c7a958bSStefano Zampini Vec vcoords; 18191c7a958bSStefano Zampini PetscSection section; 18201c7a958bSStefano Zampini PetscReal *coords; 18211c7a958bSStefano Zampini PetscInt d,cdim,nl,nf,**ctxs; 18221c7a958bSStefano Zampini PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *); 18231c7a958bSStefano Zampini 18245f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm,&cdim)); 18255f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(dm,§ion)); 18265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section,&nf)); 18275f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(dm,&vcoords)); 18285f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(vcoords,&nl)); 18295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nl*cdim,&coords)); 18305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(nf,&funcs,nf,&ctxs)); 18315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nf,&ctxs[0])); 18321c7a958bSStefano Zampini for (d=0;d<nf;d++) funcs[d] = func_coords_private; 18331c7a958bSStefano Zampini for (d=1;d<nf;d++) ctxs[d] = ctxs[d-1] + 1; 18341c7a958bSStefano Zampini for (d=0;d<cdim;d++) { 18351c7a958bSStefano Zampini PetscInt i; 18361c7a958bSStefano Zampini const PetscScalar *v; 18371c7a958bSStefano Zampini 18381c7a958bSStefano Zampini for (i=0;i<nf;i++) ctxs[i][0] = d; 18395f80ce2aSJacob Faibussowitsch CHKERRQ(DMProjectFunction(dm,0.0,funcs,(void**)ctxs,INSERT_VALUES,vcoords)); 18405f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(vcoords,&v)); 18411c7a958bSStefano Zampini for (i=0;i<nl;i++) coords[i*cdim+d] = PetscRealPart(v[i]); 18425f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(vcoords,&v)); 18431c7a958bSStefano Zampini } 18445f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&vcoords)); 18455f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetCoordinates(pc,cdim,nl,coords)); 18465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(coords)); 18475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ctxs[0])); 18485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(funcs,ctxs)); 18491c7a958bSStefano Zampini } 18501c7a958bSStefano Zampini } 18517a0e7b2cSstefano_zampini PetscFunctionReturn(0); 18527a0e7b2cSstefano_zampini } 18537a0e7b2cSstefano_zampini 18547a0e7b2cSstefano_zampini PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is) 18557a0e7b2cSstefano_zampini { 18567a0e7b2cSstefano_zampini Mat_IS *matis = (Mat_IS*)(pc->pmat->data); 18577a0e7b2cSstefano_zampini IS nis; 18587a0e7b2cSstefano_zampini const PetscInt *idxs; 18597a0e7b2cSstefano_zampini PetscInt i,nd,n = matis->A->rmap->n,*nidxs,nnd; 18607a0e7b2cSstefano_zampini 18617a0e7b2cSstefano_zampini PetscFunctionBegin; 18622c71b3e2SJacob Faibussowitsch PetscCheckFalse(mop != MPI_LAND && mop != MPI_LOR,PetscObjectComm((PetscObject)(pc)),PETSC_ERR_SUP,"Supported are MPI_LAND and MPI_LOR"); 18637a0e7b2cSstefano_zampini if (mop == MPI_LAND) { 18647a0e7b2cSstefano_zampini /* init rootdata with true */ 18651bd50df1SStefano Zampini for (i=0;i<pc->pmat->rmap->n;i++) matis->sf_rootdata[i] = 1; 18667a0e7b2cSstefano_zampini } else { 18675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(matis->sf_rootdata,pc->pmat->rmap->n)); 18687a0e7b2cSstefano_zampini } 18695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(matis->sf_leafdata,n)); 18705f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(*is,&nd)); 18715f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(*is,&idxs)); 18727a0e7b2cSstefano_zampini for (i=0;i<nd;i++) 18737a0e7b2cSstefano_zampini if (-1 < idxs[i] && idxs[i] < n) 18741bd50df1SStefano Zampini matis->sf_leafdata[idxs[i]] = 1; 18755f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(*is,&idxs)); 18765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,mop)); 18775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,mop)); 18785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 18795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE)); 18807a0e7b2cSstefano_zampini if (mop == MPI_LAND) { 18815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nd,&nidxs)); 18827a0e7b2cSstefano_zampini } else { 18835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n,&nidxs)); 18847a0e7b2cSstefano_zampini } 18857a0e7b2cSstefano_zampini for (i=0,nnd=0;i<n;i++) 18861bd50df1SStefano Zampini if (matis->sf_leafdata[i]) 18877a0e7b2cSstefano_zampini nidxs[nnd++] = i; 18885f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)(*is)),nnd,nidxs,PETSC_OWN_POINTER,&nis)); 18895f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(is)); 18907a0e7b2cSstefano_zampini *is = nis; 18911f4df5f7SStefano Zampini PetscFunctionReturn(0); 18921f4df5f7SStefano Zampini } 18931f4df5f7SStefano Zampini 18943e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z) 18953e589ea0SStefano Zampini { 18963e589ea0SStefano Zampini PC_IS *pcis = (PC_IS*)(pc->data); 18973e589ea0SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 18983e589ea0SStefano Zampini 18993e589ea0SStefano Zampini PetscFunctionBegin; 19003e589ea0SStefano Zampini if (!pcbddc->benign_have_null) { 19013e589ea0SStefano Zampini PetscFunctionReturn(0); 19023e589ea0SStefano Zampini } 19033e589ea0SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 19043e589ea0SStefano Zampini Vec swap; 19053e589ea0SStefano Zampini 19065f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change)); 19073e589ea0SStefano Zampini swap = pcbddc->work_change; 19083e589ea0SStefano Zampini pcbddc->work_change = r; 19093e589ea0SStefano Zampini r = swap; 19103e589ea0SStefano Zampini } 19115f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 19125f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 19135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 19145f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D)); 19155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 19165f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D)); 19175f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(z,0.)); 19185f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE)); 19195f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE)); 19203e589ea0SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 1921f913dca9SStefano Zampini pcbddc->work_change = r; 19225f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(z,pcbddc->work_change)); 19235f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z)); 19243e589ea0SStefano Zampini } 19253e589ea0SStefano Zampini PetscFunctionReturn(0); 19263e589ea0SStefano Zampini } 19273e589ea0SStefano Zampini 1928a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose) 1929a3df083aSStefano Zampini { 1930a3df083aSStefano Zampini PCBDDCBenignMatMult_ctx ctx; 1931a3df083aSStefano Zampini PetscBool apply_right,apply_left,reset_x; 1932a3df083aSStefano Zampini 1933a3df083aSStefano Zampini PetscFunctionBegin; 19345f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(A,&ctx)); 1935a3df083aSStefano Zampini if (transpose) { 1936a3df083aSStefano Zampini apply_right = ctx->apply_left; 1937a3df083aSStefano Zampini apply_left = ctx->apply_right; 1938a3df083aSStefano Zampini } else { 1939a3df083aSStefano Zampini apply_right = ctx->apply_right; 1940a3df083aSStefano Zampini apply_left = ctx->apply_left; 1941a3df083aSStefano Zampini } 1942a3df083aSStefano Zampini reset_x = PETSC_FALSE; 1943a3df083aSStefano Zampini if (apply_right) { 1944a3df083aSStefano Zampini const PetscScalar *ax; 1945a3df083aSStefano Zampini PetscInt nl,i; 1946a3df083aSStefano Zampini 19475f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(x,&nl)); 19485f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(x,&ax)); 19495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(ctx->work,ax,nl)); 19505f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(x,&ax)); 1951a3df083aSStefano Zampini for (i=0;i<ctx->benign_n;i++) { 1952a3df083aSStefano Zampini PetscScalar sum,val; 1953a3df083aSStefano Zampini const PetscInt *idxs; 1954a3df083aSStefano Zampini PetscInt nz,j; 19555f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz)); 19565f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs)); 1957a3df083aSStefano Zampini sum = 0.; 1958a3df083aSStefano Zampini if (ctx->apply_p0) { 1959a3df083aSStefano Zampini val = ctx->work[idxs[nz-1]]; 1960a3df083aSStefano Zampini for (j=0;j<nz-1;j++) { 1961a3df083aSStefano Zampini sum += ctx->work[idxs[j]]; 1962a3df083aSStefano Zampini ctx->work[idxs[j]] += val; 1963a3df083aSStefano Zampini } 1964a3df083aSStefano Zampini } else { 1965a3df083aSStefano Zampini for (j=0;j<nz-1;j++) { 1966a3df083aSStefano Zampini sum += ctx->work[idxs[j]]; 1967a3df083aSStefano Zampini } 1968a3df083aSStefano Zampini } 1969a3df083aSStefano Zampini ctx->work[idxs[nz-1]] -= sum; 19705f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs)); 1971a3df083aSStefano Zampini } 19725f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(x,ctx->work)); 1973a3df083aSStefano Zampini reset_x = PETSC_TRUE; 1974a3df083aSStefano Zampini } 1975a3df083aSStefano Zampini if (transpose) { 19765f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(ctx->A,x,y)); 1977a3df083aSStefano Zampini } else { 19785f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(ctx->A,x,y)); 1979a3df083aSStefano Zampini } 1980a3df083aSStefano Zampini if (reset_x) { 19815f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(x)); 1982a3df083aSStefano Zampini } 1983a3df083aSStefano Zampini if (apply_left) { 1984a3df083aSStefano Zampini PetscScalar *ay; 1985a3df083aSStefano Zampini PetscInt i; 1986a3df083aSStefano Zampini 19875f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(y,&ay)); 1988a3df083aSStefano Zampini for (i=0;i<ctx->benign_n;i++) { 1989a3df083aSStefano Zampini PetscScalar sum,val; 1990a3df083aSStefano Zampini const PetscInt *idxs; 1991a3df083aSStefano Zampini PetscInt nz,j; 19925f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz)); 19935f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs)); 1994a3df083aSStefano Zampini val = -ay[idxs[nz-1]]; 1995a3df083aSStefano Zampini if (ctx->apply_p0) { 1996a3df083aSStefano Zampini sum = 0.; 1997a3df083aSStefano Zampini for (j=0;j<nz-1;j++) { 1998a3df083aSStefano Zampini sum += ay[idxs[j]]; 1999a3df083aSStefano Zampini ay[idxs[j]] += val; 2000a3df083aSStefano Zampini } 2001a3df083aSStefano Zampini ay[idxs[nz-1]] += sum; 2002a3df083aSStefano Zampini } else { 2003a3df083aSStefano Zampini for (j=0;j<nz-1;j++) { 2004a3df083aSStefano Zampini ay[idxs[j]] += val; 2005a3df083aSStefano Zampini } 2006a3df083aSStefano Zampini ay[idxs[nz-1]] = 0.; 2007a3df083aSStefano Zampini } 20085f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs)); 2009a3df083aSStefano Zampini } 20105f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(y,&ay)); 2011a3df083aSStefano Zampini } 2012a3df083aSStefano Zampini PetscFunctionReturn(0); 2013a3df083aSStefano Zampini } 2014a3df083aSStefano Zampini 2015a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y) 2016a3df083aSStefano Zampini { 2017a3df083aSStefano Zampini PetscFunctionBegin; 20185f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE)); 2019a3df083aSStefano Zampini PetscFunctionReturn(0); 2020a3df083aSStefano Zampini } 2021a3df083aSStefano Zampini 2022a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y) 2023a3df083aSStefano Zampini { 2024a3df083aSStefano Zampini PetscFunctionBegin; 20255f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE)); 2026a3df083aSStefano Zampini PetscFunctionReturn(0); 2027a3df083aSStefano Zampini } 2028a3df083aSStefano Zampini 2029a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore) 2030a3df083aSStefano Zampini { 2031a3df083aSStefano Zampini PC_IS *pcis = (PC_IS*)pc->data; 2032a3df083aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 2033a3df083aSStefano Zampini PCBDDCBenignMatMult_ctx ctx; 2034a3df083aSStefano Zampini 2035a3df083aSStefano Zampini PetscFunctionBegin; 2036a3df083aSStefano Zampini if (!restore) { 20371dd7afcfSStefano Zampini Mat A_IB,A_BI; 2038a3df083aSStefano Zampini PetscScalar *work; 2039b334f244SStefano Zampini PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL; 2040a3df083aSStefano Zampini 2041*28b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->benign_original_mat,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored"); 20429a962809SStefano Zampini if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0); 20435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcis->n,&work)); 20445f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PETSC_COMM_SELF,&A_IB)); 20455f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE)); 20465f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(A_IB,MATSHELL)); 20475f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private)); 20485f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private)); 20495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNew(&ctx)); 20505f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetContext(A_IB,ctx)); 2051a3df083aSStefano Zampini ctx->apply_left = PETSC_TRUE; 2052a3df083aSStefano Zampini ctx->apply_right = PETSC_FALSE; 2053a3df083aSStefano Zampini ctx->apply_p0 = PETSC_FALSE; 2054a3df083aSStefano Zampini ctx->benign_n = pcbddc->benign_n; 2055059032f7SStefano Zampini if (reuse) { 2056a3df083aSStefano Zampini ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs; 20571dd7afcfSStefano Zampini ctx->free = PETSC_FALSE; 2058059032f7SStefano Zampini } else { /* TODO: could be optimized for successive solves */ 2059059032f7SStefano Zampini ISLocalToGlobalMapping N_to_D; 2060059032f7SStefano Zampini PetscInt i; 2061059032f7SStefano Zampini 20625f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D)); 20635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs)); 2064059032f7SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) { 20655f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i])); 2066059032f7SStefano Zampini } 20675f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&N_to_D)); 20681dd7afcfSStefano Zampini ctx->free = PETSC_TRUE; 2069059032f7SStefano Zampini } 2070a3df083aSStefano Zampini ctx->A = pcis->A_IB; 2071a3df083aSStefano Zampini ctx->work = work; 20725f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetUp(A_IB)); 20735f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY)); 20745f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY)); 2075a3df083aSStefano Zampini pcis->A_IB = A_IB; 2076a3df083aSStefano Zampini 2077a3df083aSStefano Zampini /* A_BI as A_IB^T */ 20785f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateTranspose(A_IB,&A_BI)); 2079a3df083aSStefano Zampini pcbddc->benign_original_mat = pcis->A_BI; 2080a3df083aSStefano Zampini pcis->A_BI = A_BI; 2081a3df083aSStefano Zampini } else { 20821dd7afcfSStefano Zampini if (!pcbddc->benign_original_mat) { 20831dd7afcfSStefano Zampini PetscFunctionReturn(0); 20841dd7afcfSStefano Zampini } 20855f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(pcis->A_IB,&ctx)); 20865f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcis->A_IB)); 2087a3df083aSStefano Zampini pcis->A_IB = ctx->A; 20881dd7afcfSStefano Zampini ctx->A = NULL; 20895f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcis->A_BI)); 20901dd7afcfSStefano Zampini pcis->A_BI = pcbddc->benign_original_mat; 20911dd7afcfSStefano Zampini pcbddc->benign_original_mat = NULL; 20921dd7afcfSStefano Zampini if (ctx->free) { 2093059032f7SStefano Zampini PetscInt i; 20941dd7afcfSStefano Zampini for (i=0;i<ctx->benign_n;i++) { 20955f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&ctx->benign_zerodiag_subs[i])); 2096059032f7SStefano Zampini } 20975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ctx->benign_zerodiag_subs)); 2098059032f7SStefano Zampini } 20995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ctx->work)); 21005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ctx)); 2101a3df083aSStefano Zampini } 2102a3df083aSStefano Zampini PetscFunctionReturn(0); 2103a3df083aSStefano Zampini } 2104a3df083aSStefano Zampini 2105a3df083aSStefano Zampini /* used just in bddc debug mode */ 2106a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B) 2107a3df083aSStefano Zampini { 2108a3df083aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 2109a3df083aSStefano Zampini Mat_IS *matis = (Mat_IS*)pc->pmat->data; 2110a3df083aSStefano Zampini Mat An; 2111a3df083aSStefano Zampini 2112a3df083aSStefano Zampini PetscFunctionBegin; 21135f80ce2aSJacob Faibussowitsch CHKERRQ(MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An)); 21145f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL)); 2115a3df083aSStefano Zampini if (is1) { 21165f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B)); 21175f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&An)); 2118a3df083aSStefano Zampini } else { 2119a3df083aSStefano Zampini *B = An; 2120a3df083aSStefano Zampini } 2121a3df083aSStefano Zampini PetscFunctionReturn(0); 2122a3df083aSStefano Zampini } 2123a3df083aSStefano Zampini 21241cf9b237SStefano Zampini /* TODO: add reuse flag */ 21251cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B) 21261cf9b237SStefano Zampini { 21271cf9b237SStefano Zampini Mat Bt; 21281cf9b237SStefano Zampini PetscScalar *a,*bdata; 21291cf9b237SStefano Zampini const PetscInt *ii,*ij; 21301cf9b237SStefano Zampini PetscInt m,n,i,nnz,*bii,*bij; 21311cf9b237SStefano Zampini PetscBool flg_row; 21321cf9b237SStefano Zampini 21331cf9b237SStefano Zampini PetscFunctionBegin; 21345f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(A,&n,&m)); 21355f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row)); 21365f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJGetArray(A,&a)); 21371cf9b237SStefano Zampini nnz = n; 21381cf9b237SStefano Zampini for (i=0;i<ii[n];i++) { 21391cf9b237SStefano Zampini if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++; 21401cf9b237SStefano Zampini } 21415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n+1,&bii)); 21425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nnz,&bij)); 21435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nnz,&bdata)); 21441cf9b237SStefano Zampini nnz = 0; 21451cf9b237SStefano Zampini bii[0] = 0; 21461cf9b237SStefano Zampini for (i=0;i<n;i++) { 21471cf9b237SStefano Zampini PetscInt j; 21481cf9b237SStefano Zampini for (j=ii[i];j<ii[i+1];j++) { 21491cf9b237SStefano Zampini PetscScalar entry = a[j]; 21503272d46bSStefano Zampini if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) { 21511cf9b237SStefano Zampini bij[nnz] = ij[j]; 21521cf9b237SStefano Zampini bdata[nnz] = entry; 21531cf9b237SStefano Zampini nnz++; 21541cf9b237SStefano Zampini } 21551cf9b237SStefano Zampini } 21561cf9b237SStefano Zampini bii[i+1] = nnz; 21571cf9b237SStefano Zampini } 21585f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJRestoreArray(A,&a)); 21595f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt)); 21605f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row)); 21611cf9b237SStefano Zampini { 21621cf9b237SStefano Zampini Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data); 21631cf9b237SStefano Zampini b->free_a = PETSC_TRUE; 21641cf9b237SStefano Zampini b->free_ij = PETSC_TRUE; 21651cf9b237SStefano Zampini } 21663272d46bSStefano Zampini if (*B == A) { 21675f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A)); 21683272d46bSStefano Zampini } 21691cf9b237SStefano Zampini *B = Bt; 21701cf9b237SStefano Zampini PetscFunctionReturn(0); 21711cf9b237SStefano Zampini } 21721cf9b237SStefano Zampini 21738361f951SStefano Zampini PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS* cc[], IS* primalv) 21744f1b2e48SStefano Zampini { 2175c80a6c00SStefano Zampini Mat B = NULL; 2176c80a6c00SStefano Zampini DM dm; 21774f1b2e48SStefano Zampini IS is_dummy,*cc_n; 21784f1b2e48SStefano Zampini ISLocalToGlobalMapping l2gmap_dummy; 21794f1b2e48SStefano Zampini PCBDDCGraph graph; 2180c80a6c00SStefano Zampini PetscInt *xadj_filtered = NULL,*adjncy_filtered = NULL; 21814f1b2e48SStefano Zampini PetscInt i,n; 21824f1b2e48SStefano Zampini PetscInt *xadj,*adjncy; 2183c80a6c00SStefano Zampini PetscBool isplex = PETSC_FALSE; 21844f1b2e48SStefano Zampini 21854f1b2e48SStefano Zampini PetscFunctionBegin; 2186a2eca866SStefano Zampini if (ncc) *ncc = 0; 2187a2eca866SStefano Zampini if (cc) *cc = NULL; 2188a2eca866SStefano Zampini if (primalv) *primalv = NULL; 21895f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphCreate(&graph)); 21905f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetDM(pc->pmat,&dm)); 21914f819b78SStefano Zampini if (!dm) { 21925f80ce2aSJacob Faibussowitsch CHKERRQ(PCGetDM(pc,&dm)); 2193c80a6c00SStefano Zampini } 2194c80a6c00SStefano Zampini if (dm) { 21955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex)); 2196c80a6c00SStefano Zampini } 21978361f951SStefano Zampini if (filter) isplex = PETSC_FALSE; 21988361f951SStefano Zampini 2199c80a6c00SStefano Zampini if (isplex) { /* this code has been modified from plexpartition.c */ 2200c80a6c00SStefano Zampini PetscInt p, pStart, pEnd, a, adjSize, idx, size, nroots; 2201c80a6c00SStefano Zampini PetscInt *adj = NULL; 2202c80a6c00SStefano Zampini IS cellNumbering; 2203c80a6c00SStefano Zampini const PetscInt *cellNum; 2204c80a6c00SStefano Zampini PetscBool useCone, useClosure; 2205c80a6c00SStefano Zampini PetscSection section; 2206c80a6c00SStefano Zampini PetscSegBuffer adjBuffer; 2207c80a6c00SStefano Zampini PetscSF sfPoint; 2208c80a6c00SStefano Zampini 22095f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd)); 22105f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sfPoint)); 22115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 2212c80a6c00SStefano Zampini /* Build adjacency graph via a section/segbuffer */ 22135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ion)); 22145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(section, pStart, pEnd)); 22155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer)); 2216c80a6c00SStefano Zampini /* Always use FVM adjacency to create partitioner graph */ 22175f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 22185f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE)); 22195f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellNumbering(dm, &cellNumbering)); 22205f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(cellNumbering, &cellNum)); 2221c80a6c00SStefano Zampini for (n = 0, p = pStart; p < pEnd; p++) { 2222c80a6c00SStefano Zampini /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 2223c80a6c00SStefano Zampini if (nroots > 0) {if (cellNum[p] < 0) continue;} 2224c80a6c00SStefano Zampini adjSize = PETSC_DETERMINE; 22255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 2226c80a6c00SStefano Zampini for (a = 0; a < adjSize; ++a) { 2227c80a6c00SStefano Zampini const PetscInt point = adj[a]; 22285cef3d0dSStefano Zampini if (pStart <= point && point < pEnd) { 2229c80a6c00SStefano Zampini PetscInt *PETSC_RESTRICT pBuf; 22305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(section, p, 1)); 22315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2232c80a6c00SStefano Zampini *pBuf = point; 2233c80a6c00SStefano Zampini } 2234c80a6c00SStefano Zampini } 2235c80a6c00SStefano Zampini n++; 2236c80a6c00SStefano Zampini } 22375f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetBasicAdjacency(dm, useCone, useClosure)); 2238c80a6c00SStefano Zampini /* Derive CSR graph from section/segbuffer */ 22395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(section)); 22405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(section, &size)); 22415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n+1, &xadj)); 2242c80a6c00SStefano Zampini for (idx = 0, p = pStart; p < pEnd; p++) { 2243c80a6c00SStefano Zampini if (nroots > 0) {if (cellNum[p] < 0) continue;} 22445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, p, &(xadj[idx++]))); 2245c80a6c00SStefano Zampini } 2246c80a6c00SStefano Zampini xadj[n] = size; 22475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferExtractAlloc(adjBuffer, &adjncy)); 2248c80a6c00SStefano Zampini /* Clean up */ 22495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferDestroy(&adjBuffer)); 22505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(§ion)); 22515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adj)); 2252c80a6c00SStefano Zampini graph->xadj = xadj; 2253c80a6c00SStefano Zampini graph->adjncy = adjncy; 2254c80a6c00SStefano Zampini } else { 2255c80a6c00SStefano Zampini Mat A; 22568361f951SStefano Zampini PetscBool isseqaij, flg_row; 2257c80a6c00SStefano Zampini 22585f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(pc->pmat,&A)); 225963c961adSStefano Zampini if (!A->rmap->N || !A->cmap->N) { 22605f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphDestroy(&graph)); 226163c961adSStefano Zampini PetscFunctionReturn(0); 226263c961adSStefano Zampini } 22635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij)); 22644f1b2e48SStefano Zampini if (!isseqaij && filter) { 22651cf9b237SStefano Zampini PetscBool isseqdense; 22661cf9b237SStefano Zampini 22675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense)); 22681cf9b237SStefano Zampini if (!isseqdense) { 22695f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B)); 22701cf9b237SStefano Zampini } else { /* TODO: rectangular case and LDA */ 22711cf9b237SStefano Zampini PetscScalar *array; 22721cf9b237SStefano Zampini PetscReal chop=1.e-6; 22731cf9b237SStefano Zampini 22745f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(A,MAT_COPY_VALUES,&B)); 22755f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(B,&array)); 22765f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(B,&n,NULL)); 22771cf9b237SStefano Zampini for (i=0;i<n;i++) { 22781cf9b237SStefano Zampini PetscInt j; 22791cf9b237SStefano Zampini for (j=i+1;j<n;j++) { 22801cf9b237SStefano Zampini PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)])); 22811cf9b237SStefano Zampini if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.; 22821cf9b237SStefano Zampini if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.; 22831cf9b237SStefano Zampini } 22841cf9b237SStefano Zampini } 22855f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(B,&array)); 22865f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B)); 22871cf9b237SStefano Zampini } 22884f1b2e48SStefano Zampini } else { 22895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)A)); 22904f1b2e48SStefano Zampini B = A; 22914f1b2e48SStefano Zampini } 22925f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row)); 22934f1b2e48SStefano Zampini 22944f1b2e48SStefano Zampini /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */ 22954f1b2e48SStefano Zampini if (filter) { 22964f1b2e48SStefano Zampini PetscScalar *data; 22974f1b2e48SStefano Zampini PetscInt j,cum; 22984f1b2e48SStefano Zampini 22995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered)); 23005f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJGetArray(B,&data)); 23014f1b2e48SStefano Zampini cum = 0; 23024f1b2e48SStefano Zampini for (i=0;i<n;i++) { 23034f1b2e48SStefano Zampini PetscInt t; 23044f1b2e48SStefano Zampini 23054f1b2e48SStefano Zampini for (j=xadj[i];j<xadj[i+1];j++) { 23064f1b2e48SStefano Zampini if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) { 23074f1b2e48SStefano Zampini continue; 23084f1b2e48SStefano Zampini } 23094f1b2e48SStefano Zampini adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j]; 23104f1b2e48SStefano Zampini } 23114f1b2e48SStefano Zampini t = xadj_filtered[i]; 23124f1b2e48SStefano Zampini xadj_filtered[i] = cum; 23134f1b2e48SStefano Zampini cum += t; 23144f1b2e48SStefano Zampini } 23155f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJRestoreArray(B,&data)); 23164f1b2e48SStefano Zampini graph->xadj = xadj_filtered; 23174f1b2e48SStefano Zampini graph->adjncy = adjncy_filtered; 23184f1b2e48SStefano Zampini } else { 23194f1b2e48SStefano Zampini graph->xadj = xadj; 23204f1b2e48SStefano Zampini graph->adjncy = adjncy; 23214f1b2e48SStefano Zampini } 2322c80a6c00SStefano Zampini } 2323c80a6c00SStefano Zampini /* compute local connected components using PCBDDCGraph */ 23245f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy)); 23255f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy)); 23265f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_dummy)); 23275f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphInit(graph,l2gmap_dummy,n,PETSC_MAX_INT)); 23285f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&l2gmap_dummy)); 23295f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL)); 23305f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphComputeConnectedComponents(graph)); 2331c80a6c00SStefano Zampini 23324f1b2e48SStefano Zampini /* partial clean up */ 23335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(xadj_filtered,adjncy_filtered)); 2334c80a6c00SStefano Zampini if (B) { 2335c80a6c00SStefano Zampini PetscBool flg_row; 23365f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row)); 23375f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B)); 23384f1b2e48SStefano Zampini } 2339c80a6c00SStefano Zampini if (isplex) { 23405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(xadj)); 23415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adjncy)); 2342c80a6c00SStefano Zampini } 23434f1b2e48SStefano Zampini 23444f1b2e48SStefano Zampini /* get back data */ 2345c80a6c00SStefano Zampini if (isplex) { 2346c80a6c00SStefano Zampini if (ncc) *ncc = graph->ncc; 2347c80a6c00SStefano Zampini if (cc || primalv) { 2348c80a6c00SStefano Zampini Mat A; 2349c80a6c00SStefano Zampini PetscBT btv,btvt; 2350c80a6c00SStefano Zampini PetscSection subSection; 2351c80a6c00SStefano Zampini PetscInt *ids,cum,cump,*cids,*pids; 2352c80a6c00SStefano Zampini 23535f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSubdomainSection(dm,&subSection)); 23545f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(pc->pmat,&A)); 23555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(A->rmap->n,&ids,graph->ncc+1,&cids,A->rmap->n,&pids)); 23565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(A->rmap->n,&btv)); 23575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(A->rmap->n,&btvt)); 2358c80a6c00SStefano Zampini 2359c80a6c00SStefano Zampini cids[0] = 0; 2360c80a6c00SStefano Zampini for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) { 2361c80a6c00SStefano Zampini PetscInt j; 2362c80a6c00SStefano Zampini 23635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTMemzero(A->rmap->n,btvt)); 2364c80a6c00SStefano Zampini for (j = graph->cptr[i]; j < graph->cptr[i+1]; j++) { 2365c80a6c00SStefano Zampini PetscInt k, size, *closure = NULL, cell = graph->queue[j]; 2366c80a6c00SStefano Zampini 23675f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure)); 2368c80a6c00SStefano Zampini for (k = 0; k < 2*size; k += 2) { 236920c3699dSStefano Zampini PetscInt s, pp, p = closure[k], off, dof, cdof; 2370c80a6c00SStefano Zampini 23715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(subSection,p,&cdof)); 23725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(subSection,p,&off)); 23735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(subSection,p,&dof)); 2374c80a6c00SStefano Zampini for (s = 0; s < dof-cdof; s++) { 2375c80a6c00SStefano Zampini if (PetscBTLookupSet(btvt,off+s)) continue; 2376e432b41dSStefano Zampini if (!PetscBTLookup(btv,off+s)) ids[cum++] = off+s; 2377e432b41dSStefano Zampini else pids[cump++] = off+s; /* cross-vertex */ 2378c80a6c00SStefano Zampini } 23795f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,p,&pp,NULL)); 238020c3699dSStefano Zampini if (pp != p) { 23815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(subSection,pp,&cdof)); 23825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(subSection,pp,&off)); 23835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(subSection,pp,&dof)); 238420c3699dSStefano Zampini for (s = 0; s < dof-cdof; s++) { 238520c3699dSStefano Zampini if (PetscBTLookupSet(btvt,off+s)) continue; 2386e432b41dSStefano Zampini if (!PetscBTLookup(btv,off+s)) ids[cum++] = off+s; 2387e432b41dSStefano Zampini else pids[cump++] = off+s; /* cross-vertex */ 238820c3699dSStefano Zampini } 238920c3699dSStefano Zampini } 2390c80a6c00SStefano Zampini } 23915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&size,&closure)); 2392c80a6c00SStefano Zampini } 2393c80a6c00SStefano Zampini cids[i+1] = cum; 2394c80a6c00SStefano Zampini /* mark dofs as already assigned */ 2395c80a6c00SStefano Zampini for (j = cids[i]; j < cids[i+1]; j++) { 23965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(btv,ids[j])); 2397c80a6c00SStefano Zampini } 2398c80a6c00SStefano Zampini } 2399c80a6c00SStefano Zampini if (cc) { 24005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(graph->ncc,&cc_n)); 2401c80a6c00SStefano Zampini for (i = 0; i < graph->ncc; i++) { 24025f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,cids[i+1]-cids[i],ids+cids[i],PETSC_COPY_VALUES,&cc_n[i])); 2403c80a6c00SStefano Zampini } 2404c80a6c00SStefano Zampini *cc = cc_n; 2405c80a6c00SStefano Zampini } 2406c80a6c00SStefano Zampini if (primalv) { 24075f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)pc),cump,pids,PETSC_COPY_VALUES,primalv)); 2408c80a6c00SStefano Zampini } 24095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(ids,cids,pids)); 24105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&btv)); 24115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&btvt)); 2412c80a6c00SStefano Zampini } 2413c80a6c00SStefano Zampini } else { 24141cf9b237SStefano Zampini if (ncc) *ncc = graph->ncc; 24151cf9b237SStefano Zampini if (cc) { 24165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(graph->ncc,&cc_n)); 24174f1b2e48SStefano Zampini for (i=0;i<graph->ncc;i++) { 24185f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,graph->cptr[i+1]-graph->cptr[i],graph->queue+graph->cptr[i],PETSC_COPY_VALUES,&cc_n[i])); 24194f1b2e48SStefano Zampini } 24204f1b2e48SStefano Zampini *cc = cc_n; 24211cf9b237SStefano Zampini } 2422c80a6c00SStefano Zampini } 24234f1b2e48SStefano Zampini /* clean up graph */ 24240a545947SLisandro Dalcin graph->xadj = NULL; 24250a545947SLisandro Dalcin graph->adjncy = NULL; 24265f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphDestroy(&graph)); 24274f1b2e48SStefano Zampini PetscFunctionReturn(0); 24284f1b2e48SStefano Zampini } 24294f1b2e48SStefano Zampini 24305408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag) 24315408967cSStefano Zampini { 24325408967cSStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 24335408967cSStefano Zampini PC_IS* pcis = (PC_IS*)(pc->data); 2434dee84bffSStefano Zampini IS dirIS = NULL; 24354f1b2e48SStefano Zampini PetscInt i; 24365408967cSStefano Zampini 24375408967cSStefano Zampini PetscFunctionBegin; 24385f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS)); 24395408967cSStefano Zampini if (zerodiag) { 24405408967cSStefano Zampini Mat A; 24415408967cSStefano Zampini Vec vec3_N; 24425408967cSStefano Zampini PetscScalar *vals; 24435408967cSStefano Zampini const PetscInt *idxs; 2444d12d3064SStefano Zampini PetscInt nz,*count; 24455408967cSStefano Zampini 24465408967cSStefano Zampini /* p0 */ 24475f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcis->vec1_N,0.)); 24485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcis->n,&vals)); 24495f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(zerodiag,&nz)); 24505f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(zerodiag,&idxs)); 24514f1b2e48SStefano Zampini for (i=0;i<nz;i++) vals[i] = 1.; 24525f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES)); 24535f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(pcis->vec1_N)); 24545f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(pcis->vec1_N)); 24555408967cSStefano Zampini /* v_I */ 24565f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetRandom(pcis->vec2_N,NULL)); 24575408967cSStefano Zampini for (i=0;i<nz;i++) vals[i] = 0.; 24585f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES)); 24595f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(zerodiag,&idxs)); 24605f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcis->is_B_local,&idxs)); 24615408967cSStefano Zampini for (i=0;i<pcis->n_B;i++) vals[i] = 0.; 24625f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES)); 24635f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcis->is_B_local,&idxs)); 24645408967cSStefano Zampini if (dirIS) { 24655408967cSStefano Zampini PetscInt n; 24665408967cSStefano Zampini 24675f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(dirIS,&n)); 24685f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(dirIS,&idxs)); 24695408967cSStefano Zampini for (i=0;i<n;i++) vals[i] = 0.; 24705f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES)); 24715f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(dirIS,&idxs)); 24725408967cSStefano Zampini } 24735f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(pcis->vec2_N)); 24745f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(pcis->vec2_N)); 24755f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(pcis->vec1_N,&vec3_N)); 24765f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(vec3_N,0.)); 24775f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(pc->pmat,&A)); 24785f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(A,pcis->vec1_N,vec3_N)); 24795f80ce2aSJacob Faibussowitsch CHKERRQ(VecDot(vec3_N,pcis->vec2_N,&vals[0])); 24802c71b3e2SJacob Faibussowitsch PetscCheckFalse(PetscAbsScalar(vals[0]) > 1.e-1,PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! b(v_I,p_0) = %1.6e (should be numerically 0.)",PetscAbsScalar(vals[0])); 24815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vals)); 24825f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&vec3_N)); 2483d12d3064SStefano Zampini 2484d12d3064SStefano Zampini /* there should not be any pressure dofs lying on the interface */ 24855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(pcis->n,&count)); 24865f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcis->is_B_local,&idxs)); 2487d12d3064SStefano Zampini for (i=0;i<pcis->n_B;i++) count[idxs[i]]++; 24885f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcis->is_B_local,&idxs)); 24895f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(zerodiag,&idxs)); 24902c71b3e2SJacob Faibussowitsch for (i=0;i<nz;i++) PetscCheckFalse(count[idxs[i]],PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! pressure dof %D is an interface dof",idxs[i]); 24915f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(zerodiag,&idxs)); 24925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(count)); 24935408967cSStefano Zampini } 24945f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&dirIS)); 24955408967cSStefano Zampini 24965408967cSStefano Zampini /* check PCBDDCBenignGetOrSetP0 */ 24975f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetRandom(pcis->vec1_global,NULL)); 24984f1b2e48SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i; 24995f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE)); 25004f1b2e48SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1; 25015f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE)); 2502f2a566d8SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) { 2503f2a566d8SStefano Zampini PetscInt val = PetscRealPart(pcbddc->benign_p0[i]); 25042c71b3e2SJacob Faibussowitsch PetscCheckFalse(val != -PetscGlobalRank-i,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error testing PCBDDCBenignGetOrSetP0! Found %g at %D instead of %g",PetscRealPart(pcbddc->benign_p0[i]),i,-PetscGlobalRank-i); 2505f2a566d8SStefano Zampini } 25065408967cSStefano Zampini PetscFunctionReturn(0); 25075408967cSStefano Zampini } 25085408967cSStefano Zampini 25093b03f7bbSStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, PetscBool reuse, IS *zerodiaglocal) 2510339f8db1SStefano Zampini { 2511339f8db1SStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 2512e432b41dSStefano Zampini Mat_IS* matis = (Mat_IS*)(pc->pmat->data); 25133b03f7bbSStefano Zampini IS pressures = NULL,zerodiag = NULL,*bzerodiag = NULL,zerodiag_save,*zerodiag_subs; 25143b03f7bbSStefano Zampini PetscInt nz,n,benign_n,bsp = 1; 25154edc6404Sstefano_zampini PetscInt *interior_dofs,n_interior_dofs,nneu; 25164edc6404Sstefano_zampini PetscBool sorted,have_null,has_null_pressures,recompute_zerodiag,checkb; 2517339f8db1SStefano Zampini PetscErrorCode ierr; 2518339f8db1SStefano Zampini 2519339f8db1SStefano Zampini PetscFunctionBegin; 25203b03f7bbSStefano Zampini if (reuse) goto project_b0; 25215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&pcbddc->benign_sf)); 25225f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->benign_B0)); 2523a3df083aSStefano Zampini for (n=0;n<pcbddc->benign_n;n++) { 25245f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->benign_zerodiag_subs[n])); 2525a3df083aSStefano Zampini } 25265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddc->benign_zerodiag_subs)); 25273b03f7bbSStefano Zampini has_null_pressures = PETSC_TRUE; 25283b03f7bbSStefano Zampini have_null = PETSC_TRUE; 25293b03f7bbSStefano Zampini /* if a local information on dofs is present, gets pressure dofs from command line (uses the last field is not provided) 25303b03f7bbSStefano Zampini Without local information, it uses only the zerodiagonal dofs (ok if the pressure block is all zero and it is a scalar field) 25314f1b2e48SStefano Zampini Checks if all the pressure dofs in each subdomain have a zero diagonal 25324f1b2e48SStefano Zampini If not, a change of basis on pressures is not needed 25331ae86dd6SStefano Zampini since the local Schur complements are already SPD 25344f1b2e48SStefano Zampini */ 253540fa8d13SStefano Zampini if (pcbddc->n_ISForDofsLocal) { 25367fbe2174Sstefano_zampini IS iP = NULL; 25373b03f7bbSStefano Zampini PetscInt p,*pp; 25383b03f7bbSStefano Zampini PetscBool flg; 25394f1b2e48SStefano Zampini 25405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->n_ISForDofsLocal,&pp)); 25413b03f7bbSStefano Zampini n = pcbddc->n_ISForDofsLocal; 254228b8efb1Sstefano_zampini ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)pc),((PetscObject)pc)->prefix,"BDDC benign options","PC");CHKERRQ(ierr); 25435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsIntArray("-pc_bddc_pressure_field","Field id for pressures",NULL,pp,&n,&flg)); 254428b8efb1Sstefano_zampini ierr = PetscOptionsEnd();CHKERRQ(ierr); 25453b03f7bbSStefano Zampini if (!flg) { 25463b03f7bbSStefano Zampini n = 1; 25473b03f7bbSStefano Zampini pp[0] = pcbddc->n_ISForDofsLocal-1; 25483b03f7bbSStefano Zampini } 25493b03f7bbSStefano Zampini 25503b03f7bbSStefano Zampini bsp = 0; 25513b03f7bbSStefano Zampini for (p=0;p<n;p++) { 25523b03f7bbSStefano Zampini PetscInt bs; 25533b03f7bbSStefano Zampini 25542c71b3e2SJacob Faibussowitsch PetscCheckFalse(pp[p] < 0 || pp[p] > pcbddc->n_ISForDofsLocal-1,PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Invalid field id for pressures %D",pp[p]); 25555f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs)); 25563b03f7bbSStefano Zampini bsp += bs; 25573b03f7bbSStefano Zampini } 25585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(bsp,&bzerodiag)); 25593b03f7bbSStefano Zampini bsp = 0; 25603b03f7bbSStefano Zampini for (p=0;p<n;p++) { 25613b03f7bbSStefano Zampini const PetscInt *idxs; 25623b03f7bbSStefano Zampini PetscInt b,bs,npl,*bidxs; 25633b03f7bbSStefano Zampini 25645f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]],&bs)); 25655f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pcbddc->ISForDofsLocal[pp[p]],&npl)); 25665f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs)); 25675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(npl/bs,&bidxs)); 25683b03f7bbSStefano Zampini for (b=0;b<bs;b++) { 25693b03f7bbSStefano Zampini PetscInt i; 25703b03f7bbSStefano Zampini 25713b03f7bbSStefano Zampini for (i=0;i<npl/bs;i++) bidxs[i] = idxs[bs*i+b]; 25725f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,npl/bs,bidxs,PETSC_COPY_VALUES,&bzerodiag[bsp])); 25733b03f7bbSStefano Zampini bsp++; 25743b03f7bbSStefano Zampini } 25755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(bidxs)); 25765f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcbddc->ISForDofsLocal[pp[p]],&idxs)); 25773b03f7bbSStefano Zampini } 25785f80ce2aSJacob Faibussowitsch CHKERRQ(ISConcatenate(PETSC_COMM_SELF,bsp,bzerodiag,&pressures)); 25793b03f7bbSStefano Zampini 25807fbe2174Sstefano_zampini /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */ 25815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP",(PetscObject*)&iP)); 25827fbe2174Sstefano_zampini if (iP) { 25837fbe2174Sstefano_zampini IS newpressures; 25847fbe2174Sstefano_zampini 25855f80ce2aSJacob Faibussowitsch CHKERRQ(ISDifference(pressures,iP,&newpressures)); 25865f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pressures)); 25877fbe2174Sstefano_zampini pressures = newpressures; 25887fbe2174Sstefano_zampini } 25895f80ce2aSJacob Faibussowitsch CHKERRQ(ISSorted(pressures,&sorted)); 259040fa8d13SStefano Zampini if (!sorted) { 25915f80ce2aSJacob Faibussowitsch CHKERRQ(ISSort(pressures)); 259240fa8d13SStefano Zampini } 25935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pp)); 259440fa8d13SStefano Zampini } 25953b03f7bbSStefano Zampini 259697d764eeSStefano Zampini /* pcis has not been setup yet, so get the local size from the subdomain matrix */ 25975f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(pcbddc->local_mat,&n,NULL)); 259827b6a85dSStefano Zampini if (!n) pcbddc->benign_change_explicit = PETSC_TRUE; 25995f80ce2aSJacob Faibussowitsch CHKERRQ(MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag)); 26005f80ce2aSJacob Faibussowitsch CHKERRQ(ISSorted(zerodiag,&sorted)); 2601339f8db1SStefano Zampini if (!sorted) { 26025f80ce2aSJacob Faibussowitsch CHKERRQ(ISSort(zerodiag)); 2603339f8db1SStefano Zampini } 26045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)zerodiag)); 26054edc6404Sstefano_zampini zerodiag_save = zerodiag; 26065f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(zerodiag,&nz)); 26074f1b2e48SStefano Zampini if (!nz) { 26084f1b2e48SStefano Zampini if (n) have_null = PETSC_FALSE; 26094f1b2e48SStefano Zampini has_null_pressures = PETSC_FALSE; 26105f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&zerodiag)); 261140fa8d13SStefano Zampini } 26124f1b2e48SStefano Zampini recompute_zerodiag = PETSC_FALSE; 26133b03f7bbSStefano Zampini 26144f1b2e48SStefano Zampini /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */ 26154f1b2e48SStefano Zampini zerodiag_subs = NULL; 26163b03f7bbSStefano Zampini benign_n = 0; 26171f4df5f7SStefano Zampini n_interior_dofs = 0; 26181f4df5f7SStefano Zampini interior_dofs = NULL; 26194edc6404Sstefano_zampini nneu = 0; 26204edc6404Sstefano_zampini if (pcbddc->NeumannBoundariesLocal) { 26215f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nneu)); 26224edc6404Sstefano_zampini } 26233369cb78Sstefano_zampini checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level); 26244edc6404Sstefano_zampini if (checkb) { /* need to compute interior nodes */ 26251f4df5f7SStefano Zampini PetscInt n,i,j; 26261f4df5f7SStefano Zampini PetscInt n_neigh,*neigh,*n_shared,**shared; 26271f4df5f7SStefano Zampini PetscInt *iwork; 26281f4df5f7SStefano Zampini 26295f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetSize(matis->rmapping,&n)); 26305f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetInfo(matis->rmapping,&n_neigh,&neigh,&n_shared,&shared)); 26315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(n,&iwork)); 26325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n,&interior_dofs)); 263390648384SStefano Zampini for (i=1;i<n_neigh;i++) 26341f4df5f7SStefano Zampini for (j=0;j<n_shared[i];j++) 26351f4df5f7SStefano Zampini iwork[shared[i][j]] += 1; 26361f4df5f7SStefano Zampini for (i=0;i<n;i++) 26371f4df5f7SStefano Zampini if (!iwork[i]) 26381f4df5f7SStefano Zampini interior_dofs[n_interior_dofs++] = i; 26395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(iwork)); 26405f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreInfo(matis->rmapping,&n_neigh,&neigh,&n_shared,&shared)); 26411f4df5f7SStefano Zampini } 26424f1b2e48SStefano Zampini if (has_null_pressures) { 26434f1b2e48SStefano Zampini IS *subs; 26444edc6404Sstefano_zampini PetscInt nsubs,i,j,nl; 26451f4df5f7SStefano Zampini const PetscInt *idxs; 26461f4df5f7SStefano Zampini PetscScalar *array; 26471f4df5f7SStefano Zampini Vec *work; 26484f1b2e48SStefano Zampini 26494f1b2e48SStefano Zampini subs = pcbddc->local_subs; 26504f1b2e48SStefano Zampini nsubs = pcbddc->n_local_subs; 26511f4df5f7SStefano Zampini /* these vectors are needed to check if the constant on pressures is in the kernel of the local operator B (i.e. B(v_I,p0) should be zero) */ 26524edc6404Sstefano_zampini if (checkb) { 26535f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicateVecs(matis->y,2,&work)); 26545f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(zerodiag,&nl)); 26555f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(zerodiag,&idxs)); 26561f4df5f7SStefano Zampini /* work[0] = 1_p */ 26575f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(work[0],0.)); 26585f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(work[0],&array)); 26591f4df5f7SStefano Zampini for (j=0;j<nl;j++) array[idxs[j]] = 1.; 26605f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(work[0],&array)); 26611f4df5f7SStefano Zampini /* work[0] = 1_v */ 26625f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(work[1],1.)); 26635f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(work[1],&array)); 26641f4df5f7SStefano Zampini for (j=0;j<nl;j++) array[idxs[j]] = 0.; 26655f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(work[1],&array)); 26665f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(zerodiag,&idxs)); 26671f4df5f7SStefano Zampini } 26683b03f7bbSStefano Zampini 26693b03f7bbSStefano Zampini if (nsubs > 1 || bsp > 1) { 26703b03f7bbSStefano Zampini IS *is; 26713b03f7bbSStefano Zampini PetscInt b,totb; 26723b03f7bbSStefano Zampini 26733b03f7bbSStefano Zampini totb = bsp; 26743b03f7bbSStefano Zampini is = bsp > 1 ? bzerodiag : &zerodiag; 26753b03f7bbSStefano Zampini nsubs = PetscMax(nsubs,1); 26765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(nsubs*totb,&zerodiag_subs)); 26773b03f7bbSStefano Zampini for (b=0;b<totb;b++) { 26784f1b2e48SStefano Zampini for (i=0;i<nsubs;i++) { 26794f1b2e48SStefano Zampini ISLocalToGlobalMapping l2g; 26804f1b2e48SStefano Zampini IS t_zerodiag_subs; 26814f1b2e48SStefano Zampini PetscInt nl; 26824f1b2e48SStefano Zampini 26833b03f7bbSStefano Zampini if (subs) { 26845f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(subs[i],&l2g)); 26853b03f7bbSStefano Zampini } else { 26863b03f7bbSStefano Zampini IS tis; 26873b03f7bbSStefano Zampini 26885f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(pcbddc->local_mat,&nl,NULL)); 26895f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,nl,0,1,&tis)); 26905f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(tis,&l2g)); 26915f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&tis)); 26923b03f7bbSStefano Zampini } 26935f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,is[b],&t_zerodiag_subs)); 26945f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(t_zerodiag_subs,&nl)); 26954f1b2e48SStefano Zampini if (nl) { 26964f1b2e48SStefano Zampini PetscBool valid = PETSC_TRUE; 26974f1b2e48SStefano Zampini 26984edc6404Sstefano_zampini if (checkb) { 26995f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(matis->x,0)); 27005f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(subs[i],&nl)); 27015f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(subs[i],&idxs)); 27025f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(matis->x,&array)); 27031f4df5f7SStefano Zampini for (j=0;j<nl;j++) array[idxs[j]] = 1.; 27045f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(matis->x,&array)); 27055f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(subs[i],&idxs)); 27065f80ce2aSJacob Faibussowitsch CHKERRQ(VecPointwiseMult(matis->x,work[0],matis->x)); 27075f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(matis->A,matis->x,matis->y)); 27085f80ce2aSJacob Faibussowitsch CHKERRQ(VecPointwiseMult(matis->y,work[1],matis->y)); 27095f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(matis->y,&array)); 27101f4df5f7SStefano Zampini for (j=0;j<n_interior_dofs;j++) { 27111f4df5f7SStefano Zampini if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) { 27121f4df5f7SStefano Zampini valid = PETSC_FALSE; 27131f4df5f7SStefano Zampini break; 27141f4df5f7SStefano Zampini } 27151f4df5f7SStefano Zampini } 27165f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(matis->y,&array)); 27171f4df5f7SStefano Zampini } 27186632bad2Sstefano_zampini if (valid && nneu) { 27196632bad2Sstefano_zampini const PetscInt *idxs; 27201f4df5f7SStefano Zampini PetscInt nzb; 27211f4df5f7SStefano Zampini 27225f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs)); 27235f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApply(l2g,IS_GTOLM_DROP,nneu,idxs,&nzb,NULL)); 27245f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs)); 27251f4df5f7SStefano Zampini if (nzb) valid = PETSC_FALSE; 27261f4df5f7SStefano Zampini } 27271f4df5f7SStefano Zampini if (valid && pressures) { 27283b03f7bbSStefano Zampini IS t_pressure_subs,tmp; 27293b03f7bbSStefano Zampini PetscInt i1,i2; 27303b03f7bbSStefano Zampini 27315f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs)); 27325f80ce2aSJacob Faibussowitsch CHKERRQ(ISEmbed(t_zerodiag_subs,t_pressure_subs,PETSC_TRUE,&tmp)); 27335f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(tmp,&i1)); 27345f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(t_zerodiag_subs,&i2)); 27353b03f7bbSStefano Zampini if (i2 != i1) valid = PETSC_FALSE; 27365f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&t_pressure_subs)); 27375f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&tmp)); 27384f1b2e48SStefano Zampini } 27394f1b2e48SStefano Zampini if (valid) { 27405f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[benign_n])); 27413b03f7bbSStefano Zampini benign_n++; 27423b03f7bbSStefano Zampini } else recompute_zerodiag = PETSC_TRUE; 27434f1b2e48SStefano Zampini } 27445f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&t_zerodiag_subs)); 27455f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&l2g)); 27464f1b2e48SStefano Zampini } 27473b03f7bbSStefano Zampini } 27484f1b2e48SStefano Zampini } else { /* there's just one subdomain (or zero if they have not been detected */ 27494f1b2e48SStefano Zampini PetscBool valid = PETSC_TRUE; 27501f4df5f7SStefano Zampini 27516632bad2Sstefano_zampini if (nneu) valid = PETSC_FALSE; 27521f4df5f7SStefano Zampini if (valid && pressures) { 27535f80ce2aSJacob Faibussowitsch CHKERRQ(ISEqual(pressures,zerodiag,&valid)); 27544f1b2e48SStefano Zampini } 27554edc6404Sstefano_zampini if (valid && checkb) { 27565f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(matis->A,work[0],matis->x)); 27575f80ce2aSJacob Faibussowitsch CHKERRQ(VecPointwiseMult(matis->x,work[1],matis->x)); 27585f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(matis->x,&array)); 27591f4df5f7SStefano Zampini for (j=0;j<n_interior_dofs;j++) { 27601f4df5f7SStefano Zampini if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) { 27611f4df5f7SStefano Zampini valid = PETSC_FALSE; 27621f4df5f7SStefano Zampini break; 27631f4df5f7SStefano Zampini } 27641f4df5f7SStefano Zampini } 27655f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(matis->x,&array)); 27661f4df5f7SStefano Zampini } 27674f1b2e48SStefano Zampini if (valid) { 27683b03f7bbSStefano Zampini benign_n = 1; 27695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(benign_n,&zerodiag_subs)); 27705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)zerodiag)); 27714f1b2e48SStefano Zampini zerodiag_subs[0] = zerodiag; 27724f1b2e48SStefano Zampini } 27734f1b2e48SStefano Zampini } 27744edc6404Sstefano_zampini if (checkb) { 27755f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroyVecs(2,&work)); 27764f1b2e48SStefano Zampini } 27771f4df5f7SStefano Zampini } 27785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(interior_dofs)); 27794f1b2e48SStefano Zampini 27803b03f7bbSStefano Zampini if (!benign_n) { 2781b9b0e38cSStefano Zampini PetscInt n; 2782b9b0e38cSStefano Zampini 27835f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&zerodiag)); 27844f1b2e48SStefano Zampini recompute_zerodiag = PETSC_FALSE; 27855f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(pcbddc->local_mat,&n,NULL)); 278676a58201SStefano Zampini if (n) have_null = PETSC_FALSE; 2787b9b0e38cSStefano Zampini } 27884f1b2e48SStefano Zampini 27894f1b2e48SStefano Zampini /* final check for null pressures */ 27904f1b2e48SStefano Zampini if (zerodiag && pressures) { 27915f80ce2aSJacob Faibussowitsch CHKERRQ(ISEqual(pressures,zerodiag,&have_null)); 27924f1b2e48SStefano Zampini } 27934f1b2e48SStefano Zampini 27944f1b2e48SStefano Zampini if (recompute_zerodiag) { 27955f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&zerodiag)); 27963b03f7bbSStefano Zampini if (benign_n == 1) { 27975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)zerodiag_subs[0])); 27984f1b2e48SStefano Zampini zerodiag = zerodiag_subs[0]; 27994f1b2e48SStefano Zampini } else { 28004f1b2e48SStefano Zampini PetscInt i,nzn,*new_idxs; 28014f1b2e48SStefano Zampini 28024f1b2e48SStefano Zampini nzn = 0; 28033b03f7bbSStefano Zampini for (i=0;i<benign_n;i++) { 28044f1b2e48SStefano Zampini PetscInt ns; 28055f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(zerodiag_subs[i],&ns)); 28064f1b2e48SStefano Zampini nzn += ns; 28074f1b2e48SStefano Zampini } 28085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nzn,&new_idxs)); 28094f1b2e48SStefano Zampini nzn = 0; 28103b03f7bbSStefano Zampini for (i=0;i<benign_n;i++) { 28114f1b2e48SStefano Zampini PetscInt ns,*idxs; 28125f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(zerodiag_subs[i],&ns)); 28135f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs)); 28145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(new_idxs+nzn,idxs,ns)); 28155f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs)); 28164f1b2e48SStefano Zampini nzn += ns; 28174f1b2e48SStefano Zampini } 28185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortInt(nzn,new_idxs)); 28195f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag)); 28204f1b2e48SStefano Zampini } 28214f1b2e48SStefano Zampini have_null = PETSC_FALSE; 28224f1b2e48SStefano Zampini } 28234f1b2e48SStefano Zampini 28243b03f7bbSStefano Zampini /* determines if the coarse solver will be singular or not */ 28255f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc))); 28263b03f7bbSStefano Zampini 2827669cc0f4SStefano Zampini /* Prepare matrix to compute no-net-flux */ 2828a198735bSStefano Zampini if (pcbddc->compute_nonetflux && !pcbddc->divudotp) { 2829a198735bSStefano Zampini Mat A,loc_divudotp; 2830a198735bSStefano Zampini ISLocalToGlobalMapping rl2g,cl2g,l2gmap; 2831a198735bSStefano Zampini IS row,col,isused = NULL; 2832a198735bSStefano Zampini PetscInt M,N,n,st,n_isused; 2833a198735bSStefano Zampini 28341f4df5f7SStefano Zampini if (pressures) { 28351f4df5f7SStefano Zampini isused = pressures; 28361f4df5f7SStefano Zampini } else { 28374edc6404Sstefano_zampini isused = zerodiag_save; 28381f4df5f7SStefano Zampini } 28395f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL)); 28405f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(pc->pmat,&A)); 28415f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(A,&n,NULL)); 28422c71b3e2SJacob Faibussowitsch PetscCheckFalse(!isused && n,PETSC_COMM_SELF,PETSC_ERR_USER,"Don't know how to extract div u dot p! Please provide the pressure field"); 2843a198735bSStefano Zampini n_isused = 0; 2844a198735bSStefano Zampini if (isused) { 28455f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(isused,&n_isused)); 2846a198735bSStefano Zampini } 28475f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc))); 2848a198735bSStefano Zampini st = st-n_isused; 28491ae86dd6SStefano Zampini if (n) { 2850a198735bSStefano Zampini const PetscInt *gidxs; 2851a198735bSStefano Zampini 28525f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp)); 28535f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs)); 2854a198735bSStefano Zampini /* TODO: extend ISCreateStride with st = PETSC_DECIDE */ 28555f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row)); 28565f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col)); 28575f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs)); 28581ae86dd6SStefano Zampini } else { 28595f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp)); 28605f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row)); 28615f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col)); 2862a198735bSStefano Zampini } 28635f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(pc->pmat,NULL,&N)); 28645f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(row,&M)); 28655f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(row,&rl2g)); 28665f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(col,&cl2g)); 28675f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&row)); 28685f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&col)); 28695f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp)); 28705f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(pcbddc->divudotp,MATIS)); 28715f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N)); 28725f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g)); 28735f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&rl2g)); 28745f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&cl2g)); 28755f80ce2aSJacob Faibussowitsch CHKERRQ(MatISSetLocalMat(pcbddc->divudotp,loc_divudotp)); 28765f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&loc_divudotp)); 28775f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY)); 28785f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY)); 28791ae86dd6SStefano Zampini } 28805f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&zerodiag_save)); 28815f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pressures)); 28823b03f7bbSStefano Zampini if (bzerodiag) { 28833b03f7bbSStefano Zampini PetscInt i; 2884b3afcdbeSStefano Zampini 28853b03f7bbSStefano Zampini for (i=0;i<bsp;i++) { 28865f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&bzerodiag[i])); 28873b03f7bbSStefano Zampini } 28885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(bzerodiag)); 28893b03f7bbSStefano Zampini } 28903b03f7bbSStefano Zampini pcbddc->benign_n = benign_n; 28913b03f7bbSStefano Zampini pcbddc->benign_zerodiag_subs = zerodiag_subs; 28923b03f7bbSStefano Zampini 28933b03f7bbSStefano Zampini /* determines if the problem has subdomains with 0 pressure block */ 28943b03f7bbSStefano Zampini have_null = (PetscBool)(!!pcbddc->benign_n); 28955f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc))); 28963b03f7bbSStefano Zampini 28973b03f7bbSStefano Zampini project_b0: 28985f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(pcbddc->local_mat,&n,NULL)); 2899b3afcdbeSStefano Zampini /* change of basis and p0 dofs */ 29003b03f7bbSStefano Zampini if (pcbddc->benign_n) { 29014f1b2e48SStefano Zampini PetscInt i,s,*nnz; 29024f1b2e48SStefano Zampini 2903339f8db1SStefano Zampini /* local change of basis for pressures */ 29045f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->benign_change)); 29055f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change)); 29065f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(pcbddc->benign_change,MATAIJ)); 29075f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE)); 29085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n,&nnz)); 2909aa0d93e9SStefano Zampini for (i=0;i<n;i++) nnz[i] = 1; /* defaults to identity */ 29104f1b2e48SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) { 2911aa0d93e9SStefano Zampini const PetscInt *idxs; 29124f1b2e48SStefano Zampini PetscInt nzs,j; 29134f1b2e48SStefano Zampini 29145f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nzs)); 29155f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcbddc->benign_zerodiag_subs[i],&idxs)); 29164f1b2e48SStefano Zampini for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */ 29174f1b2e48SStefano Zampini nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */ 29185f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],&idxs)); 29194f1b2e48SStefano Zampini } 29205f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz)); 29215f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(pcbddc->benign_change,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE)); 29225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(nnz)); 2923aa0d93e9SStefano Zampini /* set identity by default */ 2924aa0d93e9SStefano Zampini for (i=0;i<n;i++) { 29255f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(pcbddc->benign_change,i,i,1.,INSERT_VALUES)); 2926339f8db1SStefano Zampini } 29275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0)); 29285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(pcbddc->benign_n,&pcbddc->benign_p0_lidx,pcbddc->benign_n,&pcbddc->benign_p0_gidx,pcbddc->benign_n,&pcbddc->benign_p0)); 2929339f8db1SStefano Zampini /* set change on pressures */ 29304f1b2e48SStefano Zampini for (s=0;s<pcbddc->benign_n;s++) { 29314f1b2e48SStefano Zampini PetscScalar *array; 2932aa0d93e9SStefano Zampini const PetscInt *idxs; 29334f1b2e48SStefano Zampini PetscInt nzs; 29344f1b2e48SStefano Zampini 29355f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pcbddc->benign_zerodiag_subs[s],&nzs)); 29365f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcbddc->benign_zerodiag_subs[s],&idxs)); 29374f1b2e48SStefano Zampini for (i=0;i<nzs-1;i++) { 2938339f8db1SStefano Zampini PetscScalar vals[2]; 2939339f8db1SStefano Zampini PetscInt cols[2]; 2940339f8db1SStefano Zampini 2941339f8db1SStefano Zampini cols[0] = idxs[i]; 29424f1b2e48SStefano Zampini cols[1] = idxs[nzs-1]; 2943339f8db1SStefano Zampini vals[0] = 1.; 2944b0f5fe93SStefano Zampini vals[1] = 1.; 29455f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES)); 2946339f8db1SStefano Zampini } 29475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nzs,&array)); 29484f1b2e48SStefano Zampini for (i=0;i<nzs-1;i++) array[i] = -1.; 29494f1b2e48SStefano Zampini array[nzs-1] = 1.; 29505f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES)); 29514f1b2e48SStefano Zampini /* store local idxs for p0 */ 29524f1b2e48SStefano Zampini pcbddc->benign_p0_lidx[s] = idxs[nzs-1]; 29535f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcbddc->benign_zerodiag_subs[s],&idxs)); 29545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(array)); 29554f1b2e48SStefano Zampini } 29565f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY)); 29575f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY)); 29583b03f7bbSStefano Zampini 2959a3df083aSStefano Zampini /* project if needed */ 2960a3df083aSStefano Zampini if (pcbddc->benign_change_explicit) { 29611dd7afcfSStefano Zampini Mat M; 29621dd7afcfSStefano Zampini 29635f80ce2aSJacob Faibussowitsch CHKERRQ(MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M)); 29645f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->local_mat)); 29655f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJCompress(M,&pcbddc->local_mat)); 29665f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&M)); 2967a3df083aSStefano Zampini } 29684f1b2e48SStefano Zampini /* store global idxs for p0 */ 29695f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(matis->rmapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx)); 2970339f8db1SStefano Zampini } 2971339f8db1SStefano Zampini *zerodiaglocal = zerodiag; 2972339f8db1SStefano Zampini PetscFunctionReturn(0); 2973339f8db1SStefano Zampini } 2974339f8db1SStefano Zampini 2975015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get) 2976efc2fbd9SStefano Zampini { 2977efc2fbd9SStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 2978de9d7bd0SStefano Zampini PetscScalar *array; 2979efc2fbd9SStefano Zampini 2980efc2fbd9SStefano Zampini PetscFunctionBegin; 2981efc2fbd9SStefano Zampini if (!pcbddc->benign_sf) { 29825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf)); 29835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx)); 2984efc2fbd9SStefano Zampini } 2985de9d7bd0SStefano Zampini if (get) { 29865f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(v,(const PetscScalar**)&array)); 29875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0,MPI_REPLACE)); 29885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0,MPI_REPLACE)); 29895f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(v,(const PetscScalar**)&array)); 2990de9d7bd0SStefano Zampini } else { 29915f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(v,&array)); 29925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPI_REPLACE)); 29935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPI_REPLACE)); 29945f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(v,&array)); 2995efc2fbd9SStefano Zampini } 2996efc2fbd9SStefano Zampini PetscFunctionReturn(0); 2997efc2fbd9SStefano Zampini } 2998efc2fbd9SStefano Zampini 2999c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop) 3000c263805aSStefano Zampini { 3001c263805aSStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 3002c263805aSStefano Zampini 3003c263805aSStefano Zampini PetscFunctionBegin; 3004c263805aSStefano Zampini /* TODO: add error checking 3005c263805aSStefano Zampini - avoid nested pop (or push) calls. 3006c263805aSStefano Zampini - cannot push before pop. 30071c604dc7SStefano Zampini - cannot call this if pcbddc->local_mat is NULL 3008c263805aSStefano Zampini */ 30094f1b2e48SStefano Zampini if (!pcbddc->benign_n) { 3010efc2fbd9SStefano Zampini PetscFunctionReturn(0); 3011efc2fbd9SStefano Zampini } 3012c263805aSStefano Zampini if (pop) { 3013a3df083aSStefano Zampini if (pcbddc->benign_change_explicit) { 30144f1b2e48SStefano Zampini IS is_p0; 30154f1b2e48SStefano Zampini MatReuse reuse; 3016c263805aSStefano Zampini 3017c263805aSStefano Zampini /* extract B_0 */ 30184f1b2e48SStefano Zampini reuse = MAT_INITIAL_MATRIX; 30194f1b2e48SStefano Zampini if (pcbddc->benign_B0) { 30204f1b2e48SStefano Zampini reuse = MAT_REUSE_MATRIX; 30214f1b2e48SStefano Zampini } 30225f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0)); 30235f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0)); 3024c263805aSStefano Zampini /* remove rows and cols from local problem */ 30255f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE)); 30265f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE)); 30275f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL)); 30285f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_p0)); 3029a3df083aSStefano Zampini } else { 3030a3df083aSStefano Zampini Mat_IS *matis = (Mat_IS*)pc->pmat->data; 3031a3df083aSStefano Zampini PetscScalar *vals; 3032a3df083aSStefano Zampini PetscInt i,n,*idxs_ins; 3033a3df083aSStefano Zampini 30345f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(matis->y,&n)); 30355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(n,&idxs_ins,n,&vals)); 3036a3df083aSStefano Zampini if (!pcbddc->benign_B0) { 30370b5adadeSStefano Zampini PetscInt *nnz; 30385f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0)); 30395f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(pcbddc->benign_B0,MATAIJ)); 30405f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE)); 30415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->benign_n,&nnz)); 3042331e053bSStefano Zampini for (i=0;i<pcbddc->benign_n;i++) { 30435f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i])); 3044331e053bSStefano Zampini nnz[i] = n - nnz[i]; 3045331e053bSStefano Zampini } 30465f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz)); 30475f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(pcbddc->benign_B0,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE)); 30485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(nnz)); 3049331e053bSStefano Zampini } 3050a3df083aSStefano Zampini 3051a3df083aSStefano Zampini for (i=0;i<pcbddc->benign_n;i++) { 3052a3df083aSStefano Zampini PetscScalar *array; 3053a3df083aSStefano Zampini PetscInt *idxs,j,nz,cum; 3054a3df083aSStefano Zampini 30555f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(matis->x,0.)); 30565f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz)); 30575f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs)); 3058a3df083aSStefano Zampini for (j=0;j<nz;j++) vals[j] = 1.; 30595f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES)); 30605f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(matis->x)); 30615f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(matis->x)); 30625f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(matis->y,0.)); 30635f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(matis->A,matis->x,matis->y)); 30645f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(matis->y,&array)); 3065a3df083aSStefano Zampini cum = 0; 3066a3df083aSStefano Zampini for (j=0;j<n;j++) { 306722db5ddcSStefano Zampini if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) { 3068a3df083aSStefano Zampini vals[cum] = array[j]; 3069a3df083aSStefano Zampini idxs_ins[cum] = j; 3070a3df083aSStefano Zampini cum++; 3071a3df083aSStefano Zampini } 3072a3df083aSStefano Zampini } 30735f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES)); 30745f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(matis->y,&array)); 30755f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs)); 3076a3df083aSStefano Zampini } 30775f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY)); 30785f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY)); 30795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(idxs_ins,vals)); 3080a3df083aSStefano Zampini } 3081c263805aSStefano Zampini } else { /* push */ 3082a3df083aSStefano Zampini if (pcbddc->benign_change_explicit) { 30834f1b2e48SStefano Zampini PetscInt i; 30844f1b2e48SStefano Zampini 30854f1b2e48SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) { 30864f1b2e48SStefano Zampini PetscScalar *B0_vals; 30874f1b2e48SStefano Zampini PetscInt *B0_cols,B0_ncol; 30884f1b2e48SStefano Zampini 30895f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals)); 30905f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES)); 30915f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES)); 30925f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES)); 30935f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals)); 30944f1b2e48SStefano Zampini } 30955f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY)); 30965f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY)); 30976080607fSStefano Zampini } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!"); 3098c263805aSStefano Zampini } 3099c263805aSStefano Zampini PetscFunctionReturn(0); 3100c263805aSStefano Zampini } 3101c263805aSStefano Zampini 310208122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc) 3103b1b3d7a2SStefano Zampini { 3104b1b3d7a2SStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 310508122e43SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 310608122e43SStefano Zampini PetscBLASInt B_dummyint,B_neigs,B_ierr,B_lwork; 310708122e43SStefano Zampini PetscBLASInt *B_iwork,*B_ifail; 310808122e43SStefano Zampini PetscScalar *work,lwork; 310908122e43SStefano Zampini PetscScalar *St,*S,*eigv; 311008122e43SStefano Zampini PetscScalar *Sarray,*Starray; 3111bd2a564bSStefano Zampini PetscReal *eigs,thresh,lthresh,uthresh; 31121b968477SStefano Zampini PetscInt i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs; 3113f6f667cfSStefano Zampini PetscBool allocated_S_St; 311408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 311508122e43SStefano Zampini PetscReal *rwork; 311608122e43SStefano Zampini #endif 3117b1b3d7a2SStefano Zampini PetscErrorCode ierr; 3118b1b3d7a2SStefano Zampini 3119b1b3d7a2SStefano Zampini PetscFunctionBegin; 3120*28b400f6SJacob Faibussowitsch PetscCheck(sub_schurs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data"); 3121*28b400f6SJacob Faibussowitsch PetscCheck(sub_schurs->schur_explicit,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO"); 31222c71b3e2SJacob Faibussowitsch PetscCheckFalse(sub_schurs->n_subs && (!sub_schurs->is_symmetric),PETSC_COMM_SELF,PETSC_ERR_SUP,"Adaptive selection not yet implemented for this matrix pencil (herm %d, symm %d, posdef %d)",sub_schurs->is_hermitian,sub_schurs->is_symmetric,sub_schurs->is_posdef); 31235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0)); 312406a4e24aSStefano Zampini 3125fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 31265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 31275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n")); 31285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n")); 31295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 3130fd14bc51SStefano Zampini } 3131fd14bc51SStefano Zampini 3132e496cd5dSStefano Zampini if (pcbddc->dbg_flag) { 31335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d cc %D (%d,%d).\n",PetscGlobalRank,sub_schurs->n_subs,sub_schurs->is_hermitian,sub_schurs->is_posdef)); 3134e496cd5dSStefano Zampini } 3135e496cd5dSStefano Zampini 313608122e43SStefano Zampini /* max size of subsets */ 313708122e43SStefano Zampini mss = 0; 313808122e43SStefano Zampini for (i=0;i<sub_schurs->n_subs;i++) { 313908122e43SStefano Zampini PetscInt subset_size; 3140862806e4SStefano Zampini 31415f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(sub_schurs->is_subs[i],&subset_size)); 314208122e43SStefano Zampini mss = PetscMax(mss,subset_size); 314308122e43SStefano Zampini } 314408122e43SStefano Zampini 314508122e43SStefano Zampini /* min/max and threshold */ 314608122e43SStefano Zampini nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss; 3147f6f667cfSStefano Zampini nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0; 314808122e43SStefano Zampini nmax = PetscMax(nmin,nmax); 3149f6f667cfSStefano Zampini allocated_S_St = PETSC_FALSE; 3150bd2a564bSStefano Zampini if (nmin || !sub_schurs->is_posdef) { /* XXX */ 3151f6f667cfSStefano Zampini allocated_S_St = PETSC_TRUE; 3152f6f667cfSStefano Zampini } 315308122e43SStefano Zampini 315408122e43SStefano Zampini /* allocate lapack workspace */ 315508122e43SStefano Zampini cum = cum2 = 0; 315608122e43SStefano Zampini maxneigs = 0; 315708122e43SStefano Zampini for (i=0;i<sub_schurs->n_subs;i++) { 315808122e43SStefano Zampini PetscInt n,subset_size; 3159f6f667cfSStefano Zampini 31605f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(sub_schurs->is_subs[i],&subset_size)); 316108122e43SStefano Zampini n = PetscMin(subset_size,nmax); 31629162d606SStefano Zampini cum += subset_size; 31639162d606SStefano Zampini cum2 += subset_size*n; 316408122e43SStefano Zampini maxneigs = PetscMax(maxneigs,n); 316508122e43SStefano Zampini } 31667ebab0bbSStefano Zampini lwork = 0; 316708122e43SStefano Zampini if (mss) { 3168bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 31697ebab0bbSStefano Zampini PetscScalar sdummy = 0.; 317008122e43SStefano Zampini PetscBLASInt B_itype = 1; 31717ebab0bbSStefano Zampini PetscBLASInt B_N = mss, idummy = 0; 31727ebab0bbSStefano Zampini PetscReal rdummy = 0.,zero = 0.0; 31734c6709b3SStefano Zampini PetscReal eps = 0.0; /* dlamch? */ 317408122e43SStefano Zampini 317508122e43SStefano Zampini B_lwork = -1; 31767ebab0bbSStefano Zampini /* some implementations may complain about NULL pointers, even if we are querying */ 31777ebab0bbSStefano Zampini S = &sdummy; 31787ebab0bbSStefano Zampini St = &sdummy; 31797ebab0bbSStefano Zampini eigs = &rdummy; 31807ebab0bbSStefano Zampini eigv = &sdummy; 31817ebab0bbSStefano Zampini B_iwork = &idummy; 31827ebab0bbSStefano Zampini B_ifail = &idummy; 3183d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX) 31847ebab0bbSStefano Zampini rwork = &rdummy; 3185d1710679SStefano Zampini #endif 31868bec7fa6SStefano Zampini thresh = 1.0; 31875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 318808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 318908122e43SStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&zero,&thresh,&B_dummyint,&B_dummyint,&eps,&B_neigs,eigs,eigv,&B_N,&lwork,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 319008122e43SStefano Zampini #else 319108122e43SStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&zero,&thresh,&B_dummyint,&B_dummyint,&eps,&B_neigs,eigs,eigv,&B_N,&lwork,&B_lwork,B_iwork,B_ifail,&B_ierr)); 319208122e43SStefano Zampini #endif 31932c71b3e2SJacob Faibussowitsch PetscCheckFalse(B_ierr != 0,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr); 31945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 3195bd2a564bSStefano Zampini } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented"); 319608122e43SStefano Zampini } 319708122e43SStefano Zampini 319808122e43SStefano Zampini nv = 0; 3199d62866d3SStefano Zampini if (sub_schurs->is_vertices && pcbddc->use_vertices) { /* complement set of active subsets, each entry is a vertex (boundary made by active subsets, vertices and dirichlet dofs) */ 32005f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(sub_schurs->is_vertices,&nv)); 320108122e43SStefano Zampini } 32025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork)); 3203f6f667cfSStefano Zampini if (allocated_S_St) { 32045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(mss*mss,&S,mss*mss,&St)); 3205f6f667cfSStefano Zampini } 32065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail)); 320708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 32085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(7*mss,&rwork)); 320908122e43SStefano Zampini #endif 32109162d606SStefano Zampini ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n, 32119162d606SStefano Zampini nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr, 32129162d606SStefano Zampini nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr, 321308122e43SStefano Zampini nv+cum,&pcbddc->adaptive_constraints_idxs, 32149162d606SStefano Zampini nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr); 32155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(pcbddc->adaptive_constraints_n,nv+sub_schurs->n_subs)); 321608122e43SStefano Zampini 321708122e43SStefano Zampini maxneigs = 0; 321872b8c272SStefano Zampini cum = cumarray = 0; 32199162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[0] = 0; 32209162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[0] = 0; 3221d62866d3SStefano Zampini if (sub_schurs->is_vertices && pcbddc->use_vertices) { 322208122e43SStefano Zampini const PetscInt *idxs; 322308122e43SStefano Zampini 32245f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(sub_schurs->is_vertices,&idxs)); 322508122e43SStefano Zampini for (cum=0;cum<nv;cum++) { 322608122e43SStefano Zampini pcbddc->adaptive_constraints_n[cum] = 1; 322708122e43SStefano Zampini pcbddc->adaptive_constraints_idxs[cum] = idxs[cum]; 322808122e43SStefano Zampini pcbddc->adaptive_constraints_data[cum] = 1.0; 32299162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1; 32309162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1; 323108122e43SStefano Zampini } 32325f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(sub_schurs->is_vertices,&idxs)); 323308122e43SStefano Zampini } 323408122e43SStefano Zampini 323508122e43SStefano Zampini if (mss) { /* multilevel */ 32365f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray)); 32375f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray)); 323808122e43SStefano Zampini } 323908122e43SStefano Zampini 3240bd2a564bSStefano Zampini lthresh = pcbddc->adaptive_threshold[0]; 3241bd2a564bSStefano Zampini uthresh = pcbddc->adaptive_threshold[1]; 324208122e43SStefano Zampini for (i=0;i<sub_schurs->n_subs;i++) { 324308122e43SStefano Zampini const PetscInt *idxs; 32449d54b7f4SStefano Zampini PetscReal upper,lower; 3245862806e4SStefano Zampini PetscInt j,subset_size,eigs_start = 0; 324608122e43SStefano Zampini PetscBLASInt B_N; 3247aff50787SStefano Zampini PetscBool same_data = PETSC_FALSE; 3248bd2a564bSStefano Zampini PetscBool scal = PETSC_FALSE; 324908122e43SStefano Zampini 32509d54b7f4SStefano Zampini if (pcbddc->use_deluxe_scaling) { 32519d54b7f4SStefano Zampini upper = PETSC_MAX_REAL; 3252bd2a564bSStefano Zampini lower = uthresh; 32539d54b7f4SStefano Zampini } else { 3254*28b400f6SJacob Faibussowitsch PetscCheck(sub_schurs->is_posdef,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented without deluxe scaling"); 3255bd2a564bSStefano Zampini upper = 1./uthresh; 32569d54b7f4SStefano Zampini lower = 0.; 32579d54b7f4SStefano Zampini } 32585f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(sub_schurs->is_subs[i],&subset_size)); 32595f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(sub_schurs->is_subs[i],&idxs)); 32605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(subset_size,&B_N)); 3261bd2a564bSStefano Zampini /* this is experimental: we assume the dofs have been properly grouped to have 3262bd2a564bSStefano Zampini the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */ 3263bd2a564bSStefano Zampini if (!sub_schurs->is_posdef) { 3264bd2a564bSStefano Zampini Mat T; 3265bd2a564bSStefano Zampini 3266bd2a564bSStefano Zampini for (j=0;j<subset_size;j++) { 3267bd2a564bSStefano Zampini if (PetscRealPart(*(Sarray+cumarray+j*(subset_size+1))) < 0.0) { 32685f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Sarray+cumarray,&T)); 32695f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(T,-1.0)); 32705f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&T)); 32715f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,Starray+cumarray,&T)); 32725f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(T,-1.0)); 32735f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&T)); 3274bd2a564bSStefano Zampini if (sub_schurs->change_primal_sub) { 3275bd2a564bSStefano Zampini PetscInt nz,k; 3276bd2a564bSStefano Zampini const PetscInt *idxs; 3277bd2a564bSStefano Zampini 32785f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(sub_schurs->change_primal_sub[i],&nz)); 32795f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(sub_schurs->change_primal_sub[i],&idxs)); 3280bd2a564bSStefano Zampini for (k=0;k<nz;k++) { 3281bd2a564bSStefano Zampini *( Sarray + cumarray + idxs[k]*(subset_size+1)) *= -1.0; 3282bd2a564bSStefano Zampini *(Starray + cumarray + idxs[k]*(subset_size+1)) = 0.0; 3283bd2a564bSStefano Zampini } 32845f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(sub_schurs->change_primal_sub[i],&idxs)); 3285bd2a564bSStefano Zampini } 3286bd2a564bSStefano Zampini scal = PETSC_TRUE; 3287bd2a564bSStefano Zampini break; 3288bd2a564bSStefano Zampini } 3289bd2a564bSStefano Zampini } 3290bd2a564bSStefano Zampini } 3291bd2a564bSStefano Zampini 3292f6f667cfSStefano Zampini if (allocated_S_St) { /* S and S_t should be copied since we could need them later */ 3293bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 3294aff50787SStefano Zampini PetscInt j,k; 3295580bdb30SBarry Smith if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscArraycmp() later */ 32965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(S,subset_size*subset_size)); 32975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(St,subset_size*subset_size)); 329808122e43SStefano Zampini } 329908122e43SStefano Zampini for (j=0;j<subset_size;j++) { 3300aff50787SStefano Zampini for (k=j;k<subset_size;k++) { 3301aff50787SStefano Zampini S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k]; 3302aff50787SStefano Zampini St[j*subset_size+k] = Starray[cumarray+j*subset_size+k]; 3303aff50787SStefano Zampini } 330408122e43SStefano Zampini } 330508122e43SStefano Zampini } else { 33065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size)); 33075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size)); 330808122e43SStefano Zampini } 33098bec7fa6SStefano Zampini } else { 3310f6f667cfSStefano Zampini S = Sarray + cumarray; 3311f6f667cfSStefano Zampini St = Starray + cumarray; 33128bec7fa6SStefano Zampini } 3313aff50787SStefano Zampini /* see if we can save some work */ 3314b7ab4a40SStefano Zampini if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) { 33155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycmp(S,St,subset_size*subset_size,&same_data)); 3316aff50787SStefano Zampini } 3317aff50787SStefano Zampini 3318b7ab4a40SStefano Zampini if (same_data && !sub_schurs->change) { /* there's no need of constraints here */ 3319aff50787SStefano Zampini B_neigs = 0; 3320aff50787SStefano Zampini } else { 3321bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 332208122e43SStefano Zampini PetscBLASInt B_itype = 1; 3323f6f667cfSStefano Zampini PetscBLASInt B_IL, B_IU; 33244c6709b3SStefano Zampini PetscReal eps = -1.0; /* dlamch? */ 33259552c7c7SStefano Zampini PetscInt nmin_s; 3326bd2a564bSStefano Zampini PetscBool compute_range; 3327bd2a564bSStefano Zampini 33289036ceccSStefano Zampini B_neigs = 0; 3329bd2a564bSStefano Zampini compute_range = (PetscBool)!same_data; 3330bd2a564bSStefano Zampini if (nmin >= subset_size) compute_range = PETSC_FALSE; 333108122e43SStefano Zampini 3332fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 33339036ceccSStefano Zampini PetscInt nc = 0; 3334d16cbb6bSStefano Zampini 33359036ceccSStefano Zampini if (sub_schurs->change_primal_sub) { 33365f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(sub_schurs->change_primal_sub[i],&nc)); 33379036ceccSStefano Zampini } 33385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Computing for sub %D/%D size %D count %D fid %D (range %d) (change %D).\n",i,sub_schurs->n_subs,subset_size,pcbddc->mat_graph->count[idxs[0]]+1,pcbddc->mat_graph->which_dof[idxs[0]],compute_range,nc)); 3339b7ab4a40SStefano Zampini } 3340b7ab4a40SStefano Zampini 33415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 3342b7ab4a40SStefano Zampini if (compute_range) { 3343d16cbb6bSStefano Zampini 3344d16cbb6bSStefano Zampini /* ask for eigenvalues larger than thresh */ 3345bd2a564bSStefano Zampini if (sub_schurs->is_posdef) { 334608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 33479d54b7f4SStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 334808122e43SStefano Zampini #else 33499d54b7f4SStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 335008122e43SStefano Zampini #endif 33515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 3352bd2a564bSStefano Zampini } else { /* no theory so far, but it works nicely */ 33539036ceccSStefano Zampini PetscInt recipe = 0,recipe_m = 1; 3354bd2a564bSStefano Zampini PetscReal bb[2]; 3355bd2a564bSStefano Zampini 33565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe",&recipe,NULL)); 3357bd2a564bSStefano Zampini switch (recipe) { 3358bd2a564bSStefano Zampini case 0: 3359bd2a564bSStefano Zampini if (scal) { bb[0] = PETSC_MIN_REAL; bb[1] = lthresh; } 3360bd2a564bSStefano Zampini else { bb[0] = uthresh; bb[1] = PETSC_MAX_REAL; } 3361bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3362bd2a564bSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 3363bd2a564bSStefano Zampini #else 3364bd2a564bSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 3365bd2a564bSStefano Zampini #endif 33665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 3367bd2a564bSStefano Zampini break; 3368bd2a564bSStefano Zampini case 1: 3369bd2a564bSStefano Zampini bb[0] = PETSC_MIN_REAL; bb[1] = lthresh*lthresh; 3370bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3371bd2a564bSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 3372bd2a564bSStefano Zampini #else 3373bd2a564bSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 3374bd2a564bSStefano Zampini #endif 33755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 3376bd2a564bSStefano Zampini if (!scal) { 33779036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 3378bd2a564bSStefano Zampini 3379aed7e7d0SStefano Zampini bb[0] = PetscMax(lthresh*lthresh,uthresh); bb[1] = PETSC_MAX_REAL; 33805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size)); 33815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size)); 3382bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3383bd2a564bSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 3384bd2a564bSStefano Zampini #else 3385bd2a564bSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 3386bd2a564bSStefano Zampini #endif 33875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 3388bd2a564bSStefano Zampini B_neigs += B_neigs2; 3389bd2a564bSStefano Zampini } 3390bd2a564bSStefano Zampini break; 33919036ceccSStefano Zampini case 2: 33929036ceccSStefano Zampini if (scal) { 33939036ceccSStefano Zampini bb[0] = PETSC_MIN_REAL; 33949036ceccSStefano Zampini bb[1] = 0; 33959036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 33969036ceccSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 33979036ceccSStefano Zampini #else 33989036ceccSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 33999036ceccSStefano Zampini #endif 34005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 34019036ceccSStefano Zampini } else { 34029036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 34039036ceccSStefano Zampini PetscBool import = PETSC_FALSE; 34049036ceccSStefano Zampini 34059036ceccSStefano Zampini lthresh = PetscMax(lthresh,0.0); 34069036ceccSStefano Zampini if (lthresh > 0.0) { 34079036ceccSStefano Zampini bb[0] = PETSC_MIN_REAL; 34089036ceccSStefano Zampini bb[1] = lthresh*lthresh; 34099036ceccSStefano Zampini 34109036ceccSStefano Zampini import = PETSC_TRUE; 34119036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 34129036ceccSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 34139036ceccSStefano Zampini #else 34149036ceccSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 34159036ceccSStefano Zampini #endif 34165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 34179036ceccSStefano Zampini } 34189036ceccSStefano Zampini bb[0] = PetscMax(lthresh*lthresh,uthresh); 34199036ceccSStefano Zampini bb[1] = PETSC_MAX_REAL; 34209036ceccSStefano Zampini if (import) { 34215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size)); 34225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size)); 34239036ceccSStefano Zampini } 34249036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 34259036ceccSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 34269036ceccSStefano Zampini #else 34279036ceccSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 34289036ceccSStefano Zampini #endif 34295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 34309036ceccSStefano Zampini B_neigs += B_neigs2; 34319036ceccSStefano Zampini } 34329036ceccSStefano Zampini break; 34339036ceccSStefano Zampini case 3: 34349036ceccSStefano Zampini if (scal) { 34355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min_scal",&recipe_m,NULL)); 34369036ceccSStefano Zampini } else { 34375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL,((PetscObject)pc)->prefix,"-pc_bddc_adaptive_recipe3_min",&recipe_m,NULL)); 34389036ceccSStefano Zampini } 34399036ceccSStefano Zampini if (!scal) { 34409036ceccSStefano Zampini bb[0] = uthresh; 34419036ceccSStefano Zampini bb[1] = PETSC_MAX_REAL; 34429036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 34439036ceccSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 34449036ceccSStefano Zampini #else 34459036ceccSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 34469036ceccSStefano Zampini #endif 34475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 34489036ceccSStefano Zampini } 34499036ceccSStefano Zampini if (recipe_m > 0 && B_N - B_neigs > 0) { 34509036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 34519036ceccSStefano Zampini 34529036ceccSStefano Zampini B_IL = 1; 34535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(PetscMin(recipe_m,B_N - B_neigs),&B_IU)); 34545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size)); 34555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size)); 34569036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 34579036ceccSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 34589036ceccSStefano Zampini #else 34599036ceccSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 34609036ceccSStefano Zampini #endif 34615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 34629036ceccSStefano Zampini B_neigs += B_neigs2; 34639036ceccSStefano Zampini } 34649036ceccSStefano Zampini break; 346548cebe81SStefano Zampini case 4: 346648cebe81SStefano Zampini bb[0] = PETSC_MIN_REAL; bb[1] = lthresh; 346748cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX) 346848cebe81SStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 346948cebe81SStefano Zampini #else 347048cebe81SStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 347148cebe81SStefano Zampini #endif 34725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 347348cebe81SStefano Zampini { 347448cebe81SStefano Zampini PetscBLASInt B_neigs2 = 0; 347548cebe81SStefano Zampini 347648cebe81SStefano Zampini bb[0] = PetscMax(lthresh+PETSC_SMALL,uthresh); bb[1] = PETSC_MAX_REAL; 34775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size)); 34785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size)); 347948cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX) 348048cebe81SStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 348148cebe81SStefano Zampini #else 348248cebe81SStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*B_N,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 348348cebe81SStefano Zampini #endif 34845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 348548cebe81SStefano Zampini B_neigs += B_neigs2; 348648cebe81SStefano Zampini } 348748cebe81SStefano Zampini break; 348880db8efeSStefano Zampini case 5: /* same as before: first compute all eigenvalues, then filter */ 348980db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX) 349080db8efeSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","A","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 349180db8efeSStefano Zampini #else 349280db8efeSStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","A","L",&B_N,St,&B_N,S,&B_N,&bb[0],&bb[1],&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 349380db8efeSStefano Zampini #endif 34945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 349580db8efeSStefano Zampini { 349680db8efeSStefano Zampini PetscInt e,k,ne; 349780db8efeSStefano Zampini for (e=0,ne=0;e<B_neigs;e++) { 349880db8efeSStefano Zampini if (eigs[e] < lthresh || eigs[e] > uthresh) { 349980db8efeSStefano Zampini for (k=0;k<B_N;k++) S[ne*B_N+k] = eigv[e*B_N+k]; 350080db8efeSStefano Zampini eigs[ne] = eigs[e]; 350180db8efeSStefano Zampini ne++; 350280db8efeSStefano Zampini } 350380db8efeSStefano Zampini } 35045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(eigv,S,B_N*ne)); 350580db8efeSStefano Zampini B_neigs = ne; 350680db8efeSStefano Zampini } 350780db8efeSStefano Zampini break; 3508bd2a564bSStefano Zampini default: 350998921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unknown recipe %D",recipe); 3510bd2a564bSStefano Zampini } 3511bd2a564bSStefano Zampini } 3512bd2a564bSStefano Zampini } else if (!same_data) { /* this is just to see all the eigenvalues */ 3513d16cbb6bSStefano Zampini B_IU = PetscMax(1,PetscMin(B_N,nmax)); 3514d16cbb6bSStefano Zampini B_IL = 1; 3515d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 35169d54b7f4SStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 3517d16cbb6bSStefano Zampini #else 35189d54b7f4SStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 3519d16cbb6bSStefano Zampini #endif 35205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 3521b03ebc13SStefano Zampini } else { /* same_data is true, so just get the adaptive functional requested by the user */ 3522b7ab4a40SStefano Zampini PetscInt k; 3523*28b400f6SJacob Faibussowitsch PetscCheck(sub_schurs->change_primal_sub,PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen"); 35245f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax)); 35255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(nmax,&B_neigs)); 3526b7ab4a40SStefano Zampini nmin = nmax; 35275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(eigv,subset_size*nmax)); 3528b7ab4a40SStefano Zampini for (k=0;k<nmax;k++) { 3529b7ab4a40SStefano Zampini eigs[k] = 1./PETSC_SMALL; 3530b7ab4a40SStefano Zampini eigv[k*(subset_size+1)] = 1.0; 3531b7ab4a40SStefano Zampini } 3532d16cbb6bSStefano Zampini } 35335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 353408122e43SStefano Zampini if (B_ierr) { 35352c71b3e2SJacob Faibussowitsch PetscCheckFalse(B_ierr < 0,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr); 35362c71b3e2SJacob Faibussowitsch else PetscCheckFalse(B_ierr <= B_N,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr); 353798921bdaSJacob Faibussowitsch else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: leading minor of order %d is not positive definite",(int)B_ierr-B_N-1); 353808122e43SStefano Zampini } 353908122e43SStefano Zampini 354008122e43SStefano Zampini if (B_neigs > nmax) { 3541fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 35425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer," found %d eigs, more than maximum required %D.\n",B_neigs,nmax)); 3543fd14bc51SStefano Zampini } 3544bd2a564bSStefano Zampini if (pcbddc->use_deluxe_scaling) eigs_start = scal ? 0 : B_neigs-nmax; 354508122e43SStefano Zampini B_neigs = nmax; 354608122e43SStefano Zampini } 354708122e43SStefano Zampini 35489552c7c7SStefano Zampini nmin_s = PetscMin(nmin,B_N); 35499552c7c7SStefano Zampini if (B_neigs < nmin_s) { 35509036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 355108122e43SStefano Zampini 35529d54b7f4SStefano Zampini if (pcbddc->use_deluxe_scaling) { 3553bd2a564bSStefano Zampini if (scal) { 3554bd2a564bSStefano Zampini B_IU = nmin_s; 3555bd2a564bSStefano Zampini B_IL = B_neigs + 1; 3556bd2a564bSStefano Zampini } else { 3557f6f667cfSStefano Zampini B_IL = B_N - nmin_s + 1; 35589d54b7f4SStefano Zampini B_IU = B_N - B_neigs; 3559bd2a564bSStefano Zampini } 35609d54b7f4SStefano Zampini } else { 35619d54b7f4SStefano Zampini B_IL = B_neigs + 1; 35629d54b7f4SStefano Zampini B_IU = nmin_s; 35639d54b7f4SStefano Zampini } 3564fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 35655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer," found %d eigs, less than minimum required %D. Asking for %d to %d incl (fortran like)\n",B_neigs,nmin,B_IL,B_IU)); 3566fd14bc51SStefano Zampini } 3567bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 35681ae86dd6SStefano Zampini PetscInt j,k; 356908122e43SStefano Zampini for (j=0;j<subset_size;j++) { 35701ae86dd6SStefano Zampini for (k=j;k<subset_size;k++) { 35711ae86dd6SStefano Zampini S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k]; 35721ae86dd6SStefano Zampini St[j*subset_size+k] = Starray[cumarray+j*subset_size+k]; 357308122e43SStefano Zampini } 357408122e43SStefano Zampini } 357508122e43SStefano Zampini } else { 35765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(S,Sarray+cumarray,subset_size*subset_size)); 35775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(St,Starray+cumarray,subset_size*subset_size)); 357808122e43SStefano Zampini } 35795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 358008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 35819d54b7f4SStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*subset_size,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr)); 358208122e43SStefano Zampini #else 35839d54b7f4SStefano Zampini PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs2,eigs+B_neigs,eigv+B_neigs*subset_size,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr)); 358408122e43SStefano Zampini #endif 35855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops((4.0*subset_size*subset_size*subset_size)/3.0)); 35865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 358708122e43SStefano Zampini B_neigs += B_neigs2; 358808122e43SStefano Zampini } 358908122e43SStefano Zampini if (B_ierr) { 35902c71b3e2SJacob Faibussowitsch PetscCheckFalse(B_ierr < 0,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr); 35912c71b3e2SJacob Faibussowitsch else PetscCheckFalse(B_ierr <= B_N,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr); 359298921bdaSJacob Faibussowitsch else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: leading minor of order %d is not positive definite",(int)B_ierr-B_N-1); 359308122e43SStefano Zampini } 3594fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 35955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer," -> Got %d eigs\n",B_neigs)); 359608122e43SStefano Zampini for (j=0;j<B_neigs;j++) { 359708122e43SStefano Zampini if (eigs[j] == 0.0) { 35985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer," Inf\n")); 359908122e43SStefano Zampini } else { 36009d54b7f4SStefano Zampini if (pcbddc->use_deluxe_scaling) { 36015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer," %1.6e\n",eigs[j+eigs_start])); 36029d54b7f4SStefano Zampini } else { 36035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer," %1.6e\n",1./eigs[j+eigs_start])); 36049d54b7f4SStefano Zampini } 3605fd14bc51SStefano Zampini } 360608122e43SStefano Zampini } 360708122e43SStefano Zampini } 3608bd2a564bSStefano Zampini } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented"); 3609aff50787SStefano Zampini } 36106c3e6151SStefano Zampini /* change the basis back to the original one */ 36116c3e6151SStefano Zampini if (sub_schurs->change) { 361272b8c272SStefano Zampini Mat change,phi,phit; 36136c3e6151SStefano Zampini 361403dfb2d7SStefano Zampini if (pcbddc->dbg_flag > 2) { 36156c3e6151SStefano Zampini PetscInt ii; 36166c3e6151SStefano Zampini for (ii=0;ii<B_neigs;ii++) { 36175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer," -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N)); 36186c3e6151SStefano Zampini for (j=0;j<B_N;j++) { 3619684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3620684229deSStefano Zampini PetscReal r = PetscRealPart(eigv[(ii+eigs_start)*subset_size+j]); 3621684229deSStefano Zampini PetscReal c = PetscImaginaryPart(eigv[(ii+eigs_start)*subset_size+j]); 36225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer," %1.4e + %1.4e i\n",r,c)); 3623684229deSStefano Zampini #else 36245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer," %1.4e\n",eigv[(ii+eigs_start)*subset_size+j])); 3625684229deSStefano Zampini #endif 36266c3e6151SStefano Zampini } 36276c3e6151SStefano Zampini } 36286c3e6151SStefano Zampini } 36295f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetOperators(sub_schurs->change[i],&change,NULL)); 36305f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit)); 36315f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi)); 36325f80ce2aSJacob Faibussowitsch CHKERRQ(MatCopy(phi,phit,SAME_NONZERO_PATTERN)); 36335f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&phit)); 36345f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&phi)); 36356c3e6151SStefano Zampini } 36368bec7fa6SStefano Zampini maxneigs = PetscMax(B_neigs,maxneigs); 36378bec7fa6SStefano Zampini pcbddc->adaptive_constraints_n[i+nv] = B_neigs; 36389162d606SStefano Zampini if (B_neigs) { 36395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum],eigv+eigs_start*subset_size,B_neigs*subset_size)); 3640fd14bc51SStefano Zampini 3641fd14bc51SStefano Zampini if (pcbddc->dbg_flag > 1) { 36429552c7c7SStefano Zampini PetscInt ii; 36439552c7c7SStefano Zampini for (ii=0;ii<B_neigs;ii++) { 36445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer," -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N)); 36459552c7c7SStefano Zampini for (j=0;j<B_N;j++) { 3646ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3647ac47001eSStefano Zampini PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]); 3648ac47001eSStefano Zampini PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]); 36495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer," %1.4e + %1.4e i\n",r,c)); 3650ac47001eSStefano Zampini #else 36515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer," %1.4e\n",pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]])); 3652ac47001eSStefano Zampini #endif 36539552c7c7SStefano Zampini } 36549552c7c7SStefano Zampini } 3655fd14bc51SStefano Zampini } 36565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size)); 36579162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size; 36589162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs; 36599162d606SStefano Zampini cum++; 366008122e43SStefano Zampini } 36615f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(sub_schurs->is_subs[i],&idxs)); 366208122e43SStefano Zampini /* shift for next computation */ 366308122e43SStefano Zampini cumarray += subset_size*subset_size; 366408122e43SStefano Zampini } 3665fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 36665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 3667fd14bc51SStefano Zampini } 366808122e43SStefano Zampini 366908122e43SStefano Zampini if (mss) { 36705f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray)); 36715f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray)); 3672f6f667cfSStefano Zampini /* destroy matrices (junk) */ 36735f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&sub_schurs->sum_S_Ej_inv_all)); 36745f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&sub_schurs->sum_S_Ej_tilda_all)); 367508122e43SStefano Zampini } 3676f6f667cfSStefano Zampini if (allocated_S_St) { 36775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(S,St)); 3678f6f667cfSStefano Zampini } 36795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree5(eigv,eigs,work,B_iwork,B_ifail)); 368008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 36815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(rwork)); 368208122e43SStefano Zampini #endif 368308122e43SStefano Zampini if (pcbddc->dbg_flag) { 36841b968477SStefano Zampini PetscInt maxneigs_r; 36855f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc))); 36865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %D\n",maxneigs_r)); 368708122e43SStefano Zampini } 36885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_BDDC_AdaptiveSetUp[pcbddc->current_level],pc,0,0,0)); 368908122e43SStefano Zampini PetscFunctionReturn(0); 369008122e43SStefano Zampini } 3691b1b3d7a2SStefano Zampini 3692c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc) 3693c8587f34SStefano Zampini { 36948629588bSStefano Zampini PetscScalar *coarse_submat_vals; 3695c8587f34SStefano Zampini 3696c8587f34SStefano Zampini PetscFunctionBegin; 3697f4ddd8eeSStefano Zampini /* Setup local scatters R_to_B and (optionally) R_to_D */ 36985e8657edSStefano Zampini /* PCBDDCSetUpLocalWorkVectors should be called first! */ 36995f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetUpLocalScatters(pc)); 3700c8587f34SStefano Zampini 3701684f6988SStefano Zampini /* Setup local neumann solver ksp_R */ 37020fccc4e9SStefano Zampini /* PCBDDCSetUpLocalScatters should be called first! */ 37035f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE)); 3704c8587f34SStefano Zampini 37058629588bSStefano Zampini /* 37068629588bSStefano Zampini Setup local correction and local part of coarse basis. 37078629588bSStefano Zampini Gives back the dense local part of the coarse matrix in column major ordering 37088629588bSStefano Zampini */ 37095f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetUpCorrection(pc,&coarse_submat_vals)); 37108629588bSStefano Zampini 37118629588bSStefano Zampini /* Compute total number of coarse nodes and setup coarse solver */ 37125f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals)); 37138629588bSStefano Zampini 37148629588bSStefano Zampini /* free */ 37155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(coarse_submat_vals)); 3716c8587f34SStefano Zampini PetscFunctionReturn(0); 3717c8587f34SStefano Zampini } 3718c8587f34SStefano Zampini 3719674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc) 3720674ae819SStefano Zampini { 3721674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 3722674ae819SStefano Zampini 3723674ae819SStefano Zampini PetscFunctionBegin; 37245f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->user_primal_vertices)); 37255f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->user_primal_vertices_local)); 37265f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->NeumannBoundaries)); 37275f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 37285f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->DirichletBoundaries)); 37295f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceDestroy(&pcbddc->onearnullspace)); 37305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddc->onearnullvecs_state)); 37315f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 37325f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetDofsSplitting(pc,0,NULL)); 37335f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetDofsSplittingLocal(pc,0,NULL)); 3734674ae819SStefano Zampini PetscFunctionReturn(0); 3735674ae819SStefano Zampini } 3736674ae819SStefano Zampini 3737674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc) 3738674ae819SStefano Zampini { 3739674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 37404f1b2e48SStefano Zampini PetscInt i; 3741674ae819SStefano Zampini 3742674ae819SStefano Zampini PetscFunctionBegin; 37435f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->nedcG)); 37445f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->nedclocal)); 37455f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->discretegradient)); 37465f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix)); 37475f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->ChangeOfBasisMatrix)); 37485f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->switch_static_change)); 37495f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pcbddc->work_change)); 37505f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->ConstraintMatrix)); 37515f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->divudotp)); 37525f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->divudotp_vl2l)); 37535f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphDestroy(&pcbddc->mat_graph)); 37544f1b2e48SStefano Zampini for (i=0;i<pcbddc->n_local_subs;i++) { 37555f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->local_subs[i])); 37564f1b2e48SStefano Zampini } 3757e68a0315Sstefano_zampini pcbddc->n_local_subs = 0; 37585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddc->local_subs)); 37595f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSubSchursDestroy(&pcbddc->sub_schurs)); 3760c703fcc7SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 37618af8fcf9SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 37621c7a958bSStefano Zampini pcbddc->corner_selected = PETSC_FALSE; 3763674ae819SStefano Zampini PetscFunctionReturn(0); 3764674ae819SStefano Zampini } 3765674ae819SStefano Zampini 3766674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc) 3767674ae819SStefano Zampini { 3768674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 3769674ae819SStefano Zampini 3770674ae819SStefano Zampini PetscFunctionBegin; 37715f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pcbddc->coarse_vec)); 377258da7f69SStefano Zampini if (pcbddc->coarse_phi_B) { 3773ca92afb2SStefano Zampini PetscScalar *array; 37745f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(pcbddc->coarse_phi_B,&array)); 37755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(array)); 377658da7f69SStefano Zampini } 37775f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->coarse_phi_B)); 37785f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->coarse_phi_D)); 37795f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->coarse_psi_B)); 37805f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->coarse_psi_D)); 37815f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pcbddc->vec1_P)); 37825f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pcbddc->vec1_C)); 37835f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->local_auxmat2)); 37845f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->local_auxmat1)); 37855f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pcbddc->vec1_R)); 37865f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pcbddc->vec2_R)); 37875f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->is_R_local)); 37885f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterDestroy(&pcbddc->R_to_B)); 37895f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterDestroy(&pcbddc->R_to_D)); 37905f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterDestroy(&pcbddc->coarse_loc_to_glob)); 37915f80ce2aSJacob Faibussowitsch CHKERRQ(KSPReset(pcbddc->ksp_D)); 37925f80ce2aSJacob Faibussowitsch CHKERRQ(KSPReset(pcbddc->ksp_R)); 37935f80ce2aSJacob Faibussowitsch CHKERRQ(KSPReset(pcbddc->coarse_ksp)); 37945f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->local_mat)); 37955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddc->primal_indices_local_idxs)); 37965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult)); 37975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddc->global_primal_indices)); 37985f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->coarse_subassembling)); 37995f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->benign_change)); 38005f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pcbddc->benign_vec)); 38015f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCBenignShellMat(pc,PETSC_TRUE)); 38025f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->benign_B0)); 38035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&pcbddc->benign_sf)); 3804ca92afb2SStefano Zampini if (pcbddc->benign_zerodiag_subs) { 3805ca92afb2SStefano Zampini PetscInt i; 3806ca92afb2SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) { 38075f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->benign_zerodiag_subs[i])); 3808ca92afb2SStefano Zampini } 38095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddc->benign_zerodiag_subs)); 3810ca92afb2SStefano Zampini } 38115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0)); 3812674ae819SStefano Zampini PetscFunctionReturn(0); 3813674ae819SStefano Zampini } 3814674ae819SStefano Zampini 3815f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc) 38166bfb1811SStefano Zampini { 38176bfb1811SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 38186bfb1811SStefano Zampini PC_IS *pcis = (PC_IS*)pc->data; 38196bfb1811SStefano Zampini VecType impVecType; 38204f1b2e48SStefano Zampini PetscInt n_constraints,n_R,old_size; 38216bfb1811SStefano Zampini 38226bfb1811SStefano Zampini PetscFunctionBegin; 38234f1b2e48SStefano Zampini n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices; 3824b371cd4fSStefano Zampini n_R = pcis->n - pcbddc->n_vertices; 38255f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetType(pcis->vec1_N,&impVecType)); 3826e7b262bdSStefano Zampini /* local work vectors (try to avoid unneeded work)*/ 3827e7b262bdSStefano Zampini /* R nodes */ 3828e7b262bdSStefano Zampini old_size = -1; 3829e7b262bdSStefano Zampini if (pcbddc->vec1_R) { 38305f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSize(pcbddc->vec1_R,&old_size)); 3831e7b262bdSStefano Zampini } 3832e7b262bdSStefano Zampini if (n_R != old_size) { 38335f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pcbddc->vec1_R)); 38345f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pcbddc->vec2_R)); 38355f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R)); 38365f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R)); 38375f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(pcbddc->vec1_R,impVecType)); 38385f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R)); 3839e7b262bdSStefano Zampini } 3840e7b262bdSStefano Zampini /* local primal dofs */ 3841e7b262bdSStefano Zampini old_size = -1; 3842e7b262bdSStefano Zampini if (pcbddc->vec1_P) { 38435f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSize(pcbddc->vec1_P,&old_size)); 3844e7b262bdSStefano Zampini } 3845e9189074SStefano Zampini if (pcbddc->local_primal_size != old_size) { 38465f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pcbddc->vec1_P)); 38475f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P)); 38485f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size)); 38495f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(pcbddc->vec1_P,impVecType)); 3850e7b262bdSStefano Zampini } 3851e7b262bdSStefano Zampini /* local explicit constraints */ 3852e7b262bdSStefano Zampini old_size = -1; 3853e7b262bdSStefano Zampini if (pcbddc->vec1_C) { 38545f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSize(pcbddc->vec1_C,&old_size)); 3855e7b262bdSStefano Zampini } 3856e7b262bdSStefano Zampini if (n_constraints && n_constraints != old_size) { 38575f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pcbddc->vec1_C)); 38585f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C)); 38595f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints)); 38605f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(pcbddc->vec1_C,impVecType)); 386183b7ccabSStefano Zampini } 38626bfb1811SStefano Zampini PetscFunctionReturn(0); 38636bfb1811SStefano Zampini } 38646bfb1811SStefano Zampini 386547f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n) 386688ebb749SStefano Zampini { 386725084f0cSStefano Zampini /* pointers to pcis and pcbddc */ 386888ebb749SStefano Zampini PC_IS* pcis = (PC_IS*)pc->data; 386988ebb749SStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 3870d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 387125084f0cSStefano Zampini /* submatrices of local problem */ 387280677318SStefano Zampini Mat A_RV,A_VR,A_VV,local_auxmat2_R; 387306656605SStefano Zampini /* submatrices of local coarse problem */ 387406656605SStefano Zampini Mat S_VV,S_CV,S_VC,S_CC; 387525084f0cSStefano Zampini /* working matrices */ 387606656605SStefano Zampini Mat C_CR; 387725084f0cSStefano Zampini /* additional working stuff */ 387806656605SStefano Zampini PC pc_R; 3879c58f9fdbSStefano Zampini Mat F,Brhs = NULL; 38805cbda25cSStefano Zampini Vec dummy_vec; 38817ebab0bbSStefano Zampini PetscBool isLU,isCHOL,need_benign_correction,sparserhs; 388225084f0cSStefano Zampini PetscScalar *coarse_submat_vals; /* TODO: use a PETSc matrix */ 388306656605SStefano Zampini PetscScalar *work; 388406656605SStefano Zampini PetscInt *idx_V_B; 3885ffd830a3SStefano Zampini PetscInt lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I; 388606656605SStefano Zampini PetscInt i,n_R,n_D,n_B; 388706656605SStefano Zampini PetscScalar one=1.0,m_one=-1.0; 388888ebb749SStefano Zampini 388988ebb749SStefano Zampini PetscFunctionBegin; 38902c71b3e2SJacob Faibussowitsch PetscCheckFalse(!pcbddc->symmetric_primal && pcbddc->benign_n,PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented"); 38915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0)); 3892ffd830a3SStefano Zampini 3893ffd830a3SStefano Zampini /* Set Non-overlapping dimensions */ 3894b371cd4fSStefano Zampini n_vertices = pcbddc->n_vertices; 38954f1b2e48SStefano Zampini n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices; 3896b371cd4fSStefano Zampini n_B = pcis->n_B; 3897b371cd4fSStefano Zampini n_D = pcis->n - n_B; 389888ebb749SStefano Zampini n_R = pcis->n - n_vertices; 389988ebb749SStefano Zampini 390088ebb749SStefano Zampini /* vertices in boundary numbering */ 39015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n_vertices,&idx_V_B)); 39025f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B)); 39032c71b3e2SJacob Faibussowitsch PetscCheckFalse(i != n_vertices,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D",n_vertices,i); 390488ebb749SStefano Zampini 390506656605SStefano Zampini /* Subdomain contribution (Non-overlapping) to coarse matrix */ 39065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals)); 39075f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV)); 39085f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseSetLDA(S_VV,pcbddc->local_primal_size)); 39095f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV)); 39105f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseSetLDA(S_CV,pcbddc->local_primal_size)); 39115f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC)); 39125f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseSetLDA(S_VC,pcbddc->local_primal_size)); 39135f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC)); 39145f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseSetLDA(S_CC,pcbddc->local_primal_size)); 391506656605SStefano Zampini 391606656605SStefano Zampini /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */ 39175f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->ksp_R,&pc_R)); 39185f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetUp(pc_R)); 39195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU)); 39205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL)); 3921ffd830a3SStefano Zampini lda_rhs = n_R; 3922a3df083aSStefano Zampini need_benign_correction = PETSC_FALSE; 39237ebab0bbSStefano Zampini if (isLU || isCHOL) { 39245f80ce2aSJacob Faibussowitsch CHKERRQ(PCFactorGetMatrix(pc_R,&F)); 3925b334f244SStefano Zampini } else if (sub_schurs && sub_schurs->reuse_solver) { 3926df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 3927d62866d3SStefano Zampini MatFactorType type; 3928d62866d3SStefano Zampini 3929df4d28bfSStefano Zampini F = reuse_solver->F; 39305f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetFactorType(F,&type)); 3931d62866d3SStefano Zampini if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE; 39327ebab0bbSStefano Zampini if (type == MAT_FACTOR_LU) isLU = PETSC_TRUE; 39335f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(F,&lda_rhs,NULL)); 393422db5ddcSStefano Zampini need_benign_correction = (PetscBool)(!!reuse_solver->benign_n); 39357ebab0bbSStefano Zampini } else F = NULL; 393606656605SStefano Zampini 3937c58f9fdbSStefano Zampini /* determine if we can use a sparse right-hand side */ 3938c58f9fdbSStefano Zampini sparserhs = PETSC_FALSE; 3939c58f9fdbSStefano Zampini if (F) { 3940ea799195SBarry Smith MatSolverType solver; 3941c58f9fdbSStefano Zampini 39425f80ce2aSJacob Faibussowitsch CHKERRQ(MatFactorGetSolverType(F,&solver)); 39435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(solver,MATSOLVERMUMPS,&sparserhs)); 3944c58f9fdbSStefano Zampini } 3945c58f9fdbSStefano Zampini 3946ffd830a3SStefano Zampini /* allocate workspace */ 3947ffd830a3SStefano Zampini n = 0; 3948ffd830a3SStefano Zampini if (n_constraints) { 3949ffd830a3SStefano Zampini n += lda_rhs*n_constraints; 3950ffd830a3SStefano Zampini } 3951ffd830a3SStefano Zampini if (n_vertices) { 3952ffd830a3SStefano Zampini n = PetscMax(2*lda_rhs*n_vertices,n); 3953ffd830a3SStefano Zampini n = PetscMax((lda_rhs+n_B)*n_vertices,n); 3954ffd830a3SStefano Zampini } 39552a3a6641Sstefano_zampini if (!pcbddc->symmetric_primal) { 39562a3a6641Sstefano_zampini n = PetscMax(2*lda_rhs*pcbddc->local_primal_size,n); 39572a3a6641Sstefano_zampini } 39585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n,&work)); 3959ffd830a3SStefano Zampini 39605cbda25cSStefano Zampini /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */ 39615cbda25cSStefano Zampini dummy_vec = NULL; 39625cbda25cSStefano Zampini if (need_benign_correction && lda_rhs != n_R && F) { 39635f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&dummy_vec)); 39645f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(dummy_vec,lda_rhs,PETSC_DECIDE)); 39655f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(dummy_vec,((PetscObject)pcis->vec1_N)->type_name)); 39665cbda25cSStefano Zampini } 39675cbda25cSStefano Zampini 39685f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->local_auxmat1)); 39695f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->local_auxmat2)); 39707ebab0bbSStefano Zampini 397188ebb749SStefano Zampini /* Precompute stuffs needed for preprocessing and application of BDDC*/ 397288ebb749SStefano Zampini if (n_constraints) { 3973837cedc9SStefano Zampini Mat M3,C_B; 397406656605SStefano Zampini IS is_aux; 397506656605SStefano Zampini 397625084f0cSStefano Zampini /* Extract constraints on R nodes: C_{CR} */ 39775f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux)); 39785f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR)); 39795f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B)); 398088ebb749SStefano Zampini 398180677318SStefano Zampini /* Assemble local_auxmat2_R = (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */ 398280677318SStefano Zampini /* Assemble pcbddc->local_auxmat2 = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */ 3983c58f9fdbSStefano Zampini if (!sparserhs) { 39845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(work,lda_rhs*n_constraints)); 398588ebb749SStefano Zampini for (i=0;i<n_constraints;i++) { 398606656605SStefano Zampini const PetscScalar *row_cmat_values; 398706656605SStefano Zampini const PetscInt *row_cmat_indices; 398806656605SStefano Zampini PetscInt size_of_constraint,j; 398988ebb749SStefano Zampini 39905f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values)); 399106656605SStefano Zampini for (j=0;j<size_of_constraint;j++) { 3992ffd830a3SStefano Zampini work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j]; 399306656605SStefano Zampini } 39945f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values)); 399506656605SStefano Zampini } 39965f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&Brhs)); 3997c58f9fdbSStefano Zampini } else { 3998c58f9fdbSStefano Zampini Mat tC_CR; 3999c58f9fdbSStefano Zampini 40005f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(C_CR,-1.0)); 4001c58f9fdbSStefano Zampini if (lda_rhs != n_R) { 4002c58f9fdbSStefano Zampini PetscScalar *aa; 4003c58f9fdbSStefano Zampini PetscInt r,*ii,*jj; 4004c58f9fdbSStefano Zampini PetscBool done; 4005c58f9fdbSStefano Zampini 40065f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done)); 4007*28b400f6SJacob Faibussowitsch PetscCheck(done,PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed"); 40085f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJGetArray(C_CR,&aa)); 40095f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_constraints,lda_rhs,ii,jj,aa,&tC_CR)); 40105f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(C_CR,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done)); 4011*28b400f6SJacob Faibussowitsch PetscCheck(done,PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed"); 4012c58f9fdbSStefano Zampini } else { 40135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)C_CR)); 4014c58f9fdbSStefano Zampini tC_CR = C_CR; 4015c58f9fdbSStefano Zampini } 40165f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateTranspose(tC_CR,&Brhs)); 40175f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&tC_CR)); 4018c58f9fdbSStefano Zampini } 40195f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R)); 402006656605SStefano Zampini if (F) { 4021a3df083aSStefano Zampini if (need_benign_correction) { 4022df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4023a3df083aSStefano Zampini 402472b8c272SStefano Zampini /* rhs is already zero on interior dofs, no need to change the rhs */ 40255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(reuse_solver->benign_save_vals,pcbddc->benign_n)); 4026a3df083aSStefano Zampini } 40275f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatSolve(F,Brhs,local_auxmat2_R)); 4028a3df083aSStefano Zampini if (need_benign_correction) { 4029a3df083aSStefano Zampini PetscScalar *marr; 4030df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4031a3df083aSStefano Zampini 40325f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(local_auxmat2_R,&marr)); 40335cbda25cSStefano Zampini if (lda_rhs != n_R) { 40345cbda25cSStefano Zampini for (i=0;i<n_constraints;i++) { 40355f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(dummy_vec,marr+i*lda_rhs)); 40365f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE)); 40375f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(dummy_vec)); 40385cbda25cSStefano Zampini } 40395cbda25cSStefano Zampini } else { 4040a3df083aSStefano Zampini for (i=0;i<n_constraints;i++) { 40415f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs)); 40425f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE)); 40435f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec1_R)); 4044a3df083aSStefano Zampini } 40455cbda25cSStefano Zampini } 40465f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(local_auxmat2_R,&marr)); 4047a3df083aSStefano Zampini } 404806656605SStefano Zampini } else { 404980677318SStefano Zampini PetscScalar *marr; 405080677318SStefano Zampini 40515f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(local_auxmat2_R,&marr)); 405206656605SStefano Zampini for (i=0;i<n_constraints;i++) { 40535f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs)); 40545f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs)); 40555f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R)); 40565f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R)); 40575f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec1_R)); 40585f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec2_R)); 405906656605SStefano Zampini } 40605f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(local_auxmat2_R,&marr)); 406106656605SStefano Zampini } 4062c58f9fdbSStefano Zampini if (sparserhs) { 40635f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(C_CR,-1.0)); 4064c58f9fdbSStefano Zampini } 40655f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Brhs)); 406680677318SStefano Zampini if (!pcbddc->switch_static) { 40675f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2)); 406880677318SStefano Zampini for (i=0;i<n_constraints;i++) { 4069ab2d12f3SJunchao Zhang Vec r, b; 40705f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumnVecRead(local_auxmat2_R,i,&r)); 40715f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumnVec(pcbddc->local_auxmat2,i,&b)); 40725f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_B,r,b,INSERT_VALUES,SCATTER_FORWARD)); 40735f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_B,r,b,INSERT_VALUES,SCATTER_FORWARD)); 40745f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumnVec(pcbddc->local_auxmat2,i,&b)); 40755f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumnVecRead(local_auxmat2_R,i,&r)); 407680677318SStefano Zampini } 40775f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3)); 407880677318SStefano Zampini } else { 4079ffd830a3SStefano Zampini if (lda_rhs != n_R) { 4080ffd830a3SStefano Zampini IS dummy; 4081ffd830a3SStefano Zampini 40825f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy)); 40835f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2)); 40845f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&dummy)); 4085ffd830a3SStefano Zampini } else { 40865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)local_auxmat2_R)); 408780677318SStefano Zampini pcbddc->local_auxmat2 = local_auxmat2_R; 4088ffd830a3SStefano Zampini } 40895f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3)); 409080677318SStefano Zampini } 40915f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_aux)); 409280677318SStefano Zampini /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR})^{-1} */ 40935f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(M3,m_one)); 409480677318SStefano Zampini if (isCHOL) { 40955f80ce2aSJacob Faibussowitsch CHKERRQ(MatCholeskyFactor(M3,NULL,NULL)); 409680677318SStefano Zampini } else { 40975f80ce2aSJacob Faibussowitsch CHKERRQ(MatLUFactor(M3,NULL,NULL,NULL)); 409880677318SStefano Zampini } 40995f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqDenseInvertFactors_Private(M3)); 410080677318SStefano Zampini /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */ 41015f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(M3,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1)); 41025f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&C_B)); 41035f80ce2aSJacob Faibussowitsch CHKERRQ(MatCopy(M3,S_CC,SAME_NONZERO_PATTERN)); /* S_CC can have a different LDA, MatMatSolve doesn't support it */ 41045f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&M3)); 4105f4ddd8eeSStefano Zampini } 4106fc227af8SStefano Zampini 4107fc227af8SStefano Zampini /* Get submatrices from subdomain matrix */ 410888ebb749SStefano Zampini if (n_vertices) { 41097ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 41107ebab0bbSStefano Zampini PetscBool oldpin; 41117ebab0bbSStefano Zampini #endif 41127ebab0bbSStefano Zampini PetscBool isaij; 411306656605SStefano Zampini IS is_aux; 41143a50541eSStefano Zampini 4115b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */ 41166816873aSStefano Zampini IS tis; 41176816873aSStefano Zampini 41185f80ce2aSJacob Faibussowitsch CHKERRQ(ISDuplicate(pcbddc->is_R_local,&tis)); 41195f80ce2aSJacob Faibussowitsch CHKERRQ(ISSort(tis)); 41205f80ce2aSJacob Faibussowitsch CHKERRQ(ISComplement(tis,0,pcis->n,&is_aux)); 41215f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&tis)); 41226816873aSStefano Zampini } else { 41235f80ce2aSJacob Faibussowitsch CHKERRQ(ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux)); 41246816873aSStefano Zampini } 41257ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 4126b470e4b4SRichard Tran Mills oldpin = pcbddc->local_mat->boundtocpu; 41277ebab0bbSStefano Zampini #endif 41285f80ce2aSJacob Faibussowitsch CHKERRQ(MatBindToCPU(pcbddc->local_mat,PETSC_TRUE)); 41295f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV)); 41305f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR)); 41315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isaij)); 41327ebab0bbSStefano Zampini if (!isaij) { /* TODO REMOVE: MatMatMult(A_VR,A_RRmA_RV) below may raise an error */ 41335f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR)); 41347ebab0bbSStefano Zampini } 41355f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV)); 41367ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 41375f80ce2aSJacob Faibussowitsch CHKERRQ(MatBindToCPU(pcbddc->local_mat,oldpin)); 41387ebab0bbSStefano Zampini #endif 41395f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_aux)); 414088ebb749SStefano Zampini } 414188ebb749SStefano Zampini 414288ebb749SStefano Zampini /* Matrix of coarse basis functions (local) */ 4143f4ddd8eeSStefano Zampini if (pcbddc->coarse_phi_B) { 414406656605SStefano Zampini PetscInt on_B,on_primal,on_D=n_D; 414506656605SStefano Zampini if (pcbddc->coarse_phi_D) { 41465f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL)); 414706656605SStefano Zampini } 41485f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal)); 414906656605SStefano Zampini if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) { 415006656605SStefano Zampini PetscScalar *marray; 415106656605SStefano Zampini 41525f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(pcbddc->coarse_phi_B,&marray)); 41535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(marray)); 41545f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->coarse_phi_B)); 41555f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->coarse_psi_B)); 41565f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->coarse_phi_D)); 41575f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->coarse_psi_D)); 4158f4ddd8eeSStefano Zampini } 4159f4ddd8eeSStefano Zampini } 416006656605SStefano Zampini 4161f4ddd8eeSStefano Zampini if (!pcbddc->coarse_phi_B) { 4162a6e023c1Sstefano_zampini PetscScalar *marr; 416388ebb749SStefano Zampini 4164a6e023c1Sstefano_zampini /* memory size */ 416506656605SStefano Zampini n = n_B*pcbddc->local_primal_size; 4166a6e023c1Sstefano_zampini if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D*pcbddc->local_primal_size; 4167a6e023c1Sstefano_zampini if (!pcbddc->symmetric_primal) n *= 2; 41685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(n,&marr)); 41695f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_B)); 4170a6e023c1Sstefano_zampini marr += n_B*pcbddc->local_primal_size; 41718eeda7d8SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 41725f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_phi_D)); 4173a6e023c1Sstefano_zampini marr += n_D*pcbddc->local_primal_size; 417488ebb749SStefano Zampini } 41753301b35fSStefano Zampini if (!pcbddc->symmetric_primal) { 41765f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_B)); 4177a6e023c1Sstefano_zampini marr += n_B*pcbddc->local_primal_size; 41788eeda7d8SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 41795f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marr,&pcbddc->coarse_psi_D)); 418088ebb749SStefano Zampini } 418188ebb749SStefano Zampini } else { 41825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)pcbddc->coarse_phi_B)); 4183c0553b1fSStefano Zampini pcbddc->coarse_psi_B = pcbddc->coarse_phi_B; 41841b968477SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 41855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)pcbddc->coarse_phi_D)); 4186c0553b1fSStefano Zampini pcbddc->coarse_psi_D = pcbddc->coarse_phi_D; 4187c0553b1fSStefano Zampini } 418888ebb749SStefano Zampini } 418906656605SStefano Zampini } 4190019a44ceSStefano Zampini 419106656605SStefano Zampini /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */ 41924f1b2e48SStefano Zampini p0_lidx_I = NULL; 41934f1b2e48SStefano Zampini if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) { 4194d12edf2fSStefano Zampini const PetscInt *idxs; 4195d12edf2fSStefano Zampini 41965f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcis->is_I_local,&idxs)); 41975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->benign_n,&p0_lidx_I)); 41984f1b2e48SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) { 41995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i])); 42004f1b2e48SStefano Zampini } 42015f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcis->is_I_local,&idxs)); 4202d12edf2fSStefano Zampini } 4203d16cbb6bSStefano Zampini 420406656605SStefano Zampini /* vertices */ 420506656605SStefano Zampini if (n_vertices) { 4206c58f9fdbSStefano Zampini PetscBool restoreavr = PETSC_FALSE; 420716f15bc4SStefano Zampini 42085f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV)); 420904708bb6SStefano Zampini 421016f15bc4SStefano Zampini if (n_R) { 421114393ed6SStefano Zampini Mat A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */ 421206656605SStefano Zampini PetscBLASInt B_N,B_one = 1; 42131683a169SBarry Smith const PetscScalar *x; 42141683a169SBarry Smith PetscScalar *y; 421506656605SStefano Zampini 42165f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(A_RV,m_one)); 421714393ed6SStefano Zampini if (need_benign_correction) { 421814393ed6SStefano Zampini ISLocalToGlobalMapping RtoN; 421914393ed6SStefano Zampini IS is_p0; 422014393ed6SStefano Zampini PetscInt *idxs_p0,n; 422114393ed6SStefano Zampini 42225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->benign_n,&idxs_p0)); 42235f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN)); 42245f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0)); 42252c71b3e2SJacob Faibussowitsch PetscCheckFalse(n != pcbddc->benign_n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in R numbering for benign p0! %D != %D",n,pcbddc->benign_n); 42265f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&RtoN)); 42275f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0)); 42285f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr)); 42295f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_p0)); 423014393ed6SStefano Zampini } 423114393ed6SStefano Zampini 42325f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV)); 4233c58f9fdbSStefano Zampini if (!sparserhs || need_benign_correction) { 4234ffd830a3SStefano Zampini if (lda_rhs == n_R) { 42355f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV)); 4236ffd830a3SStefano Zampini } else { 4237ca92afb2SStefano Zampini PetscScalar *av,*array; 4238ca92afb2SStefano Zampini const PetscInt *xadj,*adjncy; 4239ca92afb2SStefano Zampini PetscInt n; 4240ca92afb2SStefano Zampini PetscBool flg_row; 4241ffd830a3SStefano Zampini 4242ca92afb2SStefano Zampini array = work+lda_rhs*n_vertices; 42435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(array,lda_rhs*n_vertices)); 42445f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV)); 42455f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row)); 42465f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJGetArray(A_RV,&av)); 4247ca92afb2SStefano Zampini for (i=0;i<n;i++) { 4248ca92afb2SStefano Zampini PetscInt j; 4249ca92afb2SStefano Zampini for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j]; 4250ffd830a3SStefano Zampini } 42515f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row)); 42525f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_RV)); 42535f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV)); 4254ffd830a3SStefano Zampini } 4255a3df083aSStefano Zampini if (need_benign_correction) { 4256df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4257a3df083aSStefano Zampini PetscScalar *marr; 4258a3df083aSStefano Zampini 42595f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(A_RV,&marr)); 426014393ed6SStefano Zampini /* need \Phi^T A_RV = (I+L)A_RV, L given by 426114393ed6SStefano Zampini 426214393ed6SStefano Zampini | 0 0 0 | (V) 426314393ed6SStefano Zampini L = | 0 0 -1 | (P-p0) 426414393ed6SStefano Zampini | 0 0 -1 | (p0) 426514393ed6SStefano Zampini 426614393ed6SStefano Zampini */ 4267df4d28bfSStefano Zampini for (i=0;i<reuse_solver->benign_n;i++) { 426814393ed6SStefano Zampini const PetscScalar *vals; 426914393ed6SStefano Zampini const PetscInt *idxs,*idxs_zero; 427014393ed6SStefano Zampini PetscInt n,j,nz; 427114393ed6SStefano Zampini 42725f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz)); 42735f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero)); 42745f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals)); 427514393ed6SStefano Zampini for (j=0;j<n;j++) { 427614393ed6SStefano Zampini PetscScalar val = vals[j]; 427714393ed6SStefano Zampini PetscInt k,col = idxs[j]; 427814393ed6SStefano Zampini for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val; 427914393ed6SStefano Zampini } 42805f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals)); 42815f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero)); 428214393ed6SStefano Zampini } 42835f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(A_RV,&marr)); 428472b8c272SStefano Zampini } 42855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)A_RV)); 4286c58f9fdbSStefano Zampini Brhs = A_RV; 4287c58f9fdbSStefano Zampini } else { 4288c58f9fdbSStefano Zampini Mat tA_RVT,A_RVT; 4289c58f9fdbSStefano Zampini 4290c58f9fdbSStefano Zampini if (!pcbddc->symmetric_primal) { 4291fb6280fbSStefano Zampini /* A_RV already scaled by -1 */ 42925f80ce2aSJacob Faibussowitsch CHKERRQ(MatTranspose(A_RV,MAT_INITIAL_MATRIX,&A_RVT)); 4293c58f9fdbSStefano Zampini } else { 4294c58f9fdbSStefano Zampini restoreavr = PETSC_TRUE; 42955f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(A_VR,-1.0)); 42965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)A_VR)); 4297c58f9fdbSStefano Zampini A_RVT = A_VR; 4298c58f9fdbSStefano Zampini } 4299c58f9fdbSStefano Zampini if (lda_rhs != n_R) { 4300c58f9fdbSStefano Zampini PetscScalar *aa; 4301c58f9fdbSStefano Zampini PetscInt r,*ii,*jj; 4302c58f9fdbSStefano Zampini PetscBool done; 4303c58f9fdbSStefano Zampini 43045f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done)); 4305*28b400f6SJacob Faibussowitsch PetscCheck(done,PETSC_COMM_SELF,PETSC_ERR_PLIB,"GetRowIJ failed"); 43065f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJGetArray(A_RVT,&aa)); 43075f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n_vertices,lda_rhs,ii,jj,aa,&tA_RVT)); 43085f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(A_RVT,0,PETSC_FALSE,PETSC_FALSE,&r,(const PetscInt**)&ii,(const PetscInt**)&jj,&done)); 4309*28b400f6SJacob Faibussowitsch PetscCheck(done,PETSC_COMM_SELF,PETSC_ERR_PLIB,"RestoreRowIJ failed"); 4310c58f9fdbSStefano Zampini } else { 43115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)A_RVT)); 4312c58f9fdbSStefano Zampini tA_RVT = A_RVT; 4313c58f9fdbSStefano Zampini } 43145f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateTranspose(tA_RVT,&Brhs)); 43155f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&tA_RVT)); 43165f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_RVT)); 4317c58f9fdbSStefano Zampini } 431872b8c272SStefano Zampini if (F) { 431914393ed6SStefano Zampini /* need to correct the rhs */ 432072b8c272SStefano Zampini if (need_benign_correction) { 432172b8c272SStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 432272b8c272SStefano Zampini PetscScalar *marr; 432372b8c272SStefano Zampini 43245f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(Brhs,&marr)); 43255cbda25cSStefano Zampini if (lda_rhs != n_R) { 43265cbda25cSStefano Zampini for (i=0;i<n_vertices;i++) { 43275f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(dummy_vec,marr+i*lda_rhs)); 43285f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE)); 43295f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(dummy_vec)); 43305cbda25cSStefano Zampini } 43315cbda25cSStefano Zampini } else { 4332a3df083aSStefano Zampini for (i=0;i<n_vertices;i++) { 43335f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs)); 43345f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE)); 43355f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec1_R)); 4336a3df083aSStefano Zampini } 43375cbda25cSStefano Zampini } 43385f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(Brhs,&marr)); 4339a3df083aSStefano Zampini } 43405f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatSolve(F,Brhs,A_RRmA_RV)); 4341c58f9fdbSStefano Zampini if (restoreavr) { 43425f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(A_VR,-1.0)); 4343c58f9fdbSStefano Zampini } 434414393ed6SStefano Zampini /* need to correct the solution */ 4345a3df083aSStefano Zampini if (need_benign_correction) { 4346df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4347a3df083aSStefano Zampini PetscScalar *marr; 4348a3df083aSStefano Zampini 43495f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(A_RRmA_RV,&marr)); 43505cbda25cSStefano Zampini if (lda_rhs != n_R) { 43515cbda25cSStefano Zampini for (i=0;i<n_vertices;i++) { 43525f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(dummy_vec,marr+i*lda_rhs)); 43535f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE)); 43545f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(dummy_vec)); 43555cbda25cSStefano Zampini } 43565cbda25cSStefano Zampini } else { 4357a3df083aSStefano Zampini for (i=0;i<n_vertices;i++) { 43585f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs)); 43595f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE)); 43605f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec1_R)); 4361a3df083aSStefano Zampini } 43625cbda25cSStefano Zampini } 43635f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(A_RRmA_RV,&marr)); 4364a3df083aSStefano Zampini } 436506656605SStefano Zampini } else { 43665f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(Brhs,&y)); 436706656605SStefano Zampini for (i=0;i<n_vertices;i++) { 43685f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs)); 43695f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs)); 43705f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R)); 43715f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R)); 43725f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec1_R)); 43735f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec2_R)); 437406656605SStefano Zampini } 43755f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(Brhs,&y)); 437606656605SStefano Zampini } 43775f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_RV)); 43785f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Brhs)); 4379ffd830a3SStefano Zampini /* S_VV and S_CV */ 438006656605SStefano Zampini if (n_constraints) { 438106656605SStefano Zampini Mat B; 438280677318SStefano Zampini 43835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(work+lda_rhs*n_vertices,n_B*n_vertices)); 438480677318SStefano Zampini for (i=0;i<n_vertices;i++) { 43855f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs)); 43865f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B)); 43875f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 43885f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 43895f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcis->vec1_B)); 43905f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec1_R)); 439180677318SStefano Zampini } 43925f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B)); 43934222ddf1SHong Zhang /* Reuse dense S_C = pcbddc->local_auxmat1 * B */ 43945f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductCreateWithMat(pcbddc->local_auxmat1,B,NULL,S_CV)); 43955f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSetType(S_CV,MATPRODUCT_AB)); 43965f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSetFromOptions(S_CV)); 43975f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSymbolic(S_CV)); 43985f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductNumeric(S_CV)); 43995f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductClear(S_CV)); 44004222ddf1SHong Zhang 44015f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B)); 44025f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B)); 44034222ddf1SHong Zhang /* Reuse B = local_auxmat2_R * S_CV */ 44045f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductCreateWithMat(local_auxmat2_R,S_CV,NULL,B)); 44055f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSetType(B,MATPRODUCT_AB)); 44065f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSetFromOptions(B)); 44075f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSymbolic(B)); 44085f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductNumeric(B)); 44094222ddf1SHong Zhang 44105f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(S_CV,m_one)); 44115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(lda_rhs*n_vertices,&B_N)); 4412ffd830a3SStefano Zampini PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one)); 44135f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B)); 441406656605SStefano Zampini } 4415ffd830a3SStefano Zampini if (lda_rhs != n_R) { 44165f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_RRmA_RV)); 44175f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV)); 44185f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseSetLDA(A_RRmA_RV,lda_rhs)); 4419ffd830a3SStefano Zampini } 44205f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt)); 442114393ed6SStefano Zampini /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */ 442214393ed6SStefano Zampini if (need_benign_correction) { 4423df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 442414393ed6SStefano Zampini PetscScalar *marr,*sums; 442514393ed6SStefano Zampini 44265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n_vertices,&sums)); 44275f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(S_VVt,&marr)); 4428df4d28bfSStefano Zampini for (i=0;i<reuse_solver->benign_n;i++) { 442914393ed6SStefano Zampini const PetscScalar *vals; 443014393ed6SStefano Zampini const PetscInt *idxs,*idxs_zero; 443114393ed6SStefano Zampini PetscInt n,j,nz; 443214393ed6SStefano Zampini 44335f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz)); 44345f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero)); 443514393ed6SStefano Zampini for (j=0;j<n_vertices;j++) { 443614393ed6SStefano Zampini PetscInt k; 443714393ed6SStefano Zampini sums[j] = 0.; 443814393ed6SStefano Zampini for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs]; 443914393ed6SStefano Zampini } 44405f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals)); 444114393ed6SStefano Zampini for (j=0;j<n;j++) { 444214393ed6SStefano Zampini PetscScalar val = vals[j]; 444314393ed6SStefano Zampini PetscInt k; 444414393ed6SStefano Zampini for (k=0;k<n_vertices;k++) { 444514393ed6SStefano Zampini marr[idxs[j]+k*n_vertices] += val*sums[k]; 444614393ed6SStefano Zampini } 444714393ed6SStefano Zampini } 44485f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals)); 44495f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero)); 445014393ed6SStefano Zampini } 44515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(sums)); 44525f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(S_VVt,&marr)); 44535f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_RV_bcorr)); 445414393ed6SStefano Zampini } 44555f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_RRmA_RV)); 44565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(n_vertices*n_vertices,&B_N)); 44575f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(A_VV,&x)); 44585f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(S_VVt,&y)); 445906656605SStefano Zampini PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one)); 44605f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(A_VV,&x)); 44615f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(S_VVt,&y)); 44625f80ce2aSJacob Faibussowitsch CHKERRQ(MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN)); 44635f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&S_VVt)); 4464019a44ceSStefano Zampini } else { 44655f80ce2aSJacob Faibussowitsch CHKERRQ(MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN)); 4466d16cbb6bSStefano Zampini } 44675f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_VV)); 4468d16cbb6bSStefano Zampini 446906656605SStefano Zampini /* coarse basis functions */ 447006656605SStefano Zampini for (i=0;i<n_vertices;i++) { 4471ab2d12f3SJunchao Zhang Vec v; 4472ab2d12f3SJunchao Zhang PetscScalar one = 1.0,zero = 0.0; 447316f15bc4SStefano Zampini 44745f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i)); 44755f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumnVec(pcbddc->coarse_phi_B,i,&v)); 44765f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD)); 44775f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD)); 4478ab2d12f3SJunchao Zhang if (PetscDefined(USE_DEBUG)) { /* The following VecSetValues() expects a sequential matrix */ 4479ab2d12f3SJunchao Zhang PetscMPIInt rank; 44805f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pcbddc->coarse_phi_B),&rank)); 44812c71b3e2SJacob Faibussowitsch PetscCheckFalse(rank > 1,PetscObjectComm((PetscObject)pcbddc->coarse_phi_B),PETSC_ERR_PLIB,"Expected a sequential dense matrix"); 4482ab2d12f3SJunchao Zhang } 44835f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(v,1,&idx_V_B[i],&one,INSERT_VALUES)); 44845f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(v)); /* If v is on device, hope VecSetValues() eventually implemented by a host to device memcopy */ 44855f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(v)); 44865f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumnVec(pcbddc->coarse_phi_B,i,&v)); 448706656605SStefano Zampini 448806656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 44894f1b2e48SStefano Zampini PetscInt j; 44904f1b2e48SStefano Zampini 44915f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumnVec(pcbddc->coarse_phi_D,i,&v)); 44925f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD)); 44935f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD)); 4494ab2d12f3SJunchao Zhang if (PetscDefined(USE_DEBUG)) { /* The following VecSetValues() expects a sequential matrix */ 4495ab2d12f3SJunchao Zhang PetscMPIInt rank; 44965f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pcbddc->coarse_phi_D),&rank)); 44972c71b3e2SJacob Faibussowitsch PetscCheckFalse(rank > 1,PetscObjectComm((PetscObject)pcbddc->coarse_phi_D),PETSC_ERR_PLIB,"Expected a sequential dense matrix"); 4498ab2d12f3SJunchao Zhang } 44995f80ce2aSJacob Faibussowitsch for (j=0;j<pcbddc->benign_n;j++) CHKERRQ(VecSetValues(v,1,&p0_lidx_I[j],&zero,INSERT_VALUES)); 45005f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(v)); 45015f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(v)); 45025f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumnVec(pcbddc->coarse_phi_D,i,&v)); 450306656605SStefano Zampini } 45045f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec1_R)); 450506656605SStefano Zampini } 450604708bb6SStefano Zampini /* if n_R == 0 the object is not destroyed */ 45075f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_RV)); 450806656605SStefano Zampini } 45095f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&dummy_vec)); 451006656605SStefano Zampini 451106656605SStefano Zampini if (n_constraints) { 451206656605SStefano Zampini Mat B; 451306656605SStefano Zampini 45145f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B)); 45155f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(S_CC,m_one)); 45165f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductCreateWithMat(local_auxmat2_R,S_CC,NULL,B)); 45175f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSetType(B,MATPRODUCT_AB)); 45185f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSetFromOptions(B)); 45195f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductSymbolic(B)); 45205f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductNumeric(B)); 4521a961b312SStefano Zampini 45225f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(S_CC,m_one)); 452306656605SStefano Zampini if (n_vertices) { 452403dfb2d7SStefano Zampini if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */ 45255f80ce2aSJacob Faibussowitsch CHKERRQ(MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC)); 452680677318SStefano Zampini } else { 452780677318SStefano Zampini Mat S_VCt; 452880677318SStefano Zampini 4529ffd830a3SStefano Zampini if (lda_rhs != n_R) { 45305f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B)); 45315f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B)); 45325f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseSetLDA(B,lda_rhs)); 4533ffd830a3SStefano Zampini } 45345f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt)); 45355f80ce2aSJacob Faibussowitsch CHKERRQ(MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN)); 45365f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&S_VCt)); 453780677318SStefano Zampini } 453806656605SStefano Zampini } 45395f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B)); 454006656605SStefano Zampini /* coarse basis functions */ 454106656605SStefano Zampini for (i=0;i<n_constraints;i++) { 4542ab2d12f3SJunchao Zhang Vec v; 454306656605SStefano Zampini 45445f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i)); 45455f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumnVec(pcbddc->coarse_phi_B,i+n_vertices,&v)); 45465f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD)); 45475f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD)); 45485f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumnVec(pcbddc->coarse_phi_B,i+n_vertices,&v)); 454906656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 45504f1b2e48SStefano Zampini PetscInt j; 4551ab2d12f3SJunchao Zhang PetscScalar zero = 0.0; 45525f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumnVec(pcbddc->coarse_phi_D,i+n_vertices,&v)); 45535f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD)); 45545f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD)); 45555f80ce2aSJacob Faibussowitsch for (j=0;j<pcbddc->benign_n;j++) CHKERRQ(VecSetValues(v,1,&p0_lidx_I[j],&zero,INSERT_VALUES)); 45565f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(v)); 45575f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(v)); 45585f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumnVec(pcbddc->coarse_phi_D,i+n_vertices,&v)); 455906656605SStefano Zampini } 45605f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec1_R)); 456106656605SStefano Zampini } 456206656605SStefano Zampini } 456380677318SStefano Zampini if (n_constraints) { 45645f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&local_auxmat2_R)); 456580677318SStefano Zampini } 45665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(p0_lidx_I)); 456772b8c272SStefano Zampini 456872b8c272SStefano Zampini /* coarse matrix entries relative to B_0 */ 456972b8c272SStefano Zampini if (pcbddc->benign_n) { 457072b8c272SStefano Zampini Mat B0_B,B0_BPHI; 457172b8c272SStefano Zampini IS is_dummy; 45721683a169SBarry Smith const PetscScalar *data; 457372b8c272SStefano Zampini PetscInt j; 457472b8c272SStefano Zampini 45755f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy)); 45765f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B)); 45775f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_dummy)); 45785f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI)); 45795f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI)); 45805f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(B0_BPHI,&data)); 458172b8c272SStefano Zampini for (j=0;j<pcbddc->benign_n;j++) { 458272b8c272SStefano Zampini PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j; 458372b8c272SStefano Zampini for (i=0;i<pcbddc->local_primal_size;i++) { 458472b8c272SStefano Zampini coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j]; 458572b8c272SStefano Zampini coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j]; 458672b8c272SStefano Zampini } 458772b8c272SStefano Zampini } 45885f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(B0_BPHI,&data)); 45895f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B0_B)); 45905f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B0_BPHI)); 459172b8c272SStefano Zampini } 4592019a44ceSStefano Zampini 459306656605SStefano Zampini /* compute other basis functions for non-symmetric problems */ 45943301b35fSStefano Zampini if (!pcbddc->symmetric_primal) { 4595ffd830a3SStefano Zampini Mat B_V=NULL,B_C=NULL; 4596ffd830a3SStefano Zampini PetscScalar *marray; 459706656605SStefano Zampini 459806656605SStefano Zampini if (n_constraints) { 4599ffd830a3SStefano Zampini Mat S_CCT,C_CRT; 460006656605SStefano Zampini 46015f80ce2aSJacob Faibussowitsch CHKERRQ(MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT)); 46025f80ce2aSJacob Faibussowitsch CHKERRQ(MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT)); 46035f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C)); 46045f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&S_CCT)); 460506656605SStefano Zampini if (n_vertices) { 4606ffd830a3SStefano Zampini Mat S_VCT; 460706656605SStefano Zampini 46085f80ce2aSJacob Faibussowitsch CHKERRQ(MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT)); 46095f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V)); 46105f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&S_VCT)); 461106656605SStefano Zampini } 46125f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&C_CRT)); 46135b782168SStefano Zampini } else { 46145f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V)); 461506656605SStefano Zampini } 461616f15bc4SStefano Zampini if (n_vertices && n_R) { 4617ffd830a3SStefano Zampini PetscScalar *av,*marray; 4618ffd830a3SStefano Zampini const PetscInt *xadj,*adjncy; 4619ffd830a3SStefano Zampini PetscInt n; 4620ffd830a3SStefano Zampini PetscBool flg_row; 462106656605SStefano Zampini 4622ffd830a3SStefano Zampini /* B_V = B_V - A_VR^T */ 46235f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR)); 46245f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row)); 46255f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJGetArray(A_VR,&av)); 46265f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(B_V,&marray)); 4627ffd830a3SStefano Zampini for (i=0;i<n;i++) { 4628ffd830a3SStefano Zampini PetscInt j; 4629ffd830a3SStefano Zampini for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j]; 4630ffd830a3SStefano Zampini } 46315f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(B_V,&marray)); 46325f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row)); 46335f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_VR)); 463406656605SStefano Zampini } 463506656605SStefano Zampini 4636ffd830a3SStefano Zampini /* currently there's no support for MatTransposeMatSolve(F,B,X) */ 4637abc8f43dSstefano_zampini if (n_vertices) { 46385f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(B_V,&marray)); 4639ffd830a3SStefano Zampini for (i=0;i<n_vertices;i++) { 46405f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec1_R,marray+i*n_R)); 46415f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec2_R,work+i*n_R)); 46425f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R)); 46435f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R)); 46445f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec1_R)); 46455f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec2_R)); 464606656605SStefano Zampini } 46475f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(B_V,&marray)); 4648abc8f43dSstefano_zampini } 46495b782168SStefano Zampini if (B_C) { 46505f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(B_C,&marray)); 4651ffd830a3SStefano Zampini for (i=n_vertices;i<n_constraints+n_vertices;i++) { 46525f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R)); 46535f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec2_R,work+i*n_R)); 46545f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R)); 46555f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R)); 46565f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec1_R)); 46575f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec2_R)); 465806656605SStefano Zampini } 46595f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(B_C,&marray)); 46605b782168SStefano Zampini } 466106656605SStefano Zampini /* coarse basis functions */ 466206656605SStefano Zampini for (i=0;i<pcbddc->local_primal_size;i++) { 4663ab2d12f3SJunchao Zhang Vec v; 466406656605SStefano Zampini 46655f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec1_R,work+i*n_R)); 46665f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumnVec(pcbddc->coarse_psi_B,i,&v)); 46675f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD)); 46685f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD)); 466906656605SStefano Zampini if (i<n_vertices) { 4670ab2d12f3SJunchao Zhang PetscScalar one = 1.0; 46715f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(v,1,&idx_V_B[i],&one,INSERT_VALUES)); 46725f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(v)); 46735f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(v)); 467406656605SStefano Zampini } 46755f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumnVec(pcbddc->coarse_psi_B,i,&v)); 467606656605SStefano Zampini 467706656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 46785f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumnVec(pcbddc->coarse_psi_D,i,&v)); 46795f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD)); 46805f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,v,INSERT_VALUES,SCATTER_FORWARD)); 46815f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumnVec(pcbddc->coarse_psi_D,i,&v)); 468206656605SStefano Zampini } 46835f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec1_R)); 468406656605SStefano Zampini } 46855f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B_V)); 46865f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B_C)); 468706656605SStefano Zampini } 4688a6e023c1Sstefano_zampini 4689d62866d3SStefano Zampini /* free memory */ 46905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(idx_V_B)); 46915f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&S_VV)); 46925f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&S_CV)); 46935f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&S_VC)); 46945f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&S_CC)); 46955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(work)); 4696d62866d3SStefano Zampini if (n_vertices) { 46975f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_VR)); 4698d62866d3SStefano Zampini } 4699d62866d3SStefano Zampini if (n_constraints) { 47005f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&C_CR)); 4701d62866d3SStefano Zampini } 47025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_BDDC_CorrectionSetUp[pcbddc->current_level],pc,0,0,0)); 47038ead10e4SStefano Zampini 470488ebb749SStefano Zampini /* Checking coarse_sub_mat and coarse basis functios */ 470588ebb749SStefano Zampini /* Symmetric case : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */ 470688ebb749SStefano Zampini /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */ 4707d12edf2fSStefano Zampini if (pcbddc->dbg_flag) { 470888ebb749SStefano Zampini Mat coarse_sub_mat; 470925084f0cSStefano Zampini Mat AUXMAT,TM1,TM2,TM3,TM4; 471088ebb749SStefano Zampini Mat coarse_phi_D,coarse_phi_B; 471188ebb749SStefano Zampini Mat coarse_psi_D,coarse_psi_B; 471288ebb749SStefano Zampini Mat A_II,A_BB,A_IB,A_BI; 47138bec7fa6SStefano Zampini Mat C_B,CPHI; 47148bec7fa6SStefano Zampini IS is_dummy; 47158bec7fa6SStefano Zampini Vec mones; 471688ebb749SStefano Zampini MatType checkmattype=MATSEQAIJ; 471788ebb749SStefano Zampini PetscReal real_value; 471888ebb749SStefano Zampini 4719a3df083aSStefano Zampini if (pcbddc->benign_n && !pcbddc->benign_change_explicit) { 4720a3df083aSStefano Zampini Mat A; 47215f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCBenignProject(pc,NULL,NULL,&A)); 47225f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II)); 47235f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB)); 47245f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI)); 47255f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB)); 47265f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A)); 4727a3df083aSStefano Zampini } else { 47285f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II)); 47295f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB)); 47305f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI)); 47315f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB)); 4732a3df083aSStefano Zampini } 47335f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D)); 47345f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B)); 4735ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 47365f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D)); 47375f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B)); 473888ebb749SStefano Zampini } 47395f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat)); 474088ebb749SStefano Zampini 47415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n")); 47425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal)); 47435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 4744ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 47455f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT)); 47465f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1)); 47475f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&AUXMAT)); 47485f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT)); 47495f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2)); 47505f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&AUXMAT)); 47515f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT)); 47525f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3)); 47535f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&AUXMAT)); 47545f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT)); 47555f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4)); 47565f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&AUXMAT)); 475788ebb749SStefano Zampini } else { 47585f80ce2aSJacob Faibussowitsch CHKERRQ(MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1)); 47595f80ce2aSJacob Faibussowitsch CHKERRQ(MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2)); 47605f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT)); 47615f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3)); 47625f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&AUXMAT)); 47635f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT)); 47645f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4)); 47655f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&AUXMAT)); 476688ebb749SStefano Zampini } 47675f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN)); 47685f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN)); 47695f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN)); 47705f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1)); 47714f1b2e48SStefano Zampini if (pcbddc->benign_n) { 4772fc227af8SStefano Zampini Mat B0_B,B0_BPHI; 47731683a169SBarry Smith const PetscScalar *data2; 47741683a169SBarry Smith PetscScalar *data; 47754f1b2e48SStefano Zampini PetscInt j; 4776d12edf2fSStefano Zampini 47775f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy)); 47785f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B)); 47795f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI)); 47805f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI)); 47815f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(TM1,&data)); 47825f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(B0_BPHI,&data2)); 47834f1b2e48SStefano Zampini for (j=0;j<pcbddc->benign_n;j++) { 47844f1b2e48SStefano Zampini PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j; 4785d12edf2fSStefano Zampini for (i=0;i<pcbddc->local_primal_size;i++) { 47864f1b2e48SStefano Zampini data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j]; 47874f1b2e48SStefano Zampini data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j]; 47884f1b2e48SStefano Zampini } 4789d12edf2fSStefano Zampini } 47905f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(TM1,&data)); 47915f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(B0_BPHI,&data2)); 47925f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B0_B)); 47935f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_dummy)); 47945f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B0_BPHI)); 4795d12edf2fSStefano Zampini } 4796d12edf2fSStefano Zampini #if 0 4797d12edf2fSStefano Zampini { 4798d12edf2fSStefano Zampini PetscViewer viewer; 4799d12edf2fSStefano Zampini char filename[256]; 4800ffd830a3SStefano Zampini sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level); 48015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer)); 48025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB)); 48035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)coarse_sub_mat,"computed")); 48045f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(coarse_sub_mat,viewer)); 48055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)TM1,"projected")); 48065f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(TM1,viewer)); 4807a7414863SStefano Zampini if (pcbddc->coarse_phi_B) { 48085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B")); 48095f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(pcbddc->coarse_phi_B,viewer)); 481072b8c272SStefano Zampini } 4811ffd830a3SStefano Zampini if (pcbddc->coarse_phi_D) { 48125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D")); 48135f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(pcbddc->coarse_phi_D,viewer)); 4814ffd830a3SStefano Zampini } 4815ffd830a3SStefano Zampini if (pcbddc->coarse_psi_B) { 48165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B")); 48175f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(pcbddc->coarse_psi_B,viewer)); 4818ffd830a3SStefano Zampini } 481972b8c272SStefano Zampini if (pcbddc->coarse_psi_D) { 48205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D")); 48215f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(pcbddc->coarse_psi_D,viewer)); 4822ffd830a3SStefano Zampini } 48235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)pcbddc->local_mat,"A")); 48245f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(pcbddc->local_mat,viewer)); 48255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C")); 48265f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(pcbddc->ConstraintMatrix,viewer)); 48275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)pcis->is_I_local,"I")); 48285f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(pcis->is_I_local,viewer)); 48295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)pcis->is_B_local,"B")); 48305f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(pcis->is_B_local,viewer)); 48315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R")); 48325f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(pcbddc->is_R_local,viewer)); 48335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 4834d12edf2fSStefano Zampini } 4835d12edf2fSStefano Zampini #endif 48365f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN)); 48375f80ce2aSJacob Faibussowitsch CHKERRQ(MatNorm(TM1,NORM_FROBENIUS,&real_value)); 48385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 48395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d matrix error % 1.14e\n",PetscGlobalRank,real_value)); 48408bec7fa6SStefano Zampini 48418bec7fa6SStefano Zampini /* check constraints */ 48425f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy)); 48435f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B)); 48444f1b2e48SStefano Zampini if (!pcbddc->benign_n) { /* TODO: add benign case */ 48455f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI)); 4846a00504b5SStefano Zampini } else { 4847a00504b5SStefano Zampini PetscScalar *data; 4848a00504b5SStefano Zampini Mat tmat; 48495f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(pcbddc->coarse_phi_B,&data)); 48505f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat)); 48515f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(pcbddc->coarse_phi_B,&data)); 48525f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI)); 48535f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&tmat)); 4854a00504b5SStefano Zampini } 48555f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(CPHI,&mones,NULL)); 48565f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(mones,-1.0)); 48575f80ce2aSJacob Faibussowitsch CHKERRQ(MatDiagonalSet(CPHI,mones,ADD_VALUES)); 48585f80ce2aSJacob Faibussowitsch CHKERRQ(MatNorm(CPHI,NORM_FROBENIUS,&real_value)); 48595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value)); 4860ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 48615f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI)); 48625f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(mones,-1.0)); 48635f80ce2aSJacob Faibussowitsch CHKERRQ(MatDiagonalSet(CPHI,mones,ADD_VALUES)); 48645f80ce2aSJacob Faibussowitsch CHKERRQ(MatNorm(CPHI,NORM_FROBENIUS,&real_value)); 48655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value)); 486688ebb749SStefano Zampini } 48675f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&C_B)); 48685f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&CPHI)); 48695f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_dummy)); 48705f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&mones)); 48715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 48725f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_II)); 48735f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_BB)); 48745f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_IB)); 48755f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_BI)); 48765f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&TM1)); 48775f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&TM2)); 48785f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&TM3)); 48795f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&TM4)); 48805f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&coarse_phi_D)); 48815f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&coarse_phi_B)); 4882ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 48835f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&coarse_psi_D)); 48845f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&coarse_psi_B)); 488588ebb749SStefano Zampini } 48865f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&coarse_sub_mat)); 488788ebb749SStefano Zampini } 48887ebab0bbSStefano Zampini /* FINAL CUDA support (we cannot currently mix viennacl and cuda vectors */ 48897ebab0bbSStefano Zampini { 48907ebab0bbSStefano Zampini PetscBool gpu; 48917ebab0bbSStefano Zampini 48925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)pcis->vec1_N,VECSEQCUDA,&gpu)); 48937ebab0bbSStefano Zampini if (gpu) { 48947ebab0bbSStefano Zampini if (pcbddc->local_auxmat1) { 48955f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcbddc->local_auxmat1,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->local_auxmat1)); 48967ebab0bbSStefano Zampini } 48977ebab0bbSStefano Zampini if (pcbddc->local_auxmat2) { 48985f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcbddc->local_auxmat2,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->local_auxmat2)); 48997ebab0bbSStefano Zampini } 49007ebab0bbSStefano Zampini if (pcbddc->coarse_phi_B) { 49015f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcbddc->coarse_phi_B,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_phi_B)); 49027ebab0bbSStefano Zampini } 49037ebab0bbSStefano Zampini if (pcbddc->coarse_phi_D) { 49045f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcbddc->coarse_phi_D,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_phi_D)); 49057ebab0bbSStefano Zampini } 49067ebab0bbSStefano Zampini if (pcbddc->coarse_psi_B) { 49075f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcbddc->coarse_psi_B,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_psi_B)); 49087ebab0bbSStefano Zampini } 49097ebab0bbSStefano Zampini if (pcbddc->coarse_psi_D) { 49105f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcbddc->coarse_psi_D,MATSEQDENSECUDA,MAT_INPLACE_MATRIX,&pcbddc->coarse_psi_D)); 49117ebab0bbSStefano Zampini } 49127ebab0bbSStefano Zampini } 49137ebab0bbSStefano Zampini } 49148629588bSStefano Zampini /* get back data */ 49158629588bSStefano Zampini *coarse_submat_vals_n = coarse_submat_vals; 491688ebb749SStefano Zampini PetscFunctionReturn(0); 491788ebb749SStefano Zampini } 491888ebb749SStefano Zampini 49197dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B) 4920aa0d41d4SStefano Zampini { 4921d65f70fdSStefano Zampini Mat *work_mat; 4922d65f70fdSStefano Zampini IS isrow_s,iscol_s; 4923d65f70fdSStefano Zampini PetscBool rsorted,csorted; 4924c43ebad9SStefano Zampini PetscInt rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL; 4925aa0d41d4SStefano Zampini 4926aa0d41d4SStefano Zampini PetscFunctionBegin; 49275f80ce2aSJacob Faibussowitsch CHKERRQ(ISSorted(isrow,&rsorted)); 49285f80ce2aSJacob Faibussowitsch CHKERRQ(ISSorted(iscol,&csorted)); 49295f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(isrow,&rsize)); 49305f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(iscol,&csize)); 4931aa0d41d4SStefano Zampini 4932d65f70fdSStefano Zampini if (!rsorted) { 4933906d46d4SStefano Zampini const PetscInt *idxs; 4934906d46d4SStefano Zampini PetscInt *idxs_sorted,i; 4935aa0d41d4SStefano Zampini 49365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(rsize,&idxs_perm_r)); 49375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(rsize,&idxs_sorted)); 4938d65f70fdSStefano Zampini for (i=0;i<rsize;i++) { 4939d65f70fdSStefano Zampini idxs_perm_r[i] = i; 4940aa0d41d4SStefano Zampini } 49415f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(isrow,&idxs)); 49425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r)); 4943d65f70fdSStefano Zampini for (i=0;i<rsize;i++) { 4944d65f70fdSStefano Zampini idxs_sorted[i] = idxs[idxs_perm_r[i]]; 4945aa0d41d4SStefano Zampini } 49465f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(isrow,&idxs)); 49475f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s)); 4948d65f70fdSStefano Zampini } else { 49495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)isrow)); 4950d65f70fdSStefano Zampini isrow_s = isrow; 4951aa0d41d4SStefano Zampini } 4952906d46d4SStefano Zampini 4953d65f70fdSStefano Zampini if (!csorted) { 4954d65f70fdSStefano Zampini if (isrow == iscol) { 49555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)isrow_s)); 4956d65f70fdSStefano Zampini iscol_s = isrow_s; 4957d65f70fdSStefano Zampini } else { 4958d65f70fdSStefano Zampini const PetscInt *idxs; 4959d65f70fdSStefano Zampini PetscInt *idxs_sorted,i; 4960906d46d4SStefano Zampini 49615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(csize,&idxs_perm_c)); 49625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(csize,&idxs_sorted)); 4963d65f70fdSStefano Zampini for (i=0;i<csize;i++) { 4964d65f70fdSStefano Zampini idxs_perm_c[i] = i; 4965d65f70fdSStefano Zampini } 49665f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(iscol,&idxs)); 49675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortIntWithPermutation(csize,idxs,idxs_perm_c)); 4968d65f70fdSStefano Zampini for (i=0;i<csize;i++) { 4969d65f70fdSStefano Zampini idxs_sorted[i] = idxs[idxs_perm_c[i]]; 4970d65f70fdSStefano Zampini } 49715f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(iscol,&idxs)); 49725f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s)); 4973d65f70fdSStefano Zampini } 4974d65f70fdSStefano Zampini } else { 49755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)iscol)); 4976d65f70fdSStefano Zampini iscol_s = iscol; 4977d65f70fdSStefano Zampini } 4978d65f70fdSStefano Zampini 49795f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat)); 4980d65f70fdSStefano Zampini 4981d65f70fdSStefano Zampini if (!rsorted || !csorted) { 4982906d46d4SStefano Zampini Mat new_mat; 4983d65f70fdSStefano Zampini IS is_perm_r,is_perm_c; 4984906d46d4SStefano Zampini 4985d65f70fdSStefano Zampini if (!rsorted) { 4986d65f70fdSStefano Zampini PetscInt *idxs_r,i; 49875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(rsize,&idxs_r)); 4988d65f70fdSStefano Zampini for (i=0;i<rsize;i++) { 4989d65f70fdSStefano Zampini idxs_r[idxs_perm_r[i]] = i; 4990906d46d4SStefano Zampini } 49915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(idxs_perm_r)); 49925f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r)); 4993d65f70fdSStefano Zampini } else { 49945f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r)); 4995906d46d4SStefano Zampini } 49965f80ce2aSJacob Faibussowitsch CHKERRQ(ISSetPermutation(is_perm_r)); 4997d65f70fdSStefano Zampini 4998d65f70fdSStefano Zampini if (!csorted) { 4999d65f70fdSStefano Zampini if (isrow_s == iscol_s) { 50005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)is_perm_r)); 5001d65f70fdSStefano Zampini is_perm_c = is_perm_r; 5002d65f70fdSStefano Zampini } else { 5003d65f70fdSStefano Zampini PetscInt *idxs_c,i; 5004*28b400f6SJacob Faibussowitsch PetscCheck(idxs_perm_c,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Permutation array not present"); 50055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(csize,&idxs_c)); 5006d65f70fdSStefano Zampini for (i=0;i<csize;i++) { 5007d65f70fdSStefano Zampini idxs_c[idxs_perm_c[i]] = i; 5008d65f70fdSStefano Zampini } 50095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(idxs_perm_c)); 50105f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c)); 5011d65f70fdSStefano Zampini } 5012d65f70fdSStefano Zampini } else { 50135f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c)); 5014d65f70fdSStefano Zampini } 50155f80ce2aSJacob Faibussowitsch CHKERRQ(ISSetPermutation(is_perm_c)); 5016d65f70fdSStefano Zampini 50175f80ce2aSJacob Faibussowitsch CHKERRQ(MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat)); 50185f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&work_mat[0])); 5019d65f70fdSStefano Zampini work_mat[0] = new_mat; 50205f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_perm_r)); 50215f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_perm_c)); 5022d65f70fdSStefano Zampini } 5023d65f70fdSStefano Zampini 50245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)work_mat[0])); 5025d65f70fdSStefano Zampini *B = work_mat[0]; 50265f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroyMatrices(1,&work_mat)); 50275f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&isrow_s)); 50285f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&iscol_s)); 5029d65f70fdSStefano Zampini PetscFunctionReturn(0); 5030d65f70fdSStefano Zampini } 5031d65f70fdSStefano Zampini 50325e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix) 5033aa0d41d4SStefano Zampini { 5034aa0d41d4SStefano Zampini Mat_IS* matis = (Mat_IS*)pc->pmat->data; 50355e8657edSStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 5036022d8d2bSstefano_zampini Mat new_mat,lA; 50375e8657edSStefano Zampini IS is_local,is_global; 5038d65f70fdSStefano Zampini PetscInt local_size; 5039d65f70fdSStefano Zampini PetscBool isseqaij; 5040aa0d41d4SStefano Zampini 5041aa0d41d4SStefano Zampini PetscFunctionBegin; 50425f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->local_mat)); 50435f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(matis->A,&local_size,NULL)); 50445f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local)); 50455f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApplyIS(matis->rmapping,is_local,&is_global)); 50465f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_local)); 50475f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat)); 50485f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_global)); 5049906d46d4SStefano Zampini 5050906d46d4SStefano Zampini if (pcbddc->dbg_flag) { 5051906d46d4SStefano Zampini Vec x,x_change; 5052906d46d4SStefano Zampini PetscReal error; 5053906d46d4SStefano Zampini 50545f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change)); 50555f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetRandom(x,NULL)); 50565f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(ChangeOfBasisMatrix,x,x_change)); 50575f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD)); 50585f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD)); 50595f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(new_mat,matis->x,matis->y)); 506088428137SStefano Zampini if (!pcbddc->change_interior) { 506188428137SStefano Zampini const PetscScalar *x,*y,*v; 506288428137SStefano Zampini PetscReal lerror = 0.; 506388428137SStefano Zampini PetscInt i; 506488428137SStefano Zampini 50655f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(matis->x,&x)); 50665f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(matis->y,&y)); 50675f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(matis->counter,&v)); 506888428137SStefano Zampini for (i=0;i<local_size;i++) 506988428137SStefano Zampini if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i]-y[i]) > lerror) 507088428137SStefano Zampini lerror = PetscAbsScalar(x[i]-y[i]); 50715f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(matis->x,&x)); 50725f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(matis->y,&y)); 50735f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(matis->counter,&v)); 50745f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&lerror,&error,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)pc))); 5075637e8532SStefano Zampini if (error > PETSC_SMALL) { 5076637e8532SStefano Zampini if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) { 507798921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on I: %1.6e",error); 5078637e8532SStefano Zampini } else { 507998921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on I: %1.6e",error); 5080637e8532SStefano Zampini } 5081637e8532SStefano Zampini } 508288428137SStefano Zampini } 50835f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE)); 50845f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE)); 50855f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(x,-1.0,x_change)); 50865f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(x,NORM_INFINITY,&error)); 5087637e8532SStefano Zampini if (error > PETSC_SMALL) { 5088637e8532SStefano Zampini if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) { 508998921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",error); 5090637e8532SStefano Zampini } else { 509198921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_USER,"Error global vs local change on N: %1.6e",error); 5092637e8532SStefano Zampini } 5093637e8532SStefano Zampini } 50945f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&x)); 50955f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&x_change)); 5096906d46d4SStefano Zampini } 5097906d46d4SStefano Zampini 5098022d8d2bSstefano_zampini /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */ 50995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA)); 5100022d8d2bSstefano_zampini 510122d5777bSStefano Zampini /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */ 51025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij)); 510322d5777bSStefano Zampini if (isseqaij) { 51045f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->local_mat)); 51055f80ce2aSJacob Faibussowitsch CHKERRQ(MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat)); 5106022d8d2bSstefano_zampini if (lA) { 5107022d8d2bSstefano_zampini Mat work; 51085f80ce2aSJacob Faibussowitsch CHKERRQ(MatPtAP(lA,new_mat,MAT_INITIAL_MATRIX,2.0,&work)); 51095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work)); 51105f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&work)); 5111022d8d2bSstefano_zampini } 5112aa0d41d4SStefano Zampini } else { 5113a00504b5SStefano Zampini Mat work_mat; 51141cf9b237SStefano Zampini 51155f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->local_mat)); 51165f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat)); 51175f80ce2aSJacob Faibussowitsch CHKERRQ(MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat)); 51185f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&work_mat)); 5119022d8d2bSstefano_zampini if (lA) { 5120022d8d2bSstefano_zampini Mat work; 51215f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(lA,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat)); 51225f80ce2aSJacob Faibussowitsch CHKERRQ(MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&work)); 51235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject)work)); 51245f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&work)); 5125022d8d2bSstefano_zampini } 5126aa0d41d4SStefano Zampini } 51273301b35fSStefano Zampini if (matis->A->symmetric_set) { 51285f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric)); 5129e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX) 51305f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric)); 5131e496cd5dSStefano Zampini #endif 51323301b35fSStefano Zampini } 51335f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&new_mat)); 5134aa0d41d4SStefano Zampini PetscFunctionReturn(0); 5135aa0d41d4SStefano Zampini } 5136aa0d41d4SStefano Zampini 51378ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc) 5138a64d13efSStefano Zampini { 5139a64d13efSStefano Zampini PC_IS* pcis = (PC_IS*)(pc->data); 5140a64d13efSStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 5141d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 514253892102SStefano Zampini PetscInt *idx_R_local=NULL; 51433a50541eSStefano Zampini PetscInt n_vertices,i,j,n_R,n_D,n_B; 51443a50541eSStefano Zampini PetscInt vbs,bs; 51456816873aSStefano Zampini PetscBT bitmask=NULL; 5146a64d13efSStefano Zampini 5147a64d13efSStefano Zampini PetscFunctionBegin; 5148b23d619eSStefano Zampini /* 5149b23d619eSStefano Zampini No need to setup local scatters if 5150b23d619eSStefano Zampini - primal space is unchanged 5151b23d619eSStefano Zampini AND 5152b23d619eSStefano Zampini - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains) 5153b23d619eSStefano Zampini AND 5154b23d619eSStefano Zampini - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine 5155b23d619eSStefano Zampini */ 5156b23d619eSStefano Zampini if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) { 5157f4ddd8eeSStefano Zampini PetscFunctionReturn(0); 5158f4ddd8eeSStefano Zampini } 5159f4ddd8eeSStefano Zampini /* destroy old objects */ 51605f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->is_R_local)); 51615f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterDestroy(&pcbddc->R_to_B)); 51625f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterDestroy(&pcbddc->R_to_D)); 5163a64d13efSStefano Zampini /* Set Non-overlapping dimensions */ 5164b371cd4fSStefano Zampini n_B = pcis->n_B; 5165b371cd4fSStefano Zampini n_D = pcis->n - n_B; 5166b371cd4fSStefano Zampini n_vertices = pcbddc->n_vertices; 51673a50541eSStefano Zampini 5168a64d13efSStefano Zampini /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */ 51696816873aSStefano Zampini 517053892102SStefano Zampini /* create auxiliary bitmask and allocate workspace */ 5171b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 51725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcis->n-n_vertices,&idx_R_local)); 51735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(pcis->n,&bitmask)); 5174a64d13efSStefano Zampini for (i=0;i<n_vertices;i++) { 51755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i])); 5176a64d13efSStefano Zampini } 5177a64d13efSStefano Zampini 5178a64d13efSStefano Zampini for (i=0, n_R=0; i<pcis->n; i++) { 51794641a718SStefano Zampini if (!PetscBTLookup(bitmask,i)) { 51806816873aSStefano Zampini idx_R_local[n_R++] = i; 5181a64d13efSStefano Zampini } 5182a64d13efSStefano Zampini } 5183df4d28bfSStefano Zampini } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */ 5184df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 51856816873aSStefano Zampini 51865f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local)); 51875f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(reuse_solver->is_R,&n_R)); 51886816873aSStefano Zampini } 51893a50541eSStefano Zampini 51903a50541eSStefano Zampini /* Block code */ 51913a50541eSStefano Zampini vbs = 1; 51925f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetBlockSize(pcbddc->local_mat,&bs)); 51933a50541eSStefano Zampini if (bs>1 && !(n_vertices%bs)) { 51943a50541eSStefano Zampini PetscBool is_blocked = PETSC_TRUE; 51953a50541eSStefano Zampini PetscInt *vary; 5196b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 51975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcis->n/bs,&vary)); 51985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(vary,pcis->n/bs)); 5199d3df7717SStefano Zampini /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */ 5200d3df7717SStefano Zampini /* it is ok to check this way since local_primal_ref_node are always sorted by local numbering and idx_R_local is obtained as a complement */ 52010e6343abSStefano Zampini for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++; 5202d3df7717SStefano Zampini for (i=0; i<pcis->n/bs; i++) { 52033a50541eSStefano Zampini if (vary[i]!=0 && vary[i]!=bs) { 52043a50541eSStefano Zampini is_blocked = PETSC_FALSE; 52053a50541eSStefano Zampini break; 52063a50541eSStefano Zampini } 52073a50541eSStefano Zampini } 52085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vary)); 5209d3df7717SStefano Zampini } else { 5210d3df7717SStefano Zampini /* Verify directly the R set */ 5211d3df7717SStefano Zampini for (i=0; i<n_R/bs; i++) { 5212d3df7717SStefano Zampini PetscInt j,node=idx_R_local[bs*i]; 5213d3df7717SStefano Zampini for (j=1; j<bs; j++) { 5214d3df7717SStefano Zampini if (node != idx_R_local[bs*i+j]-j) { 5215d3df7717SStefano Zampini is_blocked = PETSC_FALSE; 5216d3df7717SStefano Zampini break; 5217d3df7717SStefano Zampini } 5218d3df7717SStefano Zampini } 5219d3df7717SStefano Zampini } 5220d3df7717SStefano Zampini } 52213a50541eSStefano Zampini if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */ 52223a50541eSStefano Zampini vbs = bs; 52233a50541eSStefano Zampini for (i=0;i<n_R/vbs;i++) { 52243a50541eSStefano Zampini idx_R_local[i] = idx_R_local[vbs*i]/vbs; 52253a50541eSStefano Zampini } 52263a50541eSStefano Zampini } 52273a50541eSStefano Zampini } 52285f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local)); 5229b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 5230df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 523153892102SStefano Zampini 52325f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local)); 52335f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&reuse_solver->is_R)); 52345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)pcbddc->is_R_local)); 5235df4d28bfSStefano Zampini reuse_solver->is_R = pcbddc->is_R_local; 523653892102SStefano Zampini } else { 52375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(idx_R_local)); 523853892102SStefano Zampini } 5239a64d13efSStefano Zampini 5240a64d13efSStefano Zampini /* print some info if requested */ 5241a64d13efSStefano Zampini if (pcbddc->dbg_flag) { 52425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n")); 52435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 52445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 52455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank)); 52465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %D, dirichlet_size = %D, boundary_size = %D\n",pcis->n,n_D,n_B)); 52475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"r_size = %D, v_size = %D, constraints = %D, local_primal_size = %D\n",n_R,n_vertices,pcbddc->local_primal_size-n_vertices-pcbddc->benign_n,pcbddc->local_primal_size)); 52485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 5249a64d13efSStefano Zampini } 5250a64d13efSStefano Zampini 5251a64d13efSStefano Zampini /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */ 5252b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 52536816873aSStefano Zampini IS is_aux1,is_aux2; 52546816873aSStefano Zampini PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local; 52556816873aSStefano Zampini 52565f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local)); 52575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcis->n_B-n_vertices,&aux_array1)); 52585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcis->n_B-n_vertices,&aux_array2)); 52595f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices)); 52604641a718SStefano Zampini for (i=0; i<n_D; i++) { 52615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(bitmask,is_indices[i])); 52624641a718SStefano Zampini } 52635f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices)); 5264a64d13efSStefano Zampini for (i=0, j=0; i<n_R; i++) { 52654641a718SStefano Zampini if (!PetscBTLookup(bitmask,idx_R_local[i])) { 52664641a718SStefano Zampini aux_array1[j++] = i; 5267a64d13efSStefano Zampini } 5268a64d13efSStefano Zampini } 52695f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1)); 52705f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices)); 5271a64d13efSStefano Zampini for (i=0, j=0; i<n_B; i++) { 52724641a718SStefano Zampini if (!PetscBTLookup(bitmask,is_indices[i])) { 52734641a718SStefano Zampini aux_array2[j++] = i; 5274a64d13efSStefano Zampini } 5275a64d13efSStefano Zampini } 52765f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices)); 52775f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2)); 52785f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B)); 52795f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_aux1)); 52805f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_aux2)); 5281a64d13efSStefano Zampini 52828eeda7d8SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 52835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n_D,&aux_array1)); 5284a64d13efSStefano Zampini for (i=0, j=0; i<n_R; i++) { 52854641a718SStefano Zampini if (PetscBTLookup(bitmask,idx_R_local[i])) { 52864641a718SStefano Zampini aux_array1[j++] = i; 5287a64d13efSStefano Zampini } 5288a64d13efSStefano Zampini } 52895f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1)); 52905f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D)); 52915f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_aux1)); 5292a64d13efSStefano Zampini } 52935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&bitmask)); 52945f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local)); 5295d62866d3SStefano Zampini } else { 5296df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 52976816873aSStefano Zampini IS tis; 52986816873aSStefano Zampini PetscInt schur_size; 52996816873aSStefano Zampini 53005f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(reuse_solver->is_B,&schur_size)); 53015f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis)); 53025f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B)); 53035f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&tis)); 53046816873aSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 53055f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis)); 53065f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D)); 53075f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&tis)); 5308d62866d3SStefano Zampini } 5309d62866d3SStefano Zampini } 5310a64d13efSStefano Zampini PetscFunctionReturn(0); 5311a64d13efSStefano Zampini } 5312a64d13efSStefano Zampini 53136d9e27e4SStefano Zampini static PetscErrorCode MatNullSpacePropagateAny_Private(Mat A, IS is, Mat B) 531492cccca0SStefano Zampini { 531592cccca0SStefano Zampini MatNullSpace NullSpace; 531692cccca0SStefano Zampini Mat dmat; 531792cccca0SStefano Zampini const Vec *nullvecs; 531892cccca0SStefano Zampini Vec v,v2,*nullvecs2; 53196d9e27e4SStefano Zampini VecScatter sct = NULL; 5320eb06acf8SStefano Zampini PetscContainer c; 5321eb06acf8SStefano Zampini PetscScalar *ddata; 5322295df10fSStefano Zampini PetscInt k,nnsp_size,bsiz,bsiz2,n,N,bs; 532392cccca0SStefano Zampini PetscBool nnsp_has_cnst; 532492cccca0SStefano Zampini 532592cccca0SStefano Zampini PetscFunctionBegin; 53266d9e27e4SStefano Zampini if (!is && !B) { /* MATIS */ 53276d9e27e4SStefano Zampini Mat_IS* matis = (Mat_IS*)A->data; 53286d9e27e4SStefano Zampini 53296d9e27e4SStefano Zampini if (!B) { 53305f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(A,&B)); 53316d9e27e4SStefano Zampini } 53326d9e27e4SStefano Zampini sct = matis->cctx; 53335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)sct)); 53346d9e27e4SStefano Zampini } else { 53355f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNullSpace(B,&NullSpace)); 533692cccca0SStefano Zampini if (!NullSpace) { 53375f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNearNullSpace(B,&NullSpace)); 533892cccca0SStefano Zampini } 533992cccca0SStefano Zampini if (NullSpace) PetscFunctionReturn(0); 53406d9e27e4SStefano Zampini } 53415f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNullSpace(A,&NullSpace)); 534292cccca0SStefano Zampini if (!NullSpace) { 53435f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNearNullSpace(A,&NullSpace)); 534492cccca0SStefano Zampini } 534592cccca0SStefano Zampini if (!NullSpace) PetscFunctionReturn(0); 53466d9e27e4SStefano Zampini 53475f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(A,&v,NULL)); 53485f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(B,&v2,NULL)); 53496d9e27e4SStefano Zampini if (!sct) { 53505f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterCreate(v,is,v2,NULL,&sct)); 53516d9e27e4SStefano Zampini } 53525f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceGetVecs(NullSpace,&nnsp_has_cnst,&nnsp_size,(const Vec**)&nullvecs)); 5353295df10fSStefano Zampini bsiz = bsiz2 = nnsp_size+!!nnsp_has_cnst; 53545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(bsiz,&nullvecs2)); 53555f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetBlockSize(v2,&bs)); 53565f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSize(v2,&N)); 53575f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(v2,&n)); 53585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n*bsiz,&ddata)); 535992cccca0SStefano Zampini for (k=0;k<nnsp_size;k++) { 53605f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B),bs,n,N,ddata + n*k,&nullvecs2[k])); 53615f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(sct,nullvecs[k],nullvecs2[k],INSERT_VALUES,SCATTER_FORWARD)); 53625f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(sct,nullvecs[k],nullvecs2[k],INSERT_VALUES,SCATTER_FORWARD)); 536392cccca0SStefano Zampini } 536492cccca0SStefano Zampini if (nnsp_has_cnst) { 53655f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B),bs,n,N,ddata + n*nnsp_size,&nullvecs2[nnsp_size])); 53665f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(nullvecs2[nnsp_size],1.0)); 536792cccca0SStefano Zampini } 53685f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCOrthonormalizeVecs(&bsiz2,nullvecs2)); 53695f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceCreate(PetscObjectComm((PetscObject)B),PETSC_FALSE,bsiz2,nullvecs2,&NullSpace)); 5370295df10fSStefano Zampini 53715f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateDense(PetscObjectComm((PetscObject)B),n,PETSC_DECIDE,N,bsiz2,ddata,&dmat)); 53725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscContainerCreate(PetscObjectComm((PetscObject)B),&c)); 53735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscContainerSetPointer(c,ddata)); 53745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault)); 53755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject)dmat,"_PBDDC_Null_dmat_arr",(PetscObject)c)); 53765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscContainerDestroy(&c)); 53775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject)NullSpace,"_PBDDC_Null_dmat",(PetscObject)dmat)); 53785f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&dmat)); 5379eb06acf8SStefano Zampini 538092cccca0SStefano Zampini for (k=0;k<bsiz;k++) { 53815f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&nullvecs2[k])); 538292cccca0SStefano Zampini } 53835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(nullvecs2)); 53845f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetNearNullSpace(B,NullSpace)); 53855f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceDestroy(&NullSpace)); 53865f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&v)); 53875f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&v2)); 53885f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterDestroy(&sct)); 538992cccca0SStefano Zampini PetscFunctionReturn(0); 539092cccca0SStefano Zampini } 5391304d26faSStefano Zampini 5392684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann) 5393304d26faSStefano Zampini { 5394304d26faSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 5395304d26faSStefano Zampini PC_IS *pcis = (PC_IS*)pc->data; 5396304d26faSStefano Zampini PC pc_temp; 5397304d26faSStefano Zampini Mat A_RR; 539892cccca0SStefano Zampini MatNullSpace nnsp; 5399f4ddd8eeSStefano Zampini MatReuse reuse; 5400304d26faSStefano Zampini PetscScalar m_one = -1.0; 5401304d26faSStefano Zampini PetscReal value; 540204708bb6SStefano Zampini PetscInt n_D,n_R; 540392cccca0SStefano Zampini PetscBool issbaij,opts; 54040a545947SLisandro Dalcin void (*f)(void) = NULL; 5405312be037SStefano Zampini char dir_prefix[256],neu_prefix[256],str_level[16]; 5406e604994aSStefano Zampini size_t len; 5407304d26faSStefano Zampini 5408304d26faSStefano Zampini PetscFunctionBegin; 54095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0)); 54106d9e27e4SStefano Zampini /* approximate solver, propagate NearNullSpace if needed */ 54116d9e27e4SStefano Zampini if (!pc->setupcalled && (pcbddc->NullSpace_corr[0] || pcbddc->NullSpace_corr[2])) { 54126d9e27e4SStefano Zampini MatNullSpace gnnsp1,gnnsp2; 54136d9e27e4SStefano Zampini PetscBool lhas,ghas; 54146d9e27e4SStefano Zampini 54155f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNearNullSpace(pcbddc->local_mat,&nnsp)); 54165f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNearNullSpace(pc->pmat,&gnnsp1)); 54175f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNullSpace(pc->pmat,&gnnsp2)); 54186d9e27e4SStefano Zampini lhas = nnsp ? PETSC_TRUE : PETSC_FALSE; 54195f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&lhas,&ghas,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc))); 54206d9e27e4SStefano Zampini if (!ghas && (gnnsp1 || gnnsp2)) { 54215f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpacePropagateAny_Private(pc->pmat,NULL,NULL)); 54226d9e27e4SStefano Zampini } 54236d9e27e4SStefano Zampini } 54246d9e27e4SStefano Zampini 5425e604994aSStefano Zampini /* compute prefixes */ 54265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcpy(dir_prefix,"")); 54275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcpy(neu_prefix,"")); 5428e604994aSStefano Zampini if (!pcbddc->current_level) { 54295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,sizeof(dir_prefix))); 54305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,sizeof(neu_prefix))); 54315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix))); 54325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix))); 5433e604994aSStefano Zampini } else { 54345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level))); 54355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(((PetscObject)pc)->prefix,&len)); 5436e604994aSStefano Zampini len -= 15; /* remove "pc_bddc_coarse_" */ 5437312be037SStefano Zampini if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */ 5438312be037SStefano Zampini if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */ 5439a126751eSBarry Smith /* Nonstandard use of PetscStrncpy() to only copy a portion of the input string */ 54405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1)); 54415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1)); 54425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(dir_prefix,"pc_bddc_dirichlet_",sizeof(dir_prefix))); 54435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(neu_prefix,"pc_bddc_neumann_",sizeof(neu_prefix))); 54445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(dir_prefix,str_level,sizeof(dir_prefix))); 54455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(neu_prefix,str_level,sizeof(neu_prefix))); 5446e604994aSStefano Zampini } 5447e604994aSStefano Zampini 5448304d26faSStefano Zampini /* DIRICHLET PROBLEM */ 5449684f6988SStefano Zampini if (dirichlet) { 5450d5574798SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 5451450f8f5eSStefano Zampini if (pcbddc->benign_n && !pcbddc->benign_change_explicit) { 54522c71b3e2SJacob Faibussowitsch PetscCheckFalse(!sub_schurs || !sub_schurs->reuse_solver,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented"); 5453450f8f5eSStefano Zampini if (pcbddc->dbg_flag) { 5454a3df083aSStefano Zampini Mat A_IIn; 5455a3df083aSStefano Zampini 54565f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn)); 54575f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcis->A_II)); 5458a3df083aSStefano Zampini pcis->A_II = A_IIn; 5459a3df083aSStefano Zampini } 5460450f8f5eSStefano Zampini } 54613301b35fSStefano Zampini if (pcbddc->local_mat->symmetric_set) { 54625f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric)); 5463964fefecSStefano Zampini } 5464ac78edfcSStefano Zampini /* Matrix for Dirichlet problem is pcis->A_II */ 5465964fefecSStefano Zampini n_D = pcis->n - pcis->n_B; 546692cccca0SStefano Zampini opts = PETSC_FALSE; 5467304d26faSStefano Zampini if (!pcbddc->ksp_D) { /* create object if not yet build */ 546892cccca0SStefano Zampini opts = PETSC_TRUE; 54695f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D)); 54705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1)); 5471304d26faSStefano Zampini /* default */ 54725f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetType(pcbddc->ksp_D,KSPPREONLY)); 54735f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix)); 54745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)pcis->pA_II,MATSEQSBAIJ,&issbaij)); 54755f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->ksp_D,&pc_temp)); 54769577ea80SStefano Zampini if (issbaij) { 54775f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pc_temp,PCCHOLESKY)); 54789577ea80SStefano Zampini } else { 54795f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pc_temp,PCLU)); 54809577ea80SStefano Zampini } 54815f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetErrorIfNotConverged(pcbddc->ksp_D,pc->erroriffailure)); 548292cccca0SStefano Zampini } 54835f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOptionsPrefix(pcis->pA_II,((PetscObject)pcbddc->ksp_D)->prefix)); 54845f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->pA_II)); 5485304d26faSStefano Zampini /* Allow user's customization */ 548692cccca0SStefano Zampini if (opts) { 54875f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetFromOptions(pcbddc->ksp_D)); 548892cccca0SStefano Zampini } 54895f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNearNullSpace(pcis->pA_II,&nnsp)); 54906d9e27e4SStefano Zampini if (pcbddc->NullSpace_corr[0] && !nnsp) { /* approximate solver, propagate NearNullSpace */ 54915f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpacePropagateAny_Private(pcbddc->local_mat,pcis->is_I_local,pcis->pA_II)); 549292cccca0SStefano Zampini } 54935f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNearNullSpace(pcis->pA_II,&nnsp)); 54945f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->ksp_D,&pc_temp)); 54955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f)); 549692cccca0SStefano Zampini if (f && pcbddc->mat_graph->cloc && !nnsp) { 5497cd18cfedSStefano Zampini PetscReal *coords = pcbddc->mat_graph->coords,*scoords; 5498cd18cfedSStefano Zampini const PetscInt *idxs; 5499cd18cfedSStefano Zampini PetscInt cdim = pcbddc->mat_graph->cdim,nl,i,d; 5500cd18cfedSStefano Zampini 55015f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pcis->is_I_local,&nl)); 55025f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcis->is_I_local,&idxs)); 55035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nl*cdim,&scoords)); 5504cd18cfedSStefano Zampini for (i=0;i<nl;i++) { 5505cd18cfedSStefano Zampini for (d=0;d<cdim;d++) { 5506cd18cfedSStefano Zampini scoords[i*cdim+d] = coords[idxs[i]*cdim+d]; 5507cd18cfedSStefano Zampini } 5508cd18cfedSStefano Zampini } 55095f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcis->is_I_local,&idxs)); 55105f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetCoordinates(pc_temp,cdim,nl,scoords)); 55115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(scoords)); 5512cd18cfedSStefano Zampini } 5513b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 5514df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5515d62866d3SStefano Zampini 55165f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver)); 5517d5574798SStefano Zampini } 551892cccca0SStefano Zampini 5519304d26faSStefano Zampini /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */ 5520304d26faSStefano Zampini if (!n_D) { 55215f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->ksp_D,&pc_temp)); 55225f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pc_temp,PCNONE)); 5523304d26faSStefano Zampini } 55245f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetUp(pcbddc->ksp_D)); 5525304d26faSStefano Zampini /* set ksp_D into pcis data */ 55265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)pcbddc->ksp_D)); 55275f80ce2aSJacob Faibussowitsch CHKERRQ(KSPDestroy(&pcis->ksp_D)); 5528304d26faSStefano Zampini pcis->ksp_D = pcbddc->ksp_D; 5529684f6988SStefano Zampini } 5530304d26faSStefano Zampini 5531304d26faSStefano Zampini /* NEUMANN PROBLEM */ 55320a545947SLisandro Dalcin A_RR = NULL; 5533684f6988SStefano Zampini if (neumann) { 5534d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 553504708bb6SStefano Zampini PetscInt ibs,mbs; 55360aa714b2SStefano Zampini PetscBool issbaij, reuse_neumann_solver; 553704708bb6SStefano Zampini Mat_IS* matis = (Mat_IS*)pc->pmat->data; 55380aa714b2SStefano Zampini 55390aa714b2SStefano Zampini reuse_neumann_solver = PETSC_FALSE; 55400aa714b2SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 55410aa714b2SStefano Zampini IS iP; 55420aa714b2SStefano Zampini 55430aa714b2SStefano Zampini reuse_neumann_solver = PETSC_TRUE; 55445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject)sub_schurs->A,"__KSPFETIDP_iP",(PetscObject*)&iP)); 55450aa714b2SStefano Zampini if (iP) reuse_neumann_solver = PETSC_FALSE; 55460aa714b2SStefano Zampini } 5547f4ddd8eeSStefano Zampini /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */ 55485f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(pcbddc->is_R_local,&n_R)); 5549f4ddd8eeSStefano Zampini if (pcbddc->ksp_R) { /* already created ksp */ 5550f4ddd8eeSStefano Zampini PetscInt nn_R; 55515f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR)); 55525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)A_RR)); 55535f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(A_RR,&nn_R,NULL)); 5554f4ddd8eeSStefano Zampini if (nn_R != n_R) { /* old ksp is not reusable, so reset it */ 55555f80ce2aSJacob Faibussowitsch CHKERRQ(KSPReset(pcbddc->ksp_R)); 55565f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_RR)); 5557f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5558f4ddd8eeSStefano Zampini } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */ 5559727cdba6SStefano Zampini if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */ 55605f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_RR)); 5561f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5562f4ddd8eeSStefano Zampini } else { /* safe to reuse the matrix */ 5563f4ddd8eeSStefano Zampini reuse = MAT_REUSE_MATRIX; 5564f4ddd8eeSStefano Zampini } 5565f4ddd8eeSStefano Zampini } 5566f4ddd8eeSStefano Zampini /* last check */ 5567d1e9a80fSBarry Smith if (pc->flag == DIFFERENT_NONZERO_PATTERN) { 55685f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_RR)); 5569f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5570f4ddd8eeSStefano Zampini } 5571f4ddd8eeSStefano Zampini } else { /* first time, so we need to create the matrix */ 5572f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5573f4ddd8eeSStefano Zampini } 5574365a3a41SStefano Zampini /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection 5575365a3a41SStefano Zampini TODO: Get Rid of these conversions */ 55765f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetBlockSize(pcbddc->local_mat,&mbs)); 55775f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetBlockSize(pcbddc->is_R_local,&ibs)); 55785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij)); 557904708bb6SStefano Zampini if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */ 558004708bb6SStefano Zampini if (matis->A == pcbddc->local_mat) { 55815f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->local_mat)); 55825f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat)); 5583af732b37SStefano Zampini } else { 55845f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat)); 55856816873aSStefano Zampini } 558604708bb6SStefano Zampini } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */ 558704708bb6SStefano Zampini if (matis->A == pcbddc->local_mat) { 55885f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->local_mat)); 55895f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(matis->A,mbs > 1 ? MATSEQBAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat)); 559004708bb6SStefano Zampini } else { 55915f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(pcbddc->local_mat,mbs > 1 ? MATSEQBAIJ : MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat)); 559204708bb6SStefano Zampini } 559304708bb6SStefano Zampini } 5594a00504b5SStefano Zampini /* extract A_RR */ 55950aa714b2SStefano Zampini if (reuse_neumann_solver) { 5596a00504b5SStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5597a00504b5SStefano Zampini 5598a00504b5SStefano Zampini if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */ 55995f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_RR)); 5600a00504b5SStefano Zampini if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */ 56015f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR)); 560216e386b8SStefano Zampini } else { 56035f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR)); 5604a00504b5SStefano Zampini } 5605a00504b5SStefano Zampini } else { 56065f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_RR)); 56075f80ce2aSJacob Faibussowitsch CHKERRQ(PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL)); 56085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)A_RR)); 5609a00504b5SStefano Zampini } 5610a00504b5SStefano Zampini } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */ 56115f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR)); 561216e386b8SStefano Zampini } 56133301b35fSStefano Zampini if (pcbddc->local_mat->symmetric_set) { 56145f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric)); 56156816873aSStefano Zampini } 561692cccca0SStefano Zampini opts = PETSC_FALSE; 5617f4ddd8eeSStefano Zampini if (!pcbddc->ksp_R) { /* create object if not present */ 561892cccca0SStefano Zampini opts = PETSC_TRUE; 56195f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R)); 56205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1)); 5621304d26faSStefano Zampini /* default */ 56225f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetType(pcbddc->ksp_R,KSPPREONLY)); 56235f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix)); 56245f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->ksp_R,&pc_temp)); 56255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij)); 56269577ea80SStefano Zampini if (issbaij) { 56275f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pc_temp,PCCHOLESKY)); 56289577ea80SStefano Zampini } else { 56295f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pc_temp,PCLU)); 56309577ea80SStefano Zampini } 56315f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetErrorIfNotConverged(pcbddc->ksp_R,pc->erroriffailure)); 563292cccca0SStefano Zampini } 56335f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR)); 56345f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOptionsPrefix(A_RR,((PetscObject)pcbddc->ksp_R)->prefix)); 563592cccca0SStefano Zampini if (opts) { /* Allow user's customization once */ 56365f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetFromOptions(pcbddc->ksp_R)); 563792cccca0SStefano Zampini } 56385f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNearNullSpace(A_RR,&nnsp)); 56396d9e27e4SStefano Zampini if (pcbddc->NullSpace_corr[2] && !nnsp) { /* approximate solver, propagate NearNullSpace */ 56405f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpacePropagateAny_Private(pcbddc->local_mat,pcbddc->is_R_local,A_RR)); 564192cccca0SStefano Zampini } 56425f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNearNullSpace(A_RR,&nnsp)); 56435f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->ksp_R,&pc_temp)); 56445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQueryFunction((PetscObject)pc_temp,"PCSetCoordinates_C",&f)); 564592cccca0SStefano Zampini if (f && pcbddc->mat_graph->cloc && !nnsp) { 5646cd18cfedSStefano Zampini PetscReal *coords = pcbddc->mat_graph->coords,*scoords; 5647cd18cfedSStefano Zampini const PetscInt *idxs; 5648cd18cfedSStefano Zampini PetscInt cdim = pcbddc->mat_graph->cdim,nl,i,d; 5649cd18cfedSStefano Zampini 56505f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pcbddc->is_R_local,&nl)); 56515f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcbddc->is_R_local,&idxs)); 56525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nl*cdim,&scoords)); 5653cd18cfedSStefano Zampini for (i=0;i<nl;i++) { 5654cd18cfedSStefano Zampini for (d=0;d<cdim;d++) { 5655cd18cfedSStefano Zampini scoords[i*cdim+d] = coords[idxs[i]*cdim+d]; 5656cd18cfedSStefano Zampini } 5657cd18cfedSStefano Zampini } 56585f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcbddc->is_R_local,&idxs)); 56595f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetCoordinates(pc_temp,cdim,nl,scoords)); 56605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(scoords)); 5661cd18cfedSStefano Zampini } 566292cccca0SStefano Zampini 5663304d26faSStefano Zampini /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */ 5664304d26faSStefano Zampini if (!n_R) { 56655f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->ksp_R,&pc_temp)); 56665f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pc_temp,PCNONE)); 5667304d26faSStefano Zampini } 5668df4d28bfSStefano Zampini /* Reuse solver if it is present */ 56690aa714b2SStefano Zampini if (reuse_neumann_solver) { 5670df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5671d62866d3SStefano Zampini 56725f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver)); 5673d62866d3SStefano Zampini } 56745f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetUp(pcbddc->ksp_R)); 5675684f6988SStefano Zampini } 5676304d26faSStefano Zampini 5677684f6988SStefano Zampini if (pcbddc->dbg_flag) { 56785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 56795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 56805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n")); 5681684f6988SStefano Zampini } 56825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_BDDC_LocalSolvers[pcbddc->current_level],pc,0,0,0)); 5683c7017625SStefano Zampini 5684c7017625SStefano Zampini /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */ 5685c7017625SStefano Zampini if (pcbddc->NullSpace_corr[0]) { 56865f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE)); 5687c7017625SStefano Zampini } 5688c7017625SStefano Zampini if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) { 56895f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1])); 5690c7017625SStefano Zampini } 5691c7017625SStefano Zampini if (neumann && pcbddc->NullSpace_corr[2]) { 56925f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3])); 5693c7017625SStefano Zampini } 5694c7017625SStefano Zampini /* check Dirichlet and Neumann solvers */ 5695c7017625SStefano Zampini if (pcbddc->dbg_flag) { 5696684f6988SStefano Zampini if (dirichlet) { /* Dirichlet */ 56975f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetRandom(pcis->vec1_D,NULL)); 56985f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D)); 56995f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D)); 57005f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D)); 57015f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D)); 57025f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(pcis->vec1_D,NORM_INFINITY,&value)); 57035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d infinity error for Dirichlet solve (%s) = % 1.14e \n",PetscGlobalRank,((PetscObject)(pcbddc->ksp_D))->prefix,value)); 57045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 5705304d26faSStefano Zampini } 5706684f6988SStefano Zampini if (neumann) { /* Neumann */ 57075f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetRandom(pcbddc->vec1_R,NULL)); 57085f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R)); 57095f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R)); 57105f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec2_R)); 57115f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R)); 57125f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value)); 57135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d infinity error for Neumann solve (%s) = % 1.14e\n",PetscGlobalRank,((PetscObject)(pcbddc->ksp_R))->prefix,value)); 57145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 5715304d26faSStefano Zampini } 5716684f6988SStefano Zampini } 57175cbda25cSStefano Zampini /* free Neumann problem's matrix */ 57185f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A_RR)); 5719304d26faSStefano Zampini PetscFunctionReturn(0); 5720304d26faSStefano Zampini } 5721304d26faSStefano Zampini 572280677318SStefano Zampini static PetscErrorCode PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose) 5723674ae819SStefano Zampini { 5724674ae819SStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)(pc->data); 5725be83ff47SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 5726b334f244SStefano Zampini PetscBool reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE; 5727674ae819SStefano Zampini 5728674ae819SStefano Zampini PetscFunctionBegin; 5729b334f244SStefano Zampini if (!reuse_solver) { 57305f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcbddc->vec1_R,0.)); 573120c7b377SStefano Zampini } 573280677318SStefano Zampini if (!pcbddc->switch_static) { 573380677318SStefano Zampini if (applytranspose && pcbddc->local_auxmat1) { 57345f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C)); 57355f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B)); 573620c7b377SStefano Zampini } 5737b334f244SStefano Zampini if (!reuse_solver) { 57385f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE)); 57395f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE)); 574020c7b377SStefano Zampini } else { 5741df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5742be83ff47SStefano Zampini 57435f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD)); 57445f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD)); 574520c7b377SStefano Zampini } 5746be83ff47SStefano Zampini } else { 57475f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE)); 57485f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE)); 57495f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE)); 57505f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE)); 575180677318SStefano Zampini if (applytranspose && pcbddc->local_auxmat1) { 57525f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C)); 57535f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B)); 57545f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE)); 57555f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE)); 5756674ae819SStefano Zampini } 5757674ae819SStefano Zampini } 57585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][1],pc,0,0,0)); 5759b334f244SStefano Zampini if (!reuse_solver || pcbddc->switch_static) { 576080677318SStefano Zampini if (applytranspose) { 57615f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R)); 576280677318SStefano Zampini } else { 57635f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R)); 576480677318SStefano Zampini } 57655f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(pcbddc->ksp_R,pc,pcbddc->vec1_R)); 5766be83ff47SStefano Zampini } else { 5767df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5768be83ff47SStefano Zampini 5769be83ff47SStefano Zampini if (applytranspose) { 57705f80ce2aSJacob Faibussowitsch CHKERRQ(MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B)); 5771be83ff47SStefano Zampini } else { 57725f80ce2aSJacob Faibussowitsch CHKERRQ(MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B)); 5773be83ff47SStefano Zampini } 5774be83ff47SStefano Zampini } 57755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][1],pc,0,0,0)); 57765f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(inout_B,0.)); 577780677318SStefano Zampini if (!pcbddc->switch_static) { 5778b334f244SStefano Zampini if (!reuse_solver) { 57795f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD)); 57805f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD)); 5781be83ff47SStefano Zampini } else { 5782df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5783be83ff47SStefano Zampini 57845f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE)); 57855f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE)); 5786be83ff47SStefano Zampini } 578780677318SStefano Zampini if (!applytranspose && pcbddc->local_auxmat1) { 57885f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C)); 57895f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B)); 579080677318SStefano Zampini } 579180677318SStefano Zampini } else { 57925f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD)); 57935f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD)); 57945f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD)); 57955f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD)); 579680677318SStefano Zampini if (!applytranspose && pcbddc->local_auxmat1) { 57975f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C)); 57985f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R)); 579980677318SStefano Zampini } 58005f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD)); 58015f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD)); 58025f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD)); 58035f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD)); 5804674ae819SStefano Zampini } 5805674ae819SStefano Zampini PetscFunctionReturn(0); 5806674ae819SStefano Zampini } 5807674ae819SStefano Zampini 5808dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */ 5809dc359a40SStefano Zampini PetscErrorCode PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose) 5810674ae819SStefano Zampini { 5811674ae819SStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)(pc->data); 5812674ae819SStefano Zampini PC_IS* pcis = (PC_IS*) (pc->data); 5813674ae819SStefano Zampini const PetscScalar zero = 0.0; 5814674ae819SStefano Zampini 5815674ae819SStefano Zampini PetscFunctionBegin; 5816dc359a40SStefano Zampini /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */ 58174fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 5818dc359a40SStefano Zampini if (applytranspose) { 58195f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P)); 58205f80ce2aSJacob Faibussowitsch if (pcbddc->switch_static) CHKERRQ(MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P)); 5821dc359a40SStefano Zampini } else { 58225f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P)); 58235f80ce2aSJacob Faibussowitsch if (pcbddc->switch_static) CHKERRQ(MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P)); 582415aaf578SStefano Zampini } 58254fee134fSStefano Zampini } else { 58265f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcbddc->vec1_P,zero)); 58274fee134fSStefano Zampini } 5828efc2fbd9SStefano Zampini 5829efc2fbd9SStefano Zampini /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */ 58304f1b2e48SStefano Zampini if (pcbddc->benign_n) { 5831efc2fbd9SStefano Zampini PetscScalar *array; 58324f1b2e48SStefano Zampini PetscInt j; 5833efc2fbd9SStefano Zampini 58345f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(pcbddc->vec1_P,&array)); 58354f1b2e48SStefano Zampini for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j]; 58365f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(pcbddc->vec1_P,&array)); 5837efc2fbd9SStefano Zampini } 5838efc2fbd9SStefano Zampini 583912edc857SStefano Zampini /* start communications from local primal nodes to rhs of coarse solver */ 58405f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcbddc->coarse_vec,zero)); 58415f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD)); 58425f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD)); 584312edc857SStefano Zampini 58449f00e9b4SStefano Zampini /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */ 584512edc857SStefano Zampini if (pcbddc->coarse_ksp) { 584651694757SStefano Zampini Mat coarse_mat; 5847964fefecSStefano Zampini Vec rhs,sol; 584851694757SStefano Zampini MatNullSpace nullsp; 584927b6a85dSStefano Zampini PetscBool isbddc = PETSC_FALSE; 5850964fefecSStefano Zampini 585127b6a85dSStefano Zampini if (pcbddc->benign_have_null) { 585227b6a85dSStefano Zampini PC coarse_pc; 585327b6a85dSStefano Zampini 58545f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->coarse_ksp,&coarse_pc)); 58555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc)); 585627b6a85dSStefano Zampini /* we need to propagate to coarser levels the need for a possible benign correction */ 585727b6a85dSStefano Zampini if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) { 585827b6a85dSStefano Zampini PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data); 585927b6a85dSStefano Zampini coarsepcbddc->benign_skip_correction = PETSC_FALSE; 58603bca92a6SStefano Zampini coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE; 586127b6a85dSStefano Zampini } 586227b6a85dSStefano Zampini } 58635f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetRhs(pcbddc->coarse_ksp,&rhs)); 58645f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetSolution(pcbddc->coarse_ksp,&sol)); 58655f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL)); 586612edc857SStefano Zampini if (applytranspose) { 5867*28b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->benign_apply_coarse_only,PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented"); 58685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0)); 58695f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol)); 58705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0)); 58715f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(pcbddc->coarse_ksp,pc,sol)); 58725f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetTransposeNullSpace(coarse_mat,&nullsp)); 58739bfcb8eaSStefano Zampini if (nullsp) { 58745f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceRemove(nullsp,sol)); 58759bfcb8eaSStefano Zampini } 58762701bc32SStefano Zampini } else { 58775f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNullSpace(coarse_mat,&nullsp)); 58781f4df5f7SStefano Zampini if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */ 58792701bc32SStefano Zampini PC coarse_pc; 58802701bc32SStefano Zampini 58819bfcb8eaSStefano Zampini if (nullsp) { 58825f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceRemove(nullsp,rhs)); 58839bfcb8eaSStefano Zampini } 58845f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->coarse_ksp,&coarse_pc)); 58855f80ce2aSJacob Faibussowitsch CHKERRQ(PCPreSolve(coarse_pc,pcbddc->coarse_ksp)); 58865f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol)); 58875f80ce2aSJacob Faibussowitsch CHKERRQ(PCPostSolve(coarse_pc,pcbddc->coarse_ksp)); 588812edc857SStefano Zampini } else { 58895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0)); 58905f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(pcbddc->coarse_ksp,rhs,sol)); 58915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2],pc,0,0,0)); 58925f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(pcbddc->coarse_ksp,pc,sol)); 58939bfcb8eaSStefano Zampini if (nullsp) { 58945f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceRemove(nullsp,sol)); 58959bfcb8eaSStefano Zampini } 589612edc857SStefano Zampini } 58972701bc32SStefano Zampini } 58981d82a3b6SStefano Zampini /* we don't need the benign correction at coarser levels anymore */ 589927b6a85dSStefano Zampini if (pcbddc->benign_have_null && isbddc) { 590027b6a85dSStefano Zampini PC coarse_pc; 590127b6a85dSStefano Zampini PC_BDDC* coarsepcbddc; 590227b6a85dSStefano Zampini 59035f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->coarse_ksp,&coarse_pc)); 590427b6a85dSStefano Zampini coarsepcbddc = (PC_BDDC*)(coarse_pc->data); 590527b6a85dSStefano Zampini coarsepcbddc->benign_skip_correction = PETSC_TRUE; 59063bca92a6SStefano Zampini coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE; 590727b6a85dSStefano Zampini } 590812edc857SStefano Zampini } 5909674ae819SStefano Zampini 5910674ae819SStefano Zampini /* Local solution on R nodes */ 59114fee134fSStefano Zampini if (pcis->n && !pcbddc->benign_apply_coarse_only) { 59125f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose)); 59139f00e9b4SStefano Zampini } 59149f00e9b4SStefano Zampini /* communications from coarse sol to local primal nodes */ 59155f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE)); 59165f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE)); 5917674ae819SStefano Zampini 59184fee134fSStefano Zampini /* Sum contributions from the two levels */ 59194fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 5920dc359a40SStefano Zampini if (applytranspose) { 59215f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B)); 59225f80ce2aSJacob Faibussowitsch if (pcbddc->switch_static) CHKERRQ(MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D)); 5923dc359a40SStefano Zampini } else { 59245f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B)); 59255f80ce2aSJacob Faibussowitsch if (pcbddc->switch_static) CHKERRQ(MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D)); 5926dc359a40SStefano Zampini } 5927efc2fbd9SStefano Zampini /* store p0 */ 59284f1b2e48SStefano Zampini if (pcbddc->benign_n) { 5929efc2fbd9SStefano Zampini PetscScalar *array; 59304f1b2e48SStefano Zampini PetscInt j; 5931efc2fbd9SStefano Zampini 59325f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(pcbddc->vec1_P,&array)); 59334f1b2e48SStefano Zampini for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j]; 59345f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(pcbddc->vec1_P,&array)); 5935efc2fbd9SStefano Zampini } 59364fee134fSStefano Zampini } else { /* expand the coarse solution */ 59374fee134fSStefano Zampini if (applytranspose) { 59385f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B)); 59394fee134fSStefano Zampini } else { 59405f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B)); 59414fee134fSStefano Zampini } 59424fee134fSStefano Zampini } 5943674ae819SStefano Zampini PetscFunctionReturn(0); 5944674ae819SStefano Zampini } 5945674ae819SStefano Zampini 594612edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode) 5947674ae819SStefano Zampini { 5948674ae819SStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)(pc->data); 594912edc857SStefano Zampini Vec from,to; 59507ebab0bbSStefano Zampini const PetscScalar *array; 5951674ae819SStefano Zampini 5952674ae819SStefano Zampini PetscFunctionBegin; 595312edc857SStefano Zampini if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */ 595412edc857SStefano Zampini from = pcbddc->coarse_vec; 595512edc857SStefano Zampini to = pcbddc->vec1_P; 595612edc857SStefano Zampini if (pcbddc->coarse_ksp) { /* get array from coarse processes */ 595712edc857SStefano Zampini Vec tvec; 595858da7f69SStefano Zampini 59595f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetRhs(pcbddc->coarse_ksp,&tvec)); 59605f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(tvec)); 59615f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetSolution(pcbddc->coarse_ksp,&tvec)); 59625f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(tvec,&array)); 59635f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(from,array)); 59645f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(tvec,&array)); 596512edc857SStefano Zampini } 596612edc857SStefano Zampini } else { /* from local to global -> put data in coarse right hand side */ 596712edc857SStefano Zampini from = pcbddc->vec1_P; 596812edc857SStefano Zampini to = pcbddc->coarse_vec; 596912edc857SStefano Zampini } 59705f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode)); 5971674ae819SStefano Zampini PetscFunctionReturn(0); 5972674ae819SStefano Zampini } 5973674ae819SStefano Zampini 597412edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode) 5975674ae819SStefano Zampini { 5976674ae819SStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)(pc->data); 597712edc857SStefano Zampini Vec from,to; 59787ebab0bbSStefano Zampini const PetscScalar *array; 5979674ae819SStefano Zampini 5980674ae819SStefano Zampini PetscFunctionBegin; 598112edc857SStefano Zampini if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */ 598212edc857SStefano Zampini from = pcbddc->coarse_vec; 598312edc857SStefano Zampini to = pcbddc->vec1_P; 598412edc857SStefano Zampini } else { /* from local to global -> put data in coarse right hand side */ 598512edc857SStefano Zampini from = pcbddc->vec1_P; 598612edc857SStefano Zampini to = pcbddc->coarse_vec; 598712edc857SStefano Zampini } 59885f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode)); 598912edc857SStefano Zampini if (smode == SCATTER_FORWARD) { 599012edc857SStefano Zampini if (pcbddc->coarse_ksp) { /* get array from coarse processes */ 599112edc857SStefano Zampini Vec tvec; 599258da7f69SStefano Zampini 59935f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetRhs(pcbddc->coarse_ksp,&tvec)); 59945f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(to,&array)); 59955f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(tvec,array)); 59965f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(to,&array)); 599758da7f69SStefano Zampini } 599858da7f69SStefano Zampini } else { 599958da7f69SStefano Zampini if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */ 60005f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(from)); 600112edc857SStefano Zampini } 600212edc857SStefano Zampini } 6003674ae819SStefano Zampini PetscFunctionReturn(0); 6004674ae819SStefano Zampini } 6005674ae819SStefano Zampini 6006674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc) 6007674ae819SStefano Zampini { 6008674ae819SStefano Zampini PetscErrorCode ierr; 6009674ae819SStefano Zampini PC_IS* pcis = (PC_IS*)(pc->data); 6010674ae819SStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 6011674ae819SStefano Zampini Mat_IS* matis = (Mat_IS*)pc->pmat->data; 6012984c4197SStefano Zampini /* one and zero */ 6013984c4197SStefano Zampini PetscScalar one=1.0,zero=0.0; 6014984c4197SStefano Zampini /* space to store constraints and their local indices */ 60159162d606SStefano Zampini PetscScalar *constraints_data; 60169162d606SStefano Zampini PetscInt *constraints_idxs,*constraints_idxs_B; 60179162d606SStefano Zampini PetscInt *constraints_idxs_ptr,*constraints_data_ptr; 60189162d606SStefano Zampini PetscInt *constraints_n; 6019984c4197SStefano Zampini /* iterators */ 6020b3d85658SStefano Zampini PetscInt i,j,k,total_counts,total_counts_cc,cum; 6021984c4197SStefano Zampini /* BLAS integers */ 6022e310c8b4SStefano Zampini PetscBLASInt lwork,lierr; 6023e310c8b4SStefano Zampini PetscBLASInt Blas_N,Blas_M,Blas_K,Blas_one=1; 6024c4303822SStefano Zampini PetscBLASInt Blas_LDA,Blas_LDB,Blas_LDC; 6025727cdba6SStefano Zampini /* reuse */ 60260e6343abSStefano Zampini PetscInt olocal_primal_size,olocal_primal_size_cc; 60270e6343abSStefano Zampini PetscInt *olocal_primal_ref_node,*olocal_primal_ref_mult; 6028984c4197SStefano Zampini /* change of basis */ 6029b3d85658SStefano Zampini PetscBool qr_needed; 60309162d606SStefano Zampini PetscBT change_basis,qr_needed_idx; 6031984c4197SStefano Zampini /* auxiliary stuff */ 603264efe560SStefano Zampini PetscInt *nnz,*is_indices; 60338a0068c3SStefano Zampini PetscInt ncc; 6034984c4197SStefano Zampini /* some quantities */ 603545a1bb75SStefano Zampini PetscInt n_vertices,total_primal_vertices,valid_constraints; 6036a58a30b4SStefano Zampini PetscInt size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints; 603757715f18SStefano Zampini PetscReal tol; /* tolerance for retaining eigenmodes */ 6038984c4197SStefano Zampini 6039674ae819SStefano Zampini PetscFunctionBegin; 604057715f18SStefano Zampini tol = PetscSqrtReal(PETSC_SMALL); 60418e61c736SStefano Zampini /* Destroy Mat objects computed previously */ 60425f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->ChangeOfBasisMatrix)); 60435f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->ConstraintMatrix)); 60445f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->switch_static_change)); 6045088faed8SStefano Zampini /* save info on constraints from previous setup (if any) */ 6046088faed8SStefano Zampini olocal_primal_size = pcbddc->local_primal_size; 60470e6343abSStefano Zampini olocal_primal_size_cc = pcbddc->local_primal_size_cc; 60485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult)); 60495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc)); 60505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc)); 60515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult)); 60525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddc->primal_indices_local_idxs)); 6053cf5a6209SStefano Zampini 6054cf5a6209SStefano Zampini if (!pcbddc->adaptive_selection) { 60559162d606SStefano Zampini IS ISForVertices,*ISForFaces,*ISForEdges; 6056cf5a6209SStefano Zampini MatNullSpace nearnullsp; 6057cf5a6209SStefano Zampini const Vec *nearnullvecs; 6058cf5a6209SStefano Zampini Vec *localnearnullsp; 6059cf5a6209SStefano Zampini PetscScalar *array; 6060cf5a6209SStefano Zampini PetscInt n_ISForFaces,n_ISForEdges,nnsp_size; 6061cf5a6209SStefano Zampini PetscBool nnsp_has_cnst; 6062674ae819SStefano Zampini /* LAPACK working arrays for SVD or POD */ 6063b3d85658SStefano Zampini PetscBool skip_lapack,boolforchange; 6064674ae819SStefano Zampini PetscScalar *work; 6065674ae819SStefano Zampini PetscReal *singular_vals; 6066674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 6067674ae819SStefano Zampini PetscReal *rwork; 6068674ae819SStefano Zampini #endif 606955080a34SStefano Zampini PetscScalar *temp_basis = NULL,*correlation_mat = NULL; 6070964fefecSStefano Zampini PetscBLASInt dummy_int=1; 6071964fefecSStefano Zampini PetscScalar dummy_scalar=1.; 607255080a34SStefano Zampini PetscBool use_pod = PETSC_FALSE; 6073674ae819SStefano Zampini 607455080a34SStefano Zampini /* MKL SVD with same input gives different results on different processes! */ 6075b88df2e7SBarry Smith #if defined(PETSC_MISSING_LAPACK_GESVD) || defined(PETSC_HAVE_MKL_LIBS) 607655080a34SStefano Zampini use_pod = PETSC_TRUE; 607755080a34SStefano Zampini #endif 6078674ae819SStefano Zampini /* Get index sets for faces, edges and vertices from graph */ 60795f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices)); 6080e4d548c7SStefano Zampini /* print some info */ 60815c643e28SStefano Zampini if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) { 6082e4d548c7SStefano Zampini PetscInt nv; 6083e4d548c7SStefano Zampini 60845f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer)); 60855f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(ISForVertices,&nv)); 60865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 60875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n")); 60885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%D)\n",PetscGlobalRank,nv,pcbddc->use_vertices)); 60895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges (%D)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges)); 60905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces (%D)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces)); 60915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 60925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 6093e4d548c7SStefano Zampini } 6094e4d548c7SStefano Zampini 6095d06fc5fdSStefano Zampini /* free unneeded index sets */ 6096d06fc5fdSStefano Zampini if (!pcbddc->use_vertices) { 60975f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&ISForVertices)); 6098674ae819SStefano Zampini } 6099d06fc5fdSStefano Zampini if (!pcbddc->use_edges) { 6100d06fc5fdSStefano Zampini for (i=0;i<n_ISForEdges;i++) { 61015f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&ISForEdges[i])); 6102d06fc5fdSStefano Zampini } 61035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ISForEdges)); 6104d06fc5fdSStefano Zampini n_ISForEdges = 0; 6105d06fc5fdSStefano Zampini } 6106d06fc5fdSStefano Zampini if (!pcbddc->use_faces) { 6107d06fc5fdSStefano Zampini for (i=0;i<n_ISForFaces;i++) { 61085f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&ISForFaces[i])); 6109d06fc5fdSStefano Zampini } 61105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ISForFaces)); 6111d06fc5fdSStefano Zampini n_ISForFaces = 0; 6112d06fc5fdSStefano Zampini } 611370022509SStefano Zampini 6114674ae819SStefano Zampini /* check if near null space is attached to global mat */ 61156d9e27e4SStefano Zampini if (pcbddc->use_nnsp) { 61165f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNearNullSpace(pc->pmat,&nearnullsp)); 61176d9e27e4SStefano Zampini } else nearnullsp = NULL; 61186d9e27e4SStefano Zampini 6119674ae819SStefano Zampini if (nearnullsp) { 61205f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs)); 6121f4ddd8eeSStefano Zampini /* remove any stored info */ 61225f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceDestroy(&pcbddc->onearnullspace)); 61235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddc->onearnullvecs_state)); 6124f4ddd8eeSStefano Zampini /* store information for BDDC solver reuse */ 61255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)nearnullsp)); 6126f4ddd8eeSStefano Zampini pcbddc->onearnullspace = nearnullsp; 61275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state)); 6128f4ddd8eeSStefano Zampini for (i=0;i<nnsp_size;i++) { 61295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i])); 6130f4ddd8eeSStefano Zampini } 6131984c4197SStefano Zampini } else { /* if near null space is not provided BDDC uses constants by default */ 6132984c4197SStefano Zampini nnsp_size = 0; 6133674ae819SStefano Zampini nnsp_has_cnst = PETSC_TRUE; 6134674ae819SStefano Zampini } 6135984c4197SStefano Zampini /* get max number of constraints on a single cc */ 6136984c4197SStefano Zampini max_constraints = nnsp_size; 6137984c4197SStefano Zampini if (nnsp_has_cnst) max_constraints++; 6138984c4197SStefano Zampini 6139674ae819SStefano Zampini /* 6140674ae819SStefano Zampini Evaluate maximum storage size needed by the procedure 61419162d606SStefano Zampini - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]" 61429162d606SStefano Zampini - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]" 61439162d606SStefano Zampini There can be multiple constraints per connected component 6144674ae819SStefano Zampini */ 6145674ae819SStefano Zampini n_vertices = 0; 6146674ae819SStefano Zampini if (ISForVertices) { 61475f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(ISForVertices,&n_vertices)); 6148674ae819SStefano Zampini } 61499162d606SStefano Zampini ncc = n_vertices+n_ISForFaces+n_ISForEdges; 61505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n)); 61519162d606SStefano Zampini 61529162d606SStefano Zampini total_counts = n_ISForFaces+n_ISForEdges; 61539162d606SStefano Zampini total_counts *= max_constraints; 6154674ae819SStefano Zampini total_counts += n_vertices; 61555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(total_counts,&change_basis)); 61569162d606SStefano Zampini 6157674ae819SStefano Zampini total_counts = 0; 6158674ae819SStefano Zampini max_size_of_constraint = 0; 6159674ae819SStefano Zampini for (i=0;i<n_ISForEdges+n_ISForFaces;i++) { 61609162d606SStefano Zampini IS used_is; 6161674ae819SStefano Zampini if (i<n_ISForEdges) { 61629162d606SStefano Zampini used_is = ISForEdges[i]; 6163674ae819SStefano Zampini } else { 61649162d606SStefano Zampini used_is = ISForFaces[i-n_ISForEdges]; 6165674ae819SStefano Zampini } 61665f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(used_is,&j)); 6167674ae819SStefano Zampini total_counts += j; 6168674ae819SStefano Zampini max_size_of_constraint = PetscMax(j,max_size_of_constraint); 6169674ae819SStefano Zampini } 61705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(total_counts*max_constraints+n_vertices,&constraints_data,total_counts+n_vertices,&constraints_idxs,total_counts+n_vertices,&constraints_idxs_B)); 61719162d606SStefano Zampini 6172984c4197SStefano Zampini /* get local part of global near null space vectors */ 61735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nnsp_size,&localnearnullsp)); 6174984c4197SStefano Zampini for (k=0;k<nnsp_size;k++) { 61755f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(pcis->vec1_N,&localnearnullsp[k])); 61765f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD)); 61775f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD)); 6178984c4197SStefano Zampini } 6179674ae819SStefano Zampini 6180242a89d7SStefano Zampini /* whether or not to skip lapack calls */ 6181242a89d7SStefano Zampini skip_lapack = PETSC_TRUE; 6182a773dcb8SStefano Zampini if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE; 6183242a89d7SStefano Zampini 6184984c4197SStefano Zampini /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */ 6185a773dcb8SStefano Zampini if (!skip_lapack) { 6186674ae819SStefano Zampini PetscScalar temp_work; 6187911cabfeSStefano Zampini 618855080a34SStefano Zampini if (use_pod) { 6189984c4197SStefano Zampini /* Proper Orthogonal Decomposition (POD) using the snapshot method */ 61905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(max_constraints*max_constraints,&correlation_mat)); 61915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(max_constraints,&singular_vals)); 61925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis)); 6193674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 61945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(3*max_constraints,&rwork)); 6195674ae819SStefano Zampini #endif 6196674ae819SStefano Zampini /* now we evaluate the optimal workspace using query with lwork=-1 */ 61975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(max_constraints,&Blas_N)); 61985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(max_constraints,&Blas_LDA)); 6199674ae819SStefano Zampini lwork = -1; 62005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6201674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6202c8244a33SStefano Zampini PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr)); 6203674ae819SStefano Zampini #else 6204c8244a33SStefano Zampini PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr)); 6205674ae819SStefano Zampini #endif 62065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 6207*28b400f6SJacob Faibussowitsch PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr); 620855080a34SStefano Zampini } else { 620955080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD) 6210674ae819SStefano Zampini /* SVD */ 6211674ae819SStefano Zampini PetscInt max_n,min_n; 6212674ae819SStefano Zampini max_n = max_size_of_constraint; 6213984c4197SStefano Zampini min_n = max_constraints; 6214984c4197SStefano Zampini if (max_size_of_constraint < max_constraints) { 6215674ae819SStefano Zampini min_n = max_size_of_constraint; 6216984c4197SStefano Zampini max_n = max_constraints; 6217674ae819SStefano Zampini } 62185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(min_n,&singular_vals)); 6219674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 62205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(5*min_n,&rwork)); 6221674ae819SStefano Zampini #endif 6222674ae819SStefano Zampini /* now we evaluate the optimal workspace using query with lwork=-1 */ 6223674ae819SStefano Zampini lwork = -1; 62245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(max_n,&Blas_M)); 62255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(min_n,&Blas_N)); 62265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(max_n,&Blas_LDA)); 62275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6228674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 62299162d606SStefano Zampini PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&constraints_data[0],&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,&lierr)); 6230674ae819SStefano Zampini #else 62319162d606SStefano Zampini PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&constraints_data[0],&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,rwork,&lierr)); 6232674ae819SStefano Zampini #endif 62335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 6234*28b400f6SJacob Faibussowitsch PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr); 623555080a34SStefano Zampini #else 623655080a34SStefano Zampini SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"This should not happen"); 6237984c4197SStefano Zampini #endif /* on missing GESVD */ 623855080a34SStefano Zampini } 6239674ae819SStefano Zampini /* Allocate optimal workspace */ 62405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork)); 62415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(lwork,&work)); 6242674ae819SStefano Zampini } 6243674ae819SStefano Zampini /* Now we can loop on constraining sets */ 6244674ae819SStefano Zampini total_counts = 0; 62459162d606SStefano Zampini constraints_idxs_ptr[0] = 0; 62469162d606SStefano Zampini constraints_data_ptr[0] = 0; 6247674ae819SStefano Zampini /* vertices */ 62489162d606SStefano Zampini if (n_vertices) { 62495f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(ISForVertices,(const PetscInt**)&is_indices)); 62505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(constraints_idxs,is_indices,n_vertices)); 6251674ae819SStefano Zampini for (i=0;i<n_vertices;i++) { 62529162d606SStefano Zampini constraints_n[total_counts] = 1; 62539162d606SStefano Zampini constraints_data[total_counts] = 1.0; 62549162d606SStefano Zampini constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1; 62559162d606SStefano Zampini constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1; 6256674ae819SStefano Zampini total_counts++; 6257674ae819SStefano Zampini } 62585f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices)); 6259674ae819SStefano Zampini n_vertices = total_counts; 6260674ae819SStefano Zampini } 6261984c4197SStefano Zampini 6262674ae819SStefano Zampini /* edges and faces */ 62639162d606SStefano Zampini total_counts_cc = total_counts; 6264911cabfeSStefano Zampini for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) { 62659162d606SStefano Zampini IS used_is; 62669162d606SStefano Zampini PetscBool idxs_copied = PETSC_FALSE; 62679162d606SStefano Zampini 6268911cabfeSStefano Zampini if (ncc<n_ISForEdges) { 62699162d606SStefano Zampini used_is = ISForEdges[ncc]; 6270984c4197SStefano Zampini boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */ 6271674ae819SStefano Zampini } else { 62729162d606SStefano Zampini used_is = ISForFaces[ncc-n_ISForEdges]; 6273984c4197SStefano Zampini boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */ 6274674ae819SStefano Zampini } 6275674ae819SStefano Zampini temp_constraints = 0; /* zero the number of constraints I have on this conn comp */ 62769162d606SStefano Zampini 62775f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(used_is,&size_of_constraint)); 62785f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(used_is,(const PetscInt**)&is_indices)); 6279984c4197SStefano Zampini /* change of basis should not be performed on local periodic nodes */ 6280984c4197SStefano Zampini if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE; 6281674ae819SStefano Zampini if (nnsp_has_cnst) { 62825b08dc53SStefano Zampini PetscScalar quad_value; 62839162d606SStefano Zampini 62845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint)); 62859162d606SStefano Zampini idxs_copied = PETSC_TRUE; 62869162d606SStefano Zampini 6287a773dcb8SStefano Zampini if (!pcbddc->use_nnsp_true) { 6288674ae819SStefano Zampini quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint)); 6289a773dcb8SStefano Zampini } else { 6290a773dcb8SStefano Zampini quad_value = 1.0; 6291a773dcb8SStefano Zampini } 6292674ae819SStefano Zampini for (j=0;j<size_of_constraint;j++) { 62939162d606SStefano Zampini constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value; 6294674ae819SStefano Zampini } 62959162d606SStefano Zampini temp_constraints++; 6296674ae819SStefano Zampini total_counts++; 6297674ae819SStefano Zampini } 6298674ae819SStefano Zampini for (k=0;k<nnsp_size;k++) { 6299984c4197SStefano Zampini PetscReal real_value; 63009162d606SStefano Zampini PetscScalar *ptr_to_data; 63019162d606SStefano Zampini 63025f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array)); 63039162d606SStefano Zampini ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint]; 6304674ae819SStefano Zampini for (j=0;j<size_of_constraint;j++) { 63059162d606SStefano Zampini ptr_to_data[j] = array[is_indices[j]]; 6306674ae819SStefano Zampini } 63075f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array)); 6308984c4197SStefano Zampini /* check if array is null on the connected component */ 63095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_N)); 63109162d606SStefano Zampini PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one)); 631157715f18SStefano Zampini if (real_value > tol*size_of_constraint) { /* keep indices and values */ 6312674ae819SStefano Zampini temp_constraints++; 6313674ae819SStefano Zampini total_counts++; 63149162d606SStefano Zampini if (!idxs_copied) { 63155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint)); 63169162d606SStefano Zampini idxs_copied = PETSC_TRUE; 6317674ae819SStefano Zampini } 6318674ae819SStefano Zampini } 63199162d606SStefano Zampini } 63205f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(used_is,(const PetscInt**)&is_indices)); 632145a1bb75SStefano Zampini valid_constraints = temp_constraints; 6322eb97c9d2SStefano Zampini if (!pcbddc->use_nnsp_true && temp_constraints) { 6323a773dcb8SStefano Zampini if (temp_constraints == 1) { /* just normalize the constraint */ 63249162d606SStefano Zampini PetscScalar norm,*ptr_to_data; 63259162d606SStefano Zampini 63269162d606SStefano Zampini ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]]; 63275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_N)); 63289162d606SStefano Zampini PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one)); 6329a773dcb8SStefano Zampini norm = 1.0/PetscSqrtReal(PetscRealPart(norm)); 63309162d606SStefano Zampini PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one)); 6331a773dcb8SStefano Zampini } else { /* perform SVD */ 63329162d606SStefano Zampini PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]]; 6333674ae819SStefano Zampini 633455080a34SStefano Zampini if (use_pod) { 6335984c4197SStefano Zampini /* SVD: Y = U*S*V^H -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag 6336984c4197SStefano Zampini POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2) 6337984c4197SStefano Zampini -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined 6338984c4197SStefano Zampini the constraints basis will differ (by a complex factor with absolute value equal to 1) 6339984c4197SStefano Zampini from that computed using LAPACKgesvd 6340984c4197SStefano Zampini -> This is due to a different computation of eigenvectors in LAPACKheev 6341984c4197SStefano Zampini -> The quality of the POD-computed basis will be the same */ 63425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(correlation_mat,temp_constraints*temp_constraints)); 6343674ae819SStefano Zampini /* Store upper triangular part of correlation matrix */ 63445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_N)); 63455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6346674ae819SStefano Zampini for (j=0;j<temp_constraints;j++) { 6347674ae819SStefano Zampini for (k=0;k<j+1;k++) { 63489162d606SStefano Zampini PetscStackCallBLAS("BLASdot",correlation_mat[j*temp_constraints+k] = BLASdot_(&Blas_N,ptr_to_data+k*size_of_constraint,&Blas_one,ptr_to_data+j*size_of_constraint,&Blas_one)); 6349674ae819SStefano Zampini } 6350674ae819SStefano Zampini } 6351e310c8b4SStefano Zampini /* compute eigenvalues and eigenvectors of correlation matrix */ 63525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(temp_constraints,&Blas_N)); 63535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(temp_constraints,&Blas_LDA)); 6354674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6355c8244a33SStefano Zampini PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr)); 6356674ae819SStefano Zampini #else 6357c8244a33SStefano Zampini PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr)); 6358674ae819SStefano Zampini #endif 63595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 6360*28b400f6SJacob Faibussowitsch PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr); 6361984c4197SStefano Zampini /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */ 6362674ae819SStefano Zampini j = 0; 636387b3baaaSStefano Zampini while (j < temp_constraints && singular_vals[j]/singular_vals[temp_constraints-1] < tol) j++; 6364674ae819SStefano Zampini total_counts = total_counts-j; 636545a1bb75SStefano Zampini valid_constraints = temp_constraints-j; 6366e310c8b4SStefano Zampini /* scale and copy POD basis into used quadrature memory */ 63675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_M)); 63685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(temp_constraints,&Blas_N)); 63695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(temp_constraints,&Blas_K)); 63705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_LDA)); 63715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(temp_constraints,&Blas_LDB)); 63725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_LDC)); 6373674ae819SStefano Zampini if (j<temp_constraints) { 6374984c4197SStefano Zampini PetscInt ii; 6375984c4197SStefano Zampini for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]); 63765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 63779162d606SStefano Zampini PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&Blas_M,&Blas_N,&Blas_K,&one,ptr_to_data,&Blas_LDA,correlation_mat,&Blas_LDB,&zero,temp_basis,&Blas_LDC)); 63785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 6379984c4197SStefano Zampini for (k=0;k<temp_constraints-j;k++) { 6380674ae819SStefano Zampini for (ii=0;ii<size_of_constraint;ii++) { 63819162d606SStefano Zampini ptr_to_data[k*size_of_constraint+ii] = singular_vals[temp_constraints-1-k]*temp_basis[(temp_constraints-1-k)*size_of_constraint+ii]; 6382674ae819SStefano Zampini } 6383674ae819SStefano Zampini } 6384674ae819SStefano Zampini } 638555080a34SStefano Zampini } else { 638655080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD) 63875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_M)); 63885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(temp_constraints,&Blas_N)); 63895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_LDA)); 63905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6391674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 63929162d606SStefano Zampini PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,ptr_to_data,&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,&lierr)); 6393674ae819SStefano Zampini #else 63949162d606SStefano Zampini PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,ptr_to_data,&Blas_LDA,singular_vals,&dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,rwork,&lierr)); 6395674ae819SStefano Zampini #endif 6396*28b400f6SJacob Faibussowitsch PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr); 63975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 6398984c4197SStefano Zampini /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */ 6399e310c8b4SStefano Zampini k = temp_constraints; 6400e310c8b4SStefano Zampini if (k > size_of_constraint) k = size_of_constraint; 6401674ae819SStefano Zampini j = 0; 640287b3baaaSStefano Zampini while (j < k && singular_vals[k-j-1]/singular_vals[0] < tol) j++; 640345a1bb75SStefano Zampini valid_constraints = k-j; 6404911cabfeSStefano Zampini total_counts = total_counts-temp_constraints+valid_constraints; 640555080a34SStefano Zampini #else 640655080a34SStefano Zampini SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"This should not happen"); 6407984c4197SStefano Zampini #endif /* on missing GESVD */ 6408674ae819SStefano Zampini } 6409a773dcb8SStefano Zampini } 641055080a34SStefano Zampini } 64119162d606SStefano Zampini /* update pointers information */ 64129162d606SStefano Zampini if (valid_constraints) { 64139162d606SStefano Zampini constraints_n[total_counts_cc] = valid_constraints; 64149162d606SStefano Zampini constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint; 64159162d606SStefano Zampini constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints; 64169162d606SStefano Zampini /* set change_of_basis flag */ 641745a1bb75SStefano Zampini if (boolforchange) { 6418b3d85658SStefano Zampini PetscBTSet(change_basis,total_counts_cc); 64199162d606SStefano Zampini } 6420b3d85658SStefano Zampini total_counts_cc++; 642145a1bb75SStefano Zampini } 642245a1bb75SStefano Zampini } 6423984c4197SStefano Zampini /* free workspace */ 64248f1c130eSStefano Zampini if (!skip_lapack) { 64255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(work)); 6426984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX) 64275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(rwork)); 6428984c4197SStefano Zampini #endif 64295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(singular_vals)); 64305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(correlation_mat)); 64315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(temp_basis)); 6432984c4197SStefano Zampini } 6433984c4197SStefano Zampini for (k=0;k<nnsp_size;k++) { 64345f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&localnearnullsp[k])); 6435984c4197SStefano Zampini } 64365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(localnearnullsp)); 6437cf5a6209SStefano Zampini /* free index sets of faces, edges and vertices */ 6438cf5a6209SStefano Zampini for (i=0;i<n_ISForFaces;i++) { 64395f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&ISForFaces[i])); 6440cf5a6209SStefano Zampini } 6441cf5a6209SStefano Zampini if (n_ISForFaces) { 64425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ISForFaces)); 6443cf5a6209SStefano Zampini } 6444cf5a6209SStefano Zampini for (i=0;i<n_ISForEdges;i++) { 64455f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&ISForEdges[i])); 6446cf5a6209SStefano Zampini } 6447cf5a6209SStefano Zampini if (n_ISForEdges) { 64485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ISForEdges)); 6449cf5a6209SStefano Zampini } 64505f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&ISForVertices)); 645108122e43SStefano Zampini } else { 645208122e43SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 6453984c4197SStefano Zampini 645408122e43SStefano Zampini total_counts = 0; 645508122e43SStefano Zampini n_vertices = 0; 6456d62866d3SStefano Zampini if (sub_schurs->is_vertices && pcbddc->use_vertices) { 64575f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(sub_schurs->is_vertices,&n_vertices)); 645808122e43SStefano Zampini } 645908122e43SStefano Zampini max_constraints = 0; 64609162d606SStefano Zampini total_counts_cc = 0; 646108122e43SStefano Zampini for (i=0;i<sub_schurs->n_subs+n_vertices;i++) { 646208122e43SStefano Zampini total_counts += pcbddc->adaptive_constraints_n[i]; 64639162d606SStefano Zampini if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++; 646408122e43SStefano Zampini max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]); 646508122e43SStefano Zampini } 64669162d606SStefano Zampini constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr; 64679162d606SStefano Zampini constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr; 64689162d606SStefano Zampini constraints_idxs = pcbddc->adaptive_constraints_idxs; 64699162d606SStefano Zampini constraints_data = pcbddc->adaptive_constraints_data; 647074d5cdf7SStefano Zampini /* constraints_n differs from pcbddc->adaptive_constraints_n */ 64715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(total_counts_cc,&constraints_n)); 64729162d606SStefano Zampini total_counts_cc = 0; 64739162d606SStefano Zampini for (i=0;i<sub_schurs->n_subs+n_vertices;i++) { 64749162d606SStefano Zampini if (pcbddc->adaptive_constraints_n[i]) { 64759162d606SStefano Zampini constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i]; 647608122e43SStefano Zampini } 647708122e43SStefano Zampini } 647808122e43SStefano Zampini 64798bec7fa6SStefano Zampini max_size_of_constraint = 0; 64809162d606SStefano Zampini for (i=0;i<total_counts_cc;i++) max_size_of_constraint = PetscMax(max_size_of_constraint,constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i]); 64815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B)); 648208122e43SStefano Zampini /* Change of basis */ 64835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(total_counts_cc,&change_basis)); 648408122e43SStefano Zampini if (pcbddc->use_change_of_basis) { 648508122e43SStefano Zampini for (i=0;i<sub_schurs->n_subs;i++) { 648608122e43SStefano Zampini if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) { 64875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(change_basis,i+n_vertices)); 648808122e43SStefano Zampini } 648908122e43SStefano Zampini } 649008122e43SStefano Zampini } 649108122e43SStefano Zampini } 6492984c4197SStefano Zampini pcbddc->local_primal_size = total_counts; 64935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs)); 649408122e43SStefano Zampini 64959162d606SStefano Zampini /* map constraints_idxs in boundary numbering */ 64965f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B)); 64972c71b3e2SJacob Faibussowitsch PetscCheckFalse(i != constraints_idxs_ptr[total_counts_cc],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for constraints indices %D != %D",constraints_idxs_ptr[total_counts_cc],i); 6498674ae819SStefano Zampini 6499674ae819SStefano Zampini /* Create constraint matrix */ 65005f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix)); 65015f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(pcbddc->ConstraintMatrix,MATAIJ)); 65025f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n)); 6503984c4197SStefano Zampini 6504984c4197SStefano Zampini /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */ 6505a717540cSStefano Zampini /* determine if a QR strategy is needed for change of basis */ 65065a52fde0SStefano Zampini qr_needed = pcbddc->use_qr_single; 65075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(total_counts_cc,&qr_needed_idx)); 6508984c4197SStefano Zampini total_primal_vertices=0; 6509b3d85658SStefano Zampini pcbddc->local_primal_size_cc = 0; 65109162d606SStefano Zampini for (i=0;i<total_counts_cc;i++) { 65119162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i]; 651272b8c272SStefano Zampini if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) { 65139162d606SStefano Zampini pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]]; 6514b3d85658SStefano Zampini pcbddc->local_primal_size_cc += 1; 651564efe560SStefano Zampini } else if (PetscBTLookup(change_basis,i)) { 65169162d606SStefano Zampini for (k=0;k<constraints_n[i];k++) { 65179162d606SStefano Zampini pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k]; 6518a717540cSStefano Zampini } 6519b3d85658SStefano Zampini pcbddc->local_primal_size_cc += constraints_n[i]; 652091af6908SStefano Zampini if (constraints_n[i] > 1 || pcbddc->use_qr_single) { 6521a717540cSStefano Zampini PetscBTSet(qr_needed_idx,i); 6522a717540cSStefano Zampini qr_needed = PETSC_TRUE; 6523a717540cSStefano Zampini } 6524fa434743SStefano Zampini } else { 6525b3d85658SStefano Zampini pcbddc->local_primal_size_cc += 1; 6526fa434743SStefano Zampini } 6527a717540cSStefano Zampini } 6528b371cd4fSStefano Zampini /* note that the local variable n_vertices used below stores the number of pointwise constraints */ 6529b371cd4fSStefano Zampini pcbddc->n_vertices = total_primal_vertices; 6530674ae819SStefano Zampini /* permute indices in order to have a sorted set of vertices */ 65315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs)); 65325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(pcbddc->local_primal_size_cc+pcbddc->benign_n,&pcbddc->local_primal_ref_node,pcbddc->local_primal_size_cc+pcbddc->benign_n,&pcbddc->local_primal_ref_mult)); 65335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices)); 65340e6343abSStefano Zampini for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1; 6535984c4197SStefano Zampini 6536984c4197SStefano Zampini /* nonzero structure of constraint matrix */ 653774d5cdf7SStefano Zampini /* and get reference dof for local constraints */ 65385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->local_primal_size,&nnz)); 6539984c4197SStefano Zampini for (i=0;i<total_primal_vertices;i++) nnz[i] = 1; 654074d5cdf7SStefano Zampini 6541984c4197SStefano Zampini j = total_primal_vertices; 654274d5cdf7SStefano Zampini total_counts = total_primal_vertices; 6543b3d85658SStefano Zampini cum = total_primal_vertices; 65449162d606SStefano Zampini for (i=n_vertices;i<total_counts_cc;i++) { 65454641a718SStefano Zampini if (!PetscBTLookup(change_basis,i)) { 6546b3d85658SStefano Zampini pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]]; 6547b3d85658SStefano Zampini pcbddc->local_primal_ref_mult[cum] = constraints_n[i]; 6548b3d85658SStefano Zampini cum++; 65499162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i]; 655074d5cdf7SStefano Zampini for (k=0;k<constraints_n[i];k++) { 655174d5cdf7SStefano Zampini pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k]; 655274d5cdf7SStefano Zampini nnz[j+k] = size_of_constraint; 655374d5cdf7SStefano Zampini } 65549162d606SStefano Zampini j += constraints_n[i]; 6555674ae819SStefano Zampini } 6556674ae819SStefano Zampini } 65575f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz)); 65585f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(pcbddc->ConstraintMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE)); 65595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(nnz)); 6560088faed8SStefano Zampini 6561674ae819SStefano Zampini /* set values in constraint matrix */ 6562984c4197SStefano Zampini for (i=0;i<total_primal_vertices;i++) { 65635f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES)); 6564674ae819SStefano Zampini } 6565984c4197SStefano Zampini total_counts = total_primal_vertices; 65669162d606SStefano Zampini for (i=n_vertices;i<total_counts_cc;i++) { 65674641a718SStefano Zampini if (!PetscBTLookup(change_basis,i)) { 65689162d606SStefano Zampini PetscInt *cols; 65699162d606SStefano Zampini 65709162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i]; 65719162d606SStefano Zampini cols = constraints_idxs+constraints_idxs_ptr[i]; 65729162d606SStefano Zampini for (k=0;k<constraints_n[i];k++) { 65739162d606SStefano Zampini PetscInt row = total_counts+k; 65749162d606SStefano Zampini PetscScalar *vals; 65759162d606SStefano Zampini 65769162d606SStefano Zampini vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint; 65775f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES)); 65789162d606SStefano Zampini } 65799162d606SStefano Zampini total_counts += constraints_n[i]; 6580674ae819SStefano Zampini } 6581674ae819SStefano Zampini } 6582674ae819SStefano Zampini /* assembling */ 65835f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY)); 65845f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY)); 65855f80ce2aSJacob Faibussowitsch CHKERRQ(MatViewFromOptions(pcbddc->ConstraintMatrix,(PetscObject)pc,"-pc_bddc_constraint_mat_view")); 6586088faed8SStefano Zampini 6587674ae819SStefano Zampini /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */ 6588674ae819SStefano Zampini if (pcbddc->use_change_of_basis) { 6589026de310SStefano Zampini /* dual and primal dofs on a single cc */ 6590984c4197SStefano Zampini PetscInt dual_dofs,primal_dofs; 6591984c4197SStefano Zampini /* working stuff for GEQRF */ 65925a52fde0SStefano Zampini PetscScalar *qr_basis = NULL,*qr_tau = NULL,*qr_work = NULL,lqr_work_t; 6593984c4197SStefano Zampini PetscBLASInt lqr_work; 6594984c4197SStefano Zampini /* working stuff for UNGQR */ 65953c377650SSatish Balay PetscScalar *gqr_work = NULL,lgqr_work_t=0.0; 6596984c4197SStefano Zampini PetscBLASInt lgqr_work; 6597984c4197SStefano Zampini /* working stuff for TRTRS */ 65985a52fde0SStefano Zampini PetscScalar *trs_rhs = NULL; 65993f08241aSStefano Zampini PetscBLASInt Blas_NRHS; 6600984c4197SStefano Zampini /* pointers for values insertion into change of basis matrix */ 6601984c4197SStefano Zampini PetscInt *start_rows,*start_cols; 6602984c4197SStefano Zampini PetscScalar *start_vals; 6603984c4197SStefano Zampini /* working stuff for values insertion */ 66044641a718SStefano Zampini PetscBT is_primal; 660564efe560SStefano Zampini PetscInt *aux_primal_numbering_B; 6606906d46d4SStefano Zampini /* matrix sizes */ 6607906d46d4SStefano Zampini PetscInt global_size,local_size; 6608906d46d4SStefano Zampini /* temporary change of basis */ 6609906d46d4SStefano Zampini Mat localChangeOfBasisMatrix; 6610cf5a6209SStefano Zampini /* extra space for debugging */ 66115a52fde0SStefano Zampini PetscScalar *dbg_work = NULL; 6612984c4197SStefano Zampini 6613906d46d4SStefano Zampini /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */ 66145f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix)); 66155f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(localChangeOfBasisMatrix,MATAIJ)); 66165f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n)); 6617906d46d4SStefano Zampini /* nonzeros for local mat */ 66185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcis->n,&nnz)); 66191dd7afcfSStefano Zampini if (!pcbddc->benign_change || pcbddc->fake_change) { 6620bbb9e6c6SStefano Zampini for (i=0;i<pcis->n;i++) nnz[i]=1; 66211dd7afcfSStefano Zampini } else { 66221dd7afcfSStefano Zampini const PetscInt *ii; 66231dd7afcfSStefano Zampini PetscInt n; 66241dd7afcfSStefano Zampini PetscBool flg_row; 66255f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row)); 66261dd7afcfSStefano Zampini for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i]; 66275f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row)); 66281dd7afcfSStefano Zampini } 66299162d606SStefano Zampini for (i=n_vertices;i<total_counts_cc;i++) { 6630a717540cSStefano Zampini if (PetscBTLookup(change_basis,i)) { 66319162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i]; 6632a717540cSStefano Zampini if (PetscBTLookup(qr_needed_idx,i)) { 66339162d606SStefano Zampini for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint; 6634a717540cSStefano Zampini } else { 66359162d606SStefano Zampini nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint; 66369162d606SStefano Zampini for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2; 6637a717540cSStefano Zampini } 6638a717540cSStefano Zampini } 6639a717540cSStefano Zampini } 66405f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz)); 66415f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(localChangeOfBasisMatrix,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE)); 66425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(nnz)); 66431dd7afcfSStefano Zampini /* Set interior change in the matrix */ 66441dd7afcfSStefano Zampini if (!pcbddc->benign_change || pcbddc->fake_change) { 6645bbb9e6c6SStefano Zampini for (i=0;i<pcis->n;i++) { 66465f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES)); 6647a717540cSStefano Zampini } 66481dd7afcfSStefano Zampini } else { 66491dd7afcfSStefano Zampini const PetscInt *ii,*jj; 66501dd7afcfSStefano Zampini PetscScalar *aa; 66511dd7afcfSStefano Zampini PetscInt n; 66521dd7afcfSStefano Zampini PetscBool flg_row; 66535f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row)); 66545f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJGetArray(pcbddc->benign_change,&aa)); 66551dd7afcfSStefano Zampini for (i=0;i<n;i++) { 66565f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES)); 66571dd7afcfSStefano Zampini } 66585f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJRestoreArray(pcbddc->benign_change,&aa)); 66595f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row)); 66601dd7afcfSStefano Zampini } 6661a717540cSStefano Zampini 6662a717540cSStefano Zampini if (pcbddc->dbg_flag) { 66635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n")); 66645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank)); 6665a717540cSStefano Zampini } 6666a717540cSStefano Zampini 6667a717540cSStefano Zampini /* Now we loop on the constraints which need a change of basis */ 6668a717540cSStefano Zampini /* 6669a717540cSStefano Zampini Change of basis matrix is evaluated similarly to the FIRST APPROACH in 6670a717540cSStefano Zampini Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1) 6671a717540cSStefano Zampini 6672a6b551f4SStefano Zampini Basic blocks of change of basis matrix T computed by 6673a717540cSStefano Zampini 6674a6b551f4SStefano Zampini - Using the following block transformation if there is only a primal dof on the cc (and -pc_bddc_use_qr_single is not specified) 6675a6b551f4SStefano Zampini 6676a6b551f4SStefano Zampini | 1 0 ... 0 s_1/S | 6677a6b551f4SStefano Zampini | 0 1 ... 0 s_2/S | 6678a717540cSStefano Zampini | ... | 6679a6b551f4SStefano Zampini | 0 ... 1 s_{n-1}/S | 6680a6b551f4SStefano Zampini | -s_1/s_n ... -s_{n-1}/s_n s_n/S | 6681a717540cSStefano Zampini 6682a6b551f4SStefano Zampini with S = \sum_{i=1}^n s_i^2 6683a6b551f4SStefano Zampini NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering 6684a6b551f4SStefano Zampini in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering 6685a6b551f4SStefano Zampini 6686a6b551f4SStefano Zampini - QR decomposition of constraints otherwise 6687a717540cSStefano Zampini */ 66885a52fde0SStefano Zampini if (qr_needed && max_size_of_constraint) { 6689984c4197SStefano Zampini /* space to store Q */ 66905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis)); 66914e64d54eSstefano_zampini /* array to store scaling factors for reflectors */ 66925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(max_constraints,&qr_tau)); 6693984c4197SStefano Zampini /* first we issue queries for optimal work */ 66945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(max_size_of_constraint,&Blas_M)); 66955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(max_constraints,&Blas_N)); 66965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(max_size_of_constraint,&Blas_LDA)); 6697984c4197SStefano Zampini lqr_work = -1; 66983f08241aSStefano Zampini PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr)); 6699*28b400f6SJacob Faibussowitsch PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr); 67005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work)); 67015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work)); 6702984c4197SStefano Zampini lgqr_work = -1; 67035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(max_size_of_constraint,&Blas_M)); 67045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(max_size_of_constraint,&Blas_N)); 67055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(max_constraints,&Blas_K)); 67065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(max_size_of_constraint,&Blas_LDA)); 67073f08241aSStefano Zampini if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */ 6708c964aadfSJose E. Roman PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr)); 6709*28b400f6SJacob Faibussowitsch PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to ORGQR/UNGQR Lapack routine %d",(int)lierr); 67105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work)); 67115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work)); 6712984c4197SStefano Zampini /* array to store rhs and solution of triangular solver */ 67135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(max_constraints*max_constraints,&trs_rhs)); 6714a717540cSStefano Zampini /* allocating workspace for check */ 6715a717540cSStefano Zampini if (pcbddc->dbg_flag) { 67165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work)); 6717a717540cSStefano Zampini } 6718a717540cSStefano Zampini } 6719984c4197SStefano Zampini /* array to store whether a node is primal or not */ 67205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(pcis->n_B,&is_primal)); 67215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B)); 67225f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B)); 67232c71b3e2SJacob Faibussowitsch PetscCheckFalse(i != total_primal_vertices,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D",total_primal_vertices,i); 672439e2fb2aSStefano Zampini for (i=0;i<total_primal_vertices;i++) { 67255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(is_primal,aux_primal_numbering_B[i])); 672639e2fb2aSStefano Zampini } 67275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(aux_primal_numbering_B)); 6728984c4197SStefano Zampini 6729a717540cSStefano Zampini /* loop on constraints and see whether or not they need a change of basis and compute it */ 67309162d606SStefano Zampini for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) { 67319162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts]; 67324641a718SStefano Zampini if (PetscBTLookup(change_basis,total_counts)) { 6733984c4197SStefano Zampini /* get constraint info */ 67349162d606SStefano Zampini primal_dofs = constraints_n[total_counts]; 6735984c4197SStefano Zampini dual_dofs = size_of_constraint-primal_dofs; 6736984c4197SStefano Zampini 6737984c4197SStefano Zampini if (pcbddc->dbg_flag) { 67385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraints %D: %D need a change of basis (size %D)\n",total_counts,primal_dofs,size_of_constraint)); 6739674ae819SStefano Zampini } 6740984c4197SStefano Zampini 6741fa434743SStefano Zampini if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */ 6742a717540cSStefano Zampini 6743a717540cSStefano Zampini /* copy quadrature constraints for change of basis check */ 6744a717540cSStefano Zampini if (pcbddc->dbg_flag) { 67455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs)); 6746a717540cSStefano Zampini } 6747984c4197SStefano Zampini /* copy temporary constraints into larger work vector (in order to store all columns of Q) */ 67485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs)); 6749984c4197SStefano Zampini 6750984c4197SStefano Zampini /* compute QR decomposition of constraints */ 67515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_M)); 67525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(primal_dofs,&Blas_N)); 67535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_LDA)); 67545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 67553f08241aSStefano Zampini PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr)); 6756*28b400f6SJacob Faibussowitsch PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr); 67575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 6758984c4197SStefano Zampini 6759a5b23f4aSJose E. Roman /* explicitly compute R^-T */ 67605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(trs_rhs,primal_dofs*primal_dofs)); 6761984c4197SStefano Zampini for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0; 67625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(primal_dofs,&Blas_N)); 67635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(primal_dofs,&Blas_NRHS)); 67645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_LDA)); 67655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(primal_dofs,&Blas_LDB)); 67665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 67673f08241aSStefano Zampini PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr)); 6768*28b400f6SJacob Faibussowitsch PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr); 67695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 6770984c4197SStefano Zampini 6771a717540cSStefano Zampini /* explicitly compute all columns of Q (Q = [Q1 | Q2]) overwriting QR factorization in qr_basis */ 67725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_M)); 67735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_N)); 67745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(primal_dofs,&Blas_K)); 67755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_LDA)); 67765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6777c964aadfSJose E. Roman PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr)); 6778*28b400f6SJacob Faibussowitsch PetscCheck(!lierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in ORGQR/UNGQR Lapack routine %d",(int)lierr); 67795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 6780984c4197SStefano Zampini 6781984c4197SStefano Zampini /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints 6782984c4197SStefano Zampini i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below) 6783984c4197SStefano Zampini where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */ 67845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_M)); 67855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(primal_dofs,&Blas_N)); 67865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(primal_dofs,&Blas_K)); 67875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_LDA)); 67885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(primal_dofs,&Blas_LDB)); 67895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_LDC)); 67905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 67919162d606SStefano Zampini PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&Blas_M,&Blas_N,&Blas_K,&one,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&zero,constraints_data+constraints_data_ptr[total_counts],&Blas_LDC)); 67925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 67935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs)); 6794984c4197SStefano Zampini 6795984c4197SStefano Zampini /* insert values in change of basis matrix respecting global ordering of new primal dofs */ 67969162d606SStefano Zampini start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]]; 6797984c4197SStefano Zampini /* insert cols for primal dofs */ 6798984c4197SStefano Zampini for (j=0;j<primal_dofs;j++) { 6799984c4197SStefano Zampini start_vals = &qr_basis[j*size_of_constraint]; 68009162d606SStefano Zampini start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j]; 68015f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES)); 6802984c4197SStefano Zampini } 6803984c4197SStefano Zampini /* insert cols for dual dofs */ 6804984c4197SStefano Zampini for (j=0,k=0;j<dual_dofs;k++) { 68059162d606SStefano Zampini if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) { 6806984c4197SStefano Zampini start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint]; 68079162d606SStefano Zampini start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k]; 68085f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES)); 6809984c4197SStefano Zampini j++; 6810674ae819SStefano Zampini } 6811674ae819SStefano Zampini } 6812984c4197SStefano Zampini 6813984c4197SStefano Zampini /* check change of basis */ 6814984c4197SStefano Zampini if (pcbddc->dbg_flag) { 6815984c4197SStefano Zampini PetscInt ii,jj; 6816984c4197SStefano Zampini PetscBool valid_qr=PETSC_TRUE; 68175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(primal_dofs,&Blas_M)); 68185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_N)); 68195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_K)); 68205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_LDA)); 68215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_LDB)); 68225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(primal_dofs,&Blas_LDC)); 68235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6824cf5a6209SStefano Zampini PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&Blas_M,&Blas_N,&Blas_K,&one,dbg_work,&Blas_LDA,qr_basis,&Blas_LDB,&zero,&dbg_work[size_of_constraint*primal_dofs],&Blas_LDC)); 68255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 6826984c4197SStefano Zampini for (jj=0;jj<size_of_constraint;jj++) { 6827984c4197SStefano Zampini for (ii=0;ii<primal_dofs;ii++) { 6828cf5a6209SStefano Zampini if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE; 6829c068d9bbSLisandro Dalcin if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) valid_qr = PETSC_FALSE; 6830674ae819SStefano Zampini } 6831674ae819SStefano Zampini } 6832984c4197SStefano Zampini if (!valid_qr) { 68335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n")); 6834984c4197SStefano Zampini for (jj=0;jj<size_of_constraint;jj++) { 6835984c4197SStefano Zampini for (ii=0;ii<primal_dofs;ii++) { 6836cf5a6209SStefano Zampini if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) { 68375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %D is not orthogonal to constraint %D (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]))); 6838674ae819SStefano Zampini } 6839c068d9bbSLisandro Dalcin if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-(PetscReal)1) > 1.e-12) { 68405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %D is not unitary w.r.t constraint %D (%1.14e)!\n",jj,ii,PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]))); 6841984c4197SStefano Zampini } 6842984c4197SStefano Zampini } 6843984c4197SStefano Zampini } 6844674ae819SStefano Zampini } else { 68455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n")); 6846674ae819SStefano Zampini } 6847674ae819SStefano Zampini } 6848a717540cSStefano Zampini } else { /* simple transformation block */ 6849a717540cSStefano Zampini PetscInt row,col; 6850a6b551f4SStefano Zampini PetscScalar val,norm; 6851a6b551f4SStefano Zampini 68525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBLASIntCast(size_of_constraint,&Blas_N)); 68539162d606SStefano Zampini PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,constraints_data+constraints_data_ptr[total_counts],&Blas_one,constraints_data+constraints_data_ptr[total_counts],&Blas_one)); 6854a717540cSStefano Zampini for (j=0;j<size_of_constraint;j++) { 68559162d606SStefano Zampini PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j]; 68569162d606SStefano Zampini row = constraints_idxs[constraints_idxs_ptr[total_counts]+j]; 6857bbb9e6c6SStefano Zampini if (!PetscBTLookup(is_primal,row_B)) { 68589162d606SStefano Zampini col = constraints_idxs[constraints_idxs_ptr[total_counts]]; 68595f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES)); 68605f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES)); 6861a717540cSStefano Zampini } else { 6862a717540cSStefano Zampini for (k=0;k<size_of_constraint;k++) { 68639162d606SStefano Zampini col = constraints_idxs[constraints_idxs_ptr[total_counts]+k]; 6864a717540cSStefano Zampini if (row != col) { 68659162d606SStefano Zampini val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]]; 6866a717540cSStefano Zampini } else { 68679162d606SStefano Zampini val = constraints_data[constraints_data_ptr[total_counts]]/norm; 6868a717540cSStefano Zampini } 68695f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES)); 6870a717540cSStefano Zampini } 6871a717540cSStefano Zampini } 6872a717540cSStefano Zampini } 687398a51de6SStefano Zampini if (pcbddc->dbg_flag) { 68745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n")); 6875a717540cSStefano Zampini } 6876674ae819SStefano Zampini } 6877984c4197SStefano Zampini } else { 6878984c4197SStefano Zampini if (pcbddc->dbg_flag) { 68795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraint %D does not need a change of basis (size %D)\n",total_counts,size_of_constraint)); 6880674ae819SStefano Zampini } 6881674ae819SStefano Zampini } 6882674ae819SStefano Zampini } 6883a717540cSStefano Zampini 6884a717540cSStefano Zampini /* free workspace */ 6885a717540cSStefano Zampini if (qr_needed) { 6886984c4197SStefano Zampini if (pcbddc->dbg_flag) { 68875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(dbg_work)); 6888984c4197SStefano Zampini } 68895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(trs_rhs)); 68905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(qr_tau)); 68915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(qr_work)); 68925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(gqr_work)); 68935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(qr_basis)); 6894674ae819SStefano Zampini } 68955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&is_primal)); 68965f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY)); 68975f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY)); 6898906d46d4SStefano Zampini 6899906d46d4SStefano Zampini /* assembling of global change of variable */ 690088c03ad3SStefano Zampini if (!pcbddc->fake_change) { 6901bbb9e6c6SStefano Zampini Mat tmat; 690216f15bc4SStefano Zampini PetscInt bs; 690316f15bc4SStefano Zampini 69045f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSize(pcis->vec1_global,&global_size)); 69055f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(pcis->vec1_global,&local_size)); 69065f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat)); 69075f80ce2aSJacob Faibussowitsch CHKERRQ(MatISSetLocalMat(tmat,localChangeOfBasisMatrix)); 69085f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY)); 69095f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY)); 69105f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix)); 69115f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ)); 69125f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetBlockSize(pc->pmat,&bs)); 69135f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs)); 69145f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size)); 69155f80ce2aSJacob Faibussowitsch CHKERRQ(MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE)); 69165f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(tmat,MATAIJ,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix)); 69175f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&tmat)); 69185f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcis->vec1_global,0.0)); 69195f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcis->vec1_N,1.0)); 69205f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE)); 69215f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE)); 69225f80ce2aSJacob Faibussowitsch CHKERRQ(VecReciprocal(pcis->vec1_global)); 69235f80ce2aSJacob Faibussowitsch CHKERRQ(MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL)); 692488c03ad3SStefano Zampini 6925906d46d4SStefano Zampini /* check */ 6926906d46d4SStefano Zampini if (pcbddc->dbg_flag) { 6927906d46d4SStefano Zampini PetscReal error; 6928906d46d4SStefano Zampini Vec x,x_change; 6929906d46d4SStefano Zampini 69305f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(pcis->vec1_global,&x)); 69315f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(pcis->vec1_global,&x_change)); 69325f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetRandom(x,NULL)); 69335f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(x,pcis->vec1_global)); 69345f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD)); 69355f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD)); 69365f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N)); 69375f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE)); 69385f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE)); 69395f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change)); 69405f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(x,-1.0,x_change)); 69415f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(x,NORM_INFINITY,&error)); 6942637e8532SStefano Zampini if (error > PETSC_SMALL) { 694398921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error global vs local change on N: %1.6e",error); 6944637e8532SStefano Zampini } 69455f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&x)); 69465f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&x_change)); 6947906d46d4SStefano Zampini } 6948b96c3477SStefano Zampini /* adapt sub_schurs computed (if any) */ 6949b96c3477SStefano Zampini if (pcbddc->use_deluxe_scaling) { 6950b96c3477SStefano Zampini PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs; 6951bf3a8328SStefano Zampini 69522c71b3e2SJacob Faibussowitsch PetscCheckFalse(pcbddc->use_change_of_basis && pcbddc->adaptive_userdefined,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot mix automatic change of basis, adaptive selection and user-defined constraints"); 6953b334f244SStefano Zampini if (sub_schurs && sub_schurs->S_Ej_all) { 6954ac632422SStefano Zampini Mat S_new,tmat; 6955bf3a8328SStefano Zampini IS is_all_N,is_V_Sall = NULL; 6956bbb9e6c6SStefano Zampini 69575f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N)); 69585f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat)); 6959bf3a8328SStefano Zampini if (pcbddc->deluxe_zerorows) { 6960bf3a8328SStefano Zampini ISLocalToGlobalMapping NtoSall; 6961bf3a8328SStefano Zampini IS is_V; 69625f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V)); 69635f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall)); 69645f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall)); 69655f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&NtoSall)); 69665f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_V)); 6967bf3a8328SStefano Zampini } 69685f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_all_N)); 69695f80ce2aSJacob Faibussowitsch CHKERRQ(MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new)); 69705f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&sub_schurs->S_Ej_all)); 69715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)S_new)); 6972bf3a8328SStefano Zampini if (pcbddc->deluxe_zerorows) { 6973bf3a8328SStefano Zampini const PetscScalar *array; 6974bf3a8328SStefano Zampini const PetscInt *idxs_V,*idxs_all; 6975bf3a8328SStefano Zampini PetscInt i,n_V; 6976bf3a8328SStefano Zampini 69775f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL)); 69785f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(is_V_Sall,&n_V)); 69795f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(is_V_Sall,&idxs_V)); 69805f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(sub_schurs->is_Ej_all,&idxs_all)); 69815f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(pcis->D,&array)); 6982b087196eSStefano Zampini for (i=0;i<n_V;i++) { 6983b087196eSStefano Zampini PetscScalar val; 6984b087196eSStefano Zampini PetscInt idx; 6985b087196eSStefano Zampini 6986b087196eSStefano Zampini idx = idxs_V[i]; 6987b087196eSStefano Zampini val = array[idxs_all[idxs_V[i]]]; 69885f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(S_new,idx,idx,val,INSERT_VALUES)); 6989b087196eSStefano Zampini } 69905f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY)); 69915f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY)); 69925f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(pcis->D,&array)); 69935f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all)); 69945f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(is_V_Sall,&idxs_V)); 6995bf3a8328SStefano Zampini } 6996ac632422SStefano Zampini sub_schurs->S_Ej_all = S_new; 69975f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&S_new)); 6998ac632422SStefano Zampini if (sub_schurs->sum_S_Ej_all) { 69995f80ce2aSJacob Faibussowitsch CHKERRQ(MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new)); 70005f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&sub_schurs->sum_S_Ej_all)); 70015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)S_new)); 7002bf3a8328SStefano Zampini if (pcbddc->deluxe_zerorows) { 70035f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL)); 7004bf3a8328SStefano Zampini } 7005ac632422SStefano Zampini sub_schurs->sum_S_Ej_all = S_new; 70065f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&S_new)); 7007ac632422SStefano Zampini } 70085f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_V_Sall)); 70095f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&tmat)); 7010b96c3477SStefano Zampini } 7011c9db6a07SStefano Zampini /* destroy any change of basis context in sub_schurs */ 7012b334f244SStefano Zampini if (sub_schurs && sub_schurs->change) { 7013c9db6a07SStefano Zampini PetscInt i; 7014c9db6a07SStefano Zampini 7015c9db6a07SStefano Zampini for (i=0;i<sub_schurs->n_subs;i++) { 70165f80ce2aSJacob Faibussowitsch CHKERRQ(KSPDestroy(&sub_schurs->change[i])); 7017c9db6a07SStefano Zampini } 70185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(sub_schurs->change)); 7019c9db6a07SStefano Zampini } 7020b96c3477SStefano Zampini } 702116909a7fSStefano Zampini if (pcbddc->switch_static) { /* need to save the local change */ 702216909a7fSStefano Zampini pcbddc->switch_static_change = localChangeOfBasisMatrix; 702316909a7fSStefano Zampini } else { 70245f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&localChangeOfBasisMatrix)); 702516909a7fSStefano Zampini } 70261dd7afcfSStefano Zampini /* determine if any process has changed the pressures locally */ 702727b6a85dSStefano Zampini pcbddc->change_interior = pcbddc->benign_have_null; 702872b8c272SStefano Zampini } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */ 70295f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pcbddc->ConstraintMatrix)); 703072b8c272SStefano Zampini pcbddc->ConstraintMatrix = localChangeOfBasisMatrix; 703172b8c272SStefano Zampini pcbddc->use_qr_single = qr_needed; 703272b8c272SStefano Zampini } 70331dd7afcfSStefano Zampini } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) { 703427b6a85dSStefano Zampini if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) { 70355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix)); 7036b9b85e73SStefano Zampini pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix; 7037906d46d4SStefano Zampini } else { 70381dd7afcfSStefano Zampini Mat benign_global = NULL; 703927b6a85dSStefano Zampini if (pcbddc->benign_have_null) { 70401dd7afcfSStefano Zampini Mat M; 70411dd7afcfSStefano Zampini 70429e9b7b1fSStefano Zampini pcbddc->change_interior = PETSC_TRUE; 70435f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(matis->counter,pcis->vec1_N)); 70445f80ce2aSJacob Faibussowitsch CHKERRQ(VecReciprocal(pcis->vec1_N)); 70455f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&benign_global)); 70469e9b7b1fSStefano Zampini if (pcbddc->benign_change) { 70475f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M)); 70485f80ce2aSJacob Faibussowitsch CHKERRQ(MatDiagonalScale(M,pcis->vec1_N,NULL)); 7049906d46d4SStefano Zampini } else { 70505f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&M)); 70515f80ce2aSJacob Faibussowitsch CHKERRQ(MatDiagonalSet(M,pcis->vec1_N,INSERT_VALUES)); 7052906d46d4SStefano Zampini } 70535f80ce2aSJacob Faibussowitsch CHKERRQ(MatISSetLocalMat(benign_global,M)); 70545f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&M)); 70555f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(benign_global,MAT_FINAL_ASSEMBLY)); 70565f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(benign_global,MAT_FINAL_ASSEMBLY)); 70571dd7afcfSStefano Zampini } 70581dd7afcfSStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix) { 70595f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix)); 70605f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&benign_global)); 706127b6a85dSStefano Zampini } else if (pcbddc->benign_have_null) { 70621dd7afcfSStefano Zampini pcbddc->ChangeOfBasisMatrix = benign_global; 70631dd7afcfSStefano Zampini } 70641dd7afcfSStefano Zampini } 706516909a7fSStefano Zampini if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */ 706616909a7fSStefano Zampini IS is_global; 706716909a7fSStefano Zampini const PetscInt *gidxs; 706816909a7fSStefano Zampini 70695f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetIndices(matis->rmapping,&gidxs)); 70705f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global)); 70715f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreIndices(matis->rmapping,&gidxs)); 70725f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change)); 70735f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_global)); 707416909a7fSStefano Zampini } 70751dd7afcfSStefano Zampini } 70761dd7afcfSStefano Zampini if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) { 70775f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(pcis->vec1_global,&pcbddc->work_change)); 7078b9b85e73SStefano Zampini } 7079a717540cSStefano Zampini 708072b8c272SStefano Zampini if (!pcbddc->fake_change) { 70814f1b2e48SStefano Zampini /* add pressure dofs to set of primal nodes for numbering purposes */ 70824f1b2e48SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) { 70834f1b2e48SStefano Zampini pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i]; 70844f1b2e48SStefano Zampini pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i]; 7085019a44ceSStefano Zampini pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1; 7086019a44ceSStefano Zampini pcbddc->local_primal_size_cc++; 7087019a44ceSStefano Zampini pcbddc->local_primal_size++; 7088019a44ceSStefano Zampini } 7089019a44ceSStefano Zampini 7090019a44ceSStefano Zampini /* check if a new primal space has been introduced (also take into account benign trick) */ 7091727cdba6SStefano Zampini pcbddc->new_primal_space_local = PETSC_TRUE; 7092727cdba6SStefano Zampini if (olocal_primal_size == pcbddc->local_primal_size) { 70935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc,&pcbddc->new_primal_space_local)); 7094c1c8e736SStefano Zampini pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local); 70950e6343abSStefano Zampini if (!pcbddc->new_primal_space_local) { 70965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc,&pcbddc->new_primal_space_local)); 7097727cdba6SStefano Zampini pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local); 7098727cdba6SStefano Zampini } 70990e6343abSStefano Zampini } 7100727cdba6SStefano Zampini /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */ 71015f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc))); 710272b8c272SStefano Zampini } 71035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult)); 7104727cdba6SStefano Zampini 7105a717540cSStefano Zampini /* flush dbg viewer */ 7106b8ffe317SStefano Zampini if (pcbddc->dbg_flag) { 71075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 7108b8ffe317SStefano Zampini } 7109a717540cSStefano Zampini 7110e310c8b4SStefano Zampini /* free workspace */ 71115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&qr_needed_idx)); 71125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&change_basis)); 711308122e43SStefano Zampini if (!pcbddc->adaptive_selection) { 71145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n)); 71155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B)); 711608122e43SStefano Zampini } else { 71179162d606SStefano Zampini ierr = PetscFree5(pcbddc->adaptive_constraints_n, 71189162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr, 71199162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr, 712008122e43SStefano Zampini pcbddc->adaptive_constraints_idxs, 712108122e43SStefano Zampini pcbddc->adaptive_constraints_data);CHKERRQ(ierr); 71225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(constraints_n)); 71235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(constraints_idxs_B)); 712408122e43SStefano Zampini } 7125674ae819SStefano Zampini PetscFunctionReturn(0); 7126674ae819SStefano Zampini } 7127674ae819SStefano Zampini 7128674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc) 7129674ae819SStefano Zampini { 713071582508SStefano Zampini ISLocalToGlobalMapping map; 7131674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 7132674ae819SStefano Zampini Mat_IS *matis = (Mat_IS*)pc->pmat->data; 713366da6bd7Sstefano_zampini PetscInt i,N; 713466da6bd7Sstefano_zampini PetscBool rcsr = PETSC_FALSE; 7135674ae819SStefano Zampini 7136674ae819SStefano Zampini PetscFunctionBegin; 71378af8fcf9SStefano Zampini if (pcbddc->recompute_topography) { 7138b03ebc13SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 71398e61c736SStefano Zampini /* Reset previously computed graph */ 71405f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphReset(pcbddc->mat_graph)); 7141674ae819SStefano Zampini /* Init local Graph struct */ 71425f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(pc->pmat,&N,NULL)); 71435f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalToGlobalMapping(pc->pmat,&map,NULL)); 71445f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphInit(pcbddc->mat_graph,map,N,pcbddc->graphmaxcount)); 7145674ae819SStefano Zampini 71467a0e7b2cSstefano_zampini if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) { 71475f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCConsistencyCheckIS(pc,MPI_LOR,&pcbddc->user_primal_vertices_local)); 71487a0e7b2cSstefano_zampini } 7149575ad6abSStefano Zampini /* Check validity of the csr graph passed in by the user */ 71502c71b3e2SJacob Faibussowitsch PetscCheckFalse(pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid size of local CSR graph! Found %D, expected %D",pcbddc->mat_graph->nvtxs_csr,pcbddc->mat_graph->nvtxs); 71519577ea80SStefano Zampini 7152674ae819SStefano Zampini /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */ 715366da6bd7Sstefano_zampini if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) { 71544d379d7bSStefano Zampini PetscInt *xadj,*adjncy; 71554d379d7bSStefano Zampini PetscInt nvtxs; 7156e496cd5dSStefano Zampini PetscBool flg_row=PETSC_FALSE; 7157674ae819SStefano Zampini 71585f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row)); 71592fffb893SStefano Zampini if (flg_row) { 71605f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES)); 7161b96c3477SStefano Zampini pcbddc->computed_rowadj = PETSC_TRUE; 71622fffb893SStefano Zampini } 71635f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row)); 716466da6bd7Sstefano_zampini rcsr = PETSC_TRUE; 7165674ae819SStefano Zampini } 71669b28b941SStefano Zampini if (pcbddc->dbg_flag) { 71675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 7168674ae819SStefano Zampini } 7169674ae819SStefano Zampini 7170ab8c8b98SStefano Zampini if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) { 7171ab8c8b98SStefano Zampini PetscReal *lcoords; 7172ab8c8b98SStefano Zampini PetscInt n; 7173ab8c8b98SStefano Zampini MPI_Datatype dimrealtype; 7174ab8c8b98SStefano Zampini 71754f819b78SStefano Zampini /* TODO: support for blocked */ 71762c71b3e2SJacob Faibussowitsch PetscCheckFalse(pcbddc->mat_graph->cnloc != pc->pmat->rmap->n,PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid number of local coordinates! Got %D, expected %D",pcbddc->mat_graph->cnloc,pc->pmat->rmap->n); 71775f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(matis->A,&n,NULL)); 71785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->mat_graph->cdim*n,&lcoords)); 71795f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_contiguous(pcbddc->mat_graph->cdim,MPIU_REAL,&dimrealtype)); 71805f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_commit(&dimrealtype)); 71815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords,MPI_REPLACE)); 71825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(matis->sf,dimrealtype,pcbddc->mat_graph->coords,lcoords,MPI_REPLACE)); 71835f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_free(&dimrealtype)); 71845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddc->mat_graph->coords)); 7185ab8c8b98SStefano Zampini 7186ab8c8b98SStefano Zampini pcbddc->mat_graph->coords = lcoords; 7187ab8c8b98SStefano Zampini pcbddc->mat_graph->cloc = PETSC_TRUE; 7188ab8c8b98SStefano Zampini pcbddc->mat_graph->cnloc = n; 7189ab8c8b98SStefano Zampini } 71902c71b3e2SJacob Faibussowitsch PetscCheckFalse(pcbddc->mat_graph->cnloc && pcbddc->mat_graph->cnloc != pcbddc->mat_graph->nvtxs,PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid number of local subdomain coordinates! Got %D, expected %D",pcbddc->mat_graph->cnloc,pcbddc->mat_graph->nvtxs); 7191625961bdSStefano Zampini pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && pcbddc->mat_graph->cdim && !pcbddc->corner_selected); 7192ab8c8b98SStefano Zampini 7193674ae819SStefano Zampini /* Setup of Graph */ 71944b2aedd3SStefano Zampini pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */ 71955f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphSetUp(pcbddc->mat_graph,pcbddc->vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices_local)); 7196674ae819SStefano Zampini 71974f1b2e48SStefano Zampini /* attach info on disconnected subdomains if present */ 71984f1b2e48SStefano Zampini if (pcbddc->n_local_subs) { 719920c3699dSStefano Zampini PetscInt *local_subs,n,totn; 72004f1b2e48SStefano Zampini 72015f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(matis->A,&n,NULL)); 72025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n,&local_subs)); 720320c3699dSStefano Zampini for (i=0;i<n;i++) local_subs[i] = pcbddc->n_local_subs; 72044f1b2e48SStefano Zampini for (i=0;i<pcbddc->n_local_subs;i++) { 72054f1b2e48SStefano Zampini const PetscInt *idxs; 72064f1b2e48SStefano Zampini PetscInt nl,j; 72074f1b2e48SStefano Zampini 72085f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pcbddc->local_subs[i],&nl)); 72095f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcbddc->local_subs[i],&idxs)); 721071582508SStefano Zampini for (j=0;j<nl;j++) local_subs[idxs[j]] = i; 72115f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcbddc->local_subs[i],&idxs)); 72124f1b2e48SStefano Zampini } 721320c3699dSStefano Zampini for (i=0,totn=0;i<n;i++) totn = PetscMax(totn,local_subs[i]); 721420c3699dSStefano Zampini pcbddc->mat_graph->n_local_subs = totn + 1; 72154f1b2e48SStefano Zampini pcbddc->mat_graph->local_subs = local_subs; 72164f1b2e48SStefano Zampini } 72178af8fcf9SStefano Zampini } 72184f1b2e48SStefano Zampini 7219cac5312eSStefano Zampini if (!pcbddc->graphanalyzed) { 7220674ae819SStefano Zampini /* Graph's connected components analysis */ 72215f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph)); 722271582508SStefano Zampini pcbddc->graphanalyzed = PETSC_TRUE; 72234f819b78SStefano Zampini pcbddc->corner_selected = pcbddc->corner_selection; 72248af8fcf9SStefano Zampini } 722566da6bd7Sstefano_zampini if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0; 7226674ae819SStefano Zampini PetscFunctionReturn(0); 7227674ae819SStefano Zampini } 7228674ae819SStefano Zampini 7229295df10fSStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt *nio, Vec vecs[]) 72309a7d3425SStefano Zampini { 7231295df10fSStefano Zampini PetscInt i,j,n; 72329a7d3425SStefano Zampini PetscScalar *alphas; 7233295df10fSStefano Zampini PetscReal norm,*onorms; 72349a7d3425SStefano Zampini 72359a7d3425SStefano Zampini PetscFunctionBegin; 7236295df10fSStefano Zampini n = *nio; 72378c0031efSStefano Zampini if (!n) PetscFunctionReturn(0); 72385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(n,&alphas,n,&onorms)); 72395f80ce2aSJacob Faibussowitsch CHKERRQ(VecNormalize(vecs[0],&norm)); 724092cccca0SStefano Zampini if (norm < PETSC_SMALL) { 7241295df10fSStefano Zampini onorms[0] = 0.0; 72425f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(vecs[0],0.0)); 7243295df10fSStefano Zampini } else { 7244295df10fSStefano Zampini onorms[0] = norm; 724592cccca0SStefano Zampini } 7246295df10fSStefano Zampini 72478c0031efSStefano Zampini for (i=1;i<n;i++) { 72485f80ce2aSJacob Faibussowitsch CHKERRQ(VecMDot(vecs[i],i,vecs,alphas)); 72498c0031efSStefano Zampini for (j=0;j<i;j++) alphas[j] = PetscConj(-alphas[j]); 72505f80ce2aSJacob Faibussowitsch CHKERRQ(VecMAXPY(vecs[i],i,alphas,vecs)); 72515f80ce2aSJacob Faibussowitsch CHKERRQ(VecNormalize(vecs[i],&norm)); 725292cccca0SStefano Zampini if (norm < PETSC_SMALL) { 7253295df10fSStefano Zampini onorms[i] = 0.0; 72545f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(vecs[i],0.0)); 7255295df10fSStefano Zampini } else { 7256295df10fSStefano Zampini onorms[i] = norm; 725792cccca0SStefano Zampini } 72589a7d3425SStefano Zampini } 7259295df10fSStefano Zampini /* push nonzero vectors at the beginning */ 7260295df10fSStefano Zampini for (i=0;i<n;i++) { 7261295df10fSStefano Zampini if (onorms[i] == 0.0) { 7262295df10fSStefano Zampini for (j=i+1;j<n;j++) { 7263295df10fSStefano Zampini if (onorms[j] != 0.0) { 72645f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(vecs[j],vecs[i])); 7265295df10fSStefano Zampini onorms[j] = 0.0; 7266295df10fSStefano Zampini } 7267295df10fSStefano Zampini } 7268295df10fSStefano Zampini } 7269295df10fSStefano Zampini } 7270295df10fSStefano Zampini for (i=0,*nio=0;i<n;i++) *nio += onorms[i] != 0.0 ? 1 : 0; 72715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(alphas,onorms)); 72729a7d3425SStefano Zampini PetscFunctionReturn(0); 72739a7d3425SStefano Zampini } 72749a7d3425SStefano Zampini 7275bb360cb4SStefano Zampini PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void) 7276e7931f94SStefano Zampini { 7277e432b41dSStefano Zampini ISLocalToGlobalMapping mapping; 727857de7509SStefano Zampini Mat A; 7279e7931f94SStefano Zampini PetscInt n_neighs,*neighs,*n_shared,**shared; 7280e7931f94SStefano Zampini PetscMPIInt size,rank,color; 728152e5ac9dSStefano Zampini PetscInt *xadj,*adjncy; 728252e5ac9dSStefano Zampini PetscInt *adjncy_wgt,*v_wgt,*ranks_send_to_idx; 7283bb360cb4SStefano Zampini PetscInt im_active,active_procs,N,n,i,j,threshold = 2; 728457de7509SStefano Zampini PetscInt void_procs,*procs_candidates = NULL; 728527b6a85dSStefano Zampini PetscInt xadj_count,*count; 728627b6a85dSStefano Zampini PetscBool ismatis,use_vwgt=PETSC_FALSE; 728727b6a85dSStefano Zampini PetscSubcomm psubcomm; 728827b6a85dSStefano Zampini MPI_Comm subcomm; 7289a57a6d2fSStefano Zampini 7290e7931f94SStefano Zampini PetscFunctionBegin; 729157de7509SStefano Zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 72925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis)); 7293*28b400f6SJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",PETSC_FUNCTION_NAME); 729457de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat,*n_subdomains,2); 729557de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat,redprocs,3); 72962c71b3e2SJacob Faibussowitsch PetscCheckFalse(*n_subdomains <=0,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %D",*n_subdomains); 729757de7509SStefano Zampini 729857de7509SStefano Zampini if (have_void) *have_void = PETSC_FALSE; 72995f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size)); 73005f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank)); 73015f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(mat,&A)); 73025f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(A,&n,NULL)); 7303bb360cb4SStefano Zampini im_active = !!n; 73045f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat))); 730557de7509SStefano Zampini void_procs = size - active_procs; 730657de7509SStefano Zampini /* get ranks of of non-active processes in mat communicator */ 730757de7509SStefano Zampini if (void_procs) { 730857de7509SStefano Zampini PetscInt ncand; 730957de7509SStefano Zampini 731057de7509SStefano Zampini if (have_void) *have_void = PETSC_TRUE; 73115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size,&procs_candidates)); 73125f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat))); 731357de7509SStefano Zampini for (i=0,ncand=0;i<size;i++) { 731457de7509SStefano Zampini if (!procs_candidates[i]) { 731557de7509SStefano Zampini procs_candidates[ncand++] = i; 731657de7509SStefano Zampini } 731757de7509SStefano Zampini } 731857de7509SStefano Zampini /* force n_subdomains to be not greater that the number of non-active processes */ 731957de7509SStefano Zampini *n_subdomains = PetscMin(void_procs,*n_subdomains); 732057de7509SStefano Zampini } 732157de7509SStefano Zampini 7322bb360cb4SStefano Zampini /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix 73239dddd249SSatish Balay number of subdomains requested 1 -> send to rank-0 or first candidate in voids */ 73245f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(mat,&N,NULL)); 7325bb360cb4SStefano Zampini if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) { 732614f0bfb9SStefano Zampini PetscInt issize,isidx,dest; 732714f0bfb9SStefano Zampini if (*n_subdomains == 1) dest = 0; 732814f0bfb9SStefano Zampini else dest = rank; 732957de7509SStefano Zampini if (im_active) { 733057de7509SStefano Zampini issize = 1; 733157de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 733214f0bfb9SStefano Zampini isidx = procs_candidates[dest]; 733357de7509SStefano Zampini } else { 733414f0bfb9SStefano Zampini isidx = dest; 733557de7509SStefano Zampini } 733657de7509SStefano Zampini } else { 733757de7509SStefano Zampini issize = 0; 733857de7509SStefano Zampini isidx = -1; 733957de7509SStefano Zampini } 7340bb360cb4SStefano Zampini if (*n_subdomains != 1) *n_subdomains = active_procs; 73415f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends)); 73425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(procs_candidates)); 734357de7509SStefano Zampini PetscFunctionReturn(0); 734457de7509SStefano Zampini } 73455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL)); 73465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL)); 734727b6a85dSStefano Zampini threshold = PetscMax(threshold,2); 7348e7931f94SStefano Zampini 7349e7931f94SStefano Zampini /* Get info on mapping */ 73505f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalToGlobalMapping(mat,&mapping,NULL)); 73515f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetInfo(mapping,&n_neighs,&neighs,&n_shared,&shared)); 7352e7931f94SStefano Zampini 7353e7931f94SStefano Zampini /* build local CSR graph of subdomains' connectivity */ 73545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(2,&xadj)); 7355e7931f94SStefano Zampini xadj[0] = 0; 7356e7931f94SStefano Zampini xadj[1] = PetscMax(n_neighs-1,0); 73575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(xadj[1],&adjncy)); 73585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(xadj[1],&adjncy_wgt)); 73595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(n,&count)); 736027b6a85dSStefano Zampini for (i=1;i<n_neighs;i++) 736127b6a85dSStefano Zampini for (j=0;j<n_shared[i];j++) 736227b6a85dSStefano Zampini count[shared[i][j]] += 1; 7363e7931f94SStefano Zampini 736427b6a85dSStefano Zampini xadj_count = 0; 73652b510759SStefano Zampini for (i=1;i<n_neighs;i++) { 736627b6a85dSStefano Zampini for (j=0;j<n_shared[i];j++) { 736727b6a85dSStefano Zampini if (count[shared[i][j]] < threshold) { 7368d023bfaeSStefano Zampini adjncy[xadj_count] = neighs[i]; 7369d023bfaeSStefano Zampini adjncy_wgt[xadj_count] = n_shared[i]; 7370d023bfaeSStefano Zampini xadj_count++; 737127b6a85dSStefano Zampini break; 737227b6a85dSStefano Zampini } 7373e7931f94SStefano Zampini } 7374e7931f94SStefano Zampini } 7375d023bfaeSStefano Zampini xadj[1] = xadj_count; 73765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(count)); 73775f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreInfo(mapping,&n_neighs,&neighs,&n_shared,&shared)); 73785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt)); 7379e7931f94SStefano Zampini 73805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(1,&ranks_send_to_idx)); 7381e7931f94SStefano Zampini 738227b6a85dSStefano Zampini /* Restrict work on active processes only */ 73835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMPIIntCast(im_active,&color)); 738427b6a85dSStefano Zampini if (void_procs) { 73855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm)); 73865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSubcommSetNumber(psubcomm,2)); /* 2 groups, active process and not active processes */ 73875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSubcommSetTypeGeneral(psubcomm,color,rank)); 738827b6a85dSStefano Zampini subcomm = PetscSubcommChild(psubcomm); 738927b6a85dSStefano Zampini } else { 739027b6a85dSStefano Zampini psubcomm = NULL; 739127b6a85dSStefano Zampini subcomm = PetscObjectComm((PetscObject)mat); 739227b6a85dSStefano Zampini } 739327b6a85dSStefano Zampini 739427b6a85dSStefano Zampini v_wgt = NULL; 739527b6a85dSStefano Zampini if (!color) { 73965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(xadj)); 73975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adjncy)); 73985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adjncy_wgt)); 7399c8587f34SStefano Zampini } else { 740052e5ac9dSStefano Zampini Mat subdomain_adj; 740152e5ac9dSStefano Zampini IS new_ranks,new_ranks_contig; 740252e5ac9dSStefano Zampini MatPartitioning partitioner; 740327b6a85dSStefano Zampini PetscInt rstart=0,rend=0; 740452e5ac9dSStefano Zampini PetscInt *is_indices,*oldranks; 740557de7509SStefano Zampini PetscMPIInt size; 7406b0c7d250SStefano Zampini PetscBool aggregate; 7407b0c7d250SStefano Zampini 74085f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(subcomm,&size)); 740927b6a85dSStefano Zampini if (void_procs) { 741027b6a85dSStefano Zampini PetscInt prank = rank; 74115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size,&oldranks)); 74125f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm)); 7413e7931f94SStefano Zampini for (i=0;i<xadj[1];i++) { 74145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(adjncy[i],size,oldranks,&adjncy[i])); 7415c8587f34SStefano Zampini } 74165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt)); 741727b6a85dSStefano Zampini } else { 741827b6a85dSStefano Zampini oldranks = NULL; 741927b6a85dSStefano Zampini } 7420b0c7d250SStefano Zampini aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE); 742127b6a85dSStefano Zampini if (aggregate) { /* TODO: all this part could be made more efficient */ 7422b0c7d250SStefano Zampini PetscInt lrows,row,ncols,*cols; 7423b0c7d250SStefano Zampini PetscMPIInt nrank; 7424b0c7d250SStefano Zampini PetscScalar *vals; 7425b0c7d250SStefano Zampini 74265f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(subcomm,&nrank)); 7427b0c7d250SStefano Zampini lrows = 0; 7428b0c7d250SStefano Zampini if (nrank<redprocs) { 7429b0c7d250SStefano Zampini lrows = size/redprocs; 7430b0c7d250SStefano Zampini if (nrank<size%redprocs) lrows++; 7431b0c7d250SStefano Zampini } 74325f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj)); 74335f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(subdomain_adj,&rstart,&rend)); 74345f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE)); 74355f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE)); 7436b0c7d250SStefano Zampini row = nrank; 7437b0c7d250SStefano Zampini ncols = xadj[1]-xadj[0]; 7438b0c7d250SStefano Zampini cols = adjncy; 74395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(ncols,&vals)); 7440b0c7d250SStefano Zampini for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i]; 74415f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES)); 74425f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY)); 74435f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY)); 74445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(xadj)); 74455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adjncy)); 74465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adjncy_wgt)); 74475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vals)); 744827b6a85dSStefano Zampini if (use_vwgt) { 744927b6a85dSStefano Zampini Vec v; 745027b6a85dSStefano Zampini const PetscScalar *array; 745127b6a85dSStefano Zampini PetscInt nl; 745227b6a85dSStefano Zampini 74535f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(subdomain_adj,&v,NULL)); 74545f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(v,row,(PetscScalar)n,INSERT_VALUES)); 74555f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(v)); 74565f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(v)); 74575f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(v,&nl)); 74585f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(v,&array)); 74595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nl,&v_wgt)); 746022db5ddcSStefano Zampini for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]); 74615f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(v,&array)); 74625f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&v)); 746327b6a85dSStefano Zampini } 7464b0c7d250SStefano Zampini } else { 74655f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj)); 746627b6a85dSStefano Zampini if (use_vwgt) { 74675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(1,&v_wgt)); 7468bb360cb4SStefano Zampini v_wgt[0] = n; 746927b6a85dSStefano Zampini } 7470b0c7d250SStefano Zampini } 74715f80ce2aSJacob Faibussowitsch /* CHKERRQ(MatView(subdomain_adj,0)); */ 7472e7931f94SStefano Zampini 7473e7931f94SStefano Zampini /* Partition */ 74745f80ce2aSJacob Faibussowitsch CHKERRQ(MatPartitioningCreate(subcomm,&partitioner)); 7475ce64c636SStefano Zampini #if defined(PETSC_HAVE_PTSCOTCH) 74765f80ce2aSJacob Faibussowitsch CHKERRQ(MatPartitioningSetType(partitioner,MATPARTITIONINGPTSCOTCH)); 7477ce64c636SStefano Zampini #elif defined(PETSC_HAVE_PARMETIS) 74785f80ce2aSJacob Faibussowitsch CHKERRQ(MatPartitioningSetType(partitioner,MATPARTITIONINGPARMETIS)); 7479ce64c636SStefano Zampini #else 74805f80ce2aSJacob Faibussowitsch CHKERRQ(MatPartitioningSetType(partitioner,MATPARTITIONINGAVERAGE)); 7481ce64c636SStefano Zampini #endif 74825f80ce2aSJacob Faibussowitsch CHKERRQ(MatPartitioningSetAdjacency(partitioner,subdomain_adj)); 748327b6a85dSStefano Zampini if (v_wgt) { 74845f80ce2aSJacob Faibussowitsch CHKERRQ(MatPartitioningSetVertexWeights(partitioner,v_wgt)); 7485c8587f34SStefano Zampini } 748657de7509SStefano Zampini *n_subdomains = PetscMin((PetscInt)size,*n_subdomains); 74875f80ce2aSJacob Faibussowitsch CHKERRQ(MatPartitioningSetNParts(partitioner,*n_subdomains)); 74885f80ce2aSJacob Faibussowitsch CHKERRQ(MatPartitioningSetFromOptions(partitioner)); 74895f80ce2aSJacob Faibussowitsch CHKERRQ(MatPartitioningApply(partitioner,&new_ranks)); 74905f80ce2aSJacob Faibussowitsch /* CHKERRQ(MatPartitioningView(partitioner,0)); */ 7491e7931f94SStefano Zampini 749252e5ac9dSStefano Zampini /* renumber new_ranks to avoid "holes" in new set of processors */ 74935f80ce2aSJacob Faibussowitsch CHKERRQ(ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig)); 74945f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&new_ranks)); 74955f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices)); 749657de7509SStefano Zampini if (!aggregate) { 749757de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 74986bdcaf15SBarry Smith PetscAssert(oldranks,PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen"); 749957de7509SStefano Zampini ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]]; 750027b6a85dSStefano Zampini } else if (oldranks) { 7501b0c7d250SStefano Zampini ranks_send_to_idx[0] = oldranks[is_indices[0]]; 750227b6a85dSStefano Zampini } else { 750327b6a85dSStefano Zampini ranks_send_to_idx[0] = is_indices[0]; 750457de7509SStefano Zampini } 750528143c3dSStefano Zampini } else { 75067fb8a5e4SKarl Rupp PetscInt idx = 0; 7507b0c7d250SStefano Zampini PetscMPIInt tag; 7508b0c7d250SStefano Zampini MPI_Request *reqs; 7509b0c7d250SStefano Zampini 75105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag)); 75115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(rend-rstart,&reqs)); 7512b0c7d250SStefano Zampini for (i=rstart;i<rend;i++) { 75135f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart])); 751428143c3dSStefano Zampini } 75155f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Recv(&idx,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE)); 75165f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE)); 75175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(reqs)); 751857de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 75196bdcaf15SBarry Smith PetscAssert(oldranks,PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen"); 75207fb8a5e4SKarl Rupp ranks_send_to_idx[0] = procs_candidates[oldranks[idx]]; 752127b6a85dSStefano Zampini } else if (oldranks) { 75227fb8a5e4SKarl Rupp ranks_send_to_idx[0] = oldranks[idx]; 752327b6a85dSStefano Zampini } else { 75247fb8a5e4SKarl Rupp ranks_send_to_idx[0] = idx; 7525e7931f94SStefano Zampini } 752657de7509SStefano Zampini } 75275f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices)); 7528e7931f94SStefano Zampini /* clean up */ 75295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(oldranks)); 75305f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&new_ranks_contig)); 75315f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&subdomain_adj)); 75325f80ce2aSJacob Faibussowitsch CHKERRQ(MatPartitioningDestroy(&partitioner)); 7533e7931f94SStefano Zampini } 75345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSubcommDestroy(&psubcomm)); 75355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(procs_candidates)); 7536e7931f94SStefano Zampini 7537e7931f94SStefano Zampini /* assemble parallel IS for sends */ 7538e7931f94SStefano Zampini i = 1; 753927b6a85dSStefano Zampini if (!color) i=0; 75405f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends)); 7541e7931f94SStefano Zampini PetscFunctionReturn(0); 7542e7931f94SStefano Zampini } 7543e7931f94SStefano Zampini 7544e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate; 7545e7931f94SStefano Zampini 75461e0482f5SStefano Zampini PetscErrorCode PCBDDCMatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, PetscBool restrict_full, PetscBool reuse, Mat *mat_n, PetscInt nis, IS isarray[], PetscInt nvecs, Vec nnsp_vec[]) 7547e7931f94SStefano Zampini { 754870cf5478SStefano Zampini Mat local_mat; 7549e7931f94SStefano Zampini IS is_sends_internal; 75509d30be91SStefano Zampini PetscInt rows,cols,new_local_rows; 75511ae86dd6SStefano Zampini PetscInt i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs; 75529d30be91SStefano Zampini PetscBool ismatis,isdense,newisdense,destroy_mat; 7553e7931f94SStefano Zampini ISLocalToGlobalMapping l2gmap; 7554e7931f94SStefano Zampini PetscInt* l2gmap_indices; 7555e7931f94SStefano Zampini const PetscInt* is_indices; 7556e7931f94SStefano Zampini MatType new_local_type; 7557e7931f94SStefano Zampini /* buffers */ 7558e7931f94SStefano Zampini PetscInt *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs; 755928143c3dSStefano Zampini PetscInt *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is; 75609d30be91SStefano Zampini PetscInt *recv_buffer_idxs_local; 75611683a169SBarry Smith PetscScalar *ptr_vals,*recv_buffer_vals; 75621683a169SBarry Smith const PetscScalar *send_buffer_vals; 75631ae86dd6SStefano Zampini PetscScalar *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs; 7564e7931f94SStefano Zampini /* MPI */ 756528143c3dSStefano Zampini MPI_Comm comm,comm_n; 756628143c3dSStefano Zampini PetscSubcomm subcomm; 7567e569e4e1SStefano Zampini PetscMPIInt n_sends,n_recvs,size; 756828143c3dSStefano Zampini PetscMPIInt *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is; 756928143c3dSStefano Zampini PetscMPIInt *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals; 75701ae86dd6SStefano Zampini PetscMPIInt len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest; 75711ae86dd6SStefano Zampini MPI_Request *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs; 75721ae86dd6SStefano Zampini MPI_Request *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs; 7573e7931f94SStefano Zampini 7574e7931f94SStefano Zampini PetscFunctionBegin; 757557de7509SStefano Zampini PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 75765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis)); 75775f80ce2aSJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",PETSC_FUNCTION_NAME); 757857de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat,n_subdomains,3); 757957de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat,restrict_comm,4); 758057de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat,restrict_full,5); 758157de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat,reuse,6); 758257de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat,nis,8); 75831ae86dd6SStefano Zampini PetscValidLogicalCollectiveInt(mat,nvecs,10); 75841ae86dd6SStefano Zampini if (nvecs) { 75852c71b3e2SJacob Faibussowitsch PetscCheckFalse(nvecs > 1,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported"); 75861ae86dd6SStefano Zampini PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11); 75871ae86dd6SStefano Zampini } 758857de7509SStefano Zampini /* further checks */ 75895f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(mat,&local_mat)); 75905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense)); 75915f80ce2aSJacob Faibussowitsch PetscCheck(isdense,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE"); 75925f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(local_mat,&rows,&cols)); 75935f80ce2aSJacob Faibussowitsch PetscCheck(rows == cols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square"); 759457de7509SStefano Zampini if (reuse && *mat_n) { 759570cf5478SStefano Zampini PetscInt mrows,mcols,mnrows,mncols; 759657de7509SStefano Zampini PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7); 75975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis)); 75985f80ce2aSJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS"); 75995f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(mat,&mrows,&mcols)); 76005f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(*mat_n,&mnrows,&mncols)); 76015f80ce2aSJacob Faibussowitsch PetscCheck(mrows == mnrows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows); 76025f80ce2aSJacob Faibussowitsch PetscCheck(mcols == mncols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols); 760370cf5478SStefano Zampini } 76045f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetBlockSize(local_mat,&bs)); 7605064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(mat,bs,1); 760657de7509SStefano Zampini 7607e7931f94SStefano Zampini /* prepare IS for sending if not provided */ 7608e7931f94SStefano Zampini if (!is_sends) { 76095f80ce2aSJacob Faibussowitsch PetscCheck(n_subdomains,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains"); 76105f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCMatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL)); 7611c8587f34SStefano Zampini } else { 76125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)is_sends)); 7613e7931f94SStefano Zampini is_sends_internal = is_sends; 7614c8587f34SStefano Zampini } 7615e7931f94SStefano Zampini 7616e7931f94SStefano Zampini /* get comm */ 76175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)mat,&comm)); 7618e7931f94SStefano Zampini 7619e7931f94SStefano Zampini /* compute number of sends */ 76205f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(is_sends_internal,&i)); 76215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMPIIntCast(i,&n_sends)); 7622e7931f94SStefano Zampini 7623e7931f94SStefano Zampini /* compute number of receives */ 76245f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm,&size)); 76255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size,&iflags)); 76265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(iflags,size)); 76275f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(is_sends_internal,&is_indices)); 7628e7931f94SStefano Zampini for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1; 76295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs)); 76305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(iflags)); 7631e7931f94SStefano Zampini 763228143c3dSStefano Zampini /* restrict comm if requested */ 76330a545947SLisandro Dalcin subcomm = NULL; 763428143c3dSStefano Zampini destroy_mat = PETSC_FALSE; 763528143c3dSStefano Zampini if (restrict_comm) { 7636779c1cceSStefano Zampini PetscMPIInt color,subcommsize; 7637779c1cceSStefano Zampini 763828143c3dSStefano Zampini color = 0; 763953a05cb3SStefano Zampini if (restrict_full) { 764053a05cb3SStefano Zampini if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */ 764153a05cb3SStefano Zampini } else { 764253a05cb3SStefano Zampini if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */ 764353a05cb3SStefano Zampini } 76445f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm)); 7645e569e4e1SStefano Zampini subcommsize = size - subcommsize; 764628143c3dSStefano Zampini /* check if reuse has been requested */ 764757de7509SStefano Zampini if (reuse) { 764828143c3dSStefano Zampini if (*mat_n) { 764928143c3dSStefano Zampini PetscMPIInt subcommsize2; 76505f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2)); 76515f80ce2aSJacob Faibussowitsch PetscCheck(subcommsize == subcommsize2,PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2); 765228143c3dSStefano Zampini comm_n = PetscObjectComm((PetscObject)*mat_n); 765328143c3dSStefano Zampini } else { 765428143c3dSStefano Zampini comm_n = PETSC_COMM_SELF; 765528143c3dSStefano Zampini } 765628143c3dSStefano Zampini } else { /* MAT_INITIAL_MATRIX */ 7657779c1cceSStefano Zampini PetscMPIInt rank; 7658779c1cceSStefano Zampini 76595f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm,&rank)); 76605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSubcommCreate(comm,&subcomm)); 76615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSubcommSetNumber(subcomm,2)); 76625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSubcommSetTypeGeneral(subcomm,color,rank)); 7663306c2d5bSBarry Smith comm_n = PetscSubcommChild(subcomm); 766428143c3dSStefano Zampini } 766528143c3dSStefano Zampini /* flag to destroy *mat_n if not significative */ 766628143c3dSStefano Zampini if (color) destroy_mat = PETSC_TRUE; 766728143c3dSStefano Zampini } else { 766828143c3dSStefano Zampini comm_n = comm; 766928143c3dSStefano Zampini } 767028143c3dSStefano Zampini 7671e7931f94SStefano Zampini /* prepare send/receive buffers */ 76725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size,&ilengths_idxs)); 76735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(ilengths_idxs,size)); 76745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size,&ilengths_vals)); 76755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(ilengths_vals,size)); 767628143c3dSStefano Zampini if (nis) { 76775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(size,&ilengths_idxs_is)); 767828143c3dSStefano Zampini } 7679e7931f94SStefano Zampini 768028143c3dSStefano Zampini /* Get data from local matrices */ 7681e432b41dSStefano Zampini PetscCheck(isdense,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented"); 7682e7931f94SStefano Zampini /* TODO: See below some guidelines on how to prepare the local buffers */ 7683e7931f94SStefano Zampini /* 7684e7931f94SStefano Zampini send_buffer_vals should contain the raw values of the local matrix 7685e7931f94SStefano Zampini send_buffer_idxs should contain: 7686e7931f94SStefano Zampini - MatType_PRIVATE type 7687e7931f94SStefano Zampini - PetscInt size_of_l2gmap 7688e7931f94SStefano Zampini - PetscInt global_row_indices[size_of_l2gmap] 7689e7931f94SStefano Zampini - PetscInt all_other_info_which_is_needed_to_compute_preallocation_and_set_values 7690e7931f94SStefano Zampini */ 7691e432b41dSStefano Zampini { 7692e432b41dSStefano Zampini ISLocalToGlobalMapping mapping; 7693e432b41dSStefano Zampini 76945f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalToGlobalMapping(mat,&mapping,NULL)); 76955f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(local_mat,&send_buffer_vals)); 76965f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetSize(mapping,&i)); 76975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(i+2,&send_buffer_idxs)); 7698e7931f94SStefano Zampini send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE; 7699e7931f94SStefano Zampini send_buffer_idxs[1] = i; 77005f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetIndices(mapping,(const PetscInt**)&ptr_idxs)); 77015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(&send_buffer_idxs[2],ptr_idxs,i)); 77025f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreIndices(mapping,(const PetscInt**)&ptr_idxs)); 77035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMPIIntCast(i,&len)); 7704e7931f94SStefano Zampini for (i=0;i<n_sends;i++) { 7705e7931f94SStefano Zampini ilengths_vals[is_indices[i]] = len*len; 7706e7931f94SStefano Zampini ilengths_idxs[is_indices[i]] = len+2; 7707c8587f34SStefano Zampini } 7708c8587f34SStefano Zampini } 77095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals)); 771028143c3dSStefano Zampini /* additional is (if any) */ 771128143c3dSStefano Zampini if (nis) { 771228143c3dSStefano Zampini PetscMPIInt psum; 771328143c3dSStefano Zampini PetscInt j; 771428143c3dSStefano Zampini for (j=0,psum=0;j<nis;j++) { 771528143c3dSStefano Zampini PetscInt plen; 77165f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(isarray[j],&plen)); 77175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMPIIntCast(plen,&len)); 771828143c3dSStefano Zampini psum += len+1; /* indices + lenght */ 771928143c3dSStefano Zampini } 77205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(psum,&send_buffer_idxs_is)); 772128143c3dSStefano Zampini for (j=0,psum=0;j<nis;j++) { 772228143c3dSStefano Zampini PetscInt plen; 772328143c3dSStefano Zampini const PetscInt *is_array_idxs; 77245f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(isarray[j],&plen)); 772528143c3dSStefano Zampini send_buffer_idxs_is[psum] = plen; 77265f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(isarray[j],&is_array_idxs)); 77275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen)); 77285f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(isarray[j],&is_array_idxs)); 772928143c3dSStefano Zampini psum += plen+1; /* indices + lenght */ 773028143c3dSStefano Zampini } 773128143c3dSStefano Zampini for (i=0;i<n_sends;i++) { 773228143c3dSStefano Zampini ilengths_idxs_is[is_indices[i]] = psum; 773328143c3dSStefano Zampini } 77345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is)); 773528143c3dSStefano Zampini } 77365f80ce2aSJacob Faibussowitsch CHKERRQ(MatISRestoreLocalMat(mat,&local_mat)); 773728143c3dSStefano Zampini 7738e7931f94SStefano Zampini buf_size_idxs = 0; 7739e7931f94SStefano Zampini buf_size_vals = 0; 774028143c3dSStefano Zampini buf_size_idxs_is = 0; 77411ae86dd6SStefano Zampini buf_size_vecs = 0; 7742e7931f94SStefano Zampini for (i=0;i<n_recvs;i++) { 7743e7931f94SStefano Zampini buf_size_idxs += (PetscInt)olengths_idxs[i]; 7744e7931f94SStefano Zampini buf_size_vals += (PetscInt)olengths_vals[i]; 774528143c3dSStefano Zampini if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i]; 77461ae86dd6SStefano Zampini if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i]; 7747e7931f94SStefano Zampini } 77485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(buf_size_idxs,&recv_buffer_idxs)); 77495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(buf_size_vals,&recv_buffer_vals)); 77505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is)); 77515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(buf_size_vecs,&recv_buffer_vecs)); 7752e7931f94SStefano Zampini 7753e7931f94SStefano Zampini /* get new tags for clean communications */ 77545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetNewTag((PetscObject)mat,&tag_idxs)); 77555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetNewTag((PetscObject)mat,&tag_vals)); 77565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is)); 77575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetNewTag((PetscObject)mat,&tag_vecs)); 7758e7931f94SStefano Zampini 7759e7931f94SStefano Zampini /* allocate for requests */ 77605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n_sends,&send_req_idxs)); 77615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n_sends,&send_req_vals)); 77625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n_sends,&send_req_idxs_is)); 77635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n_sends,&send_req_vecs)); 77645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n_recvs,&recv_req_idxs)); 77655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n_recvs,&recv_req_vals)); 77665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n_recvs,&recv_req_idxs_is)); 77675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n_recvs,&recv_req_vecs)); 7768e7931f94SStefano Zampini 7769e7931f94SStefano Zampini /* communications */ 7770e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 7771e7931f94SStefano Zampini ptr_vals = recv_buffer_vals; 777228143c3dSStefano Zampini ptr_idxs_is = recv_buffer_idxs_is; 77731ae86dd6SStefano Zampini ptr_vecs = recv_buffer_vecs; 7774e7931f94SStefano Zampini for (i=0;i<n_recvs;i++) { 7775e7931f94SStefano Zampini source_dest = onodes[i]; 77765f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i])); 77775f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i])); 7778e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7779e7931f94SStefano Zampini ptr_vals += olengths_vals[i]; 778028143c3dSStefano Zampini if (nis) { 778157de7509SStefano Zampini source_dest = onodes_is[i]; 77825f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Irecv(ptr_idxs_is,olengths_idxs_is[i],MPIU_INT,source_dest,tag_idxs_is,comm,&recv_req_idxs_is[i])); 778328143c3dSStefano Zampini ptr_idxs_is += olengths_idxs_is[i]; 778428143c3dSStefano Zampini } 77851ae86dd6SStefano Zampini if (nvecs) { 77861ae86dd6SStefano Zampini source_dest = onodes[i]; 77875f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i])); 77881ae86dd6SStefano Zampini ptr_vecs += olengths_idxs[i]-2; 77891ae86dd6SStefano Zampini } 7790e7931f94SStefano Zampini } 7791e7931f94SStefano Zampini for (i=0;i<n_sends;i++) { 77925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMPIIntCast(is_indices[i],&source_dest)); 77935f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i])); 77945f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Isend((PetscScalar*)send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i])); 779528143c3dSStefano Zampini if (nis) { 77965f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Isend(send_buffer_idxs_is,ilengths_idxs_is[source_dest],MPIU_INT,source_dest,tag_idxs_is,comm,&send_req_idxs_is[i])); 779728143c3dSStefano Zampini } 77981ae86dd6SStefano Zampini if (nvecs) { 77995f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(nnsp_vec[0],&send_buffer_vecs)); 78005f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Isend(send_buffer_vecs,ilengths_idxs[source_dest]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&send_req_vecs[i])); 78011ae86dd6SStefano Zampini } 7802e7931f94SStefano Zampini } 78035f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(is_sends_internal,&is_indices)); 78045f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is_sends_internal)); 7805e7931f94SStefano Zampini 7806e7931f94SStefano Zampini /* assemble new l2g map */ 78075f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE)); 7808e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 78099d30be91SStefano Zampini new_local_rows = 0; 7810e7931f94SStefano Zampini for (i=0;i<n_recvs;i++) { 78119d30be91SStefano Zampini new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */ 7812e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7813e7931f94SStefano Zampini } 78145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(new_local_rows,&l2gmap_indices)); 7815e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 78169d30be91SStefano Zampini new_local_rows = 0; 7817e7931f94SStefano Zampini for (i=0;i<n_recvs;i++) { 78185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,*(ptr_idxs+1))); 78199d30be91SStefano Zampini new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */ 7820e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7821e7931f94SStefano Zampini } 78225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices)); 78235f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap)); 78245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(l2gmap_indices)); 7825e7931f94SStefano Zampini 7826e7931f94SStefano Zampini /* infer new local matrix type from received local matrices type */ 7827e7931f94SStefano Zampini /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */ 7828e7931f94SStefano Zampini /* it also assumes that if the block size is set, than it is the same among all local matrices (see checks at the beginning of the function) */ 7829e7931f94SStefano Zampini if (n_recvs) { 783028143c3dSStefano Zampini MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0]; 7831e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 7832e7931f94SStefano Zampini for (i=0;i<n_recvs;i++) { 7833e7931f94SStefano Zampini if ((PetscInt)new_local_type_private != *ptr_idxs) { 7834e7931f94SStefano Zampini new_local_type_private = MATAIJ_PRIVATE; 7835e7931f94SStefano Zampini break; 7836e7931f94SStefano Zampini } 7837e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7838e7931f94SStefano Zampini } 7839e7931f94SStefano Zampini switch (new_local_type_private) { 784028143c3dSStefano Zampini case MATDENSE_PRIVATE: 7841e7931f94SStefano Zampini new_local_type = MATSEQAIJ; 7842e7931f94SStefano Zampini bs = 1; 7843e7931f94SStefano Zampini break; 7844e7931f94SStefano Zampini case MATAIJ_PRIVATE: 7845e7931f94SStefano Zampini new_local_type = MATSEQAIJ; 7846e7931f94SStefano Zampini bs = 1; 7847e7931f94SStefano Zampini break; 7848e7931f94SStefano Zampini case MATBAIJ_PRIVATE: 7849e7931f94SStefano Zampini new_local_type = MATSEQBAIJ; 7850e7931f94SStefano Zampini break; 7851e7931f94SStefano Zampini case MATSBAIJ_PRIVATE: 7852e7931f94SStefano Zampini new_local_type = MATSEQSBAIJ; 7853e7931f94SStefano Zampini break; 7854e7931f94SStefano Zampini default: 785598921bdaSJacob Faibussowitsch SETERRQ(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,PETSC_FUNCTION_NAME); 7856e7931f94SStefano Zampini } 7857ed8ed4edSstefano_zampini } else { /* by default, new_local_type is seqaij */ 7858ed8ed4edSstefano_zampini new_local_type = MATSEQAIJ; 785928143c3dSStefano Zampini bs = 1; 7860e7931f94SStefano Zampini } 7861e7931f94SStefano Zampini 786270cf5478SStefano Zampini /* create MATIS object if needed */ 786357de7509SStefano Zampini if (!reuse) { 78645f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(mat,&rows,&cols)); 78655f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,l2gmap,mat_n)); 786670cf5478SStefano Zampini } else { 786770cf5478SStefano Zampini /* it also destroys the local matrices */ 786857de7509SStefano Zampini if (*mat_n) { 78695f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap)); 787057de7509SStefano Zampini } else { /* this is a fake object */ 78715f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,l2gmap,mat_n)); 787257de7509SStefano Zampini } 787370cf5478SStefano Zampini } 78745f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(*mat_n,&local_mat)); 78755f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(local_mat,new_local_type)); 78769d30be91SStefano Zampini 78775f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE)); 78789d30be91SStefano Zampini 78799d30be91SStefano Zampini /* Global to local map of received indices */ 78805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local)); /* needed for values insertion */ 78815f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local)); 78825f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&l2gmap)); 78839d30be91SStefano Zampini 78849d30be91SStefano Zampini /* restore attributes -> type of incoming data and its size */ 78859d30be91SStefano Zampini buf_size_idxs = 0; 78869d30be91SStefano Zampini for (i=0;i<n_recvs;i++) { 78879d30be91SStefano Zampini recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs]; 78889d30be91SStefano Zampini recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1]; 78899d30be91SStefano Zampini buf_size_idxs += (PetscInt)olengths_idxs[i]; 78909d30be91SStefano Zampini } 78915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(recv_buffer_idxs)); 78929d30be91SStefano Zampini 78939d30be91SStefano Zampini /* set preallocation */ 78945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense)); 78959d30be91SStefano Zampini if (!newisdense) { 78960a545947SLisandro Dalcin PetscInt *new_local_nnz=NULL; 78979d30be91SStefano Zampini 78989d30be91SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 78999d30be91SStefano Zampini if (n_recvs) { 79005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(new_local_rows,&new_local_nnz)); 79019d30be91SStefano Zampini } 79029d30be91SStefano Zampini for (i=0;i<n_recvs;i++) { 79039d30be91SStefano Zampini PetscInt j; 79049d30be91SStefano Zampini if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */ 79059d30be91SStefano Zampini for (j=0;j<*(ptr_idxs+1);j++) { 79069d30be91SStefano Zampini new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1); 79079d30be91SStefano Zampini } 79089d30be91SStefano Zampini } else { 79099d30be91SStefano Zampini /* TODO */ 79109d30be91SStefano Zampini } 79119d30be91SStefano Zampini ptr_idxs += olengths_idxs[i]; 79129d30be91SStefano Zampini } 79139d30be91SStefano Zampini if (new_local_nnz) { 79149d30be91SStefano Zampini for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows); 79155f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz)); 79169d30be91SStefano Zampini for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs; 79175f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz)); 79189d30be91SStefano Zampini for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0); 79195f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz)); 79209d30be91SStefano Zampini } else { 79215f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetUp(local_mat)); 79229d30be91SStefano Zampini } 79235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(new_local_nnz)); 79249d30be91SStefano Zampini } else { 79255f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetUp(local_mat)); 79269d30be91SStefano Zampini } 7927e7931f94SStefano Zampini 7928e7931f94SStefano Zampini /* set values */ 7929e7931f94SStefano Zampini ptr_vals = recv_buffer_vals; 79309d30be91SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 7931e7931f94SStefano Zampini for (i=0;i<n_recvs;i++) { 7932e7931f94SStefano Zampini if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */ 79335f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE)); 79345f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES)); 79355f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY)); 79365f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY)); 79375f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE)); 793828143c3dSStefano Zampini } else { 793928143c3dSStefano Zampini /* TODO */ 7940e7931f94SStefano Zampini } 7941e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7942e7931f94SStefano Zampini ptr_vals += olengths_vals[i]; 7943e7931f94SStefano Zampini } 79445f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY)); 79455f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY)); 79465f80ce2aSJacob Faibussowitsch CHKERRQ(MatISRestoreLocalMat(*mat_n,&local_mat)); 79475f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY)); 79485f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY)); 79495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(recv_buffer_vals)); 7950e7931f94SStefano Zampini 7951dfd14d43SStefano Zampini #if 0 795228143c3dSStefano Zampini if (!restrict_comm) { /* check */ 7953e7931f94SStefano Zampini Vec lvec,rvec; 7954e7931f94SStefano Zampini PetscReal infty_error; 7955e7931f94SStefano Zampini 79565f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(mat,&rvec,&lvec)); 79575f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetRandom(rvec,NULL)); 79585f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(mat,rvec,lvec)); 79595f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(lvec,-1.0)); 79605f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultAdd(*mat_n,rvec,lvec,lvec)); 79615f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(lvec,NORM_INFINITY,&infty_error)); 79625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error)); 79635f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&rvec)); 79645f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&lvec)); 7965e7931f94SStefano Zampini } 796628143c3dSStefano Zampini #endif 7967e7931f94SStefano Zampini 796828143c3dSStefano Zampini /* assemble new additional is (if any) */ 796928143c3dSStefano Zampini if (nis) { 797028143c3dSStefano Zampini PetscInt **temp_idxs,*count_is,j,psum; 797128143c3dSStefano Zampini 79725f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE)); 79735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(nis,&count_is)); 797428143c3dSStefano Zampini ptr_idxs = recv_buffer_idxs_is; 797528143c3dSStefano Zampini psum = 0; 797628143c3dSStefano Zampini for (i=0;i<n_recvs;i++) { 797728143c3dSStefano Zampini for (j=0;j<nis;j++) { 797828143c3dSStefano Zampini PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */ 797928143c3dSStefano Zampini count_is[j] += plen; /* increment counting of buffer for j-th IS */ 798028143c3dSStefano Zampini psum += plen; 798128143c3dSStefano Zampini ptr_idxs += plen+1; /* shift pointer to received data */ 798228143c3dSStefano Zampini } 798328143c3dSStefano Zampini } 79845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nis,&temp_idxs)); 79855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(psum,&temp_idxs[0])); 798628143c3dSStefano Zampini for (i=1;i<nis;i++) { 798728143c3dSStefano Zampini temp_idxs[i] = temp_idxs[i-1]+count_is[i-1]; 798828143c3dSStefano Zampini } 79895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(count_is,nis)); 799028143c3dSStefano Zampini ptr_idxs = recv_buffer_idxs_is; 799128143c3dSStefano Zampini for (i=0;i<n_recvs;i++) { 799228143c3dSStefano Zampini for (j=0;j<nis;j++) { 799328143c3dSStefano Zampini PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */ 79945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen)); 799528143c3dSStefano Zampini count_is[j] += plen; /* increment starting point of buffer for j-th IS */ 799628143c3dSStefano Zampini ptr_idxs += plen+1; /* shift pointer to received data */ 799728143c3dSStefano Zampini } 799828143c3dSStefano Zampini } 799928143c3dSStefano Zampini for (i=0;i<nis;i++) { 80005f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&isarray[i])); 80015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i])); 80025f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i])); 800328143c3dSStefano Zampini } 80045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(count_is)); 80055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(temp_idxs[0])); 80065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(temp_idxs)); 800728143c3dSStefano Zampini } 8008e7931f94SStefano Zampini /* free workspace */ 80095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(recv_buffer_idxs_is)); 80105f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE)); 80115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(send_buffer_idxs)); 80125f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE)); 8013e7931f94SStefano Zampini if (isdense) { 80145f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(mat,&local_mat)); 80155f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(local_mat,&send_buffer_vals)); 80165f80ce2aSJacob Faibussowitsch CHKERRQ(MatISRestoreLocalMat(mat,&local_mat)); 8017e7931f94SStefano Zampini } else { 80185f80ce2aSJacob Faibussowitsch /* CHKERRQ(PetscFree(send_buffer_vals)); */ 8019e7931f94SStefano Zampini } 802028143c3dSStefano Zampini if (nis) { 80215f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE)); 80225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(send_buffer_idxs_is)); 802328143c3dSStefano Zampini } 80241ae86dd6SStefano Zampini 80251ae86dd6SStefano Zampini if (nvecs) { 80265f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE)); 80275f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE)); 80285f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(nnsp_vec[0],&send_buffer_vecs)); 80295f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&nnsp_vec[0])); 80305f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(comm_n,&nnsp_vec[0])); 80315f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE)); 80325f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(nnsp_vec[0],VECSTANDARD)); 80331ae86dd6SStefano Zampini /* set values */ 80341ae86dd6SStefano Zampini ptr_vals = recv_buffer_vecs; 80351ae86dd6SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 80365f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(nnsp_vec[0],&send_buffer_vecs)); 80371ae86dd6SStefano Zampini for (i=0;i<n_recvs;i++) { 80381ae86dd6SStefano Zampini PetscInt j; 80391ae86dd6SStefano Zampini for (j=0;j<*(ptr_idxs+1);j++) { 80401ae86dd6SStefano Zampini send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j); 80411ae86dd6SStefano Zampini } 80421ae86dd6SStefano Zampini ptr_idxs += olengths_idxs[i]; 80431ae86dd6SStefano Zampini ptr_vals += olengths_idxs[i]-2; 80441ae86dd6SStefano Zampini } 80455f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(nnsp_vec[0],&send_buffer_vecs)); 80465f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(nnsp_vec[0])); 80475f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(nnsp_vec[0])); 80481ae86dd6SStefano Zampini } 80491ae86dd6SStefano Zampini 80505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(recv_buffer_vecs)); 80515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(recv_buffer_idxs_local)); 80525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(recv_req_idxs)); 80535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(recv_req_vals)); 80545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(recv_req_vecs)); 80555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(recv_req_idxs_is)); 80565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(send_req_idxs)); 80575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(send_req_vals)); 80585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(send_req_vecs)); 80595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(send_req_idxs_is)); 80605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ilengths_vals)); 80615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ilengths_idxs)); 80625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(olengths_vals)); 80635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(olengths_idxs)); 80645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(onodes)); 806528143c3dSStefano Zampini if (nis) { 80665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ilengths_idxs_is)); 80675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(olengths_idxs_is)); 80685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(onodes_is)); 806928143c3dSStefano Zampini } 80705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSubcommDestroy(&subcomm)); 807128143c3dSStefano Zampini if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */ 80725f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(mat_n)); 807328143c3dSStefano Zampini for (i=0;i<nis;i++) { 80745f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&isarray[i])); 807528143c3dSStefano Zampini } 80761ae86dd6SStefano Zampini if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */ 80775f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&nnsp_vec[0])); 80781ae86dd6SStefano Zampini } 807953a05cb3SStefano Zampini *mat_n = NULL; 808028143c3dSStefano Zampini } 8081e7931f94SStefano Zampini PetscFunctionReturn(0); 8082e7931f94SStefano Zampini } 8083a57a6d2fSStefano Zampini 808412edc857SStefano Zampini /* temporary hack into ksp private data structure */ 8085af0996ceSBarry Smith #include <petsc/private/kspimpl.h> 808612edc857SStefano Zampini 8087c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals) 8088c8587f34SStefano Zampini { 8089c8587f34SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 8090c8587f34SStefano Zampini PC_IS *pcis = (PC_IS*)pc->data; 809120a2ab83SStefano Zampini Mat coarse_mat,coarse_mat_is,coarse_submat_dense; 80921ae86dd6SStefano Zampini Mat coarsedivudotp = NULL; 80931e0482f5SStefano Zampini Mat coarseG,t_coarse_mat_is; 80949881197aSStefano Zampini MatNullSpace CoarseNullSpace = NULL; 809520a2ab83SStefano Zampini ISLocalToGlobalMapping coarse_islg; 80964f819b78SStefano Zampini IS coarse_is,*isarray,corners; 80976e683305SStefano Zampini PetscInt i,im_active=-1,active_procs=-1; 809830368db7SStefano Zampini PetscInt nis,nisdofs,nisneu,nisvert; 8099e569e4e1SStefano Zampini PetscInt coarse_eqs_per_proc; 8100f9eb5b7dSStefano Zampini PC pc_temp; 8101c8587f34SStefano Zampini PCType coarse_pc_type; 8102c8587f34SStefano Zampini KSPType coarse_ksp_type; 8103f9eb5b7dSStefano Zampini PetscBool multilevel_requested,multilevel_allowed; 81047274672aSStefano Zampini PetscBool coarse_reuse; 81051e0482f5SStefano Zampini PetscInt ncoarse,nedcfield; 810668457ee5SStefano Zampini PetscBool compute_vecs = PETSC_FALSE; 810722bc73bbSStefano Zampini PetscScalar *array; 810857de7509SStefano Zampini MatReuse coarse_mat_reuse; 810957de7509SStefano Zampini PetscBool restr, full_restr, have_void; 8110e569e4e1SStefano Zampini PetscMPIInt size; 81119881197aSStefano Zampini PetscErrorCode ierr; 8112fdc09c96SStefano Zampini 8113c8587f34SStefano Zampini PetscFunctionBegin; 81145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0)); 8115c8587f34SStefano Zampini /* Assign global numbering to coarse dofs */ 811668457ee5SStefano Zampini if (pcbddc->new_primal_space || pcbddc->coarse_size == -1) { /* a new primal space is present or it is the first initialization, so recompute global numbering */ 8117fa7f1dd8SStefano Zampini PetscInt ocoarse_size; 81185a75c04eSSatish Balay compute_vecs = PETSC_TRUE; 81197de4f681Sstefano_zampini 81207de4f681Sstefano_zampini pcbddc->new_primal_space = PETSC_TRUE; 8121fa7f1dd8SStefano Zampini ocoarse_size = pcbddc->coarse_size; 81225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddc->global_primal_indices)); 81235f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices)); 8124f4ddd8eeSStefano Zampini /* see if we can avoid some work */ 8125fa7f1dd8SStefano Zampini if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */ 812651bea450SStefano Zampini /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */ 812751bea450SStefano Zampini if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) { 81285f80ce2aSJacob Faibussowitsch CHKERRQ(KSPReset(pcbddc->coarse_ksp)); 8129fa7f1dd8SStefano Zampini coarse_reuse = PETSC_FALSE; 8130fa7f1dd8SStefano Zampini } else { /* we can safely reuse already computed coarse matrix */ 8131fa7f1dd8SStefano Zampini coarse_reuse = PETSC_TRUE; 8132f4ddd8eeSStefano Zampini } 8133fa7f1dd8SStefano Zampini } else { /* there's no coarse ksp, so we need to create the coarse matrix too */ 8134fa7f1dd8SStefano Zampini coarse_reuse = PETSC_FALSE; 8135f4ddd8eeSStefano Zampini } 813670cf5478SStefano Zampini /* reset any subassembling information */ 813757de7509SStefano Zampini if (!coarse_reuse || pcbddc->recompute_topography) { 81385f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pcbddc->coarse_subassembling)); 813957de7509SStefano Zampini } 81406e683305SStefano Zampini } else { /* primal space is unchanged, so we can reuse coarse matrix */ 8141fa7f1dd8SStefano Zampini coarse_reuse = PETSC_TRUE; 8142f4ddd8eeSStefano Zampini } 814357de7509SStefano Zampini if (coarse_reuse && pcbddc->coarse_ksp) { 81445f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL)); 81455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)coarse_mat)); 814657de7509SStefano Zampini coarse_mat_reuse = MAT_REUSE_MATRIX; 814718a45a71SStefano Zampini } else { 814857de7509SStefano Zampini coarse_mat = NULL; 814957de7509SStefano Zampini coarse_mat_reuse = MAT_INITIAL_MATRIX; 81506e683305SStefano Zampini } 8151e7931f94SStefano Zampini 8152abbbba34SStefano Zampini /* creates temporary l2gmap and IS for coarse indexes */ 81535f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is)); 81545f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg)); 8155abbbba34SStefano Zampini 8156abbbba34SStefano Zampini /* creates temporary MATIS object for coarse matrix */ 81575f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_submat_dense)); 81585f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateIS(PetscObjectComm((PetscObject)pc),1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_islg,coarse_islg,&t_coarse_mat_is)); 81595f80ce2aSJacob Faibussowitsch CHKERRQ(MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense)); 81605f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY)); 81615f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY)); 81625f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&coarse_submat_dense)); 8163abbbba34SStefano Zampini 816457de7509SStefano Zampini /* count "active" (i.e. with positive local size) and "void" processes */ 816557de7509SStefano Zampini im_active = !!(pcis->n); 81665f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc))); 816757de7509SStefano Zampini 816814f0bfb9SStefano Zampini /* determine number of processes partecipating to coarse solver and compute subassembling pattern */ 816928d58a37SPierre Jolivet /* restr : whether we want to exclude senders (which are not receivers) from the subassembling pattern */ 817057de7509SStefano Zampini /* full_restr : just use the receivers from the subassembling pattern */ 81715f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size)); 817257de7509SStefano Zampini coarse_mat_is = NULL; 817357de7509SStefano Zampini multilevel_allowed = PETSC_FALSE; 817457de7509SStefano Zampini multilevel_requested = PETSC_FALSE; 8175e569e4e1SStefano Zampini coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc); 8176ce64c636SStefano Zampini if (coarse_eqs_per_proc < 0) coarse_eqs_per_proc = pcbddc->coarse_size; 817757de7509SStefano Zampini if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE; 8178e569e4e1SStefano Zampini if (pcbddc->coarse_size <= pcbddc->coarse_eqs_limit) multilevel_requested = PETSC_FALSE; 817957de7509SStefano Zampini if (multilevel_requested) { 818057de7509SStefano Zampini ncoarse = active_procs/pcbddc->coarsening_ratio; 818157de7509SStefano Zampini restr = PETSC_FALSE; 818257de7509SStefano Zampini full_restr = PETSC_FALSE; 818357de7509SStefano Zampini } else { 8184e569e4e1SStefano Zampini ncoarse = pcbddc->coarse_size/coarse_eqs_per_proc + !!(pcbddc->coarse_size%coarse_eqs_per_proc); 818557de7509SStefano Zampini restr = PETSC_TRUE; 818657de7509SStefano Zampini full_restr = PETSC_TRUE; 818757de7509SStefano Zampini } 8188e569e4e1SStefano Zampini if (!pcbddc->coarse_size || size == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE; 818957de7509SStefano Zampini ncoarse = PetscMax(1,ncoarse); 819057de7509SStefano Zampini if (!pcbddc->coarse_subassembling) { 8191a198735bSStefano Zampini if (pcbddc->coarsening_ratio > 1) { 8192bb360cb4SStefano Zampini if (multilevel_requested) { 81935f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCMatISGetSubassemblingPattern(pc->pmat,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void)); 8194bb360cb4SStefano Zampini } else { 81955f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void)); 8196bb360cb4SStefano Zampini } 8197a198735bSStefano Zampini } else { 81987de4f681Sstefano_zampini PetscMPIInt rank; 819928d58a37SPierre Jolivet 82005f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank)); 8201e569e4e1SStefano Zampini have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE; 82025f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling)); 8203a198735bSStefano Zampini } 820457de7509SStefano Zampini } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */ 820557de7509SStefano Zampini PetscInt psum; 820657de7509SStefano Zampini if (pcbddc->coarse_ksp) psum = 1; 820757de7509SStefano Zampini else psum = 0; 82085f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc))); 8209075e25bcSStefano Zampini have_void = ncoarse < size ? PETSC_TRUE : PETSC_FALSE; 821057de7509SStefano Zampini } 821157de7509SStefano Zampini /* determine if we can go multilevel */ 821257de7509SStefano Zampini if (multilevel_requested) { 821357de7509SStefano Zampini if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */ 821457de7509SStefano Zampini else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */ 821557de7509SStefano Zampini } 821657de7509SStefano Zampini if (multilevel_allowed && have_void) restr = PETSC_TRUE; 821757de7509SStefano Zampini 8218e4d548c7SStefano Zampini /* dump subassembling pattern */ 8219e4d548c7SStefano Zampini if (pcbddc->dbg_flag && multilevel_allowed) { 82205f80ce2aSJacob Faibussowitsch CHKERRQ(ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer)); 8221e4d548c7SStefano Zampini } 82226e683305SStefano Zampini /* compute dofs splitting and neumann boundaries for coarse dofs */ 82231e0482f5SStefano Zampini nedcfield = -1; 82244f819b78SStefano Zampini corners = NULL; 82258966356dSPierre Jolivet if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal || pcbddc->corner_selected)) { /* protects from unneeded computations */ 82266e683305SStefano Zampini PetscInt *tidxs,*tidxs2,nout,tsize,i; 82276e683305SStefano Zampini const PetscInt *idxs; 82286e683305SStefano Zampini ISLocalToGlobalMapping tmap; 82296e683305SStefano Zampini 82306e683305SStefano Zampini /* create map between primal indices (in local representative ordering) and local primal numbering */ 82315f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap)); 82326e683305SStefano Zampini /* allocate space for temporary storage */ 82335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->local_primal_size,&tidxs)); 82345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->local_primal_size,&tidxs2)); 82356e683305SStefano Zampini /* allocate for IS array */ 82366e683305SStefano Zampini nisdofs = pcbddc->n_ISForDofsLocal; 82371e0482f5SStefano Zampini if (pcbddc->nedclocal) { 82381e0482f5SStefano Zampini if (pcbddc->nedfield > -1) { 82391e0482f5SStefano Zampini nedcfield = pcbddc->nedfield; 82401e0482f5SStefano Zampini } else { 82411e0482f5SStefano Zampini nedcfield = 0; 8242*28b400f6SJacob Faibussowitsch PetscCheck(!nisdofs,PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen (%D)",nisdofs); 82431e0482f5SStefano Zampini nisdofs = 1; 82441e0482f5SStefano Zampini } 82451e0482f5SStefano Zampini } 82466e683305SStefano Zampini nisneu = !!pcbddc->NeumannBoundariesLocal; 824727b6a85dSStefano Zampini nisvert = 0; /* nisvert is not used */ 824830368db7SStefano Zampini nis = nisdofs + nisneu + nisvert; 82495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nis,&isarray)); 82506e683305SStefano Zampini /* dofs splitting */ 82516e683305SStefano Zampini for (i=0;i<nisdofs;i++) { 82525f80ce2aSJacob Faibussowitsch /* CHKERRQ(ISView(pcbddc->ISForDofsLocal[i],0)); */ 82531e0482f5SStefano Zampini if (nedcfield != i) { 82545f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize)); 82555f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs)); 82565f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs)); 82575f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs)); 82581e0482f5SStefano Zampini } else { 82595f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pcbddc->nedclocal,&tsize)); 82605f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcbddc->nedclocal,&idxs)); 82615f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs)); 82622c71b3e2SJacob Faibussowitsch PetscCheckFalse(tsize != nout,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping coarse nedelec field! %D != %D",tsize,nout); 82635f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcbddc->nedclocal,&idxs)); 82641e0482f5SStefano Zampini } 82655f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2)); 82665f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i])); 82675f80ce2aSJacob Faibussowitsch /* CHKERRQ(ISView(isarray[i],0)); */ 82686e683305SStefano Zampini } 82696e683305SStefano Zampini /* neumann boundaries */ 82706e683305SStefano Zampini if (pcbddc->NeumannBoundariesLocal) { 82715f80ce2aSJacob Faibussowitsch /* CHKERRQ(ISView(pcbddc->NeumannBoundariesLocal,0)); */ 82725f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize)); 82735f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs)); 82745f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs)); 82755f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs)); 82765f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2)); 82775f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs])); 82785f80ce2aSJacob Faibussowitsch /* CHKERRQ(ISView(isarray[nisdofs],0)); */ 82796e683305SStefano Zampini } 82804f819b78SStefano Zampini /* coordinates */ 82814f819b78SStefano Zampini if (pcbddc->corner_selected) { 82825f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&corners)); 82835f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(corners,&tsize)); 82845f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(corners,&idxs)); 82855f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs)); 82862c71b3e2SJacob Faibussowitsch PetscCheckFalse(tsize != nout,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed when mapping corners! %D != %D",tsize,nout); 82875f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(corners,&idxs)); 82885f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&corners)); 82895f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2)); 82905f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&corners)); 82914f819b78SStefano Zampini } 82925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(tidxs)); 82935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(tidxs2)); 82945f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&tmap)); 82956e683305SStefano Zampini } else { 82966e683305SStefano Zampini nis = 0; 82976e683305SStefano Zampini nisdofs = 0; 82986e683305SStefano Zampini nisneu = 0; 829930368db7SStefano Zampini nisvert = 0; 83006e683305SStefano Zampini isarray = NULL; 83016e683305SStefano Zampini } 83026e683305SStefano Zampini /* destroy no longer needed map */ 83035f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&coarse_islg)); 83046e683305SStefano Zampini 830557de7509SStefano Zampini /* subassemble */ 830657de7509SStefano Zampini if (multilevel_allowed) { 83071ae86dd6SStefano Zampini Vec vp[1]; 83081ae86dd6SStefano Zampini PetscInt nvecs = 0; 830957de7509SStefano Zampini PetscBool reuse,reuser; 83101ae86dd6SStefano Zampini 831157de7509SStefano Zampini if (coarse_mat) reuse = PETSC_TRUE; 831257de7509SStefano Zampini else reuse = PETSC_FALSE; 83135f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc))); 83141ae86dd6SStefano Zampini vp[0] = NULL; 83151ae86dd6SStefano Zampini if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */ 83165f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PetscObjectComm((PetscObject)pc),&vp[0])); 83175f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE)); 83185f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(vp[0],VECSTANDARD)); 83191ae86dd6SStefano Zampini nvecs = 1; 83201ae86dd6SStefano Zampini 83211ae86dd6SStefano Zampini if (pcbddc->divudotp) { 8322a198735bSStefano Zampini Mat B,loc_divudotp; 83231ae86dd6SStefano Zampini Vec v,p; 83241ae86dd6SStefano Zampini IS dummy; 83251ae86dd6SStefano Zampini PetscInt np; 83261ae86dd6SStefano Zampini 83275f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp)); 83285f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(loc_divudotp,&np,NULL)); 83295f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy)); 83305f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B)); 83315f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(B,&v,&p)); 83325f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(p,1.)); 83335f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(B,p,v)); 83345f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&p)); 83355f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B)); 83365f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(vp[0],&array)); 83375f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pcbddc->vec1_P,array)); 83385f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P)); 83395f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pcbddc->vec1_P)); 83405f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(vp[0],&array)); 83415f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&dummy)); 83425f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&v)); 834374e2c79eSStefano Zampini } 83441ae86dd6SStefano Zampini } 83451ae86dd6SStefano Zampini if (reuser) { 83465f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp)); 834774e2c79eSStefano Zampini } else { 83485f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray,nvecs,vp)); 83491ae86dd6SStefano Zampini } 83501ae86dd6SStefano Zampini if (vp[0]) { /* vp[0] could have been placed on a different set of processes */ 83511683a169SBarry Smith PetscScalar *arraym; 83521683a169SBarry Smith const PetscScalar *arrayv; 83531ae86dd6SStefano Zampini PetscInt nl; 83545f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(vp[0],&nl)); 83555f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp)); 83565f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(coarsedivudotp,&arraym)); 83575f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(vp[0],&arrayv)); 83585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(arraym,arrayv,nl)); 83595f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(vp[0],&arrayv)); 83605f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(coarsedivudotp,&arraym)); 83615f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&vp[0])); 8362a198735bSStefano Zampini } else { 83635f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp)); 83641ae86dd6SStefano Zampini } 83651ae86dd6SStefano Zampini } else { 83665f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCMatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,0,NULL,0,NULL)); 83676e683305SStefano Zampini } 836857de7509SStefano Zampini if (coarse_mat_is || coarse_mat) { 836957de7509SStefano Zampini if (!multilevel_allowed) { 83705f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert(coarse_mat_is,MATAIJ,coarse_mat_reuse,&coarse_mat)); 83716e683305SStefano Zampini } else { 837257de7509SStefano Zampini /* if this matrix is present, it means we are not reusing the coarse matrix */ 837357de7509SStefano Zampini if (coarse_mat_is) { 8374*28b400f6SJacob Faibussowitsch PetscCheck(!coarse_mat,PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen"); 83755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)coarse_mat_is)); 837657de7509SStefano Zampini coarse_mat = coarse_mat_is; 837757de7509SStefano Zampini } 8378779c1cceSStefano Zampini } 8379779c1cceSStefano Zampini } 83805f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&t_coarse_mat_is)); 83815f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&coarse_mat_is)); 83826e683305SStefano Zampini 83836e683305SStefano Zampini /* create local to global scatters for coarse problem */ 838468457ee5SStefano Zampini if (compute_vecs) { 83856e683305SStefano Zampini PetscInt lrows; 83865f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pcbddc->coarse_vec)); 838757de7509SStefano Zampini if (coarse_mat) { 83885f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(coarse_mat,&lrows,NULL)); 83896e683305SStefano Zampini } else { 83906e683305SStefano Zampini lrows = 0; 83916e683305SStefano Zampini } 83925f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec)); 83935f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE)); 83945f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(pcbddc->coarse_vec,coarse_mat ? coarse_mat->defaultvectype : VECSTANDARD)); 83955f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterDestroy(&pcbddc->coarse_loc_to_glob)); 83965f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob)); 83976e683305SStefano Zampini } 83985f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&coarse_is)); 8399c8587f34SStefano Zampini 8400f9eb5b7dSStefano Zampini /* set defaults for coarse KSP and PC */ 8401f9eb5b7dSStefano Zampini if (multilevel_allowed) { 8402f9eb5b7dSStefano Zampini coarse_ksp_type = KSPRICHARDSON; 8403f9eb5b7dSStefano Zampini coarse_pc_type = PCBDDC; 8404f9eb5b7dSStefano Zampini } else { 8405f9eb5b7dSStefano Zampini coarse_ksp_type = KSPPREONLY; 8406f9eb5b7dSStefano Zampini coarse_pc_type = PCREDUNDANT; 8407c8587f34SStefano Zampini } 8408c8587f34SStefano Zampini 84096e683305SStefano Zampini /* print some info if requested */ 84106e683305SStefano Zampini if (pcbddc->dbg_flag) { 84116e683305SStefano Zampini if (!multilevel_allowed) { 84125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n")); 84136e683305SStefano Zampini if (multilevel_requested) { 84145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Not enough active processes on level %D (active processes %D, coarsening ratio %D)\n",pcbddc->current_level,active_procs,pcbddc->coarsening_ratio)); 84156e683305SStefano Zampini } else if (pcbddc->max_levels) { 84165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%D)\n",pcbddc->max_levels)); 84176e683305SStefano Zampini } 84185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 84196e683305SStefano Zampini } 84206e683305SStefano Zampini } 84216e683305SStefano Zampini 84221e0482f5SStefano Zampini /* communicate coarse discrete gradient */ 84231e0482f5SStefano Zampini coarseG = NULL; 84241e0482f5SStefano Zampini if (pcbddc->nedcG && multilevel_allowed) { 84251e0482f5SStefano Zampini MPI_Comm ccomm; 84261e0482f5SStefano Zampini if (coarse_mat) { 84271e0482f5SStefano Zampini ccomm = PetscObjectComm((PetscObject)coarse_mat); 84281e0482f5SStefano Zampini } else { 84291e0482f5SStefano Zampini ccomm = MPI_COMM_NULL; 84301e0482f5SStefano Zampini } 84315f80ce2aSJacob Faibussowitsch CHKERRQ(MatMPIAIJRestrict(pcbddc->nedcG,ccomm,&coarseG)); 84321e0482f5SStefano Zampini } 84331e0482f5SStefano Zampini 8434f9eb5b7dSStefano Zampini /* create the coarse KSP object only once with defaults */ 843557de7509SStefano Zampini if (coarse_mat) { 843628d58a37SPierre Jolivet PetscBool isredundant,isbddc,force,valid; 84376a1308c2SStefano Zampini PetscViewer dbg_viewer = NULL; 84387274672aSStefano Zampini 84396e683305SStefano Zampini if (pcbddc->dbg_flag) { 844057de7509SStefano Zampini dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat)); 84415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level)); 84426e683305SStefano Zampini } 8443f9eb5b7dSStefano Zampini if (!pcbddc->coarse_ksp) { 8444312be037SStefano Zampini char prefix[256],str_level[16]; 8445e604994aSStefano Zampini size_t len; 84461e0482f5SStefano Zampini 84475f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp)); 84485f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure)); 84495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1)); 84505f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1)); 84515f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat)); 84525f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type)); 84535f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE)); 84545f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->coarse_ksp,&pc_temp)); 84551e0482f5SStefano Zampini /* TODO is this logic correct? should check for coarse_mat type */ 84565f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pc_temp,coarse_pc_type)); 8457e604994aSStefano Zampini /* prefix */ 84585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcpy(prefix,"")); 84595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcpy(str_level,"")); 8460e604994aSStefano Zampini if (!pcbddc->current_level) { 84615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(prefix,((PetscObject)pc)->prefix,sizeof(prefix))); 84625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(prefix,"pc_bddc_coarse_",sizeof(prefix))); 8463c8587f34SStefano Zampini } else { 84645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(((PetscObject)pc)->prefix,&len)); 8465312be037SStefano Zampini if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */ 8466312be037SStefano Zampini if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */ 8467a126751eSBarry Smith /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */ 84685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1)); 84695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(str_level,sizeof(str_level),"l%d_",(int)(pcbddc->current_level))); 84705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(prefix,str_level,sizeof(prefix))); 8471e604994aSStefano Zampini } 84725f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix)); 84733e3c6dadSStefano Zampini /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */ 84745f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetLevel(pc_temp,pcbddc->current_level+1)); 84755f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio)); 84765f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetLevels(pc_temp,pcbddc->max_levels)); 8477f9eb5b7dSStefano Zampini /* allow user customization */ 84785f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetFromOptions(pcbddc->coarse_ksp)); 8479e569e4e1SStefano Zampini /* get some info after set from options */ 84805f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->coarse_ksp,&pc_temp)); 848128d58a37SPierre Jolivet /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */ 848228d58a37SPierre Jolivet force = PETSC_FALSE; 84835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(NULL,((PetscObject)pc_temp)->prefix,"-pc_type_forced",&force,NULL)); 84845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompareAny((PetscObject)pc_temp,&valid,PCBDDC,PCNN,PCHPDDM,"")); 84855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc)); 848628d58a37SPierre Jolivet if (multilevel_allowed && !force && !valid) { 8487e569e4e1SStefano Zampini isbddc = PETSC_TRUE; 84885f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pc_temp,PCBDDC)); 84895f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetLevel(pc_temp,pcbddc->current_level+1)); 84905f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio)); 84915f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetLevels(pc_temp,pcbddc->max_levels)); 84924f819b78SStefano Zampini if (pc_temp->ops->setfromoptions) { /* need to setfromoptions again, skipping the pc_type */ 84934f819b78SStefano Zampini ierr = PetscObjectOptionsBegin((PetscObject)pc_temp);CHKERRQ(ierr); 84945f80ce2aSJacob Faibussowitsch CHKERRQ((*pc_temp->ops->setfromoptions)(PetscOptionsObject,pc_temp)); 84955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)pc_temp)); 84964f819b78SStefano Zampini ierr = PetscOptionsEnd();CHKERRQ(ierr); 84974f819b78SStefano Zampini pc_temp->setfromoptionscalled++; 84984f819b78SStefano Zampini } 8499e569e4e1SStefano Zampini } 85003e3c6dadSStefano Zampini } 85013e3c6dadSStefano Zampini /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */ 85025f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->coarse_ksp,&pc_temp)); 85033e3c6dadSStefano Zampini if (nisdofs) { 85045f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray)); 85053e3c6dadSStefano Zampini for (i=0;i<nisdofs;i++) { 85065f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&isarray[i])); 85073e3c6dadSStefano Zampini } 85083e3c6dadSStefano Zampini } 85093e3c6dadSStefano Zampini if (nisneu) { 85105f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs])); 85115f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&isarray[nisdofs])); 8512312be037SStefano Zampini } 851330368db7SStefano Zampini if (nisvert) { 85145f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1])); 85155f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&isarray[nis-1])); 851630368db7SStefano Zampini } 85171e0482f5SStefano Zampini if (coarseG) { 85185f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetDiscreteGradient(pc_temp,coarseG,1,nedcfield,PETSC_FALSE,PETSC_TRUE)); 85191e0482f5SStefano Zampini } 8520f9eb5b7dSStefano Zampini 8521f9eb5b7dSStefano Zampini /* get some info after set from options */ 85225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc)); 85234f819b78SStefano Zampini 8524b76f3995Sstefano_zampini /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */ 8525b76f3995Sstefano_zampini if (isbddc && !multilevel_allowed) { 85265f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pc_temp,coarse_pc_type)); 8527f9eb5b7dSStefano Zampini } 852828d58a37SPierre Jolivet /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */ 852928d58a37SPierre Jolivet force = PETSC_FALSE; 85305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(NULL,((PetscObject)pc_temp)->prefix,"-pc_type_forced",&force,NULL)); 85315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompareAny((PetscObject)pc_temp,&valid,PCBDDC,PCNN,PCHPDDM,"")); 853228d58a37SPierre Jolivet if (multilevel_requested && multilevel_allowed && !valid && !force) { 85335f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pc_temp,PCBDDC)); 8534b76f3995Sstefano_zampini } 85355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant)); 85364f3a063dSStefano Zampini if (isredundant) { 85374f3a063dSStefano Zampini KSP inner_ksp; 85384f3a063dSStefano Zampini PC inner_pc; 85399326c5c6Sstefano_zampini 85405f80ce2aSJacob Faibussowitsch CHKERRQ(PCRedundantGetKSP(pc_temp,&inner_ksp)); 85415f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(inner_ksp,&inner_pc)); 85424f3a063dSStefano Zampini } 8543f9eb5b7dSStefano Zampini 854457de7509SStefano Zampini /* parameters which miss an API */ 85455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc)); 854657de7509SStefano Zampini if (isbddc) { 8547720d30f9SStefano Zampini PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data; 85487274672aSStefano Zampini 8549720d30f9SStefano Zampini pcbddc_coarse->detect_disconnected = PETSC_TRUE; 855057de7509SStefano Zampini pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc; 8551e569e4e1SStefano Zampini pcbddc_coarse->coarse_eqs_limit = pcbddc->coarse_eqs_limit; 855227b6a85dSStefano Zampini pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null; 855327b6a85dSStefano Zampini if (pcbddc_coarse->benign_saddle_point) { 8554a198735bSStefano Zampini Mat coarsedivudotp_is; 8555a198735bSStefano Zampini ISLocalToGlobalMapping l2gmap,rl2g,cl2g; 8556a198735bSStefano Zampini IS row,col; 8557a198735bSStefano Zampini const PetscInt *gidxs; 8558a198735bSStefano Zampini PetscInt n,st,M,N; 8559a198735bSStefano Zampini 85605f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(coarsedivudotp,&n,NULL)); 85615f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat))); 8562a198735bSStefano Zampini st = st-n; 85635f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row)); 85645f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL)); 85655f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetSize(l2gmap,&n)); 85665f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs)); 85675f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col)); 85685f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs)); 85695f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(row,&rl2g)); 85705f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(col,&cl2g)); 85715f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(row,&M)); 85725f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(coarse_mat,&N,NULL)); 85735f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&row)); 85745f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&col)); 85755f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is)); 85765f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(coarsedivudotp_is,MATIS)); 85775f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N)); 85785f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g)); 85795f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&rl2g)); 85805f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(&cl2g)); 85815f80ce2aSJacob Faibussowitsch CHKERRQ(MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp)); 85825f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&coarsedivudotp)); 85835f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,PETSC_FALSE,NULL)); 85845f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&coarsedivudotp_is)); 8585720d30f9SStefano Zampini pcbddc_coarse->adaptive_userdefined = PETSC_TRUE; 8586bd2a564bSStefano Zampini if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE; 8587720d30f9SStefano Zampini } 8588d4d8cf7bSStefano Zampini } 85899881197aSStefano Zampini 85903301b35fSStefano Zampini /* propagate symmetry info of coarse matrix */ 85915f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE)); 85923301b35fSStefano Zampini if (pc->pmat->symmetric_set) { 85935f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric)); 85943301b35fSStefano Zampini } 85953301b35fSStefano Zampini if (pc->pmat->hermitian_set) { 85965f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian)); 85973301b35fSStefano Zampini } 85983301b35fSStefano Zampini if (pc->pmat->spd_set) { 85995f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd)); 86003301b35fSStefano Zampini } 860127b6a85dSStefano Zampini if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) { 86025f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE)); 860327b6a85dSStefano Zampini } 86046e683305SStefano Zampini /* set operators */ 86055f80ce2aSJacob Faibussowitsch CHKERRQ(MatViewFromOptions(coarse_mat,(PetscObject)pc,"-pc_bddc_coarse_mat_view")); 86065f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOptionsPrefix(coarse_mat,((PetscObject)pcbddc->coarse_ksp)->prefix)); 86075f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat)); 86086e683305SStefano Zampini if (pcbddc->dbg_flag) { 86095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level)); 86106e683305SStefano Zampini } 86116e683305SStefano Zampini } 86125f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&coarseG)); 86135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(isarray)); 8614b1ecc7b1SStefano Zampini #if 0 8615b9b85e73SStefano Zampini { 8616b9b85e73SStefano Zampini PetscViewer viewer; 8617b9b85e73SStefano Zampini char filename[256]; 8618b1ecc7b1SStefano Zampini sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level); 86195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer)); 86205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB)); 86215f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(coarse_mat,viewer)); 86225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerPopFormat(viewer)); 86235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 8624b9b85e73SStefano Zampini } 8625b9b85e73SStefano Zampini #endif 8626f9eb5b7dSStefano Zampini 86274f819b78SStefano Zampini if (corners) { 86284f819b78SStefano Zampini Vec gv; 86294f819b78SStefano Zampini IS is; 86304f819b78SStefano Zampini const PetscInt *idxs; 86314f819b78SStefano Zampini PetscInt i,d,N,n,cdim = pcbddc->mat_graph->cdim; 86324f819b78SStefano Zampini PetscScalar *coords; 86334f819b78SStefano Zampini 8634*28b400f6SJacob Faibussowitsch PetscCheck(pcbddc->mat_graph->cloc,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing local coordinates"); 86355f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSize(pcbddc->coarse_vec,&N)); 86365f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(pcbddc->coarse_vec,&n)); 86375f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PetscObjectComm((PetscObject)pcbddc->coarse_vec),&gv)); 86385f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(gv,cdim)); 86395f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(gv,n*cdim,N*cdim)); 86405f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(gv,VECSTANDARD)); 86415f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetFromOptions(gv)); 86425f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(gv,PETSC_MAX_REAL)); /* we only propagate coordinates from vertices constraints */ 86434f819b78SStefano Zampini 86445f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&is)); 86455f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(is,&n)); 86465f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(is,&idxs)); 86475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n*cdim,&coords)); 86484f819b78SStefano Zampini for (i=0;i<n;i++) { 86494f819b78SStefano Zampini for (d=0;d<cdim;d++) { 86504f819b78SStefano Zampini coords[cdim*i+d] = pcbddc->mat_graph->coords[cdim*idxs[i]+d]; 86514f819b78SStefano Zampini } 86524f819b78SStefano Zampini } 86535f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(is,&idxs)); 86545f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&is)); 86554f819b78SStefano Zampini 86565f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(corners,&n)); 86575f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(corners,&idxs)); 86585f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValuesBlocked(gv,n,idxs,coords,INSERT_VALUES)); 86595f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(corners,&idxs)); 86605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(coords)); 86615f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(gv)); 86625f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(gv)); 86635f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(gv,&coords)); 86644f819b78SStefano Zampini if (pcbddc->coarse_ksp) { 86654f819b78SStefano Zampini PC coarse_pc; 86664f819b78SStefano Zampini PetscBool isbddc; 86674f819b78SStefano Zampini 86685f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->coarse_ksp,&coarse_pc)); 86695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc)); 86704f819b78SStefano Zampini if (isbddc) { /* coarse coordinates have PETSC_MAX_REAL, specific for BDDC */ 86714f819b78SStefano Zampini PetscReal *realcoords; 86724f819b78SStefano Zampini 86735f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(gv,&n)); 86744f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 86755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n,&realcoords)); 86764f819b78SStefano Zampini for (i=0;i<n;i++) realcoords[i] = PetscRealPart(coords[i]); 86774f819b78SStefano Zampini #else 86784f819b78SStefano Zampini realcoords = coords; 86794f819b78SStefano Zampini #endif 86805f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetCoordinates(coarse_pc,cdim,n/cdim,realcoords)); 86814f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 86825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(realcoords)); 86834f819b78SStefano Zampini #endif 86844f819b78SStefano Zampini } 86854f819b78SStefano Zampini } 86865f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(gv,&coords)); 86875f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&gv)); 86884f819b78SStefano Zampini } 86895f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&corners)); 86904f819b78SStefano Zampini 869198a51de6SStefano Zampini if (pcbddc->coarse_ksp) { 869298a51de6SStefano Zampini Vec crhs,csol; 869304708bb6SStefano Zampini 86945f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetSolution(pcbddc->coarse_ksp,&csol)); 86955f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetRhs(pcbddc->coarse_ksp,&crhs)); 8696f347579bSStefano Zampini if (!csol) { 86975f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL)); 8698f9eb5b7dSStefano Zampini } 8699f347579bSStefano Zampini if (!crhs) { 87005f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs))); 8701f347579bSStefano Zampini } 8702b0f5fe93SStefano Zampini } 87035f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&coarsedivudotp)); 8704b0f5fe93SStefano Zampini 8705b0f5fe93SStefano Zampini /* compute null space for coarse solver if the benign trick has been requested */ 8706b0f5fe93SStefano Zampini if (pcbddc->benign_null) { 8707b0f5fe93SStefano Zampini 87085f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcbddc->vec1_P,0.)); 87094f1b2e48SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) { 87105f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES)); 87114f1b2e48SStefano Zampini } 87125f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(pcbddc->vec1_P)); 87135f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(pcbddc->vec1_P)); 87145f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD)); 87155f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD)); 8716b0f5fe93SStefano Zampini if (coarse_mat) { 8717b0f5fe93SStefano Zampini Vec nullv; 8718b0f5fe93SStefano Zampini PetscScalar *array,*array2; 8719b0f5fe93SStefano Zampini PetscInt nl; 8720b0f5fe93SStefano Zampini 87215f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(coarse_mat,&nullv,NULL)); 87225f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(nullv,&nl)); 87235f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array)); 87245f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(nullv,&array2)); 87255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(array2,array,nl)); 87265f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(nullv,&array2)); 87275f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array)); 87285f80ce2aSJacob Faibussowitsch CHKERRQ(VecNormalize(nullv,NULL)); 87295f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace)); 87305f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&nullv)); 8731b0f5fe93SStefano Zampini } 8732b0f5fe93SStefano Zampini } 87335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_BDDC_CoarseSetUp[pcbddc->current_level],pc,0,0,0)); 8734b0f5fe93SStefano Zampini 87355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0)); 8736b0f5fe93SStefano Zampini if (pcbddc->coarse_ksp) { 8737b0f5fe93SStefano Zampini PetscBool ispreonly; 8738b0f5fe93SStefano Zampini 8739b0f5fe93SStefano Zampini if (CoarseNullSpace) { 8740b0f5fe93SStefano Zampini PetscBool isnull; 87415f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull)); 8742bef83e63SStefano Zampini if (isnull) { 87435f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetNullSpace(coarse_mat,CoarseNullSpace)); 8744b0f5fe93SStefano Zampini } 8745bef83e63SStefano Zampini /* TODO: add local nullspaces (if any) */ 8746b0f5fe93SStefano Zampini } 8747b0f5fe93SStefano Zampini /* setup coarse ksp */ 87485f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetUp(pcbddc->coarse_ksp)); 8749cbcc2c2aSStefano Zampini /* Check coarse problem if in debug mode or if solving with an iterative method */ 87505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly)); 87516e683305SStefano Zampini if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates)) { 8752c8587f34SStefano Zampini KSP check_ksp; 87532b510759SStefano Zampini KSPType check_ksp_type; 8754c8587f34SStefano Zampini PC check_pc; 87556e683305SStefano Zampini Vec check_vec,coarse_vec; 87566a1308c2SStefano Zampini PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0; 87572b510759SStefano Zampini PetscInt its; 87586e683305SStefano Zampini PetscBool compute_eigs; 87596e683305SStefano Zampini PetscReal *eigs_r,*eigs_c; 87606e683305SStefano Zampini PetscInt neigs; 87618e185a42SStefano Zampini const char *prefix; 8762c8587f34SStefano Zampini 87632b510759SStefano Zampini /* Create ksp object suitable for estimation of extreme eigenvalues */ 87645f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp)); 87655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectIncrementTabLevel((PetscObject)check_ksp,(PetscObject)pcbddc->coarse_ksp,0)); 87665f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,PETSC_FALSE)); 87675f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(check_ksp,coarse_mat,coarse_mat)); 87685f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size)); 8769e4d548c7SStefano Zampini /* prevent from setup unneeded object */ 87705f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(check_ksp,&check_pc)); 87715f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(check_pc,PCNONE)); 87722b510759SStefano Zampini if (ispreonly) { 87732b510759SStefano Zampini check_ksp_type = KSPPREONLY; 87746e683305SStefano Zampini compute_eigs = PETSC_FALSE; 87752b510759SStefano Zampini } else { 8776cbcc2c2aSStefano Zampini check_ksp_type = KSPGMRES; 87776e683305SStefano Zampini compute_eigs = PETSC_TRUE; 8778c8587f34SStefano Zampini } 87795f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetType(check_ksp,check_ksp_type)); 87805f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetComputeSingularValues(check_ksp,compute_eigs)); 87815f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetComputeEigenvalues(check_ksp,compute_eigs)); 87825f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1)); 87835f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix)); 87845f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOptionsPrefix(check_ksp,prefix)); 87855f80ce2aSJacob Faibussowitsch CHKERRQ(KSPAppendOptionsPrefix(check_ksp,"check_")); 87865f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetFromOptions(check_ksp)); 87875f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetUp(check_ksp)); 87885f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(pcbddc->coarse_ksp,&check_pc)); 87895f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetPC(check_ksp,check_pc)); 8790c8587f34SStefano Zampini /* create random vec */ 87915f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(coarse_mat,&coarse_vec,&check_vec)); 87925f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetRandom(check_vec,NULL)); 87935f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(coarse_mat,check_vec,coarse_vec)); 8794c8587f34SStefano Zampini /* solve coarse problem */ 87955f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(check_ksp,coarse_vec,coarse_vec)); 87965f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(check_ksp,pc,coarse_vec)); 8797cbcc2c2aSStefano Zampini /* set eigenvalue estimation if preonly has not been requested */ 87986e683305SStefano Zampini if (compute_eigs) { 87995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->coarse_size+1,&eigs_r)); 88005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->coarse_size+1,&eigs_c)); 88015f80ce2aSJacob Faibussowitsch CHKERRQ(KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs)); 88021ae86dd6SStefano Zampini if (neigs) { 88036e683305SStefano Zampini lambda_max = eigs_r[neigs-1]; 88046e683305SStefano Zampini lambda_min = eigs_r[0]; 88056e683305SStefano Zampini if (pcbddc->use_coarse_estimates) { 88062701bc32SStefano Zampini if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */ 88075f80ce2aSJacob Faibussowitsch CHKERRQ(KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min)); 88085f80ce2aSJacob Faibussowitsch CHKERRQ(KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min))); 8809cbcc2c2aSStefano Zampini } 8810c8587f34SStefano Zampini } 8811c8587f34SStefano Zampini } 88121ae86dd6SStefano Zampini } 8813cbcc2c2aSStefano Zampini 8814c8587f34SStefano Zampini /* check coarse problem residual error */ 88156e683305SStefano Zampini if (pcbddc->dbg_flag) { 88166e683305SStefano Zampini PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp)); 88175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1))); 88185f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(check_vec,-1.0,coarse_vec)); 88195f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(check_vec,NORM_INFINITY,&infty_error)); 88205f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(coarse_mat,check_vec,coarse_vec)); 88215f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error)); 88225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates)); 88235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer)); 88245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer)); 88255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error : %1.6e\n",infty_error)); 88265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error)); 8827b0f5fe93SStefano Zampini if (CoarseNullSpace) { 88285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n")); 8829b0f5fe93SStefano Zampini } 88306e683305SStefano Zampini if (compute_eigs) { 88316e683305SStefano Zampini PetscReal lambda_max_s,lambda_min_s; 8832b03ebc13SStefano Zampini KSPConvergedReason reason; 88335f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetType(check_ksp,&check_ksp_type)); 88345f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetIterationNumber(check_ksp,&its)); 88355f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetConvergedReason(check_ksp,&reason)); 88365f80ce2aSJacob Faibussowitsch CHKERRQ(KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s)); 88375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem eigenvalues (estimated with %d iterations of %s, conv reason %d): %1.6e %1.6e (%1.6e %1.6e)\n",its,check_ksp_type,reason,lambda_min,lambda_max,lambda_min_s,lambda_max_s)); 88386e683305SStefano Zampini for (i=0;i<neigs;i++) { 88395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i])); 8840c8587f34SStefano Zampini } 88416e683305SStefano Zampini } 88425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(dbg_viewer)); 88435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1))); 88446e683305SStefano Zampini } 88455f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&check_vec)); 88465f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coarse_vec)); 88475f80ce2aSJacob Faibussowitsch CHKERRQ(KSPDestroy(&check_ksp)); 88486e683305SStefano Zampini if (compute_eigs) { 88495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(eigs_r)); 88505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(eigs_c)); 8851c8587f34SStefano Zampini } 88526e683305SStefano Zampini } 88536e683305SStefano Zampini } 88545f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceDestroy(&CoarseNullSpace)); 8855cbcc2c2aSStefano Zampini /* print additional info */ 8856cbcc2c2aSStefano Zampini if (pcbddc->dbg_flag) { 88576e683305SStefano Zampini /* waits until all processes reaches this point */ 88585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBarrier((PetscObject)pc)); 88595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %D\n",pcbddc->current_level)); 88605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 8861cbcc2c2aSStefano Zampini } 8862cbcc2c2aSStefano Zampini 88632b510759SStefano Zampini /* free memory */ 88645f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&coarse_mat)); 88655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_BDDC_CoarseSolver[pcbddc->current_level],pc,0,0,0)); 8866c8587f34SStefano Zampini PetscFunctionReturn(0); 8867c8587f34SStefano Zampini } 8868674ae819SStefano Zampini 8869f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n) 8870f34684f1SStefano Zampini { 8871f34684f1SStefano Zampini PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 8872f34684f1SStefano Zampini PC_IS* pcis = (PC_IS*)pc->data; 8873f34684f1SStefano Zampini Mat_IS* matis = (Mat_IS*)pc->pmat->data; 8874dc456d91SStefano Zampini IS subset,subset_mult,subset_n; 8875dc456d91SStefano Zampini PetscInt local_size,coarse_size=0; 887673be2a3aSStefano Zampini PetscInt *local_primal_indices=NULL; 8877dc456d91SStefano Zampini const PetscInt *t_local_primal_indices; 8878f34684f1SStefano Zampini 8879f34684f1SStefano Zampini PetscFunctionBegin; 8880f34684f1SStefano Zampini /* Compute global number of coarse dofs */ 88812c71b3e2SJacob Faibussowitsch PetscCheckFalse(pcbddc->local_primal_size && !pcbddc->local_primal_ref_node,PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first"); 88825f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n)); 88835f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset)); 88845f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&subset_n)); 88855f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult)); 88865f80ce2aSJacob Faibussowitsch CHKERRQ(ISRenumber(subset,subset_mult,&coarse_size,&subset_n)); 88875f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&subset)); 88885f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&subset_mult)); 88895f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(subset_n,&local_size)); 88902c71b3e2SJacob Faibussowitsch PetscCheckFalse(local_size != pcbddc->local_primal_size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %D != %D",local_size,pcbddc->local_primal_size); 88915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(local_size,&local_primal_indices)); 88925f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(subset_n,&t_local_primal_indices)); 88935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(local_primal_indices,t_local_primal_indices,local_size)); 88945f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(subset_n,&t_local_primal_indices)); 88955f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&subset_n)); 8896f34684f1SStefano Zampini 8897f34684f1SStefano Zampini /* check numbering */ 8898f34684f1SStefano Zampini if (pcbddc->dbg_flag) { 8899019a44ceSStefano Zampini PetscScalar coarsesum,*array,*array2; 8900dc456d91SStefano Zampini PetscInt i; 8901b9b85e73SStefano Zampini PetscBool set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE; 8902f34684f1SStefano Zampini 89035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 89045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n")); 89055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n")); 89065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 8907019a44ceSStefano Zampini /* counter */ 89085f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcis->vec1_global,0.0)); 89095f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcis->vec1_N,1.0)); 89105f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE)); 89115f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE)); 89125f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD)); 89135f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD)); 89145f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcis->vec1_N,0.0)); 8915f34684f1SStefano Zampini for (i=0;i<pcbddc->local_primal_size;i++) { 89165f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES)); 8917f34684f1SStefano Zampini } 89185f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(pcis->vec1_N)); 89195f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(pcis->vec1_N)); 89205f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcis->vec1_global,0.0)); 89215f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE)); 89225f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE)); 89235f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD)); 89245f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD)); 89255f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(pcis->vec1_N,&array)); 89265f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(pcis->vec2_N,&array2)); 8927f34684f1SStefano Zampini for (i=0;i<pcis->n;i++) { 8928019a44ceSStefano Zampini if (array[i] != 0.0 && array[i] != array2[i]) { 89292c66d082SStefano Zampini PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi; 893075c01103SStefano Zampini PetscInt neigh = (PetscInt)PetscRealPart(array2[i]); 8931b9b85e73SStefano Zampini set_error = PETSC_TRUE; 89325f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi)); 89335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %D (gid %D) owned by %D processes instead of %D!\n",PetscGlobalRank,i,gi,owned,neigh)); 8934f34684f1SStefano Zampini } 8935f34684f1SStefano Zampini } 89365f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(pcis->vec2_N,&array2)); 89375f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc))); 89385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 8939f34684f1SStefano Zampini for (i=0;i<pcis->n;i++) { 8940f34684f1SStefano Zampini if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]); 8941f34684f1SStefano Zampini } 89425f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(pcis->vec1_N,&array)); 89435f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcis->vec1_global,0.0)); 89445f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE)); 89455f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE)); 89465f80ce2aSJacob Faibussowitsch CHKERRQ(VecSum(pcis->vec1_global,&coarsesum)); 89475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %D (%lf)\n",coarse_size,PetscRealPart(coarsesum))); 8948b9b85e73SStefano Zampini if (pcbddc->dbg_flag > 1 || set_error_reduced) { 8949ca8b9ea9SStefano Zampini PetscInt *gidxs; 8950ca8b9ea9SStefano Zampini 89515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pcbddc->local_primal_size,&gidxs)); 89525f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs)); 89535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n")); 89545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 89555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank)); 8956f34684f1SStefano Zampini for (i=0;i<pcbddc->local_primal_size;i++) { 89575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_primal_indices[%D]=%D (%D,%D)\n",i,local_primal_indices[i],pcbddc->primal_indices_local_idxs[i],gidxs[i])); 8958f34684f1SStefano Zampini } 89595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 89605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(gidxs)); 8961f34684f1SStefano Zampini } 89625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 89635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 8964*28b400f6SJacob Faibussowitsch PetscCheck(!set_error_reduced,PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed"); 8965f34684f1SStefano Zampini } 89666080607fSStefano Zampini 8967f34684f1SStefano Zampini /* get back data */ 8968f34684f1SStefano Zampini *coarse_size_n = coarse_size; 8969f34684f1SStefano Zampini *local_primal_indices_n = local_primal_indices; 8970674ae819SStefano Zampini PetscFunctionReturn(0); 8971674ae819SStefano Zampini } 8972674ae819SStefano Zampini 8973a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis) 8974e456f2a8SStefano Zampini { 8975e456f2a8SStefano Zampini IS localis_t; 8976a7dc3881SStefano Zampini PetscInt i,lsize,*idxs,n; 8977e456f2a8SStefano Zampini PetscScalar *vals; 8978e456f2a8SStefano Zampini 8979e456f2a8SStefano Zampini PetscFunctionBegin; 8980a7dc3881SStefano Zampini /* get indices in local ordering exploiting local to global map */ 89815f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(globalis,&lsize)); 89825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(lsize,&vals)); 8983e456f2a8SStefano Zampini for (i=0;i<lsize;i++) vals[i] = 1.0; 89845f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(globalis,(const PetscInt**)&idxs)); 89855f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(gwork,0.0)); 89865f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(lwork,0.0)); 89871035eff8SStefano Zampini if (idxs) { /* multilevel guard */ 89885f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOption(gwork,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE)); 89895f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES)); 89901035eff8SStefano Zampini } 89915f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(gwork)); 89925f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(globalis,(const PetscInt**)&idxs)); 89935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vals)); 89945f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(gwork)); 8995a7dc3881SStefano Zampini /* now compute set in local ordering */ 89965f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD)); 89975f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD)); 89985f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(lwork,(const PetscScalar**)&vals)); 89995f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSize(lwork,&n)); 9000a7dc3881SStefano Zampini for (i=0,lsize=0;i<n;i++) { 9001ff92baa0SMatthew G. Knepley if (PetscRealPart(vals[i]) > 0.5) { 9002e456f2a8SStefano Zampini lsize++; 9003e456f2a8SStefano Zampini } 9004e456f2a8SStefano Zampini } 90055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(lsize,&idxs)); 9006a7dc3881SStefano Zampini for (i=0,lsize=0;i<n;i++) { 9007ff92baa0SMatthew G. Knepley if (PetscRealPart(vals[i]) > 0.5) { 9008e456f2a8SStefano Zampini idxs[lsize++] = i; 9009e456f2a8SStefano Zampini } 9010e456f2a8SStefano Zampini } 90115f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(lwork,(const PetscScalar**)&vals)); 90125f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t)); 9013e456f2a8SStefano Zampini *localis = localis_t; 9014e456f2a8SStefano Zampini PetscFunctionReturn(0); 9015e456f2a8SStefano Zampini } 9016906d46d4SStefano Zampini 901708122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc) 9018b96c3477SStefano Zampini { 9019a64f4aa4SStefano Zampini PC_IS *pcis=(PC_IS*)pc->data; 9020b96c3477SStefano Zampini PC_BDDC *pcbddc=(PC_BDDC*)pc->data; 9021b96c3477SStefano Zampini PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs; 9022a64f4aa4SStefano Zampini Mat S_j; 9023b96c3477SStefano Zampini PetscInt *used_xadj,*used_adjncy; 9024b96c3477SStefano Zampini PetscBool free_used_adj; 9025b96c3477SStefano Zampini PetscErrorCode ierr; 9026b96c3477SStefano Zampini 9027b96c3477SStefano Zampini PetscFunctionBegin; 90285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0)); 9029b96c3477SStefano Zampini /* decide the adjacency to be used for determining internal problems for local schur on subsets */ 9030b96c3477SStefano Zampini free_used_adj = PETSC_FALSE; 903108122e43SStefano Zampini if (pcbddc->sub_schurs_layers == -1) { 9032b96c3477SStefano Zampini used_xadj = NULL; 9033b96c3477SStefano Zampini used_adjncy = NULL; 9034b96c3477SStefano Zampini } else { 903508122e43SStefano Zampini if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) { 903608122e43SStefano Zampini used_xadj = pcbddc->mat_graph->xadj; 903708122e43SStefano Zampini used_adjncy = pcbddc->mat_graph->adjncy; 903808122e43SStefano Zampini } else if (pcbddc->computed_rowadj) { 9039b96c3477SStefano Zampini used_xadj = pcbddc->mat_graph->xadj; 9040b96c3477SStefano Zampini used_adjncy = pcbddc->mat_graph->adjncy; 9041b96c3477SStefano Zampini } else { 90422fffb893SStefano Zampini PetscBool flg_row=PETSC_FALSE; 9043b96c3477SStefano Zampini const PetscInt *xadj,*adjncy; 9044b96c3477SStefano Zampini PetscInt nvtxs; 9045b96c3477SStefano Zampini 90465f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row)); 90472fffb893SStefano Zampini if (flg_row) { 90485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy)); 90495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(used_xadj,xadj,nvtxs+1)); 90505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(used_adjncy,adjncy,xadj[nvtxs])); 9051b96c3477SStefano Zampini free_used_adj = PETSC_TRUE; 90522fffb893SStefano Zampini } else { 90532fffb893SStefano Zampini pcbddc->sub_schurs_layers = -1; 90542fffb893SStefano Zampini used_xadj = NULL; 90552fffb893SStefano Zampini used_adjncy = NULL; 90562fffb893SStefano Zampini } 90575f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row)); 9058b96c3477SStefano Zampini } 9059b96c3477SStefano Zampini } 9060d5574798SStefano Zampini 9061d5574798SStefano Zampini /* setup sub_schurs data */ 90625f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSchurComplement(pcis->A_II,pcis->pA_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j)); 9063df4d28bfSStefano Zampini if (!sub_schurs->schur_explicit) { 9064df4d28bfSStefano Zampini /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */ 90655f80ce2aSJacob Faibussowitsch CHKERRQ(MatSchurComplementSetKSP(S_j,pcbddc->ksp_D)); 90665f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSubSchursSetUp(sub_schurs,NULL,S_j,PETSC_FALSE,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,NULL,pcbddc->adaptive_selection,PETSC_FALSE,PETSC_FALSE,0,NULL,NULL,NULL,NULL)); 9067a64f4aa4SStefano Zampini } else { 906872b8c272SStefano Zampini Mat change = NULL; 90699d54b7f4SStefano Zampini Vec scaling = NULL; 9070111315fdSstefano_zampini IS change_primal = NULL, iP; 9071111315fdSstefano_zampini PetscInt benign_n; 9072111315fdSstefano_zampini PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis; 90737ebab0bbSStefano Zampini PetscBool need_change = PETSC_FALSE; 9074111315fdSstefano_zampini PetscBool discrete_harmonic = PETSC_FALSE; 9075a3df083aSStefano Zampini 90765feab87aSStefano Zampini if (!pcbddc->use_vertices && reuse_solvers) { 90775feab87aSStefano Zampini PetscInt n_vertices; 90785feab87aSStefano Zampini 90795f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(sub_schurs->is_vertices,&n_vertices)); 90802034aafcSStefano Zampini reuse_solvers = (PetscBool)!n_vertices; 90815feab87aSStefano Zampini } 9082a3df083aSStefano Zampini if (!pcbddc->benign_change_explicit) { 9083a3df083aSStefano Zampini benign_n = pcbddc->benign_n; 9084ca92afb2SStefano Zampini } else { 9085a3df083aSStefano Zampini benign_n = 0; 9086ca92afb2SStefano Zampini } 9087b7ab4a40SStefano Zampini /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc. 9088b7ab4a40SStefano Zampini We need a global reduction to avoid possible deadlocks. 9089b7ab4a40SStefano Zampini We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */ 909072b8c272SStefano Zampini if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) { 909122db5ddcSStefano Zampini PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change); 90925f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc))); 909322db5ddcSStefano Zampini need_change = (PetscBool)(!need_change); 9094b7ab4a40SStefano Zampini } 9095b7ab4a40SStefano Zampini /* If the user defines additional constraints, we import them here. 9096b7ab4a40SStefano Zampini We need to compute the change of basis according to the quadrature weights attached to pmat via MatSetNearNullSpace, and this could not be done (at the moment) without some hacking */ 9097b7ab4a40SStefano Zampini if (need_change) { 909888c03ad3SStefano Zampini PC_IS *pcisf; 909988c03ad3SStefano Zampini PC_BDDC *pcbddcf; 910088c03ad3SStefano Zampini PC pcf; 910188c03ad3SStefano Zampini 9102*28b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->sub_schurs_rebuild,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph"); 91035f80ce2aSJacob Faibussowitsch CHKERRQ(PCCreate(PetscObjectComm((PetscObject)pc),&pcf)); 91045f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetOperators(pcf,pc->mat,pc->pmat)); 91055f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pcf,PCBDDC)); 9106b9be95fcSstefano_zampini 910788c03ad3SStefano Zampini /* hacks */ 910888c03ad3SStefano Zampini pcisf = (PC_IS*)pcf->data; 910972b8c272SStefano Zampini pcisf->is_B_local = pcis->is_B_local; 911072b8c272SStefano Zampini pcisf->vec1_N = pcis->vec1_N; 911172b8c272SStefano Zampini pcisf->BtoNmap = pcis->BtoNmap; 911272b8c272SStefano Zampini pcisf->n = pcis->n; 911372b8c272SStefano Zampini pcisf->n_B = pcis->n_B; 911488c03ad3SStefano Zampini pcbddcf = (PC_BDDC*)pcf->data; 91155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddcf->mat_graph)); 911688c03ad3SStefano Zampini pcbddcf->mat_graph = pcbddc->mat_graph; 911788c03ad3SStefano Zampini pcbddcf->use_faces = PETSC_TRUE; 911888c03ad3SStefano Zampini pcbddcf->use_change_of_basis = PETSC_TRUE; 911988c03ad3SStefano Zampini pcbddcf->use_change_on_faces = PETSC_TRUE; 912072b8c272SStefano Zampini pcbddcf->use_qr_single = PETSC_TRUE; 912188c03ad3SStefano Zampini pcbddcf->fake_change = PETSC_TRUE; 9122b9be95fcSstefano_zampini 9123b9be95fcSstefano_zampini /* setup constraints so that we can get information on primal vertices and change of basis (in local numbering) */ 91245f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCConstraintsSetUp(pcf)); 912572b8c272SStefano Zampini sub_schurs->change_with_qr = pcbddcf->use_qr_single; 91265f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal)); 912772b8c272SStefano Zampini change = pcbddcf->ConstraintMatrix; 912872b8c272SStefano Zampini pcbddcf->ConstraintMatrix = NULL; 9129b9be95fcSstefano_zampini 913088c03ad3SStefano Zampini /* free unneeded memory allocated in PCBDDCConstraintsSetUp */ 91315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddcf->sub_schurs)); 91325f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceDestroy(&pcbddcf->onearnullspace)); 91335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult)); 91345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddcf->primal_indices_local_idxs)); 91355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcbddcf->onearnullvecs_state)); 91365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pcf->data)); 913788c03ad3SStefano Zampini pcf->ops->destroy = NULL; 9138b9be95fcSstefano_zampini pcf->ops->reset = NULL; 91395f80ce2aSJacob Faibussowitsch CHKERRQ(PCDestroy(&pcf)); 914088c03ad3SStefano Zampini } 91419d54b7f4SStefano Zampini if (!pcbddc->use_deluxe_scaling) scaling = pcis->D; 9142111315fdSstefano_zampini 91435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_iP",(PetscObject*)&iP)); 9144111315fdSstefano_zampini if (iP) { 9145111315fdSstefano_zampini ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)iP),sub_schurs->prefix,"BDDC sub_schurs options","PC");CHKERRQ(ierr); 91465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-sub_schurs_discrete_harmonic",NULL,NULL,discrete_harmonic,&discrete_harmonic,NULL)); 9147111315fdSstefano_zampini ierr = PetscOptionsEnd();CHKERRQ(ierr); 9148111315fdSstefano_zampini } 9149111315fdSstefano_zampini if (discrete_harmonic) { 9150111315fdSstefano_zampini Mat A; 91515f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(pcbddc->local_mat,MAT_COPY_VALUES,&A)); 91525f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroRowsColumnsIS(A,iP,1.0,NULL,NULL)); 91535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject)A,"__KSPFETIDP_iP",(PetscObject)iP)); 91545f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSubSchursSetUp(sub_schurs,A,S_j,pcbddc->sub_schurs_exact_schur,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,scaling,pcbddc->adaptive_selection,reuse_solvers,pcbddc->benign_saddle_point,benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_zerodiag_subs,change,change_primal)); 91555f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A)); 9156111315fdSstefano_zampini } else { 91575f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSubSchursSetUp(sub_schurs,pcbddc->local_mat,S_j,pcbddc->sub_schurs_exact_schur,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,scaling,pcbddc->adaptive_selection,reuse_solvers,pcbddc->benign_saddle_point,benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_zerodiag_subs,change,change_primal)); 9158111315fdSstefano_zampini } 91595f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&change)); 91605f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&change_primal)); 9161ca92afb2SStefano Zampini } 91625f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&S_j)); 9163b96c3477SStefano Zampini 9164b96c3477SStefano Zampini /* free adjacency */ 9165b96c3477SStefano Zampini if (free_used_adj) { 91665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(used_xadj,used_adjncy)); 9167b96c3477SStefano Zampini } 91685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_BDDC_Schurs[pcbddc->current_level],pc,0,0,0)); 9169b96c3477SStefano Zampini PetscFunctionReturn(0); 9170b96c3477SStefano Zampini } 9171b96c3477SStefano Zampini 917208122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc) 9173b96c3477SStefano Zampini { 9174b96c3477SStefano Zampini PC_IS *pcis=(PC_IS*)pc->data; 9175b96c3477SStefano Zampini PC_BDDC *pcbddc=(PC_BDDC*)pc->data; 9176b96c3477SStefano Zampini PCBDDCGraph graph; 9177b96c3477SStefano Zampini 9178b96c3477SStefano Zampini PetscFunctionBegin; 9179b96c3477SStefano Zampini /* attach interface graph for determining subsets */ 918008122e43SStefano Zampini if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */ 91813301b35fSStefano Zampini IS verticesIS,verticescomm; 91823301b35fSStefano Zampini PetscInt vsize,*idxs; 9183b96c3477SStefano Zampini 91845f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS)); 91855f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(verticesIS,&vsize)); 91865f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(verticesIS,(const PetscInt**)&idxs)); 91875f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm)); 91885f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(verticesIS,(const PetscInt**)&idxs)); 91895f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS)); 91905f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphCreate(&graph)); 91915f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global,pcbddc->graphmaxcount)); 91925f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm)); 91935f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&verticescomm)); 91945f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphComputeConnectedComponents(graph)); 9195b96c3477SStefano Zampini } else { 9196b96c3477SStefano Zampini graph = pcbddc->mat_graph; 9197b96c3477SStefano Zampini } 9198e4d548c7SStefano Zampini /* print some info */ 91995c643e28SStefano Zampini if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) { 9200e4d548c7SStefano Zampini IS vertices; 9201e4d548c7SStefano Zampini PetscInt nv,nedges,nfaces; 92025f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer)); 92035f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices)); 92045f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetSize(vertices,&nv)); 92055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 92065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n")); 92075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%D)\n",PetscGlobalRank,(int)nv,pcbddc->use_vertices)); 92085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges (%D)\n",PetscGlobalRank,(int)nedges,pcbddc->use_edges)); 92095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces (%D)\n",PetscGlobalRank,(int)nfaces,pcbddc->use_faces)); 92105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer)); 92115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 92125f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphRestoreCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices)); 9213e4d548c7SStefano Zampini } 9214b96c3477SStefano Zampini 9215b96c3477SStefano Zampini /* sub_schurs init */ 9216b334f244SStefano Zampini if (!pcbddc->sub_schurs) { 92175f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSubSchursCreate(&pcbddc->sub_schurs)); 9218b334f244SStefano Zampini } 92195f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCSubSchursInit(pcbddc->sub_schurs,((PetscObject)pc)->prefix,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap,pcbddc->sub_schurs_rebuild)); 9220a64f4aa4SStefano Zampini 9221b96c3477SStefano Zampini /* free graph struct */ 922208122e43SStefano Zampini if (pcbddc->sub_schurs_rebuild) { 92235f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCGraphDestroy(&graph)); 9224b96c3477SStefano Zampini } 9225b96c3477SStefano Zampini PetscFunctionReturn(0); 9226b96c3477SStefano Zampini } 9227fa34dd3eSStefano Zampini 9228fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc) 9229fa34dd3eSStefano Zampini { 9230fa34dd3eSStefano Zampini PC_IS *pcis=(PC_IS*)pc->data; 9231fa34dd3eSStefano Zampini PC_BDDC *pcbddc=(PC_BDDC*)pc->data; 9232fa34dd3eSStefano Zampini 9233fa34dd3eSStefano Zampini PetscFunctionBegin; 9234fa34dd3eSStefano Zampini if (pcbddc->n_vertices == pcbddc->local_primal_size) { 9235fa34dd3eSStefano Zampini IS zerodiag = NULL; 92364f1b2e48SStefano Zampini Mat S_j,B0_B=NULL; 9237fa34dd3eSStefano Zampini Vec dummy_vec=NULL,vec_check_B,vec_scale_P; 92384f1b2e48SStefano Zampini PetscScalar *p0_check,*array,*array2; 923975c01103SStefano Zampini PetscReal norm; 9240fa34dd3eSStefano Zampini PetscInt i; 9241fa34dd3eSStefano Zampini 9242fa34dd3eSStefano Zampini /* B0 and B0_B */ 9243fa34dd3eSStefano Zampini if (zerodiag) { 9244fa34dd3eSStefano Zampini IS dummy; 9245fa34dd3eSStefano Zampini 92465f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy)); 92475f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B)); 92485f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(B0_B,NULL,&dummy_vec)); 92495f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&dummy)); 9250fa34dd3eSStefano Zampini } 9251fa34dd3eSStefano Zampini /* I need a primal vector to scale primal nodes since BDDC sums contibutions */ 92525f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(pcbddc->vec1_P,&vec_scale_P)); 92535f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcbddc->vec1_P,1.0)); 92545f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD)); 92555f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD)); 92565f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE)); 92575f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE)); 92585f80ce2aSJacob Faibussowitsch CHKERRQ(VecReciprocal(vec_scale_P)); 9259fa34dd3eSStefano Zampini /* S_j */ 92605f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSchurComplement(pcis->A_II,pcis->pA_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j)); 92615f80ce2aSJacob Faibussowitsch CHKERRQ(MatSchurComplementSetKSP(S_j,pcbddc->ksp_D)); 9262fa34dd3eSStefano Zampini 9263fa34dd3eSStefano Zampini /* mimic vector in \widetilde{W}_\Gamma */ 92645f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetRandom(pcis->vec1_N,NULL)); 9265fa34dd3eSStefano Zampini /* continuous in primal space */ 92665f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetRandom(pcbddc->coarse_vec,NULL)); 92675f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE)); 92685f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE)); 92695f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(pcbddc->vec1_P,&array)); 92705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(pcbddc->benign_n,&p0_check)); 92714f1b2e48SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i]; 92725f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES)); 92735f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(pcbddc->vec1_P,&array)); 92745f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(pcis->vec1_N)); 92755f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(pcis->vec1_N)); 92765f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD)); 92775f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD)); 92785f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(pcis->vec2_B,&vec_check_B)); 92795f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(pcis->vec2_B,vec_check_B)); 9280fa34dd3eSStefano Zampini 9281fa34dd3eSStefano Zampini /* assemble rhs for coarse problem */ 9282fa34dd3eSStefano Zampini /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */ 9283fa34dd3eSStefano Zampini /* local with Schur */ 92845f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(S_j,pcis->vec2_B,pcis->vec1_B)); 9285fa34dd3eSStefano Zampini if (zerodiag) { 92865f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(dummy_vec,&array)); 92874f1b2e48SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i]; 92885f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(dummy_vec,&array)); 92895f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B)); 9290fa34dd3eSStefano Zampini } 9291fa34dd3eSStefano Zampini /* sum on primal nodes the local contributions */ 92925f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 92935f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 92945f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(pcis->vec1_N,&array)); 92955f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(pcbddc->vec1_P,&array2)); 9296fa34dd3eSStefano Zampini for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]]; 92975f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(pcbddc->vec1_P,&array2)); 92985f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(pcis->vec1_N,&array)); 92995f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcbddc->coarse_vec,0.)); 93005f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD)); 93015f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD)); 93025f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE)); 93035f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE)); 93045f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(pcbddc->vec1_P,&array)); 9305fa34dd3eSStefano Zampini /* scale primal nodes (BDDC sums contibutions) */ 93065f80ce2aSJacob Faibussowitsch CHKERRQ(VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P)); 93075f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES)); 93085f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(pcbddc->vec1_P,&array)); 93095f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(pcis->vec1_N)); 93105f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(pcis->vec1_N)); 93115f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 93125f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 9313fa34dd3eSStefano Zampini /* global: \widetilde{B0}_B w_\Gamma */ 9314fa34dd3eSStefano Zampini if (zerodiag) { 93155f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(B0_B,pcis->vec2_B,dummy_vec)); 93165f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(dummy_vec,&array)); 93174f1b2e48SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i]; 93185f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(dummy_vec,&array)); 9319fa34dd3eSStefano Zampini } 9320fa34dd3eSStefano Zampini /* BDDC */ 93215f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(pcis->vec1_D,0.)); 93225f80ce2aSJacob Faibussowitsch CHKERRQ(PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE)); 9323fa34dd3eSStefano Zampini 93245f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(pcis->vec1_B,pcis->vec2_B)); 93255f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(pcis->vec1_B,-1.0,vec_check_B)); 93265f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(pcis->vec1_B,NORM_INFINITY,&norm)); 93275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm)); 93284f1b2e48SStefano Zampini for (i=0;i<pcbddc->benign_n;i++) { 93295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%D] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]))); 9330fa34dd3eSStefano Zampini } 93315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(p0_check)); 93325f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&vec_scale_P)); 93335f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&vec_check_B)); 93345f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&dummy_vec)); 93355f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&S_j)); 93365f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&B0_B)); 9337fa34dd3eSStefano Zampini } 9338fa34dd3eSStefano Zampini PetscFunctionReturn(0); 9339fa34dd3eSStefano Zampini } 93401e0482f5SStefano Zampini 93411e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h> 93421e0482f5SStefano Zampini PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B) 93431e0482f5SStefano Zampini { 93441e0482f5SStefano Zampini Mat At; 93451e0482f5SStefano Zampini IS rows; 93461e0482f5SStefano Zampini PetscInt rst,ren; 93471e0482f5SStefano Zampini PetscLayout rmap; 93481e0482f5SStefano Zampini 93491e0482f5SStefano Zampini PetscFunctionBegin; 93501e0482f5SStefano Zampini rst = ren = 0; 93511e0482f5SStefano Zampini if (ccomm != MPI_COMM_NULL) { 93525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutCreate(ccomm,&rmap)); 93535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetSize(rmap,A->rmap->N)); 93545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetBlockSize(rmap,1)); 93555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetUp(rmap)); 93565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutGetRange(rmap,&rst,&ren)); 93571e0482f5SStefano Zampini } 93585f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)A),ren-rst,rst,1,&rows)); 93595f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(A,rows,NULL,MAT_INITIAL_MATRIX,&At)); 93605f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&rows)); 93611e0482f5SStefano Zampini 93621e0482f5SStefano Zampini if (ccomm != MPI_COMM_NULL) { 93631e0482f5SStefano Zampini Mat_MPIAIJ *a,*b; 93641e0482f5SStefano Zampini IS from,to; 93651e0482f5SStefano Zampini Vec gvec; 93661e0482f5SStefano Zampini PetscInt lsize; 93671e0482f5SStefano Zampini 93685f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(ccomm,B)); 93695f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(*B,ren-rst,PETSC_DECIDE,PETSC_DECIDE,At->cmap->N)); 93705f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(*B,MATAIJ)); 93715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutDestroy(&((*B)->rmap))); 93725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetUp((*B)->cmap)); 93731e0482f5SStefano Zampini a = (Mat_MPIAIJ*)At->data; 93741e0482f5SStefano Zampini b = (Mat_MPIAIJ*)(*B)->data; 93755f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(ccomm,&b->size)); 93765f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(ccomm,&b->rank)); 93775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)a->A)); 93785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)a->B)); 93791e0482f5SStefano Zampini b->A = a->A; 93801e0482f5SStefano Zampini b->B = a->B; 93811e0482f5SStefano Zampini 93821e0482f5SStefano Zampini b->donotstash = a->donotstash; 93831e0482f5SStefano Zampini b->roworiented = a->roworiented; 93840a545947SLisandro Dalcin b->rowindices = NULL; 93850a545947SLisandro Dalcin b->rowvalues = NULL; 93861e0482f5SStefano Zampini b->getrowactive = PETSC_FALSE; 93871e0482f5SStefano Zampini 93881e0482f5SStefano Zampini (*B)->rmap = rmap; 93891e0482f5SStefano Zampini (*B)->factortype = A->factortype; 93901e0482f5SStefano Zampini (*B)->assembled = PETSC_TRUE; 93911e0482f5SStefano Zampini (*B)->insertmode = NOT_SET_VALUES; 93921e0482f5SStefano Zampini (*B)->preallocated = PETSC_TRUE; 93931e0482f5SStefano Zampini 93941e0482f5SStefano Zampini if (a->colmap) { 93951e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE) 93965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTableCreateCopy(a->colmap,&b->colmap)); 93971e0482f5SStefano Zampini #else 93985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(At->cmap->N,&b->colmap)); 93995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogObjectMemory((PetscObject)*B,At->cmap->N*sizeof(PetscInt))); 94005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(b->colmap,a->colmap,At->cmap->N)); 94011e0482f5SStefano Zampini #endif 94020a545947SLisandro Dalcin } else b->colmap = NULL; 94031e0482f5SStefano Zampini if (a->garray) { 94041e0482f5SStefano Zampini PetscInt len; 94051e0482f5SStefano Zampini len = a->B->cmap->n; 94065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(len+1,&b->garray)); 94075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogObjectMemory((PetscObject)(*B),len*sizeof(PetscInt))); 94085f80ce2aSJacob Faibussowitsch if (len) CHKERRQ(PetscArraycpy(b->garray,a->garray,len)); 94090a545947SLisandro Dalcin } else b->garray = NULL; 94101e0482f5SStefano Zampini 94115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)a->lvec)); 94121e0482f5SStefano Zampini b->lvec = a->lvec; 94135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogObjectParent((PetscObject)*B,(PetscObject)b->lvec)); 94141e0482f5SStefano Zampini 94151e0482f5SStefano Zampini /* cannot use VecScatterCopy */ 94165f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(b->lvec,&lsize)); 94175f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(ccomm,lsize,b->garray,PETSC_USE_POINTER,&from)); 94185f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateStride(PETSC_COMM_SELF,lsize,0,1,&to)); 94195f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(*B,&gvec,NULL)); 94205f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterCreate(gvec,from,b->lvec,to,&b->Mvctx)); 94215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogObjectParent((PetscObject)*B,(PetscObject)b->Mvctx)); 94225f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&from)); 94235f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&to)); 94245f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&gvec)); 94251e0482f5SStefano Zampini } 94265f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&At)); 94271e0482f5SStefano Zampini PetscFunctionReturn(0); 94281e0482f5SStefano Zampini } 9429