xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
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,&section));
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), &section));
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(&section));
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